"),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}};var n="Controlmenu",r;r=function(e){e.draggable=!1,e.center=!1,e.width="auto",e.lightbox=!1,e.footerContent="",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),n.on("clickoutside",function(e){this.get("visible")&&(e.target.ancestor(".atto_control")||(e.preventDefault(),this.hide()))},this)}},{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'),a.append(f)),h=M.util.image_url("t/expanded","moodle"),c=e.Node.create('"),f.append(c),l=a.getAttribute("aria-activedescendant"),l||(c.setAttribute("tabindex","0"),a.setAttribute("aria-activedescendant",c.generateID())),M.editor_atto.widgets[n]=n;var p=e.Node.create(''),d=0,v={};for(d=0;d'+v.text+""+"")),M.editor_atto.buttonhandlers[n+"_action_"+d]||(e.one("body").delegate("click",M.editor_atto.buttonclicked_handler,".atto_"+n+"_action_"+d),e.one("body").delegate("key",M.editor_atto.buttonclicked_handler,"space,enter",".atto_"+n+"_action_"+d),M.editor_atto.buttonhandlers[n+"_action_"+d]=v.handler);M.editor_atto.buttonhandlers[n]||(e.one("body").delegate("click",M.editor_atto.showhide_menu_handler,".atto_"+n+"_button"),M.editor_atto.buttonhandlers[n]=!0);var m=new M.core.dialogue({bodyContent:p,visible:!1,width:o+"em",lightbox:!1,closeButton:!1,center:!1});M.editor_atto.menus[n+"_"+t]=m,m.align(c,[e.WidgetPositionAlign.TL,e.WidgetPositionAlign.BL]),m.hide(),m.headerNode.hide(),m.render
+()},add_toolbar_button:function(t,n,r,i,s){var o=M.editor_atto.get_toolbar_node(t),u=o.one(".atto_group."+i+"_group"),a,f;u||(u=e.Node.create(''),o.append(u)),a=e.Node.create('"),u.append(a),f=o.getAttribute("aria-activedescendant"),f||(a.setAttribute("tabindex","0"),o.setAttribute("aria-activedescendant",a.generateID())),M.editor_atto.buttonhandlers[n]||(e.one("body").delegate("click",M.editor_atto.buttonclicked_handler,".atto_"+n+"_button"),M.editor_atto.buttonhandlers[n]=s),M.editor_atto.widgets[n]=n},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);try{document.execCommand("styleWithCSS",0,!1)}catch(a){try{document.execCommand("useCSS",0,!0)}catch(f){try{document.execCommand("styleWithCSS",!1,!1)}catch(l){}}}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 c,h,p,d;for(c=0;c=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}};var n="Controlmenu",r;r=function(e){e.draggable=!1,e.center=!1,e.width="auto",e.lightbox=!1,e.footerContent="",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),n.on("clickoutside",function(e){this.get("visible")&&(e.target.ancestor(".atto_control")||(e.preventDefault(),this.hide()))},this)}},{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"]});
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 04f6078a7e0..fe4af1c16cc 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
@@ -161,6 +161,18 @@ M.editor_atto = M.editor_atto || {
var plugin = this.getAttribute('data-plugin');
var handler = this.getAttribute('data-handler');
var overlay = M.editor_atto.menus[plugin + '_' + elementid];
+ var toolbar = M.editor_atto.get_toolbar_node(elementid);
+ var currentid = toolbar.getAttribute('aria-activedescendant');
+
+ // Right now, currentid is the id of the previously selected button.
+ if (currentid) {
+ current = Y.one('#' + currentid);
+ // We only ever want one button with a tabindex of 0 at any one time.
+ current.setAttribute('tabindex', '-1');
+ }
+ this.setAttribute('tabindex', 0);
+ // And update the activedescendant to point at the currently selected button.
+ toolbar.setAttribute('aria-activedescendant', this.generateID());
if (overlay) {
overlay.hide();
@@ -323,6 +335,7 @@ M.editor_atto = M.editor_atto || {
currentfocus = toolbar.getAttribute('aria-activedescendant');
if (!currentfocus) {
+ // Initially set the first button in the toolbar to be the default on keyboard focus.
button.setAttribute('tabindex', '0');
toolbar.setAttribute('aria-activedescendant', button.generateID());
}
@@ -406,6 +419,7 @@ M.editor_atto = M.editor_atto || {
currentfocus = toolbar.getAttribute('aria-activedescendant');
if (!currentfocus) {
+ // Initially set the first button in the toolbar to be the default on keyboard focus.
button.setAttribute('tabindex', '0');
toolbar.setAttribute('aria-activedescendant', button.generateID());
}
@@ -540,17 +554,31 @@ M.editor_atto = M.editor_atto || {
M.editor_atto.filepickeroptions[params.elementid] = params.filepickeroptions;
// Init each of the plugins
- var i, j;
+ var i, j, group, plugin;
for (i = 0; i < params.plugins.length; i++) {
- var group = params.plugins[i].group;
+ group = params.plugins[i].group;
for (j = 0; j < params.plugins[i].plugins.length; j++) {
- var plugin = params.plugins[i].plugins[j];
+ plugin = params.plugins[i].plugins[j];
plugin.params.elementid = params.elementid;
plugin.params.group = group;
M['atto_' + plugin.name].init(plugin.params);
}
}
+
+ // Let the plugins run some init code once all plugins are in the page.
+ for (i = 0; i < params.plugins.length; i++) {
+ group = params.plugins[i].group;
+ for (j = 0; j < params.plugins[i].plugins.length; j++) {
+ plugin = params.plugins[i].plugins[j];
+ plugin.params.elementid = params.elementid;
+ plugin.params.group = group;
+
+ if (typeof M['atto_' + plugin.name].after_init !== 'undefined') {
+ M['atto_' + plugin.name].after_init(plugin.params);
+ }
+ }
+ }
},
/**
@@ -613,11 +641,21 @@ M.editor_atto = M.editor_atto || {
e.preventDefault();
- buttons = toolbar.all('button');
+ // This workaround is because we cannot do ".atto_group:not([hidden]) button" in ie8 (even with selector-css3).
+ // Create an empty NodeList.
+ buttons = toolbar.all('empty');
+ toolbar.all('.atto_group').each(function(group) {
+ if (!group.hasAttribute('hidden')) {
+ // Append the visible buttons to the buttons list.
+ buttons = buttons.concat(group.all('button'));
+ }
+ });
+ // The currentid is the id of the previously selected button.
currentid = toolbar.getAttribute('aria-activedescendant');
if (!currentid) {
return;
}
+ // We only ever want one button with a tabindex of 0.
current = Y.one('#' + currentid);
current.setAttribute('tabindex', '-1');
@@ -636,7 +674,7 @@ M.editor_atto = M.editor_atto || {
currentindex = 0;
}
}
-
+ // Currentindex has been updated to point to the new button.
current = buttons.item(currentindex);
current.setAttribute('tabindex', '0');
current.focus();
diff --git a/lib/editor/atto/yui/src/editor/js/editor.js b/lib/editor/atto/yui/src/editor/js/editor.js
index 26aad700965..ce3a7425312 100644
--- a/lib/editor/atto/yui/src/editor/js/editor.js
+++ b/lib/editor/atto/yui/src/editor/js/editor.js
@@ -159,6 +159,18 @@ M.editor_atto = M.editor_atto || {
var plugin = this.getAttribute('data-plugin');
var handler = this.getAttribute('data-handler');
var overlay = M.editor_atto.menus[plugin + '_' + elementid];
+ var toolbar = M.editor_atto.get_toolbar_node(elementid);
+ var currentid = toolbar.getAttribute('aria-activedescendant');
+
+ // Right now, currentid is the id of the previously selected button.
+ if (currentid) {
+ current = Y.one('#' + currentid);
+ // We only ever want one button with a tabindex of 0 at any one time.
+ current.setAttribute('tabindex', '-1');
+ }
+ this.setAttribute('tabindex', 0);
+ // And update the activedescendant to point at the currently selected button.
+ toolbar.setAttribute('aria-activedescendant', this.generateID());
if (overlay) {
overlay.hide();
@@ -321,6 +333,7 @@ M.editor_atto = M.editor_atto || {
currentfocus = toolbar.getAttribute('aria-activedescendant');
if (!currentfocus) {
+ // Initially set the first button in the toolbar to be the default on keyboard focus.
button.setAttribute('tabindex', '0');
toolbar.setAttribute('aria-activedescendant', button.generateID());
}
@@ -404,6 +417,7 @@ M.editor_atto = M.editor_atto || {
currentfocus = toolbar.getAttribute('aria-activedescendant');
if (!currentfocus) {
+ // Initially set the first button in the toolbar to be the default on keyboard focus.
button.setAttribute('tabindex', '0');
toolbar.setAttribute('aria-activedescendant', button.generateID());
}
@@ -538,17 +552,31 @@ M.editor_atto = M.editor_atto || {
M.editor_atto.filepickeroptions[params.elementid] = params.filepickeroptions;
// Init each of the plugins
- var i, j;
+ var i, j, group, plugin;
for (i = 0; i < params.plugins.length; i++) {
- var group = params.plugins[i].group;
+ group = params.plugins[i].group;
for (j = 0; j < params.plugins[i].plugins.length; j++) {
- var plugin = params.plugins[i].plugins[j];
+ plugin = params.plugins[i].plugins[j];
plugin.params.elementid = params.elementid;
plugin.params.group = group;
M['atto_' + plugin.name].init(plugin.params);
}
}
+
+ // Let the plugins run some init code once all plugins are in the page.
+ for (i = 0; i < params.plugins.length; i++) {
+ group = params.plugins[i].group;
+ for (j = 0; j < params.plugins[i].plugins.length; j++) {
+ plugin = params.plugins[i].plugins[j];
+ plugin.params.elementid = params.elementid;
+ plugin.params.group = group;
+
+ if (typeof M['atto_' + plugin.name].after_init !== 'undefined') {
+ M['atto_' + plugin.name].after_init(plugin.params);
+ }
+ }
+ }
},
/**
@@ -611,11 +639,21 @@ M.editor_atto = M.editor_atto || {
e.preventDefault();
- buttons = toolbar.all('button');
+ // This workaround is because we cannot do ".atto_group:not([hidden]) button" in ie8 (even with selector-css3).
+ // Create an empty NodeList.
+ buttons = toolbar.all('empty');
+ toolbar.all('.atto_group').each(function(group) {
+ if (!group.hasAttribute('hidden')) {
+ // Append the visible buttons to the buttons list.
+ buttons = buttons.concat(group.all('button'));
+ }
+ });
+ // The currentid is the id of the previously selected button.
currentid = toolbar.getAttribute('aria-activedescendant');
if (!currentid) {
return;
}
+ // We only ever want one button with a tabindex of 0.
current = Y.one('#' + currentid);
current.setAttribute('tabindex', '-1');
@@ -634,7 +672,7 @@ M.editor_atto = M.editor_atto || {
currentindex = 0;
}
}
-
+ // Currentindex has been updated to point to the new button.
current = buttons.item(currentindex);
current.setAttribute('tabindex', '0');
current.focus();