MDL-66539 atto_link: Non-intuitive action for atto link button

This commit is contained in:
Huong Nguyen 2021-04-07 14:33:13 +07:00
parent 30b8ad51f4
commit 6372d61f71
7 changed files with 355 additions and 51 deletions

View File

@ -29,3 +29,4 @@ $string['openinnewwindow'] = 'Open in new window';
$string['pluginname'] = 'Link';
$string['unlink'] = 'Unlink';
$string['privacy:metadata'] = 'The atto_link plugin does not store any personal data.';
$string['texttodisplay'] = 'Text to display';

View File

@ -35,7 +35,8 @@ function atto_link_strings_for_js() {
'unlink',
'enterurl',
'browserepositories',
'openinnewwindow'),
'openinnewwindow',
'texttodisplay'),
'atto_link');
}

View File

@ -12,6 +12,7 @@ Feature: Add links to Atto
And I set the field "Description" to "Super cool"
And I select the text in the "Description" Atto editor
And I click on "Link" "button"
Then the field "Text to display" matches value "Super cool"
And I click on "Browse repositories..." "button"
And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
And I click on "moodle-logo.png" "link"
@ -22,4 +23,59 @@ Feature: Add links to Atto
And I set the field "Text editor" to "Plain text area"
And I press "Save changes"
And I click on "Edit profile" "link" in the "region-main" "region"
Then I should see "Super cool</a>"
And I should see "Super cool</a>"
@javascript
Scenario: Insert a link without providing text to display
Given I log in as "admin"
When I open my profile in edit mode
And I click on "Link" "button"
And I set the field "Enter a URL" to "https://moodle.org/"
Then the field "Text to display" matches value "https://moodle.org/"
And I click on "Create link" "button"
And I should see "https://moodle.org/"
And I click on "Link" "button"
And the field "Text to display" matches value "https://moodle.org/"
And the field "Enter a URL" matches value "https://moodle.org/"
And I click on "Close" "button" in the "Create link" "dialogue"
And I click on "Show more buttons" "button"
And I click on "HTML" "button"
And I should see "https://moodle.org/</a>"
@javascript
Scenario: Insert a link with providing text to display
Given I log in as "admin"
When I open my profile in edit mode
And I click on "Link" "button"
And I set the field "Text to display" to "Moodle - Open-source learning platform"
And I set the field "Enter a URL" to "https://moodle.org/"
And I click on "Create link" "button"
Then I should see "Moodle - Open-source learning platform"
And I click on "Link" "button"
And the field "Text to display" matches value "Moodle - Open-source learning platform"
And the field "Enter a URL" matches value "https://moodle.org/"
And I click on "Close" "button" in the "Create link" "dialogue"
And I click on "Show more buttons" "button"
And I click on "HTML" "button"
And I should see "Moodle - Open-source learning platform</a>"
And I should not see "https://moodle.org/</a>"
@javascript
Scenario: Edit a link that already had a custom text to display
Given I log in as "admin"
And I follow "Preferences" in the user menu
And I follow "Editor preferences"
And I set the field "Text editor" to "Plain text area"
And I press "Save changes"
And I click on "Edit profile" "link" in the "region-main" "region"
And I set the field "Description" to "<a href=\"https://moodle.org/\">Moodle - Open-source learning platform</a>"
And I click on "Update profile" "button"
And I follow "Preferences" in the user menu
And I follow "Editor preferences"
And I set the field "Text editor" to "Atto HTML editor"
And I press "Save changes"
When I click on "Edit profile" "link" in the "region-main" "region"
Then I should see "Moodle - Open-source learning platform"
And I click on "Link" "button"
And the field "Text to display" matches value "Moodle - Open-source learning platform"
And the field "Enter a URL" matches value "https://moodle.org/"

View File

