MDL-43869 Atto: Add functions to get the nodes from the elementids.

If plugins try and do this themselves with Y.one, they will fall foul of the
qtype essay page bug which uses : in the id for form elements.

This is an alternative solution, to escaping the ids, which seemed unreliable for older
version of ie.
This commit is contained in:
Damyon Wiese
2014-03-26 09:59:35 +08:00
parent 45698f7714
commit 48bdf86f31
12 changed files with 227 additions and 116 deletions
@@ -31,8 +31,8 @@ M.atto_html = M.atto_html || {
init : function(params) {
var click = function(e, elementid) {
e.preventDefault();
var textarea = Y.one('#' + elementid);
var atto = Y.one('#' + elementid + 'editable');
var textarea = M.editor_atto.get_textarea_node(elementid),
atto = M.editor_atto.get_editable_node(elementid);
if (M.atto_html.ishtml) {
M.editor_atto.enable_all_widgets(elementid);
@@ -1 +1 @@
YUI.add("moodle-atto_html-button",function(e,t){M.atto_html=M.atto_html||{ishtml:!1,init:function(t){var n=function(t,n){t.preventDefault();var r=e.one("#"+n),i=e.one("#"+n+"editable");M.atto_html.ishtml?(M.editor_atto.enable_all_widgets(n),i.setHTML(""),i.append(r.get("value")),r.hide(),i.show(),i.focus()):(M.editor_atto.disable_all_widgets(n),M.editor_atto.enable_widget(n,"html"),M.editor_atto.text_updated(n),i.hide(),r.show(),r.focus()),M.atto_html.ishtml=!M.atto_html.ishtml},r=M.util.image_url("e/source_code","core");M.editor_atto.add_toolbar_button(t.elementid,"html",r,t.group,n)}}},"@VERSION@",{requires:["node","event-valuechange"]});
YUI.add("moodle-atto_html-button",function(e,t){M.atto_html=M.atto_html||{ishtml:!1,init:function(e){var t=function(e,t){e.preventDefault();var n=M.editor_atto.get_textarea_node(t),r=M.editor_atto.get_editable_node(t);M.atto_html.ishtml?(M.editor_atto.enable_all_widgets(t),r.setHTML(""),r.append(n.get("value")),n.hide(),r.show(),r.focus()):(M.editor_atto.disable_all_widgets(t),M.editor_atto.enable_widget(t,"html"),M.editor_atto.text_updated(t),r.hide(),n.show(),n.focus()),M.atto_html.ishtml=!M.atto_html.ishtml},n=M.util.image_url("e/source_code","core");M.editor_atto.add_toolbar_button(e.elementid,"html",n,e.group,t)}}},"@VERSION@",{requires:["node","event-valuechange"]});
@@ -31,8 +31,8 @@ M.atto_html = M.atto_html || {
init : function(params) {
var click = function(e, elementid) {
e.preventDefault();
var textarea = Y.one('#' + elementid);
var atto = Y.one('#' + elementid + 'editable');
var textarea = M.editor_atto.get_textarea_node(elementid),
atto = M.editor_atto.get_editable_node(elementid);
if (M.atto_html.ishtml) {
M.editor_atto.enable_all_widgets(elementid);
+2 -2
View File
@@ -29,8 +29,8 @@ M.atto_html = M.atto_html || {
init : function(params) {
var click = function(e, elementid) {
e.preventDefault();
var textarea = Y.one('#' + elementid);
var atto = Y.one('#' + elementid + 'editable');
var textarea = M.editor_atto.get_textarea_node(elementid),
atto = M.editor_atto.get_editable_node(elementid);
if (M.atto_html.ishtml) {
M.editor_atto.enable_all_widgets(elementid);
@@ -480,7 +480,7 @@ M.atto_table = M.atto_table || {
var iconurl = M.util.image_url('e/table', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'table', iconurl, params.group, this.display_chooser, this);
var contenteditable = Y.one('#' + params.elementid + 'editable');
var contenteditable = M.editor_atto.get_editable_node(params.elementid);
contenteditable.delegate('click', this.show_menu, 'td > .atto_control, th > .atto_control', this, params.elementid);
contenteditable.delegate('key', this.show_menu, 'down:enter,space', 'td > .atto_control, th > .atto_control', this, params.elementid);
// Disable mozilla table controls.
@@ -502,7 +502,7 @@ M.atto_table = M.atto_table || {
* @param String elementid - The id of the text area backed by the content editable field.
*/
insert_table_controls : function(elementid) {
var contenteditable = Y.one('#' + elementid + 'editable'),
var contenteditable = M.editor_atto.get_editable_node(elementid),
allcells = contenteditable.all('td .atto_control,th .atto_control'),
cells = contenteditable.all('td:last-child,th:last-child,tbody tr:last-child > td, tbody tr:last-child > th');
File diff suppressed because one or more lines are too long
@@ -480,7 +480,7 @@ M.atto_table = M.atto_table || {
var iconurl = M.util.image_url('e/table', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'table', iconurl, params.group, this.display_chooser, this);
var contenteditable = Y.one('#' + params.elementid + 'editable');
var contenteditable = M.editor_atto.get_editable_node(params.elementid);
contenteditable.delegate('click', this.show_menu, 'td > .atto_control, th > .atto_control', this, params.elementid);
contenteditable.delegate('key', this.show_menu, 'down:enter,space', 'td > .atto_control, th > .atto_control', this, params.elementid);
// Disable mozilla table controls.
@@ -502,7 +502,7 @@ M.atto_table = M.atto_table || {
* @param String elementid - The id of the text area backed by the content editable field.
*/
insert_table_controls : function(elementid) {
var contenteditable = Y.one('#' + elementid + 'editable'),
var contenteditable = M.editor_atto.get_editable_node(elementid),
allcells = contenteditable.all('td .atto_control,th .atto_control'),
cells = contenteditable.all('td:last-child,th:last-child,tbody tr:last-child > td, tbody tr:last-child > th');
+2 -2
View File
@@ -478,7 +478,7 @@ M.atto_table = M.atto_table || {
var iconurl = M.util.image_url('e/table', 'core');
M.editor_atto.add_toolbar_button(params.elementid, 'table', iconurl, params.group, this.display_chooser, this);
var contenteditable = Y.one('#' + params.elementid + 'editable');
var contenteditable = M.editor_atto.get_editable_node(params.elementid);
contenteditable.delegate('click', this.show_menu, 'td > .atto_control, th > .atto_control', this, params.elementid);
contenteditable.delegate('key', this.show_menu, 'down:enter,space', 'td > .atto_control, th > .atto_control', this, params.elementid);
// Disable mozilla table controls.
@@ -500,7 +500,7 @@ M.atto_table = M.atto_table || {
* @param String elementid - The id of the text area backed by the content editable field.
*/
insert_table_controls : function(elementid) {
var contenteditable = Y.one('#' + elementid + 'editable'),
var contenteditable = M.editor_atto.get_editable_node(elementid),
allcells = contenteditable.all('td .atto_control,th .atto_control'),
cells = contenteditable.all('td:last-child,th:last-child,tbody tr:last-child > td, tbody tr:last-child > th');
@@ -121,24 +121,14 @@ M.editor_atto = M.editor_atto || {
}
},
/**
* Determine if the specified toolbar button/menu is enabled.
* @param string elementid, the element id of this editor.
* @param string plugin, the plugin that created the button/menu.
*/
is_enabled : function(elementid, plugin) {
var element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
return !element.hasAttribute('disabled');
},
/**
* Disable all buttons and menus in the toolbar.
* @param string elementid, the element id of this editor.
*/
disable_all_widgets : function(elementid) {
var plugin, element;
var plugin, element, toolbar = M.editor_atto.get_toolbar_node(elementid);
for (plugin in M.editor_atto.widgets) {
element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
element = toolbar.one('.atto_' + plugin + '_button');
if (element) {
element.setAttribute('disabled', 'true');
@@ -146,13 +136,60 @@ M.editor_atto = M.editor_atto || {
}
},
/**
* Get the node of the original textarea element that this editor replaced.
*
* @param string elementid, the element id of this editor.
* @return Y.Node
*/
get_textarea_node : function(elementid) {
// Note - it is not safe to use a CSS selector like '#' + elementid
// because the id may have colons in it - e.g. quiz.
return Y.one(document.getElementById(elementid));
},
/**
* Get the node of the toolbar container for this editor.
*
* @param string elementid, the element id of this editor.
* @return Y.Node
*/
get_toolbar_node : function(elementid) {
// Note - it is not safe to use a CSS selector like '#' + elementid
// because the id may have colons in it - e.g. quiz.
return Y.one(document.getElementById(elementid + '_toolbar'));
},
/**
* Get the node of the contenteditable container for this editor.
*
* @param string elementid, the element id of this editor.
* @return Y.Node
*/
get_editable_node : function(elementid) {
// Note - it is not safe to use a CSS selector like '#' + elementid
// because the id may have colons in it - e.g. quiz.
return Y.one(document.getElementById(elementid + 'editable'));
},
/**
* Determine if the specified toolbar button/menu is enabled.
* @param string elementid, the element id of this editor.
* @param string plugin, the plugin that created the button/menu.
*/
is_enabled : function(elementid, plugin) {
var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + plugin + '_button');
return !element.hasAttribute('disabled');
},
/**
* Enable 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.
*/
enable_widget : function(elementid, plugin) {
var element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + plugin + '_button');
if (element) {
element.removeAttribute('disabled');
@@ -166,7 +203,7 @@ M.editor_atto = M.editor_atto || {
enable_all_widgets : function(elementid) {
var plugin, element;
for (plugin in M.editor_atto.widgets) {
element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + plugin + '_button');
if (element) {
element.removeAttribute('disabled');
@@ -199,8 +236,8 @@ M.editor_atto = M.editor_atto || {
* @param array entries - List of menu entries with the string (entry.text) and the handlers (entry.handler).
*/
add_toolbar_menu : function(elementid, plugin, iconurl, groupname, entries) {
var toolbar = Y.one('#' + elementid + '_toolbar'),
group = Y.one('#' + elementid + '_toolbar .atto_group.' + groupname + '_group'),
var toolbar = M.editor_atto.get_toolbar_node(elementid),
group = toolbar.one('.atto_group.' + groupname + '_group'),
currentfocus,
button,
expimgurl;
@@ -283,8 +320,8 @@ M.editor_atto = M.editor_atto || {
* @handler function handler- A function to call when the button is clicked.
*/
add_toolbar_button : function(elementid, plugin, iconurl, groupname, handler) {
var toolbar = Y.one('#' + elementid + '_toolbar'),
group = Y.one('#' + elementid + '_toolbar .atto_group.' + groupname + '_group'),
var toolbar = M.editor_atto.get_toolbar_node(elementid),
group = toolbar.one('.atto_group.' + groupname + '_group'),
button,
currentfocus;
@@ -347,7 +384,7 @@ M.editor_atto = M.editor_atto || {
* @param string elementid of this editor
*/
focus : function(elementid) {
Y.one('#' + elementid + 'editable').focus();
M.editor_atto.get_editable_node(elementid).focus();
},
/**
@@ -366,8 +403,7 @@ M.editor_atto = M.editor_atto || {
// Editable content wrapper.
var content = Y.Node.create('<div class="' + CSS.CONTENTWRAPPER + '" />');
var elementid = params.elementid.replace(':', '\\:');
var textarea = Y.one('#' +elementid);
var textarea = M.editor_atto.get_textarea_node(params.elementid);
content.appendChild(atto);
@@ -400,19 +436,19 @@ M.editor_atto = M.editor_atto || {
// Copy the current value back to the textarea when focus leaves us.
atto.on('blur', function() {
this.text_updated(elementid);
this.text_updated(params.elementid);
}, this);
// Listen for Arrow left and Arrow right keys.
Y.one(Y.config.doc.body).delegate('key',
this.keyboard_navigation,
'down:37,39',
'#' + elementid + '_toolbar',
'#' + params.elementid + '_toolbar',
this,
elementid);
params.elementid);
// Save the file picker options for later.
M.editor_atto.filepickeroptions[elementid] = params.filepickeroptions;
M.editor_atto.filepickeroptions[params.elementid] = params.filepickeroptions;
// Init each of the plugins
var i, j;
@@ -420,7 +456,7 @@ M.editor_atto = M.editor_atto || {
var group = params.plugins[i].group;
for (j = 0; j < params.plugins[i].plugins.length; j++) {
var plugin = params.plugins[i].plugins[j];
plugin.params.elementid = elementid;
plugin.params.elementid = params.elementid;
plugin.params.group = group;
M['atto_' + plugin.name].init(plugin.params);
@@ -434,7 +470,7 @@ M.editor_atto = M.editor_atto || {
* @param string elementid - the id of the textarea we created this editor from.
*/
text_updated : function(elementid) {
var textarea = Y.one('#' + elementid),
var textarea = M.editor_atto.get_textarea_node(elementid),
cleancontent = this.get_clean_html(elementid);
textarea.set('value', cleancontent);
// Trigger handlers for this action.
@@ -453,7 +489,7 @@ M.editor_atto = M.editor_atto || {
* @return string HTML stripped of YUI ids
*/
get_clean_html : function(elementid) {
var atto = Y.one('#' + elementid + 'editable').cloneNode(true);
var atto = M.editor_atto.get_editable_node(elementid).cloneNode(true);
Y.each(atto.all('[id]'), function(node) {
var id = node.get('id');
@@ -481,12 +517,13 @@ M.editor_atto = M.editor_atto || {
var buttons,
current,
currentid,
currentindex;
currentindex,
toolbar = M.editor_atto.get_toolbar_node(elementid);
e.preventDefault();
buttons = Y.all('#' + elementid + '_toolbar button');
currentid = Y.one('#' + elementid + '_toolbar').getAttribute('aria-activedescendant');
buttons = toolbar.all('button');
currentid = toolbar.getAttribute('aria-activedescendant');
if (!currentid) {
return;
}
@@ -512,7 +549,7 @@ M.editor_atto = M.editor_atto || {
current = buttons.item(currentindex);
current.setAttribute('tabindex', '0');
current.focus();
Y.one('#' + elementid + '_toolbar').setAttribute('aria-activedescendant', current.generateID());
toolbar.setAttribute('aria-activedescendant', current.generateID());
},
/**
@@ -538,7 +575,7 @@ M.editor_atto = M.editor_atto || {
var options = M.editor_atto.filepickeroptions[elementid][type];
options.formcallback = callback;
options.editor_target = Y.one(elementid);
options.editor_target = M.editor_atto.get_textarea_node(elementid);
M.core_filepicker.show(Y, options);
});
File diff suppressed because one or more lines are too long
@@ -121,24 +121,14 @@ M.editor_atto = M.editor_atto || {
}
},
/**
* Determine if the specified toolbar button/menu is enabled.
* @param string elementid, the element id of this editor.
* @param string plugin, the plugin that created the button/menu.
*/
is_enabled : function(elementid, plugin) {
var element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
return !element.hasAttribute('disabled');
},
/**
* Disable all buttons and menus in the toolbar.
* @param string elementid, the element id of this editor.
*/
disable_all_widgets : function(elementid) {
var plugin, element;
var plugin, element, toolbar = M.editor_atto.get_toolbar_node(elementid);
for (plugin in M.editor_atto.widgets) {
element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
element = toolbar.one('.atto_' + plugin + '_button');
if (element) {
element.setAttribute('disabled', 'true');
@@ -146,13 +136,60 @@ M.editor_atto = M.editor_atto || {
}
},
/**
* Get the node of the original textarea element that this editor replaced.
*
* @param string elementid, the element id of this editor.
* @return Y.Node
*/
get_textarea_node : function(elementid) {
// Note - it is not safe to use a CSS selector like '#' + elementid
// because the id may have colons in it - e.g. quiz.
return Y.one(document.getElementById(elementid));
},
/**
* Get the node of the toolbar container for this editor.
*
* @param string elementid, the element id of this editor.
* @return Y.Node
*/
get_toolbar_node : function(elementid) {
// Note - it is not safe to use a CSS selector like '#' + elementid
// because the id may have colons in it - e.g. quiz.
return Y.one(document.getElementById(elementid + '_toolbar'));
},
/**
* Get the node of the contenteditable container for this editor.
*
* @param string elementid, the element id of this editor.
* @return Y.Node
*/
get_editable_node : function(elementid) {
// Note - it is not safe to use a CSS selector like '#' + elementid
// because the id may have colons in it - e.g. quiz.
return Y.one(document.getElementById(elementid + 'editable'));
},
/**
* Determine if the specified toolbar button/menu is enabled.
* @param string elementid, the element id of this editor.
* @param string plugin, the plugin that created the button/menu.
*/
is_enabled : function(elementid, plugin) {
var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + plugin + '_button');
return !element.hasAttribute('disabled');
},
/**
* Enable 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.
*/
enable_widget : function(elementid, plugin) {
var element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + plugin + '_button');
if (element) {
element.removeAttribute('disabled');
@@ -166,7 +203,7 @@ M.editor_atto = M.editor_atto || {
enable_all_widgets : function(elementid) {
var plugin, element;
for (plugin in M.editor_atto.widgets) {
element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + plugin + '_button');
if (element) {
element.removeAttribute('disabled');
@@ -199,8 +236,8 @@ M.editor_atto = M.editor_atto || {
* @param array entries - List of menu entries with the string (entry.text) and the handlers (entry.handler).
*/
add_toolbar_menu : function(elementid, plugin, iconurl, groupname, entries) {
var toolbar = Y.one('#' + elementid + '_toolbar'),
group = Y.one('#' + elementid + '_toolbar .atto_group.' + groupname + '_group'),
var toolbar = M.editor_atto.get_toolbar_node(elementid),
group = toolbar.one('.atto_group.' + groupname + '_group'),
currentfocus,
button,
expimgurl;
@@ -283,8 +320,8 @@ M.editor_atto = M.editor_atto || {
* @handler function handler- A function to call when the button is clicked.
*/
add_toolbar_button : function(elementid, plugin, iconurl, groupname, handler) {
var toolbar = Y.one('#' + elementid + '_toolbar'),
group = Y.one('#' + elementid + '_toolbar .atto_group.' + groupname + '_group'),
var toolbar = M.editor_atto.get_toolbar_node(elementid),
group = toolbar.one('.atto_group.' + groupname + '_group'),
button,
currentfocus;
@@ -347,7 +384,7 @@ M.editor_atto = M.editor_atto || {
* @param string elementid of this editor
*/
focus : function(elementid) {
Y.one('#' + elementid + 'editable').focus();
M.editor_atto.get_editable_node(elementid).focus();
},
/**
@@ -366,8 +403,7 @@ M.editor_atto = M.editor_atto || {
// Editable content wrapper.
var content = Y.Node.create('<div class="' + CSS.CONTENTWRAPPER + '" />');
var elementid = params.elementid.replace(':', '\\:');
var textarea = Y.one('#' +elementid);
var textarea = M.editor_atto.get_textarea_node(params.elementid);
content.appendChild(atto);
@@ -400,19 +436,19 @@ M.editor_atto = M.editor_atto || {
// Copy the current value back to the textarea when focus leaves us.
atto.on('blur', function() {
this.text_updated(elementid);
this.text_updated(params.elementid);
}, this);
// Listen for Arrow left and Arrow right keys.
Y.one(Y.config.doc.body).delegate('key',
this.keyboard_navigation,
'down:37,39',
'#' + elementid + '_toolbar',
'#' + params.elementid + '_toolbar',
this,
elementid);
params.elementid);
// Save the file picker options for later.
M.editor_atto.filepickeroptions[elementid] = params.filepickeroptions;
M.editor_atto.filepickeroptions[params.elementid] = params.filepickeroptions;
// Init each of the plugins
var i, j;
@@ -420,7 +456,7 @@ M.editor_atto = M.editor_atto || {
var group = params.plugins[i].group;
for (j = 0; j < params.plugins[i].plugins.length; j++) {
var plugin = params.plugins[i].plugins[j];
plugin.params.elementid = elementid;
plugin.params.elementid = params.elementid;
plugin.params.group = group;
M['atto_' + plugin.name].init(plugin.params);
@@ -434,7 +470,7 @@ M.editor_atto = M.editor_atto || {
* @param string elementid - the id of the textarea we created this editor from.
*/
text_updated : function(elementid) {
var textarea = Y.one('#' + elementid),
var textarea = M.editor_atto.get_textarea_node(elementid),
cleancontent = this.get_clean_html(elementid);
textarea.set('value', cleancontent);
// Trigger handlers for this action.
@@ -453,7 +489,7 @@ M.editor_atto = M.editor_atto || {
* @return string HTML stripped of YUI ids
*/
get_clean_html : function(elementid) {
var atto = Y.one('#' + elementid + 'editable').cloneNode(true);
var atto = M.editor_atto.get_editable_node(elementid).cloneNode(true);
Y.each(atto.all('[id]'), function(node) {
var id = node.get('id');
@@ -481,12 +517,13 @@ M.editor_atto = M.editor_atto || {
var buttons,
current,
currentid,
currentindex;
currentindex,
toolbar = M.editor_atto.get_toolbar_node(elementid);
e.preventDefault();
buttons = Y.all('#' + elementid + '_toolbar button');
currentid = Y.one('#' + elementid + '_toolbar').getAttribute('aria-activedescendant');
buttons = toolbar.all('button');
currentid = toolbar.getAttribute('aria-activedescendant');
if (!currentid) {
return;
}
@@ -512,7 +549,7 @@ M.editor_atto = M.editor_atto || {
current = buttons.item(currentindex);
current.setAttribute('tabindex', '0');
current.focus();
Y.one('#' + elementid + '_toolbar').setAttribute('aria-activedescendant', current.generateID());
toolbar.setAttribute('aria-activedescendant', current.generateID());
},
/**
@@ -538,7 +575,7 @@ M.editor_atto = M.editor_atto || {
var options = M.editor_atto.filepickeroptions[elementid][type];
options.formcallback = callback;
options.editor_target = Y.one(elementid);
options.editor_target = M.editor_atto.get_textarea_node(elementid);
M.core_filepicker.show(Y, options);
});
+70 -33
View File
@@ -119,24 +119,14 @@ M.editor_atto = M.editor_atto || {
}
},
/**
* Determine if the specified toolbar button/menu is enabled.
* @param string elementid, the element id of this editor.
* @param string plugin, the plugin that created the button/menu.
*/
is_enabled : function(elementid, plugin) {
var element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
return !element.hasAttribute('disabled');
},
/**
* Disable all buttons and menus in the toolbar.
* @param string elementid, the element id of this editor.
*/
disable_all_widgets : function(elementid) {
var plugin, element;
var plugin, element, toolbar = M.editor_atto.get_toolbar_node(elementid);
for (plugin in M.editor_atto.widgets) {
element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
element = toolbar.one('.atto_' + plugin + '_button');
if (element) {
element.setAttribute('disabled', 'true');
@@ -144,13 +134,60 @@ M.editor_atto = M.editor_atto || {
}
},
/**
* Get the node of the original textarea element that this editor replaced.
*
* @param string elementid, the element id of this editor.
* @return Y.Node
*/
get_textarea_node : function(elementid) {
// Note - it is not safe to use a CSS selector like '#' + elementid
// because the id may have colons in it - e.g. quiz.
return Y.one(document.getElementById(elementid));
},
/**
* Get the node of the toolbar container for this editor.
*
* @param string elementid, the element id of this editor.
* @return Y.Node
*/
get_toolbar_node : function(elementid) {
// Note - it is not safe to use a CSS selector like '#' + elementid
// because the id may have colons in it - e.g. quiz.
return Y.one(document.getElementById(elementid + '_toolbar'));
},
/**
* Get the node of the contenteditable container for this editor.
*
* @param string elementid, the element id of this editor.
* @return Y.Node
*/
get_editable_node : function(elementid) {
// Note - it is not safe to use a CSS selector like '#' + elementid
// because the id may have colons in it - e.g. quiz.
return Y.one(document.getElementById(elementid + 'editable'));
},
/**
* Determine if the specified toolbar button/menu is enabled.
* @param string elementid, the element id of this editor.
* @param string plugin, the plugin that created the button/menu.
*/
is_enabled : function(elementid, plugin) {
var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + plugin + '_button');
return !element.hasAttribute('disabled');
},
/**
* Enable 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.
*/
enable_widget : function(elementid, plugin) {
var element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + plugin + '_button');
if (element) {
element.removeAttribute('disabled');
@@ -164,7 +201,7 @@ M.editor_atto = M.editor_atto || {
enable_all_widgets : function(elementid) {
var plugin, element;
for (plugin in M.editor_atto.widgets) {
element = Y.one('#' + elementid + '_toolbar .atto_' + plugin + '_button');
element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + plugin + '_button');
if (element) {
element.removeAttribute('disabled');
@@ -197,8 +234,8 @@ M.editor_atto = M.editor_atto || {
* @param array entries - List of menu entries with the string (entry.text) and the handlers (entry.handler).
*/
add_toolbar_menu : function(elementid, plugin, iconurl, groupname, entries) {
var toolbar = Y.one('#' + elementid + '_toolbar'),
group = Y.one('#' + elementid + '_toolbar .atto_group.' + groupname + '_group'),
var toolbar = M.editor_atto.get_toolbar_node(elementid),
group = toolbar.one('.atto_group.' + groupname + '_group'),
currentfocus,
button,
expimgurl;
@@ -281,8 +318,8 @@ M.editor_atto = M.editor_atto || {
* @handler function handler- A function to call when the button is clicked.
*/
add_toolbar_button : function(elementid, plugin, iconurl, groupname, handler) {
var toolbar = Y.one('#' + elementid + '_toolbar'),
group = Y.one('#' + elementid + '_toolbar .atto_group.' + groupname + '_group'),
var toolbar = M.editor_atto.get_toolbar_node(elementid),
group = toolbar.one('.atto_group.' + groupname + '_group'),
button,
currentfocus;
@@ -345,7 +382,7 @@ M.editor_atto = M.editor_atto || {
* @param string elementid of this editor
*/
focus : function(elementid) {
Y.one('#' + elementid + 'editable').focus();
M.editor_atto.get_editable_node(elementid).focus();
},
/**
@@ -364,8 +401,7 @@ M.editor_atto = M.editor_atto || {
// Editable content wrapper.
var content = Y.Node.create('<div class="' + CSS.CONTENTWRAPPER + '" />');
var elementid = params.elementid.replace(':', '\\:');
var textarea = Y.one('#' +elementid);
var textarea = M.editor_atto.get_textarea_node(params.elementid);
content.appendChild(atto);
@@ -398,19 +434,19 @@ M.editor_atto = M.editor_atto || {
// Copy the current value back to the textarea when focus leaves us.
atto.on('blur', function() {
this.text_updated(elementid);
this.text_updated(params.elementid);
}, this);
// Listen for Arrow left and Arrow right keys.
Y.one(Y.config.doc.body).delegate('key',
this.keyboard_navigation,
'down:37,39',
'#' + elementid + '_toolbar',
'#' + params.elementid + '_toolbar',
this,
elementid);
params.elementid);
// Save the file picker options for later.
M.editor_atto.filepickeroptions[elementid] = params.filepickeroptions;
M.editor_atto.filepickeroptions[params.elementid] = params.filepickeroptions;
// Init each of the plugins
var i, j;
@@ -418,7 +454,7 @@ M.editor_atto = M.editor_atto || {
var group = params.plugins[i].group;
for (j = 0; j < params.plugins[i].plugins.length; j++) {
var plugin = params.plugins[i].plugins[j];
plugin.params.elementid = elementid;
plugin.params.elementid = params.elementid;
plugin.params.group = group;
M['atto_' + plugin.name].init(plugin.params);
@@ -432,7 +468,7 @@ M.editor_atto = M.editor_atto || {
* @param string elementid - the id of the textarea we created this editor from.
*/
text_updated : function(elementid) {
var textarea = Y.one('#' + elementid),
var textarea = M.editor_atto.get_textarea_node(elementid),
cleancontent = this.get_clean_html(elementid);
textarea.set('value', cleancontent);
// Trigger handlers for this action.
@@ -451,7 +487,7 @@ M.editor_atto = M.editor_atto || {
* @return string HTML stripped of YUI ids
*/
get_clean_html : function(elementid) {
var atto = Y.one('#' + elementid + 'editable').cloneNode(true);
var atto = M.editor_atto.get_editable_node(elementid).cloneNode(true);
Y.each(atto.all('[id]'), function(node) {
var id = node.get('id');
@@ -479,12 +515,13 @@ M.editor_atto = M.editor_atto || {
var buttons,
current,
currentid,
currentindex;
currentindex,
toolbar = M.editor_atto.get_toolbar_node(elementid);
e.preventDefault();
buttons = Y.all('#' + elementid + '_toolbar button');
currentid = Y.one('#' + elementid + '_toolbar').getAttribute('aria-activedescendant');
buttons = toolbar.all('button');
currentid = toolbar.getAttribute('aria-activedescendant');
if (!currentid) {
return;
}
@@ -510,7 +547,7 @@ M.editor_atto = M.editor_atto || {
current = buttons.item(currentindex);
current.setAttribute('tabindex', '0');
current.focus();
Y.one('#' + elementid + '_toolbar').setAttribute('aria-activedescendant', current.generateID());
toolbar.setAttribute('aria-activedescendant', current.generateID());
},
/**
@@ -536,7 +573,7 @@ M.editor_atto = M.editor_atto || {
var options = M.editor_atto.filepickeroptions[elementid][type];
options.formcallback = callback;
options.editor_target = Y.one(elementid);
options.editor_target = M.editor_atto.get_textarea_node(elementid);
M.core_filepicker.show(Y, options);
});