diff --git a/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-debug.js b/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-debug.js
index 5319f52284e..697f4de41ff 100644
--- a/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-debug.js
+++ b/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_bold-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'b,strong'
+};
+
/**
* Atto text editor bold plugin.
*
@@ -36,6 +45,18 @@ M.atto_bold = M.atto_bold || {
var iconurl = M.util.image_url('e/bold', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'bold', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'bold');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'bold');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-min.js b/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-min.js
index bb9a5f786f1..c7e378b20d7 100644
--- a/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-min.js
+++ b/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_bold-button",function(e,t){M.atto_bold=M.atto_bold||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("bold",!1,null),M.editor_atto.text_updated(t)},n=M.util.image_url("e/bold","core");M.editor_atto.add_toolbar_button(e.elementid,"bold",n,e.group,t)}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_bold-button",function(e,t){var n={TAGS:"b,strong"};M.atto_bold=M.atto_bold||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("bold",!1,null),M.editor_atto.text_updated(t)},r=M.util.image_url("e/bold","core");M.editor_atto.add_toolbar_button(e.elementid,"bold",r,e.group,t);var i=M.editor_atto.get_editable_node(e.elementid);i.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"bold"):M.editor_atto.remove_widget_highlight(e.elementid,"bold")})}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button.js b/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button.js
index 5319f52284e..697f4de41ff 100644
--- a/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button.js
+++ b/lib/editor/atto/plugins/bold/yui/build/moodle-atto_bold-button/moodle-atto_bold-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_bold-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'b,strong'
+};
+
/**
* Atto text editor bold plugin.
*
@@ -36,6 +45,18 @@ M.atto_bold = M.atto_bold || {
var iconurl = M.util.image_url('e/bold', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'bold', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'bold');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'bold');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/bold/yui/src/button/js/button.js b/lib/editor/atto/plugins/bold/yui/src/button/js/button.js
index 5a29c73f621..b59bd518b4d 100644
--- a/lib/editor/atto/plugins/bold/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/bold/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'b,strong'
+};
+
/**
* Atto text editor bold plugin.
*
@@ -34,5 +43,17 @@ M.atto_bold = M.atto_bold || {
var iconurl = M.util.image_url('e/bold', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'bold', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'bold');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'bold');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js
index 0667bacc269..120d5358337 100644
--- a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js
+++ b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js
@@ -105,7 +105,10 @@ M.atto_equation = M.atto_equation || {
tabview.render();
dialogue.show();
- M.atto_equation.resolve_equation();
+ var equation = M.atto_equation.resolve_equation();
+ if (equation) {
+ Y.one('#atto_equation_equation').set('text', equation);
+ }
M.atto_equation.update_preview(false, elementid);
M.atto_equation.dialogue = dialogue;
}
@@ -128,6 +131,17 @@ M.atto_equation = M.atto_equation || {
// Add the button to the toolbar.
M.editor_atto.add_toolbar_button(params.elementid, 'equation', iconurl, params.group, this.display_chooser);
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.atto_equation.resolve_equation() !== false) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'equation');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'equation');
+ }
+ });
}
},
@@ -136,6 +150,7 @@ M.atto_equation = M.atto_equation || {
* extract the equation (and set it in the form).
*
* @method resolve_equation
+ * @return {String|Boolean} The equation or false.
*/
resolve_equation : function() {
// Find the equation in the surrounding text.
@@ -145,7 +160,7 @@ M.atto_equation = M.atto_equation || {
// Note this is a document fragment and YUI doesn't like them.
if (!selectednode) {
- return;
+ return false;
}
text = Y.one(selectednode).get('text');
@@ -156,8 +171,9 @@ M.atto_equation = M.atto_equation || {
equation = equation.pop();
// Replace the equation.
equation = equation.substring(2, equation.length - 2);
- Y.one('#atto_equation_equation').set('text', equation);
+ return equation;
}
+ return false;
},
/**
diff --git a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js
index ba9c3cacf3e..375fac12cb2 100644
--- a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js
+++ b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_equation-button",function(e,t){M.atto_equation=M.atto_equation||{dialogue:null,selection:null,contextids:{},library:{},lastcursor:0,display_chooser:function(t,n){t.preventDefault(),M.editor_atto.is_active(n)||M.editor_atto.focus(n),M.atto_equation.selection=M.editor_atto.get_selection();if(M.atto_equation.selection!==!1&&!M.atto_equation.selection.collapsed){var r;M.atto_equation.dialogue?r=M.atto_equation.dialogue:r=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0,width:"800px"}),r.render(),r.set("bodyContent",M.atto_equation.get_form_content(n)),r.set("headerContent",M.util.get_string("pluginname","atto_equation"));var i=new e.TabView({srcNode:"#atto_equation_library"});i.render(),r.show(),M.atto_equation.resolve_equation(),M.atto_equation.update_preview(!1,n),M.atto_equation.dialogue=r}},init:function(e){var t=M.util.image_url("e/math","core");e.texfilteractive&&(this.contextids[e.elementid]=e.contextid,this.library=e.library,M.editor_atto.add_toolbar_button(e.elementid,"equation",t,e.group,this.display_chooser))},resolve_equation:function(){var t=M.editor_atto.get_selection_parent_node(),n,r;if(!t)return;n=e.one(t).get("text"),pattern=/\$\$[\S\s]*\$\$/,r=pattern.exec(n),r&&r.length&&(r=r.pop(),r=r.substring(2,r.length-2),e.one("#atto_equation_equation").set("text",r))},set_equation:function(t,n){var r,i,s,o,u,a;t.preventDefault(),M.atto_equation.dialogue.hide(),M.editor_atto.set_selection(M.atto_equation.selection),r=t.currentTarget.ancestor(".atto_form").one("textarea"),a=r.get("value"),a!==""&&(a="$$ "+a.trim()+" $$",i=e.one(M.editor_atto.get_selection_parent_node()),s=i.get("text"),o=/\$\$[\S\s]*\$\$/,u=o.exec(s),u&&u.length?(u=u.pop(),s=s.replace(u,"$$"+a+"$$"),i.set("text",s)):document.selection&&document.selection.createRange().pasteHTML?document.selection.createRange().pasteHTML(a):document.execCommand("insertHTML",!1,a),M.editor_atto.text_updated(n))},update_preview:function(t,n){var r=e.one("#atto_equation_equation"),i=r.get("value"),s,o,u="",a="\\square ",f=r.get("selectionStart");f||(f=0);while(i.charAt(f)==="\\"&&f>0)f-=1;var l=/[\w\{\}]/;while(l.test(i.charAt(f))&&f'+this.get_library_html(t)+'"+' '+"
";var o=M.cfg.wwwroot+"/lib/editor/atto/plugins/equation/ajax.php",u={sesskey:M.cfg.sesskey,contextid:this.contextids[t],action:"filtertext",text:n};return preview=e.io(o,{sync:!0,data:u,method:"POST"}),preview.status===200&&(n=preview.responseText),n}}},"@VERSION@",{requires:["node","escape","io","event-valuechange","tabview"]});
diff --git a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js
index 0667bacc269..120d5358337 100644
--- a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js
+++ b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js
@@ -105,7 +105,10 @@ M.atto_equation = M.atto_equation || {
tabview.render();
dialogue.show();
- M.atto_equation.resolve_equation();
+ var equation = M.atto_equation.resolve_equation();
+ if (equation) {
+ Y.one('#atto_equation_equation').set('text', equation);
+ }
M.atto_equation.update_preview(false, elementid);
M.atto_equation.dialogue = dialogue;
}
@@ -128,6 +131,17 @@ M.atto_equation = M.atto_equation || {
// Add the button to the toolbar.
M.editor_atto.add_toolbar_button(params.elementid, 'equation', iconurl, params.group, this.display_chooser);
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.atto_equation.resolve_equation() !== false) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'equation');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'equation');
+ }
+ });
}
},
@@ -136,6 +150,7 @@ M.atto_equation = M.atto_equation || {
* extract the equation (and set it in the form).
*
* @method resolve_equation
+ * @return {String|Boolean} The equation or false.
*/
resolve_equation : function() {
// Find the equation in the surrounding text.
@@ -145,7 +160,7 @@ M.atto_equation = M.atto_equation || {
// Note this is a document fragment and YUI doesn't like them.
if (!selectednode) {
- return;
+ return false;
}
text = Y.one(selectednode).get('text');
@@ -156,8 +171,9 @@ M.atto_equation = M.atto_equation || {
equation = equation.pop();
// Replace the equation.
equation = equation.substring(2, equation.length - 2);
- Y.one('#atto_equation_equation').set('text', equation);
+ return equation;
}
+ return false;
},
/**
diff --git a/lib/editor/atto/plugins/equation/yui/src/button/js/button.js b/lib/editor/atto/plugins/equation/yui/src/button/js/button.js
index 8a38f592c5c..c614e152c11 100644
--- a/lib/editor/atto/plugins/equation/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/equation/yui/src/button/js/button.js
@@ -103,7 +103,10 @@ M.atto_equation = M.atto_equation || {
tabview.render();
dialogue.show();
- M.atto_equation.resolve_equation();
+ var equation = M.atto_equation.resolve_equation();
+ if (equation) {
+ Y.one('#atto_equation_equation').set('text', equation);
+ }
M.atto_equation.update_preview(false, elementid);
M.atto_equation.dialogue = dialogue;
}
@@ -126,6 +129,17 @@ M.atto_equation = M.atto_equation || {
// Add the button to the toolbar.
M.editor_atto.add_toolbar_button(params.elementid, 'equation', iconurl, params.group, this.display_chooser);
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.atto_equation.resolve_equation() !== false) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'equation');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'equation');
+ }
+ });
}
},
@@ -134,6 +148,7 @@ M.atto_equation = M.atto_equation || {
* extract the equation (and set it in the form).
*
* @method resolve_equation
+ * @return {String|Boolean} The equation or false.
*/
resolve_equation : function() {
// Find the equation in the surrounding text.
@@ -143,7 +158,7 @@ M.atto_equation = M.atto_equation || {
// Note this is a document fragment and YUI doesn't like them.
if (!selectednode) {
- return;
+ return false;
}
text = Y.one(selectednode).get('text');
@@ -154,8 +169,9 @@ M.atto_equation = M.atto_equation || {
equation = equation.pop();
// Replace the equation.
equation = equation.substring(2, equation.length - 2);
- Y.one('#atto_equation_equation').set('text', equation);
+ return equation;
}
+ return false;
},
/**
diff --git a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js
index 8ae8b92065a..81e01626367 100644
--- a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js
+++ b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_image-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'img'
+};
+
/**
* Atto text editor image plugin.
*
@@ -51,25 +60,11 @@ M.atto_image = M.atto_image || {
dialogue.centerDialogue();
M.atto_image.dialogue = dialogue;
- var selectedText = M.editor_atto.get_selection_text();
- var i = 0;
+ var images = M.editor_atto.get_selected_nodes(elementid);
+ images = images.filter(SELECTORS.TAGS);
- var images = [];
- for (i = 0; i < selectedText.childNodes.length; i++) {
- var child = selectedText.childNodes[0];
- if (images.length === 0) {
- if (child.nodeName.toLowerCase() === 'img') {
- images[0] = child;
- } else {
- if (child.getElementsByTagName) {
- images = child.getElementsByTagName('img');
- }
- }
- }
- }
-
- if (images.length > 0) {
- var image = Y.one(images[0]);
+ if (images.size() > 0) {
+ var image = images.item(0);
var width = image.getAttribute('width');
var height = image.getAttribute('height');
if (width > 0) {
@@ -93,6 +88,18 @@ M.atto_image = M.atto_image || {
var iconurl = M.util.image_url('e/insert_edit_image', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'image', iconurl, params.group, display_chooser);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (e.selectedNodes.filter(SELECTORS.TAGS).size() > 0) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'image');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'image');
+ }
+ });
},
open_filepicker : function(e) {
var elementid = this.getAttribute('data-editor');
diff --git a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js
index eae2c60b4af..0f48260ffa5 100644
--- a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js
+++ b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js
@@ -1,2 +1,2 @@
-YUI.add("moodle-atto_image-button",function(e,t){M.atto_image=M.atto_image||{dialogue:null,selection:null,init:function(t){var n=function(t,n){t.preventDefault(),M.editor_atto.is_active(n)||M.editor_atto.focus(n),M.atto_image.selection=M.editor_atto.get_selection();if(M.atto_image.selection!==!1){var r;M.atto_image.dialogue?r=M.atto_image.dialogue:r=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),r.set("bodyContent",M.atto_image.get_form_content(n)),r.set("headerContent",M.util.get_string("createimage","atto_image")),r.render(),r.centerDialogue(),M.atto_image.dialogue=r;var i=M.editor_atto.get_selection_text(),s=0,o=[];for(s=0;s0){var a=e.one(o[0]),f=a.getAttribute("width"),l=a.getAttribute("height");f>0&&e.one("#atto_image_widthentry").set("value",f),l>0&&e.one("#atto_image_heightentry").set("value",l),e.one("#atto_image_preview").set("src",a.get("src")),e.one("#atto_image_preview").setStyle("display","inline"),e.one("#atto_image_altentry").set("value",a.get("alt")),e.one("#atto_image_urlentry").set("value",a.get("src"));var c=a.get("role");c==="presentation"&&e.one("#atto_image_presentation").set("checked","checked")}r.show()}},r=M.util.image_url("e/insert_edit_image","core");M.editor_atto.add_toolbar_button(t.elementid,"image",r,t.group,n)},open_filepicker:function(e){var t=this.getAttribute("data-editor");e.preventDefault(),M.editor_atto.show_filepicker(t,"image",M.atto_image.filepicker_callback)},filepicker_callback:function(t){if(t.url!==""){var n=e.one("#atto_image_urlentry");n.set("value",t.url);var r=new Image;r.onload=function(){e.one("#atto_image_widthentry").set("value",this.width),e.one("#atto_image_heightentry").set("value",this.height),e.one("#atto_image_preview").set("src",this.src),e.one("#atto_image_preview").setStyle("display","inline")},r.src=t.url}},url_changed:function(){var t=e.one("#atto_image_urlentry");if(t.get("value")!==""){var n=new Image;n.onload=function(){var t;t=e.one("#atto_image_widthentry"),t.get("value")===""&&t.set("value",this.width),t=e.one("#atto_image_heightentry"),t.get("value")===""&&t.set("value",this.height),t=e.one("#atto_image_preview"),t.set("src",this.src),t.setStyle("display","inline")},n.src=t.get("value")}},set_image:function(t,n){var r=t.currentTarget.ancestor(".atto_form").one("#atto_image_urlentry"),i=r.get("value");r=t.currentTarget.ancestor(".atto_form").one("#atto_image_altentry");var s=r.get("value");r=t.currentTarget.ancestor(".atto_form").one("#atto_image_widthentry");var o=r.get("value");r=t.currentTarget.ancestor(".atto_form").one("#atto_image_heightentry");var u=r.get("value");r=t.currentTarget.ancestor(".atto_form").one("#atto_image_presentation");var a=r.get("checked"),f;t.preventDefault();if(s===""&&!a){f=t.currentTarget.ancestor(".atto_form").one("#atto_image_altwarning"),f.setStyle("display","block"),r=t.currentTarget.ancestor(".atto_form").one("#atto_image_altentry"),r.setAttribute("aria-invalid",!0),r=t.currentTarget.ancestor(".atto_form").one("#atto_image_presentation"),r.setAttribute("aria-invalid",!0);return}f=t.currentTarget.ancestor(".atto_form").one("#atto_image_altwarning"),f.setStyle("display","none"),r=t.currentTarget.ancestor(".atto_form").one("#atto_image_altentry"),r.setAttribute("aria-invalid",!1),r=t.currentTarget.ancestor(".atto_form").one("#atto_image_presentation"),r.setAttribute("aria-invalid",!1),M.atto_image.dialogue.hide();if(i!==""){M.editor_atto.set_selection(M.atto_image.selection);var l='",document.selection&&document.selection.createRange().pasteHTML?document.selection.createRange().pasteHTML(l):document.execCommand("insertHTML",!1,l),M.editor_atto.text_updated(n)}},get_form_content:function(t){var n='";var r=e.Node.create(n);return r.one("#atto_image_urlentry").on("blur",M.atto_image.url_changed,this),r.one("#atto_image_urlentrysubmit").on("click",M.atto_image.set_image,this,t),M.editor_atto.can_show_filepicker(t,"image")&&r.one("#openimagebrowser").on("click",M.atto_image.open_filepicker),r}}},"@VERSION@",{requires:["node","escape"
-]});
+YUI.add("moodle-atto_image-button",function(e,t){var n={TAGS:"img"};M.atto_image=M.atto_image||{dialogue:null,selection:null,init:function(t){var r=function(t,r){t.preventDefault(),M.editor_atto.is_active(r)||M.editor_atto.focus(r),M.atto_image.selection=M.editor_atto.get_selection();if(M.atto_image.selection!==!1){var i;M.atto_image.dialogue?i=M.atto_image.dialogue:i=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),i.set("bodyContent",M.atto_image.get_form_content(r)),i.set("headerContent",M.util.get_string("createimage","atto_image")),i.render(),i.centerDialogue(),M.atto_image.dialogue=i;var s=M.editor_atto.get_selected_nodes(r);s=s.filter(n.TAGS);if(s.size()>0){var o=s.item(0),u=o.getAttribute("width"),a=o.getAttribute("height");u>0&&e.one("#atto_image_widthentry").set("value",u),a>0&&e.one("#atto_image_heightentry").set("value",a),e.one("#atto_image_preview").set("src",o.get("src")),e.one("#atto_image_preview").setStyle("display","inline"),e.one("#atto_image_altentry").set("value",o.get("alt")),e.one("#atto_image_urlentry").set("value",o.get("src"));var f=o.get("role");f==="presentation"&&e.one("#atto_image_presentation").set("checked","checked")}i.show()}},i=M.util.image_url("e/insert_edit_image","core");M.editor_atto.add_toolbar_button(t.elementid,"image",i,t.group,r);var s=M.editor_atto.get_editable_node(t.elementid);s.on("atto:selectionchanged",function(e){e.selectedNodes.filter(n.TAGS).size()>0?M.editor_atto.add_widget_highlight(e.elementid,"image"):M.editor_atto.remove_widget_highlight(e.elementid,"image")})},open_filepicker:function(e){var t=this.getAttribute("data-editor");e.preventDefault(),M.editor_atto.show_filepicker(t,"image",M.atto_image.filepicker_callback)},filepicker_callback:function(t){if(t.url!==""){var n=e.one("#atto_image_urlentry");n.set("value",t.url);var r=new Image;r.onload=function(){e.one("#atto_image_widthentry").set("value",this.width),e.one("#atto_image_heightentry").set("value",this.height),e.one("#atto_image_preview").set("src",this.src),e.one("#atto_image_preview").setStyle("display","inline")},r.src=t.url}},url_changed:function(){var t=e.one("#atto_image_urlentry");if(t.get("value")!==""){var n=new Image;n.onload=function(){var t;t=e.one("#atto_image_widthentry"),t.get("value")===""&&t.set("value",this.width),t=e.one("#atto_image_heightentry"),t.get("value")===""&&t.set("value",this.height),t=e.one("#atto_image_preview"),t.set("src",this.src),t.setStyle("display","inline")},n.src=t.get("value")}},set_image:function(t,n){var r=t.currentTarget.ancestor(".atto_form").one("#atto_image_urlentry"),i=r.get("value");r=t.currentTarget.ancestor(".atto_form").one("#atto_image_altentry");var s=r.get("value");r=t.currentTarget.ancestor(".atto_form").one("#atto_image_widthentry");var o=r.get("value");r=t.currentTarget.ancestor(".atto_form").one("#atto_image_heightentry");var u=r.get("value");r=t.currentTarget.ancestor(".atto_form").one("#atto_image_presentation");var a=r.get("checked"),f;t.preventDefault();if(s===""&&!a){f=t.currentTarget.ancestor(".atto_form").one("#atto_image_altwarning"),f.setStyle("display","block"),r=t.currentTarget.ancestor(".atto_form").one("#atto_image_altentry"),r.setAttribute("aria-invalid",!0),r=t.currentTarget.ancestor(".atto_form").one("#atto_image_presentation"),r.setAttribute("aria-invalid",!0);return}f=t.currentTarget.ancestor(".atto_form").one("#atto_image_altwarning"),f.setStyle("display","none"),r=t.currentTarget.ancestor(".atto_form").one("#atto_image_altentry"),r.setAttribute("aria-invalid",!1),r=t.currentTarget.ancestor(".atto_form").one("#atto_image_presentation"),r.setAttribute("aria-invalid",!1),M.atto_image.dialogue.hide();if(i!==""){M.editor_atto.set_selection(M.atto_image.selection);var l='",document.selection&&document.selection.createRange().pasteHTML?document.selection.createRange().pasteHTML(l):document.execCommand("insertHTML",!1,l),M.editor_atto.text_updated(n)}},get_form_content:function(t){var n='";var r=e.Node.create(n);return r.one("#atto_image_urlentry").on("blur",M.atto_image.url_changed,this),r.one("#atto_image_urlentrysubmit").on("click",M.atto_image.set_image,this,t),M.editor_atto.can_show_filepicker(t,"image")&&
+r.one("#openimagebrowser").on("click",M.atto_image.open_filepicker),r}}},"@VERSION@",{requires:["node","escape"]});
diff --git a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js
index 8ae8b92065a..81e01626367 100644
--- a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js
+++ b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_image-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'img'
+};
+
/**
* Atto text editor image plugin.
*
@@ -51,25 +60,11 @@ M.atto_image = M.atto_image || {
dialogue.centerDialogue();
M.atto_image.dialogue = dialogue;
- var selectedText = M.editor_atto.get_selection_text();
- var i = 0;
+ var images = M.editor_atto.get_selected_nodes(elementid);
+ images = images.filter(SELECTORS.TAGS);
- var images = [];
- for (i = 0; i < selectedText.childNodes.length; i++) {
- var child = selectedText.childNodes[0];
- if (images.length === 0) {
- if (child.nodeName.toLowerCase() === 'img') {
- images[0] = child;
- } else {
- if (child.getElementsByTagName) {
- images = child.getElementsByTagName('img');
- }
- }
- }
- }
-
- if (images.length > 0) {
- var image = Y.one(images[0]);
+ if (images.size() > 0) {
+ var image = images.item(0);
var width = image.getAttribute('width');
var height = image.getAttribute('height');
if (width > 0) {
@@ -93,6 +88,18 @@ M.atto_image = M.atto_image || {
var iconurl = M.util.image_url('e/insert_edit_image', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'image', iconurl, params.group, display_chooser);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (e.selectedNodes.filter(SELECTORS.TAGS).size() > 0) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'image');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'image');
+ }
+ });
},
open_filepicker : function(e) {
var elementid = this.getAttribute('data-editor');
diff --git a/lib/editor/atto/plugins/image/yui/src/button/js/button.js b/lib/editor/atto/plugins/image/yui/src/button/js/button.js
index 26bff9fa202..b6b94b19066 100644
--- a/lib/editor/atto/plugins/image/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/image/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'img'
+};
+
/**
* Atto text editor image plugin.
*
@@ -49,25 +58,11 @@ M.atto_image = M.atto_image || {
dialogue.centerDialogue();
M.atto_image.dialogue = dialogue;
- var selectedText = M.editor_atto.get_selection_text();
- var i = 0;
+ var images = M.editor_atto.get_selected_nodes(elementid);
+ images = images.filter(SELECTORS.TAGS);
- var images = [];
- for (i = 0; i < selectedText.childNodes.length; i++) {
- var child = selectedText.childNodes[0];
- if (images.length === 0) {
- if (child.nodeName.toLowerCase() === 'img') {
- images[0] = child;
- } else {
- if (child.getElementsByTagName) {
- images = child.getElementsByTagName('img');
- }
- }
- }
- }
-
- if (images.length > 0) {
- var image = Y.one(images[0]);
+ if (images.size() > 0) {
+ var image = images.item(0);
var width = image.getAttribute('width');
var height = image.getAttribute('height');
if (width > 0) {
@@ -91,6 +86,18 @@ M.atto_image = M.atto_image || {
var iconurl = M.util.image_url('e/insert_edit_image', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'image', iconurl, params.group, display_chooser);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (e.selectedNodes.filter(SELECTORS.TAGS).size() > 0) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'image');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'image');
+ }
+ });
},
open_filepicker : function(e) {
var elementid = this.getAttribute('data-editor');
diff --git a/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-debug.js b/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-debug.js
index 184c8058fd4..373b0e22d70 100644
--- a/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-debug.js
+++ b/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_italic-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'i'
+};
+
/**
* Atto text editor italic plugin.
*
@@ -36,6 +45,18 @@ M.atto_italic = M.atto_italic || {
var iconurl = M.util.image_url('e/italic', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'italic', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'italic');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'italic');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-min.js b/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-min.js
index dac855eb9f3..28a75d8d788 100644
--- a/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-min.js
+++ b/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_italic-button",function(e,t){M.atto_italic=M.atto_italic||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("italic",!1,null),M.editor_atto.text_updated(t)},n=M.util.image_url("e/italic","core");M.editor_atto.add_toolbar_button(e.elementid,"italic",n,e.group,t)}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_italic-button",function(e,t){var n={TAGS:"i"};M.atto_italic=M.atto_italic||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("italic",!1,null),M.editor_atto.text_updated(t)},r=M.util.image_url("e/italic","core");M.editor_atto.add_toolbar_button(e.elementid,"italic",r,e.group,t);var i=M.editor_atto.get_editable_node(e.elementid);i.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"italic"):M.editor_atto.remove_widget_highlight(e.elementid,"italic")})}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button.js b/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button.js
index 184c8058fd4..373b0e22d70 100644
--- a/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button.js
+++ b/lib/editor/atto/plugins/italic/yui/build/moodle-atto_italic-button/moodle-atto_italic-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_italic-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'i'
+};
+
/**
* Atto text editor italic plugin.
*
@@ -36,6 +45,18 @@ M.atto_italic = M.atto_italic || {
var iconurl = M.util.image_url('e/italic', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'italic', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'italic');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'italic');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/italic/yui/src/button/js/button.js b/lib/editor/atto/plugins/italic/yui/src/button/js/button.js
index a4000ff1b25..c97236859b6 100644
--- a/lib/editor/atto/plugins/italic/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/italic/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'i'
+};
+
/**
* Atto text editor italic plugin.
*
@@ -34,5 +43,17 @@ M.atto_italic = M.atto_italic || {
var iconurl = M.util.image_url('e/italic', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'italic', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'italic');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'italic');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-debug.js b/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-debug.js
index c1cf4864db2..9e87f788a27 100644
--- a/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-debug.js
+++ b/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_link-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'a'
+};
+
/**
* Atto text editor link plugin.
*
@@ -87,6 +96,17 @@ M.atto_link = M.atto_link || {
init : function(params) {
var iconurl = M.util.image_url('e/insert_edit_link', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'link', iconurl, params.group, this.display_chooser);
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'link');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'link');
+ }
+ });
},
/**
diff --git a/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-min.js b/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-min.js
index 923e9a977ba..f3e56775b7a 100644
--- a/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-min.js
+++ b/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_link-button",function(e,t){M.atto_link=M.atto_link||{dialogue:null,selection:null,display_chooser:function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_link.selection=M.editor_atto.get_selection();if(M.atto_link.selection!==!1&&!M.atto_link.selection.collapsed){var n;M.atto_link.dialogue?n=M.atto_link.dialogue:n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.render(),n.set("bodyContent",M.atto_link.get_form_content(t)),n.set("headerContent",M.util.get_string("createlink","atto_link")),M.atto_link.resolve_anchors(),n.show(),M.atto_link.dialogue=n}},init:function(e){var t=M.util.image_url("e/insert_edit_link","core");M.editor_atto.add_toolbar_button(e.elementid,"link",t,e.group,this.display_chooser)},resolve_anchors:function(){var t=M.editor_atto.get_selection_parent_node(),n,r,i;if(!t)return;n=M.atto_link.find_selected_anchors(e.one(t)),n.length>0&&(r=n[0],M.atto_link.selection=M.editor_atto.get_selection_from_node(r),i=r.getAttribute("href"),target=r.getAttribute("target"),i!==""&&e.one("#atto_link_urlentry").set("value",i),target==="_blank"?e.one("#atto_link_openinnewwindow").set("checked","checked"):e.one("#atto_link_openinnewwindow").set("checked",""))},open_filepicker:function(e){var t=this.getAttribute("data-editor");e.preventDefault(),M.editor_atto.show_filepicker(t,"link",M.atto_link.filepicker_callback)},filepicker_callback:function(e){M.atto_link.dialogue.hide(),e.url!==""&&(M.editor_atto.set_selection(M.atto_link.selection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,e.url))},set_link:function(t,n){var r,i,s,o,u;t.preventDefault(),M.atto_link.dialogue.hide(),r=t.currentTarget.ancestor(".atto_form").one("input[type=url]"),u=r.get("value");if(u!==""){M.editor_atto.set_selection(M.atto_link.selection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,u),s=M.editor_atto.get_selection_parent_node();if(!s)return;o=M.atto_link.find_selected_anchors(e.one(s)),e.Array.each(o,function(e){i=t.currentTarget.ancestor(".atto_form").one("input[type=checkbox]"),i.get("checked")?e.setAttribute("target","_blank"):e.removeAttribute("target")}),M.editor_atto.text_updated(n)}},find_selected_anchors:function(e){var t=e.get("tagName"),n,r;return t&&t.toLowerCase()==="a"?[e]:(r=[],e.all("a").each(function(e){!n&&M.editor_atto.selection_contains_node(e)&&r.push(e)}),r.length>0?r:(n=e.ancestor("a"),n?[n]:[]))},get_form_content:function(t){var n='";var r=e.Node.create(n);return r.one("#atto_link_urlentrysubmit").on("click",M.atto_link.set_link,this,t),M.editor_atto.can_show_filepicker(t,"link")&&r.one("#openlinkbrowser").on("click",M.atto_link.open_filepicker),r}}},"@VERSION@",{requires:["node","escape"]});
+YUI.add("moodle-atto_link-button",function(e,t){var n={TAGS:"a"};M.atto_link=M.atto_link||{dialogue:null,selection:null,display_chooser:function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_link.selection=M.editor_atto.get_selection();if(M.atto_link.selection!==!1&&!M.atto_link.selection.collapsed){var n;M.atto_link.dialogue?n=M.atto_link.dialogue:n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.render(),n.set("bodyContent",M.atto_link.get_form_content(t)),n.set("headerContent",M.util.get_string("createlink","atto_link")),M.atto_link.resolve_anchors(),n.show(),M.atto_link.dialogue=n}},init:function(e){var t=M.util.image_url("e/insert_edit_link","core");M.editor_atto.add_toolbar_button(e.elementid,"link",t,e.group,this.display_chooser);var r=M.editor_atto.get_editable_node(e.elementid);r.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"link"):M.editor_atto.remove_widget_highlight(e.elementid,"link")})},resolve_anchors:function(){var t=M.editor_atto.get_selection_parent_node(),n,r,i;if(!t)return;n=M.atto_link.find_selected_anchors(e.one(t)),n.length>0&&(r=n[0],M.atto_link.selection=M.editor_atto.get_selection_from_node(r),i=r.getAttribute("href"),target=r.getAttribute("target"),i!==""&&e.one("#atto_link_urlentry").set("value",i),target==="_blank"?e.one("#atto_link_openinnewwindow").set("checked","checked"):e.one("#atto_link_openinnewwindow").set("checked",""))},open_filepicker:function(e){var t=this.getAttribute("data-editor");e.preventDefault(),M.editor_atto.show_filepicker(t,"link",M.atto_link.filepicker_callback)},filepicker_callback:function(e){M.atto_link.dialogue.hide(),e.url!==""&&(M.editor_atto.set_selection(M.atto_link.selection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,e.url))},set_link:function(t,n){var r,i,s,o,u;t.preventDefault(),M.atto_link.dialogue.hide(),r=t.currentTarget.ancestor(".atto_form").one("input[type=url]"),u=r.get("value");if(u!==""){M.editor_atto.set_selection(M.atto_link.selection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,u),s=M.editor_atto.get_selection_parent_node();if(!s)return;o=M.atto_link.find_selected_anchors(e.one(s)),e.Array.each(o,function(e){i=t.currentTarget.ancestor(".atto_form").one("input[type=checkbox]"),i.get("checked")?e.setAttribute("target","_blank"):e.removeAttribute("target")}),M.editor_atto.text_updated(n)}},find_selected_anchors:function(e){var t=e.get("tagName"),n,r;return t&&t.toLowerCase()==="a"?[e]:(r=[],e.all("a").each(function(e){!n&&M.editor_atto.selection_contains_node(e)&&r.push(e)}),r.length>0?r:(n=e.ancestor("a"),n?[n]:[]))},get_form_content:function(t){var n='";var r=e.Node.create(n);return r.one("#atto_link_urlentrysubmit").on("click",M.atto_link.set_link,this,t),M.editor_atto.can_show_filepicker(t,"link")&&r.one("#openlinkbrowser").on("click",M.atto_link.open_filepicker),r}}},"@VERSION@",{requires:["node","escape"]});
diff --git a/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button.js b/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button.js
index c1cf4864db2..9e87f788a27 100644
--- a/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button.js
+++ b/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_link-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'a'
+};
+
/**
* Atto text editor link plugin.
*
@@ -87,6 +96,17 @@ M.atto_link = M.atto_link || {
init : function(params) {
var iconurl = M.util.image_url('e/insert_edit_link', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'link', iconurl, params.group, this.display_chooser);
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'link');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'link');
+ }
+ });
},
/**
diff --git a/lib/editor/atto/plugins/link/yui/src/button/js/button.js b/lib/editor/atto/plugins/link/yui/src/button/js/button.js
index 2dcb6c8f011..1993300499f 100644
--- a/lib/editor/atto/plugins/link/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/link/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'a'
+};
+
/**
* Atto text editor link plugin.
*
@@ -85,6 +94,17 @@ M.atto_link = M.atto_link || {
init : function(params) {
var iconurl = M.util.image_url('e/insert_edit_link', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'link', iconurl, params.group, this.display_chooser);
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'link');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'link');
+ }
+ });
},
/**
diff --git a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button-debug.js b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button-debug.js
index 91ba7b6f96f..9372ad7f954 100644
--- a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button-debug.js
+++ b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button-debug.js
@@ -148,7 +148,7 @@ M.atto_managefiles = M.atto_managefiles || {
content = editableNode.getHTML(),
params = M.atto_managefiles.params[elementid],
baseUrl = M.cfg.wwwroot + '/draftfile.php/' + params.usercontext + '/user/draft/' + params.area.itemid + '/',
- pattern = new RegExp(baseUrl.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + "(.+?)[\\?\"']", 'gm'),
+ pattern = new RegExp(baseUrl.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g, '\\$&') + "(.+?)[\\?\"']", 'gm'),
filename = '',
match = '',
usedFiles = {};
diff --git a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button-min.js b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button-min.js
index 6b5dacee2df..8e311dd40cd 100644
--- a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button-min.js
+++ b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_managefiles-button",function(e,t){M.atto_managefiles=M.atto_managefiles||{currentElementId:null,dialogue:null,params:{},init:function(t){if(t.disabled)return;if(!(!t.area.itemid&&M.editor_atto.filepickeroptions[t.elementid]&&M.editor_atto.filepickeroptions[t.elementid].image&&M.editor_atto.filepickeroptions[t.elementid].image.itemid)){console.log("Plugin managefiles not available because itemid is missing.");return}t.area.itemid=M.editor_atto.filepickeroptions[t.elementid].image.itemid,M.atto_managefiles.params[t.elementid]=t;var n=function(t,n){var r,i;t.preventDefault(),M.atto_managefiles.currentElementId=n,M.atto_managefiles.dialogue?r=M.atto_managefiles.dialogue:(r=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0,width:"800px"}),r.set("headerContent",M.util.get_string("managefiles","atto_managefiles")),M.atto_managefiles.dialogue=r,r.render(),r.centerDialogue()),i=e.Node.create(""),i.setStyle("height","700px"),i.setStyle("border","none"),i.setStyle("width","100%"),i.setAttribute("src",M.atto_managefiles.getIframeURL()),r.set("bodyContent",i),r.show(),M.editor_atto.text_updated(n)},r=M.util.image_url("e/manage_files","core");M.editor_atto.add_toolbar_button(t.elementid,"managefiles",r,t.group,n)},getIframeURL:function(){var e,t,n="";n=M.cfg.wwwroot+"/lib/editor/atto/plugins/managefiles/manage.php?",t=M.atto_managefiles.params[M.atto_managefiles.currentElementId];for(e in t.area)n+=encodeURIComponent(e)+"="+encodeURIComponent(t.area[e])+"&";return n},getUsedFiles:function(){var e=M.atto_managefiles.currentElementId,t=M.editor_atto.get_editable_node(e),n=t.getHTML(),r=M.atto_managefiles.params[e],i=M.cfg.wwwroot+"/draftfile.php/"+r.usercontext+"/user/draft/"+r.area.itemid+"/",s=new RegExp(i.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")+"(.+?)[\\?\"']","gm"),o="",u="",a={};while((u=s.exec(n))!==null)o=unescape(u[1]),a[o]=!0;return a}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_managefiles-button",function(e,t){M.atto_managefiles=M.atto_managefiles||{currentElementId:null,dialogue:null,params:{},init:function(t){if(t.disabled)return;if(!(!t.area.itemid&&M.editor_atto.filepickeroptions[t.elementid]&&M.editor_atto.filepickeroptions[t.elementid].image&&M.editor_atto.filepickeroptions[t.elementid].image.itemid)){console.log("Plugin managefiles not available because itemid is missing.");return}t.area.itemid=M.editor_atto.filepickeroptions[t.elementid].image.itemid,M.atto_managefiles.params[t.elementid]=t;var n=function(t,n){var r,i;t.preventDefault(),M.atto_managefiles.currentElementId=n,M.atto_managefiles.dialogue?r=M.atto_managefiles.dialogue:(r=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0,width:"800px"}),r.set("headerContent",M.util.get_string("managefiles","atto_managefiles")),M.atto_managefiles.dialogue=r,r.render(),r.centerDialogue()),i=e.Node.create(""),i.setStyle("height","700px"),i.setStyle("border","none"),i.setStyle("width","100%"),i.setAttribute("src",M.atto_managefiles.getIframeURL()),r.set("bodyContent",i),r.show(),M.editor_atto.text_updated(n)},r=M.util.image_url("e/manage_files","core");M.editor_atto.add_toolbar_button(t.elementid,"managefiles",r,t.group,n)},getIframeURL:function(){var e,t,n="";n=M.cfg.wwwroot+"/lib/editor/atto/plugins/managefiles/manage.php?",t=M.atto_managefiles.params[M.atto_managefiles.currentElementId];for(e in t.area)n+=encodeURIComponent(e)+"="+encodeURIComponent(t.area[e])+"&";return n},getUsedFiles:function(){var e=M.atto_managefiles.currentElementId,t=M.editor_atto.get_editable_node(e),n=t.getHTML(),r=M.atto_managefiles.params[e],i=M.cfg.wwwroot+"/draftfile.php/"+r.usercontext+"/user/draft/"+r.area.itemid+"/",s=new RegExp(i.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g,"\\$&")+"(.+?)[\\?\"']","gm"),o="",u="",a={};while((u=s.exec(n))!==null)o=unescape(u[1]),a[o]=!0;return a}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button.js b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button.js
index 91ba7b6f96f..9372ad7f954 100644
--- a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button.js
+++ b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-button/moodle-atto_managefiles-button.js
@@ -148,7 +148,7 @@ M.atto_managefiles = M.atto_managefiles || {
content = editableNode.getHTML(),
params = M.atto_managefiles.params[elementid],
baseUrl = M.cfg.wwwroot + '/draftfile.php/' + params.usercontext + '/user/draft/' + params.area.itemid + '/',
- pattern = new RegExp(baseUrl.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + "(.+?)[\\?\"']", 'gm'),
+ pattern = new RegExp(baseUrl.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g, '\\$&') + "(.+?)[\\?\"']", 'gm'),
filename = '',
match = '',
usedFiles = {};
diff --git a/lib/editor/atto/plugins/managefiles/yui/src/button/js/button.js b/lib/editor/atto/plugins/managefiles/yui/src/button/js/button.js
index ca047246a04..c7c914fcd06 100644
--- a/lib/editor/atto/plugins/managefiles/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/managefiles/yui/src/button/js/button.js
@@ -146,7 +146,7 @@ M.atto_managefiles = M.atto_managefiles || {
content = editableNode.getHTML(),
params = M.atto_managefiles.params[elementid],
baseUrl = M.cfg.wwwroot + '/draftfile.php/' + params.usercontext + '/user/draft/' + params.area.itemid + '/',
- pattern = new RegExp(baseUrl.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + "(.+?)[\\?\"']", 'gm'),
+ pattern = new RegExp(baseUrl.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g, '\\$&') + "(.+?)[\\?\"']", 'gm'),
filename = '',
match = '',
usedFiles = {};
diff --git a/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button-debug.js b/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button-debug.js
index 4901f1d3b64..9befd50f99c 100644
--- a/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button-debug.js
+++ b/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_orderedlist-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'ol'
+};
+
/**
* Atto text editor orderedlist plugin.
*
@@ -36,6 +45,18 @@ M.atto_orderedlist = M.atto_orderedlist || {
var iconurl = M.util.image_url('e/numbered_list', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'orderedlist', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'orderedlist');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'orderedlist');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button-min.js b/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button-min.js
index 245f5d96e74..47e6a7fb47c 100644
--- a/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button-min.js
+++ b/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_orderedlist-button",function(e,t){M.atto_orderedlist=M.atto_orderedlist||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("insertOrderedList",!1,null),M.editor_atto.text_updated(t)},n=M.util.image_url("e/numbered_list","core");M.editor_atto.add_toolbar_button(e.elementid,"orderedlist",n,e.group,t)}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_orderedlist-button",function(e,t){var n={TAGS:"ol"};M.atto_orderedlist=M.atto_orderedlist||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("insertOrderedList",!1,null),M.editor_atto.text_updated(t)},r=M.util.image_url("e/numbered_list","core");M.editor_atto.add_toolbar_button(e.elementid,"orderedlist",r,e.group,t);var i=M.editor_atto.get_editable_node(e.elementid);i.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"orderedlist"):M.editor_atto.remove_widget_highlight(e.elementid,"orderedlist")})}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button.js b/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button.js
index 4901f1d3b64..9befd50f99c 100644
--- a/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button.js
+++ b/lib/editor/atto/plugins/orderedlist/yui/build/moodle-atto_orderedlist-button/moodle-atto_orderedlist-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_orderedlist-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'ol'
+};
+
/**
* Atto text editor orderedlist plugin.
*
@@ -36,6 +45,18 @@ M.atto_orderedlist = M.atto_orderedlist || {
var iconurl = M.util.image_url('e/numbered_list', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'orderedlist', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'orderedlist');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'orderedlist');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/orderedlist/yui/src/button/js/button.js b/lib/editor/atto/plugins/orderedlist/yui/src/button/js/button.js
index 397b25b2364..3b7cfa35d43 100644
--- a/lib/editor/atto/plugins/orderedlist/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/orderedlist/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'ol'
+};
+
/**
* Atto text editor orderedlist plugin.
*
@@ -34,5 +43,17 @@ M.atto_orderedlist = M.atto_orderedlist || {
var iconurl = M.util.image_url('e/numbered_list', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'orderedlist', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'orderedlist');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'orderedlist');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-debug.js b/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-debug.js
index 4b753823204..9509588740e 100644
--- a/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-debug.js
+++ b/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_strike-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'strike'
+};
+
/**
* Atto text editor strike plugin.
*
@@ -36,6 +45,18 @@ M.atto_strike = M.atto_strike || {
var iconurl = M.util.image_url('e/strikethrough', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'strike', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'strike');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'strike');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-min.js b/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-min.js
index 39f48b6e56e..0a1b6980298 100644
--- a/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-min.js
+++ b/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_strike-button",function(e,t){M.atto_strike=M.atto_strike||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("strikeThrough",!1,null),M.editor_atto.text_updated(t)},n=M.util.image_url("e/strikethrough","core");M.editor_atto.add_toolbar_button(e.elementid,"strike",n,e.group,t)}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_strike-button",function(e,t){var n={TAGS:"strike"};M.atto_strike=M.atto_strike||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("strikeThrough",!1,null),M.editor_atto.text_updated(t)},r=M.util.image_url("e/strikethrough","core");M.editor_atto.add_toolbar_button(e.elementid,"strike",r,e.group,t);var i=M.editor_atto.get_editable_node(e.elementid);i.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"strike"):M.editor_atto.remove_widget_highlight(e.elementid,"strike")})}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button.js b/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button.js
index 4b753823204..9509588740e 100644
--- a/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button.js
+++ b/lib/editor/atto/plugins/strike/yui/build/moodle-atto_strike-button/moodle-atto_strike-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_strike-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'strike'
+};
+
/**
* Atto text editor strike plugin.
*
@@ -36,6 +45,18 @@ M.atto_strike = M.atto_strike || {
var iconurl = M.util.image_url('e/strikethrough', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'strike', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'strike');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'strike');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/strike/yui/src/button/js/button.js b/lib/editor/atto/plugins/strike/yui/src/button/js/button.js
index c7e95459724..326a30c7319 100644
--- a/lib/editor/atto/plugins/strike/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/strike/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'strike'
+};
+
/**
* Atto text editor strike plugin.
*
@@ -34,5 +43,17 @@ M.atto_strike = M.atto_strike || {
var iconurl = M.util.image_url('e/strikethrough', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'strike', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'strike');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'strike');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button-debug.js b/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button-debug.js
index db620b46aad..53574086f47 100644
--- a/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button-debug.js
+++ b/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_subscript-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'sub'
+};
+
/**
* Atto text editor subscript plugin.
*
@@ -36,6 +45,18 @@ M.atto_subscript = M.atto_subscript || {
var iconurl = M.util.image_url('e/subscript', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'subscript', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'sub');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'sub');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button-min.js b/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button-min.js
index ffb79f06369..a786ff68f7a 100644
--- a/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button-min.js
+++ b/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_subscript-button",function(e,t){M.atto_subscript=M.atto_subscript||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("subscript",!1,null),M.editor_atto.text_updated(t)},n=M.util.image_url("e/subscript","core");M.editor_atto.add_toolbar_button(e.elementid,"subscript",n,e.group,t)}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_subscript-button",function(e,t){var n={TAGS:"sub"};M.atto_subscript=M.atto_subscript||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("subscript",!1,null),M.editor_atto.text_updated(t)},r=M.util.image_url("e/subscript","core");M.editor_atto.add_toolbar_button(e.elementid,"subscript",r,e.group,t);var i=M.editor_atto.get_editable_node(e.elementid);i.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"sub"):M.editor_atto.remove_widget_highlight(e.elementid,"sub")})}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button.js b/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button.js
index db620b46aad..53574086f47 100644
--- a/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button.js
+++ b/lib/editor/atto/plugins/subscript/yui/build/moodle-atto_subscript-button/moodle-atto_subscript-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_subscript-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'sub'
+};
+
/**
* Atto text editor subscript plugin.
*
@@ -36,6 +45,18 @@ M.atto_subscript = M.atto_subscript || {
var iconurl = M.util.image_url('e/subscript', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'subscript', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'sub');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'sub');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/subscript/yui/src/button/js/button.js b/lib/editor/atto/plugins/subscript/yui/src/button/js/button.js
index 28afa23827d..aa6f38082e9 100644
--- a/lib/editor/atto/plugins/subscript/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/subscript/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'sub'
+};
+
/**
* Atto text editor subscript plugin.
*
@@ -34,5 +43,17 @@ M.atto_subscript = M.atto_subscript || {
var iconurl = M.util.image_url('e/subscript', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'subscript', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'sub');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'sub');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button-debug.js b/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button-debug.js
index 6a746b8bf9f..c9248427745 100644
--- a/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button-debug.js
+++ b/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_superscript-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'sup'
+};
+
/**
* Atto text editor superscript plugin.
*
@@ -36,6 +45,18 @@ M.atto_superscript = M.atto_superscript || {
var iconurl = M.util.image_url('e/superscript', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'superscript', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'sup');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'sup');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button-min.js b/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button-min.js
index 3a0c30cd0de..8ff64ef3a34 100644
--- a/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button-min.js
+++ b/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_superscript-button",function(e,t){M.atto_superscript=M.atto_superscript||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("superscript",!1,null),M.editor_atto.text_updated(t)},n=M.util.image_url("e/superscript","core");M.editor_atto.add_toolbar_button(e.elementid,"superscript",n,e.group,t)}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_superscript-button",function(e,t){var n={TAGS:"sup"};M.atto_superscript=M.atto_superscript||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("superscript",!1,null),M.editor_atto.text_updated(t)},r=M.util.image_url("e/superscript","core");M.editor_atto.add_toolbar_button(e.elementid,"superscript",r,e.group,t);var i=M.editor_atto.get_editable_node(e.elementid);i.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"sup"):M.editor_atto.remove_widget_highlight(e.elementid,"sup")})}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button.js b/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button.js
index 6a746b8bf9f..c9248427745 100644
--- a/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button.js
+++ b/lib/editor/atto/plugins/superscript/yui/build/moodle-atto_superscript-button/moodle-atto_superscript-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_superscript-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'sup'
+};
+
/**
* Atto text editor superscript plugin.
*
@@ -36,6 +45,18 @@ M.atto_superscript = M.atto_superscript || {
var iconurl = M.util.image_url('e/superscript', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'superscript', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'sup');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'sup');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/superscript/yui/src/button/js/button.js b/lib/editor/atto/plugins/superscript/yui/src/button/js/button.js
index 708009e3f26..8374e35bd3d 100644
--- a/lib/editor/atto/plugins/superscript/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/superscript/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'sup'
+};
+
/**
* Atto text editor superscript plugin.
*
@@ -34,5 +43,17 @@ M.atto_superscript = M.atto_superscript || {
var iconurl = M.util.image_url('e/superscript', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'superscript', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'sup');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'sup');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js
index 90fbdd6e7f8..34f867e185c 100644
--- a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js
+++ b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_table-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'table'
+};
+
/**
* Atto text editor table plugin.
*
@@ -519,6 +528,17 @@ M.atto_table = M.atto_table || {
document.execCommand("enableObjectResizing", false, false);
}
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'table');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'table');
+ }
+ });
},
/**
diff --git a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js
index 056fcf96a32..8cd9e242030 100644
--- a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js
+++ b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js
@@ -1,2 +1,2 @@
-YUI.add("moodle-atto_table-button",function(e,t){M.atto_table=M.atto_table||{dialogue:null,selection:null,menunode:null,controlmenu:null,lasttarget:null,display_chooser:function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_table.selection=M.editor_atto.get_selection();if(M.atto_table.selection!==!1&&!M.atto_table.selection.collapsed){var n;M.atto_table.dialogue?n=M.atto_table.dialogue:n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.render(),n.set("bodyContent",M.atto_table.get_form_content(t)),n.set("headerContent",M.util.get_string("createtable","atto_table")),n.show(),M.atto_table.dialogue=n}},show_menu:function(t,n){var r=!1;t.preventDefault();if(this.controlmenu===null){r=!0;var i="
"+l+" ",document.execCommand("insertHTML",!1,u),M.editor_atto.text_updated(n)},get_form_content:function(t){var n=e.Node.create('"+""+M.util.get_string("accessibilityhint","atto_table"));return n.one("#atto_table_submit").on("click",M.atto_table.set_table,this,t),n}}},"@VERSION@",{requires:["node","escape","event","event-valuechange"]});
diff --git a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js
index 90fbdd6e7f8..34f867e185c 100644
--- a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js
+++ b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_table-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'table'
+};
+
/**
* Atto text editor table plugin.
*
@@ -519,6 +528,17 @@ M.atto_table = M.atto_table || {
document.execCommand("enableObjectResizing", false, false);
}
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'table');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'table');
+ }
+ });
},
/**
diff --git a/lib/editor/atto/plugins/table/yui/src/button/js/button.js b/lib/editor/atto/plugins/table/yui/src/button/js/button.js
index 8d6850c7c96..311c51de2e8 100644
--- a/lib/editor/atto/plugins/table/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/table/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'table'
+};
+
/**
* Atto text editor table plugin.
*
@@ -517,6 +526,17 @@ M.atto_table = M.atto_table || {
document.execCommand("enableObjectResizing", false, false);
}
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'table');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'table');
+ }
+ });
},
/**
diff --git a/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button-debug.js b/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button-debug.js
index faaec75191c..da25d1a32dc 100644
--- a/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button-debug.js
+++ b/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_underline-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'u'
+};
+
/**
* Atto text editor underline plugin.
*
@@ -36,6 +45,18 @@ M.atto_underline = M.atto_underline || {
var iconurl = M.util.image_url('e/underline', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'underline', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'underline');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'underline');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button-min.js b/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button-min.js
index 523d8b41712..798d0f7d277 100644
--- a/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button-min.js
+++ b/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_underline-button",function(e,t){M.atto_underline=M.atto_underline||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("underline",!1,null),M.editor_atto.text_updated(t)},n=M.util.image_url("e/underline","core");M.editor_atto.add_toolbar_button(e.elementid,"underline",n,e.group,t)}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_underline-button",function(e,t){var n={TAGS:"u"};M.atto_underline=M.atto_underline||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("underline",!1,null),M.editor_atto.text_updated(t)},r=M.util.image_url("e/underline","core");M.editor_atto.add_toolbar_button(e.elementid,"underline",r,e.group,t);var i=M.editor_atto.get_editable_node(e.elementid);i.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"underline"):M.editor_atto.remove_widget_highlight(e.elementid,"underline")})}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button.js b/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button.js
index faaec75191c..da25d1a32dc 100644
--- a/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button.js
+++ b/lib/editor/atto/plugins/underline/yui/build/moodle-atto_underline-button/moodle-atto_underline-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_underline-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'u'
+};
+
/**
* Atto text editor underline plugin.
*
@@ -36,6 +45,18 @@ M.atto_underline = M.atto_underline || {
var iconurl = M.util.image_url('e/underline', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'underline', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'underline');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'underline');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/underline/yui/src/button/js/button.js b/lib/editor/atto/plugins/underline/yui/src/button/js/button.js
index 415c4175446..e2dd6b89026 100644
--- a/lib/editor/atto/plugins/underline/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/underline/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'u'
+};
+
/**
* Atto text editor underline plugin.
*
@@ -34,5 +43,17 @@ M.atto_underline = M.atto_underline || {
var iconurl = M.util.image_url('e/underline', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'underline', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'underline');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'underline');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button-debug.js b/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button-debug.js
index 49600b02f8f..e8eee96e9d2 100644
--- a/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button-debug.js
+++ b/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_unlink-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'a'
+};
+
/**
* Atto text editor unlink plugin.
*
@@ -36,6 +45,18 @@ M.atto_unlink = M.atto_unlink || {
var iconurl = M.util.image_url('e/remove_link', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'unlink', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'unlink');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'unlink');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button-min.js b/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button-min.js
index 74e953d341a..be16b4b81f0 100644
--- a/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button-min.js
+++ b/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_unlink-button",function(e,t){M.atto_unlink=M.atto_unlink||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("unlink",!1,null),M.editor_atto.text_updated(t)},n=M.util.image_url("e/remove_link","core");M.editor_atto.add_toolbar_button(e.elementid,"unlink",n,e.group,t)}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_unlink-button",function(e,t){var n={TAGS:"a"};M.atto_unlink=M.atto_unlink||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("unlink",!1,null),M.editor_atto.text_updated(t)},r=M.util.image_url("e/remove_link","core");M.editor_atto.add_toolbar_button(e.elementid,"unlink",r,e.group,t);var i=M.editor_atto.get_editable_node(e.elementid);i.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"unlink"):M.editor_atto.remove_widget_highlight(e.elementid,"unlink")})}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button.js b/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button.js
index 49600b02f8f..e8eee96e9d2 100644
--- a/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button.js
+++ b/lib/editor/atto/plugins/unlink/yui/build/moodle-atto_unlink-button/moodle-atto_unlink-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_unlink-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'a'
+};
+
/**
* Atto text editor unlink plugin.
*
@@ -36,6 +45,18 @@ M.atto_unlink = M.atto_unlink || {
var iconurl = M.util.image_url('e/remove_link', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'unlink', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'unlink');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'unlink');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/unlink/yui/src/button/js/button.js b/lib/editor/atto/plugins/unlink/yui/src/button/js/button.js
index 328ea7f1a4c..b01c8ef8b5e 100644
--- a/lib/editor/atto/plugins/unlink/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/unlink/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'a'
+};
+
/**
* Atto text editor unlink plugin.
*
@@ -34,5 +43,17 @@ M.atto_unlink = M.atto_unlink || {
var iconurl = M.util.image_url('e/remove_link', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'unlink', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'unlink');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'unlink');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button-debug.js b/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button-debug.js
index 26357ac3e4e..4ee39f03540 100644
--- a/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button-debug.js
+++ b/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button-debug.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_unorderedlist-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'ul'
+};
+
/**
* Atto text editor unorderedlist plugin.
*
@@ -36,6 +45,18 @@ M.atto_unorderedlist = M.atto_unorderedlist || {
var iconurl = M.util.image_url('e/bullet_list', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'unorderedlist', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'unorderedlist');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'unorderedlist');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button-min.js b/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button-min.js
index 013e578820c..d1c67c188d4 100644
--- a/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button-min.js
+++ b/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button-min.js
@@ -1 +1 @@
-YUI.add("moodle-atto_unorderedlist-button",function(e,t){M.atto_unorderedlist=M.atto_unorderedlist||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("insertUnorderedList",!1,null),M.editor_atto.text_updated(t)},n=M.util.image_url("e/bullet_list","core");M.editor_atto.add_toolbar_button(e.elementid,"unorderedlist",n,e.group,t)}}},"@VERSION@",{requires:["node"]});
+YUI.add("moodle-atto_unorderedlist-button",function(e,t){var n={TAGS:"ul"};M.atto_unorderedlist=M.atto_unorderedlist||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("insertUnorderedList",!1,null),M.editor_atto.text_updated(t)},r=M.util.image_url("e/bullet_list","core");M.editor_atto.add_toolbar_button(e.elementid,"unorderedlist",r,e.group,t);var i=M.editor_atto.get_editable_node(e.elementid);i.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes)?M.editor_atto.add_widget_highlight(e.elementid,"unorderedlist"):M.editor_atto.remove_widget_highlight(e.elementid,"unorderedlist")})}}},"@VERSION@",{requires:["node"]});
diff --git a/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button.js b/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button.js
index 26357ac3e4e..4ee39f03540 100644
--- a/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button.js
+++ b/lib/editor/atto/plugins/unorderedlist/yui/build/moodle-atto_unorderedlist-button/moodle-atto_unorderedlist-button.js
@@ -15,6 +15,15 @@ YUI.add('moodle-atto_unorderedlist-button', function (Y, NAME) {
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'ul'
+};
+
/**
* Atto text editor unorderedlist plugin.
*
@@ -36,6 +45,18 @@ M.atto_unorderedlist = M.atto_unorderedlist || {
var iconurl = M.util.image_url('e/bullet_list', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'unorderedlist', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'unorderedlist');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'unorderedlist');
+ }
+ });
}
};
diff --git a/lib/editor/atto/plugins/unorderedlist/yui/src/button/js/button.js b/lib/editor/atto/plugins/unorderedlist/yui/src/button/js/button.js
index d1082b8e72c..d04a38104c2 100644
--- a/lib/editor/atto/plugins/unorderedlist/yui/src/button/js/button.js
+++ b/lib/editor/atto/plugins/unorderedlist/yui/src/button/js/button.js
@@ -13,6 +13,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+/**
+ * Selectors.
+ *
+ * @type {Object}
+ */
+var SELECTORS = {
+ TAGS : 'ul'
+};
+
/**
* Atto text editor unorderedlist plugin.
*
@@ -34,5 +43,17 @@ M.atto_unorderedlist = M.atto_unorderedlist || {
var iconurl = M.util.image_url('e/bullet_list', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'unorderedlist', iconurl, params.group, click);
+
+ // Attach an event listner to watch for "changes" in the contenteditable.
+ // This includes cursor changes, we check if the button should be active or not, based
+ // on the text selection.
+ var editable = M.editor_atto.get_editable_node(params.elementid);
+ editable.on('atto:selectionchanged', function(e) {
+ if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes)) {
+ M.editor_atto.add_widget_highlight(e.elementid, 'unorderedlist');
+ } else {
+ M.editor_atto.remove_widget_highlight(e.elementid, 'unorderedlist');
+ }
+ });
}
};
diff --git a/lib/editor/atto/styles.css b/lib/editor/atto/styles.css
index 2c1032baa2f..981899e3021 100755
--- a/lib/editor/atto/styles.css
+++ b/lib/editor/atto/styles.css
@@ -53,7 +53,7 @@ div.editor_atto_toolbar button[disabled] {
background-color: #ebebeb;
}
-.editor_atto_toolbar button:active {
+.editor_atto_toolbar button:active, .editor_atto_toolbar button.highlight {
background-image: radial-gradient(ellipse at center, #ffffff 40%,#dfdfdf 100%);
background-color: #dfdfdf;
}
diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js
index 4c6c78ea91c..9dedaf58a2d 100644
--- a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js
+++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js
@@ -30,7 +30,8 @@ CSS = {
CONTENT: 'editor_atto_content',
CONTENTWRAPPER: 'editor_atto_content_wrap',
TOOLBAR: 'editor_atto_toolbar',
- WRAPPER: 'editor_atto'
+ WRAPPER: 'editor_atto',
+ HIGHLIGHT: 'highlight'
};
/**
@@ -253,6 +254,22 @@ M.editor_atto = M.editor_atto || {
return !element.hasAttribute('disabled');
},
+ /**
+ * Determine if the specified toolbar button/menu is highlighted.
+ * @param string elementid, the element id of this editor.
+ * @param string plugin, the plugin that created the button/menu.
+ * @param string buttonname, optional - used when a plugin has multiple buttons.
+ */
+ is_highlighted : function(elementid, plugin, button) {
+ var buttonpath = plugin;
+ if (button) {
+ buttonpath += '_' + button;
+ }
+ var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button');
+
+ return !element.hasClass(CSS.HIGHLIGHT);
+ },
+
/**
* Enable a single widget in the toolbar.
* @param string elementid, the element id of this editor.
@@ -271,6 +288,42 @@ M.editor_atto = M.editor_atto || {
}
},
+ /**
+ * Highlight a single widget in the toolbar.
+ * @param string elementid, the element id of this editor.
+ * @param string plugin, the name of the plugin that created the widget.
+ * @param string buttonname, optional - used when a plugin has multiple buttons.
+ */
+ add_widget_highlight : function(elementid, plugin, button) {
+ var buttonpath = plugin;
+ if (button) {
+ buttonpath += '_' + button;
+ }
+ var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button');
+
+ if (element) {
+ element.addClass(CSS.HIGHLIGHT);
+ }
+ },
+
+ /**
+ * Unhighlight a single widget in the toolbar.
+ * @param string elementid, the element id of this editor.
+ * @param string plugin, the name of the plugin that created the widget.
+ * @param string buttonname, optional - used when a plugin has multiple buttons.
+ */
+ remove_widget_highlight : function(elementid, plugin, button) {
+ var buttonpath = plugin;
+ if (button) {
+ buttonpath += '_' + button;
+ }
+ var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button');
+
+ if (element) {
+ element.removeClass(CSS.HIGHLIGHT);
+ }
+ },
+
/**
* Enable all buttons and menus in the toolbar.
* @param string elementid, the element id of this editor.
@@ -558,8 +611,9 @@ M.editor_atto = M.editor_atto || {
// Hide the old textarea.
textarea.hide();
- atto.on('keydown', this.save_selection, this, params.elementid);
- atto.on('mouseup', this.save_selection, this, params.elementid);
+
+ this.publish_events();
+ atto.on('atto:selectionchanged', this.save_selection, this, params.elementid);
atto.on('focus', this.restore_selection, this, params.elementid);
// Do not restore selection when focus is from a click event.
atto.on('mousedown', function() { this.focusfromclick = true; }, this);
@@ -607,6 +661,87 @@ M.editor_atto = M.editor_atto || {
}
}
}
+
+ },
+
+ /**
+ * Add code to trigger the a set of custom events on either the toolbar, or the contenteditable node
+ * that can be listened to by plugins (or even this class).
+ * @param string elementid - the id of the textarea we created this editor from.
+ */
+ publish_events : function() {
+ Y.Event.define("atto:selectionchanged", {
+ /**
+ * Catch the keydown/mouseup events, and fire a synthetic event for the change event.
+ * @param {Y.Event} e - The real event that triggers this synthetic one.
+ * @param {Object} params - Object containing the subscription object and the notifier.
+ */
+ changeHandler: function (e, params) {
+ // Add 3 properties to the event.
+ // 1. add the elementid.
+ var elementid = params.sub.node.getAttribute('id');
+ // Strip 'editable' from the end of the id.
+ elementid = elementid.substring(0, elementid.length - 8);
+ e.elementid = elementid;
+
+ // 2. The list of leaf nodes contained in the selection.
+ e.selectedNodes = M.editor_atto.get_selected_nodes(elementid);
+ // 3. The current selection (Range)
+ e.selection = M.editor_atto.get_selection();
+ params.notifier.fire(e);
+ },
+
+ /**
+ * Subscribe to the atto:selectionchanged event.
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ * @param {Y.Event.Notifier} notifier - YUI notifier object.
+ */
+ on: function (node, sub, notifier) {
+ var params = { notifier: notifier, sub: sub };
+ sub.attoKeyDownDetach = node.on('keydown', Y.throttle(this.changeHandler, 100), this, params);
+ sub.attoMouseUpDetach = node.on('mouseup', Y.throttle(this.changeHandler, 100), this, params);
+ sub.attoFocusDetach = node.on('focus', Y.throttle(this.changeHandler, 100), this, params);
+ },
+
+ /**
+ * Detach the atto:selectionchanged event.
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ */
+ detach: function (node, sub) {
+ sub.attoKeyDownDetach.detach();
+ sub.attoMouseUpDetach.detach();
+ sub.attoFocusDetach.detach();
+ },
+
+ /**
+ * Delegate the atto:selectionchanged event.
+ *
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ * @param {Y.Event.Notifier} notifier - YUI notifier object.
+ * @param {String} filter - CSS selector for the filter.
+ */
+ delegate: function(node, sub, notifier, filter) {
+ var params = { notifier: notifier, sub: sub };
+ sub.attoKeyDownDetachDelegate = node.delegate('keydown', Y.throttle(this.changeHandler, 100), filter, this, params);
+ sub.attoMouseUpDetachDelegate = node.delegate('mouseup', Y.throttle(this.changeHandler, 100), filter, this, params);
+ sub.attoFocusDetachDelegate = node.delegate('focus', Y.throttle(this.changeHandler, 100), filter, this, params);
+ },
+
+ /**
+ * Detach a delegated atto:selectionchanged event.
+ *
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ */
+ detachDelegate: function(node, sub) {
+ sub.attoKeyDownDetachDelegate.detach();
+ sub.attoMouseUpDetachDelegate.detach();
+ sub.attoFocusDetachDelegate.detach();
+ }
+ });
},
/**
@@ -825,6 +960,169 @@ M.editor_atto = M.editor_atto || {
return sel.inRange(range);
},
+ /**
+ * Runs a selector on each node in the selection and will only return true if all nodes
+ * in the selection match the filter.
+ *
+ * @param {String} elementid
+ * @param {String} selector
+ * @param {NodeList} selectednodes (Optional) - for performance we can pass this instead of looking it up.
+ * @return {Boolean}
+ */
+ selection_filter_matches : function(elementid, selector, selectednodes) {
+ var result = true;
+
+ if (!selectednodes) {
+ // Find this because it was not passed as a param.
+ selectednodes = M.editor_atto.get_selected_nodes(elementid);
+ }
+ selector = '.' + CSS.CONTENT + ' ' + selector;
+
+ if (selectednodes.size() === 0) {
+ return false;
+ }
+ selectednodes.each(function(node) {
+ if (!node.ancestor(selector, true)) {
+ result = false;
+ }
+ });
+ return result;
+ },
+
+ /**
+ * Returns a list of nodes that are ancestors of the selection nodes,
+ * and match the specified css selector (and are contained within the editable div).
+ *
+ * @param {String} elementid
+ * @param {String} selector
+ * @return Y.NodeList
+ */
+ selection_filter : function(elementid, selector) {
+ var selectednodes = M.editor_atto.get_selected_nodes(elementid);
+ var result = new Y.NodeList();
+ selector = '.' + CSS.CONTENT + ' ' + selector;
+ selectednodes.each(function(node) {
+ node.ancestors(selector, true).each(function(match) {
+ if (result.indexOf(match) === -1) {
+ result.push(match);
+ }
+ });
+ });
+ return result;
+ },
+
+ /**
+ * Get the deepest possible list of nodes in the current selection.
+ * @param {String} elementid
+ * @return Y.NodeList
+ */
+ get_selected_nodes : function(elementid) {
+
+ var editable = M.editor_atto.get_editable_node(elementid);
+ var startnode = M.editor_atto.get_selection_start_container();
+ var endnode = M.editor_atto.get_selection_end_container();
+
+ if (!startnode || !endnode) {
+ return new Y.NodeList();
+ }
+
+ /**
+ * Recursive function to walk the dom tree between 2 nodes and build
+ * a list of leaf nodes.
+ * @param {Y.Node} node - The current node.
+ * @param {Y.Node} endnode - The node to stop at.
+ * @param {Y.Node} boundingnode - A node that will contain the selection - do not result results outside this node.
+ * @param {Integer} skipchildren - When returning from a child to a parent, this is how many children to skip.
+ * @param {Boolean} isstart - Only true for the starting condition. Used in the case when startnode == endnode.
+ * @return {Y.NodeList} The list of leaf nodes found.
+ */
+ var find_leaf_nodes = function(node, endnode, boundingnode, skipchildren, isstart) {
+ var leafnodes = new Y.NodeList();
+ if (endnode === node) {
+ // If there are child nodes and we didn't come from a child node, then skip this end condition.
+ if (!(endnode === node && startnode === node && isstart && node.hasChildNodes())) {
+ // If the end node is a leaf - return it.
+ if (!node.hasChildNodes()) {
+ leafnodes.push(node);
+ }
+ // We reached the end of the selection.
+ return leafnodes;
+ }
+ }
+
+ // Node is not a leaf, look at it's children.
+ if (node.hasChildNodes()) {
+ var children = node.get('childNodes');
+ // Skipchildren is used when returning from a child node, to make the parent look at the next child node.
+ var child = children.item(skipchildren);
+ if (child) {
+ // There was a child node, find all the leaf nodes in it.
+ leafnodes.concat(find_leaf_nodes(child, endnode, boundingnode, 0, false));
+ }
+ } else {
+ // This node has no children - so save it.
+ leafnodes.push(node);
+ }
+ // If we hit the bounding node - this is an end condition.
+ if (node === boundingnode) {
+ return leafnodes;
+ }
+ // We have added all the nodes in this branch, look at the next child of the parent.
+ var parent = node.ancestor();
+ if (parent) {
+ var currentindex = parent.get('childNodes').indexOf(node);
+ leafnodes.concat(find_leaf_nodes(parent, endnode, boundingnode, currentindex + 1, false));
+ }
+ return leafnodes;
+ };
+
+ // Kick off the recursive function.
+ return find_leaf_nodes(startnode, endnode, editable, 0, true);
+ },
+
+ /**
+ * Get the first node that contains the current selection.
+ * @return DOMNode or false
+ */
+ get_selection_start_container : function() {
+ var selection = M.editor_atto.get_selection();
+
+ if (selection.length) {
+ selection = selection.pop();
+ }
+
+ if (selection.startContainer) {
+ return Y.one(selection.startContainer);
+ } else if (selection.parentElement) {
+ var range = selection.duplicate();
+
+ range.collapse(true);
+ return Y.one(range.parentElement());
+ }
+ },
+
+ /**
+ * Get the last node that contains the current selection.
+ * @return DOMNode or false
+ */
+ get_selection_end_container : function() {
+ var selection = M.editor_atto.get_selection();
+
+ if (selection.length) {
+ selection = selection.pop();
+ }
+
+ if (selection.endContainer) {
+ return Y.one(selection.endContainer);
+ } else if (selection.parentElement) {
+ var range = selection.duplicate();
+
+ range.collapse(false);
+ return Y.one(range.parentElement());
+ }
+ return false;
+ },
+
/**
* Get the dom node representing the common anscestor of the selection nodes.
* @return DOMNode or false
@@ -1150,4 +1448,16 @@ Y.Node.addMethod("cleanHTML", cleanHTML);
Y.NodeList.importMethod(Y.Node.prototype, "cleanHTML");
-}, '@VERSION@', {"requires": ["node", "io", "overlay", "escape", "event", "event-simulate", "moodle-core-notification"]});
+}, '@VERSION@', {
+ "requires": [
+ "node",
+ "io",
+ "overlay",
+ "escape",
+ "event",
+ "event-simulate",
+ "event-custom",
+ "yui-throttle",
+ "moodle-core-notification"
+ ]
+});
diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js
index 2b09b2356c0..00602830d96 100644
--- a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js
+++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js
@@ -1,3 +1,3 @@
-YUI.add("moodle-editor_atto-editor",function(e,t){function i(){var e=this.getHTML(),t=[{regex://gi,replace:""},{regex:/<\\?\?xml[^>]*>/gi,replace:""},{regex:/<\/?\w+:[^>]*>/gi,replace:""},{regex:/\s*MSO[-:][^;"']*;?/gi,replace:""},{regex:/]*>( |\s)*<\/span>/gi,replace:""},{regex:/class="Mso[^"]*"/gi,replace:""},{regex:/<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|!\[)[^>]*?>/gi,replace:""},{regex:new RegExp(String.fromCharCode(8220),"gi"),replace:'"'},{regex:new RegExp(String.fromCharCode(8216),"gi"),replace:"'"},{regex:new RegExp(String.fromCharCode(8217),"gi"),replace:"'"},{regex:new RegExp(String.fromCharCode(8211),"gi"),replace:"-"},{regex:new RegExp(String.fromCharCode(8212),"gi"),replace:"--"},{regex:new RegExp(String.fromCharCode(189),"gi"),replace:"1/2"},{regex:new RegExp(String.fromCharCode(188),"gi"),replace:"1/4"},{regex:new RegExp(String.fromCharCode(190),"gi"),replace:"3/4"},{regex:new RegExp(String.fromCharCode(169),"gi"),replace:"(c)"},{regex:new RegExp(String.fromCharCode(174),"gi"),replace:"(r)"},{regex:new RegExp(String.fromCharCode(8230),"gi"),replace:"..."}],n=0,r;for(n=0;n'),l.append(c)),v=M.util.image_url("t/expanded","moodle"),p=e.Node.create('"),c.append(p),h=l.getAttribute("aria-activedescendant"),h||(p.setAttribute("tabindex","0"),l.setAttribute("aria-activedescendant",p.generateID())),M.editor_atto.widgets[d]=d;var m=e.Node.create(''),g=0,y={};for(g=0;g'+y.text+""+"")),M.editor_atto.buttonhandlers[n+"_action_"+g]||(e.one("body").delegate("click",M.editor_atto.buttonclicked_handler,".atto_"+d+"_action_"+g),e.one("body").delegate("key",M.editor_atto.buttonclicked_handler,"32,enter",".atto_"+d+"_action_"+g),M.editor_atto.buttonhandlers[d+"_action_"+g]=y.handler);M.editor_atto.buttonhandlers[d]||(e.one("body").delegate("click",M.editor_atto.showhide_menu_handler,".atto_"+d+"_button"),M.editor_atto.buttonhandlers[d]=!0);var b=new M.core.dialogue({bodyContent:m,visible:!1,width:a+"em",lightbox:!1
-,closeButton:!1,center:!1});M.editor_atto.menus[d+"_"+t]=b,b.align(p,[e.WidgetPositionAlign.TL,e.WidgetPositionAlign.BL]),b.hide(),b.headerNode.hide(),b.render()},add_toolbar_button:function(t,n,r,i,s,o,u){var a=M.editor_atto.get_toolbar_node(t),f=a.one(".atto_group."+i+"_group"),l,c,h;o?c=n+"_"+o:(o="",c=n),u||(u=M.util.get_string("pluginname","atto_"+n)),f||(f=e.Node.create(''),a.append(f)),l=e.Node.create('"),f.append(l),h=a.getAttribute("aria-activedescendant"),h||(l.setAttribute("tabindex","0"),a.setAttribute("aria-activedescendant",l.generateID())),M.editor_atto.buttonhandlers[c]||(e.one("body").delegate("click",M.editor_atto.buttonclicked_handler,".atto_"+c+"_button"),M.editor_atto.buttonhandlers[c]=s),M.editor_atto.widgets[c]=c},is_active:function(t){var n=M.editor_atto.get_selection();n.length&&(n=n.pop());var r=null;n.parentElement?r=e.one(n.parentElement()):r=e.one(n.startContainer);var i=M.editor_atto.get_editable_node(t);return r&&i.contains(r)},focus:function(e){M.editor_atto.get_editable_node(e).focus()},init:function(t){var n=e.Node.create(''),r=e.Node.create(''),i=e.Node.create(''),s=e.Node.create(''),o=M.editor_atto.get_textarea_node(t.elementid),u=e.one('[for="'+t.elementid+'"]');u&&(u.generateID(),r.setAttribute("aria-labelledby",u.get("id")),i.setAttribute("aria-labelledby",u.get("id"))),s.appendChild(r),n.appendChild(i),n.appendChild(s),r.setStyle("minHeight",1.2*o.getAttribute("rows")+"em"),r.append(o.get("value")),r.cleanHTML(),o.get("parentNode").insert(n,o),M.editor_atto.disable_css_styling(),o.hide(),r.on("keydown",this.save_selection,this,t.elementid),r.on("mouseup",this.save_selection,this,t.elementid),r.on("focus",this.restore_selection,this,t.elementid),r.on("mousedown",function(){this.focusfromclick=!0},this),r.on("blur",function(){this.focusfromclick=!1,this.text_updated(t.elementid)},this),e.one(e.config.doc.body).delegate("key",this.keyboard_navigation,"down:37,39","#"+t.elementid+"_toolbar",this,t.elementid),M.editor_atto.filepickeroptions[t.elementid]=t.filepickeroptions;var a,f,l,c;for(a=0;a=r.size()&&(o=0)),i=r.item(o),i.setAttribute("tabindex","0"),i.focus(),u.setAttribute("aria-activedescendant",i.generateID())},can_show_filepicker:function(e,t){var n=M.editor_atto.filepickeroptions[e];return typeof n[t]!="undefined"},show_filepicker:function(t,n,r){e.use("core_filepicker",function(e){var i=M.editor_atto.filepickeroptions[t][n];i.formcallback=r,M.core_filepicker.show(e,i)})},get_selection_from_node:function(e){var t;return window.getSelection?(t=document.createRange(),t.setStartBefore(e.getDOMNode()),t.setEndAfter(e.getDOMNode()),[t]):document.selection?(t=document.body.createTextRange(),t.moveToElementText(e.getDOMNode()),t):!1},save_selection:function(e,t){if(this.is_active(t)){var n=this.get_selection();n.length>0&&(this.selections[t]=n)}},restore_selection:function(e,t){e.preventDefault(),this.focusfromclick||typeof this.selections[t]!="undefined"&&this.set_selection(this.selections[t]),this.focusfromclick=!1},get_selection:function(){if(window.getSelection){var e=window.getSelection(),t=[],n=0;for(n=0;n0&&e[0].cloneContents)return e[0].cloneContents()},set_selection:function(e){var t,n;if(window.getSelection){t=window.getSelection(),t.removeAllRanges();for(n=0;n
"),s.get("childNodes").each(function(e){a.append(e.remove())}),s.append(a),u=a),n&&n!==""&&(l=e.Node.create("<"+n+">"+n+">"),l.setAttrs(u.getAttrs()),u.get("childNodes").each(function(e){e.remove(),l.append(e)}),u.replace(l),u=l),r&&u.setAttrs(r);var c=M.editor_atto.get_selection_from_node(u);return M.editor_atto.set_selection(c),u},disable_css_styling:function(){try{document.execCommand("styleWithCSS",0,!1)}catch(e){try{document.execCommand("useCSS",0,!0)}catch(t){try{document.execCommand("styleWithCSS",!1,!1)}catch(n){}}}},enable_css_styling:function(){try{document.execCommand("styleWithCSS",0,!0)}catch(e){try{document.execCommand("useCSS",0,!1)}catch(t){try{document.execCommand("styleWithCSS",!1,!0)}catch(n){}}}}};var n="Controlmenu",r;r=function(e){e.draggable=!1,e.center=!1,e.width="auto",e.lightbox=!1,e.footerContent="",e.hideOn=[{eventName:"clickoutside"}],r.superclass.constructor.apply(this,[e])},e.extend(r,M.core.dialogue,{initializer:function(t){var n,i,s;r.superclass.initializer.call(this,t),s=this.get("boundingBox"),s.addClass("editor_atto_controlmenu"),n=this.bodyNode,i=e.Node.create(""),i.addClass("accesshide"),i.setHTML(this.get("headerText")),n.prepend(i)}},{NAME:n,ATTRS:{headerText:{value:""}}}),M.editor_atto=M.editor_atto||{},M.editor_atto.controlmenu=r,e.Node.addMethod("cleanHTML",i),e.NodeList.importMethod(e.Node.prototype,"cleanHTML")},"@VERSION@",{requires:["node","io","overlay","escape","event","event-simulate","moodle-core-notification"]});
+YUI.add("moodle-editor_atto-editor",function(e,t){function i(){var e=this.getHTML(),t=[{regex://gi,replace:""},{regex:/<\\?\?xml[^>]*>/gi,replace:""},{regex:/<\/?\w+:[^>]*>/gi,replace:""},{regex:/\s*MSO[-:][^;"']*;?/gi,replace:""},{regex:/]*>( |\s)*<\/span>/gi,replace:""},{regex:/class="Mso[^"]*"/gi,replace:""},{regex:/<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|!\[)[^>]*?>/gi,replace:""},{regex:new RegExp(String.fromCharCode(8220),"gi"),replace:'"'},{regex:new RegExp(String.fromCharCode(8216),"gi"),replace:"'"},{regex:new RegExp(String.fromCharCode(8217),"gi"),replace:"'"},{regex:new RegExp(String.fromCharCode(8211),"gi"),replace:"-"},{regex:new RegExp(String.fromCharCode(8212),"gi"),replace:"--"},{regex:new RegExp(String.fromCharCode(189),"gi"),replace:"1/2"},{regex:new RegExp(String.fromCharCode(188),"gi"),replace:"1/4"},{regex:new RegExp(String.fromCharCode(190),"gi"),replace:"3/4"},{regex:new RegExp(String.fromCharCode(169),"gi"),replace:"(c)"},{regex:new RegExp(String.fromCharCode(174),"gi"),replace:"(r)"},{regex:new RegExp(String.fromCharCode(8230),"gi"),replace:"..."}],n=0,r;for(n=0;n'),l.append(c)),v=M.util.image_url("t/expanded","moodle"),p=e.Node.create('"),c.append(p),h=l.getAttribute("aria-activedescendant"),h||(p.setAttribute("tabindex","0"),l.setAttribute("aria-activedescendant",p.generateID())),M.editor_atto.widgets[d]=d;var m=e.Node.create(''),g=0,y={};for(g=0;g'+y.text+""+"")),M.editor_atto.buttonhandlers[n+"_action_"+
+g]||(e.one("body").delegate("click",M.editor_atto.buttonclicked_handler,".atto_"+d+"_action_"+g),e.one("body").delegate("key",M.editor_atto.buttonclicked_handler,"32,enter",".atto_"+d+"_action_"+g),M.editor_atto.buttonhandlers[d+"_action_"+g]=y.handler);M.editor_atto.buttonhandlers[d]||(e.one("body").delegate("click",M.editor_atto.showhide_menu_handler,".atto_"+d+"_button"),M.editor_atto.buttonhandlers[d]=!0);var b=new M.core.dialogue({bodyContent:m,visible:!1,width:a+"em",lightbox:!1,closeButton:!1,center:!1});M.editor_atto.menus[d+"_"+t]=b,b.align(p,[e.WidgetPositionAlign.TL,e.WidgetPositionAlign.BL]),b.hide(),b.headerNode.hide(),b.render()},add_toolbar_button:function(t,n,r,i,s,o,u){var a=M.editor_atto.get_toolbar_node(t),f=a.one(".atto_group."+i+"_group"),l,c,h;o?c=n+"_"+o:(o="",c=n),u||(u=M.util.get_string("pluginname","atto_"+n)),f||(f=e.Node.create(''),a.append(f)),l=e.Node.create('"),f.append(l),h=a.getAttribute("aria-activedescendant"),h||(l.setAttribute("tabindex","0"),a.setAttribute("aria-activedescendant",l.generateID())),M.editor_atto.buttonhandlers[c]||(e.one("body").delegate("click",M.editor_atto.buttonclicked_handler,".atto_"+c+"_button"),M.editor_atto.buttonhandlers[c]=s),M.editor_atto.widgets[c]=c},is_active:function(t){var n=M.editor_atto.get_selection();n.length&&(n=n.pop());var r=null;n.parentElement?r=e.one(n.parentElement()):r=e.one(n.startContainer);var i=M.editor_atto.get_editable_node(t);return r&&i.contains(r)},focus:function(e){M.editor_atto.get_editable_node(e).focus()},init:function(t){var n=e.Node.create(''),r=e.Node.create(''),i=e.Node.create(''),s=e.Node.create(''),o=M.editor_atto.get_textarea_node(t.elementid),u=e.one('[for="'+t.elementid+'"]');u&&(u.generateID(),r.setAttribute("aria-labelledby",u.get("id")),i.setAttribute("aria-labelledby",u.get("id"))),s.appendChild(r),n.appendChild(i),n.appendChild(s),r.setStyle("minHeight",1.2*o.getAttribute("rows")+"em"),r.append(o.get("value")),r.cleanHTML(),o.get("parentNode").insert(n,o),M.editor_atto.disable_css_styling(),o.hide(),this.publish_events(),r.on("atto:selectionchanged",this.save_selection,this,t.elementid),r.on("focus",this.restore_selection,this,t.elementid),r.on("mousedown",function(){this.focusfromclick=!0},this),r.on("blur",function(){this.focusfromclick=!1,this.text_updated(t.elementid)},this),e.one(e.config.doc.body).delegate("key",this.keyboard_navigation,"down:37,39","#"+t.elementid+"_toolbar",this,t.elementid),M.editor_atto.filepickeroptions[t.elementid]=t.filepickeroptions;var a,f,l,c;for(a=0;a=r.size()&&(o=0)),i=r.item(o),i.setAttribute("tabindex","0"),i.focus(),u.setAttribute("aria-activedescendant",i.generateID())},can_show_filepicker:function(e,t){var n=M.editor_atto.filepickeroptions[e];return typeof n[t]!="undefined"},show_filepicker:function(t,n,r){e.use("core_filepicker",function(
+e){var i=M.editor_atto.filepickeroptions[t][n];i.formcallback=r,M.core_filepicker.show(e,i)})},get_selection_from_node:function(e){var t;return window.getSelection?(t=document.createRange(),t.setStartBefore(e.getDOMNode()),t.setEndAfter(e.getDOMNode()),[t]):document.selection?(t=document.body.createTextRange(),t.moveToElementText(e.getDOMNode()),t):!1},save_selection:function(e,t){if(this.is_active(t)){var n=this.get_selection();n.length>0&&(this.selections[t]=n)}},restore_selection:function(e,t){e.preventDefault(),this.focusfromclick||typeof this.selections[t]!="undefined"&&this.set_selection(this.selections[t]),this.focusfromclick=!1},get_selection:function(){if(window.getSelection){var e=window.getSelection(),t=[],n=0;for(n=0;n0&&e[0].cloneContents)return e[0].cloneContents()},set_selection:function(e){var t,n;if(window.getSelection){t=window.getSelection(),t.removeAllRanges();for(n=0;n"),s.get("childNodes").each(function(e){a.append(e.remove())}),s.append(a),u=a),n&&n!==""&&(l=e.Node.create("<"+n+">"+n+">"),l.setAttrs(u.getAttrs()),u.get("childNodes").each(function(e){e.remove(),l.append(e)}),u.replace(l),u=l),r&&u.setAttrs(r);var c=M.editor_atto.get_selection_from_node(u);return M.editor_atto.set_selection(c),u},disable_css_styling:function(){try{document.execCommand("styleWithCSS",0,!1)}catch(e){try{document.execCommand("useCSS",0,!0)}catch(t){try{document.execCommand("styleWithCSS",!1,!1)}catch(n){}}}},enable_css_styling:function(){try{document.execCommand("styleWithCSS",0,!0)}catch(e){try{document.execCommand("useCSS",0,!1)}catch(t){try{document.execCommand("styleWithCSS",!1,!0)}catch(n){}}}}};var n="Controlmenu",r;r=function(e){e.draggable=!1,e.center=!1,e.width="auto",e.lightbox=!1,e.footerContent="",e.hideOn=[{eventName:"clickoutside"}],r.superclass.constructor.apply(this,[e])},e.extend(r,M.core.dialogue,{initializer:function(t){var n,i,s;r.superclass.initializer.call(this,t),s=this.get("boundingBox"),s.addClass("editor_atto_controlmenu"),n=this.bodyNode,i=e.Node.create(""),i.addClass("accesshide"),i.setHTML(this.get("headerText")),n.prepend(i)}},{NAME:n,ATTRS:{headerText:{value:""}}}),M.editor_atto=M.editor_atto||{},M.editor_atto.controlmenu=r,e.Node.addMethod("cleanHTML",i),e.NodeList.importMethod(e.Node.prototype,"cleanHTML")},"@VERSION@",{requires:["node","io","overlay","escape","event","event-simulate","event-custom","yui-throttle","moodle-core-notification"]});
diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js
index 4c6c78ea91c..9dedaf58a2d 100644
--- a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js
+++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js
@@ -30,7 +30,8 @@ CSS = {
CONTENT: 'editor_atto_content',
CONTENTWRAPPER: 'editor_atto_content_wrap',
TOOLBAR: 'editor_atto_toolbar',
- WRAPPER: 'editor_atto'
+ WRAPPER: 'editor_atto',
+ HIGHLIGHT: 'highlight'
};
/**
@@ -253,6 +254,22 @@ M.editor_atto = M.editor_atto || {
return !element.hasAttribute('disabled');
},
+ /**
+ * Determine if the specified toolbar button/menu is highlighted.
+ * @param string elementid, the element id of this editor.
+ * @param string plugin, the plugin that created the button/menu.
+ * @param string buttonname, optional - used when a plugin has multiple buttons.
+ */
+ is_highlighted : function(elementid, plugin, button) {
+ var buttonpath = plugin;
+ if (button) {
+ buttonpath += '_' + button;
+ }
+ var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button');
+
+ return !element.hasClass(CSS.HIGHLIGHT);
+ },
+
/**
* Enable a single widget in the toolbar.
* @param string elementid, the element id of this editor.
@@ -271,6 +288,42 @@ M.editor_atto = M.editor_atto || {
}
},
+ /**
+ * Highlight a single widget in the toolbar.
+ * @param string elementid, the element id of this editor.
+ * @param string plugin, the name of the plugin that created the widget.
+ * @param string buttonname, optional - used when a plugin has multiple buttons.
+ */
+ add_widget_highlight : function(elementid, plugin, button) {
+ var buttonpath = plugin;
+ if (button) {
+ buttonpath += '_' + button;
+ }
+ var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button');
+
+ if (element) {
+ element.addClass(CSS.HIGHLIGHT);
+ }
+ },
+
+ /**
+ * Unhighlight a single widget in the toolbar.
+ * @param string elementid, the element id of this editor.
+ * @param string plugin, the name of the plugin that created the widget.
+ * @param string buttonname, optional - used when a plugin has multiple buttons.
+ */
+ remove_widget_highlight : function(elementid, plugin, button) {
+ var buttonpath = plugin;
+ if (button) {
+ buttonpath += '_' + button;
+ }
+ var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button');
+
+ if (element) {
+ element.removeClass(CSS.HIGHLIGHT);
+ }
+ },
+
/**
* Enable all buttons and menus in the toolbar.
* @param string elementid, the element id of this editor.
@@ -558,8 +611,9 @@ M.editor_atto = M.editor_atto || {
// Hide the old textarea.
textarea.hide();
- atto.on('keydown', this.save_selection, this, params.elementid);
- atto.on('mouseup', this.save_selection, this, params.elementid);
+
+ this.publish_events();
+ atto.on('atto:selectionchanged', this.save_selection, this, params.elementid);
atto.on('focus', this.restore_selection, this, params.elementid);
// Do not restore selection when focus is from a click event.
atto.on('mousedown', function() { this.focusfromclick = true; }, this);
@@ -607,6 +661,87 @@ M.editor_atto = M.editor_atto || {
}
}
}
+
+ },
+
+ /**
+ * Add code to trigger the a set of custom events on either the toolbar, or the contenteditable node
+ * that can be listened to by plugins (or even this class).
+ * @param string elementid - the id of the textarea we created this editor from.
+ */
+ publish_events : function() {
+ Y.Event.define("atto:selectionchanged", {
+ /**
+ * Catch the keydown/mouseup events, and fire a synthetic event for the change event.
+ * @param {Y.Event} e - The real event that triggers this synthetic one.
+ * @param {Object} params - Object containing the subscription object and the notifier.
+ */
+ changeHandler: function (e, params) {
+ // Add 3 properties to the event.
+ // 1. add the elementid.
+ var elementid = params.sub.node.getAttribute('id');
+ // Strip 'editable' from the end of the id.
+ elementid = elementid.substring(0, elementid.length - 8);
+ e.elementid = elementid;
+
+ // 2. The list of leaf nodes contained in the selection.
+ e.selectedNodes = M.editor_atto.get_selected_nodes(elementid);
+ // 3. The current selection (Range)
+ e.selection = M.editor_atto.get_selection();
+ params.notifier.fire(e);
+ },
+
+ /**
+ * Subscribe to the atto:selectionchanged event.
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ * @param {Y.Event.Notifier} notifier - YUI notifier object.
+ */
+ on: function (node, sub, notifier) {
+ var params = { notifier: notifier, sub: sub };
+ sub.attoKeyDownDetach = node.on('keydown', Y.throttle(this.changeHandler, 100), this, params);
+ sub.attoMouseUpDetach = node.on('mouseup', Y.throttle(this.changeHandler, 100), this, params);
+ sub.attoFocusDetach = node.on('focus', Y.throttle(this.changeHandler, 100), this, params);
+ },
+
+ /**
+ * Detach the atto:selectionchanged event.
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ */
+ detach: function (node, sub) {
+ sub.attoKeyDownDetach.detach();
+ sub.attoMouseUpDetach.detach();
+ sub.attoFocusDetach.detach();
+ },
+
+ /**
+ * Delegate the atto:selectionchanged event.
+ *
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ * @param {Y.Event.Notifier} notifier - YUI notifier object.
+ * @param {String} filter - CSS selector for the filter.
+ */
+ delegate: function(node, sub, notifier, filter) {
+ var params = { notifier: notifier, sub: sub };
+ sub.attoKeyDownDetachDelegate = node.delegate('keydown', Y.throttle(this.changeHandler, 100), filter, this, params);
+ sub.attoMouseUpDetachDelegate = node.delegate('mouseup', Y.throttle(this.changeHandler, 100), filter, this, params);
+ sub.attoFocusDetachDelegate = node.delegate('focus', Y.throttle(this.changeHandler, 100), filter, this, params);
+ },
+
+ /**
+ * Detach a delegated atto:selectionchanged event.
+ *
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ */
+ detachDelegate: function(node, sub) {
+ sub.attoKeyDownDetachDelegate.detach();
+ sub.attoMouseUpDetachDelegate.detach();
+ sub.attoFocusDetachDelegate.detach();
+ }
+ });
},
/**
@@ -825,6 +960,169 @@ M.editor_atto = M.editor_atto || {
return sel.inRange(range);
},
+ /**
+ * Runs a selector on each node in the selection and will only return true if all nodes
+ * in the selection match the filter.
+ *
+ * @param {String} elementid
+ * @param {String} selector
+ * @param {NodeList} selectednodes (Optional) - for performance we can pass this instead of looking it up.
+ * @return {Boolean}
+ */
+ selection_filter_matches : function(elementid, selector, selectednodes) {
+ var result = true;
+
+ if (!selectednodes) {
+ // Find this because it was not passed as a param.
+ selectednodes = M.editor_atto.get_selected_nodes(elementid);
+ }
+ selector = '.' + CSS.CONTENT + ' ' + selector;
+
+ if (selectednodes.size() === 0) {
+ return false;
+ }
+ selectednodes.each(function(node) {
+ if (!node.ancestor(selector, true)) {
+ result = false;
+ }
+ });
+ return result;
+ },
+
+ /**
+ * Returns a list of nodes that are ancestors of the selection nodes,
+ * and match the specified css selector (and are contained within the editable div).
+ *
+ * @param {String} elementid
+ * @param {String} selector
+ * @return Y.NodeList
+ */
+ selection_filter : function(elementid, selector) {
+ var selectednodes = M.editor_atto.get_selected_nodes(elementid);
+ var result = new Y.NodeList();
+ selector = '.' + CSS.CONTENT + ' ' + selector;
+ selectednodes.each(function(node) {
+ node.ancestors(selector, true).each(function(match) {
+ if (result.indexOf(match) === -1) {
+ result.push(match);
+ }
+ });
+ });
+ return result;
+ },
+
+ /**
+ * Get the deepest possible list of nodes in the current selection.
+ * @param {String} elementid
+ * @return Y.NodeList
+ */
+ get_selected_nodes : function(elementid) {
+
+ var editable = M.editor_atto.get_editable_node(elementid);
+ var startnode = M.editor_atto.get_selection_start_container();
+ var endnode = M.editor_atto.get_selection_end_container();
+
+ if (!startnode || !endnode) {
+ return new Y.NodeList();
+ }
+
+ /**
+ * Recursive function to walk the dom tree between 2 nodes and build
+ * a list of leaf nodes.
+ * @param {Y.Node} node - The current node.
+ * @param {Y.Node} endnode - The node to stop at.
+ * @param {Y.Node} boundingnode - A node that will contain the selection - do not result results outside this node.
+ * @param {Integer} skipchildren - When returning from a child to a parent, this is how many children to skip.
+ * @param {Boolean} isstart - Only true for the starting condition. Used in the case when startnode == endnode.
+ * @return {Y.NodeList} The list of leaf nodes found.
+ */
+ var find_leaf_nodes = function(node, endnode, boundingnode, skipchildren, isstart) {
+ var leafnodes = new Y.NodeList();
+ if (endnode === node) {
+ // If there are child nodes and we didn't come from a child node, then skip this end condition.
+ if (!(endnode === node && startnode === node && isstart && node.hasChildNodes())) {
+ // If the end node is a leaf - return it.
+ if (!node.hasChildNodes()) {
+ leafnodes.push(node);
+ }
+ // We reached the end of the selection.
+ return leafnodes;
+ }
+ }
+
+ // Node is not a leaf, look at it's children.
+ if (node.hasChildNodes()) {
+ var children = node.get('childNodes');
+ // Skipchildren is used when returning from a child node, to make the parent look at the next child node.
+ var child = children.item(skipchildren);
+ if (child) {
+ // There was a child node, find all the leaf nodes in it.
+ leafnodes.concat(find_leaf_nodes(child, endnode, boundingnode, 0, false));
+ }
+ } else {
+ // This node has no children - so save it.
+ leafnodes.push(node);
+ }
+ // If we hit the bounding node - this is an end condition.
+ if (node === boundingnode) {
+ return leafnodes;
+ }
+ // We have added all the nodes in this branch, look at the next child of the parent.
+ var parent = node.ancestor();
+ if (parent) {
+ var currentindex = parent.get('childNodes').indexOf(node);
+ leafnodes.concat(find_leaf_nodes(parent, endnode, boundingnode, currentindex + 1, false));
+ }
+ return leafnodes;
+ };
+
+ // Kick off the recursive function.
+ return find_leaf_nodes(startnode, endnode, editable, 0, true);
+ },
+
+ /**
+ * Get the first node that contains the current selection.
+ * @return DOMNode or false
+ */
+ get_selection_start_container : function() {
+ var selection = M.editor_atto.get_selection();
+
+ if (selection.length) {
+ selection = selection.pop();
+ }
+
+ if (selection.startContainer) {
+ return Y.one(selection.startContainer);
+ } else if (selection.parentElement) {
+ var range = selection.duplicate();
+
+ range.collapse(true);
+ return Y.one(range.parentElement());
+ }
+ },
+
+ /**
+ * Get the last node that contains the current selection.
+ * @return DOMNode or false
+ */
+ get_selection_end_container : function() {
+ var selection = M.editor_atto.get_selection();
+
+ if (selection.length) {
+ selection = selection.pop();
+ }
+
+ if (selection.endContainer) {
+ return Y.one(selection.endContainer);
+ } else if (selection.parentElement) {
+ var range = selection.duplicate();
+
+ range.collapse(false);
+ return Y.one(range.parentElement());
+ }
+ return false;
+ },
+
/**
* Get the dom node representing the common anscestor of the selection nodes.
* @return DOMNode or false
@@ -1150,4 +1448,16 @@ Y.Node.addMethod("cleanHTML", cleanHTML);
Y.NodeList.importMethod(Y.Node.prototype, "cleanHTML");
-}, '@VERSION@', {"requires": ["node", "io", "overlay", "escape", "event", "event-simulate", "moodle-core-notification"]});
+}, '@VERSION@', {
+ "requires": [
+ "node",
+ "io",
+ "overlay",
+ "escape",
+ "event",
+ "event-simulate",
+ "event-custom",
+ "yui-throttle",
+ "moodle-core-notification"
+ ]
+});
diff --git a/lib/editor/atto/yui/src/editor/js/editor.js b/lib/editor/atto/yui/src/editor/js/editor.js
index 2bfc2261e4e..359468b5906 100755
--- a/lib/editor/atto/yui/src/editor/js/editor.js
+++ b/lib/editor/atto/yui/src/editor/js/editor.js
@@ -28,7 +28,8 @@ CSS = {
CONTENT: 'editor_atto_content',
CONTENTWRAPPER: 'editor_atto_content_wrap',
TOOLBAR: 'editor_atto_toolbar',
- WRAPPER: 'editor_atto'
+ WRAPPER: 'editor_atto',
+ HIGHLIGHT: 'highlight'
};
/**
@@ -251,6 +252,22 @@ M.editor_atto = M.editor_atto || {
return !element.hasAttribute('disabled');
},
+ /**
+ * Determine if the specified toolbar button/menu is highlighted.
+ * @param string elementid, the element id of this editor.
+ * @param string plugin, the plugin that created the button/menu.
+ * @param string buttonname, optional - used when a plugin has multiple buttons.
+ */
+ is_highlighted : function(elementid, plugin, button) {
+ var buttonpath = plugin;
+ if (button) {
+ buttonpath += '_' + button;
+ }
+ var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button');
+
+ return !element.hasClass(CSS.HIGHLIGHT);
+ },
+
/**
* Enable a single widget in the toolbar.
* @param string elementid, the element id of this editor.
@@ -269,6 +286,42 @@ M.editor_atto = M.editor_atto || {
}
},
+ /**
+ * Highlight a single widget in the toolbar.
+ * @param string elementid, the element id of this editor.
+ * @param string plugin, the name of the plugin that created the widget.
+ * @param string buttonname, optional - used when a plugin has multiple buttons.
+ */
+ add_widget_highlight : function(elementid, plugin, button) {
+ var buttonpath = plugin;
+ if (button) {
+ buttonpath += '_' + button;
+ }
+ var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button');
+
+ if (element) {
+ element.addClass(CSS.HIGHLIGHT);
+ }
+ },
+
+ /**
+ * Unhighlight a single widget in the toolbar.
+ * @param string elementid, the element id of this editor.
+ * @param string plugin, the name of the plugin that created the widget.
+ * @param string buttonname, optional - used when a plugin has multiple buttons.
+ */
+ remove_widget_highlight : function(elementid, plugin, button) {
+ var buttonpath = plugin;
+ if (button) {
+ buttonpath += '_' + button;
+ }
+ var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button');
+
+ if (element) {
+ element.removeClass(CSS.HIGHLIGHT);
+ }
+ },
+
/**
* Enable all buttons and menus in the toolbar.
* @param string elementid, the element id of this editor.
@@ -556,8 +609,9 @@ M.editor_atto = M.editor_atto || {
// Hide the old textarea.
textarea.hide();
- atto.on('keydown', this.save_selection, this, params.elementid);
- atto.on('mouseup', this.save_selection, this, params.elementid);
+
+ this.publish_events();
+ atto.on('atto:selectionchanged', this.save_selection, this, params.elementid);
atto.on('focus', this.restore_selection, this, params.elementid);
// Do not restore selection when focus is from a click event.
atto.on('mousedown', function() { this.focusfromclick = true; }, this);
@@ -605,6 +659,87 @@ M.editor_atto = M.editor_atto || {
}
}
}
+
+ },
+
+ /**
+ * Add code to trigger the a set of custom events on either the toolbar, or the contenteditable node
+ * that can be listened to by plugins (or even this class).
+ * @param string elementid - the id of the textarea we created this editor from.
+ */
+ publish_events : function() {
+ Y.Event.define("atto:selectionchanged", {
+ /**
+ * Catch the keydown/mouseup events, and fire a synthetic event for the change event.
+ * @param {Y.Event} e - The real event that triggers this synthetic one.
+ * @param {Object} params - Object containing the subscription object and the notifier.
+ */
+ changeHandler: function (e, params) {
+ // Add 3 properties to the event.
+ // 1. add the elementid.
+ var elementid = params.sub.node.getAttribute('id');
+ // Strip 'editable' from the end of the id.
+ elementid = elementid.substring(0, elementid.length - 8);
+ e.elementid = elementid;
+
+ // 2. The list of leaf nodes contained in the selection.
+ e.selectedNodes = M.editor_atto.get_selected_nodes(elementid);
+ // 3. The current selection (Range)
+ e.selection = M.editor_atto.get_selection();
+ params.notifier.fire(e);
+ },
+
+ /**
+ * Subscribe to the atto:selectionchanged event.
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ * @param {Y.Event.Notifier} notifier - YUI notifier object.
+ */
+ on: function (node, sub, notifier) {
+ var params = { notifier: notifier, sub: sub };
+ sub.attoKeyDownDetach = node.on('keydown', Y.throttle(this.changeHandler, 100), this, params);
+ sub.attoMouseUpDetach = node.on('mouseup', Y.throttle(this.changeHandler, 100), this, params);
+ sub.attoFocusDetach = node.on('focus', Y.throttle(this.changeHandler, 100), this, params);
+ },
+
+ /**
+ * Detach the atto:selectionchanged event.
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ */
+ detach: function (node, sub) {
+ sub.attoKeyDownDetach.detach();
+ sub.attoMouseUpDetach.detach();
+ sub.attoFocusDetach.detach();
+ },
+
+ /**
+ * Delegate the atto:selectionchanged event.
+ *
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ * @param {Y.Event.Notifier} notifier - YUI notifier object.
+ * @param {String} filter - CSS selector for the filter.
+ */
+ delegate: function(node, sub, notifier, filter) {
+ var params = { notifier: notifier, sub: sub };
+ sub.attoKeyDownDetachDelegate = node.delegate('keydown', Y.throttle(this.changeHandler, 100), filter, this, params);
+ sub.attoMouseUpDetachDelegate = node.delegate('mouseup', Y.throttle(this.changeHandler, 100), filter, this, params);
+ sub.attoFocusDetachDelegate = node.delegate('focus', Y.throttle(this.changeHandler, 100), filter, this, params);
+ },
+
+ /**
+ * Detach a delegated atto:selectionchanged event.
+ *
+ * @param {Y.Node} node - The node for the subscription - must be the contenteditable node.
+ * @param {Y.Subscription} sub - YUI Subscription object.
+ */
+ detachDelegate: function(node, sub) {
+ sub.attoKeyDownDetachDelegate.detach();
+ sub.attoMouseUpDetachDelegate.detach();
+ sub.attoFocusDetachDelegate.detach();
+ }
+ });
},
/**
@@ -823,6 +958,169 @@ M.editor_atto = M.editor_atto || {
return sel.inRange(range);
},
+ /**
+ * Runs a selector on each node in the selection and will only return true if all nodes
+ * in the selection match the filter.
+ *
+ * @param {String} elementid
+ * @param {String} selector
+ * @param {NodeList} selectednodes (Optional) - for performance we can pass this instead of looking it up.
+ * @return {Boolean}
+ */
+ selection_filter_matches : function(elementid, selector, selectednodes) {
+ var result = true;
+
+ if (!selectednodes) {
+ // Find this because it was not passed as a param.
+ selectednodes = M.editor_atto.get_selected_nodes(elementid);
+ }
+ selector = '.' + CSS.CONTENT + ' ' + selector;
+
+ if (selectednodes.size() === 0) {
+ return false;
+ }
+ selectednodes.each(function(node) {
+ if (!node.ancestor(selector, true)) {
+ result = false;
+ }
+ });
+ return result;
+ },
+
+ /**
+ * Returns a list of nodes that are ancestors of the selection nodes,
+ * and match the specified css selector (and are contained within the editable div).
+ *
+ * @param {String} elementid
+ * @param {String} selector
+ * @return Y.NodeList
+ */
+ selection_filter : function(elementid, selector) {
+ var selectednodes = M.editor_atto.get_selected_nodes(elementid);
+ var result = new Y.NodeList();
+ selector = '.' + CSS.CONTENT + ' ' + selector;
+ selectednodes.each(function(node) {
+ node.ancestors(selector, true).each(function(match) {
+ if (result.indexOf(match) === -1) {
+ result.push(match);
+ }
+ });
+ });
+ return result;
+ },
+
+ /**
+ * Get the deepest possible list of nodes in the current selection.
+ * @param {String} elementid
+ * @return Y.NodeList
+ */
+ get_selected_nodes : function(elementid) {
+
+ var editable = M.editor_atto.get_editable_node(elementid);
+ var startnode = M.editor_atto.get_selection_start_container();
+ var endnode = M.editor_atto.get_selection_end_container();
+
+ if (!startnode || !endnode) {
+ return new Y.NodeList();
+ }
+
+ /**
+ * Recursive function to walk the dom tree between 2 nodes and build
+ * a list of leaf nodes.
+ * @param {Y.Node} node - The current node.
+ * @param {Y.Node} endnode - The node to stop at.
+ * @param {Y.Node} boundingnode - A node that will contain the selection - do not result results outside this node.
+ * @param {Integer} skipchildren - When returning from a child to a parent, this is how many children to skip.
+ * @param {Boolean} isstart - Only true for the starting condition. Used in the case when startnode == endnode.
+ * @return {Y.NodeList} The list of leaf nodes found.
+ */
+ var find_leaf_nodes = function(node, endnode, boundingnode, skipchildren, isstart) {
+ var leafnodes = new Y.NodeList();
+ if (endnode === node) {
+ // If there are child nodes and we didn't come from a child node, then skip this end condition.
+ if (!(endnode === node && startnode === node && isstart && node.hasChildNodes())) {
+ // If the end node is a leaf - return it.
+ if (!node.hasChildNodes()) {
+ leafnodes.push(node);
+ }
+ // We reached the end of the selection.
+ return leafnodes;
+ }
+ }
+
+ // Node is not a leaf, look at it's children.
+ if (node.hasChildNodes()) {
+ var children = node.get('childNodes');
+ // Skipchildren is used when returning from a child node, to make the parent look at the next child node.
+ var child = children.item(skipchildren);
+ if (child) {
+ // There was a child node, find all the leaf nodes in it.
+ leafnodes.concat(find_leaf_nodes(child, endnode, boundingnode, 0, false));
+ }
+ } else {
+ // This node has no children - so save it.
+ leafnodes.push(node);
+ }
+ // If we hit the bounding node - this is an end condition.
+ if (node === boundingnode) {
+ return leafnodes;
+ }
+ // We have added all the nodes in this branch, look at the next child of the parent.
+ var parent = node.ancestor();
+ if (parent) {
+ var currentindex = parent.get('childNodes').indexOf(node);
+ leafnodes.concat(find_leaf_nodes(parent, endnode, boundingnode, currentindex + 1, false));
+ }
+ return leafnodes;
+ };
+
+ // Kick off the recursive function.
+ return find_leaf_nodes(startnode, endnode, editable, 0, true);
+ },
+
+ /**
+ * Get the first node that contains the current selection.
+ * @return DOMNode or false
+ */
+ get_selection_start_container : function() {
+ var selection = M.editor_atto.get_selection();
+
+ if (selection.length) {
+ selection = selection.pop();
+ }
+
+ if (selection.startContainer) {
+ return Y.one(selection.startContainer);
+ } else if (selection.parentElement) {
+ var range = selection.duplicate();
+
+ range.collapse(true);
+ return Y.one(range.parentElement());
+ }
+ },
+
+ /**
+ * Get the last node that contains the current selection.
+ * @return DOMNode or false
+ */
+ get_selection_end_container : function() {
+ var selection = M.editor_atto.get_selection();
+
+ if (selection.length) {
+ selection = selection.pop();
+ }
+
+ if (selection.endContainer) {
+ return Y.one(selection.endContainer);
+ } else if (selection.parentElement) {
+ var range = selection.duplicate();
+
+ range.collapse(false);
+ return Y.one(range.parentElement());
+ }
+ return false;
+ },
+
/**
* Get the dom node representing the common anscestor of the selection nodes.
* @return DOMNode or false
diff --git a/lib/editor/atto/yui/src/editor/meta/editor.json b/lib/editor/atto/yui/src/editor/meta/editor.json
index 1cb269517d2..7f887402add 100644
--- a/lib/editor/atto/yui/src/editor/meta/editor.json
+++ b/lib/editor/atto/yui/src/editor/meta/editor.json
@@ -7,6 +7,8 @@
"escape",
"event",
"event-simulate",
+ "event-custom",
+ "yui-throttle",
"moodle-core-notification"
]
}