@ -36,13 +36,23 @@ YUI.add('moodle-atto_link-button', function (Y, NAME) {
var COMPONENTNAME = 'atto_link',
CSS = {
NEWWINDOW: 'atto_link_openinnewwindow',
URLINPUT: 'atto_link_urlentry'
URLINPUT: 'atto_link_urlentry',
URLTEXT: 'atto_link_urltext'
},
SELECTORS = {
URLINPUT: '.atto_link_urlentry'
NEWWINDOW: '.atto_link_openinnewwindow',
URLINPUT: '.atto_link_urlentry',
URLTEXT: '.atto_link_urltext',
SUBMIT: '.submit',
LINKBROWSER: '.openlinkbrowser'
},
TEMPLATE = '' +
'<form class="atto_form">' +
'<div class="mb-1">' +
'<label for="{{elementid}}_atto_link_urltext">{{get_string "texttodisplay" component}}</label>' +
'<input class="form-control fullwidth {{CSS.URLTEXT}}" type="text" ' +
'id="{{elementid}}_atto_link_urltext" size="32"/>' +
'</div>' +
'{{#if showFilepicker}}' +
'<label for="{{elementid}}_atto_link_urlentry">{{get_string "enterurl" component}}</label>' +
'<div class="input-group input-append w-100 mb-1">' +
@ -61,7 +71,8 @@ var COMPONENTNAME = 'atto_link',
'</div>' +
'{{/if}}' +
'<div class="form-check">' +
'<input type="checkbox" class="form-check-input newwindow" id="{{elementid}}_{{CSS.NEWWINDOW}}"/>' +
'<input type="checkbox" class="form-check-input newwindow {{CSS.NEWWINDOW}}" ' +
'id="{{elementid}}_{{CSS.NEWWINDOW}}"/>' +
'<label class="form-check-label" for="{{elementid}}_{{CSS.NEWWINDOW}}">' +
'{{get_string "openinnewwindow" component}}' +
'</label>' +
@ -92,6 +103,14 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
*/
_content: null,
/**
* Text to display has value or not.
* @property _hasTextToDisplay
* @type Boolean
* @private
*/
_hasTextToDisplay: false,
initializer: function() {
// Add the link button first.
this.addButton({
@ -156,7 +175,8 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
anchornodes,
anchornode,
url,
target;
target,
textToDisplay;
// Note this is a document fragment and YUI doesn't like them.
if (!selectednode) {
@ -169,13 +189,24 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
this._currentSelection = this.get('host').getSelectionFromNode(anchornode);
url = anchornode.getAttribute('href');
target = anchornode.getAttribute('target');
textToDisplay = anchornode.get('innerText');
if (url !== '') {
this._content.one('.url').setAttribute('value', url);
this._content.one(SELECTORS.URLINPUT).setAttribute('value', url);
}
if (textToDisplay !== '') {
this._content.one(SELECTORS.URLTEXT).set('value', textToDisplay);
}
if (target === '_blank') {
this._content.one('.newwindow').setAttribute('checked', 'checked');
this._content.one(SELECTORS.NEWWINDOW).setAttribute('checked', 'checked');
} else {
this._content.one('.newwindow').removeAttribute('checked');
this._content.one(SELECTORS.NEWWINDOW).removeAttribute('checked');
}
} else {
// User is selecting some text before clicking on the Link button.
textToDisplay = Y.one(selectednode).get('textContent');
if (textToDisplay !== '') {
this._hasTextToDisplay = true;
this._content.one(SELECTORS.URLTEXT).set('value', textToDisplay);
}
}
},
@ -218,7 +249,7 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
focusAfterHide: null
}).hide();
input = this._content.one('.url');
input = this._content.one(SELECTORS.URLINPUT);
value = input.get('value');
if (value !== '') {
@ -250,14 +281,23 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
link,
selectednode,
target,
anchornodes;
anchornodes,
isUpdating,
urlText,
textToDisplay;
this.editor.focus();
host.setSelection(this._currentSelection);
isUpdating = !this._currentSelection[0].collapsed;
urlText = this._content.one(SELECTORS.URLTEXT);
textToDisplay = urlText.get('value').replace(/(<([^>]+)>)/gi, "").trim();
if (textToDisplay === '') {
textToDisplay = url;
}
if (this._currentSelection[0].collapsed) {
if (!isUpdating) {
// Firefox cannot add links when the selection is empty so we will add it manually.
link = Y.Node.create('<a>' + url + '</a>');
link = Y.Node.create('<a>' + textToDisplay + '</a>');
link.setAttribute('href', url);
// Add the node and select it to replicate the behaviour of execCommand.
@ -279,12 +319,16 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
anchornodes = this._findSelectedAnchors(Y.one(selectednode));
// Add new window attributes if requested.
Y.Array.each(anchornodes, function(anchornode) {
target = this._content.one('.newwindow');
target = this._content.one(SELECTORS.NEWWINDOW);
if (target.get('checked')) {
anchornode.setAttribute('target', '_blank');
} else {
anchornode.removeAttribute('target');
}
if (isUpdating) {
// The 'createLink' command do not allow to set the custom text to display. So we need to do it here.
anchornode.set('innerText', textToDisplay);
}
}, this);
return selectednode;
@ -342,9 +386,11 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
CSS: CSS
}));
this._content.one('.submit').on('click', this._setLink, this);
this._content.one(SELECTORS.URLINPUT).on('keyup', this._updateTextToDisplay, this);
this._content.one(SELECTORS.URLTEXT).on('keyup', this._setTextToDisplayState, this);
this._content.one(SELECTORS.SUBMIT).on('click', this._setLink, this);
if (canShowFilepicker) {
this._content.one('.openlinkbrowser').on('click', function(e) {
this._content.one(SELECTORS.LINKBROWSER).on('click', function(e) {
e.preventDefault();
this.get('host').showFilepicker('link', this._filepickerCallback, this);
}, this);
@ -375,10 +421,10 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
// would then be unlinked too.
nodes.each(function(node) {
// We need to select the whole anchor node for this to work in some browsers.
// We only need to search up because getSeletedNodes returns all Nodes in the selection.
// We only need to search up because getSelectedNodes returns all Nodes in the selection.
var anchor = node.ancestor('a', true);
if (anchor) {
// Set the selection to the whole of the first anchro.
// Set the selection to the whole of the first anchor.
host.setSelection(host.getSelectionFromNode(anchor));
// Call the browser unlink.
@ -397,6 +443,42 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
this.markUpdated();
}
}
},
/**
* Set the current text to display state.
*
* @method _setTextToDisplayState
* @private
*/
_setTextToDisplayState: function() {
var urlText,
urlTextVal;
urlText = this._content.one(SELECTORS.URLTEXT);
urlTextVal = urlText.get('value');
if (urlTextVal !== '') {
this._hasTextToDisplay = true;
} else {
this._hasTextToDisplay = false;
}
},
/**
* Update the text to display if the user does not provide the custom text.
*
* @method _updateTextToDisplay
* @private
*/
_updateTextToDisplay: function() {
var urlEntry,
urlText,
urlEntryVal;
urlEntry = this._content.one(SELECTORS.URLINPUT);
urlText = this._content.one(SELECTORS.URLTEXT);
urlEntryVal = urlEntry.get('value');
if (!this._hasTextToDisplay) {
urlText.set('value', urlEntryVal);
}
}
});

File diff suppressed because one or more lines are too long

View File

@ -36,13 +36,23 @@ YUI.add('moodle-atto_link-button', function (Y, NAME) {
var COMPONENTNAME = 'atto_link',
CSS = {
NEWWINDOW: 'atto_link_openinnewwindow',
URLINPUT: 'atto_link_urlentry'
URLINPUT: 'atto_link_urlentry',
URLTEXT: 'atto_link_urltext'
},
SELECTORS = {
URLINPUT: '.atto_link_urlentry'
NEWWINDOW: '.atto_link_openinnewwindow',
URLINPUT: '.atto_link_urlentry',
URLTEXT: '.atto_link_urltext',
SUBMIT: '.submit',
LINKBROWSER: '.openlinkbrowser'
},
TEMPLATE = '' +
'<form class="atto_form">' +
'<div class="mb-1">' +
'<label for="{{elementid}}_atto_link_urltext">{{get_string "texttodisplay" component}}</label>' +
'<input class="form-control fullwidth {{CSS.URLTEXT}}" type="text" ' +
'id="{{elementid}}_atto_link_urltext" size="32"/>' +
'</div>' +
'{{#if showFilepicker}}' +
'<label for="{{elementid}}_atto_link_urlentry">{{get_string "enterurl" component}}</label>' +
'<div class="input-group input-append w-100 mb-1">' +
@ -61,7 +71,8 @@ var COMPONENTNAME = 'atto_link',
'</div>' +
'{{/if}}' +
'<div class="form-check">' +
'<input type="checkbox" class="form-check-input newwindow" id="{{elementid}}_{{CSS.NEWWINDOW}}"/>' +
'<input type="checkbox" class="form-check-input newwindow {{CSS.NEWWINDOW}}" ' +
'id="{{elementid}}_{{CSS.NEWWINDOW}}"/>' +
'<label class="form-check-label" for="{{elementid}}_{{CSS.NEWWINDOW}}">' +
'{{get_string "openinnewwindow" component}}' +
'</label>' +
@ -92,6 +103,14 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
*/
_content: null,
/**
* Text to display has value or not.
* @property _hasTextToDisplay
* @type Boolean
* @private
*/
_hasTextToDisplay: false,
initializer: function() {
// Add the link button first.
this.addButton({
@ -156,7 +175,8 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
anchornodes,
anchornode,
url,
target;
target,
textToDisplay;
// Note this is a document fragment and YUI doesn't like them.
if (!selectednode) {
@ -169,13 +189,24 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
this._currentSelection = this.get('host').getSelectionFromNode(anchornode);
url = anchornode.getAttribute('href');
target = anchornode.getAttribute('target');
textToDisplay = anchornode.get('innerText');
if (url !== '') {
this._content.one('.url').setAttribute('value', url);
this._content.one(SELECTORS.URLINPUT).setAttribute('value', url);
}
if (textToDisplay !== '') {
this._content.one(SELECTORS.URLTEXT).set('value', textToDisplay);
}
if (target === '_blank') {
this._content.one('.newwindow').setAttribute('checked', 'checked');
this._content.one(SELECTORS.NEWWINDOW).setAttribute('checked', 'checked');
} else {
this._content.one('.newwindow').removeAttribute('checked');
this._content.one(SELECTORS.NEWWINDOW).removeAttribute('checked');
}
} else {
// User is selecting some text before clicking on the Link button.
textToDisplay = Y.one(selectednode).get('textContent');
if (textToDisplay !== '') {
this._hasTextToDisplay = true;
this._content.one(SELECTORS.URLTEXT).set('value', textToDisplay);
}
}
},
@ -218,7 +249,7 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
focusAfterHide: null
}).hide();
input = this._content.one('.url');
input = this._content.one(SELECTORS.URLINPUT);
value = input.get('value');
if (value !== '') {
@ -250,14 +281,23 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
link,
selectednode,
target,
anchornodes;
anchornodes,
isUpdating,
urlText,
textToDisplay;
this.editor.focus();
host.setSelection(this._currentSelection);
isUpdating = !this._currentSelection[0].collapsed;
urlText = this._content.one(SELECTORS.URLTEXT);
textToDisplay = urlText.get('value').replace(/(<([^>]+)>)/gi, "").trim();
if (textToDisplay === '') {
textToDisplay = url;
}
if (this._currentSelection[0].collapsed) {
if (!isUpdating) {
// Firefox cannot add links when the selection is empty so we will add it manually.
link = Y.Node.create('<a>' + url + '</a>');
link = Y.Node.create('<a>' + textToDisplay + '</a>');
link.setAttribute('href', url);
// Add the node and select it to replicate the behaviour of execCommand.
@ -279,12 +319,16 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
anchornodes = this._findSelectedAnchors(Y.one(selectednode));
// Add new window attributes if requested.
Y.Array.each(anchornodes, function(anchornode) {
target = this._content.one('.newwindow');
target = this._content.one(SELECTORS.NEWWINDOW);
if (target.get('checked')) {
anchornode.setAttribute('target', '_blank');
} else {
anchornode.removeAttribute('target');
}
if (isUpdating) {
// The 'createLink' command do not allow to set the custom text to display. So we need to do it here.
anchornode.set('innerText', textToDisplay);
}
}, this);
return selectednode;
@ -342,9 +386,11 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
CSS: CSS
}));
this._content.one('.submit').on('click', this._setLink, this);
this._content.one(SELECTORS.URLINPUT).on('keyup', this._updateTextToDisplay, this);
this._content.one(SELECTORS.URLTEXT).on('keyup', this._setTextToDisplayState, this);
this._content.one(SELECTORS.SUBMIT).on('click', this._setLink, this);
if (canShowFilepicker) {
this._content.one('.openlinkbrowser').on('click', function(e) {
this._content.one(SELECTORS.LINKBROWSER).on('click', function(e) {
e.preventDefault();
this.get('host').showFilepicker('link', this._filepickerCallback, this);
}, this);
@ -375,10 +421,10 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
// would then be unlinked too.
nodes.each(function(node) {
// We need to select the whole anchor node for this to work in some browsers.
// We only need to search up because getSeletedNodes returns all Nodes in the selection.
// We only need to search up because getSelectedNodes returns all Nodes in the selection.
var anchor = node.ancestor('a', true);
if (anchor) {
// Set the selection to the whole of the first anchro.
// Set the selection to the whole of the first anchor.
host.setSelection(host.getSelectionFromNode(anchor));
// Call the browser unlink.
@ -397,6 +443,42 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
this.markUpdated();
}
}
},
/**
* Set the current text to display state.
*
* @method _setTextToDisplayState
* @private
*/
_setTextToDisplayState: function() {
var urlText,
urlTextVal;
urlText = this._content.one(SELECTORS.URLTEXT);
urlTextVal = urlText.get('value');
if (urlTextVal !== '') {
this._hasTextToDisplay = true;
} else {
this._hasTextToDisplay = false;
}
},
/**
* Update the text to display if the user does not provide the custom text.
*
* @method _updateTextToDisplay
* @private
*/
_updateTextToDisplay: function() {
var urlEntry,
urlText,
urlEntryVal;
urlEntry = this._content.one(SELECTORS.URLINPUT);
urlText = this._content.one(SELECTORS.URLTEXT);
urlEntryVal = urlEntry.get('value');
if (!this._hasTextToDisplay) {
urlText.set('value', urlEntryVal);
}
}
});

View File

@ -34,13 +34,23 @@
var COMPONENTNAME = 'atto_link',
CSS = {
NEWWINDOW: 'atto_link_openinnewwindow',
URLINPUT: 'atto_link_urlentry'
URLINPUT: 'atto_link_urlentry',
URLTEXT: 'atto_link_urltext'
},
SELECTORS = {
URLINPUT: '.atto_link_urlentry'
NEWWINDOW: '.atto_link_openinnewwindow',
URLINPUT: '.atto_link_urlentry',
URLTEXT: '.atto_link_urltext',
SUBMIT: '.submit',
LINKBROWSER: '.openlinkbrowser'
},
TEMPLATE = '' +
'<form class="atto_form">' +
'<div class="mb-1">' +
'<label for="{{elementid}}_atto_link_urltext">{{get_string "texttodisplay" component}}</label>' +
'<input class="form-control fullwidth {{CSS.URLTEXT}}" type="text" ' +
'id="{{elementid}}_atto_link_urltext" size="32"/>' +
'</div>' +
'{{#if showFilepicker}}' +
'<label for="{{elementid}}_atto_link_urlentry">{{get_string "enterurl" component}}</label>' +
'<div class="input-group input-append w-100 mb-1">' +
@ -59,7 +69,8 @@ var COMPONENTNAME = 'atto_link',
'</div>' +
'{{/if}}' +
'<div class="form-check">' +
'<input type="checkbox" class="form-check-input newwindow" id="{{elementid}}_{{CSS.NEWWINDOW}}"/>' +
'<input type="checkbox" class="form-check-input newwindow {{CSS.NEWWINDOW}}" ' +
'id="{{elementid}}_{{CSS.NEWWINDOW}}"/>' +
'<label class="form-check-label" for="{{elementid}}_{{CSS.NEWWINDOW}}">' +
'{{get_string "openinnewwindow" component}}' +
'</label>' +
@ -90,6 +101,14 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
*/
_content: null,
/**
* Text to display has value or not.
* @property _hasTextToDisplay
* @type Boolean
* @private
*/
_hasTextToDisplay: false,
initializer: function() {
// Add the link button first.
this.addButton({
@ -154,7 +173,8 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
anchornodes,
anchornode,
url,
target;
target,
textToDisplay;
// Note this is a document fragment and YUI doesn't like them.
if (!selectednode) {
@ -167,13 +187,24 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
this._currentSelection = this.get('host').getSelectionFromNode(anchornode);
url = anchornode.getAttribute('href');
target = anchornode.getAttribute('target');
textToDisplay = anchornode.get('innerText');
if (url !== '') {
this._content.one('.url').setAttribute('value', url);
this._content.one(SELECTORS.URLINPUT).setAttribute('value', url);
}
if (textToDisplay !== '') {
this._content.one(SELECTORS.URLTEXT).set('value', textToDisplay);
}
if (target === '_blank') {
this._content.one('.newwindow').setAttribute('checked', 'checked');
this._content.one(SELECTORS.NEWWINDOW).setAttribute('checked', 'checked');
} else {
this._content.one('.newwindow').removeAttribute('checked');
this._content.one(SELECTORS.NEWWINDOW).removeAttribute('checked');
}
} else {
// User is selecting some text before clicking on the Link button.
textToDisplay = Y.one(selectednode).get('textContent');
if (textToDisplay !== '') {
this._hasTextToDisplay = true;
this._content.one(SELECTORS.URLTEXT).set('value', textToDisplay);
}
}
},
@ -216,7 +247,7 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
focusAfterHide: null
}).hide();
input = this._content.one('.url');
input = this._content.one(SELECTORS.URLINPUT);
value = input.get('value');
if (value !== '') {
@ -248,14 +279,23 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
link,
selectednode,
target,
anchornodes;
anchornodes,
isUpdating,
urlText,
textToDisplay;
this.editor.focus();
host.setSelection(this._currentSelection);
isUpdating = !this._currentSelection[0].collapsed;
urlText = this._content.one(SELECTORS.URLTEXT);
textToDisplay = urlText.get('value').replace(/(<([^>]+)>)/gi, "").trim();
if (textToDisplay === '') {
textToDisplay = url;
}
if (this._currentSelection[0].collapsed) {
if (!isUpdating) {
// Firefox cannot add links when the selection is empty so we will add it manually.
link = Y.Node.create('<a>' + url + '</a>');
link = Y.Node.create('<a>' + textToDisplay + '</a>');
link.setAttribute('href', url);
// Add the node and select it to replicate the behaviour of execCommand.
@ -277,12 +317,16 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
anchornodes = this._findSelectedAnchors(Y.one(selectednode));
// Add new window attributes if requested.
Y.Array.each(anchornodes, function(anchornode) {
target = this._content.one('.newwindow');
target = this._content.one(SELECTORS.NEWWINDOW);
if (target.get('checked')) {
anchornode.setAttribute('target', '_blank');
} else {
anchornode.removeAttribute('target');
}
if (isUpdating) {
// The 'createLink' command do not allow to set the custom text to display. So we need to do it here.
anchornode.set('innerText', textToDisplay);
}
}, this);
return selectednode;
@ -340,9 +384,11 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
CSS: CSS
}));
this._content.one('.submit').on('click', this._setLink, this);
this._content.one(SELECTORS.URLINPUT).on('keyup', this._updateTextToDisplay, this);
this._content.one(SELECTORS.URLTEXT).on('keyup', this._setTextToDisplayState, this);
this._content.one(SELECTORS.SUBMIT).on('click', this._setLink, this);
if (canShowFilepicker) {
this._content.one('.openlinkbrowser').on('click', function(e) {
this._content.one(SELECTORS.LINKBROWSER).on('click', function(e) {
e.preventDefault();
this.get('host').showFilepicker('link', this._filepickerCallback, this);
}, this);
@ -373,10 +419,10 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
// would then be unlinked too.
nodes.each(function(node) {
// We need to select the whole anchor node for this to work in some browsers.
// We only need to search up because getSeletedNodes returns all Nodes in the selection.
// We only need to search up because getSelectedNodes returns all Nodes in the selection.
var anchor = node.ancestor('a', true);
if (anchor) {
// Set the selection to the whole of the first anchro.
// Set the selection to the whole of the first anchor.
host.setSelection(host.getSelectionFromNode(anchor));
// Call the browser unlink.
@ -395,5 +441,41 @@ Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.Edit
this.markUpdated();
}
}
},
/**
* Set the current text to display state.
*
* @method _setTextToDisplayState
* @private
*/
_setTextToDisplayState: function() {
var urlText,
urlTextVal;
urlText = this._content.one(SELECTORS.URLTEXT);
urlTextVal = urlText.get('value');
if (urlTextVal !== '') {
this._hasTextToDisplay = true;
} else {
this._hasTextToDisplay = false;
}
},
/**
* Update the text to display if the user does not provide the custom text.
*
* @method _updateTextToDisplay
* @private
*/
_updateTextToDisplay: function() {
var urlEntry,
urlText,
urlEntryVal;
urlEntry = this._content.one(SELECTORS.URLINPUT);
urlText = this._content.one(SELECTORS.URLTEXT);
urlEntryVal = urlEntry.get('value');
if (!this._hasTextToDisplay) {
urlText.set('value', urlEntryVal);
}
}
});