From bdfbdeeb640fa55e85ccb094db6df810b51261cf Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Thu, 20 Feb 2014 14:53:50 +1300 Subject: [PATCH] MDL-44040 editor: implemented shortcuts for bold, italic, underline and undo --- .../moodle-atto_bold-button-debug.js | 3 +- .../moodle-atto_bold-button-min.js | 2 +- .../moodle-atto_bold-button.js | 3 +- .../plugins/bold/yui/src/button/js/button.js | 1 + .../bold/yui/src/button/meta/button.json | 5 +- .../moodle-atto_italic-button-debug.js | 3 +- .../moodle-atto_italic-button-min.js | 2 +- .../moodle-atto_italic-button.js | 3 +- .../italic/yui/src/button/js/button.js | 1 + .../italic/yui/src/button/meta/button.json | 2 +- .../moodle-atto_underline-button-debug.js | 3 +- .../moodle-atto_underline-button-min.js | 2 +- .../moodle-atto_underline-button.js | 3 +- .../underline/yui/src/button/js/button.js | 1 + .../underline/yui/src/button/meta/button.json | 2 +- .../moodle-atto_undo-button-debug.js | 3 +- .../moodle-atto_undo-button-min.js | 2 +- .../moodle-atto_undo-button.js | 3 +- .../plugins/undo/yui/src/button/js/button.js | 1 + .../undo/yui/src/button/meta/button.json | 2 +- ...oodle-editor_atto-editor-shortcut-debug.js | 263 ++++++++++++++++++ .../moodle-editor_atto-editor-shortcut-min.js | 1 + .../moodle-editor_atto-editor-shortcut.js | 262 +++++++++++++++++ .../moodle-editor_atto-editor-debug.js | 3 +- .../moodle-editor_atto-editor-min.js | 4 +- .../moodle-editor_atto-editor.js | 3 +- lib/editor/atto/yui/src/editor/build.json | 5 + lib/editor/atto/yui/src/editor/js/editor.js | 3 +- lib/editor/atto/yui/src/editor/js/shortcut.js | 258 +++++++++++++++++ .../atto/yui/src/editor/meta/editor.json | 8 + 30 files changed, 836 insertions(+), 21 deletions(-) create mode 100644 lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-debug.js create mode 100644 lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-min.js create mode 100644 lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut.js create mode 100644 lib/editor/atto/yui/src/editor/js/shortcut.js 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 697f4de41ff..6a257507b0f 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 @@ -45,6 +45,7 @@ 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); + M.editor_atto.add_button_shortcut({action: 'bold', keys: 66}); // 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 @@ -61,4 +62,4 @@ M.atto_bold = M.atto_bold || { }; -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); 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 c7e378b20d7..95d24988962 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){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"]}); +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),M.editor_atto.add_button_shortcut({action:"bold",keys:66});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","moodle-editor_atto-editor-shortcut"]}); 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 697f4de41ff..6a257507b0f 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 @@ -45,6 +45,7 @@ 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); + M.editor_atto.add_button_shortcut({action: 'bold', keys: 66}); // 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 @@ -61,4 +62,4 @@ M.atto_bold = M.atto_bold || { }; -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); 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 b59bd518b4d..1fa76664d5d 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 @@ -43,6 +43,7 @@ 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); + M.editor_atto.add_button_shortcut({action: 'bold', keys: 66}); // 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 diff --git a/lib/editor/atto/plugins/bold/yui/src/button/meta/button.json b/lib/editor/atto/plugins/bold/yui/src/button/meta/button.json index e668c0ffbdd..92347fbc33e 100644 --- a/lib/editor/atto/plugins/bold/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/bold/yui/src/button/meta/button.json @@ -1,5 +1,8 @@ { "moodle-atto_bold-button": { - "requires": ["node"] + "requires": [ + "node", + "moodle-editor_atto-editor-shortcut" + ] } } 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 373b0e22d70..ed5f947505e 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 @@ -45,6 +45,7 @@ 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); + M.editor_atto.add_button_shortcut({action: 'italic', keys: 73}); // 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 @@ -61,4 +62,4 @@ M.atto_italic = M.atto_italic || { }; -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); 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 28a75d8d788..073511cf59c 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){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"]}); +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),M.editor_atto.add_button_shortcut({action:"italic",keys:73});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","moodle-editor_atto-editor-shortcut"]}); 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 373b0e22d70..ed5f947505e 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 @@ -45,6 +45,7 @@ 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); + M.editor_atto.add_button_shortcut({action: 'italic', keys: 73}); // 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 @@ -61,4 +62,4 @@ M.atto_italic = M.atto_italic || { }; -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); 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 c97236859b6..b6310e7a95e 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 @@ -43,6 +43,7 @@ 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); + M.editor_atto.add_button_shortcut({action: 'italic', keys: 73}); // 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 diff --git a/lib/editor/atto/plugins/italic/yui/src/button/meta/button.json b/lib/editor/atto/plugins/italic/yui/src/button/meta/button.json index 4109b10ce61..6a0efa9d9bc 100644 --- a/lib/editor/atto/plugins/italic/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/italic/yui/src/button/meta/button.json @@ -1,5 +1,5 @@ { "moodle-atto_italic-button": { - "requires": ["node"] + "requires": ["node", "moodle-editor_atto-editor-shortcut"] } } 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 da25d1a32dc..b33432adf82 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 @@ -45,6 +45,7 @@ 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); + M.editor_atto.add_button_shortcut({action: 'underline', keys: 85}); // 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 @@ -61,4 +62,4 @@ M.atto_underline = M.atto_underline || { }; -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); 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 798d0f7d277..80c5066b5a8 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){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"]}); +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),M.editor_atto.add_button_shortcut({action:"underline",keys:85});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","moodle-editor_atto-editor-shortcut"]}); 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 da25d1a32dc..b33432adf82 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 @@ -45,6 +45,7 @@ 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); + M.editor_atto.add_button_shortcut({action: 'underline', keys: 85}); // 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 @@ -61,4 +62,4 @@ M.atto_underline = M.atto_underline || { }; -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); 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 e2dd6b89026..d13ff4b5eac 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 @@ -43,6 +43,7 @@ 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); + M.editor_atto.add_button_shortcut({action: 'underline', keys: 85}); // 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 diff --git a/lib/editor/atto/plugins/underline/yui/src/button/meta/button.json b/lib/editor/atto/plugins/underline/yui/src/button/meta/button.json index e96b89bcddb..8e9cea14ddd 100644 --- a/lib/editor/atto/plugins/underline/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/underline/yui/src/button/meta/button.json @@ -1,5 +1,5 @@ { "moodle-atto_underline-button": { - "requires": ["node"] + "requires": ["node", "moodle-editor_atto-editor-shortcut"] } } diff --git a/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button-debug.js b/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button-debug.js index 6aa450b5a99..6143f87a008 100644 --- a/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button-debug.js +++ b/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button-debug.js @@ -138,9 +138,10 @@ M.atto_undo = M.atto_undo || { // Redo button. iconurl = M.util.image_url('e/redo', 'core'); M.editor_atto.add_toolbar_button(params.elementid, 'undo', iconurl, params.group, M.atto_undo.redo_handler, 'redo', M.util.get_string('redo', 'atto_undo')); + M.editor_atto.add_button_shortcut({action: 'redo', keys: 89}); } } }; -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); diff --git a/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button-min.js b/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button-min.js index c23e0e9d8b4..df0ab2c9358 100644 --- a/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button-min.js +++ b/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_undo-button",function(e,t){M.atto_undo=M.atto_undo||{browsersupportsundo:null,click_handler:function(e,t,n){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand(n,!1,null),M.editor_atto.text_updated(t)},undo_handler:function(e,t){M.atto_undo.click_handler(e,t,"undo")},redo_handler:function(e,t){M.atto_undo.click_handler(e,t,"redo")},test_undo_support:function(){var t=document.activeElement,n=!1,r=e.Node.create('
a
');e.one("body").prepend(r),r.focus();try{document.execCommand("insertText",!1,"b"),r.getHTML()==="ba"&&(document.execCommand("undo",!1),r.getHTML()==="a"&&(document.execCommand("redo",!1),r.getHTML()==="ba"&&(n=!0)))}catch(i){return!1}return e.one("body").removeChild(r),t.focus(),n},init:function(e){M.atto_undo.browsersupportsundo===null&&(M.atto_undo.browsersupportsundo=M.atto_undo.test_undo_support());if(M.atto_undo.browsersupportsundo){var t=M.util.image_url("e/undo","core");M.editor_atto.add_toolbar_button(e.elementid,"undo",t,e.group,M.atto_undo.undo_handler,"undo",M.util.get_string("undo","atto_undo")),t=M.util.image_url("e/redo","core"),M.editor_atto.add_toolbar_button(e.elementid,"undo",t,e.group,M.atto_undo.redo_handler,"redo",M.util.get_string("redo","atto_undo"))}}}},"@VERSION@",{requires:["node"]}); +YUI.add("moodle-atto_undo-button",function(e,t){M.atto_undo=M.atto_undo||{browsersupportsundo:null,click_handler:function(e,t,n){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand(n,!1,null),M.editor_atto.text_updated(t)},undo_handler:function(e,t){M.atto_undo.click_handler(e,t,"undo")},redo_handler:function(e,t){M.atto_undo.click_handler(e,t,"redo")},test_undo_support:function(){var t=document.activeElement,n=!1,r=e.Node.create('
a
');e.one("body").prepend(r),r.focus();try{document.execCommand("insertText",!1,"b"),r.getHTML()==="ba"&&(document.execCommand("undo",!1),r.getHTML()==="a"&&(document.execCommand("redo",!1),r.getHTML()==="ba"&&(n=!0)))}catch(i){return!1}return e.one("body").removeChild(r),t.focus(),n},init:function(e){M.atto_undo.browsersupportsundo===null&&(M.atto_undo.browsersupportsundo=M.atto_undo.test_undo_support());if(M.atto_undo.browsersupportsundo){var t=M.util.image_url("e/undo","core");M.editor_atto.add_toolbar_button(e.elementid,"undo",t,e.group,M.atto_undo.undo_handler,"undo",M.util.get_string("undo","atto_undo")),t=M.util.image_url("e/redo","core"),M.editor_atto.add_toolbar_button(e.elementid,"undo",t,e.group,M.atto_undo.redo_handler,"redo",M.util.get_string("redo","atto_undo")),M.editor_atto.add_button_shortcut({action:"redo",keys:89})}}}},"@VERSION@",{requires:["node","moodle-editor_atto-editor-shortcut"]}); diff --git a/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button.js b/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button.js index 6aa450b5a99..6143f87a008 100644 --- a/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button.js +++ b/lib/editor/atto/plugins/undo/yui/build/moodle-atto_undo-button/moodle-atto_undo-button.js @@ -138,9 +138,10 @@ M.atto_undo = M.atto_undo || { // Redo button. iconurl = M.util.image_url('e/redo', 'core'); M.editor_atto.add_toolbar_button(params.elementid, 'undo', iconurl, params.group, M.atto_undo.redo_handler, 'redo', M.util.get_string('redo', 'atto_undo')); + M.editor_atto.add_button_shortcut({action: 'redo', keys: 89}); } } }; -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); diff --git a/lib/editor/atto/plugins/undo/yui/src/button/js/button.js b/lib/editor/atto/plugins/undo/yui/src/button/js/button.js index 3b0be134eae..98d2f6cbc5c 100755 --- a/lib/editor/atto/plugins/undo/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/undo/yui/src/button/js/button.js @@ -136,6 +136,7 @@ M.atto_undo = M.atto_undo || { // Redo button. iconurl = M.util.image_url('e/redo', 'core'); M.editor_atto.add_toolbar_button(params.elementid, 'undo', iconurl, params.group, M.atto_undo.redo_handler, 'redo', M.util.get_string('redo', 'atto_undo')); + M.editor_atto.add_button_shortcut({action: 'redo', keys: 89}); } } }; diff --git a/lib/editor/atto/plugins/undo/yui/src/button/meta/button.json b/lib/editor/atto/plugins/undo/yui/src/button/meta/button.json index 59737f492c8..1e574b9dbaf 100755 --- a/lib/editor/atto/plugins/undo/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/undo/yui/src/button/meta/button.json @@ -1,5 +1,5 @@ { "moodle-atto_undo-button": { - "requires": ["node"] + "requires": ["node", "moodle-editor_atto-editor-shortcut"] } } diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-debug.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-debug.js new file mode 100644 index 00000000000..76a4c809646 --- /dev/null +++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-debug.js @@ -0,0 +1,263 @@ +YUI.add('moodle-editor_atto-editor-shortcut', function (Y, NAME) { + +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +var SHORTCUT, + SHORTCUTNAME = 'AttoButtonShortcut', + EVENTS = { + press: 'press' + }, + ATTRS = { + action: 'action', + eventtype: 'eventtype', + keys: 'keys' + }, + CSS = { + editorid: 'data-editor', + contenteditable: '.editor_atto_content' + }, + NS = 'moodle-editor_atto-editor-shortcut'; + +/** + * Atto editor shortcut class + * + * @namespace M.editor_atto + * @class Shortcut + * @constructor + * @extends Base + * @copyright 2014 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +SHORTCUT = function() { + SHORTCUT.superclass.constructor.apply(this, arguments); +}; +SHORTCUT.prototype = { + /** + * Initialises a new shortcut. + * @method initializer + */ + initializer: function() { + /** + * Shortcut Event: press. + * + * This event is fired when the user triggers the shortcut object by pressing the required keys. + * The event has a default function {@see execActionDefault()} that calls the browser to execute the action used + * when the shortcut is created. + * If you wish to provide your own functionality you need to add a listener to the shortcut you create for this + * event, and then when it is fired call e.preventDefault() on the event facade it provides. + * + * The event facade contains two custom properties: + * * elementid: The ID of the editor that is being acted upon. + * * origevent: The original event facade, should you need it for any reason (I hope not) + * + * @event press + */ + this.publish(EVENTS.press, { + emitFacade: true, + defaultFn: this.execActionDefault + }); + }, + /** + * Gets called when the user has triggered this shortcut. + * @method trigger + * @param {EventFacade} e + */ + trigger: function(e) { + e.preventDefault(); + var elementid = e.target.getAttribute(CSS.editorid); + this.fire(EVENTS.press, { + elementid: elementid, + origevent: e + }); + }, + /** + * Binds this shortcut to the editors being shown on the page. + * @method bind + * @chainable + * @param {Node} node + * @param {String} container CSS to select the container element to bind to. Usually the contenteditable element. + * @return {SHORTCUT} + */ + bind: function(node, container) { + var eventtype = this.get(ATTRS.eventtype), + keys = this.get(ATTRS.keys); + Y.one('body').delegate( + eventtype, // Event. + this.trigger, // Callback. + keys, // Keys. + container, // Delegated container. + this // Context. + ); + return this; + }, + /** + * The default action performed when this shortcut (or any) is triggered. + * + * This can be cancelled by attaching your own event listener to the press event published + * by this shortcut and then calling e.preventDefault() on the EventFacade it triggers. + * + * @method execActionDefault + * @param {EventFacade} e + */ + execActionDefault: function(e) { + var elementid = e.elementid; + if (!M.editor_atto.is_active(elementid)) { + M.editor_atto.focus(elementid); + } + document.execCommand(this.get(ATTRS.action), false, null); + // Clean the YUI ids from the HTML. + M.editor_atto.text_updated(elementid); + }, + + /** + * Returns the default meta key to use with a shortcut. + * @method getDefaultMeta + * @returns {string} + */ + getDefaultMeta: function() { + return (Y.UA.os === 'macintosh') ? '+meta' : '+ctrl'; + }, + + /** + * Returns the key event to use for this shortcut. + * @returns {string} + */ + getKeyEvent: function() { + return 'down:'; + } +}; +Y.extend(SHORTCUT, Y.Base, SHORTCUT.prototype, { + NAME: SHORTCUTNAME, + ATTRS: { + /** + * The action this shortcut is performing. + * If using the default functionality this should be the browser command to execute. + * @attribute action + * @type String + * @writeOnce + */ + action: { + writeOnce: 'init', + validator: function(val) { + return Y.Lang.isString(val); + } + }, + /** + * The key code(s) used to trigger the shortcut, should be something like `85` for u (underline). + * + * For a single char all you need to do is set the keys property to the char you want to map to a shortcut. + * If you need to do something more advanced (special combinations etc) you can specify a complete key set and + * then set the simplekeys property to false. + * + * Please note that if you do provide an complete char set the browser defaults can only be overridden on the key down + * event. A keypress is unfortunately good enough. + * + * @attribute keys + * @default false + * @type String|Bool + * @writeOnce + */ + keys: { + writeOnce: 'init', + value: false, + validator: function(val) { + return Y.Lang.isString(val) || Y.Lang.isNumber(val) || Y.Lang.isBoolean(val); + }, + getter: function(val) { + if (this.get('simplekeys')) { + return this.getKeyEvent() + val + this.getDefaultMeta(); + } + } + }, + /** + * The event type to trigger on. + * I can't imagine any good reason to override this, if you find one please let me know. + * @attribute eventtype + * @type String + * @writeOnce + * @default key + */ + eventtype: { + writeOnce: 'init', + value: 'key', + validator: function(val) { + return Y.Lang.isString(val); + } + }, + /** + * When set to true a simple key combination is being used and we'll have to append the correct type and control for it. + * + * Set this too off if you want to define the complete key combination for the shortcut yourself (advanced). + */ + simplekeys: { + value: true, + validator: function(val) { + return Y.Lang.isBoolean(val); + } + } + } +}); + +M.editor_atto = M.editor_atto || {}; +Y.mix(M.editor_atto, { + /** + * An associative collection of shortcut objects that have been bound to the editors on the page. + * @protected + * @namespace M.editor_atto + * @property shortcutdelegations + * @type Object + */ + shortcutdelegations: {}, + + /** + * Adds a button shortcut given a configuration object containing properties for it. + * + * The config object must contain at least action and keys. + * For more details see {@link SHORTCUT()} + * + * @static + * @namespace M.editor_atto + * @method add_button_shortcut + * @param {Object} config A configuration object containing at least action and keys. + * @return SHORTCUT + */ + add_button_shortcut: function(config) { + var shortcut = new SHORTCUT(config); + return this.register_button_shortcut(shortcut); + }, + + /** + * Registers a shortcut object and binds it to the editors being displayed on the current page. + * + * @static + * @namespace M.editor_atto + * @method register_button_shortcut + * @param {SHORTCUT} shortcut The shortcut object to add. + * @return SHORTCUT + */ + register_button_shortcut: function(shortcut) { + var action = shortcut.get(ATTRS.action), + keys = shortcut.get(ATTRS.keys); + if (!M.editor_atto.shortcutdelegations[action] && keys) { + Y.log('Atto shortcut registered: ' + keys + ' now triggers ' + action, 'debug', NS); + M.editor_atto.shortcutdelegations[action] = shortcut.bind(Y.one('body'), CSS.contenteditable); + } + return M.editor_atto.shortcutdelegations[action]; + } +}); + + +}, '@VERSION@', {"requires": ["node", "event", "event-custom", "moodle-editor_atto-editor"]}); diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-min.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-min.js new file mode 100644 index 00000000000..679b5f4ba69 --- /dev/null +++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-min.js @@ -0,0 +1 @@ +YUI.add("moodle-editor_atto-editor-shortcut",function(e,t){var n,r="AttoButtonShortcut",i={press:"press"},s={action:"action",eventtype:"eventtype",keys:"keys"},o={editorid:"data-editor",contenteditable:".editor_atto_content"},u="moodle-editor_atto-editor-shortcut";n=function(){n.superclass.constructor.apply(this,arguments)},n.prototype={initializer:function(){this.publish(i.press,{emitFacade:!0,defaultFn:this.execActionDefault})},trigger:function(e){e.preventDefault();var t=e.target.getAttribute(o.editorid);this.fire(i.press,{elementid:t,origevent:e})},bind:function(t,n){var r=this.get(s.eventtype),i=this.get(s.keys);return e.one("body").delegate(r,this.trigger,i,n,this),this},execActionDefault:function(e){var t=e.elementid;M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand(this.get(s.action),!1,null),M.editor_atto.text_updated(t)},getDefaultMeta:function(){return e.UA.os==="macintosh"?"+meta":"+ctrl"},getKeyEvent:function(){return"down:"}},e.extend(n,e.Base,n.prototype,{NAME:r,ATTRS:{action:{writeOnce:"init",validator:function(t){return e.Lang.isString(t)}},keys:{writeOnce:"init",value:!1,validator:function(t){return e.Lang.isString(t)||e.Lang.isNumber(t)||e.Lang.isBoolean(t)},getter:function(e){if(this.get("simplekeys"))return this.getKeyEvent()+e+this.getDefaultMeta()}},eventtype:{writeOnce:"init",value:"key",validator:function(t){return e.Lang.isString(t)}},simplekeys:{value:!0,validator:function(t){return e.Lang.isBoolean(t)}}}}),M.editor_atto=M.editor_atto||{},e.mix(M.editor_atto,{shortcutdelegations:{},add_button_shortcut:function(e){var t=new n(e);return this.register_button_shortcut(t)},register_button_shortcut:function(t){var n=t.get(s.action),r=t.get(s.keys);return!M.editor_atto.shortcutdelegations[n]&&r&&(M.editor_atto.shortcutdelegations[n]=t.bind(e.one("body"),o.contenteditable)),M.editor_atto.shortcutdelegations[n]}})},"@VERSION@",{requires:["node","event","event-custom","moodle-editor_atto-editor"]}); diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut.js new file mode 100644 index 00000000000..1ab16eb317f --- /dev/null +++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut.js @@ -0,0 +1,262 @@ +YUI.add('moodle-editor_atto-editor-shortcut', function (Y, NAME) { + +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +var SHORTCUT, + SHORTCUTNAME = 'AttoButtonShortcut', + EVENTS = { + press: 'press' + }, + ATTRS = { + action: 'action', + eventtype: 'eventtype', + keys: 'keys' + }, + CSS = { + editorid: 'data-editor', + contenteditable: '.editor_atto_content' + }, + NS = 'moodle-editor_atto-editor-shortcut'; + +/** + * Atto editor shortcut class + * + * @namespace M.editor_atto + * @class Shortcut + * @constructor + * @extends Base + * @copyright 2014 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +SHORTCUT = function() { + SHORTCUT.superclass.constructor.apply(this, arguments); +}; +SHORTCUT.prototype = { + /** + * Initialises a new shortcut. + * @method initializer + */ + initializer: function() { + /** + * Shortcut Event: press. + * + * This event is fired when the user triggers the shortcut object by pressing the required keys. + * The event has a default function {@see execActionDefault()} that calls the browser to execute the action used + * when the shortcut is created. + * If you wish to provide your own functionality you need to add a listener to the shortcut you create for this + * event, and then when it is fired call e.preventDefault() on the event facade it provides. + * + * The event facade contains two custom properties: + * * elementid: The ID of the editor that is being acted upon. + * * origevent: The original event facade, should you need it for any reason (I hope not) + * + * @event press + */ + this.publish(EVENTS.press, { + emitFacade: true, + defaultFn: this.execActionDefault + }); + }, + /** + * Gets called when the user has triggered this shortcut. + * @method trigger + * @param {EventFacade} e + */ + trigger: function(e) { + e.preventDefault(); + var elementid = e.target.getAttribute(CSS.editorid); + this.fire(EVENTS.press, { + elementid: elementid, + origevent: e + }); + }, + /** + * Binds this shortcut to the editors being shown on the page. + * @method bind + * @chainable + * @param {Node} node + * @param {String} container CSS to select the container element to bind to. Usually the contenteditable element. + * @return {SHORTCUT} + */ + bind: function(node, container) { + var eventtype = this.get(ATTRS.eventtype), + keys = this.get(ATTRS.keys); + Y.one('body').delegate( + eventtype, // Event. + this.trigger, // Callback. + keys, // Keys. + container, // Delegated container. + this // Context. + ); + return this; + }, + /** + * The default action performed when this shortcut (or any) is triggered. + * + * This can be cancelled by attaching your own event listener to the press event published + * by this shortcut and then calling e.preventDefault() on the EventFacade it triggers. + * + * @method execActionDefault + * @param {EventFacade} e + */ + execActionDefault: function(e) { + var elementid = e.elementid; + if (!M.editor_atto.is_active(elementid)) { + M.editor_atto.focus(elementid); + } + document.execCommand(this.get(ATTRS.action), false, null); + // Clean the YUI ids from the HTML. + M.editor_atto.text_updated(elementid); + }, + + /** + * Returns the default meta key to use with a shortcut. + * @method getDefaultMeta + * @returns {string} + */ + getDefaultMeta: function() { + return (Y.UA.os === 'macintosh') ? '+meta' : '+ctrl'; + }, + + /** + * Returns the key event to use for this shortcut. + * @returns {string} + */ + getKeyEvent: function() { + return 'down:'; + } +}; +Y.extend(SHORTCUT, Y.Base, SHORTCUT.prototype, { + NAME: SHORTCUTNAME, + ATTRS: { + /** + * The action this shortcut is performing. + * If using the default functionality this should be the browser command to execute. + * @attribute action + * @type String + * @writeOnce + */ + action: { + writeOnce: 'init', + validator: function(val) { + return Y.Lang.isString(val); + } + }, + /** + * The key code(s) used to trigger the shortcut, should be something like `85` for u (underline). + * + * For a single char all you need to do is set the keys property to the char you want to map to a shortcut. + * If you need to do something more advanced (special combinations etc) you can specify a complete key set and + * then set the simplekeys property to false. + * + * Please note that if you do provide an complete char set the browser defaults can only be overridden on the key down + * event. A keypress is unfortunately good enough. + * + * @attribute keys + * @default false + * @type String|Bool + * @writeOnce + */ + keys: { + writeOnce: 'init', + value: false, + validator: function(val) { + return Y.Lang.isString(val) || Y.Lang.isNumber(val) || Y.Lang.isBoolean(val); + }, + getter: function(val) { + if (this.get('simplekeys')) { + return this.getKeyEvent() + val + this.getDefaultMeta(); + } + } + }, + /** + * The event type to trigger on. + * I can't imagine any good reason to override this, if you find one please let me know. + * @attribute eventtype + * @type String + * @writeOnce + * @default key + */ + eventtype: { + writeOnce: 'init', + value: 'key', + validator: function(val) { + return Y.Lang.isString(val); + } + }, + /** + * When set to true a simple key combination is being used and we'll have to append the correct type and control for it. + * + * Set this too off if you want to define the complete key combination for the shortcut yourself (advanced). + */ + simplekeys: { + value: true, + validator: function(val) { + return Y.Lang.isBoolean(val); + } + } + } +}); + +M.editor_atto = M.editor_atto || {}; +Y.mix(M.editor_atto, { + /** + * An associative collection of shortcut objects that have been bound to the editors on the page. + * @protected + * @namespace M.editor_atto + * @property shortcutdelegations + * @type Object + */ + shortcutdelegations: {}, + + /** + * Adds a button shortcut given a configuration object containing properties for it. + * + * The config object must contain at least action and keys. + * For more details see {@link SHORTCUT()} + * + * @static + * @namespace M.editor_atto + * @method add_button_shortcut + * @param {Object} config A configuration object containing at least action and keys. + * @return SHORTCUT + */ + add_button_shortcut: function(config) { + var shortcut = new SHORTCUT(config); + return this.register_button_shortcut(shortcut); + }, + + /** + * Registers a shortcut object and binds it to the editors being displayed on the current page. + * + * @static + * @namespace M.editor_atto + * @method register_button_shortcut + * @param {SHORTCUT} shortcut The shortcut object to add. + * @return SHORTCUT + */ + register_button_shortcut: function(shortcut) { + var action = shortcut.get(ATTRS.action), + keys = shortcut.get(ATTRS.keys); + if (!M.editor_atto.shortcutdelegations[action] && keys) { + M.editor_atto.shortcutdelegations[action] = shortcut.bind(Y.one('body'), CSS.contenteditable); + } + return M.editor_atto.shortcutdelegations[action]; + } +}); + + +}, '@VERSION@', {"requires": ["node", "event", "event-custom", "moodle-editor_atto-editor"]}); 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 35d31ea5ad6..0522d98dd19 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 @@ -572,7 +572,8 @@ M.editor_atto = M.editor_atto || { 'role="textbox" ' + 'spellcheck="true" ' + 'aria-live="off" ' + - 'class="' + CSS.CONTENT + '" />'); + 'class="' + CSS.CONTENT + '" '+ + 'data-editor="' + params.elementid + '" />'); var toolbar = Y.Node.create(''),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('