diff --git a/lib/editor/atto/lib.php b/lib/editor/atto/lib.php index 3cb83d7f0a4..fafa9df3a20 100644 --- a/lib/editor/atto/lib.php +++ b/lib/editor/atto/lib.php @@ -113,7 +113,7 @@ class atto_texteditor extends texteditor { $extra = component_callback('atto_' . $plugin, 'params_for_js', array($elementid, $options, $fpoptions)); if ($extra) { - $jsplugin['params'] = $extra; + $jsplugin = array_merge($jsplugin, $extra); } // We always need the plugin name. $PAGE->requires->string_for_js('pluginname', 'atto_' . $plugin); @@ -123,7 +123,7 @@ class atto_texteditor extends texteditor { } $PAGE->requires->yui_module($modules, - 'M.editor_atto.init', + 'Y.M.editor_atto.Editor.init', array($this->get_init_params($elementid, $options, $fpoptions, $jsplugins))); } diff --git a/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button-debug.js b/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button-debug.js index f8eb598c803..9ed64e97419 100644 --- a/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button-debug.js +++ b/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button-debug.js @@ -15,106 +15,192 @@ YUI.add('moodle-atto_accessibilitychecker-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor accessibilitychecker plugin. - * - * This plugin adds some functions to do things that screen readers do not do well. - * Specifically, listing the active styles for the selected text, - * listing the images in the page, listing the links in the page. - * +/* * @package atto_accessibilitychecker * @copyright 2014 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_accessibilitychecker = M.atto_accessibilitychecker || { + +/** + * @module moodle-atto_accessibilitychecker-button + */ + +/** + * Accessibility Checking tool for the Atto editor. + * + * @namespace M.atto_accessibilitychecker + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENT = 'atto_accessibilitychecker'; + +Y.namespace('M.atto_accessibilitychecker').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The window used to display the accessibility ui. + * The warnings which are displayed. * - * @property dialogue - * @type M.core.dialogue - * @default null + * @property _displayedWarnings + * @type Object + * @private */ - dialogue : null, + _displayedWarnings: {}, - /** - * Array of nodes that have an accessibility problem - * - * @property displayedwarnings - * @type Array - * @default null - */ - displayedwarnings: [], - - /** - * Display the ui dialogue. - * - * @method init - * @param Event e - * @param string elementid - */ - display_ui : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - var dialogue; - if (!M.atto_accessibilitychecker.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true, - width: '800px' - }); - dialogue.set('headerContent', M.util.get_string('pluginname', 'atto_accessibilitychecker')); - dialogue.render(); - } else { - dialogue = M.atto_accessibilitychecker.dialogue; - // Clear the array of previously displayed warnings. - M.atto_accessibilitychecker.displayedwarnings = []; - } - - dialogue.set('bodyContent', M.atto_accessibilitychecker.get_report(elementid)); - dialogue.centerDialogue(); - - // Add ability to select problem areas in the editor. - Y.all('.accessibilitywarnings li').on('click', function(e) { - e.preventDefault(); - - var index = e.target.getAttribute("data-index"); - var node = M.atto_accessibilitychecker.displayedwarnings[index]; - - M.atto_accessibilitychecker.dialogue.hide(); - if (node) { - M.editor_atto.set_selection(M.editor_atto.get_selection_from_node(node)); - } + initializer: function() { + this.addButton({ + icon: 'e/accessibility_checker', + callback: this._displayDialogue }); - - dialogue.show(); - M.atto_accessibilitychecker.dialogue = dialogue; }, /** - * Add this button to the form. + * Display the Accessibility Checker tool. * - * @method init - * @param {Object} params + * @method _displayDialogue + * @private */ - init : function(params) { - var iconurl = M.util.image_url('e/visual_blocks', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'accessibilitychecker', iconurl, params.group, this.display_ui); + _displayDialogue: function() { + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('pluginname', COMPONENT), + width: '800px', + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var content = Y.Node.create('
'); + content.append(this._getWarnings()); + + // Add ability to select problem areas in the editor. + content.delegate('click', function(e) { + e.preventDefault(); + + var host = this.get('host'), + index = e.target.getAttribute("data-index"), + node = this._displayedWarnings[index], + dialogue = this.getDialogue(); + + + if (node) { + // Clear the dialogue's focusAfterHide to ensure we focus + // on the selection. + dialogue.set('focusAfterHide', null); + + // Hide the dialogue. + dialogue.hide(); + + // Then set the selection. + host.setSelection(host.getSelectionFromNode(node)); + } else { + // Hide the dialogue. + dialogue.hide(); + } + }, 'a', this); + + return content; + }, + + /** + * Find all problems with the content editable region. + * + * @method _getWarnings + * @return {Node} A complete list of all warnings and problems. + * @private + */ + _getWarnings: function() { + var problemNodes, + list = Y.Node.create('
'); + + // Images with no alt text or dodgy alt text. + problemNodes = []; + this.editor.all('img').each(function (img) { + alt = img.getAttribute('alt'); + if (typeof alt === 'undefined' || alt === '') { + if (img.getAttribute('role') !== 'presentation') { + problemNodes.push(img); + } + } + }, this); + this._addWarnings(list, M.util.get_string('imagesmissingalt', COMPONENT), problemNodes, true); + + problemNodes = []; + this.editor.all('*').each(function (node) { + var foreground, + background, + ratio, + lum1, + lum2; + + // Check for non-empty text. + if (Y.Lang.trim(node.get('text')) !== '') { + foreground = node.getComputedStyle('color'); + background = node.getComputedStyle('backgroundColor'); + + lum1 = this._getLuminanceFromCssColor(foreground); + lum2 = this._getLuminanceFromCssColor(background); + + // Algorithm from "http://www.w3.org/TR/WCAG20-GENERAL/G18.html". + if (lum1 > lum2) { + ratio = (lum1 + 0.05) / (lum2 + 0.05); + } else { + ratio = (lum2 + 0.05) / (lum1 + 0.05); + } + if (ratio <= 4.5) { + Y.log('Contrast ratio is too low: ' + ratio + + ' Colour 1: ' + foreground + + ' Colour 2: ' + background + + ' Luminance 1: ' + lum1 + + ' Luminance 2: ' + lum2); + + // We only want the highest node with dodgy contrast reported. + var i = 0, found = false; + for (i = 0; i < problemNodes.length; i++) { + if (node.ancestors('*').indexOf(problemNodes[i]) !== -1) { + // Do not add node - it already has a parent in the list. + found = true; + break; + } else if (problemNodes[i].ancestors('*').indexOf(node) !== -1) { + // Replace the existing node with this one because it is higher up the DOM. + problemNodes[i] = node; + found = true; + break; + } + } + if (!found) { + problemNodes.push(node); + } + } + } + }, this); + this._addWarnings(list, M.util.get_string('needsmorecontrast', COMPONENT), problemNodes, false); + + if (!list.hasChildNodes()) { + list.append('

' + M.util.get_string('nowarnings', COMPONENT) + '

'); + } + // Append the list of current styles. + return list; }, /** * Generate the HTML that lists the found warnings. * - * @method add_warnings - * @param Y.Node list - node to append the html to. - * @param String description - description of this failure. - * @param Y.Node[] nodes - list of failing nodes. - * @param boolean imagewarnings - true if the warnings are related to images, false if text. + * @method _addWarnings + * @param {Node} A Node to append the html to. + * @param {String} description Description of this failure. + * @param {array} nodes An array of failing nodes. + * @param {boolean} imagewarnings true if the warnings are related to images, false if text. */ - add_warnings : function(list, description, nodes, imagewarnings) { + _addWarnings: function(list, description, nodes, imagewarnings) { var warning, fails, i, key, src, textfield; if (nodes.length > 0) { @@ -128,12 +214,12 @@ M.atto_accessibilitychecker = M.atto_accessibilitychecker || { fails.append(Y.Node.create('
  • '+src+'
  • ')); } else { - key = 'text_'+i; + key = 'text_' + i; textfield = ('innerText' in nodes[i])? 'innerText' : 'textContent'; fails.append(Y.Node.create('
  • ' + nodes[i].get(textfield) + '
  • ')); } - M.atto_accessibilitychecker.displayedwarnings[key] = nodes[i]; + this._displayedWarnings[key] = nodes[i]; } warning.append(fails); @@ -142,13 +228,14 @@ M.atto_accessibilitychecker = M.atto_accessibilitychecker || { }, /** - * Convert a css color to a luminance value. + * Convert a CSS color to a luminance value. * - * @method get_luminance_from_css_color - * @param {String} colortext - * @return {Integer} + * @method _getLuminanceFromCssColor + * @param {String} colortext The Hex value for the colour + * @return {Number} The luminance value. + * @private */ - get_luminance_from_css_color : function(colortext) { + _getLuminanceFromCssColor: function(colortext) { var color; if (colortext === 'transparent') { @@ -172,110 +259,8 @@ M.atto_accessibilitychecker = M.atto_accessibilitychecker || { b1 = part1(color[2]); return 0.2126 * r1 + 0.7152 * g1 + 0.0722 * b1; - }, - - /** - * List the accessibility warnings for the current editor - * - * @method list_warnings - * @param string elementid - * @return String - */ - list_warnings : function(elementid) { - - var list = Y.Node.create('
    '); - - var editable = M.editor_atto.get_editable_node(elementid); - - var problemnodes = []; - - // Images with no alt text or dodgy alt text. - var alt; - editable.all('img').each(function (img) { - alt = img.getAttribute('alt'); - if (typeof alt === 'undefined' || alt === '') { - if (img.getAttribute('role') !== 'presentation') { - problemnodes.push(img); - } - } - }, this); - - this.add_warnings(list, M.util.get_string('imagesmissingalt', 'atto_accessibilitychecker'), problemnodes, true); - - // Contrast ratios. - problemnodes = []; - var foreground, background, lum1, lum2, ratio; - editable.all('*').each(function (node) { - // Check for non-empty text. - if (Y.Lang.trim(node.get('text')) !== '') { - foreground = node.getComputedStyle('color'); - background = node.getComputedStyle('backgroundColor'); - - lum1 = this.get_luminance_from_css_color(foreground); - lum2 = this.get_luminance_from_css_color(background); - - // Algorithm from "http://www.w3.org/TR/WCAG20-GENERAL/G18.html". - if (lum1 > lum2) { - ratio = (lum1 + 0.05) / (lum2 + 0.05); - } else { - ratio = (lum2 + 0.05) / (lum1 + 0.05); - } - if (ratio <= 4.5) { - Y.log('Contrast ratio is too low: ' + ratio + - ' Colour 1: ' + foreground + - ' Colour 2: ' + background + - ' Luminance 1: ' + lum1 + - ' Luminance 2: ' + lum2); - - // We only want the highest node with dodgy contrast reported. - var i = 0, found = false; - for (i = 0; i < problemnodes.length; i++) { - if (node.ancestors('*').indexOf(problemnodes[i]) !== -1) { - // Do not add node - it already has a parent in the list. - found = true; - break; - } else if (problemnodes[i].ancestors('*').indexOf(node) !== -1) { - // Replace the existing node with this one because it is higher up the DOM. - problemnodes[i] = node; - found = true; - break; - } - } - if (!found) { - problemnodes.push(node); - } - } - } - }, this); - - this.add_warnings(list, M.util.get_string('needsmorecontrast', 'atto_accessibilitychecker'), problemnodes, false); - - if (!list.hasChildNodes()) { - list.append('

    ' + M.util.get_string('nowarnings', 'atto_accessibilitychecker') + '

    '); - } - // Append the list of current styles. - return list; - }, - - /** - * Return the HTML of the form to show in the dialogue. - * - * @method get_report - * @param string elementid - * @return string - */ - get_report : function(elementid) { - // Current styles. - var html = '
    '; - - var content = Y.Node.create(html); - - content.append(this.list_warnings(elementid)); - - return content; } - -}; +}); -}, '@VERSION@', {"requires": ["node", "escape", "color-base"]}); +}, '@VERSION@', {"requires": ["color-base", "moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button-min.js b/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button-min.js index 8b64be89ebf..aaab0815bef 100644 --- a/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button-min.js +++ b/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_accessibilitychecker-button",function(e,t){M.atto_accessibilitychecker=M.atto_accessibilitychecker||{dialogue:null,displayedwarnings:[],display_ui:function(t,n){t.preventDefault(),M.editor_atto.is_active(n)||M.editor_atto.focus(n);var r;M.atto_accessibilitychecker.dialogue?(r=M.atto_accessibilitychecker.dialogue,M.atto_accessibilitychecker.displayedwarnings=[]):(r=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0,width:"800px"}),r.set("headerContent",M.util.get_string("pluginname","atto_accessibilitychecker")),r.render()),r.set("bodyContent",M.atto_accessibilitychecker.get_report(n)),r.centerDialogue(),e.all(".accessibilitywarnings li").on("click",function(e){e.preventDefault();var t=e.target.getAttribute("data-index"),n=M.atto_accessibilitychecker.displayedwarnings[t];M.atto_accessibilitychecker.dialogue.hide(),n&&M.editor_atto.set_selection(M.editor_atto.get_selection_from_node(n))}),r.show(),M.atto_accessibilitychecker.dialogue=r},init:function(e){var t=M.util.image_url("e/visual_blocks","core");M.editor_atto.add_toolbar_button(e.elementid,"accessibilitychecker",t,e.group,this.display_ui)},add_warnings:function(t,n,r,i){var s,o,u,a,f,l;if(r.length>0){s=e.Node.create("

    "+n+"

    "),o=e.Node.create('
      '),u=0;for(u=0;u '+f+""))):(a="text_"+u,l="innerText"in r[u]?"innerText":"textContent",o.append(e.Node.create('
    1. '+r[u].get(l)+"
    2. "))),M.atto_accessibilitychecker.displayedwarnings[a]=r[u];s.append(o),t.append(s)}},get_luminance_from_css_color:function(t){var n;t==="transparent"&&(t="#ffffff"),n=e.Color.toArray(e.Color.toRGB(t));var r=function(e){return e=parseInt(e,10)/255,e<=.03928?e/=12.92:e=Math.pow((e+.055)/1.055,2.4),e},i=r(n[0]),s=r(n[1]),o=r(n[2]);return.2126*i+.7152*s+.0722*o},list_warnings:function(t){var n=e.Node.create("
      "),r=M.editor_atto.get_editable_node(t),i=[],s;r.all("img").each(function(e){s=e.getAttribute("alt"),(typeof s=="undefined"||s==="")&&e.getAttribute("role")!=="presentation"&&i.push(e)},this),this.add_warnings(n,M.util.get_string("imagesmissingalt","atto_accessibilitychecker"),i,!0),i=[];var o,u,a,f,l;return r.all("*").each(function(t){if(e.Lang.trim(t.get("text"))!==""){o=t.getComputedStyle("color"),u=t.getComputedStyle("backgroundColor"),a=this.get_luminance_from_css_color(o),f=this.get_luminance_from_css_color(u),a>f?l=(a+.05)/(f+.05):l=(f+.05)/(a+.05);if(l<=4.5){var n=0,r=!1;for(n=0;n"+M.util.get_string("nowarnings","atto_accessibilitychecker")+"

      "),n},get_report:function(t){var n='
      ',r=e.Node.create(n);return r.append(this.list_warnings(t)),r}}},"@VERSION@",{requires:["node","escape","color-base"]}); +YUI.add("moodle-atto_accessibilitychecker-button",function(e,t){var n="atto_accessibilitychecker";e.namespace("M.atto_accessibilitychecker").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_displayedWarnings:{},initializer:function(){this.addButton({icon:"e/accessibility_checker",callback:this._displayDialogue})},_displayDialogue:function(){var e=this.getDialogue({headerContent:M.util.get_string("pluginname",n),width:"800px",focusAfterHide:!0});e.set("bodyContent",this._getDialogueContent()).show()},_getDialogueContent:function(){var t=e.Node.create('
      ');return t.append(this._getWarnings()),t.delegate("click",function(e){e.preventDefault();var t=this.get("host"),n=e.target.getAttribute("data-index"),r=this._displayedWarnings[n],i=this.getDialogue();r?(i.set("focusAfterHide",null),i.hide(),t.setSelection(t.getSelectionFromNode(r))):i.hide()},"a",this),t},_getWarnings:function(){var t,r=e.Node.create("
      ");return t=[],this.editor.all("img").each(function(e){alt=e.getAttribute("alt"),(typeof alt=="undefined"||alt==="")&&e.getAttribute("role")!=="presentation"&&t.push(e)},this),this._addWarnings(r,M.util.get_string("imagesmissingalt",n),t,!0),t=[],this.editor.all("*").each(function(n){var r,i,s,o,u;if(e.Lang.trim(n.get("text"))!==""){r=n.getComputedStyle("color"),i=n.getComputedStyle("backgroundColor"),o=this._getLuminanceFromCssColor(r),u=this._getLuminanceFromCssColor(i),o>u?s=(o+.05)/(u+.05):s=(u+.05)/(o+.05);if(s<=4.5){var a=0,f=!1;for(a=0;a"+M.util.get_string("nowarnings",n)+"

      "),r},_addWarnings:function(t,n,r,i){var s,o,u,a,f,l;if(r.length>0){s=e.Node.create("

      "+n+"

      "),o=e.Node.create('
        '),u=0;for(u=0;u '+f+""))):(a="text_"+u,l="innerText"in r[u]?"innerText":"textContent",o.append(e.Node.create('
      1. '+r[u].get(l)+"
      2. "))),this._displayedWarnings[a]=r[u];s.append(o),t.append(s)}},_getLuminanceFromCssColor:function(t){var n;t==="transparent"&&(t="#ffffff"),n=e.Color.toArray(e.Color.toRGB(t));var r=function(e){return e=parseInt(e,10)/255,e<=.03928?e/=12.92:e=Math.pow((e+.055)/1.055,2.4),e},i=r(n[0]),s=r(n[1]),o=r(n[2]);return.2126*i+.7152*s+.0722*o}})},"@VERSION@",{requires:["color-base","moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button.js b/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button.js index 860f5b48351..307129035aa 100644 --- a/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button.js +++ b/lib/editor/atto/plugins/accessibilitychecker/yui/build/moodle-atto_accessibilitychecker-button/moodle-atto_accessibilitychecker-button.js @@ -15,106 +15,187 @@ YUI.add('moodle-atto_accessibilitychecker-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor accessibilitychecker plugin. - * - * This plugin adds some functions to do things that screen readers do not do well. - * Specifically, listing the active styles for the selected text, - * listing the images in the page, listing the links in the page. - * +/* * @package atto_accessibilitychecker * @copyright 2014 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_accessibilitychecker = M.atto_accessibilitychecker || { + +/** + * @module moodle-atto_accessibilitychecker-button + */ + +/** + * Accessibility Checking tool for the Atto editor. + * + * @namespace M.atto_accessibilitychecker + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENT = 'atto_accessibilitychecker'; + +Y.namespace('M.atto_accessibilitychecker').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The window used to display the accessibility ui. + * The warnings which are displayed. * - * @property dialogue - * @type M.core.dialogue - * @default null + * @property _displayedWarnings + * @type Object + * @private */ - dialogue : null, + _displayedWarnings: {}, - /** - * Array of nodes that have an accessibility problem - * - * @property displayedwarnings - * @type Array - * @default null - */ - displayedwarnings: [], - - /** - * Display the ui dialogue. - * - * @method init - * @param Event e - * @param string elementid - */ - display_ui : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - var dialogue; - if (!M.atto_accessibilitychecker.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true, - width: '800px' - }); - dialogue.set('headerContent', M.util.get_string('pluginname', 'atto_accessibilitychecker')); - dialogue.render(); - } else { - dialogue = M.atto_accessibilitychecker.dialogue; - // Clear the array of previously displayed warnings. - M.atto_accessibilitychecker.displayedwarnings = []; - } - - dialogue.set('bodyContent', M.atto_accessibilitychecker.get_report(elementid)); - dialogue.centerDialogue(); - - // Add ability to select problem areas in the editor. - Y.all('.accessibilitywarnings li').on('click', function(e) { - e.preventDefault(); - - var index = e.target.getAttribute("data-index"); - var node = M.atto_accessibilitychecker.displayedwarnings[index]; - - M.atto_accessibilitychecker.dialogue.hide(); - if (node) { - M.editor_atto.set_selection(M.editor_atto.get_selection_from_node(node)); - } + initializer: function() { + this.addButton({ + icon: 'e/accessibility_checker', + callback: this._displayDialogue }); - - dialogue.show(); - M.atto_accessibilitychecker.dialogue = dialogue; }, /** - * Add this button to the form. + * Display the Accessibility Checker tool. * - * @method init - * @param {Object} params + * @method _displayDialogue + * @private */ - init : function(params) { - var iconurl = M.util.image_url('e/visual_blocks', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'accessibilitychecker', iconurl, params.group, this.display_ui); + _displayDialogue: function() { + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('pluginname', COMPONENT), + width: '800px', + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var content = Y.Node.create('
        '); + content.append(this._getWarnings()); + + // Add ability to select problem areas in the editor. + content.delegate('click', function(e) { + e.preventDefault(); + + var host = this.get('host'), + index = e.target.getAttribute("data-index"), + node = this._displayedWarnings[index], + dialogue = this.getDialogue(); + + + if (node) { + // Clear the dialogue's focusAfterHide to ensure we focus + // on the selection. + dialogue.set('focusAfterHide', null); + + // Hide the dialogue. + dialogue.hide(); + + // Then set the selection. + host.setSelection(host.getSelectionFromNode(node)); + } else { + // Hide the dialogue. + dialogue.hide(); + } + }, 'a', this); + + return content; + }, + + /** + * Find all problems with the content editable region. + * + * @method _getWarnings + * @return {Node} A complete list of all warnings and problems. + * @private + */ + _getWarnings: function() { + var problemNodes, + list = Y.Node.create('
        '); + + // Images with no alt text or dodgy alt text. + problemNodes = []; + this.editor.all('img').each(function (img) { + alt = img.getAttribute('alt'); + if (typeof alt === 'undefined' || alt === '') { + if (img.getAttribute('role') !== 'presentation') { + problemNodes.push(img); + } + } + }, this); + this._addWarnings(list, M.util.get_string('imagesmissingalt', COMPONENT), problemNodes, true); + + problemNodes = []; + this.editor.all('*').each(function (node) { + var foreground, + background, + ratio, + lum1, + lum2; + + // Check for non-empty text. + if (Y.Lang.trim(node.get('text')) !== '') { + foreground = node.getComputedStyle('color'); + background = node.getComputedStyle('backgroundColor'); + + lum1 = this._getLuminanceFromCssColor(foreground); + lum2 = this._getLuminanceFromCssColor(background); + + // Algorithm from "http://www.w3.org/TR/WCAG20-GENERAL/G18.html". + if (lum1 > lum2) { + ratio = (lum1 + 0.05) / (lum2 + 0.05); + } else { + ratio = (lum2 + 0.05) / (lum1 + 0.05); + } + if (ratio <= 4.5) { + + // We only want the highest node with dodgy contrast reported. + var i = 0, found = false; + for (i = 0; i < problemNodes.length; i++) { + if (node.ancestors('*').indexOf(problemNodes[i]) !== -1) { + // Do not add node - it already has a parent in the list. + found = true; + break; + } else if (problemNodes[i].ancestors('*').indexOf(node) !== -1) { + // Replace the existing node with this one because it is higher up the DOM. + problemNodes[i] = node; + found = true; + break; + } + } + if (!found) { + problemNodes.push(node); + } + } + } + }, this); + this._addWarnings(list, M.util.get_string('needsmorecontrast', COMPONENT), problemNodes, false); + + if (!list.hasChildNodes()) { + list.append('

        ' + M.util.get_string('nowarnings', COMPONENT) + '

        '); + } + // Append the list of current styles. + return list; }, /** * Generate the HTML that lists the found warnings. * - * @method add_warnings - * @param Y.Node list - node to append the html to. - * @param String description - description of this failure. - * @param Y.Node[] nodes - list of failing nodes. - * @param boolean imagewarnings - true if the warnings are related to images, false if text. + * @method _addWarnings + * @param {Node} A Node to append the html to. + * @param {String} description Description of this failure. + * @param {array} nodes An array of failing nodes. + * @param {boolean} imagewarnings true if the warnings are related to images, false if text. */ - add_warnings : function(list, description, nodes, imagewarnings) { + _addWarnings: function(list, description, nodes, imagewarnings) { var warning, fails, i, key, src, textfield; if (nodes.length > 0) { @@ -128,12 +209,12 @@ M.atto_accessibilitychecker = M.atto_accessibilitychecker || { fails.append(Y.Node.create('
      3. '+src+'
      4. ')); } else { - key = 'text_'+i; + key = 'text_' + i; textfield = ('innerText' in nodes[i])? 'innerText' : 'textContent'; fails.append(Y.Node.create('
      5. ' + nodes[i].get(textfield) + '
      6. ')); } - M.atto_accessibilitychecker.displayedwarnings[key] = nodes[i]; + this._displayedWarnings[key] = nodes[i]; } warning.append(fails); @@ -142,13 +223,14 @@ M.atto_accessibilitychecker = M.atto_accessibilitychecker || { }, /** - * Convert a css color to a luminance value. + * Convert a CSS color to a luminance value. * - * @method get_luminance_from_css_color - * @param {String} colortext - * @return {Integer} + * @method _getLuminanceFromCssColor + * @param {String} colortext The Hex value for the colour + * @return {Number} The luminance value. + * @private */ - get_luminance_from_css_color : function(colortext) { + _getLuminanceFromCssColor: function(colortext) { var color; if (colortext === 'transparent') { @@ -172,105 +254,8 @@ M.atto_accessibilitychecker = M.atto_accessibilitychecker || { b1 = part1(color[2]); return 0.2126 * r1 + 0.7152 * g1 + 0.0722 * b1; - }, - - /** - * List the accessibility warnings for the current editor - * - * @method list_warnings - * @param string elementid - * @return String - */ - list_warnings : function(elementid) { - - var list = Y.Node.create('
        '); - - var editable = M.editor_atto.get_editable_node(elementid); - - var problemnodes = []; - - // Images with no alt text or dodgy alt text. - var alt; - editable.all('img').each(function (img) { - alt = img.getAttribute('alt'); - if (typeof alt === 'undefined' || alt === '') { - if (img.getAttribute('role') !== 'presentation') { - problemnodes.push(img); - } - } - }, this); - - this.add_warnings(list, M.util.get_string('imagesmissingalt', 'atto_accessibilitychecker'), problemnodes, true); - - // Contrast ratios. - problemnodes = []; - var foreground, background, lum1, lum2, ratio; - editable.all('*').each(function (node) { - // Check for non-empty text. - if (Y.Lang.trim(node.get('text')) !== '') { - foreground = node.getComputedStyle('color'); - background = node.getComputedStyle('backgroundColor'); - - lum1 = this.get_luminance_from_css_color(foreground); - lum2 = this.get_luminance_from_css_color(background); - - // Algorithm from "http://www.w3.org/TR/WCAG20-GENERAL/G18.html". - if (lum1 > lum2) { - ratio = (lum1 + 0.05) / (lum2 + 0.05); - } else { - ratio = (lum2 + 0.05) / (lum1 + 0.05); - } - if (ratio <= 4.5) { - - // We only want the highest node with dodgy contrast reported. - var i = 0, found = false; - for (i = 0; i < problemnodes.length; i++) { - if (node.ancestors('*').indexOf(problemnodes[i]) !== -1) { - // Do not add node - it already has a parent in the list. - found = true; - break; - } else if (problemnodes[i].ancestors('*').indexOf(node) !== -1) { - // Replace the existing node with this one because it is higher up the DOM. - problemnodes[i] = node; - found = true; - break; - } - } - if (!found) { - problemnodes.push(node); - } - } - } - }, this); - - this.add_warnings(list, M.util.get_string('needsmorecontrast', 'atto_accessibilitychecker'), problemnodes, false); - - if (!list.hasChildNodes()) { - list.append('

        ' + M.util.get_string('nowarnings', 'atto_accessibilitychecker') + '

        '); - } - // Append the list of current styles. - return list; - }, - - /** - * Return the HTML of the form to show in the dialogue. - * - * @method get_report - * @param string elementid - * @return string - */ - get_report : function(elementid) { - // Current styles. - var html = '
        '; - - var content = Y.Node.create(html); - - content.append(this.list_warnings(elementid)); - - return content; } - -}; +}); -}, '@VERSION@', {"requires": ["node", "escape", "color-base"]}); +}, '@VERSION@', {"requires": ["color-base", "moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/accessibilitychecker/yui/src/button/js/button.js b/lib/editor/atto/plugins/accessibilitychecker/yui/src/button/js/button.js index b1f87aa5b91..89ed9850ae3 100644 --- a/lib/editor/atto/plugins/accessibilitychecker/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/accessibilitychecker/yui/src/button/js/button.js @@ -13,106 +13,192 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor accessibilitychecker plugin. - * - * This plugin adds some functions to do things that screen readers do not do well. - * Specifically, listing the active styles for the selected text, - * listing the images in the page, listing the links in the page. - * +/* * @package atto_accessibilitychecker * @copyright 2014 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_accessibilitychecker = M.atto_accessibilitychecker || { + +/** + * @module moodle-atto_accessibilitychecker-button + */ + +/** + * Accessibility Checking tool for the Atto editor. + * + * @namespace M.atto_accessibilitychecker + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENT = 'atto_accessibilitychecker'; + +Y.namespace('M.atto_accessibilitychecker').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The window used to display the accessibility ui. + * The warnings which are displayed. * - * @property dialogue - * @type M.core.dialogue - * @default null + * @property _displayedWarnings + * @type Object + * @private */ - dialogue : null, + _displayedWarnings: {}, - /** - * Array of nodes that have an accessibility problem - * - * @property displayedwarnings - * @type Array - * @default null - */ - displayedwarnings: [], - - /** - * Display the ui dialogue. - * - * @method init - * @param Event e - * @param string elementid - */ - display_ui : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - var dialogue; - if (!M.atto_accessibilitychecker.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true, - width: '800px' - }); - dialogue.set('headerContent', M.util.get_string('pluginname', 'atto_accessibilitychecker')); - dialogue.render(); - } else { - dialogue = M.atto_accessibilitychecker.dialogue; - // Clear the array of previously displayed warnings. - M.atto_accessibilitychecker.displayedwarnings = []; - } - - dialogue.set('bodyContent', M.atto_accessibilitychecker.get_report(elementid)); - dialogue.centerDialogue(); - - // Add ability to select problem areas in the editor. - Y.all('.accessibilitywarnings li').on('click', function(e) { - e.preventDefault(); - - var index = e.target.getAttribute("data-index"); - var node = M.atto_accessibilitychecker.displayedwarnings[index]; - - M.atto_accessibilitychecker.dialogue.hide(); - if (node) { - M.editor_atto.set_selection(M.editor_atto.get_selection_from_node(node)); - } + initializer: function() { + this.addButton({ + icon: 'e/accessibility_checker', + callback: this._displayDialogue }); - - dialogue.show(); - M.atto_accessibilitychecker.dialogue = dialogue; }, /** - * Add this button to the form. + * Display the Accessibility Checker tool. * - * @method init - * @param {Object} params + * @method _displayDialogue + * @private */ - init : function(params) { - var iconurl = M.util.image_url('e/visual_blocks', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'accessibilitychecker', iconurl, params.group, this.display_ui); + _displayDialogue: function() { + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('pluginname', COMPONENT), + width: '800px', + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var content = Y.Node.create('
        '); + content.append(this._getWarnings()); + + // Add ability to select problem areas in the editor. + content.delegate('click', function(e) { + e.preventDefault(); + + var host = this.get('host'), + index = e.target.getAttribute("data-index"), + node = this._displayedWarnings[index], + dialogue = this.getDialogue(); + + + if (node) { + // Clear the dialogue's focusAfterHide to ensure we focus + // on the selection. + dialogue.set('focusAfterHide', null); + + // Hide the dialogue. + dialogue.hide(); + + // Then set the selection. + host.setSelection(host.getSelectionFromNode(node)); + } else { + // Hide the dialogue. + dialogue.hide(); + } + }, 'a', this); + + return content; + }, + + /** + * Find all problems with the content editable region. + * + * @method _getWarnings + * @return {Node} A complete list of all warnings and problems. + * @private + */ + _getWarnings: function() { + var problemNodes, + list = Y.Node.create('
        '); + + // Images with no alt text or dodgy alt text. + problemNodes = []; + this.editor.all('img').each(function (img) { + alt = img.getAttribute('alt'); + if (typeof alt === 'undefined' || alt === '') { + if (img.getAttribute('role') !== 'presentation') { + problemNodes.push(img); + } + } + }, this); + this._addWarnings(list, M.util.get_string('imagesmissingalt', COMPONENT), problemNodes, true); + + problemNodes = []; + this.editor.all('*').each(function (node) { + var foreground, + background, + ratio, + lum1, + lum2; + + // Check for non-empty text. + if (Y.Lang.trim(node.get('text')) !== '') { + foreground = node.getComputedStyle('color'); + background = node.getComputedStyle('backgroundColor'); + + lum1 = this._getLuminanceFromCssColor(foreground); + lum2 = this._getLuminanceFromCssColor(background); + + // Algorithm from "http://www.w3.org/TR/WCAG20-GENERAL/G18.html". + if (lum1 > lum2) { + ratio = (lum1 + 0.05) / (lum2 + 0.05); + } else { + ratio = (lum2 + 0.05) / (lum1 + 0.05); + } + if (ratio <= 4.5) { + Y.log('Contrast ratio is too low: ' + ratio + + ' Colour 1: ' + foreground + + ' Colour 2: ' + background + + ' Luminance 1: ' + lum1 + + ' Luminance 2: ' + lum2); + + // We only want the highest node with dodgy contrast reported. + var i = 0, found = false; + for (i = 0; i < problemNodes.length; i++) { + if (node.ancestors('*').indexOf(problemNodes[i]) !== -1) { + // Do not add node - it already has a parent in the list. + found = true; + break; + } else if (problemNodes[i].ancestors('*').indexOf(node) !== -1) { + // Replace the existing node with this one because it is higher up the DOM. + problemNodes[i] = node; + found = true; + break; + } + } + if (!found) { + problemNodes.push(node); + } + } + } + }, this); + this._addWarnings(list, M.util.get_string('needsmorecontrast', COMPONENT), problemNodes, false); + + if (!list.hasChildNodes()) { + list.append('

        ' + M.util.get_string('nowarnings', COMPONENT) + '

        '); + } + // Append the list of current styles. + return list; }, /** * Generate the HTML that lists the found warnings. * - * @method add_warnings - * @param Y.Node list - node to append the html to. - * @param String description - description of this failure. - * @param Y.Node[] nodes - list of failing nodes. - * @param boolean imagewarnings - true if the warnings are related to images, false if text. + * @method _addWarnings + * @param {Node} A Node to append the html to. + * @param {String} description Description of this failure. + * @param {array} nodes An array of failing nodes. + * @param {boolean} imagewarnings true if the warnings are related to images, false if text. */ - add_warnings : function(list, description, nodes, imagewarnings) { + _addWarnings: function(list, description, nodes, imagewarnings) { var warning, fails, i, key, src, textfield; if (nodes.length > 0) { @@ -126,12 +212,12 @@ M.atto_accessibilitychecker = M.atto_accessibilitychecker || { fails.append(Y.Node.create('
      7. '+src+'
      8. ')); } else { - key = 'text_'+i; + key = 'text_' + i; textfield = ('innerText' in nodes[i])? 'innerText' : 'textContent'; fails.append(Y.Node.create('
      9. ' + nodes[i].get(textfield) + '
      10. ')); } - M.atto_accessibilitychecker.displayedwarnings[key] = nodes[i]; + this._displayedWarnings[key] = nodes[i]; } warning.append(fails); @@ -140,13 +226,14 @@ M.atto_accessibilitychecker = M.atto_accessibilitychecker || { }, /** - * Convert a css color to a luminance value. + * Convert a CSS color to a luminance value. * - * @method get_luminance_from_css_color - * @param {String} colortext - * @return {Integer} + * @method _getLuminanceFromCssColor + * @param {String} colortext The Hex value for the colour + * @return {Number} The luminance value. + * @private */ - get_luminance_from_css_color : function(colortext) { + _getLuminanceFromCssColor: function(colortext) { var color; if (colortext === 'transparent') { @@ -170,107 +257,5 @@ M.atto_accessibilitychecker = M.atto_accessibilitychecker || { b1 = part1(color[2]); return 0.2126 * r1 + 0.7152 * g1 + 0.0722 * b1; - }, - - /** - * List the accessibility warnings for the current editor - * - * @method list_warnings - * @param string elementid - * @return String - */ - list_warnings : function(elementid) { - - var list = Y.Node.create('
        '); - - var editable = M.editor_atto.get_editable_node(elementid); - - var problemnodes = []; - - // Images with no alt text or dodgy alt text. - var alt; - editable.all('img').each(function (img) { - alt = img.getAttribute('alt'); - if (typeof alt === 'undefined' || alt === '') { - if (img.getAttribute('role') !== 'presentation') { - problemnodes.push(img); - } - } - }, this); - - this.add_warnings(list, M.util.get_string('imagesmissingalt', 'atto_accessibilitychecker'), problemnodes, true); - - // Contrast ratios. - problemnodes = []; - var foreground, background, lum1, lum2, ratio; - editable.all('*').each(function (node) { - // Check for non-empty text. - if (Y.Lang.trim(node.get('text')) !== '') { - foreground = node.getComputedStyle('color'); - background = node.getComputedStyle('backgroundColor'); - - lum1 = this.get_luminance_from_css_color(foreground); - lum2 = this.get_luminance_from_css_color(background); - - // Algorithm from "http://www.w3.org/TR/WCAG20-GENERAL/G18.html". - if (lum1 > lum2) { - ratio = (lum1 + 0.05) / (lum2 + 0.05); - } else { - ratio = (lum2 + 0.05) / (lum1 + 0.05); - } - if (ratio <= 4.5) { - Y.log('Contrast ratio is too low: ' + ratio + - ' Colour 1: ' + foreground + - ' Colour 2: ' + background + - ' Luminance 1: ' + lum1 + - ' Luminance 2: ' + lum2); - - // We only want the highest node with dodgy contrast reported. - var i = 0, found = false; - for (i = 0; i < problemnodes.length; i++) { - if (node.ancestors('*').indexOf(problemnodes[i]) !== -1) { - // Do not add node - it already has a parent in the list. - found = true; - break; - } else if (problemnodes[i].ancestors('*').indexOf(node) !== -1) { - // Replace the existing node with this one because it is higher up the DOM. - problemnodes[i] = node; - found = true; - break; - } - } - if (!found) { - problemnodes.push(node); - } - } - } - }, this); - - this.add_warnings(list, M.util.get_string('needsmorecontrast', 'atto_accessibilitychecker'), problemnodes, false); - - if (!list.hasChildNodes()) { - list.append('

        ' + M.util.get_string('nowarnings', 'atto_accessibilitychecker') + '

        '); - } - // Append the list of current styles. - return list; - }, - - /** - * Return the HTML of the form to show in the dialogue. - * - * @method get_report - * @param string elementid - * @return string - */ - get_report : function(elementid) { - // Current styles. - var html = '
        '; - - var content = Y.Node.create(html); - - content.append(this.list_warnings(elementid)); - - return content; } - -}; +}); diff --git a/lib/editor/atto/plugins/accessibilitychecker/yui/src/button/meta/button.json b/lib/editor/atto/plugins/accessibilitychecker/yui/src/button/meta/button.json index 18b8a88b4d1..af6ecb764a3 100644 --- a/lib/editor/atto/plugins/accessibilitychecker/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/accessibilitychecker/yui/src/button/meta/button.json @@ -1,5 +1,8 @@ { - "moodle-atto_accessibilitychecker-button": { - "requires": ["node", "escape", "color-base"] - } + "moodle-atto_accessibilitychecker-button": { + "requires": [ + "color-base", + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button-debug.js b/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button-debug.js index 6a849558ade..aa9104676a2 100644 --- a/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button-debug.js +++ b/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button-debug.js @@ -15,30 +15,16 @@ YUI.add('moodle-atto_accessibilityhelper-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** -* CSS classes and IDs. -* -* @type {Object} -*/ -var CSS = { - STYLESLABEL: 'atto_accessibilityhelper_styleslabel', - LISTSTYLES: 'atto_accessibilityhelper_liststyles', - LINKSLABEL: 'atto_accessibilityhelper_linkslabel', - LISTLINKS: 'atto_accessibilityhelper_listlinks', - IMAGESLABEL: 'atto_accessibilityhelper_imageslabel', - LISTIMAGES: 'atto_accessibilityhelper_listimages' -}; - - /** - * Selectors. - * - * @type {Object} +/* + * @package atto_accessibilityhelper + * @copyright 2014 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var SELECTORS = { - LISTSTYLES: '#atto_accessibilityhelper_liststyles', - LISTLINKS: '#atto_accessibilityhelper_listlinks', - LISTIMAGES: '#atto_accessibilityhelper_listimages' -}; + +/** + * @module moodle-atto_accessibilityhelper-button + */ + /** * Atto text editor accessibilityhelper plugin. * @@ -46,99 +32,209 @@ var SELECTORS = { * Specifically, listing the active styles for the selected text, * listing the images in the page, listing the links in the page. * - * @package editor-atto - * @copyright 2014 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @namespace M.atto_accessibilityhelper + * @class Button + * @extends M.editor_atto.EditorPlugin */ -M.atto_accessibilityhelper = M.atto_accessibilityhelper || { - /** - * The window used to display the accessibility ui. - * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, + +var COMPONENT = 'atto_accessibilityhelper', + TEMPLATE = '' + + // The list of styles. + '

        ' + + '{{get_string "liststyles" component}}
        ' + + '' + + '

        ' + + '' + + + '

        ' + + '{{get_string "listlinks" component}}
        ' + + '' + + '

        ' + + '' + + + '

        ' + + '{{get_string "listimages" component}}
        ' + + '' + + '

        ' + + '', + + CSS = { + STYLESLABEL: COMPONENT + '_styleslabel', + LINKSLABEL: COMPONENT + '_linkslabel', + IMAGESLABEL: COMPONENT + '_imageslabel' + }; + +Y.namespace('M.atto_accessibilityhelper').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * Display the ui dialogue. + * The warnings which are displayed. * - * @method init - * @param Event e - * @param string elementid + * @property _displayedWarnings + * @type Object + * @private */ - display_ui : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - var dialogue; - if (!M.atto_accessibilityhelper.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - dialogue.set('headerContent', M.util.get_string('pluginname', 'atto_accessibilityhelper')); - dialogue.render(); - } else { - dialogue = M.atto_accessibilityhelper.dialogue; + _displayedWarnings: {}, + + initializer: function() { + this.addButton({ + icon: 'e/screenreader_helper', + callback: this._displayDialogue + }); + }, + + /** + * Display the Accessibility Helper tool. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function() { + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('pluginname', COMPONENT), + width: '800px', + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + CSS: CSS, + component: COMPONENT + })); + + // Add the data. + content.one('.listStyles') + .empty() + .appendChild(this._listStyles()); + content.one('.listLinks') + .empty() + .appendChild(this._listLinks()); + content.one('.listImages') + .empty() + .appendChild(this._listImages()); + + // Add ability to select problem areas in the editor. + content.delegate('click', function(e) { + e.preventDefault(); + + var host = this.get('host'), + index = e.target.getAttribute("data-index"), + node = this._displayedWarnings[index], + dialogue = this.getDialogue(); + + + if (node) { + // Clear the dialogue's focusAfterHide to ensure we focus + // on the selection. + dialogue.set('focusAfterHide', null); + host.setSelection(host.getSelectionFromNode(node)); + } + + // Hide the dialogue. + dialogue.hide(); + + }, 'a', this); + + return content; + }, + + /** + * List the styles present for the selection. + * + * @method _listStyles + * @return {String} The list of styles in use. + * @private + */ + _listStyles: function() { + // Clear the status node. + var list = [], + host = this.get('host'), + current = host.getSelectionParentNode(), + tagname; + + if (current) { + current = Y.one(current); } - dialogue.set('bodyContent', M.atto_accessibilityhelper.get_content(elementid)); - dialogue.centerDialogue(); + while (current && (current !== this.editor)) { + tagname = current.get('tagName'); + if (typeof tagname !== 'undefined') { + list.push(Y.Escape.html(tagname)); + } + current = current.ancestor(); + } + if (list.length === 0) { + list.push(M.util.get_string('nostyles', COMPONENT)); + } - dialogue.show(); - M.atto_accessibilityhelper.dialogue = dialogue; + list.reverse(); + + // Append the list of current styles. + return list.join(', '); }, /** - * Add this button to the form. + * List the links for the current editor * - * @method init - * @param {Object} params + * @method _listLinks + * @return {string} + * @private */ - init : function(params) { - var iconurl = M.util.image_url('e/visual_aid', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'accessibilityhelper', iconurl, params.group, this.display_ui); + _listLinks: function() { + var list = Y.Node.create('
          '), + listitem, + selectlink; + + this.editor.all('a').each(function(link) { + selectlink = Y.Node.create('' + + Y.Escape.html(link.get('text')) + + ''); + + selectlink.setData('sourcelink', link); + selectlink.on('click', this._linkSelected, this); + + listitem = Y.Node.create('
        1. '); + listitem.appendChild(selectlink); + + list.appendChild(listitem); + }, this); + + if (!list.hasChildNodes()) { + list.append('
        2. ' + M.util.get_string('nolinks', COMPONENT) + '
        3. '); + } + + // Append the list of current styles. + return list; }, /** - * Event handler for selecting an image. + * List the images used in the editor. * - * @method image_selected - * @param Event e - * @param string elementid + * @method _listImages + * @return {Node} A Node containing all of the images present in the editor. + * @private */ - image_selected : function(e, elementid) { - e.preventDefault(); - - M.atto_accessibilityhelper.dialogue.hide(); - - var image = e.target.getData('sourceimage'); - var selection = M.editor_atto.get_selection_from_node(image); - - M.editor_atto.selections[elementid] = selection; - M.editor_atto.focus(elementid); - }, - - /** - * List the images for the current editor - * - * @method list_images - * @param string elementid - * @return String - */ - list_images : function(elementid) { - - var list = Y.Node.create('
            '); - - var editable = M.editor_atto.get_editable_node(elementid), - listitem, selectimage; - - editable.all('img').each(function(image) { + _listImages: function() { + var list = Y.Node.create('
              '), + listitem, + selectimage; + this.editor.all('img').each(function(image) { // Get the alt or title or img url of the image. var imgalt = image.getAttribute('alt'); if (imgalt === '') { @@ -149,156 +245,67 @@ M.atto_accessibilityhelper = M.atto_accessibilityhelper || { } selectimage = Y.Node.create('' + - Y.Escape.html(imgalt) + - ''); + M.util.get_string('selectimage', COMPONENT) + '">' + + Y.Escape.html(imgalt) + + ''); selectimage.setData('sourceimage', image); - selectimage.on('click', this.image_selected, this, elementid); + selectimage.on('click', this._imageSelected, this); listitem = Y.Node.create('
            1. '); listitem.append(selectimage); list.append(listitem); }, this); if (!list.hasChildNodes()) { - list.append('
            2. ' + M.util.get_string('noimages', 'atto_accessibilityhelper') + '
            3. '); + list.append('
            4. ' + M.util.get_string('noimages', COMPONENT) + '
            5. '); } + // Append the list of current styles. return list; }, + /** + * Event handler for selecting an image. + * + * @method _imageSelected + * @param {EventFacade} e + * @private + */ + _imageSelected: function(e) { + e.preventDefault(); + + this.getDialogue({ + focusAfterNode: null + }).hide(); + + var host = this.get('host'), + target = e.target.getData('sourceimage'); + + this.editor.focus(); + host.setSelection(host.getSelectionFromNode(target)); + }, + /** * Event handler for selecting a link. * - * @method link_selected - * @param Event e - * @param string elementid + * @method _linkSelected + * @param {EventFacade} e + * @private */ - link_selected : function(e, elementid) { + _linkSelected: function(e) { e.preventDefault(); - M.atto_accessibilityhelper.dialogue.hide(); + this.getDialogue({ + focusAfterNode: null + }).hide(); - var link = e.target.getData('sourcelink'); - var selection = M.editor_atto.get_selection_from_node(link); + var host = this.get('host'), + target = e.target.getData('sourcelink'); - M.editor_atto.selections[elementid] = selection; - M.editor_atto.focus(elementid); - }, - - /** - * List the links for the current editor - * - * @method list_links - * @param string elementid - * @return String - */ - list_links : function(elementid) { - - var list = Y.Node.create('
                '); - - var editable = M.editor_atto.get_editable_node(elementid), - listitem, selectlink; - - editable.all('a').each(function(link) { - selectlink = Y.Node.create('' + - Y.Escape.html(link.get('text')) + - ''); - - selectlink.setData('sourcelink', link); - selectlink.on('click', this.link_selected, this, elementid); - - listitem = Y.Node.create('
              1. '); - listitem.append(selectlink); - list.append(listitem); - }, this); - if (!list.hasChildNodes()) { - list.append('
              2. ' + M.util.get_string('nolinks', 'atto_accessibilityhelper') + '
              3. '); - } - // Append the list of current styles. - return list; - }, - - /** - * List the styles for the current selection. - * - * @method list_styles - * @param string elementid - * @return String - */ - list_styles : function(elementid) { - - // Clear the status node. - - var list = []; - - var current = M.editor_atto.get_selection_parent_node(); - var editable = M.editor_atto.get_editable_node(elementid); - var tagname; - - if (current) { - current = Y.one(current); - } - while (current && (current !== editable)) { - tagname = current.get('tagName'); - if (typeof tagname !== 'undefined') { - list.push(Y.Escape.html(tagname)); - } - current = current.ancestor(); - } - if (list.length === 0) { - list.push(M.util.get_string('nostyles', 'atto_accessibilityhelper')); - } - - list.reverse(); - // Append the list of current styles. - return list.join(', '); - }, - - /** - * Return the HTML of the form to show in the dialogue. - * - * @method get_content - * @param string elementid - * @return string - */ - get_content : function(elementid) { - // Current styles. - var html = '

                ' + - M.util.get_string('liststyles', 'atto_accessibilityhelper') + - '
                ' + - '

                '; - - - var content = Y.Node.create(html); - - content.one(SELECTORS.LISTSTYLES).append(this.list_styles(elementid)); - - // Current links. - html = '

                ' + - M.util.get_string('listlinks', 'atto_accessibilityhelper') + - '
                ' + - '

                '; - - content.append(html); - content.one(SELECTORS.LISTLINKS).append(this.list_links(elementid)); - - // Current images. - html = '

                ' + - M.util.get_string('listimages', 'atto_accessibilityhelper') + - '
                ' + - '

                '; - - content.append(html); - content.one(SELECTORS.LISTIMAGES).append(this.list_images(elementid)); - return content; + this.editor.focus(); + host.setSelection(host.getSelectionFromNode(target)); } - -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button-min.js b/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button-min.js index 80e0359464a..5840b0086c9 100644 --- a/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button-min.js +++ b/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_accessibilityhelper-button",function(e,t){var n={STYLESLABEL:"atto_accessibilityhelper_styleslabel",LISTSTYLES:"atto_accessibilityhelper_liststyles",LINKSLABEL:"atto_accessibilityhelper_linkslabel",LISTLINKS:"atto_accessibilityhelper_listlinks",IMAGESLABEL:"atto_accessibilityhelper_imageslabel",LISTIMAGES:"atto_accessibilityhelper_listimages"},r={LISTSTYLES:"#atto_accessibilityhelper_liststyles",LISTLINKS:"#atto_accessibilityhelper_listlinks",LISTIMAGES:"#atto_accessibilityhelper_listimages"};M.atto_accessibilityhelper=M.atto_accessibilityhelper||{dialogue:null,display_ui:function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t);var n;M.atto_accessibilityhelper.dialogue?n=M.atto_accessibilityhelper.dialogue:(n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.set("headerContent",M.util.get_string("pluginname","atto_accessibilityhelper")),n.render()),n.set("bodyContent",M.atto_accessibilityhelper.get_content(t)),n.centerDialogue(),n.show(),M.atto_accessibilityhelper.dialogue=n},init:function(e){var t=M.util.image_url("e/visual_aid","core");M.editor_atto.add_toolbar_button(e.elementid,"accessibilityhelper",t,e.group,this.display_ui)},image_selected:function(e,t){e.preventDefault(),M.atto_accessibilityhelper.dialogue.hide();var n=e.target.getData("sourceimage"),r=M.editor_atto.get_selection_from_node(n);M.editor_atto.selections[t]=r,M.editor_atto.focus(t)},list_images:function(t){var n=e.Node.create("
                  "),r=M.editor_atto.get_editable_node(t),i,s;return r.all("img").each(function(r){var o=r.getAttribute("alt");o===""&&(o=r.getAttribute("title"),o===""&&(o=r.getAttribute("src"))),s=e.Node.create(''+e.Escape.html(o)+""),s.setData("sourceimage",r),s.on("click",this.image_selected,this,t),i=e.Node.create("
                1. "),i.append(s),n.append(i)},this),n.hasChildNodes()||n.append("
                2. "+M.util.get_string("noimages","atto_accessibilityhelper")+"
                3. "),n},link_selected:function(e,t){e.preventDefault(),M.atto_accessibilityhelper.dialogue.hide();var n=e.target.getData("sourcelink"),r=M.editor_atto.get_selection_from_node(n);M.editor_atto.selections[t]=r,M.editor_atto.focus(t)},list_links:function(t){var n=e.Node.create("
                    "),r=M.editor_atto.get_editable_node(t),i,s;return r.all("a").each(function(r){s=e.Node.create(''+e.Escape.html(r.get("text"))+""),s.setData("sourcelink",r),s.on("click",this.link_selected,this,t),i=e.Node.create("
                  1. "),i.append(s),n.append(i)},this),n.hasChildNodes()||n.append("
                  2. "+M.util.get_string("nolinks","atto_accessibilityhelper")+"
                  3. "),n},list_styles:function(t){var n=[],r=M.editor_atto.get_selection_parent_node(),i=M.editor_atto.get_editable_node(t),s;r&&(r=e.one(r));while(r&&r!==i)s=r.get("tagName"),typeof s!="undefined"&&n.push(e.Escape.html(s)),r=r.ancestor();return n.length===0&&n.push(M.util.get_string("nostyles","atto_accessibilityhelper")),n.reverse(),n.join(", ")},get_content:function(t){var i='

                    '+M.util.get_string("liststyles","atto_accessibilityhelper")+"
                    "+'

                    ',s=e.Node.create(i);return s.one(r.LISTSTYLES).append(this.list_styles(t)),i='

                    '+M.util.get_string("listlinks","atto_accessibilityhelper")+"
                    "+'

                    ',s.append(i),s.one(r.LISTLINKS).append(this.list_links(t)),i='

                    '+M.util.get_string("listimages","atto_accessibilityhelper")+"
                    "+'

                    ',s.append(i),s.one(r.LISTIMAGES).append(this.list_images(t)),s}}},"@VERSION@",{requires:["node","escape"]}); +YUI.add("moodle-atto_accessibilityhelper-button",function(e,t){var n="atto_accessibilityhelper",r='

                    {{get_string "liststyles" component}}

                    {{get_string "listlinks" component}}

                    {{get_string "listimages" component}}

                    ',i={STYLESLABEL:n+"_styleslabel",LINKSLABEL:n+"_linkslabel",IMAGESLABEL:n+"_imageslabel"};e.namespace("M.atto_accessibilityhelper").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_displayedWarnings:{},initializer:function(){this.addButton({icon:"e/screenreader_helper",callback:this._displayDialogue})},_displayDialogue:function(){var e=this.getDialogue({headerContent:M.util.get_string("pluginname",n),width:"800px",focusAfterHide:!0});e.set("bodyContent",this._getDialogueContent()).show()},_getDialogueContent:function(){var t=e.Handlebars.compile(r),s=e.Node.create(t({CSS:i,component:n}));return s.one(".listStyles").empty().appendChild(this._listStyles()),s.one(".listLinks").empty().appendChild(this._listLinks()),s.one(".listImages").empty().appendChild(this._listImages()),s.delegate("click",function(e){e.preventDefault();var t=this.get("host"),n=e.target.getAttribute("data-index"),r=this._displayedWarnings[n],i=this.getDialogue();r&&(i.set("focusAfterHide",null),t.setSelection(t.getSelectionFromNode(r))),i.hide()},"a",this),s},_listStyles:function(){var t=[],r=this.get("host"),i=r.getSelectionParentNode(),s;i&&(i=e.one(i));while(i&&i!==this.editor)s=i.get("tagName"),typeof s!="undefined"&&t.push(e.Escape.html(s)),i=i.ancestor();return t.length===0&&t.push(M.util.get_string("nostyles",n)),t.reverse(),t.join(", ")},_listLinks:function(){var t=e.Node.create("
                      "),r,i;return this.editor.all("a").each(function(s){i=e.Node.create(''+e.Escape.html(s.get("text"))+""),i.setData("sourcelink",s),i.on("click",this._linkSelected,this),r=e.Node.create("
                    1. "),r.appendChild(i),t.appendChild(r)},this),t.hasChildNodes()||t.append("
                    2. "+M.util.get_string("nolinks",n)+"
                    3. "),t},_listImages:function(){var t=e.Node.create("
                        "),r,i;return this.editor.all("img").each(function(s){var o=s.getAttribute("alt");o===""&&(o=s.getAttribute("title"),o===""&&(o=s.getAttribute("src"))),i=e.Node.create(''+e.Escape.html(o)+""),i.setData("sourceimage",s),i.on("click",this._imageSelected,this),r=e.Node.create("
                      1. "),r.append(i),t.append(r)},this),t.hasChildNodes()||t.append("
                      2. "+M.util.get_string("noimages",n)+"
                      3. "),t},_imageSelected:function(e){e.preventDefault(),this.getDialogue({focusAfterNode:null}).hide();var t=this.get("host"),n=e.target.getData("sourceimage");this.editor.focus(),t.setSelection(t.getSelectionFromNode(n))},_linkSelected:function(e){e.preventDefault(),this.getDialogue({focusAfterNode:null}).hide();var t=this.get("host"),n=e.target.getData("sourcelink");this.editor.focus(),t.setSelection(t.getSelectionFromNode(n))}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button.js b/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button.js index 6a849558ade..aa9104676a2 100644 --- a/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button.js +++ b/lib/editor/atto/plugins/accessibilityhelper/yui/build/moodle-atto_accessibilityhelper-button/moodle-atto_accessibilityhelper-button.js @@ -15,30 +15,16 @@ YUI.add('moodle-atto_accessibilityhelper-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** -* CSS classes and IDs. -* -* @type {Object} -*/ -var CSS = { - STYLESLABEL: 'atto_accessibilityhelper_styleslabel', - LISTSTYLES: 'atto_accessibilityhelper_liststyles', - LINKSLABEL: 'atto_accessibilityhelper_linkslabel', - LISTLINKS: 'atto_accessibilityhelper_listlinks', - IMAGESLABEL: 'atto_accessibilityhelper_imageslabel', - LISTIMAGES: 'atto_accessibilityhelper_listimages' -}; - - /** - * Selectors. - * - * @type {Object} +/* + * @package atto_accessibilityhelper + * @copyright 2014 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var SELECTORS = { - LISTSTYLES: '#atto_accessibilityhelper_liststyles', - LISTLINKS: '#atto_accessibilityhelper_listlinks', - LISTIMAGES: '#atto_accessibilityhelper_listimages' -}; + +/** + * @module moodle-atto_accessibilityhelper-button + */ + /** * Atto text editor accessibilityhelper plugin. * @@ -46,99 +32,209 @@ var SELECTORS = { * Specifically, listing the active styles for the selected text, * listing the images in the page, listing the links in the page. * - * @package editor-atto - * @copyright 2014 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @namespace M.atto_accessibilityhelper + * @class Button + * @extends M.editor_atto.EditorPlugin */ -M.atto_accessibilityhelper = M.atto_accessibilityhelper || { - /** - * The window used to display the accessibility ui. - * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, + +var COMPONENT = 'atto_accessibilityhelper', + TEMPLATE = '' + + // The list of styles. + '

                        ' + + '{{get_string "liststyles" component}}
                        ' + + '' + + '

                        ' + + '' + + + '

                        ' + + '{{get_string "listlinks" component}}
                        ' + + '' + + '

                        ' + + '' + + + '

                        ' + + '{{get_string "listimages" component}}
                        ' + + '' + + '

                        ' + + '', + + CSS = { + STYLESLABEL: COMPONENT + '_styleslabel', + LINKSLABEL: COMPONENT + '_linkslabel', + IMAGESLABEL: COMPONENT + '_imageslabel' + }; + +Y.namespace('M.atto_accessibilityhelper').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * Display the ui dialogue. + * The warnings which are displayed. * - * @method init - * @param Event e - * @param string elementid + * @property _displayedWarnings + * @type Object + * @private */ - display_ui : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - var dialogue; - if (!M.atto_accessibilityhelper.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - dialogue.set('headerContent', M.util.get_string('pluginname', 'atto_accessibilityhelper')); - dialogue.render(); - } else { - dialogue = M.atto_accessibilityhelper.dialogue; + _displayedWarnings: {}, + + initializer: function() { + this.addButton({ + icon: 'e/screenreader_helper', + callback: this._displayDialogue + }); + }, + + /** + * Display the Accessibility Helper tool. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function() { + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('pluginname', COMPONENT), + width: '800px', + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + CSS: CSS, + component: COMPONENT + })); + + // Add the data. + content.one('.listStyles') + .empty() + .appendChild(this._listStyles()); + content.one('.listLinks') + .empty() + .appendChild(this._listLinks()); + content.one('.listImages') + .empty() + .appendChild(this._listImages()); + + // Add ability to select problem areas in the editor. + content.delegate('click', function(e) { + e.preventDefault(); + + var host = this.get('host'), + index = e.target.getAttribute("data-index"), + node = this._displayedWarnings[index], + dialogue = this.getDialogue(); + + + if (node) { + // Clear the dialogue's focusAfterHide to ensure we focus + // on the selection. + dialogue.set('focusAfterHide', null); + host.setSelection(host.getSelectionFromNode(node)); + } + + // Hide the dialogue. + dialogue.hide(); + + }, 'a', this); + + return content; + }, + + /** + * List the styles present for the selection. + * + * @method _listStyles + * @return {String} The list of styles in use. + * @private + */ + _listStyles: function() { + // Clear the status node. + var list = [], + host = this.get('host'), + current = host.getSelectionParentNode(), + tagname; + + if (current) { + current = Y.one(current); } - dialogue.set('bodyContent', M.atto_accessibilityhelper.get_content(elementid)); - dialogue.centerDialogue(); + while (current && (current !== this.editor)) { + tagname = current.get('tagName'); + if (typeof tagname !== 'undefined') { + list.push(Y.Escape.html(tagname)); + } + current = current.ancestor(); + } + if (list.length === 0) { + list.push(M.util.get_string('nostyles', COMPONENT)); + } - dialogue.show(); - M.atto_accessibilityhelper.dialogue = dialogue; + list.reverse(); + + // Append the list of current styles. + return list.join(', '); }, /** - * Add this button to the form. + * List the links for the current editor * - * @method init - * @param {Object} params + * @method _listLinks + * @return {string} + * @private */ - init : function(params) { - var iconurl = M.util.image_url('e/visual_aid', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'accessibilityhelper', iconurl, params.group, this.display_ui); + _listLinks: function() { + var list = Y.Node.create('
                          '), + listitem, + selectlink; + + this.editor.all('a').each(function(link) { + selectlink = Y.Node.create('' + + Y.Escape.html(link.get('text')) + + ''); + + selectlink.setData('sourcelink', link); + selectlink.on('click', this._linkSelected, this); + + listitem = Y.Node.create('
                        1. '); + listitem.appendChild(selectlink); + + list.appendChild(listitem); + }, this); + + if (!list.hasChildNodes()) { + list.append('
                        2. ' + M.util.get_string('nolinks', COMPONENT) + '
                        3. '); + } + + // Append the list of current styles. + return list; }, /** - * Event handler for selecting an image. + * List the images used in the editor. * - * @method image_selected - * @param Event e - * @param string elementid + * @method _listImages + * @return {Node} A Node containing all of the images present in the editor. + * @private */ - image_selected : function(e, elementid) { - e.preventDefault(); - - M.atto_accessibilityhelper.dialogue.hide(); - - var image = e.target.getData('sourceimage'); - var selection = M.editor_atto.get_selection_from_node(image); - - M.editor_atto.selections[elementid] = selection; - M.editor_atto.focus(elementid); - }, - - /** - * List the images for the current editor - * - * @method list_images - * @param string elementid - * @return String - */ - list_images : function(elementid) { - - var list = Y.Node.create('
                            '); - - var editable = M.editor_atto.get_editable_node(elementid), - listitem, selectimage; - - editable.all('img').each(function(image) { + _listImages: function() { + var list = Y.Node.create('
                              '), + listitem, + selectimage; + this.editor.all('img').each(function(image) { // Get the alt or title or img url of the image. var imgalt = image.getAttribute('alt'); if (imgalt === '') { @@ -149,156 +245,67 @@ M.atto_accessibilityhelper = M.atto_accessibilityhelper || { } selectimage = Y.Node.create('' + - Y.Escape.html(imgalt) + - ''); + M.util.get_string('selectimage', COMPONENT) + '">' + + Y.Escape.html(imgalt) + + ''); selectimage.setData('sourceimage', image); - selectimage.on('click', this.image_selected, this, elementid); + selectimage.on('click', this._imageSelected, this); listitem = Y.Node.create('
                            1. '); listitem.append(selectimage); list.append(listitem); }, this); if (!list.hasChildNodes()) { - list.append('
                            2. ' + M.util.get_string('noimages', 'atto_accessibilityhelper') + '
                            3. '); + list.append('
                            4. ' + M.util.get_string('noimages', COMPONENT) + '
                            5. '); } + // Append the list of current styles. return list; }, + /** + * Event handler for selecting an image. + * + * @method _imageSelected + * @param {EventFacade} e + * @private + */ + _imageSelected: function(e) { + e.preventDefault(); + + this.getDialogue({ + focusAfterNode: null + }).hide(); + + var host = this.get('host'), + target = e.target.getData('sourceimage'); + + this.editor.focus(); + host.setSelection(host.getSelectionFromNode(target)); + }, + /** * Event handler for selecting a link. * - * @method link_selected - * @param Event e - * @param string elementid + * @method _linkSelected + * @param {EventFacade} e + * @private */ - link_selected : function(e, elementid) { + _linkSelected: function(e) { e.preventDefault(); - M.atto_accessibilityhelper.dialogue.hide(); + this.getDialogue({ + focusAfterNode: null + }).hide(); - var link = e.target.getData('sourcelink'); - var selection = M.editor_atto.get_selection_from_node(link); + var host = this.get('host'), + target = e.target.getData('sourcelink'); - M.editor_atto.selections[elementid] = selection; - M.editor_atto.focus(elementid); - }, - - /** - * List the links for the current editor - * - * @method list_links - * @param string elementid - * @return String - */ - list_links : function(elementid) { - - var list = Y.Node.create('
                                '); - - var editable = M.editor_atto.get_editable_node(elementid), - listitem, selectlink; - - editable.all('a').each(function(link) { - selectlink = Y.Node.create('' + - Y.Escape.html(link.get('text')) + - ''); - - selectlink.setData('sourcelink', link); - selectlink.on('click', this.link_selected, this, elementid); - - listitem = Y.Node.create('
                              1. '); - listitem.append(selectlink); - list.append(listitem); - }, this); - if (!list.hasChildNodes()) { - list.append('
                              2. ' + M.util.get_string('nolinks', 'atto_accessibilityhelper') + '
                              3. '); - } - // Append the list of current styles. - return list; - }, - - /** - * List the styles for the current selection. - * - * @method list_styles - * @param string elementid - * @return String - */ - list_styles : function(elementid) { - - // Clear the status node. - - var list = []; - - var current = M.editor_atto.get_selection_parent_node(); - var editable = M.editor_atto.get_editable_node(elementid); - var tagname; - - if (current) { - current = Y.one(current); - } - while (current && (current !== editable)) { - tagname = current.get('tagName'); - if (typeof tagname !== 'undefined') { - list.push(Y.Escape.html(tagname)); - } - current = current.ancestor(); - } - if (list.length === 0) { - list.push(M.util.get_string('nostyles', 'atto_accessibilityhelper')); - } - - list.reverse(); - // Append the list of current styles. - return list.join(', '); - }, - - /** - * Return the HTML of the form to show in the dialogue. - * - * @method get_content - * @param string elementid - * @return string - */ - get_content : function(elementid) { - // Current styles. - var html = '

                                ' + - M.util.get_string('liststyles', 'atto_accessibilityhelper') + - '
                                ' + - '

                                '; - - - var content = Y.Node.create(html); - - content.one(SELECTORS.LISTSTYLES).append(this.list_styles(elementid)); - - // Current links. - html = '

                                ' + - M.util.get_string('listlinks', 'atto_accessibilityhelper') + - '
                                ' + - '

                                '; - - content.append(html); - content.one(SELECTORS.LISTLINKS).append(this.list_links(elementid)); - - // Current images. - html = '

                                ' + - M.util.get_string('listimages', 'atto_accessibilityhelper') + - '
                                ' + - '

                                '; - - content.append(html); - content.one(SELECTORS.LISTIMAGES).append(this.list_images(elementid)); - return content; + this.editor.focus(); + host.setSelection(host.getSelectionFromNode(target)); } - -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/accessibilityhelper/yui/src/button/js/button.js b/lib/editor/atto/plugins/accessibilityhelper/yui/src/button/js/button.js index c415c2ca26f..f6c1c74e18e 100644 --- a/lib/editor/atto/plugins/accessibilityhelper/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/accessibilityhelper/yui/src/button/js/button.js @@ -13,30 +13,16 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** -* CSS classes and IDs. -* -* @type {Object} -*/ -var CSS = { - STYLESLABEL: 'atto_accessibilityhelper_styleslabel', - LISTSTYLES: 'atto_accessibilityhelper_liststyles', - LINKSLABEL: 'atto_accessibilityhelper_linkslabel', - LISTLINKS: 'atto_accessibilityhelper_listlinks', - IMAGESLABEL: 'atto_accessibilityhelper_imageslabel', - LISTIMAGES: 'atto_accessibilityhelper_listimages' -}; - - /** - * Selectors. - * - * @type {Object} +/* + * @package atto_accessibilityhelper + * @copyright 2014 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var SELECTORS = { - LISTSTYLES: '#atto_accessibilityhelper_liststyles', - LISTLINKS: '#atto_accessibilityhelper_listlinks', - LISTIMAGES: '#atto_accessibilityhelper_listimages' -}; + +/** + * @module moodle-atto_accessibilityhelper-button + */ + /** * Atto text editor accessibilityhelper plugin. * @@ -44,99 +30,209 @@ var SELECTORS = { * Specifically, listing the active styles for the selected text, * listing the images in the page, listing the links in the page. * - * @package editor-atto - * @copyright 2014 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @namespace M.atto_accessibilityhelper + * @class Button + * @extends M.editor_atto.EditorPlugin */ -M.atto_accessibilityhelper = M.atto_accessibilityhelper || { - /** - * The window used to display the accessibility ui. - * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, + +var COMPONENT = 'atto_accessibilityhelper', + TEMPLATE = '' + + // The list of styles. + '

                                ' + + '{{get_string "liststyles" component}}
                                ' + + '' + + '

                                ' + + '' + + + '

                                ' + + '{{get_string "listlinks" component}}
                                ' + + '' + + '

                                ' + + '' + + + '

                                ' + + '{{get_string "listimages" component}}
                                ' + + '' + + '

                                ' + + '', + + CSS = { + STYLESLABEL: COMPONENT + '_styleslabel', + LINKSLABEL: COMPONENT + '_linkslabel', + IMAGESLABEL: COMPONENT + '_imageslabel' + }; + +Y.namespace('M.atto_accessibilityhelper').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * Display the ui dialogue. + * The warnings which are displayed. * - * @method init - * @param Event e - * @param string elementid + * @property _displayedWarnings + * @type Object + * @private */ - display_ui : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - var dialogue; - if (!M.atto_accessibilityhelper.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - dialogue.set('headerContent', M.util.get_string('pluginname', 'atto_accessibilityhelper')); - dialogue.render(); - } else { - dialogue = M.atto_accessibilityhelper.dialogue; + _displayedWarnings: {}, + + initializer: function() { + this.addButton({ + icon: 'e/screenreader_helper', + callback: this._displayDialogue + }); + }, + + /** + * Display the Accessibility Helper tool. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function() { + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('pluginname', COMPONENT), + width: '800px', + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + CSS: CSS, + component: COMPONENT + })); + + // Add the data. + content.one('.listStyles') + .empty() + .appendChild(this._listStyles()); + content.one('.listLinks') + .empty() + .appendChild(this._listLinks()); + content.one('.listImages') + .empty() + .appendChild(this._listImages()); + + // Add ability to select problem areas in the editor. + content.delegate('click', function(e) { + e.preventDefault(); + + var host = this.get('host'), + index = e.target.getAttribute("data-index"), + node = this._displayedWarnings[index], + dialogue = this.getDialogue(); + + + if (node) { + // Clear the dialogue's focusAfterHide to ensure we focus + // on the selection. + dialogue.set('focusAfterHide', null); + host.setSelection(host.getSelectionFromNode(node)); + } + + // Hide the dialogue. + dialogue.hide(); + + }, 'a', this); + + return content; + }, + + /** + * List the styles present for the selection. + * + * @method _listStyles + * @return {String} The list of styles in use. + * @private + */ + _listStyles: function() { + // Clear the status node. + var list = [], + host = this.get('host'), + current = host.getSelectionParentNode(), + tagname; + + if (current) { + current = Y.one(current); } - dialogue.set('bodyContent', M.atto_accessibilityhelper.get_content(elementid)); - dialogue.centerDialogue(); + while (current && (current !== this.editor)) { + tagname = current.get('tagName'); + if (typeof tagname !== 'undefined') { + list.push(Y.Escape.html(tagname)); + } + current = current.ancestor(); + } + if (list.length === 0) { + list.push(M.util.get_string('nostyles', COMPONENT)); + } - dialogue.show(); - M.atto_accessibilityhelper.dialogue = dialogue; + list.reverse(); + + // Append the list of current styles. + return list.join(', '); }, /** - * Add this button to the form. + * List the links for the current editor * - * @method init - * @param {Object} params + * @method _listLinks + * @return {string} + * @private */ - init : function(params) { - var iconurl = M.util.image_url('e/visual_aid', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'accessibilityhelper', iconurl, params.group, this.display_ui); + _listLinks: function() { + var list = Y.Node.create('
                                  '), + listitem, + selectlink; + + this.editor.all('a').each(function(link) { + selectlink = Y.Node.create('' + + Y.Escape.html(link.get('text')) + + ''); + + selectlink.setData('sourcelink', link); + selectlink.on('click', this._linkSelected, this); + + listitem = Y.Node.create('
                                1. '); + listitem.appendChild(selectlink); + + list.appendChild(listitem); + }, this); + + if (!list.hasChildNodes()) { + list.append('
                                2. ' + M.util.get_string('nolinks', COMPONENT) + '
                                3. '); + } + + // Append the list of current styles. + return list; }, /** - * Event handler for selecting an image. + * List the images used in the editor. * - * @method image_selected - * @param Event e - * @param string elementid + * @method _listImages + * @return {Node} A Node containing all of the images present in the editor. + * @private */ - image_selected : function(e, elementid) { - e.preventDefault(); - - M.atto_accessibilityhelper.dialogue.hide(); - - var image = e.target.getData('sourceimage'); - var selection = M.editor_atto.get_selection_from_node(image); - - M.editor_atto.selections[elementid] = selection; - M.editor_atto.focus(elementid); - }, - - /** - * List the images for the current editor - * - * @method list_images - * @param string elementid - * @return String - */ - list_images : function(elementid) { - - var list = Y.Node.create('
                                    '); - - var editable = M.editor_atto.get_editable_node(elementid), - listitem, selectimage; - - editable.all('img').each(function(image) { + _listImages: function() { + var list = Y.Node.create('
                                      '), + listitem, + selectimage; + this.editor.all('img').each(function(image) { // Get the alt or title or img url of the image. var imgalt = image.getAttribute('alt'); if (imgalt === '') { @@ -147,153 +243,64 @@ M.atto_accessibilityhelper = M.atto_accessibilityhelper || { } selectimage = Y.Node.create('' + - Y.Escape.html(imgalt) + - ''); + M.util.get_string('selectimage', COMPONENT) + '">' + + Y.Escape.html(imgalt) + + ''); selectimage.setData('sourceimage', image); - selectimage.on('click', this.image_selected, this, elementid); + selectimage.on('click', this._imageSelected, this); listitem = Y.Node.create('
                                    1. '); listitem.append(selectimage); list.append(listitem); }, this); if (!list.hasChildNodes()) { - list.append('
                                    2. ' + M.util.get_string('noimages', 'atto_accessibilityhelper') + '
                                    3. '); + list.append('
                                    4. ' + M.util.get_string('noimages', COMPONENT) + '
                                    5. '); } + // Append the list of current styles. return list; }, + /** + * Event handler for selecting an image. + * + * @method _imageSelected + * @param {EventFacade} e + * @private + */ + _imageSelected: function(e) { + e.preventDefault(); + + this.getDialogue({ + focusAfterNode: null + }).hide(); + + var host = this.get('host'), + target = e.target.getData('sourceimage'); + + this.editor.focus(); + host.setSelection(host.getSelectionFromNode(target)); + }, + /** * Event handler for selecting a link. * - * @method link_selected - * @param Event e - * @param string elementid + * @method _linkSelected + * @param {EventFacade} e + * @private */ - link_selected : function(e, elementid) { + _linkSelected: function(e) { e.preventDefault(); - M.atto_accessibilityhelper.dialogue.hide(); + this.getDialogue({ + focusAfterNode: null + }).hide(); - var link = e.target.getData('sourcelink'); - var selection = M.editor_atto.get_selection_from_node(link); + var host = this.get('host'), + target = e.target.getData('sourcelink'); - M.editor_atto.selections[elementid] = selection; - M.editor_atto.focus(elementid); - }, - - /** - * List the links for the current editor - * - * @method list_links - * @param string elementid - * @return String - */ - list_links : function(elementid) { - - var list = Y.Node.create('
                                        '); - - var editable = M.editor_atto.get_editable_node(elementid), - listitem, selectlink; - - editable.all('a').each(function(link) { - selectlink = Y.Node.create('' + - Y.Escape.html(link.get('text')) + - ''); - - selectlink.setData('sourcelink', link); - selectlink.on('click', this.link_selected, this, elementid); - - listitem = Y.Node.create('
                                      1. '); - listitem.append(selectlink); - list.append(listitem); - }, this); - if (!list.hasChildNodes()) { - list.append('
                                      2. ' + M.util.get_string('nolinks', 'atto_accessibilityhelper') + '
                                      3. '); - } - // Append the list of current styles. - return list; - }, - - /** - * List the styles for the current selection. - * - * @method list_styles - * @param string elementid - * @return String - */ - list_styles : function(elementid) { - - // Clear the status node. - - var list = []; - - var current = M.editor_atto.get_selection_parent_node(); - var editable = M.editor_atto.get_editable_node(elementid); - var tagname; - - if (current) { - current = Y.one(current); - } - while (current && (current !== editable)) { - tagname = current.get('tagName'); - if (typeof tagname !== 'undefined') { - list.push(Y.Escape.html(tagname)); - } - current = current.ancestor(); - } - if (list.length === 0) { - list.push(M.util.get_string('nostyles', 'atto_accessibilityhelper')); - } - - list.reverse(); - // Append the list of current styles. - return list.join(', '); - }, - - /** - * Return the HTML of the form to show in the dialogue. - * - * @method get_content - * @param string elementid - * @return string - */ - get_content : function(elementid) { - // Current styles. - var html = '

                                        ' + - M.util.get_string('liststyles', 'atto_accessibilityhelper') + - '
                                        ' + - '

                                        '; - - - var content = Y.Node.create(html); - - content.one(SELECTORS.LISTSTYLES).append(this.list_styles(elementid)); - - // Current links. - html = '

                                        ' + - M.util.get_string('listlinks', 'atto_accessibilityhelper') + - '
                                        ' + - '

                                        '; - - content.append(html); - content.one(SELECTORS.LISTLINKS).append(this.list_links(elementid)); - - // Current images. - html = '

                                        ' + - M.util.get_string('listimages', 'atto_accessibilityhelper') + - '
                                        ' + - '

                                        '; - - content.append(html); - content.one(SELECTORS.LISTIMAGES).append(this.list_images(elementid)); - return content; + this.editor.focus(); + host.setSelection(host.getSelectionFromNode(target)); } - -}; +}); diff --git a/lib/editor/atto/plugins/accessibilityhelper/yui/src/button/meta/button.json b/lib/editor/atto/plugins/accessibilityhelper/yui/src/button/meta/button.json index f825e16be17..81dd844fe1e 100644 --- a/lib/editor/atto/plugins/accessibilityhelper/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/accessibilityhelper/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_accessibilityhelper-button": { - "requires": ["node", "escape"] - } + "moodle-atto_accessibilityhelper-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button-debug.js b/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button-debug.js index bc4e76378fa..60f5e4ffbef 100644 --- a/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button-debug.js +++ b/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button-debug.js @@ -15,84 +15,83 @@ YUI.add('moodle-atto_align-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor align plugin. - * +/* * @package atto_align * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var LEFT = 'left', - RIGHT = 'right', - CENTER = 'center'; +/** + * @module moodle-atto_align-button + */ -M.atto_align = M.atto_align || { +/** + * Atto text editor align plugin. + * + * @namespace M.atto_align + * @class button + * @extends M.editor_atto.EditorPlugin + */ - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init: function(params) { - var iconurl, leftAlign, rightAlign, centerAlign; +Y.namespace('M.atto_align').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var alignment; - leftAlign = function(e, elementid) { - e.preventDefault(); - M.atto_align.changeAlignment(elementid, LEFT); - }; + alignment = 'justifyLeft'; + this.addButton({ + icon: 'e/align_left', + title: 'leftalign', + buttonName: alignment, + callback: this._changeStyle, + callbackArgs: alignment + }); - centerAlign = function(e, elementid) { - e.preventDefault(); - M.atto_align.changeAlignment(elementid, CENTER); - }; + alignment = 'justifyCenter'; + this.addButton({ + icon: 'e/align_center', + title: 'center', + buttonName: alignment, + callback: this._changeStyle, + callbackArgs: alignment + }); - rightAlign = function(e, elementid) { - e.preventDefault(); - M.atto_align.changeAlignment(elementid, RIGHT); - }; - - iconurl = M.util.image_url('e/align_left', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'align', iconurl, params.group, leftAlign, - 'left', M.util.get_string('leftalign', 'atto_align')); - - iconurl = M.util.image_url('e/align_center', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'align', iconurl, params.group, centerAlign, - 'center', M.util.get_string('center', 'atto_align')); - - iconurl = M.util.image_url('e/align_right', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'align', iconurl, params.group, rightAlign, - 'right', M.util.get_string('rightalign', 'atto_align')); + alignment = 'justifyRight'; + this.addButton({ + icon: 'e/align_right', + title: 'rightalign', + buttonName: alignment, + callback: this._changeStyle, + callbackArgs: alignment + }); }, + /** - * Changes the text alignment. + * Change the alignment to the specified justification. * - * @param {String} elementid The editor ID. - * @param {String} alignment The alignment to change to. - * @return {Void} + * @method _changeStyle + * @param {EventFacade} e + * @param {string} justification The execCommand for the new justification. + * @private */ - changeAlignment: function(elementid, alignment) { - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } + _changeStyle: function(e, justification) { + var host = this.get('host'); // We temporarily re-enable CSS styling to try to have the most consistency. // Though, IE, as always, is stubborn and will do its own thing... - M.editor_atto.enable_css_styling(); - if (alignment === RIGHT) { - document.execCommand('justifyRight', false, null); - } else if (alignment === CENTER) { - document.execCommand('justifyCenter', false, null); - } else { - document.execCommand('justifyLeft', false, null); - } - M.editor_atto.disable_css_styling(); + host.enableCssStyling(); + + document.execCommand(justification, false, null); + + // Re-disable the CSS styling after making the change. + host.disableCssStyling(); + + // Mark the text as having been updated. + this.markUpdated(); + + this.editor.focus(); } - -}; +}); -}, '@VERSION@', {"requires": []}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button-min.js b/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button-min.js index 7cc309c78c0..204f472c85e 100644 --- a/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button-min.js +++ b/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_align-button",function(e,t){var n="left",r="right",i="center";M.atto_align=M.atto_align||{init:function(e){var t,s,o,u;s=function(e,t){e.preventDefault(),M.atto_align.changeAlignment(t,n)},u=function(e,t){e.preventDefault(),M.atto_align.changeAlignment(t,i)},o=function(e,t){e.preventDefault(),M.atto_align.changeAlignment(t,r)},t=M.util.image_url("e/align_left","core"),M.editor_atto.add_toolbar_button(e.elementid,"align",t,e.group,s,"left",M.util.get_string("leftalign","atto_align")),t=M.util.image_url("e/align_center","core"),M.editor_atto.add_toolbar_button(e.elementid,"align",t,e.group,u,"center",M.util.get_string("center","atto_align")),t=M.util.image_url("e/align_right","core"),M.editor_atto.add_toolbar_button(e.elementid,"align",t,e.group,o,"right",M.util.get_string("rightalign","atto_align"))},changeAlignment:function(e,t){M.editor_atto.is_active(e)||M.editor_atto.focus(e),M.editor_atto.enable_css_styling(),t===r?document.execCommand("justifyRight",!1,null):t===i?document.execCommand("justifyCenter",!1,null):document.execCommand("justifyLeft",!1,null),M.editor_atto.disable_css_styling()}}},"@VERSION@",{requires:[]}); +YUI.add("moodle-atto_align-button",function(e,t){e.namespace("M.atto_align").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var e;e="justifyLeft",this.addButton({icon:"e/align_left",title:"leftalign",buttonName:e,callback:this._changeStyle,callbackArgs:e}),e="justifyCenter",this.addButton({icon:"e/align_center",title:"center",buttonName:e,callback:this._changeStyle,callbackArgs:e}),e="justifyRight",this.addButton({icon:"e/align_right",title:"rightalign",buttonName:e,callback:this._changeStyle,callbackArgs:e})},_changeStyle:function(e,t){var n=this.get("host");n.enableCssStyling(),document.execCommand(t,!1,null),n.disableCssStyling(),this.markUpdated(),this.editor.focus()}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button.js b/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button.js index bc4e76378fa..60f5e4ffbef 100644 --- a/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button.js +++ b/lib/editor/atto/plugins/align/yui/build/moodle-atto_align-button/moodle-atto_align-button.js @@ -15,84 +15,83 @@ YUI.add('moodle-atto_align-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor align plugin. - * +/* * @package atto_align * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var LEFT = 'left', - RIGHT = 'right', - CENTER = 'center'; +/** + * @module moodle-atto_align-button + */ -M.atto_align = M.atto_align || { +/** + * Atto text editor align plugin. + * + * @namespace M.atto_align + * @class button + * @extends M.editor_atto.EditorPlugin + */ - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init: function(params) { - var iconurl, leftAlign, rightAlign, centerAlign; +Y.namespace('M.atto_align').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var alignment; - leftAlign = function(e, elementid) { - e.preventDefault(); - M.atto_align.changeAlignment(elementid, LEFT); - }; + alignment = 'justifyLeft'; + this.addButton({ + icon: 'e/align_left', + title: 'leftalign', + buttonName: alignment, + callback: this._changeStyle, + callbackArgs: alignment + }); - centerAlign = function(e, elementid) { - e.preventDefault(); - M.atto_align.changeAlignment(elementid, CENTER); - }; + alignment = 'justifyCenter'; + this.addButton({ + icon: 'e/align_center', + title: 'center', + buttonName: alignment, + callback: this._changeStyle, + callbackArgs: alignment + }); - rightAlign = function(e, elementid) { - e.preventDefault(); - M.atto_align.changeAlignment(elementid, RIGHT); - }; - - iconurl = M.util.image_url('e/align_left', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'align', iconurl, params.group, leftAlign, - 'left', M.util.get_string('leftalign', 'atto_align')); - - iconurl = M.util.image_url('e/align_center', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'align', iconurl, params.group, centerAlign, - 'center', M.util.get_string('center', 'atto_align')); - - iconurl = M.util.image_url('e/align_right', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'align', iconurl, params.group, rightAlign, - 'right', M.util.get_string('rightalign', 'atto_align')); + alignment = 'justifyRight'; + this.addButton({ + icon: 'e/align_right', + title: 'rightalign', + buttonName: alignment, + callback: this._changeStyle, + callbackArgs: alignment + }); }, + /** - * Changes the text alignment. + * Change the alignment to the specified justification. * - * @param {String} elementid The editor ID. - * @param {String} alignment The alignment to change to. - * @return {Void} + * @method _changeStyle + * @param {EventFacade} e + * @param {string} justification The execCommand for the new justification. + * @private */ - changeAlignment: function(elementid, alignment) { - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } + _changeStyle: function(e, justification) { + var host = this.get('host'); // We temporarily re-enable CSS styling to try to have the most consistency. // Though, IE, as always, is stubborn and will do its own thing... - M.editor_atto.enable_css_styling(); - if (alignment === RIGHT) { - document.execCommand('justifyRight', false, null); - } else if (alignment === CENTER) { - document.execCommand('justifyCenter', false, null); - } else { - document.execCommand('justifyLeft', false, null); - } - M.editor_atto.disable_css_styling(); + host.enableCssStyling(); + + document.execCommand(justification, false, null); + + // Re-disable the CSS styling after making the change. + host.disableCssStyling(); + + // Mark the text as having been updated. + this.markUpdated(); + + this.editor.focus(); } - -}; +}); -}, '@VERSION@', {"requires": []}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/align/yui/src/button/js/button.js b/lib/editor/atto/plugins/align/yui/src/button/js/button.js index c34be178c3d..a1d62df13de 100644 --- a/lib/editor/atto/plugins/align/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/align/yui/src/button/js/button.js @@ -13,81 +13,80 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor align plugin. - * +/* * @package atto_align * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var LEFT = 'left', - RIGHT = 'right', - CENTER = 'center'; +/** + * @module moodle-atto_align-button + */ -M.atto_align = M.atto_align || { +/** + * Atto text editor align plugin. + * + * @namespace M.atto_align + * @class button + * @extends M.editor_atto.EditorPlugin + */ - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init: function(params) { - var iconurl, leftAlign, rightAlign, centerAlign; +Y.namespace('M.atto_align').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var alignment; - leftAlign = function(e, elementid) { - e.preventDefault(); - M.atto_align.changeAlignment(elementid, LEFT); - }; + alignment = 'justifyLeft'; + this.addButton({ + icon: 'e/align_left', + title: 'leftalign', + buttonName: alignment, + callback: this._changeStyle, + callbackArgs: alignment + }); - centerAlign = function(e, elementid) { - e.preventDefault(); - M.atto_align.changeAlignment(elementid, CENTER); - }; + alignment = 'justifyCenter'; + this.addButton({ + icon: 'e/align_center', + title: 'center', + buttonName: alignment, + callback: this._changeStyle, + callbackArgs: alignment + }); - rightAlign = function(e, elementid) { - e.preventDefault(); - M.atto_align.changeAlignment(elementid, RIGHT); - }; - - iconurl = M.util.image_url('e/align_left', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'align', iconurl, params.group, leftAlign, - 'left', M.util.get_string('leftalign', 'atto_align')); - - iconurl = M.util.image_url('e/align_center', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'align', iconurl, params.group, centerAlign, - 'center', M.util.get_string('center', 'atto_align')); - - iconurl = M.util.image_url('e/align_right', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'align', iconurl, params.group, rightAlign, - 'right', M.util.get_string('rightalign', 'atto_align')); + alignment = 'justifyRight'; + this.addButton({ + icon: 'e/align_right', + title: 'rightalign', + buttonName: alignment, + callback: this._changeStyle, + callbackArgs: alignment + }); }, + /** - * Changes the text alignment. + * Change the alignment to the specified justification. * - * @param {String} elementid The editor ID. - * @param {String} alignment The alignment to change to. - * @return {Void} + * @method _changeStyle + * @param {EventFacade} e + * @param {string} justification The execCommand for the new justification. + * @private */ - changeAlignment: function(elementid, alignment) { - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } + _changeStyle: function(e, justification) { + var host = this.get('host'); // We temporarily re-enable CSS styling to try to have the most consistency. // Though, IE, as always, is stubborn and will do its own thing... - M.editor_atto.enable_css_styling(); - if (alignment === RIGHT) { - document.execCommand('justifyRight', false, null); - } else if (alignment === CENTER) { - document.execCommand('justifyCenter', false, null); - } else { - document.execCommand('justifyLeft', false, null); - } - M.editor_atto.disable_css_styling(); - } + host.enableCssStyling(); -}; + document.execCommand(justification, false, null); + + // Re-disable the CSS styling after making the change. + host.disableCssStyling(); + + // Mark the text as having been updated. + this.markUpdated(); + + this.editor.focus(); + } +}); diff --git a/lib/editor/atto/plugins/align/yui/src/button/meta/button.json b/lib/editor/atto/plugins/align/yui/src/button/meta/button.json index 4065cb9084e..cd4d458c329 100644 --- a/lib/editor/atto/plugins/align/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/align/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_align-button": { - "requires": [] - } + "moodle-atto_align-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button-debug.js b/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button-debug.js index eabbe455f32..73273545399 100644 --- a/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button-debug.js +++ b/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button-debug.js @@ -15,123 +15,129 @@ YUI.add('moodle-atto_backcolor-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor background color plugin. - * - * @package editor-atto +/* + * @package atto_backcolor * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_backcolor = M.atto_backcolor || { - init : function(params) { - var plugin = 'backcolor'; - var rgb_white = '#FFFFFF', - rgb_red = '#EF4540', - rgb_yellow = '#FFCF35', - rgb_green = '#98CA3E', - rgb_blue = '#7D9FD3', - rgb_black = '#333333'; +/** + * @module moodle-atto_backcolor-button + */ - var click_white = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_white); - }; - var click_red = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_red); - }; - var click_yellow = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_yellow); - }; - var click_green = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_green); - }; - var click_blue = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_blue); - }; - var click_black = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_black); - }; +/** + * Atto text editor backcolor plugin. + * + * @namespace M.atto_backcolor + * @class button + * @extends M.editor_atto.EditorPlugin + */ - var buttoncss = 'width: 20px; height: 20px; border: 1px solid #CCC; background-color: '; - var white = '
                                        '; - var red = '
                                        '; - var yellow = '
                                        '; - var green = '
                                        '; - var blue = '
                                        '; - var black = '
                                        '; +var doc = document, + BackColor = 'BackColor', + colors = [ + { + name: 'white', + color: '#FFFFFF' + }, { + name: 'red', + color: '#EF4540' + }, { + name: 'yellow', + color: '#FFCF35' + }, { + name: 'green', + color: '#98CA3E' + }, { + name: 'blue', + color: '#7D9FD3' + }, { + name: 'black', + color: '#333333' + } + ]; - var iconurl = M.util.image_url('e/text_highlight', 'core'); +Y.namespace('M.atto_backcolor').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var items = []; + Y.Array.each(colors, function(color) { + items.push({ + text: '
                                        ', + callbackArgs: color.color + }); + }); - M.editor_atto.add_toolbar_menu(params.elementid, - plugin, - iconurl, - params.group, - [ - {'text' : white, 'handler' : click_white}, - {'text' : red, 'handler' : click_red}, - {'text' : yellow, 'handler' : click_yellow}, - {'text' : green, 'handler' : click_green}, - {'text' : blue, 'handler' : click_blue}, - {'text' : black, 'handler' : click_black} - ], - false, - false, - '4'); + this.addToolbarMenu({ + icon: 'e/text_highlight', + overlayWidth: '4', + globalItemConfig: { + callback: this._changeStyle + }, + items: items + }); }, /** - * Handle to change the background color. - * @param event e - The event that triggered this. - * @param string elementid - the elemen id of menu icon. - * @param string color - The color for the background. + * Change the background color to the specified color. + * + * @method _changeStyle + * @param {EventFacade} e + * @param {string} color The new background color + * @private */ - change_color : function(e, elementid, color) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - + _changeStyle: function(e, color) { if (window.getSelection) { // Test for IE9 and non-IE browsers. try { - if (!document.execCommand("BackColor", false, color)) { - M.atto_backcolor.set_back_color(color); + if (!doc.execCommand(BackColor, false, color)) { + this._fallbackChangeStyle(color); } } catch (ex) { - M.atto_backcolor.set_back_color(color); + this._fallbackChangeStyle(color); } - } else if (document.selection && document.selection.createRange) { + } else if (doc.selection && doc.selection.createRange) { // Test for IE8 or less. - range = document.selection.createRange(); - range.execCommand("BackColor", false, color); + range = doc.selection.createRange(); + range.execCommand(BackColor, false, color); } - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + // Mark as updated + this.markUpdated(); }, + /** * Change the background color. - * This function is an alternative use for IE broswers. - * @param string color - The color for the background. + * + * This function is an alternative use for IE browsers. + * + * @method _fallbackChangeStyle + * @param {string} color The color for the background. + * @chainable + * @private */ - set_back_color : function (color) { - var selection = window.getSelection(); - var range = null; + _fallbackChangeStyle: function (color) { + var selection = window.getSelection(), + range; + if (selection.rangeCount && selection.getRangeAt) { range = selection.getRangeAt(0); } - document.designMode = "on"; + doc.designMode = "on"; if (range) { selection.removeAllRanges(); selection.addRange(range); } - if (!document.execCommand("HiliteColor", false, color)) { - document.execCommand("BackColor", false, color); + if (!doc.execCommand("HiliteColor", false, color)) { + doc.execCommand(BackColor, false, color); } - document.designMode = "off"; + doc.designMode = "off"; + + return this; } -}; +}); }, '@VERSION@'); diff --git a/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button-min.js b/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button-min.js index c10a2f48530..870db415bc9 100644 --- a/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button-min.js +++ b/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_backcolor-button",function(e,t){M.atto_backcolor=M.atto_backcolor||{init:function(e){var t="backcolor",n="#FFFFFF",r="#EF4540",i="#FFCF35",s="#98CA3E",o="#7D9FD3",u="#333333",a=function(e,t){M.atto_backcolor.change_color(e,t,n)},f=function(e,t){M.atto_backcolor.change_color(e,t,r)},l=function(e,t){M.atto_backcolor.change_color(e,t,i)},c=function(e,t){M.atto_backcolor.change_color(e,t,s)},h=function(e,t){M.atto_backcolor.change_color(e,t,o)},p=function(e,t){M.atto_backcolor.change_color(e,t,u)},d="width: 20px; height: 20px; border: 1px solid #CCC; background-color: ",v='
                                        ',m='
                                        ',g='
                                        ',y='
                                        ',b='
                                        ',w='
                                        ',E=M.util.image_url("e/text_highlight","core");M.editor_atto.add_toolbar_menu(e.elementid,t,E,e.group,[{text:v,handler:a},{text:m,handler:f},{text:g,handler:l},{text:y,handler:c},{text:b,handler:h},{text:w,handler:p}],!1,!1,"4")},change_color:function(e,t,n){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t);if(window.getSelection)try{document.execCommand("BackColor",!1,n)||M.atto_backcolor.set_back_color(n)}catch(r){M.atto_backcolor.set_back_color(n)}else document.selection&&document.selection.createRange&&(range=document.selection.createRange(),range.execCommand("BackColor",!1,n));M.editor_atto.text_updated(t)},set_back_color:function(e){var t=window.getSelection(),n=null;t.rangeCount&&t.getRangeAt&&(n=t.getRangeAt(0)),document.designMode="on",n&&(t.removeAllRanges(),t.addRange(n)),document.execCommand("HiliteColor",!1,e)||document.execCommand("BackColor",!1,e),document.designMode="off"}}},"@VERSION@"); +YUI.add("moodle-atto_backcolor-button",function(e,t){var n=document,r="BackColor",i=[{name:"white",color:"#FFFFFF"},{name:"red",color:"#EF4540"},{name:"yellow",color:"#FFCF35"},{name:"green",color:"#98CA3E"},{name:"blue",color:"#7D9FD3"},{name:"black",color:"#333333"}];e.namespace("M.atto_backcolor").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var t=[];e.Array.each(i,function(e){t.push({text:'
                                        ',callbackArgs:e.color})}),this.addToolbarMenu({icon:"e/text_highlight",overlayWidth:"4",globalItemConfig:{callback:this._changeStyle},items:t})},_changeStyle:function(e,t){if(window.getSelection)try{n.execCommand(r,!1,t)||this._fallbackChangeStyle(t)}catch(i){this._fallbackChangeStyle(t)}else n.selection&&n.selection.createRange&&(range=n.selection.createRange(),range.execCommand(r,!1,t));this.markUpdated()},_fallbackChangeStyle:function(e){var t=window.getSelection(),i;return t.rangeCount&&t.getRangeAt&&(i=t.getRangeAt(0)),n.designMode="on",i&&(t.removeAllRanges(),t.addRange(i)),n.execCommand("HiliteColor",!1,e)||n.execCommand(r,!1,e),n.designMode="off",this}})},"@VERSION@"); diff --git a/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button.js b/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button.js index eabbe455f32..73273545399 100644 --- a/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button.js +++ b/lib/editor/atto/plugins/backcolor/yui/build/moodle-atto_backcolor-button/moodle-atto_backcolor-button.js @@ -15,123 +15,129 @@ YUI.add('moodle-atto_backcolor-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor background color plugin. - * - * @package editor-atto +/* + * @package atto_backcolor * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_backcolor = M.atto_backcolor || { - init : function(params) { - var plugin = 'backcolor'; - var rgb_white = '#FFFFFF', - rgb_red = '#EF4540', - rgb_yellow = '#FFCF35', - rgb_green = '#98CA3E', - rgb_blue = '#7D9FD3', - rgb_black = '#333333'; +/** + * @module moodle-atto_backcolor-button + */ - var click_white = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_white); - }; - var click_red = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_red); - }; - var click_yellow = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_yellow); - }; - var click_green = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_green); - }; - var click_blue = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_blue); - }; - var click_black = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_black); - }; +/** + * Atto text editor backcolor plugin. + * + * @namespace M.atto_backcolor + * @class button + * @extends M.editor_atto.EditorPlugin + */ - var buttoncss = 'width: 20px; height: 20px; border: 1px solid #CCC; background-color: '; - var white = '
                                        '; - var red = '
                                        '; - var yellow = '
                                        '; - var green = '
                                        '; - var blue = '
                                        '; - var black = '
                                        '; +var doc = document, + BackColor = 'BackColor', + colors = [ + { + name: 'white', + color: '#FFFFFF' + }, { + name: 'red', + color: '#EF4540' + }, { + name: 'yellow', + color: '#FFCF35' + }, { + name: 'green', + color: '#98CA3E' + }, { + name: 'blue', + color: '#7D9FD3' + }, { + name: 'black', + color: '#333333' + } + ]; - var iconurl = M.util.image_url('e/text_highlight', 'core'); +Y.namespace('M.atto_backcolor').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var items = []; + Y.Array.each(colors, function(color) { + items.push({ + text: '
                                        ', + callbackArgs: color.color + }); + }); - M.editor_atto.add_toolbar_menu(params.elementid, - plugin, - iconurl, - params.group, - [ - {'text' : white, 'handler' : click_white}, - {'text' : red, 'handler' : click_red}, - {'text' : yellow, 'handler' : click_yellow}, - {'text' : green, 'handler' : click_green}, - {'text' : blue, 'handler' : click_blue}, - {'text' : black, 'handler' : click_black} - ], - false, - false, - '4'); + this.addToolbarMenu({ + icon: 'e/text_highlight', + overlayWidth: '4', + globalItemConfig: { + callback: this._changeStyle + }, + items: items + }); }, /** - * Handle to change the background color. - * @param event e - The event that triggered this. - * @param string elementid - the elemen id of menu icon. - * @param string color - The color for the background. + * Change the background color to the specified color. + * + * @method _changeStyle + * @param {EventFacade} e + * @param {string} color The new background color + * @private */ - change_color : function(e, elementid, color) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - + _changeStyle: function(e, color) { if (window.getSelection) { // Test for IE9 and non-IE browsers. try { - if (!document.execCommand("BackColor", false, color)) { - M.atto_backcolor.set_back_color(color); + if (!doc.execCommand(BackColor, false, color)) { + this._fallbackChangeStyle(color); } } catch (ex) { - M.atto_backcolor.set_back_color(color); + this._fallbackChangeStyle(color); } - } else if (document.selection && document.selection.createRange) { + } else if (doc.selection && doc.selection.createRange) { // Test for IE8 or less. - range = document.selection.createRange(); - range.execCommand("BackColor", false, color); + range = doc.selection.createRange(); + range.execCommand(BackColor, false, color); } - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + // Mark as updated + this.markUpdated(); }, + /** * Change the background color. - * This function is an alternative use for IE broswers. - * @param string color - The color for the background. + * + * This function is an alternative use for IE browsers. + * + * @method _fallbackChangeStyle + * @param {string} color The color for the background. + * @chainable + * @private */ - set_back_color : function (color) { - var selection = window.getSelection(); - var range = null; + _fallbackChangeStyle: function (color) { + var selection = window.getSelection(), + range; + if (selection.rangeCount && selection.getRangeAt) { range = selection.getRangeAt(0); } - document.designMode = "on"; + doc.designMode = "on"; if (range) { selection.removeAllRanges(); selection.addRange(range); } - if (!document.execCommand("HiliteColor", false, color)) { - document.execCommand("BackColor", false, color); + if (!doc.execCommand("HiliteColor", false, color)) { + doc.execCommand(BackColor, false, color); } - document.designMode = "off"; + doc.designMode = "off"; + + return this; } -}; +}); }, '@VERSION@'); diff --git a/lib/editor/atto/plugins/backcolor/yui/src/button/js/button.js b/lib/editor/atto/plugins/backcolor/yui/src/button/js/button.js index 45ef2cd89a6..26eefc20ab4 100644 --- a/lib/editor/atto/plugins/backcolor/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/backcolor/yui/src/button/js/button.js @@ -13,120 +13,126 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor background color plugin. - * - * @package editor-atto +/* + * @package atto_backcolor * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_backcolor = M.atto_backcolor || { - init : function(params) { - var plugin = 'backcolor'; - var rgb_white = '#FFFFFF', - rgb_red = '#EF4540', - rgb_yellow = '#FFCF35', - rgb_green = '#98CA3E', - rgb_blue = '#7D9FD3', - rgb_black = '#333333'; +/** + * @module moodle-atto_backcolor-button + */ - var click_white = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_white); - }; - var click_red = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_red); - }; - var click_yellow = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_yellow); - }; - var click_green = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_green); - }; - var click_blue = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_blue); - }; - var click_black = function(e, elementid) { - M.atto_backcolor.change_color(e, elementid, rgb_black); - }; +/** + * Atto text editor backcolor plugin. + * + * @namespace M.atto_backcolor + * @class button + * @extends M.editor_atto.EditorPlugin + */ - var buttoncss = 'width: 20px; height: 20px; border: 1px solid #CCC; background-color: '; - var white = '
                                        '; - var red = '
                                        '; - var yellow = '
                                        '; - var green = '
                                        '; - var blue = '
                                        '; - var black = '
                                        '; +var doc = document, + BackColor = 'BackColor', + colors = [ + { + name: 'white', + color: '#FFFFFF' + }, { + name: 'red', + color: '#EF4540' + }, { + name: 'yellow', + color: '#FFCF35' + }, { + name: 'green', + color: '#98CA3E' + }, { + name: 'blue', + color: '#7D9FD3' + }, { + name: 'black', + color: '#333333' + } + ]; - var iconurl = M.util.image_url('e/text_highlight', 'core'); +Y.namespace('M.atto_backcolor').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var items = []; + Y.Array.each(colors, function(color) { + items.push({ + text: '
                                        ', + callbackArgs: color.color + }); + }); - M.editor_atto.add_toolbar_menu(params.elementid, - plugin, - iconurl, - params.group, - [ - {'text' : white, 'handler' : click_white}, - {'text' : red, 'handler' : click_red}, - {'text' : yellow, 'handler' : click_yellow}, - {'text' : green, 'handler' : click_green}, - {'text' : blue, 'handler' : click_blue}, - {'text' : black, 'handler' : click_black} - ], - false, - false, - '4'); + this.addToolbarMenu({ + icon: 'e/text_highlight', + overlayWidth: '4', + globalItemConfig: { + callback: this._changeStyle + }, + items: items + }); }, /** - * Handle to change the background color. - * @param event e - The event that triggered this. - * @param string elementid - the elemen id of menu icon. - * @param string color - The color for the background. + * Change the background color to the specified color. + * + * @method _changeStyle + * @param {EventFacade} e + * @param {string} color The new background color + * @private */ - change_color : function(e, elementid, color) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - + _changeStyle: function(e, color) { if (window.getSelection) { // Test for IE9 and non-IE browsers. try { - if (!document.execCommand("BackColor", false, color)) { - M.atto_backcolor.set_back_color(color); + if (!doc.execCommand(BackColor, false, color)) { + this._fallbackChangeStyle(color); } } catch (ex) { - M.atto_backcolor.set_back_color(color); + this._fallbackChangeStyle(color); } - } else if (document.selection && document.selection.createRange) { + } else if (doc.selection && doc.selection.createRange) { // Test for IE8 or less. - range = document.selection.createRange(); - range.execCommand("BackColor", false, color); + range = doc.selection.createRange(); + range.execCommand(BackColor, false, color); } - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + // Mark as updated + this.markUpdated(); }, + /** * Change the background color. - * This function is an alternative use for IE broswers. - * @param string color - The color for the background. + * + * This function is an alternative use for IE browsers. + * + * @method _fallbackChangeStyle + * @param {string} color The color for the background. + * @chainable + * @private */ - set_back_color : function (color) { - var selection = window.getSelection(); - var range = null; + _fallbackChangeStyle: function (color) { + var selection = window.getSelection(), + range; + if (selection.rangeCount && selection.getRangeAt) { range = selection.getRangeAt(0); } - document.designMode = "on"; + doc.designMode = "on"; if (range) { selection.removeAllRanges(); selection.addRange(range); } - if (!document.execCommand("HiliteColor", false, color)) { - document.execCommand("BackColor", false, color); + if (!doc.execCommand("HiliteColor", false, color)) { + doc.execCommand(BackColor, false, color); } - document.designMode = "off"; + doc.designMode = "off"; + + return this; } -}; +}); 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 6554e4e9d35..3736b77776b 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,50 +15,37 @@ 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 . +/* + * @package atto_bold + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_bold-button */ -var SELECTORS = { - TAGS : 'b,strong' -}; /** * Atto text editor bold plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_bold + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_bold = M.atto_bold || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('bold', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - 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}); +Y.namespace('M.atto_bold').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'bold', - // 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. - M.editor_atto.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'); - } + // Key code for the keyboard shortcut which triggers this button: + keys: '66', + + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'b, strong' }); } -}; +}); -}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 b0c51682bf5..f71bf5858a4 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),M.editor_atto.add_button_shortcut({action:"bold",keys:66}),M.editor_atto.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"]}); +YUI.add("moodle-atto_bold-button",function(e,t){e.namespace("M.atto_bold").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"bold",keys:"66",tags:"b, strong"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 6554e4e9d35..3736b77776b 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,50 +15,37 @@ 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 . +/* + * @package atto_bold + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_bold-button */ -var SELECTORS = { - TAGS : 'b,strong' -}; /** * Atto text editor bold plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_bold + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_bold = M.atto_bold || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('bold', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - 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}); +Y.namespace('M.atto_bold').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'bold', - // 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. - M.editor_atto.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'); - } + // Key code for the keyboard shortcut which triggers this button: + keys: '66', + + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'b, strong' }); } -}; +}); -}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 acff27eae92..7567ffe9842 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,47 +13,34 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_bold + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_bold-button */ -var SELECTORS = { - TAGS : 'b,strong' -}; /** * Atto text editor bold plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_bold + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_bold = M.atto_bold || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('bold', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - 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}); +Y.namespace('M.atto_bold').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'bold', - // 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. - M.editor_atto.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'); - } + // Key code for the keyboard shortcut which triggers this button: + keys: '66', + + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'b, strong' }); } -}; +}); 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 92347fbc33e..c90cc588638 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,8 +1,7 @@ { - "moodle-atto_bold-button": { - "requires": [ - "node", - "moodle-editor_atto-editor-shortcut" - ] - } + "moodle-atto_bold-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-debug.js b/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-debug.js index a638189a5ac..1e339575117 100644 --- a/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-debug.js +++ b/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-debug.js @@ -15,32 +15,24 @@ YUI.add('moodle-atto_charmap-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor charmap plugin. - * +/* * @package atto_charmap * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** - * CSS classes and IDs. + * Atto text editor character map plugin * - * @type {Object} + * @module moodle-atto_charmap-button */ -var CSS = { + +var COMPONENTNAME = 'atto_charmap', + CSS = { BUTTON: 'atto_charmap_character', CHARMAP: 'atto_charmap_selector' }, - /** - * Selectors. - * - * @type {Object} - */ - SELECTORS = { - BUTTON: '.atto_charmap_character' - }, - /** + /* * Map of special characters, kindly borrowed from TinyMCE. * * Each entries contains in order: @@ -49,6 +41,7 @@ var CSS = { * - {Boolean} Whether or not to include it in the list * - {String} The language string key * + * @property CHARMAP * @type {Array} */ CHARMAP = [ @@ -314,128 +307,111 @@ var CSS = { ['­', '­', false,'softhyphen'] ]; -M.atto_charmap = M.atto_charmap || { +/** + * Atto text editor charmap plugin. + * + * @namespace M.atto_charmap + * @class button + * @extends M.editor_atto.EditorPlugin + */ +Y.namespace('M.atto_charmap').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The ID of the current editor. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @type {String} + * @property _currentSelection + * @type Range + * @private */ - currentElementId: null, + _currentSelection: null, - /** - * The dialogue to select a character. - * - * @type {M.core.dialogue} - */ - dialogue: null, - - /** - * Keeps track of the selection made by the user. - * - * @type {Mixed} - */ - selection: null, - - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init: function(params) { - - var display_chooser = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_charmap.selection = M.editor_atto.get_selection(); - if (M.atto_charmap.selection === false) { - return; - } - - // Stores what editor we are working on. - M.atto_charmap.currentElementId = elementid; - - // Initialising the dialogue. - var dialogue; - if (!M.atto_charmap.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - - // Setting up the content of the dialogue. - dialogue.set('bodyContent', M.atto_charmap.getDialogueContent()); - dialogue.set('headerContent', M.util.get_string('insertcharacter', 'atto_charmap')); - dialogue.render(); - dialogue.centerDialogue(); - M.atto_charmap.dialogue = dialogue; - } else { - dialogue = M.atto_charmap.dialogue; - } - - dialogue.show(); - }; - - var iconurl = M.util.image_url('e/special_character', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'charmap', iconurl, params.group, display_chooser); + initializer: function() { + this.addButton({ + icon: 'e/special_character', + callback: this._displayDialogue + }); }, /** - * Generates the content of the dialogue. + * Display the Character Map selector. * - * @return {Node} Node containing the dialogue content + * @method _displayDialogue + * @private */ - getDialogueContent: function() { - var content, - html = '
                                        ', - i; - - for (i = 0; i < CHARMAP.length; i++) { - if (!CHARMAP[i][2]) { - continue; - } - html += ''; + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { + return; } - html += '
                                        '; - content = Y.Node.create(html); - Y.delegate('click', M.atto_charmap.insertChar, content, SELECTORS.BUTTON, this); + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('insertcharacter', COMPONENTNAME), + focusAfterHide: true + }, true); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile( + '
                                        ' + + '{{#each CHARMAP}}' + + '{{#if this.[2]}}' + + '' + + '{{/if}}' + + '{{/each}}' + + '
                                        ' + ); + + var content = Y.Node.create(template({ + component: COMPONENTNAME, + CSS: CSS, + CHARMAP: CHARMAP + })); + + content.delegate('click', this._insertChar, '.' + CSS.BUTTON, this); return content; }, /** - * Insert the picked character in Atto. + * Insert the picked character into the editor. * - * @param {Event} e The event - * @return {Void} + * @method _insertChar + * @param {EventFacade} e + * @private */ - insertChar: function(e) { + _insertChar: function(e) { var character = e.target.getData('character'); - e.preventDefault(); - e.stopPropagation(); - M.atto_charmap.dialogue.hide(); + // Hide the dialogue. + this.getDialogue({ + focusAfterHide: null + }).hide(); - M.editor_atto.set_selection(M.atto_charmap.selection); + var host = this.get('host'); - M.editor_atto.insert_html_at_focus_point(character); + // Focus on the last point. + host.setSelection(this._currentSelection); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(M.atto_charmap.currentElementId); + // And add the character. + host.insertContentAtFocusPoint(character); } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-min.js b/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-min.js index b0a373710df..6ae01e99ad2 100644 --- a/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-min.js +++ b/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-min.js @@ -1,2 +1,2 @@ -YUI.add("moodle-atto_charmap-button",function(e,t){var n={BUTTON:"atto_charmap_character",CHARMAP:"atto_charmap_selector"},r={BUTTON:".atto_charmap_character"},i=[[" "," ",!0,"nobreakspace"],["&","&",!0,"ampersand"],[""",""",!0,"quotationmark"],["¢","¢",!0,"centsign"],["€","€",!0,"eurosign"],["£","£",!0,"poundsign"],["¥","¥",!0,"yensign"],["©","©",!0,"copyrightsign"],["®","®",!0,"registeredsign"],["™","™",!0,"trademarksign"],["‰","‰",!0,"permillesign"],["µ","µ",!0,"microsign"],["·","·",!0,"middledot"],["•","•",!0,"bullet"],["…","…",!0,"threedotleader"],["′","′",!0,"minutesfeet"],["″","″",!0,"secondsinches"],["§","§",!0,"sectionsign"],["¶","¶",!0,"paragraphsign"],["ß","ß",!0,"sharpsesszed"],["‹","‹",!0,"singleleftpointinganglequotationmark"],["›","›",!0,"singlerightpointinganglequotationmark"],["«","«",!0,"leftpointingguillemet"],["»","»",!0,"rightpointingguillemet"],["‘","‘",!0,"leftsinglequotationmark"],["’","’",!0,"rightsinglequotationmark"],["“","“",!0,"leftdoublequotationmark"],["”","”",!0,"rightdoublequotationmark"],["‚","‚",!0,"singlelow9quotationmark"],["„","„",!0,"doublelow9quotationmark"],["<","<",!0,"lessthansign"],[">",">",!0,"greaterthansign"],["≤","≤",!0,"lessthanorequalto"],["≥","≥",!0,"greaterthanorequalto"],["–","–",!0,"endash"],["—","—",!0,"emdash"],["¯","¯",!0,"macron"],["‾","‾",!0,"overline"],["¤","¤",!0,"currencysign"],["¦","¦",!0,"brokenbar"],["¨","¨",!0,"diaeresis"],["¡","¡",!0,"invertedexclamationmark"],["¿","¿",!0,"turnedquestionmark"],["ˆ","ˆ",!0,"circumflexaccent"],["˜","˜",!0,"smalltilde"],["°","°",!0,"degreesign"],["−","−",!0,"minussign"],["±","±",!0,"plusminussign"],["÷","÷",!0,"divisionsign"],["⁄","⁄",!0,"fractionslash"],["×","×",!0,"multiplicationsign"],["¹","¹",!0,"superscriptone"],["²","²",!0,"superscripttwo"],["³","³",!0,"superscriptthree"],["¼","¼",!0,"fractiononequarter"],["½","½",!0,"fractiononehalf"],["¾","¾",!0,"fractionthreequarters"],["ƒ","ƒ",!0,"functionflorin"],["∫","∫",!0,"integral"],["∑","∑",!0,"narysumation"],["∞","∞",!0,"infinity"],["√","√",!0,"squareroot"],["∼","∼",!1,"similarto"],["≅","≅",!1,"approximatelyequalto"],["≈","≈",!0,"almostequalto"],["≠","≠",!0,"notequalto"],["≡","≡",!0,"identicalto"],["∈","∈",!1,"elementof"],["∉","∉",!1,"notanelementof"],["∋","∋",!1,"containsasmember"],["∏","∏",!0,"naryproduct"],["∧","∧",!1,"logicaland"],["∨","∨",!1,"logicalor"],["¬","¬",!0,"notsign"],["∩","∩",!0,"intersection"],["∪","∪",!1,"union"],["∂","∂",!0,"partialdifferential"],["∀","∀",!1,"forall"],["∃","∃",!1,"thereexists"],["∅","∅",!1,"diameter"],["∇","∇",!1,"backwarddifference"],["∗","∗",!1,"asteriskoperator"],["∝","∝",!1,"proportionalto"],["∠","∠",!1,"angle"],["´","´",!0,"acuteaccent"],["¸","¸",!0,"cedilla"],["ª","ª",!0,"feminineordinalindicator"],["º","º",!0,"masculineordinalindicator"],["†","†",!0,"dagger"],["‡","‡",!0,"doubledagger"],["À","À",!0,"agrave_caps"],["Á","Á",!0,"aacute_caps"],["Â","Â",!0,"acircumflex_caps"],["Ã","Ã",!0,"atilde_caps"],["Ä","Ä",!0,"adiaeresis_caps"],["Å","Å",!0,"aringabove_caps"],["Æ","Æ",!0,"ligatureae_caps"],["Ç","Ç",!0,"ccedilla_caps"],["È","È",!0,"egrave_caps"],["É","É",!0,"eacute_caps"],["Ê","Ê",!0,"ecircumflex_caps"],["Ë","Ë",!0,"ediaeresis_caps"],["Ì","Ì",!0,"igrave_caps"],["Í","Í",!0,"iacute_caps"],["Î","Î",!0,"icircumflex_caps"],["Ï","Ï",!0,"idiaeresis_caps"],["Ð","Ð",!0,"eth_caps"],["Ñ","Ñ",!0,"ntilde_caps"],["Ò","Ò",!0,"ograve_caps"],["Ó","Ó",!0,"oacute_caps"],["Ô","Ô",!0,"ocircumflex_caps"],["Õ","Õ",!0,"otilde_caps"],["Ö","Ö",!0,"odiaeresis_caps"],["Ø","Ø",!0,"oslash_caps"],["Œ","Œ",!0,"ligatureoe_caps"],["Š","Š",!0,"scaron_caps"],["Ù","Ù",!0,"ugrave_caps"],["Ú","Ú",!0,"uacute_caps"],["Û","Û",!0,"ucircumflex_caps"],["Ü","Ü",!0,"udiaeresis_caps"],["Ý","Ý",!0,"yacute_caps"],["Ÿ","Ÿ",!0,"ydiaeresis_caps"],["Þ","Þ",!0,"thorn_caps"],["à","à",!0,"agrave"],["á","á",!0,"aacute"],["â","â",!0,"acircumflex"],["ã","ã",!0,"atilde"],["ä","ä",!0,"adiaeresis"],["å","å",!0,"aringabove"],["æ","æ",!0,"ligatureae"],["ç","ç",!0,"ccedilla"],["è","è",!0,"egrave"],["é","é",!0,"eacute"],["ê","ê",!0,"ecircumflex"],["ë","ë",!0,"ediaeresis"],["ì","ì",!0,"igrave"],["í","í",!0,"iacute"],["î","î",!0,"icircumflex"],["ï","ï",!0,"idiaeresis"],["ð","ð",!0,"eth"],["ñ","ñ",!0,"ntilde"],["ò","ò",!0,"ograve"],["ó","ó",!0,"oacute"],["ô","ô",!0,"ocircumflex"],["õ","õ",!0,"otilde"],["ö","ö",!0,"odiaeresis"],["ø","ø",!0,"oslash"],["œ","œ",!0,"ligatureoe" -],["š","š",!0,"scaron"],["ù","ù",!0,"ugrave"],["ú","ú",!0,"uacute"],["û","û",!0,"ucircumflex"],["ü","ü",!0,"udiaeresis"],["ý","ý",!0,"yacute"],["þ","þ",!0,"thorn"],["ÿ","ÿ",!0,"ydiaeresis"],["Α","Α",!0,"alpha_caps"],["Β","Β",!0,"beta_caps"],["Γ","Γ",!0,"gamma_caps"],["Δ","Δ",!0,"delta_caps"],["Ε","Ε",!0,"epsilon_caps"],["Ζ","Ζ",!0,"zeta_caps"],["Η","Η",!0,"eta_caps"],["Θ","Θ",!0,"theta_caps"],["Ι","Ι",!0,"iota_caps"],["Κ","Κ",!0,"kappa_caps"],["Λ","Λ",!0,"lambda_caps"],["Μ","Μ",!0,"mu_caps"],["Ν","Ν",!0,"nu_caps"],["Ξ","Ξ",!0,"xi_caps"],["Ο","Ο",!0,"omicron_caps"],["Π","Π",!0,"pi_caps"],["Ρ","Ρ",!0,"rho_caps"],["Σ","Σ",!0,"sigma_caps"],["Τ","Τ",!0,"tau_caps"],["Υ","Υ",!0,"upsilon_caps"],["Φ","Φ",!0,"phi_caps"],["Χ","Χ",!0,"chi_caps"],["Ψ","Ψ",!0,"psi_caps"],["Ω","Ω",!0,"omega_caps"],["α","α",!0,"alpha"],["β","β",!0,"beta"],["γ","γ",!0,"gamma"],["δ","δ",!0,"delta"],["ε","ε",!0,"epsilon"],["ζ","ζ",!0,"zeta"],["η","η",!0,"eta"],["θ","θ",!0,"theta"],["ι","ι",!0,"iota"],["κ","κ",!0,"kappa"],["λ","λ",!0,"lambda"],["μ","μ",!0,"mu"],["ν","ν",!0,"nu"],["ξ","ξ",!0,"xi"],["ο","ο",!0,"omicron"],["π","π",!0,"pi"],["ρ","ρ",!0,"rho"],["ς","ς",!0,"finalsigma"],["σ","σ",!0,"sigma"],["τ","τ",!0,"tau"],["υ","υ",!0,"upsilon"],["φ","φ",!0,"phi"],["χ","χ",!0,"chi"],["ψ","ψ",!0,"psi"],["ω","ω",!0,"omega"],["ℵ","ℵ",!1,"alefsymbol"],["ϖ","ϖ",!1,"pisymbol"],["ℜ","ℜ",!1,"realpartsymbol"],["ϑ","ϑ",!1,"thetasymbol"],["ϒ","ϒ",!1,"upsilonhooksymbol"],["℘","℘",!1,"weierstrassp"],["ℑ","ℑ",!1,"imaginarypart"],["←","←",!0,"leftwardsarrow"],["↑","↑",!0,"upwardsarrow"],["→","→",!0,"rightwardsarrow"],["↓","↓",!0,"downwardsarrow"],["↔","↔",!0,"leftrightarrow"],["↵","↵",!1,"carriagereturn"],["⇐","⇐",!1,"leftwardsdoublearrow"],["⇑","⇑",!1,"upwardsdoublearrow"],["⇒","⇒",!1,"rightwardsdoublearrow"],["⇓","⇓",!1,"downwardsdoublearrow"],["⇔","⇔",!1,"leftrightdoublearrow"],["∴","∴",!1,"therefore"],["⊂","⊂",!1,"subsetof"],["⊃","⊃",!1,"supersetof"],["⊄","⊄",!1,"notasubsetof"],["⊆","⊆",!1,"subsetoforequalto"],["⊇","⊇",!1,"supersetoforequalto"],["⊕","⊕",!1,"circledplus"],["⊗","⊗",!1,"circledtimes"],["⊥","⊥",!1,"perpendicular"],["⋅","⋅",!1,"dotoperator"],["⌈","⌈",!1,"leftceiling"],["⌉","⌉",!1,"rightceiling"],["⌊","⌊",!1,"leftfloor"],["⌋","⌋",!1,"rightfloor"],["⟨","〈",!1,"leftpointinganglebracket"],["⟩","〉",!1,"rightpointinganglebracket"],["◊","◊",!0,"lozenge"],["♠","♠",!0,"blackspadesuit"],["♣","♣",!0,"blackclubsuit"],["♥","♥",!0,"blackheartsuit"],["♦","♦",!0,"blackdiamondsuit"],[" "," ",!1,"enspace"],[" "," ",!1,"emspace"],[" "," ",!1,"thinspace"],["‌","‌",!1,"zerowidthnonjoiner"],["‍","‍",!1,"zerowidthjoiner"],["‎","‎",!1,"lefttorightmark"],["‏","‏",!1,"righttoleftmark"],["­","­",!1,"softhyphen"]];M.atto_charmap=M.atto_charmap||{currentElementId:null,dialogue:null,selection:null,init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_charmap.selection=M.editor_atto.get_selection();if(M.atto_charmap.selection===!1)return;M.atto_charmap.currentElementId=t;var n;M.atto_charmap.dialogue?n=M.atto_charmap.dialogue:(n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.set("bodyContent",M.atto_charmap.getDialogueContent()),n.set("headerContent",M.util.get_string("insertcharacter","atto_charmap")),n.render(),n.centerDialogue(),M.atto_charmap.dialogue=n),n.show()},n=M.util.image_url("e/special_character","core");M.editor_atto.add_toolbar_button(e.elementid,"charmap",n,e.group,t)},getDialogueContent:function(){var t,s='
                                        ',o;for(o=0;o"+i[o][0]+""}return s+="
                                        ",t=e.Node.create(s),e.delegate("click",M.atto_charmap.insertChar,t,r.BUTTON,this),t},insertChar:function(e){var t=e.target.getData("character");e.preventDefault(),e.stopPropagation(),M.atto_charmap.dialogue.hide(),M.editor_atto.set_selection(M.atto_charmap.selection),M.editor_atto.insert_html_at_focus_point(t),M.editor_atto.text_updated(M.atto_charmap.currentElementId)}}},"@VERSION@",{requires:["node","escape"]}); +YUI.add("moodle-atto_charmap-button",function(e,t){var n="atto_charmap",r={BUTTON:"atto_charmap_character",CHARMAP:"atto_charmap_selector"},i=[[" "," ",!0,"nobreakspace"],["&","&",!0,"ampersand"],[""",""",!0,"quotationmark"],["¢","¢",!0,"centsign"],["€","€",!0,"eurosign"],["£","£",!0,"poundsign"],["¥","¥",!0,"yensign"],["©","©",!0,"copyrightsign"],["®","®",!0,"registeredsign"],["™","™",!0,"trademarksign"],["‰","‰",!0,"permillesign"],["µ","µ",!0,"microsign"],["·","·",!0,"middledot"],["•","•",!0,"bullet"],["…","…",!0,"threedotleader"],["′","′",!0,"minutesfeet"],["″","″",!0,"secondsinches"],["§","§",!0,"sectionsign"],["¶","¶",!0,"paragraphsign"],["ß","ß",!0,"sharpsesszed"],["‹","‹",!0,"singleleftpointinganglequotationmark"],["›","›",!0,"singlerightpointinganglequotationmark"],["«","«",!0,"leftpointingguillemet"],["»","»",!0,"rightpointingguillemet"],["‘","‘",!0,"leftsinglequotationmark"],["’","’",!0,"rightsinglequotationmark"],["“","“",!0,"leftdoublequotationmark"],["”","”",!0,"rightdoublequotationmark"],["‚","‚",!0,"singlelow9quotationmark"],["„","„",!0,"doublelow9quotationmark"],["<","<",!0,"lessthansign"],[">",">",!0,"greaterthansign"],["≤","≤",!0,"lessthanorequalto"],["≥","≥",!0,"greaterthanorequalto"],["–","–",!0,"endash"],["—","—",!0,"emdash"],["¯","¯",!0,"macron"],["‾","‾",!0,"overline"],["¤","¤",!0,"currencysign"],["¦","¦",!0,"brokenbar"],["¨","¨",!0,"diaeresis"],["¡","¡",!0,"invertedexclamationmark"],["¿","¿",!0,"turnedquestionmark"],["ˆ","ˆ",!0,"circumflexaccent"],["˜","˜",!0,"smalltilde"],["°","°",!0,"degreesign"],["−","−",!0,"minussign"],["±","±",!0,"plusminussign"],["÷","÷",!0,"divisionsign"],["⁄","⁄",!0,"fractionslash"],["×","×",!0,"multiplicationsign"],["¹","¹",!0,"superscriptone"],["²","²",!0,"superscripttwo"],["³","³",!0,"superscriptthree"],["¼","¼",!0,"fractiononequarter"],["½","½",!0,"fractiononehalf"],["¾","¾",!0,"fractionthreequarters"],["ƒ","ƒ",!0,"functionflorin"],["∫","∫",!0,"integral"],["∑","∑",!0,"narysumation"],["∞","∞",!0,"infinity"],["√","√",!0,"squareroot"],["∼","∼",!1,"similarto"],["≅","≅",!1,"approximatelyequalto"],["≈","≈",!0,"almostequalto"],["≠","≠",!0,"notequalto"],["≡","≡",!0,"identicalto"],["∈","∈",!1,"elementof"],["∉","∉",!1,"notanelementof"],["∋","∋",!1,"containsasmember"],["∏","∏",!0,"naryproduct"],["∧","∧",!1,"logicaland"],["∨","∨",!1,"logicalor"],["¬","¬",!0,"notsign"],["∩","∩",!0,"intersection"],["∪","∪",!1,"union"],["∂","∂",!0,"partialdifferential"],["∀","∀",!1,"forall"],["∃","∃",!1,"thereexists"],["∅","∅",!1,"diameter"],["∇","∇",!1,"backwarddifference"],["∗","∗",!1,"asteriskoperator"],["∝","∝",!1,"proportionalto"],["∠","∠",!1,"angle"],["´","´",!0,"acuteaccent"],["¸","¸",!0,"cedilla"],["ª","ª",!0,"feminineordinalindicator"],["º","º",!0,"masculineordinalindicator"],["†","†",!0,"dagger"],["‡","‡",!0,"doubledagger"],["À","À",!0,"agrave_caps"],["Á","Á",!0,"aacute_caps"],["Â","Â",!0,"acircumflex_caps"],["Ã","Ã",!0,"atilde_caps"],["Ä","Ä",!0,"adiaeresis_caps"],["Å","Å",!0,"aringabove_caps"],["Æ","Æ",!0,"ligatureae_caps"],["Ç","Ç",!0,"ccedilla_caps"],["È","È",!0,"egrave_caps"],["É","É",!0,"eacute_caps"],["Ê","Ê",!0,"ecircumflex_caps"],["Ë","Ë",!0,"ediaeresis_caps"],["Ì","Ì",!0,"igrave_caps"],["Í","Í",!0,"iacute_caps"],["Î","Î",!0,"icircumflex_caps"],["Ï","Ï",!0,"idiaeresis_caps"],["Ð","Ð",!0,"eth_caps"],["Ñ","Ñ",!0,"ntilde_caps"],["Ò","Ò",!0,"ograve_caps"],["Ó","Ó",!0,"oacute_caps"],["Ô","Ô",!0,"ocircumflex_caps"],["Õ","Õ",!0,"otilde_caps"],["Ö","Ö",!0,"odiaeresis_caps"],["Ø","Ø",!0,"oslash_caps"],["Œ","Œ",!0,"ligatureoe_caps"],["Š","Š",!0,"scaron_caps"],["Ù","Ù",!0,"ugrave_caps"],["Ú","Ú",!0,"uacute_caps"],["Û","Û",!0,"ucircumflex_caps"],["Ü","Ü",!0,"udiaeresis_caps"],["Ý","Ý",!0,"yacute_caps"],["Ÿ","Ÿ",!0,"ydiaeresis_caps"],["Þ","Þ",!0,"thorn_caps"],["à","à",!0,"agrave"],["á","á",!0,"aacute"],["â","â",!0,"acircumflex"],["ã","ã",!0,"atilde"],["ä","ä",!0,"adiaeresis"],["å","å",!0,"aringabove"],["æ","æ",!0,"ligatureae"],["ç","ç",!0,"ccedilla"],["è","è",!0,"egrave"],["é","é",!0,"eacute"],["ê","ê",!0,"ecircumflex"],["ë","ë",!0,"ediaeresis"],["ì","ì",!0,"igrave"],["í","í",!0,"iacute"],["î","î",!0,"icircumflex"],["ï","ï",!0,"idiaeresis"],["ð","ð",!0,"eth"],["ñ","ñ",!0,"ntilde"],["ò","ò",!0,"ograve"],["ó","ó",!0,"oacute"],["ô","ô",!0,"ocircumflex"],["õ","õ",!0,"otilde"],["ö","ö",!0,"odiaeresis"],["ø","ø",!0,"oslash"],["œ","œ",!0,"ligatureoe"],["š" +,"š",!0,"scaron"],["ù","ù",!0,"ugrave"],["ú","ú",!0,"uacute"],["û","û",!0,"ucircumflex"],["ü","ü",!0,"udiaeresis"],["ý","ý",!0,"yacute"],["þ","þ",!0,"thorn"],["ÿ","ÿ",!0,"ydiaeresis"],["Α","Α",!0,"alpha_caps"],["Β","Β",!0,"beta_caps"],["Γ","Γ",!0,"gamma_caps"],["Δ","Δ",!0,"delta_caps"],["Ε","Ε",!0,"epsilon_caps"],["Ζ","Ζ",!0,"zeta_caps"],["Η","Η",!0,"eta_caps"],["Θ","Θ",!0,"theta_caps"],["Ι","Ι",!0,"iota_caps"],["Κ","Κ",!0,"kappa_caps"],["Λ","Λ",!0,"lambda_caps"],["Μ","Μ",!0,"mu_caps"],["Ν","Ν",!0,"nu_caps"],["Ξ","Ξ",!0,"xi_caps"],["Ο","Ο",!0,"omicron_caps"],["Π","Π",!0,"pi_caps"],["Ρ","Ρ",!0,"rho_caps"],["Σ","Σ",!0,"sigma_caps"],["Τ","Τ",!0,"tau_caps"],["Υ","Υ",!0,"upsilon_caps"],["Φ","Φ",!0,"phi_caps"],["Χ","Χ",!0,"chi_caps"],["Ψ","Ψ",!0,"psi_caps"],["Ω","Ω",!0,"omega_caps"],["α","α",!0,"alpha"],["β","β",!0,"beta"],["γ","γ",!0,"gamma"],["δ","δ",!0,"delta"],["ε","ε",!0,"epsilon"],["ζ","ζ",!0,"zeta"],["η","η",!0,"eta"],["θ","θ",!0,"theta"],["ι","ι",!0,"iota"],["κ","κ",!0,"kappa"],["λ","λ",!0,"lambda"],["μ","μ",!0,"mu"],["ν","ν",!0,"nu"],["ξ","ξ",!0,"xi"],["ο","ο",!0,"omicron"],["π","π",!0,"pi"],["ρ","ρ",!0,"rho"],["ς","ς",!0,"finalsigma"],["σ","σ",!0,"sigma"],["τ","τ",!0,"tau"],["υ","υ",!0,"upsilon"],["φ","φ",!0,"phi"],["χ","χ",!0,"chi"],["ψ","ψ",!0,"psi"],["ω","ω",!0,"omega"],["ℵ","ℵ",!1,"alefsymbol"],["ϖ","ϖ",!1,"pisymbol"],["ℜ","ℜ",!1,"realpartsymbol"],["ϑ","ϑ",!1,"thetasymbol"],["ϒ","ϒ",!1,"upsilonhooksymbol"],["℘","℘",!1,"weierstrassp"],["ℑ","ℑ",!1,"imaginarypart"],["←","←",!0,"leftwardsarrow"],["↑","↑",!0,"upwardsarrow"],["→","→",!0,"rightwardsarrow"],["↓","↓",!0,"downwardsarrow"],["↔","↔",!0,"leftrightarrow"],["↵","↵",!1,"carriagereturn"],["⇐","⇐",!1,"leftwardsdoublearrow"],["⇑","⇑",!1,"upwardsdoublearrow"],["⇒","⇒",!1,"rightwardsdoublearrow"],["⇓","⇓",!1,"downwardsdoublearrow"],["⇔","⇔",!1,"leftrightdoublearrow"],["∴","∴",!1,"therefore"],["⊂","⊂",!1,"subsetof"],["⊃","⊃",!1,"supersetof"],["⊄","⊄",!1,"notasubsetof"],["⊆","⊆",!1,"subsetoforequalto"],["⊇","⊇",!1,"supersetoforequalto"],["⊕","⊕",!1,"circledplus"],["⊗","⊗",!1,"circledtimes"],["⊥","⊥",!1,"perpendicular"],["⋅","⋅",!1,"dotoperator"],["⌈","⌈",!1,"leftceiling"],["⌉","⌉",!1,"rightceiling"],["⌊","⌊",!1,"leftfloor"],["⌋","⌋",!1,"rightfloor"],["⟨","〈",!1,"leftpointinganglebracket"],["⟩","〉",!1,"rightpointinganglebracket"],["◊","◊",!0,"lozenge"],["♠","♠",!0,"blackspadesuit"],["♣","♣",!0,"blackclubsuit"],["♥","♥",!0,"blackheartsuit"],["♦","♦",!0,"blackdiamondsuit"],[" "," ",!1,"enspace"],[" "," ",!1,"emspace"],[" "," ",!1,"thinspace"],["‌","‌",!1,"zerowidthnonjoiner"],["‍","‍",!1,"zerowidthjoiner"],["‎","‎",!1,"lefttorightmark"],["‏","‏",!1,"righttoleftmark"],["­","­",!1,"softhyphen"]];e.namespace("M.atto_charmap").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,initializer:function(){this.addButton({icon:"e/special_character",callback:this._displayDialogue})},_displayDialogue:function(){this._currentSelection=this.get("host").getSelection();if(this._currentSelection===!1)return;var e=this.getDialogue({headerContent:M.util.get_string("insertcharacter",n),focusAfterHide:!0},!0);e.set("bodyContent",this._getDialogueContent()).show()},_getDialogueContent:function(){var t=e.Handlebars.compile('
                                        {{#each CHARMAP}}{{#if this.[2]}}{{/if}}{{/each}}
                                        '),s=e.Node.create(t({component:n,CSS:r,CHARMAP:i}));return s.delegate("click",this._insertChar,"."+r.BUTTON,this),s},_insertChar:function(e){var t=e.target.getData("character");this.getDialogue({focusAfterHide:null}).hide();var n=this.get("host");n.setSelection(this._currentSelection),n.insertContentAtFocusPoint(t)}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button.js b/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button.js index a638189a5ac..1e339575117 100644 --- a/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button.js +++ b/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button.js @@ -15,32 +15,24 @@ YUI.add('moodle-atto_charmap-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor charmap plugin. - * +/* * @package atto_charmap * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** - * CSS classes and IDs. + * Atto text editor character map plugin * - * @type {Object} + * @module moodle-atto_charmap-button */ -var CSS = { + +var COMPONENTNAME = 'atto_charmap', + CSS = { BUTTON: 'atto_charmap_character', CHARMAP: 'atto_charmap_selector' }, - /** - * Selectors. - * - * @type {Object} - */ - SELECTORS = { - BUTTON: '.atto_charmap_character' - }, - /** + /* * Map of special characters, kindly borrowed from TinyMCE. * * Each entries contains in order: @@ -49,6 +41,7 @@ var CSS = { * - {Boolean} Whether or not to include it in the list * - {String} The language string key * + * @property CHARMAP * @type {Array} */ CHARMAP = [ @@ -314,128 +307,111 @@ var CSS = { ['­', '­', false,'softhyphen'] ]; -M.atto_charmap = M.atto_charmap || { +/** + * Atto text editor charmap plugin. + * + * @namespace M.atto_charmap + * @class button + * @extends M.editor_atto.EditorPlugin + */ +Y.namespace('M.atto_charmap').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The ID of the current editor. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @type {String} + * @property _currentSelection + * @type Range + * @private */ - currentElementId: null, + _currentSelection: null, - /** - * The dialogue to select a character. - * - * @type {M.core.dialogue} - */ - dialogue: null, - - /** - * Keeps track of the selection made by the user. - * - * @type {Mixed} - */ - selection: null, - - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init: function(params) { - - var display_chooser = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_charmap.selection = M.editor_atto.get_selection(); - if (M.atto_charmap.selection === false) { - return; - } - - // Stores what editor we are working on. - M.atto_charmap.currentElementId = elementid; - - // Initialising the dialogue. - var dialogue; - if (!M.atto_charmap.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - - // Setting up the content of the dialogue. - dialogue.set('bodyContent', M.atto_charmap.getDialogueContent()); - dialogue.set('headerContent', M.util.get_string('insertcharacter', 'atto_charmap')); - dialogue.render(); - dialogue.centerDialogue(); - M.atto_charmap.dialogue = dialogue; - } else { - dialogue = M.atto_charmap.dialogue; - } - - dialogue.show(); - }; - - var iconurl = M.util.image_url('e/special_character', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'charmap', iconurl, params.group, display_chooser); + initializer: function() { + this.addButton({ + icon: 'e/special_character', + callback: this._displayDialogue + }); }, /** - * Generates the content of the dialogue. + * Display the Character Map selector. * - * @return {Node} Node containing the dialogue content + * @method _displayDialogue + * @private */ - getDialogueContent: function() { - var content, - html = '
                                        ', - i; - - for (i = 0; i < CHARMAP.length; i++) { - if (!CHARMAP[i][2]) { - continue; - } - html += ''; + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { + return; } - html += '
                                        '; - content = Y.Node.create(html); - Y.delegate('click', M.atto_charmap.insertChar, content, SELECTORS.BUTTON, this); + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('insertcharacter', COMPONENTNAME), + focusAfterHide: true + }, true); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile( + '
                                        ' + + '{{#each CHARMAP}}' + + '{{#if this.[2]}}' + + '' + + '{{/if}}' + + '{{/each}}' + + '
                                        ' + ); + + var content = Y.Node.create(template({ + component: COMPONENTNAME, + CSS: CSS, + CHARMAP: CHARMAP + })); + + content.delegate('click', this._insertChar, '.' + CSS.BUTTON, this); return content; }, /** - * Insert the picked character in Atto. + * Insert the picked character into the editor. * - * @param {Event} e The event - * @return {Void} + * @method _insertChar + * @param {EventFacade} e + * @private */ - insertChar: function(e) { + _insertChar: function(e) { var character = e.target.getData('character'); - e.preventDefault(); - e.stopPropagation(); - M.atto_charmap.dialogue.hide(); + // Hide the dialogue. + this.getDialogue({ + focusAfterHide: null + }).hide(); - M.editor_atto.set_selection(M.atto_charmap.selection); + var host = this.get('host'); - M.editor_atto.insert_html_at_focus_point(character); + // Focus on the last point. + host.setSelection(this._currentSelection); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(M.atto_charmap.currentElementId); + // And add the character. + host.insertContentAtFocusPoint(character); } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/charmap/yui/src/button/js/button.js b/lib/editor/atto/plugins/charmap/yui/src/button/js/button.js index ad0a81f785d..f777e3b0ce8 100644 --- a/lib/editor/atto/plugins/charmap/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/charmap/yui/src/button/js/button.js @@ -13,32 +13,24 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor charmap plugin. - * +/* * @package atto_charmap * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** - * CSS classes and IDs. + * Atto text editor character map plugin * - * @type {Object} + * @module moodle-atto_charmap-button */ -var CSS = { + +var COMPONENTNAME = 'atto_charmap', + CSS = { BUTTON: 'atto_charmap_character', CHARMAP: 'atto_charmap_selector' }, - /** - * Selectors. - * - * @type {Object} - */ - SELECTORS = { - BUTTON: '.atto_charmap_character' - }, - /** + /* * Map of special characters, kindly borrowed from TinyMCE. * * Each entries contains in order: @@ -47,6 +39,7 @@ var CSS = { * - {Boolean} Whether or not to include it in the list * - {String} The language string key * + * @property CHARMAP * @type {Array} */ CHARMAP = [ @@ -312,125 +305,108 @@ var CSS = { ['­', '­', false,'softhyphen'] ]; -M.atto_charmap = M.atto_charmap || { +/** + * Atto text editor charmap plugin. + * + * @namespace M.atto_charmap + * @class button + * @extends M.editor_atto.EditorPlugin + */ +Y.namespace('M.atto_charmap').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The ID of the current editor. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @type {String} + * @property _currentSelection + * @type Range + * @private */ - currentElementId: null, + _currentSelection: null, - /** - * The dialogue to select a character. - * - * @type {M.core.dialogue} - */ - dialogue: null, - - /** - * Keeps track of the selection made by the user. - * - * @type {Mixed} - */ - selection: null, - - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init: function(params) { - - var display_chooser = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_charmap.selection = M.editor_atto.get_selection(); - if (M.atto_charmap.selection === false) { - return; - } - - // Stores what editor we are working on. - M.atto_charmap.currentElementId = elementid; - - // Initialising the dialogue. - var dialogue; - if (!M.atto_charmap.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - - // Setting up the content of the dialogue. - dialogue.set('bodyContent', M.atto_charmap.getDialogueContent()); - dialogue.set('headerContent', M.util.get_string('insertcharacter', 'atto_charmap')); - dialogue.render(); - dialogue.centerDialogue(); - M.atto_charmap.dialogue = dialogue; - } else { - dialogue = M.atto_charmap.dialogue; - } - - dialogue.show(); - }; - - var iconurl = M.util.image_url('e/special_character', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'charmap', iconurl, params.group, display_chooser); + initializer: function() { + this.addButton({ + icon: 'e/special_character', + callback: this._displayDialogue + }); }, /** - * Generates the content of the dialogue. + * Display the Character Map selector. * - * @return {Node} Node containing the dialogue content + * @method _displayDialogue + * @private */ - getDialogueContent: function() { - var content, - html = '
                                        ', - i; - - for (i = 0; i < CHARMAP.length; i++) { - if (!CHARMAP[i][2]) { - continue; - } - html += ''; + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { + return; } - html += '
                                        '; - content = Y.Node.create(html); - Y.delegate('click', M.atto_charmap.insertChar, content, SELECTORS.BUTTON, this); + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('insertcharacter', COMPONENTNAME), + focusAfterHide: true + }, true); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile( + '
                                        ' + + '{{#each CHARMAP}}' + + '{{#if this.[2]}}' + + '' + + '{{/if}}' + + '{{/each}}' + + '
                                        ' + ); + + var content = Y.Node.create(template({ + component: COMPONENTNAME, + CSS: CSS, + CHARMAP: CHARMAP + })); + + content.delegate('click', this._insertChar, '.' + CSS.BUTTON, this); return content; }, /** - * Insert the picked character in Atto. + * Insert the picked character into the editor. * - * @param {Event} e The event - * @return {Void} + * @method _insertChar + * @param {EventFacade} e + * @private */ - insertChar: function(e) { + _insertChar: function(e) { var character = e.target.getData('character'); - e.preventDefault(); - e.stopPropagation(); - M.atto_charmap.dialogue.hide(); + // Hide the dialogue. + this.getDialogue({ + focusAfterHide: null + }).hide(); - M.editor_atto.set_selection(M.atto_charmap.selection); + var host = this.get('host'); - M.editor_atto.insert_html_at_focus_point(character); + // Focus on the last point. + host.setSelection(this._currentSelection); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(M.atto_charmap.currentElementId); + // And add the character. + host.insertContentAtFocusPoint(character); } -}; +}); diff --git a/lib/editor/atto/plugins/charmap/yui/src/button/meta/button.json b/lib/editor/atto/plugins/charmap/yui/src/button/meta/button.json index 8f6c36ed8f3..46d3d5e9b78 100644 --- a/lib/editor/atto/plugins/charmap/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/charmap/yui/src/button/meta/button.json @@ -1,8 +1,7 @@ { - "moodle-atto_charmap-button": { - "requires": [ - "node", - "escape" - ] - } + "moodle-atto_charmap-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button-debug.js b/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button-debug.js index 1f30fd06b46..abd59108660 100644 --- a/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button-debug.js +++ b/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button-debug.js @@ -15,29 +15,32 @@ YUI.add('moodle-atto_clear-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor clear plugin. - * - * @package editor-atto +/* + * @package atto_clear * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_clear = M.atto_clear || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('removeFormat', false); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/clear_formatting', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'clear', iconurl, params.group, click); +/** + * @module moodle-atto_clear-button + */ + +/** + * Atto text editor clear plugin. + * + * @namespace M.atto_clear + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_clear').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'removeFormat', + icon: 'e/clear_formatting' + }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button-min.js b/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button-min.js index 7fdec51985d..41a005e664c 100644 --- a/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button-min.js +++ b/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_clear-button",function(e,t){M.atto_clear=M.atto_clear||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("removeFormat",!1),M.editor_atto.text_updated(t)},n=M.util.image_url("e/clear_formatting","core");M.editor_atto.add_toolbar_button(e.elementid,"clear",n,e.group,t)}}},"@VERSION@",{requires:["node"]}); +YUI.add("moodle-atto_clear-button",function(e,t){e.namespace("M.atto_clear").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"removeFormat",icon:"e/clear_formatting"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button.js b/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button.js index 1f30fd06b46..abd59108660 100644 --- a/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button.js +++ b/lib/editor/atto/plugins/clear/yui/build/moodle-atto_clear-button/moodle-atto_clear-button.js @@ -15,29 +15,32 @@ YUI.add('moodle-atto_clear-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor clear plugin. - * - * @package editor-atto +/* + * @package atto_clear * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_clear = M.atto_clear || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('removeFormat', false); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/clear_formatting', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'clear', iconurl, params.group, click); +/** + * @module moodle-atto_clear-button + */ + +/** + * Atto text editor clear plugin. + * + * @namespace M.atto_clear + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_clear').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'removeFormat', + icon: 'e/clear_formatting' + }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/clear/yui/src/button/js/button.js b/lib/editor/atto/plugins/clear/yui/src/button/js/button.js index d40078a4127..6d4fc5583fc 100644 --- a/lib/editor/atto/plugins/clear/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/clear/yui/src/button/js/button.js @@ -13,26 +13,29 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor clear plugin. - * - * @package editor-atto +/* + * @package atto_clear * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_clear = M.atto_clear || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('removeFormat', false); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/clear_formatting', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'clear', iconurl, params.group, click); +/** + * @module moodle-atto_clear-button + */ + +/** + * Atto text editor clear plugin. + * + * @namespace M.atto_clear + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_clear').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'removeFormat', + icon: 'e/clear_formatting' + }); } -}; +}); diff --git a/lib/editor/atto/plugins/clear/yui/src/button/meta/button.json b/lib/editor/atto/plugins/clear/yui/src/button/meta/button.json index 39aab1ce8c8..10697073e4d 100644 --- a/lib/editor/atto/plugins/clear/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/clear/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_clear-button": { - "requires": ["node"] - } + "moodle-atto_clear-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/collapse/lang/en/atto_collapse.php b/lib/editor/atto/plugins/collapse/lang/en/atto_collapse.php index b9f75ed72a7..e81a608c26c 100644 --- a/lib/editor/atto/plugins/collapse/lang/en/atto_collapse.php +++ b/lib/editor/atto/plugins/collapse/lang/en/atto_collapse.php @@ -24,7 +24,7 @@ $string['pluginname'] = 'Show/hide advanced buttons'; $string['showmore'] = 'Show more buttons'; -$string['showless'] = 'Show less buttons'; +$string['showfewer'] = 'Show fewer buttons'; $string['settings'] = 'Collapse toolbar settings'; $string['showgroups'] = 'Show (n) groups when collapsed.'; $string['showgroups_desc'] = 'When the toolbar is collapsed (it is by default) only this many groups will be displayed at once.'; diff --git a/lib/editor/atto/plugins/collapse/lib.php b/lib/editor/atto/plugins/collapse/lib.php index 6b0987ccc57..94b1e839036 100644 --- a/lib/editor/atto/plugins/collapse/lib.php +++ b/lib/editor/atto/plugins/collapse/lib.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); function atto_collapse_strings_for_js() { global $PAGE; - $PAGE->requires->strings_for_js(array('showmore', 'showless'), 'atto_collapse'); + $PAGE->requires->strings_for_js(array('showmore', 'showfewer'), 'atto_collapse'); } /** diff --git a/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button-debug.js b/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button-debug.js index dea66443540..0e112b81d00 100644 --- a/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button-debug.js +++ b/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button-debug.js @@ -15,99 +15,101 @@ YUI.add('moodle-atto_collapse-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * CSS Selectors - * - * @type {Object} - */ -var SELECTORS = { - GROUPS: '.atto_group', - BUTTON: '.atto_collapse_button' -}; - -/** - * Atto text editor collapse plugin. - * +/* * @package atto_collapse * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_collapse = M.atto_collapse || { - /** - * How many groups to show when collapsed. - * - * @property showgroups - * @type {Integer} - * @default 3 - */ - showgroups : 3, +/** + * @module moodle-atto_collapse-button + */ - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - M.atto_collapse.toggle(elementid); - }; +/** + * Atto text editor collapse plugin. + * + * @namespace M.atto_collapse + * @class button + * @extends M.editor_atto.EditorPlugin + */ - this.showgroups = params.showgroups; +var PLUGINNAME = 'atto_collapse', + ATTRSHOWGROUPS = 'showgroups', + COLLAPSE = 'collapse', + COLLAPSED = 'collapsed', + GROUPS = '.atto_group'; - var iconurl = M.util.image_url('icon', 'atto_collapse'); +Y.namespace('M.atto_collapse').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var button = this.addButton({ + icon: M.util.image_url('icon', PLUGINNAME), + callback: this._toggle + }); - // Add the button to the toolbar. - M.editor_atto.add_toolbar_button(params.elementid, 'collapse', iconurl, params.group, click); + // Perform a toggle after all plugins have been loaded for the first time. + this.get('host').on('pluginsloaded', function(e, button) { + this._setVisibility(button); + + // Set the toolbar to break after the initial those displayed by default. + var firstGroup = this.toolbar.all(GROUPS).item(this.get(ATTRSHOWGROUPS)); + firstGroup.insert('
                                        ', 'before'); + }, this, button); }, /** - * Either hide or show the extra groups in the toolbar. + * Toggle the visibility of the extra groups in the toolbar. * - * @param {String} elementid - * - * @return {Void} + * @method _toggle + * @param {EventFacade} e + * @private */ - toggle : function(elementid) { - var toolbar = M.editor_atto.get_toolbar_node(elementid); - var button = toolbar.one(SELECTORS.BUTTON); - var groups = toolbar.all(SELECTORS.GROUPS).slice(this.showgroups); + _toggle: function(e) { + e.preventDefault(); + var button = this.buttons[COLLAPSE]; - if (button.getData('collapsed')) { - button.set('title', M.util.get_string('showmore', 'atto_collapse')); - groups.show(); - button.setData('collapsed', false); + if (button.getData(COLLAPSED)) { + this._setVisibility(button, true); } else { - button.set('title', M.util.get_string('showless', 'atto_collapse')); - groups.hide(); - button.setData('collapsed', true); + this._setVisibility(button); } }, /** - * After init function called after all plugins init() has been run. + * Set the visibility of the toolbar groups. * - * @param {Object} params - * - * @return {Void} + * @method _setVisibility + * @param {Node} button The collapse button + * @param {Booelan} visibility Whether the groups should be made visible + * @private */ - after_init : function(params) { - var toolbar = M.editor_atto.get_toolbar_node(params.elementid); - var button = toolbar.one(SELECTORS.BUTTON); - var firstgroup = toolbar.all(SELECTORS.GROUPS).item(this.showgroups); + _setVisibility: function(button, visibility) { + var groups = this.toolbar.all(GROUPS).slice(this.get(ATTRSHOWGROUPS)); + + if (visibility) { + button.set('title', M.util.get_string('showfewer', PLUGINNAME)); + groups.show(); + button.setData(COLLAPSED, false); + } else { + button.set('title', M.util.get_string('showmore', PLUGINNAME)); + groups.hide(); + button.setData(COLLAPSED, true); + } - // Set the toolbar to break after the initial those displayed by default. - firstgroup.insert('
                                        ', 'before'); - // Set the state to "not collapsed" (which is the state when the page loads). - button.setData('collapsed', false); - // Call toggle to change the state when the page loads to "collapsed". - M.atto_collapse.toggle(params.elementid); } - -}; +}, { + ATTRS: { + /** + * How many groups to show when collapsed. + * + * @attribute showgroups + * @type Number + * @default 3 + */ + showgroups: { + value: 3 + } + } +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button-min.js b/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button-min.js index ac12d8d9faf..b1db4f6373c 100644 --- a/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button-min.js +++ b/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_collapse-button",function(e,t){var n={GROUPS:".atto_group",BUTTON:".atto_collapse_button"};M.atto_collapse=M.atto_collapse||{showgroups:3,init:function(e){var t=function(e,t){e.preventDefault(),M.atto_collapse.toggle(t)};this.showgroups=e.showgroups;var n=M.util.image_url("icon","atto_collapse");M.editor_atto.add_toolbar_button(e.elementid,"collapse",n,e.group,t)},toggle:function(e){var t=M.editor_atto.get_toolbar_node(e),r=t.one(n.BUTTON),i=t.all(n.GROUPS).slice(this.showgroups);r.getData("collapsed")?(r.set("title",M.util.get_string("showmore","atto_collapse")),i.show(),r.setData("collapsed",!1)):(r.set("title",M.util.get_string("showless","atto_collapse")),i.hide(),r.setData("collapsed",!0))},after_init:function(e){var t=M.editor_atto.get_toolbar_node(e.elementid),r=t.one(n.BUTTON),i=t.all(n.GROUPS).item(this.showgroups);i.insert('
                                        ',"before"),r.setData("collapsed",!1),M.atto_collapse.toggle(e.elementid)}}},"@VERSION@",{requires:["node"]}); +YUI.add("moodle-atto_collapse-button",function(e,t){var n="atto_collapse",r="showgroups",i="collapse",s="collapsed",o=".atto_group";e.namespace("M.atto_collapse").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var e=this.addButton({icon:M.util.image_url("icon",n),callback:this._toggle});this.get("host").on("pluginsloaded",function(e,t){this._setVisibility(t);var n=this.toolbar.all(o).item(this.get(r));n.insert('
                                        ',"before")},this,e)},_toggle:function(e){e.preventDefault();var t=this.buttons[i];t.getData(s)?this._setVisibility(t,!0):this._setVisibility(t)},_setVisibility:function(e,t){var i=this.toolbar.all(o).slice(this.get(r));t?(e.set("title",M.util.get_string("showfewer",n)),i.show(),e.setData(s,!1)):(e.set("title",M.util.get_string("showmore",n)),i.hide(),e.setData(s,!0))}},{ATTRS:{showgroups:{value:3}}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button.js b/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button.js index dea66443540..0e112b81d00 100644 --- a/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button.js +++ b/lib/editor/atto/plugins/collapse/yui/build/moodle-atto_collapse-button/moodle-atto_collapse-button.js @@ -15,99 +15,101 @@ YUI.add('moodle-atto_collapse-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * CSS Selectors - * - * @type {Object} - */ -var SELECTORS = { - GROUPS: '.atto_group', - BUTTON: '.atto_collapse_button' -}; - -/** - * Atto text editor collapse plugin. - * +/* * @package atto_collapse * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_collapse = M.atto_collapse || { - /** - * How many groups to show when collapsed. - * - * @property showgroups - * @type {Integer} - * @default 3 - */ - showgroups : 3, +/** + * @module moodle-atto_collapse-button + */ - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - M.atto_collapse.toggle(elementid); - }; +/** + * Atto text editor collapse plugin. + * + * @namespace M.atto_collapse + * @class button + * @extends M.editor_atto.EditorPlugin + */ - this.showgroups = params.showgroups; +var PLUGINNAME = 'atto_collapse', + ATTRSHOWGROUPS = 'showgroups', + COLLAPSE = 'collapse', + COLLAPSED = 'collapsed', + GROUPS = '.atto_group'; - var iconurl = M.util.image_url('icon', 'atto_collapse'); +Y.namespace('M.atto_collapse').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var button = this.addButton({ + icon: M.util.image_url('icon', PLUGINNAME), + callback: this._toggle + }); - // Add the button to the toolbar. - M.editor_atto.add_toolbar_button(params.elementid, 'collapse', iconurl, params.group, click); + // Perform a toggle after all plugins have been loaded for the first time. + this.get('host').on('pluginsloaded', function(e, button) { + this._setVisibility(button); + + // Set the toolbar to break after the initial those displayed by default. + var firstGroup = this.toolbar.all(GROUPS).item(this.get(ATTRSHOWGROUPS)); + firstGroup.insert('
                                        ', 'before'); + }, this, button); }, /** - * Either hide or show the extra groups in the toolbar. + * Toggle the visibility of the extra groups in the toolbar. * - * @param {String} elementid - * - * @return {Void} + * @method _toggle + * @param {EventFacade} e + * @private */ - toggle : function(elementid) { - var toolbar = M.editor_atto.get_toolbar_node(elementid); - var button = toolbar.one(SELECTORS.BUTTON); - var groups = toolbar.all(SELECTORS.GROUPS).slice(this.showgroups); + _toggle: function(e) { + e.preventDefault(); + var button = this.buttons[COLLAPSE]; - if (button.getData('collapsed')) { - button.set('title', M.util.get_string('showmore', 'atto_collapse')); - groups.show(); - button.setData('collapsed', false); + if (button.getData(COLLAPSED)) { + this._setVisibility(button, true); } else { - button.set('title', M.util.get_string('showless', 'atto_collapse')); - groups.hide(); - button.setData('collapsed', true); + this._setVisibility(button); } }, /** - * After init function called after all plugins init() has been run. + * Set the visibility of the toolbar groups. * - * @param {Object} params - * - * @return {Void} + * @method _setVisibility + * @param {Node} button The collapse button + * @param {Booelan} visibility Whether the groups should be made visible + * @private */ - after_init : function(params) { - var toolbar = M.editor_atto.get_toolbar_node(params.elementid); - var button = toolbar.one(SELECTORS.BUTTON); - var firstgroup = toolbar.all(SELECTORS.GROUPS).item(this.showgroups); + _setVisibility: function(button, visibility) { + var groups = this.toolbar.all(GROUPS).slice(this.get(ATTRSHOWGROUPS)); + + if (visibility) { + button.set('title', M.util.get_string('showfewer', PLUGINNAME)); + groups.show(); + button.setData(COLLAPSED, false); + } else { + button.set('title', M.util.get_string('showmore', PLUGINNAME)); + groups.hide(); + button.setData(COLLAPSED, true); + } - // Set the toolbar to break after the initial those displayed by default. - firstgroup.insert('
                                        ', 'before'); - // Set the state to "not collapsed" (which is the state when the page loads). - button.setData('collapsed', false); - // Call toggle to change the state when the page loads to "collapsed". - M.atto_collapse.toggle(params.elementid); } - -}; +}, { + ATTRS: { + /** + * How many groups to show when collapsed. + * + * @attribute showgroups + * @type Number + * @default 3 + */ + showgroups: { + value: 3 + } + } +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/collapse/yui/src/button/js/button.js b/lib/editor/atto/plugins/collapse/yui/src/button/js/button.js index d0e09e1839e..96007ce29b3 100644 --- a/lib/editor/atto/plugins/collapse/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/collapse/yui/src/button/js/button.js @@ -13,96 +13,98 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * CSS Selectors - * - * @type {Object} - */ -var SELECTORS = { - GROUPS: '.atto_group', - BUTTON: '.atto_collapse_button' -}; - -/** - * Atto text editor collapse plugin. - * +/* * @package atto_collapse * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_collapse = M.atto_collapse || { - /** - * How many groups to show when collapsed. - * - * @property showgroups - * @type {Integer} - * @default 3 - */ - showgroups : 3, +/** + * @module moodle-atto_collapse-button + */ - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - M.atto_collapse.toggle(elementid); - }; +/** + * Atto text editor collapse plugin. + * + * @namespace M.atto_collapse + * @class button + * @extends M.editor_atto.EditorPlugin + */ - this.showgroups = params.showgroups; +var PLUGINNAME = 'atto_collapse', + ATTRSHOWGROUPS = 'showgroups', + COLLAPSE = 'collapse', + COLLAPSED = 'collapsed', + GROUPS = '.atto_group'; - var iconurl = M.util.image_url('icon', 'atto_collapse'); +Y.namespace('M.atto_collapse').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var button = this.addButton({ + icon: M.util.image_url('icon', PLUGINNAME), + callback: this._toggle + }); - // Add the button to the toolbar. - M.editor_atto.add_toolbar_button(params.elementid, 'collapse', iconurl, params.group, click); + // Perform a toggle after all plugins have been loaded for the first time. + this.get('host').on('pluginsloaded', function(e, button) { + this._setVisibility(button); + + // Set the toolbar to break after the initial those displayed by default. + var firstGroup = this.toolbar.all(GROUPS).item(this.get(ATTRSHOWGROUPS)); + firstGroup.insert('
                                        ', 'before'); + }, this, button); }, /** - * Either hide or show the extra groups in the toolbar. + * Toggle the visibility of the extra groups in the toolbar. * - * @param {String} elementid - * - * @return {Void} + * @method _toggle + * @param {EventFacade} e + * @private */ - toggle : function(elementid) { - var toolbar = M.editor_atto.get_toolbar_node(elementid); - var button = toolbar.one(SELECTORS.BUTTON); - var groups = toolbar.all(SELECTORS.GROUPS).slice(this.showgroups); + _toggle: function(e) { + e.preventDefault(); + var button = this.buttons[COLLAPSE]; - if (button.getData('collapsed')) { - button.set('title', M.util.get_string('showmore', 'atto_collapse')); - groups.show(); - button.setData('collapsed', false); + if (button.getData(COLLAPSED)) { + this._setVisibility(button, true); } else { - button.set('title', M.util.get_string('showless', 'atto_collapse')); - groups.hide(); - button.setData('collapsed', true); + this._setVisibility(button); } }, /** - * After init function called after all plugins init() has been run. + * Set the visibility of the toolbar groups. * - * @param {Object} params - * - * @return {Void} + * @method _setVisibility + * @param {Node} button The collapse button + * @param {Booelan} visibility Whether the groups should be made visible + * @private */ - after_init : function(params) { - var toolbar = M.editor_atto.get_toolbar_node(params.elementid); - var button = toolbar.one(SELECTORS.BUTTON); - var firstgroup = toolbar.all(SELECTORS.GROUPS).item(this.showgroups); + _setVisibility: function(button, visibility) { + var groups = this.toolbar.all(GROUPS).slice(this.get(ATTRSHOWGROUPS)); + + if (visibility) { + button.set('title', M.util.get_string('showfewer', PLUGINNAME)); + groups.show(); + button.setData(COLLAPSED, false); + } else { + button.set('title', M.util.get_string('showmore', PLUGINNAME)); + groups.hide(); + button.setData(COLLAPSED, true); + } - // Set the toolbar to break after the initial those displayed by default. - firstgroup.insert('
                                        ', 'before'); - // Set the state to "not collapsed" (which is the state when the page loads). - button.setData('collapsed', false); - // Call toggle to change the state when the page loads to "collapsed". - M.atto_collapse.toggle(params.elementid); } - -}; +}, { + ATTRS: { + /** + * How many groups to show when collapsed. + * + * @attribute showgroups + * @type Number + * @default 3 + */ + showgroups: { + value: 3 + } + } +}); diff --git a/lib/editor/atto/plugins/collapse/yui/src/button/meta/button.json b/lib/editor/atto/plugins/collapse/yui/src/button/meta/button.json index a88cdaa4727..f4b22c61f51 100644 --- a/lib/editor/atto/plugins/collapse/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/collapse/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_collapse-button": { - "requires": ["node"] - } + "moodle-atto_collapse-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button-debug.js b/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button-debug.js index 2f50e8f14c5..b4c308538ea 100644 --- a/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button-debug.js +++ b/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button-debug.js @@ -15,176 +15,156 @@ YUI.add('moodle-atto_emoticon-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor emoticon plugin. - * +/* * @package atto_emoticon * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** -* CSS classes and IDs. -* -* @type {Object} -*/ -var CSS = { + * @module moodle-atto_emoticon-button + */ + +var COMPONENTNAME = 'atto_emoticon', + CSS = { EMOTE: 'atto_emoticon_emote', MAP: 'atto_emoticon_map' }, - /** - * Selectors. - * - * @type {Object} - */ SELECTORS = { EMOTE: '.atto_emoticon_emote' - }; + }, + TEMPLATE = '' + + '
                                        ' + + '
                                          ' + + '{{#each emoticons}}' + + '
                                        • ' + + '' + + '' + + '' + + '
                                          ' + + '
                                          {{text}}
                                          ' + + '
                                          {{get_string altidentifier altcomponent}}
                                          ' + + '
                                        • ' + + '{{/each}}' + + '
                                        ' + + '
                                        '; -M.atto_emoticon = M.atto_emoticon || { +/** + * Atto text editor emoticon plugin. + * + * @namespace M.atto_emoticon + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_emoticon').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The ID of the current editor. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @type {String} + * @property _currentSelection + * @type Range + * @private */ - currentElementId: null, + _currentSelection: null, - /** - * The dialogue to select a character. - * - * @type {M.core.dialogue} - */ - dialogue: null, - - /** - * List of emoticons. - * - * This must be populated from the result of the PHP function emoticon_manager::get_emoticons(). - * - * @type {Array} - */ - emoticons: null, - - /** - * Keeps track of the selection made by the user. - * - * @type {Mixed} - */ - selection: null, - - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init: function(params) { - - M.atto_emoticon.emoticons = params.emoticons; - - var displayChooser = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - - // Stores the selection. - M.atto_emoticon.selection = M.editor_atto.get_selection(); - if (M.atto_emoticon.selection === false) { - return; - } - - // Stores what editor we are working on. - M.atto_emoticon.currentElementId = elementid; - - // Initialising the dialogue. - var dialogue; - if (!M.atto_emoticon.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - - // Setting up the content of the dialogue. - dialogue.set('bodyContent', M.atto_emoticon.getDialogueContent()); - dialogue.set('headerContent', M.util.get_string('insertemoticon', 'atto_emoticon')); - dialogue.render(); - dialogue.centerDialogue(); - M.atto_emoticon.dialogue = dialogue; - } else { - dialogue = M.atto_emoticon.dialogue; - } - - dialogue.show(); - }; - - var iconurl = M.util.image_url('e/emoticons', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'emoticon', iconurl, params.group, displayChooser); + initializer: function() { + this.addButton({ + icon: 'e/emoticons', + callback: this._displayDialogue + }); }, /** - * Generates the content of the dialogue. + * Display the Emoticon chooser. * - * @return {Node} Node containing the dialogue content + * @method _displayDialogue + * @private */ - getDialogueContent: function() { - var content, - emote, - emotealt, - html = '', - i; - - html += '
                                        '; - html += '
                                          '; - for (i = 0; i < M.atto_emoticon.emoticons.length; i++ ) { - emote = M.atto_emoticon.emoticons[i]; - emotealt = Y.Escape.html(M.util.get_string(emote.altidentifier, emote.altcomponent)); - html += '
                                        • '; - html += ''; - html += '
                                          ' + Y.Escape.html(emote.text) + '
                                          '; - html += '
                                          ' + emotealt + '
                                          '; - html += '
                                        • '; + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { + return; } - html += '
                                        '; - html += '
                                        '; - content = Y.Node.create(html); - content.delegate('click', M.atto_emoticon.insertEmote, SELECTORS.EMOTE, this); - content.delegate('key', M.atto_emoticon.insertEmote, '32', SELECTORS.EMOTE, this); + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('insertemoticon', COMPONENTNAME), + focusAfterHide: true + }, true); - return content; + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); }, /** - * Insert the picked emote in Atto. + * Insert the emoticon. * - * @param {Event} e The event - * @return {Void} + * @method _insertEmote + * @param {EventFacade} e + * @private */ - insertEmote: function(e) { + _insertEmote: function(e) { var target = e.target.ancestor(SELECTORS.EMOTE, true), - emote = M.atto_emoticon.emoticons[target.getData('index')], - html = ''; + host = this.get('host'); e.preventDefault(); - e.stopPropagation(); - M.atto_emoticon.dialogue.hide(); - html = ' ' + emote.text + ' '; - M.editor_atto.set_selection(M.atto_emoticon.selection); + // Hide the dialogue. + this.getDialogue({ + focusAfterHide: null + }).hide(); - M.editor_atto.insert_html_at_focus_point(html); + // Build the Emoticon text. + var html = ' ' + target.getData('text') + ' '; - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(M.atto_emoticon.currentElementId); + // Focus on the previous selection. + host.setSelection(this._currentSelection); + + // And add the character. + host.insertContentAtFocusPoint(html); + + this.markUpdated(); + }, + + /** + * Generates the content of the dialogue, attaching event listeners to + * the content. + * + * @method _getDialogueContent + * @return {Node} Node containing the dialogue content + * @private + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + emoticons: this.get('emoticons'), + CSS: CSS + })); + content.delegate('click', this._insertEmote, SELECTORS.EMOTE, this); + content.delegate('key', this._insertEmote, '32', SELECTORS.EMOTE, this); + + return content; } -}; +}, { + ATTRS: { + /** + * The list of emoticons to display. + * + * @attribute emoticons + * @type array + * @default {} + */ + emoticons: { + value: {} + } + } +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button-min.js b/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button-min.js index 263adaf09ff..5c8a9749ad4 100644 --- a/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button-min.js +++ b/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_emoticon-button",function(e,t){var n={EMOTE:"atto_emoticon_emote",MAP:"atto_emoticon_map"},r={EMOTE:".atto_emoticon_emote"};M.atto_emoticon=M.atto_emoticon||{currentElementId:null,dialogue:null,emoticons:null,selection:null,init:function(e){M.atto_emoticon.emoticons=e.emoticons;var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_emoticon.selection=M.editor_atto.get_selection();if(M.atto_emoticon.selection===!1)return;M.atto_emoticon.currentElementId=t;var n;M.atto_emoticon.dialogue?n=M.atto_emoticon.dialogue:(n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.set("bodyContent",M.atto_emoticon.getDialogueContent()),n.set("headerContent",M.util.get_string("insertemoticon","atto_emoticon")),n.render(),n.centerDialogue(),M.atto_emoticon.dialogue=n),n.show()},n=M.util.image_url("e/emoticons","core");M.editor_atto.add_toolbar_button(e.elementid,"emoticon",n,e.group,t)},getDialogueContent:function(){var t,i,s,o="",u;o+='
                                        ',o+="
                                          ";for(u=0;u",o+='",o+="
                                          "+e.Escape.html(i.text)+"
                                          ",o+="
                                          "+s+"
                                          ",o+="";return o+="
                                        ",o+="
                                        ",t=e.Node.create(o),t.delegate("click",M.atto_emoticon.insertEmote,r.EMOTE,this),t.delegate("key",M.atto_emoticon.insertEmote,"32",r.EMOTE,this),t},insertEmote:function(e){var t=e.target.ancestor(r.EMOTE,!0),n=M.atto_emoticon.emoticons[t.getData("index")],i="";e.preventDefault(),e.stopPropagation(),M.atto_emoticon.dialogue.hide(),i=" "+n.text+" ",M.editor_atto.set_selection(M.atto_emoticon.selection),M.editor_atto.insert_html_at_focus_point(i),M.editor_atto.text_updated(M.atto_emoticon.currentElementId)}}},"@VERSION@",{requires:["node"]}); +YUI.add("moodle-atto_emoticon-button",function(e,t){var n="atto_emoticon",r={EMOTE:"atto_emoticon_emote",MAP:"atto_emoticon_map"},i={EMOTE:".atto_emoticon_emote"},s='
                                          {{#each emoticons}}
                                        • {{get_string altidentifier altcomponent}}
                                          {{text}}
                                          {{get_string altidentifier altcomponent}}
                                        • {{/each}}
                                        ';e.namespace("M.atto_emoticon").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,initializer:function(){this.addButton({icon:"e/emoticons",callback:this._displayDialogue})},_displayDialogue:function(){this._currentSelection=this.get("host").getSelection();if(this._currentSelection===!1)return;var e=this.getDialogue({headerContent:M.util.get_string("insertemoticon",n),focusAfterHide:!0},!0);e.set("bodyContent",this._getDialogueContent()).show()},_insertEmote:function(e){var t=e.target.ancestor(i.EMOTE,!0),n=this.get("host");e.preventDefault(),this.getDialogue({focusAfterHide:null}).hide();var r=" "+t.getData("text")+" ";n.setSelection(this._currentSelection),n.insertContentAtFocusPoint(r),this.markUpdated()},_getDialogueContent:function(){var t=e.Handlebars.compile(s),n=e.Node.create(t({emoticons:this.get("emoticons"),CSS:r}));return n.delegate("click",this._insertEmote,i.EMOTE,this),n.delegate("key",this._insertEmote,"32",i.EMOTE,this),n}},{ATTRS:{emoticons:{value:{}}}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button.js b/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button.js index 2f50e8f14c5..b4c308538ea 100644 --- a/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button.js +++ b/lib/editor/atto/plugins/emoticon/yui/build/moodle-atto_emoticon-button/moodle-atto_emoticon-button.js @@ -15,176 +15,156 @@ YUI.add('moodle-atto_emoticon-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor emoticon plugin. - * +/* * @package atto_emoticon * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** -* CSS classes and IDs. -* -* @type {Object} -*/ -var CSS = { + * @module moodle-atto_emoticon-button + */ + +var COMPONENTNAME = 'atto_emoticon', + CSS = { EMOTE: 'atto_emoticon_emote', MAP: 'atto_emoticon_map' }, - /** - * Selectors. - * - * @type {Object} - */ SELECTORS = { EMOTE: '.atto_emoticon_emote' - }; + }, + TEMPLATE = '' + + '
                                        ' + + '
                                          ' + + '{{#each emoticons}}' + + '
                                        • ' + + '' + + '' + + '' + + '
                                          ' + + '
                                          {{text}}
                                          ' + + '
                                          {{get_string altidentifier altcomponent}}
                                          ' + + '
                                        • ' + + '{{/each}}' + + '
                                        ' + + '
                                        '; -M.atto_emoticon = M.atto_emoticon || { +/** + * Atto text editor emoticon plugin. + * + * @namespace M.atto_emoticon + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_emoticon').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The ID of the current editor. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @type {String} + * @property _currentSelection + * @type Range + * @private */ - currentElementId: null, + _currentSelection: null, - /** - * The dialogue to select a character. - * - * @type {M.core.dialogue} - */ - dialogue: null, - - /** - * List of emoticons. - * - * This must be populated from the result of the PHP function emoticon_manager::get_emoticons(). - * - * @type {Array} - */ - emoticons: null, - - /** - * Keeps track of the selection made by the user. - * - * @type {Mixed} - */ - selection: null, - - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init: function(params) { - - M.atto_emoticon.emoticons = params.emoticons; - - var displayChooser = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - - // Stores the selection. - M.atto_emoticon.selection = M.editor_atto.get_selection(); - if (M.atto_emoticon.selection === false) { - return; - } - - // Stores what editor we are working on. - M.atto_emoticon.currentElementId = elementid; - - // Initialising the dialogue. - var dialogue; - if (!M.atto_emoticon.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - - // Setting up the content of the dialogue. - dialogue.set('bodyContent', M.atto_emoticon.getDialogueContent()); - dialogue.set('headerContent', M.util.get_string('insertemoticon', 'atto_emoticon')); - dialogue.render(); - dialogue.centerDialogue(); - M.atto_emoticon.dialogue = dialogue; - } else { - dialogue = M.atto_emoticon.dialogue; - } - - dialogue.show(); - }; - - var iconurl = M.util.image_url('e/emoticons', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'emoticon', iconurl, params.group, displayChooser); + initializer: function() { + this.addButton({ + icon: 'e/emoticons', + callback: this._displayDialogue + }); }, /** - * Generates the content of the dialogue. + * Display the Emoticon chooser. * - * @return {Node} Node containing the dialogue content + * @method _displayDialogue + * @private */ - getDialogueContent: function() { - var content, - emote, - emotealt, - html = '', - i; - - html += '
                                        '; - html += '
                                          '; - for (i = 0; i < M.atto_emoticon.emoticons.length; i++ ) { - emote = M.atto_emoticon.emoticons[i]; - emotealt = Y.Escape.html(M.util.get_string(emote.altidentifier, emote.altcomponent)); - html += '
                                        • '; - html += ''; - html += '
                                          ' + Y.Escape.html(emote.text) + '
                                          '; - html += '
                                          ' + emotealt + '
                                          '; - html += '
                                        • '; + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { + return; } - html += '
                                        '; - html += '
                                        '; - content = Y.Node.create(html); - content.delegate('click', M.atto_emoticon.insertEmote, SELECTORS.EMOTE, this); - content.delegate('key', M.atto_emoticon.insertEmote, '32', SELECTORS.EMOTE, this); + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('insertemoticon', COMPONENTNAME), + focusAfterHide: true + }, true); - return content; + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); }, /** - * Insert the picked emote in Atto. + * Insert the emoticon. * - * @param {Event} e The event - * @return {Void} + * @method _insertEmote + * @param {EventFacade} e + * @private */ - insertEmote: function(e) { + _insertEmote: function(e) { var target = e.target.ancestor(SELECTORS.EMOTE, true), - emote = M.atto_emoticon.emoticons[target.getData('index')], - html = ''; + host = this.get('host'); e.preventDefault(); - e.stopPropagation(); - M.atto_emoticon.dialogue.hide(); - html = ' ' + emote.text + ' '; - M.editor_atto.set_selection(M.atto_emoticon.selection); + // Hide the dialogue. + this.getDialogue({ + focusAfterHide: null + }).hide(); - M.editor_atto.insert_html_at_focus_point(html); + // Build the Emoticon text. + var html = ' ' + target.getData('text') + ' '; - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(M.atto_emoticon.currentElementId); + // Focus on the previous selection. + host.setSelection(this._currentSelection); + + // And add the character. + host.insertContentAtFocusPoint(html); + + this.markUpdated(); + }, + + /** + * Generates the content of the dialogue, attaching event listeners to + * the content. + * + * @method _getDialogueContent + * @return {Node} Node containing the dialogue content + * @private + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + emoticons: this.get('emoticons'), + CSS: CSS + })); + content.delegate('click', this._insertEmote, SELECTORS.EMOTE, this); + content.delegate('key', this._insertEmote, '32', SELECTORS.EMOTE, this); + + return content; } -}; +}, { + ATTRS: { + /** + * The list of emoticons to display. + * + * @attribute emoticons + * @type array + * @default {} + */ + emoticons: { + value: {} + } + } +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/emoticon/yui/src/button/js/button.js b/lib/editor/atto/plugins/emoticon/yui/src/button/js/button.js index 2e51b393162..752fca1c5f2 100644 --- a/lib/editor/atto/plugins/emoticon/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/emoticon/yui/src/button/js/button.js @@ -13,173 +13,153 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor emoticon plugin. - * +/* * @package atto_emoticon * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** -* CSS classes and IDs. -* -* @type {Object} -*/ -var CSS = { + * @module moodle-atto_emoticon-button + */ + +var COMPONENTNAME = 'atto_emoticon', + CSS = { EMOTE: 'atto_emoticon_emote', MAP: 'atto_emoticon_map' }, - /** - * Selectors. - * - * @type {Object} - */ SELECTORS = { EMOTE: '.atto_emoticon_emote' - }; + }, + TEMPLATE = '' + + '
                                        ' + + '
                                          ' + + '{{#each emoticons}}' + + '
                                        • ' + + '' + + '' + + '' + + '
                                          ' + + '
                                          {{text}}
                                          ' + + '
                                          {{get_string altidentifier altcomponent}}
                                          ' + + '
                                        • ' + + '{{/each}}' + + '
                                        ' + + '
                                        '; -M.atto_emoticon = M.atto_emoticon || { +/** + * Atto text editor emoticon plugin. + * + * @namespace M.atto_emoticon + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_emoticon').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The ID of the current editor. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @type {String} + * @property _currentSelection + * @type Range + * @private */ - currentElementId: null, + _currentSelection: null, - /** - * The dialogue to select a character. - * - * @type {M.core.dialogue} - */ - dialogue: null, - - /** - * List of emoticons. - * - * This must be populated from the result of the PHP function emoticon_manager::get_emoticons(). - * - * @type {Array} - */ - emoticons: null, - - /** - * Keeps track of the selection made by the user. - * - * @type {Mixed} - */ - selection: null, - - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init: function(params) { - - M.atto_emoticon.emoticons = params.emoticons; - - var displayChooser = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - - // Stores the selection. - M.atto_emoticon.selection = M.editor_atto.get_selection(); - if (M.atto_emoticon.selection === false) { - return; - } - - // Stores what editor we are working on. - M.atto_emoticon.currentElementId = elementid; - - // Initialising the dialogue. - var dialogue; - if (!M.atto_emoticon.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - - // Setting up the content of the dialogue. - dialogue.set('bodyContent', M.atto_emoticon.getDialogueContent()); - dialogue.set('headerContent', M.util.get_string('insertemoticon', 'atto_emoticon')); - dialogue.render(); - dialogue.centerDialogue(); - M.atto_emoticon.dialogue = dialogue; - } else { - dialogue = M.atto_emoticon.dialogue; - } - - dialogue.show(); - }; - - var iconurl = M.util.image_url('e/emoticons', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'emoticon', iconurl, params.group, displayChooser); + initializer: function() { + this.addButton({ + icon: 'e/emoticons', + callback: this._displayDialogue + }); }, /** - * Generates the content of the dialogue. + * Display the Emoticon chooser. * - * @return {Node} Node containing the dialogue content + * @method _displayDialogue + * @private */ - getDialogueContent: function() { - var content, - emote, - emotealt, - html = '', - i; - - html += '
                                        '; - html += '
                                          '; - for (i = 0; i < M.atto_emoticon.emoticons.length; i++ ) { - emote = M.atto_emoticon.emoticons[i]; - emotealt = Y.Escape.html(M.util.get_string(emote.altidentifier, emote.altcomponent)); - html += '
                                        • '; - html += ''; - html += '
                                          ' + Y.Escape.html(emote.text) + '
                                          '; - html += '
                                          ' + emotealt + '
                                          '; - html += '
                                        • '; + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { + return; } - html += '
                                        '; - html += '
                                        '; - content = Y.Node.create(html); - content.delegate('click', M.atto_emoticon.insertEmote, SELECTORS.EMOTE, this); - content.delegate('key', M.atto_emoticon.insertEmote, '32', SELECTORS.EMOTE, this); + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('insertemoticon', COMPONENTNAME), + focusAfterHide: true + }, true); - return content; + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); }, /** - * Insert the picked emote in Atto. + * Insert the emoticon. * - * @param {Event} e The event - * @return {Void} + * @method _insertEmote + * @param {EventFacade} e + * @private */ - insertEmote: function(e) { + _insertEmote: function(e) { var target = e.target.ancestor(SELECTORS.EMOTE, true), - emote = M.atto_emoticon.emoticons[target.getData('index')], - html = ''; + host = this.get('host'); e.preventDefault(); - e.stopPropagation(); - M.atto_emoticon.dialogue.hide(); - html = ' ' + emote.text + ' '; - M.editor_atto.set_selection(M.atto_emoticon.selection); + // Hide the dialogue. + this.getDialogue({ + focusAfterHide: null + }).hide(); - M.editor_atto.insert_html_at_focus_point(html); + // Build the Emoticon text. + var html = ' ' + target.getData('text') + ' '; - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(M.atto_emoticon.currentElementId); + // Focus on the previous selection. + host.setSelection(this._currentSelection); + + // And add the character. + host.insertContentAtFocusPoint(html); + + this.markUpdated(); + }, + + /** + * Generates the content of the dialogue, attaching event listeners to + * the content. + * + * @method _getDialogueContent + * @return {Node} Node containing the dialogue content + * @private + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + emoticons: this.get('emoticons'), + CSS: CSS + })); + content.delegate('click', this._insertEmote, SELECTORS.EMOTE, this); + content.delegate('key', this._insertEmote, '32', SELECTORS.EMOTE, this); + + return content; } -}; +}, { + ATTRS: { + /** + * The list of emoticons to display. + * + * @attribute emoticons + * @type array + * @default {} + */ + emoticons: { + value: {} + } + } +}); diff --git a/lib/editor/atto/plugins/emoticon/yui/src/button/meta/button.json b/lib/editor/atto/plugins/emoticon/yui/src/button/meta/button.json index 2a4eaf2cf97..a17ef6d963d 100644 --- a/lib/editor/atto/plugins/emoticon/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/emoticon/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_emoticon-button": { - "requires": ["node"] - } + "moodle-atto_emoticon-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/equation/lib.php b/lib/editor/atto/plugins/equation/lib.php index 224f85bb384..58ccf5466f9 100644 --- a/lib/editor/atto/plugins/equation/lib.php +++ b/lib/editor/atto/plugins/equation/lib.php @@ -64,10 +64,23 @@ function atto_equation_params_for_js($elementid, $options, $fpoptions) { } // Tex example librarys. - $library = array('group1' => get_config('atto_equation', 'librarygroup1'), - 'group2' => get_config('atto_equation', 'librarygroup2'), - 'group3' => get_config('atto_equation', 'librarygroup3'), - 'group4' => get_config('atto_equation', 'librarygroup4')); + $library = array( + 'group1' => array( + 'groupname' => 'librarygroup1', + 'elements' => get_config('atto_equation', 'librarygroup1'), + ), + 'group2' => array( + 'groupname' => 'librarygroup2', + 'elements' => get_config('atto_equation', 'librarygroup2'), + ), + 'group3' => array( + 'groupname' => 'librarygroup3', + 'elements' => get_config('atto_equation', 'librarygroup3'), + ), + 'group4' => array( + 'groupname' => 'librarygroup4', + 'elements' => get_config('atto_equation', 'librarygroup4'), + )); return array('texfilteractive' => $texfilteractive, 'contextid'=>$context->id, 'library'=>$library); } diff --git a/lib/editor/atto/plugins/equation/styles.css b/lib/editor/atto/plugins/equation/styles.css index 2339c2e74b9..595c4cf1522 100644 --- a/lib/editor/atto/plugins/equation/styles.css +++ b/lib/editor/atto/plugins/equation/styles.css @@ -1,15 +1,15 @@ -#atto_equation_library .yui3-tabview-list { +.atto_equation_library .yui3-tabview-list { border: none; } -#atto_equation_library .yui3-tab-selected .yui3-tab-label, .yui3-skin-sam #atto_equation_library .yui3-tab-selected .yui3-tab-label:focus, .yui3-skin-sam #atto_equation_library .yui3-tab-selected .yui3-tab-label:hover { +.atto_equation_library .yui3-tab-selected .yui3-tab-label, .yui3-skin-sam #atto_equation_library .yui3-tab-selected .yui3-tab-label:focus, .yui3-skin-sam #atto_equation_library .yui3-tab-selected .yui3-tab-label:hover { background: none; color: black; border-top-left-radius: 4px; border-top-right-radius: 4px; } -#atto_equation_library button { +.atto_equation_library button { margin: 4px; } 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 c0c14aede45..bc98c72b2c2 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 @@ -16,153 +16,179 @@ YUI.add('moodle-atto_equation-button', function (Y, NAME) { // along with Moodle. If not, see . /** - * Atto text editor equation plugin. - * - * @package editor-atto + * @package atto_equation * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_equation = M.atto_equation || { - /** - * The window used to get the equation details. - * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, + +/** + * Atto text editor equation plugin. + */ + +/** + * Atto equation editor. + * + * @namespace M.atto_equation + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENTNAME = 'atto_equation', + CSS = { + EQUATION_TEXT: 'atto_equation_equation', + EQUATION_PREVIEW: 'atto_equation_preview', + SUBMIT: 'atto_equation_submit', + LIBRARY: 'atto_equation_library', + LIBRARY_GROUP_PREFIX: 'atto_equation_library' + }, + SELECTORS = { + LIBRARY_GROUP_PREFIX: '.' + CSS.LIBRARY_GROUP_PREFIX, + EQUATION_TEXT: '.' + CSS.EQUATION_TEXT, + EQUATION_PREVIEW: '.' + CSS.EQUATION_PREVIEW, + SUBMIT: '.' + CSS.SUBMIT, + LIBRARY_BUTTON: '.' + CSS.LIBRARY + ' button' + }, + TEMPLATES = { + FORM: '' + + '
                                        ' + + '{{{library}}}' + + '' + + '
                                        ' + + '

                                        {{{get_string "editequation_desc" component}}}

                                        ' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        ', + LIBRARY: '' + + '
                                        ' + + '' + + '
                                        ' + + '{{#each library}}' + + '
                                        ' + + '{{#split "\n" elements}}' + + '' + + '{{/split}}' + + '
                                        ' + + '{{/each}}' + + '
                                        ' + + '
                                        ' + }; + +Y.namespace('M.atto_equation').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** * The selection object returned by the browser. * - * @property selection + * @property _currentSelection * @type Range * @default null + * @private */ - selection : null, + _currentSelection: null, /** - * A mapping of elementids to contextids. + * The cursor position in the equation textarea. * - * @property contextids - * @type Object - * @default {} - */ - contextids : {}, - - /** - * A nested object containing a the configured list of tex examples. - * - * @property library - * @type Object - * @default {} - */ - library : {}, - - /** - * The last cursor index in the source. - * - * @property lastcursor - * @type Integer + * @property _lastCursorPos + * @type Number * @default 0 + * @private */ - lastcursor : 0, + _lastCursorPos: 0, /** - * Display the chooser dialogue. + * A reference to the dialogue content. * - * @method display_chooser - * @param Event e - * @param string elementid + * @property _content + * @type Node + * @private */ - display_chooser : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_equation.selection = M.editor_atto.get_selection(); - if (M.atto_equation.selection) { - var dialogue; - if (!M.atto_equation.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true, - width: '800px' - }); - } else { - dialogue = M.atto_equation.dialogue; - } + _content: null, - dialogue.render(); - dialogue.set('bodyContent', M.atto_equation.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('pluginname', 'atto_equation')); - - var tabview = new Y.TabView({ - srcNode: '#atto_equation_library' + initializer: function() { + if (this.get('texfilteractive')) { + // Add the button to the toolbar. + this.addButton({ + icon: 'e/math', + callback: this._displayDialogue }); - tabview.render(); - dialogue.show(); - 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; + // We need custom highlight logic for this button. + this.get('host').on('atto:selectionchanged', function() { + if (this._resolveEquation()) { + this.highlightButtons(); + } else { + this.unHighlightButtons(); + } + }, this); } }, /** - * Add this button to the form. + * Display the equation editor. * - * @method init - * @param {Object} params + * @method _displayDialogue + * @private */ - init : function(params) { - var iconurl = M.util.image_url('e/math', 'core'); + _displayDialogue: function() { + this._currentSelection = this.get('host').getSelection(); - if (params.texfilteractive) { - // Save the elementid/contextid mapping. - this.contextids[params.elementid] = params.contextid; - // Save the button library. - this.library = params.library; - - // 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. - M.editor_atto.on('atto:selectionchanged', function(e) { - if (M.atto_equation.resolve_equation()) { - M.editor_atto.add_widget_highlight(e.elementid, 'equation'); - } else { - M.editor_atto.remove_widget_highlight(e.elementid, 'equation'); - } - }); + if (this._currentSelection === false) { + return; } + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('pluginname', COMPONENTNAME), + focusAfterHide: true + }); + + var content = this._getDialogueContent(); + dialogue.set('bodyContent', content); + + var library = content.one(SELECTORS.LIBRARY_GROUP_PREFIX); + + var tabview = new Y.TabView({ + srcNode: library + }); + + tabview.render(); + dialogue.show(); + + var equation = this._resolveEquation(); + if (equation) { + content.one(SELECTORS.EQUATION_TEXT).set('text', equation); + } + this._updatePreview(false); }, /** * If there is selected text and it is part of an equation, * extract the equation (and set it in the form). * - * @method resolve_equation + * @method _resolveEquation + * @private * @return {String|Boolean} The equation or false. */ - resolve_equation : function() { + _resolveEquation: function() { + // Find the equation in the surrounding text. - var selectednode = M.editor_atto.get_selection_parent_node(), + var selectedNode = this.get('host').getSelectionParentNode(), text, equation; // Note this is a document fragment and YUI doesn't like them. - if (!selectednode) { + if (!selectedNode) { return false; } - text = Y.one(selectednode).get('text'); + text = Y.one(selectedNode).get('text'); // We use space or not space because . does not match new lines. pattern = /\$\$[\S\s]*\$\$/; equation = pattern.exec(text); @@ -176,154 +202,156 @@ M.atto_equation = M.atto_equation || { }, /** - * The OK button has been pressed - make the changes to the source. + * Handle insertion of a new equation, or update of an existing one. * - * @method set_equation - * @param {Y.Event} e - * @param {String} elementid + * @method _setEquation + * @param {EventFacade} e + * @private */ - set_equation : function(e, elementid) { + _setEquation: function(e) { var input, - selectednode, + selectedNode, text, pattern, equation, value; + var host = this.get('host'); + e.preventDefault(); - M.atto_equation.dialogue.hide(); - M.editor_atto.set_selection(M.atto_equation.selection); + this.getDialogue({ + focusAfterHide: null + }).hide(); input = e.currentTarget.ancestor('.atto_form').one('textarea'); value = input.get('value'); if (value !== '') { + host.setSelection(this._currentSelection); + value = '$$ ' + value.trim() + ' $$'; - selectednode = Y.one(M.editor_atto.get_selection_parent_node()), - text = selectednode.get('text'); + selectedNode = Y.one(host.getSelectionParentNode()); + text = selectedNode.get('text'); pattern = /\$\$[\S\s]*\$\$/; equation = pattern.exec(text); if (equation && equation.length) { // Replace the equation. equation = equation.pop(); text = text.replace(equation, '$$' + value + '$$'); - selectednode.set('text', text); + selectedNode.set('text', text); } else { // Insert the new equation. - M.editor_atto.insert_html_at_focus_point(value); + host.insertContentAtFocusPoint(value); } // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + this.markUpdated(); } }, /** * Update the preview div to match the current equation. * - * @param Event e - unused - * @param String elementid - The editor elementid. - * @method update_preview + * @param {EventFacade} e + * @method _updatePreview + * @private */ - update_preview : function(e, elementid) { - var textarea = Y.one('#atto_equation_equation'); - var equation = textarea.get('value'), url, preview; - var prefix = ''; - var cursorlatex = '\\square ' ; + _updatePreview: function(e) { + var textarea = this._content.one(SELECTORS.EQUATION_TEXT), + equation = textarea.get('value'), + url, + preview, + currentPos = textarea.get('selectionStart'), + prefix = '', + cursorLatex = '\\square ', + isChar; + - var currentpos = textarea.get('selectionStart'); - if (!currentpos) { - currentpos = 0; - } - // Move the cursor so it does not break expressions. - // - while (equation.charAt(currentpos) === '\\' && currentpos > 0) { - currentpos -= 1; - } - var ischar = /[\w\{\}]/; - while (ischar.test(equation.charAt(currentpos)) && currentpos < equation.length) { - currentpos += 1; - } - // Save the cursor position - for insertion from the library. - this.lastcursorpos = currentpos; - equation = prefix + equation.substring(0, currentpos) + cursorlatex + equation.substring(currentpos); if (e) { e.preventDefault(); } + + if (!currentPos) { + currentPos = 0; + } + // Move the cursor so it does not break expressions. + // + while (equation.charAt(currentPos) === '\\' && currentPos > 0) { + currentPos -= 1; + } + isChar = /[\w\{\}]/; + while (isChar.test(equation.charAt(currentPos)) && currentPos < equation.length) { + currentPos += 1; + } + // Save the cursor position - for insertion from the library. + this._lastCursorPos = currentPos; + equation = prefix + equation.substring(0, currentPos) + cursorLatex + equation.substring(currentPos); url = M.cfg.wwwroot + '/lib/editor/atto/plugins/equation/ajax.php'; params = { sesskey: M.cfg.sesskey, - contextid: this.contextids[elementid], - action : 'filtertext', - text : '$$ ' + equation + ' $$' + contextid: this.get('contextid'), + action: 'filtertext', + text: '$$ ' + equation + ' $$' }; - preview = Y.io(url, { sync: true, data: params }); if (preview.status === 200) { - Y.one('#atto_equation_preview').setHTML(preview.responseText); + this._content.one(SELECTORS.EQUATION_PREVIEW).setHTML(preview.responseText); } }, /** - * Return the HTML of the form to show in the dialogue. + * Return the dialogue content for the tool, attaching any required + * events. * - * @method get_form_content - * @param string elementid - * @return string + * @method _getDialogueContent + * @return {Node} + * @private */ - get_form_content : function(elementid) { - var content = Y.Node.create('
                                        ' + - this.get_library_html(elementid) + - '' + - '
                                        ' + - '

                                        ' + M.util.get_string('editequation_desc', 'atto_equation') + '

                                        ' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        '); + _getDialogueContent: function() { + var library = this._getLibraryContent(), + template = Y.Handlebars.compile(TEMPLATES.FORM); - content.one('#atto_equation_submit').on('click', M.atto_equation.set_equation, this, elementid); - content.one('#atto_equation_equation').on('valuechange', M.atto_equation.update_preview, this, elementid); - content.one('#atto_equation_equation').on('keyup', M.atto_equation.update_preview, this, elementid); - content.one('#atto_equation_equation').on('mouseup', M.atto_equation.update_preview, this, elementid); + this._content = Y.Node.create(template({ + elementid: this.get('host').get('elementid'), + component: COMPONENTNAME, + library: library, + CSS: CSS + })); - content.delegate('click', M.atto_equation.select_library_item, '#atto_equation_library button', this, elementid); + this._content.one(SELECTORS.SUBMIT).on('click', this._setEquation, this); + this._content.one(SELECTORS.EQUATION_TEXT).on('valuechange', this._updatePreview, this); + this._content.one(SELECTORS.EQUATION_TEXT).on('mouseup', this._updatePreview, this); + this._content.one(SELECTORS.EQUATION_TEXT).on('keyup', this._updatePreview, this); + this._content.delegate('click', this._selectLibraryItem, SELECTORS.LIBRARY_BUTTON, this); - return content; + return this._content; }, /** - * Reponse to button presses in the tex library panels. + * Reponse to button presses in the TeX library panels. * - * @method select_library_item - * @param Event event - * @param string elementid - * @return string + * @method _selectLibraryItem + * @param {EventFacade} e + * @return {string} + * @private */ - select_library_item : function(event, elementid) { - var tex = event.currentTarget.getAttribute('data-tex'); + _selectLibraryItem: function(e) { + var tex = e.currentTarget.getAttribute('data-tex'); - event.preventDefault(); + e.preventDefault(); - input = event.currentTarget.ancestor('.atto_form').one('textarea'); + input = e.currentTarget.ancestor('.atto_form').one('textarea'); value = input.get('value'); - value = value.substring(0, this.lastcursorpos) + tex + value.substring(this.lastcursorpos, value.length); + value = value.substring(0, this._lastCursorPos) + tex + value.substring(this._lastCursorPos, value.length); input.set('value', value); input.focus(); - var focusPoint = this.lastcursorpos + tex.length, + var focusPoint = this._lastCursorPos + tex.length, realInput = input.getDOMNode(); if (typeof realInput.selectionStart === "number") { // Modern browsers have selectionStart and selectionEnd to control the cursor position. @@ -335,54 +363,98 @@ M.atto_equation = M.atto_equation || { range.select(); } // Focus must be set before updating the preview for the cursor box to be in the correct location. - M.atto_equation.update_preview(false, elementid); + this._updatePreview(false); }, /** * Return the HTML for rendering the library of predefined buttons. * - * @method get_library_html - * @param string elementid - * @return string + * @method _getLibraryContent + * @return {string} + * @private */ - get_library_html : function(elementid) { - var content = '
                                        ', i = 0, group = 1; - content += ''; - content += '
                                        '; - for (group = 1; group < 5; group++) { - content += '
                                        '; - var examples = this.library['group' + group].split("\n"); - for (i = 0; i < examples.length; i++) { - if (examples[i]) { - examples[i] = Y.Escape.html(examples[i]); - content += ''; - } + _getLibraryContent: function() { + var template = Y.Handlebars.compile(TEMPLATES.LIBRARY), + library = this.get('library'), + content = ''; + + // Helper to iterate over a newline separated string. + Y.Handlebars.registerHelper('split', function(delimiter, str, options) { + var parts, + current, + out; + if (typeof delimiter === "undefined" || typeof str === "undefined") { + Y.log('Handlebars split helper: String and delimiter are required.', 'debug', 'moodle-atto_equation-button'); + return ''; } - content += '
                                        '; - } - content += '
                                        '; - content += '
                                        '; + + out = ''; + parts = str.trim().split(delimiter); + while (parts.length > 0) { + current = parts.shift(); + out += options.fn(current); + } + + return out; + }); + content = template({ + elementid: this.get('host').get('elementid'), + component: COMPONENTNAME, + library: library, + CSS: CSS + }); var url = M.cfg.wwwroot + '/lib/editor/atto/plugins/equation/ajax.php'; var params = { sesskey: M.cfg.sesskey, - contextid: this.contextids[elementid], - action : 'filtertext', - text : content + contextid: this.get('contextid'), + action: 'filtertext', + text: content }; - preview = Y.io(url, { sync: true, data: params, method: 'POST'}); + preview = Y.io(url, { + sync: true, + data: params, + method: 'POST' + }); if (preview.status === 200) { content = preview.responseText; } return content; } -}; +}, { + ATTRS: { + /** + * Whether the TeX filter is currently active. + * + * @attribute texfilteractive + * @type Boolean + */ + texfilteractive: { + value: false + }, + /** + * The contextid to use when generating this preview. + * + * @attribute contextid + * @type String + */ + contextid: { + value: null + }, + + /** + * The content of the example library. + * + * @attribute library + * @type object + */ + library: { + value: {} + } + } +}); -}, '@VERSION@', {"requires": ["node", "escape", "io", "event-valuechange", "tabview"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin", "io", "event-valuechange", "tabview"]}); 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 0f416d5eab3..53a447e201c 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){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();var s=M.atto_equation.resolve_equation();s&&e.one("#atto_equation_equation").set("text",s),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),M.editor_atto.on("atto:selectionchanged",function(e){M.atto_equation.resolve_equation()?M.editor_atto.add_widget_highlight(e.elementid,"equation"):M.editor_atto.remove_widget_highlight(e.elementid,"equation")}))},resolve_equation:function(){var t=M.editor_atto.get_selection_parent_node(),n,r;return t?(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),r):!1):!1},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)):M.editor_atto.insert_html_at_focus_point(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)+'"+'
                                        '+"

                                        "+M.util.get_string("editequation_desc","atto_equation")+"

                                        "+'"+'
                                        '+'
                                        '+"
                                        "+'"+"
                                        "+"");return n.one("#atto_equation_submit").on("click",M.atto_equation.set_equation,this,t),n.one("#atto_equation_equation").on("valuechange",M.atto_equation.update_preview,this,t),n.one("#atto_equation_equation").on("keyup",M.atto_equation.update_preview,this,t),n.one("#atto_equation_equation").on("mouseup",M.atto_equation.update_preview,this,t),n.delegate("click",M.atto_equation.select_library_item,"#atto_equation_library button",this,t),n},select_library_item:function(e,t){var n=e.currentTarget.getAttribute("data-tex");e.preventDefault(),input=e.currentTarget.ancestor(".atto_form").one("textarea"),value=input.get("value"),value=value.substring(0,this.lastcursorpos)+n+value.substring(this.lastcursorpos,value.length),input.set("value",value),input.focus();var r=this.lastcursorpos+n.length,i=input.getDOMNode();if(typeof i.selectionStart=="number")i.selectionStart=i.selectionEnd=r;else if(typeof i.createTextRange!="undefined"){var s=i.createTextRange();s.moveToPoint(r),s.select()}M.atto_equation.update_preview(!1,t)},get_library_html:function(t){var n='
                                        ',r=0,i=1;n+="",n+="
                                        ";for(i=1;i<5;i++){n+='
                                        ';var s=this.library["group"+i].split("\n");for(r=0;r$$'+s[r]+"$$");n+="
                                        "}n+="
                                        ",n+="
                                        ";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"]}); +YUI.add("moodle-atto_equation-button",function(e,t){var n="atto_equation",r={EQUATION_TEXT:"atto_equation_equation",EQUATION_PREVIEW:"atto_equation_preview",SUBMIT:"atto_equation_submit",LIBRARY:"atto_equation_library",LIBRARY_GROUP_PREFIX:"atto_equation_library"},i={LIBRARY_GROUP_PREFIX:"."+r.LIBRARY_GROUP_PREFIX,EQUATION_TEXT:"."+r.EQUATION_TEXT,EQUATION_PREVIEW:"."+r.EQUATION_PREVIEW,SUBMIT:"."+r.SUBMIT,LIBRARY_BUTTON:"."+r.LIBRARY+" button"},s={FORM:'
                                        {{{library}}}

                                        {{{get_string "editequation_desc" component}}}


                                        ',LIBRARY:'
                                        {{#each library}}
                                        {{#split "\n" elements}}{{/split}}
                                        {{/each}}
                                        '};e.namespace("M.atto_equation").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,_lastCursorPos:0,_content:null,initializer:function(){this.get("texfilteractive")&&(this.addButton({icon:"e/math",callback:this._displayDialogue}),this.get("host").on("atto:selectionchanged",function(){this._resolveEquation()?this.highlightButtons():this.unHighlightButtons()},this))},_displayDialogue:function(){this._currentSelection=this.get("host").getSelection();if(this._currentSelection===!1)return;var t=this.getDialogue({headerContent:M.util.get_string("pluginname",n),focusAfterHide:!0}),r=this._getDialogueContent();t.set("bodyContent",r);var s=r.one(i.LIBRARY_GROUP_PREFIX),o=new e.TabView({srcNode:s});o.render(),t.show();var u=this._resolveEquation();u&&r.one(i.EQUATION_TEXT).set("text",u),this._updatePreview(!1)},_resolveEquation:function(){var t=this.get("host").getSelectionParentNode(),n,r;return t?(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),r):!1):!1},_setEquation:function(t){var n,r,i,s,o,u,a=this.get("host");t.preventDefault(),this.getDialogue({focusAfterHide:null}).hide(),n=t.currentTarget.ancestor(".atto_form").one("textarea"),u=n.get("value"),u!==""&&(a.setSelection(this._currentSelection),u="$$ "+u.trim()+" $$",r=e.one(a.getSelectionParentNode()),i=r.get("text"),s=/\$\$[\S\s]*\$\$/,o=s.exec(i),o&&o.length?(o=o.pop(),i=i.replace(o,"$$"+u+"$$"),r.set("text",i)):a.insertContentAtFocusPoint(u),this.markUpdated())},_updatePreview:function(t){var n=this._content.one(i.EQUATION_TEXT),r=n.get("value"),s,o,u=n.get("selectionStart"),a="",f="\\square ",l;t&&t.preventDefault(),u||(u=0);while(r.charAt(u)==="\\"&&u>0)u-=1;l=/[\w\{\}]/;while(l.test(r.charAt(u))&&u0)i=r.shift(),s+=n.fn(i);return s}),o=t({elementid:this.get("host").get("elementid"),component:n,library:i,CSS:r});var u=M.cfg.wwwroot+"/lib/editor/atto/plugins/equation/ajax.php",a={sesskey:M.cfg.sesskey,contextid:this.get("contextid"),action:"filtertext",text:o};return preview=e.io(u,{sync:!0,data:a,method:"POST"}),preview.status===200&&(o=preview.responseText),o}},{ATTRS:{texfilteractive:{value:!1},contextid:{value:null},library:{value:{}}}})},"@VERSION@",{requires:["moodle-editor_atto-plugin","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 c0c14aede45..540c061f28d 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 @@ -16,153 +16,179 @@ YUI.add('moodle-atto_equation-button', function (Y, NAME) { // along with Moodle. If not, see . /** - * Atto text editor equation plugin. - * - * @package editor-atto + * @package atto_equation * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_equation = M.atto_equation || { - /** - * The window used to get the equation details. - * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, + +/** + * Atto text editor equation plugin. + */ + +/** + * Atto equation editor. + * + * @namespace M.atto_equation + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENTNAME = 'atto_equation', + CSS = { + EQUATION_TEXT: 'atto_equation_equation', + EQUATION_PREVIEW: 'atto_equation_preview', + SUBMIT: 'atto_equation_submit', + LIBRARY: 'atto_equation_library', + LIBRARY_GROUP_PREFIX: 'atto_equation_library' + }, + SELECTORS = { + LIBRARY_GROUP_PREFIX: '.' + CSS.LIBRARY_GROUP_PREFIX, + EQUATION_TEXT: '.' + CSS.EQUATION_TEXT, + EQUATION_PREVIEW: '.' + CSS.EQUATION_PREVIEW, + SUBMIT: '.' + CSS.SUBMIT, + LIBRARY_BUTTON: '.' + CSS.LIBRARY + ' button' + }, + TEMPLATES = { + FORM: '' + + '
                                        ' + + '{{{library}}}' + + '' + + '
                                        ' + + '

                                        {{{get_string "editequation_desc" component}}}

                                        ' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        ', + LIBRARY: '' + + '
                                        ' + + '' + + '
                                        ' + + '{{#each library}}' + + '
                                        ' + + '{{#split "\n" elements}}' + + '' + + '{{/split}}' + + '
                                        ' + + '{{/each}}' + + '
                                        ' + + '
                                        ' + }; + +Y.namespace('M.atto_equation').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** * The selection object returned by the browser. * - * @property selection + * @property _currentSelection * @type Range * @default null + * @private */ - selection : null, + _currentSelection: null, /** - * A mapping of elementids to contextids. + * The cursor position in the equation textarea. * - * @property contextids - * @type Object - * @default {} - */ - contextids : {}, - - /** - * A nested object containing a the configured list of tex examples. - * - * @property library - * @type Object - * @default {} - */ - library : {}, - - /** - * The last cursor index in the source. - * - * @property lastcursor - * @type Integer + * @property _lastCursorPos + * @type Number * @default 0 + * @private */ - lastcursor : 0, + _lastCursorPos: 0, /** - * Display the chooser dialogue. + * A reference to the dialogue content. * - * @method display_chooser - * @param Event e - * @param string elementid + * @property _content + * @type Node + * @private */ - display_chooser : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_equation.selection = M.editor_atto.get_selection(); - if (M.atto_equation.selection) { - var dialogue; - if (!M.atto_equation.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true, - width: '800px' - }); - } else { - dialogue = M.atto_equation.dialogue; - } + _content: null, - dialogue.render(); - dialogue.set('bodyContent', M.atto_equation.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('pluginname', 'atto_equation')); - - var tabview = new Y.TabView({ - srcNode: '#atto_equation_library' + initializer: function() { + if (this.get('texfilteractive')) { + // Add the button to the toolbar. + this.addButton({ + icon: 'e/math', + callback: this._displayDialogue }); - tabview.render(); - dialogue.show(); - 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; + // We need custom highlight logic for this button. + this.get('host').on('atto:selectionchanged', function() { + if (this._resolveEquation()) { + this.highlightButtons(); + } else { + this.unHighlightButtons(); + } + }, this); } }, /** - * Add this button to the form. + * Display the equation editor. * - * @method init - * @param {Object} params + * @method _displayDialogue + * @private */ - init : function(params) { - var iconurl = M.util.image_url('e/math', 'core'); + _displayDialogue: function() { + this._currentSelection = this.get('host').getSelection(); - if (params.texfilteractive) { - // Save the elementid/contextid mapping. - this.contextids[params.elementid] = params.contextid; - // Save the button library. - this.library = params.library; - - // 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. - M.editor_atto.on('atto:selectionchanged', function(e) { - if (M.atto_equation.resolve_equation()) { - M.editor_atto.add_widget_highlight(e.elementid, 'equation'); - } else { - M.editor_atto.remove_widget_highlight(e.elementid, 'equation'); - } - }); + if (this._currentSelection === false) { + return; } + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('pluginname', COMPONENTNAME), + focusAfterHide: true + }); + + var content = this._getDialogueContent(); + dialogue.set('bodyContent', content); + + var library = content.one(SELECTORS.LIBRARY_GROUP_PREFIX); + + var tabview = new Y.TabView({ + srcNode: library + }); + + tabview.render(); + dialogue.show(); + + var equation = this._resolveEquation(); + if (equation) { + content.one(SELECTORS.EQUATION_TEXT).set('text', equation); + } + this._updatePreview(false); }, /** * If there is selected text and it is part of an equation, * extract the equation (and set it in the form). * - * @method resolve_equation + * @method _resolveEquation + * @private * @return {String|Boolean} The equation or false. */ - resolve_equation : function() { + _resolveEquation: function() { + // Find the equation in the surrounding text. - var selectednode = M.editor_atto.get_selection_parent_node(), + var selectedNode = this.get('host').getSelectionParentNode(), text, equation; // Note this is a document fragment and YUI doesn't like them. - if (!selectednode) { + if (!selectedNode) { return false; } - text = Y.one(selectednode).get('text'); + text = Y.one(selectedNode).get('text'); // We use space or not space because . does not match new lines. pattern = /\$\$[\S\s]*\$\$/; equation = pattern.exec(text); @@ -176,154 +202,156 @@ M.atto_equation = M.atto_equation || { }, /** - * The OK button has been pressed - make the changes to the source. + * Handle insertion of a new equation, or update of an existing one. * - * @method set_equation - * @param {Y.Event} e - * @param {String} elementid + * @method _setEquation + * @param {EventFacade} e + * @private */ - set_equation : function(e, elementid) { + _setEquation: function(e) { var input, - selectednode, + selectedNode, text, pattern, equation, value; + var host = this.get('host'); + e.preventDefault(); - M.atto_equation.dialogue.hide(); - M.editor_atto.set_selection(M.atto_equation.selection); + this.getDialogue({ + focusAfterHide: null + }).hide(); input = e.currentTarget.ancestor('.atto_form').one('textarea'); value = input.get('value'); if (value !== '') { + host.setSelection(this._currentSelection); + value = '$$ ' + value.trim() + ' $$'; - selectednode = Y.one(M.editor_atto.get_selection_parent_node()), - text = selectednode.get('text'); + selectedNode = Y.one(host.getSelectionParentNode()); + text = selectedNode.get('text'); pattern = /\$\$[\S\s]*\$\$/; equation = pattern.exec(text); if (equation && equation.length) { // Replace the equation. equation = equation.pop(); text = text.replace(equation, '$$' + value + '$$'); - selectednode.set('text', text); + selectedNode.set('text', text); } else { // Insert the new equation. - M.editor_atto.insert_html_at_focus_point(value); + host.insertContentAtFocusPoint(value); } // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + this.markUpdated(); } }, /** * Update the preview div to match the current equation. * - * @param Event e - unused - * @param String elementid - The editor elementid. - * @method update_preview + * @param {EventFacade} e + * @method _updatePreview + * @private */ - update_preview : function(e, elementid) { - var textarea = Y.one('#atto_equation_equation'); - var equation = textarea.get('value'), url, preview; - var prefix = ''; - var cursorlatex = '\\square ' ; + _updatePreview: function(e) { + var textarea = this._content.one(SELECTORS.EQUATION_TEXT), + equation = textarea.get('value'), + url, + preview, + currentPos = textarea.get('selectionStart'), + prefix = '', + cursorLatex = '\\square ', + isChar; + - var currentpos = textarea.get('selectionStart'); - if (!currentpos) { - currentpos = 0; - } - // Move the cursor so it does not break expressions. - // - while (equation.charAt(currentpos) === '\\' && currentpos > 0) { - currentpos -= 1; - } - var ischar = /[\w\{\}]/; - while (ischar.test(equation.charAt(currentpos)) && currentpos < equation.length) { - currentpos += 1; - } - // Save the cursor position - for insertion from the library. - this.lastcursorpos = currentpos; - equation = prefix + equation.substring(0, currentpos) + cursorlatex + equation.substring(currentpos); if (e) { e.preventDefault(); } + + if (!currentPos) { + currentPos = 0; + } + // Move the cursor so it does not break expressions. + // + while (equation.charAt(currentPos) === '\\' && currentPos > 0) { + currentPos -= 1; + } + isChar = /[\w\{\}]/; + while (isChar.test(equation.charAt(currentPos)) && currentPos < equation.length) { + currentPos += 1; + } + // Save the cursor position - for insertion from the library. + this._lastCursorPos = currentPos; + equation = prefix + equation.substring(0, currentPos) + cursorLatex + equation.substring(currentPos); url = M.cfg.wwwroot + '/lib/editor/atto/plugins/equation/ajax.php'; params = { sesskey: M.cfg.sesskey, - contextid: this.contextids[elementid], - action : 'filtertext', - text : '$$ ' + equation + ' $$' + contextid: this.get('contextid'), + action: 'filtertext', + text: '$$ ' + equation + ' $$' }; - preview = Y.io(url, { sync: true, data: params }); if (preview.status === 200) { - Y.one('#atto_equation_preview').setHTML(preview.responseText); + this._content.one(SELECTORS.EQUATION_PREVIEW).setHTML(preview.responseText); } }, /** - * Return the HTML of the form to show in the dialogue. + * Return the dialogue content for the tool, attaching any required + * events. * - * @method get_form_content - * @param string elementid - * @return string + * @method _getDialogueContent + * @return {Node} + * @private */ - get_form_content : function(elementid) { - var content = Y.Node.create('
                                        ' + - this.get_library_html(elementid) + - '' + - '
                                        ' + - '

                                        ' + M.util.get_string('editequation_desc', 'atto_equation') + '

                                        ' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        '); + _getDialogueContent: function() { + var library = this._getLibraryContent(), + template = Y.Handlebars.compile(TEMPLATES.FORM); - content.one('#atto_equation_submit').on('click', M.atto_equation.set_equation, this, elementid); - content.one('#atto_equation_equation').on('valuechange', M.atto_equation.update_preview, this, elementid); - content.one('#atto_equation_equation').on('keyup', M.atto_equation.update_preview, this, elementid); - content.one('#atto_equation_equation').on('mouseup', M.atto_equation.update_preview, this, elementid); + this._content = Y.Node.create(template({ + elementid: this.get('host').get('elementid'), + component: COMPONENTNAME, + library: library, + CSS: CSS + })); - content.delegate('click', M.atto_equation.select_library_item, '#atto_equation_library button', this, elementid); + this._content.one(SELECTORS.SUBMIT).on('click', this._setEquation, this); + this._content.one(SELECTORS.EQUATION_TEXT).on('valuechange', this._updatePreview, this); + this._content.one(SELECTORS.EQUATION_TEXT).on('mouseup', this._updatePreview, this); + this._content.one(SELECTORS.EQUATION_TEXT).on('keyup', this._updatePreview, this); + this._content.delegate('click', this._selectLibraryItem, SELECTORS.LIBRARY_BUTTON, this); - return content; + return this._content; }, /** - * Reponse to button presses in the tex library panels. + * Reponse to button presses in the TeX library panels. * - * @method select_library_item - * @param Event event - * @param string elementid - * @return string + * @method _selectLibraryItem + * @param {EventFacade} e + * @return {string} + * @private */ - select_library_item : function(event, elementid) { - var tex = event.currentTarget.getAttribute('data-tex'); + _selectLibraryItem: function(e) { + var tex = e.currentTarget.getAttribute('data-tex'); - event.preventDefault(); + e.preventDefault(); - input = event.currentTarget.ancestor('.atto_form').one('textarea'); + input = e.currentTarget.ancestor('.atto_form').one('textarea'); value = input.get('value'); - value = value.substring(0, this.lastcursorpos) + tex + value.substring(this.lastcursorpos, value.length); + value = value.substring(0, this._lastCursorPos) + tex + value.substring(this._lastCursorPos, value.length); input.set('value', value); input.focus(); - var focusPoint = this.lastcursorpos + tex.length, + var focusPoint = this._lastCursorPos + tex.length, realInput = input.getDOMNode(); if (typeof realInput.selectionStart === "number") { // Modern browsers have selectionStart and selectionEnd to control the cursor position. @@ -335,54 +363,97 @@ M.atto_equation = M.atto_equation || { range.select(); } // Focus must be set before updating the preview for the cursor box to be in the correct location. - M.atto_equation.update_preview(false, elementid); + this._updatePreview(false); }, /** * Return the HTML for rendering the library of predefined buttons. * - * @method get_library_html - * @param string elementid - * @return string + * @method _getLibraryContent + * @return {string} + * @private */ - get_library_html : function(elementid) { - var content = '
                                        ', i = 0, group = 1; - content += ''; - content += '
                                        '; - for (group = 1; group < 5; group++) { - content += '
                                        '; - var examples = this.library['group' + group].split("\n"); - for (i = 0; i < examples.length; i++) { - if (examples[i]) { - examples[i] = Y.Escape.html(examples[i]); - content += ''; - } + _getLibraryContent: function() { + var template = Y.Handlebars.compile(TEMPLATES.LIBRARY), + library = this.get('library'), + content = ''; + + // Helper to iterate over a newline separated string. + Y.Handlebars.registerHelper('split', function(delimiter, str, options) { + var parts, + current, + out; + if (typeof delimiter === "undefined" || typeof str === "undefined") { + return ''; } - content += '
                                        '; - } - content += '
                                        '; - content += '
                                        '; + + out = ''; + parts = str.trim().split(delimiter); + while (parts.length > 0) { + current = parts.shift(); + out += options.fn(current); + } + + return out; + }); + content = template({ + elementid: this.get('host').get('elementid'), + component: COMPONENTNAME, + library: library, + CSS: CSS + }); var url = M.cfg.wwwroot + '/lib/editor/atto/plugins/equation/ajax.php'; var params = { sesskey: M.cfg.sesskey, - contextid: this.contextids[elementid], - action : 'filtertext', - text : content + contextid: this.get('contextid'), + action: 'filtertext', + text: content }; - preview = Y.io(url, { sync: true, data: params, method: 'POST'}); + preview = Y.io(url, { + sync: true, + data: params, + method: 'POST' + }); if (preview.status === 200) { content = preview.responseText; } return content; } -}; +}, { + ATTRS: { + /** + * Whether the TeX filter is currently active. + * + * @attribute texfilteractive + * @type Boolean + */ + texfilteractive: { + value: false + }, + /** + * The contextid to use when generating this preview. + * + * @attribute contextid + * @type String + */ + contextid: { + value: null + }, + + /** + * The content of the example library. + * + * @attribute library + * @type object + */ + library: { + value: {} + } + } +}); -}, '@VERSION@', {"requires": ["node", "escape", "io", "event-valuechange", "tabview"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin", "io", "event-valuechange", "tabview"]}); 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 8fde5344f23..6bbe8fd13d6 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 @@ -14,153 +14,179 @@ // along with Moodle. If not, see . /** - * Atto text editor equation plugin. - * - * @package editor-atto + * @package atto_equation * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_equation = M.atto_equation || { - /** - * The window used to get the equation details. - * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, + +/** + * Atto text editor equation plugin. + */ + +/** + * Atto equation editor. + * + * @namespace M.atto_equation + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENTNAME = 'atto_equation', + CSS = { + EQUATION_TEXT: 'atto_equation_equation', + EQUATION_PREVIEW: 'atto_equation_preview', + SUBMIT: 'atto_equation_submit', + LIBRARY: 'atto_equation_library', + LIBRARY_GROUP_PREFIX: 'atto_equation_library' + }, + SELECTORS = { + LIBRARY_GROUP_PREFIX: '.' + CSS.LIBRARY_GROUP_PREFIX, + EQUATION_TEXT: '.' + CSS.EQUATION_TEXT, + EQUATION_PREVIEW: '.' + CSS.EQUATION_PREVIEW, + SUBMIT: '.' + CSS.SUBMIT, + LIBRARY_BUTTON: '.' + CSS.LIBRARY + ' button' + }, + TEMPLATES = { + FORM: '' + + '
                                        ' + + '{{{library}}}' + + '' + + '
                                        ' + + '

                                        {{{get_string "editequation_desc" component}}}

                                        ' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        ', + LIBRARY: '' + + '
                                        ' + + '' + + '
                                        ' + + '{{#each library}}' + + '
                                        ' + + '{{#split "\n" elements}}' + + '' + + '{{/split}}' + + '
                                        ' + + '{{/each}}' + + '
                                        ' + + '
                                        ' + }; + +Y.namespace('M.atto_equation').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** * The selection object returned by the browser. * - * @property selection + * @property _currentSelection * @type Range * @default null + * @private */ - selection : null, + _currentSelection: null, /** - * A mapping of elementids to contextids. + * The cursor position in the equation textarea. * - * @property contextids - * @type Object - * @default {} - */ - contextids : {}, - - /** - * A nested object containing a the configured list of tex examples. - * - * @property library - * @type Object - * @default {} - */ - library : {}, - - /** - * The last cursor index in the source. - * - * @property lastcursor - * @type Integer + * @property _lastCursorPos + * @type Number * @default 0 + * @private */ - lastcursor : 0, + _lastCursorPos: 0, /** - * Display the chooser dialogue. + * A reference to the dialogue content. * - * @method display_chooser - * @param Event e - * @param string elementid + * @property _content + * @type Node + * @private */ - display_chooser : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_equation.selection = M.editor_atto.get_selection(); - if (M.atto_equation.selection) { - var dialogue; - if (!M.atto_equation.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true, - width: '800px' - }); - } else { - dialogue = M.atto_equation.dialogue; - } + _content: null, - dialogue.render(); - dialogue.set('bodyContent', M.atto_equation.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('pluginname', 'atto_equation')); - - var tabview = new Y.TabView({ - srcNode: '#atto_equation_library' + initializer: function() { + if (this.get('texfilteractive')) { + // Add the button to the toolbar. + this.addButton({ + icon: 'e/math', + callback: this._displayDialogue }); - tabview.render(); - dialogue.show(); - 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; + // We need custom highlight logic for this button. + this.get('host').on('atto:selectionchanged', function() { + if (this._resolveEquation()) { + this.highlightButtons(); + } else { + this.unHighlightButtons(); + } + }, this); } }, /** - * Add this button to the form. + * Display the equation editor. * - * @method init - * @param {Object} params + * @method _displayDialogue + * @private */ - init : function(params) { - var iconurl = M.util.image_url('e/math', 'core'); + _displayDialogue: function() { + this._currentSelection = this.get('host').getSelection(); - if (params.texfilteractive) { - // Save the elementid/contextid mapping. - this.contextids[params.elementid] = params.contextid; - // Save the button library. - this.library = params.library; - - // 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. - M.editor_atto.on('atto:selectionchanged', function(e) { - if (M.atto_equation.resolve_equation()) { - M.editor_atto.add_widget_highlight(e.elementid, 'equation'); - } else { - M.editor_atto.remove_widget_highlight(e.elementid, 'equation'); - } - }); + if (this._currentSelection === false) { + return; } + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('pluginname', COMPONENTNAME), + focusAfterHide: true + }); + + var content = this._getDialogueContent(); + dialogue.set('bodyContent', content); + + var library = content.one(SELECTORS.LIBRARY_GROUP_PREFIX); + + var tabview = new Y.TabView({ + srcNode: library + }); + + tabview.render(); + dialogue.show(); + + var equation = this._resolveEquation(); + if (equation) { + content.one(SELECTORS.EQUATION_TEXT).set('text', equation); + } + this._updatePreview(false); }, /** * If there is selected text and it is part of an equation, * extract the equation (and set it in the form). * - * @method resolve_equation + * @method _resolveEquation + * @private * @return {String|Boolean} The equation or false. */ - resolve_equation : function() { + _resolveEquation: function() { + // Find the equation in the surrounding text. - var selectednode = M.editor_atto.get_selection_parent_node(), + var selectedNode = this.get('host').getSelectionParentNode(), text, equation; // Note this is a document fragment and YUI doesn't like them. - if (!selectednode) { + if (!selectedNode) { return false; } - text = Y.one(selectednode).get('text'); + text = Y.one(selectedNode).get('text'); // We use space or not space because . does not match new lines. pattern = /\$\$[\S\s]*\$\$/; equation = pattern.exec(text); @@ -174,154 +200,156 @@ M.atto_equation = M.atto_equation || { }, /** - * The OK button has been pressed - make the changes to the source. + * Handle insertion of a new equation, or update of an existing one. * - * @method set_equation - * @param {Y.Event} e - * @param {String} elementid + * @method _setEquation + * @param {EventFacade} e + * @private */ - set_equation : function(e, elementid) { + _setEquation: function(e) { var input, - selectednode, + selectedNode, text, pattern, equation, value; + var host = this.get('host'); + e.preventDefault(); - M.atto_equation.dialogue.hide(); - M.editor_atto.set_selection(M.atto_equation.selection); + this.getDialogue({ + focusAfterHide: null + }).hide(); input = e.currentTarget.ancestor('.atto_form').one('textarea'); value = input.get('value'); if (value !== '') { + host.setSelection(this._currentSelection); + value = '$$ ' + value.trim() + ' $$'; - selectednode = Y.one(M.editor_atto.get_selection_parent_node()), - text = selectednode.get('text'); + selectedNode = Y.one(host.getSelectionParentNode()); + text = selectedNode.get('text'); pattern = /\$\$[\S\s]*\$\$/; equation = pattern.exec(text); if (equation && equation.length) { // Replace the equation. equation = equation.pop(); text = text.replace(equation, '$$' + value + '$$'); - selectednode.set('text', text); + selectedNode.set('text', text); } else { // Insert the new equation. - M.editor_atto.insert_html_at_focus_point(value); + host.insertContentAtFocusPoint(value); } // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + this.markUpdated(); } }, /** * Update the preview div to match the current equation. * - * @param Event e - unused - * @param String elementid - The editor elementid. - * @method update_preview + * @param {EventFacade} e + * @method _updatePreview + * @private */ - update_preview : function(e, elementid) { - var textarea = Y.one('#atto_equation_equation'); - var equation = textarea.get('value'), url, preview; - var prefix = ''; - var cursorlatex = '\\square ' ; + _updatePreview: function(e) { + var textarea = this._content.one(SELECTORS.EQUATION_TEXT), + equation = textarea.get('value'), + url, + preview, + currentPos = textarea.get('selectionStart'), + prefix = '', + cursorLatex = '\\square ', + isChar; + - var currentpos = textarea.get('selectionStart'); - if (!currentpos) { - currentpos = 0; - } - // Move the cursor so it does not break expressions. - // - while (equation.charAt(currentpos) === '\\' && currentpos > 0) { - currentpos -= 1; - } - var ischar = /[\w\{\}]/; - while (ischar.test(equation.charAt(currentpos)) && currentpos < equation.length) { - currentpos += 1; - } - // Save the cursor position - for insertion from the library. - this.lastcursorpos = currentpos; - equation = prefix + equation.substring(0, currentpos) + cursorlatex + equation.substring(currentpos); if (e) { e.preventDefault(); } + + if (!currentPos) { + currentPos = 0; + } + // Move the cursor so it does not break expressions. + // + while (equation.charAt(currentPos) === '\\' && currentPos > 0) { + currentPos -= 1; + } + isChar = /[\w\{\}]/; + while (isChar.test(equation.charAt(currentPos)) && currentPos < equation.length) { + currentPos += 1; + } + // Save the cursor position - for insertion from the library. + this._lastCursorPos = currentPos; + equation = prefix + equation.substring(0, currentPos) + cursorLatex + equation.substring(currentPos); url = M.cfg.wwwroot + '/lib/editor/atto/plugins/equation/ajax.php'; params = { sesskey: M.cfg.sesskey, - contextid: this.contextids[elementid], - action : 'filtertext', - text : '$$ ' + equation + ' $$' + contextid: this.get('contextid'), + action: 'filtertext', + text: '$$ ' + equation + ' $$' }; - preview = Y.io(url, { sync: true, data: params }); if (preview.status === 200) { - Y.one('#atto_equation_preview').setHTML(preview.responseText); + this._content.one(SELECTORS.EQUATION_PREVIEW).setHTML(preview.responseText); } }, /** - * Return the HTML of the form to show in the dialogue. + * Return the dialogue content for the tool, attaching any required + * events. * - * @method get_form_content - * @param string elementid - * @return string + * @method _getDialogueContent + * @return {Node} + * @private */ - get_form_content : function(elementid) { - var content = Y.Node.create('
                                        ' + - this.get_library_html(elementid) + - '' + - '
                                        ' + - '

                                        ' + M.util.get_string('editequation_desc', 'atto_equation') + '

                                        ' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        '); + _getDialogueContent: function() { + var library = this._getLibraryContent(), + template = Y.Handlebars.compile(TEMPLATES.FORM); - content.one('#atto_equation_submit').on('click', M.atto_equation.set_equation, this, elementid); - content.one('#atto_equation_equation').on('valuechange', M.atto_equation.update_preview, this, elementid); - content.one('#atto_equation_equation').on('keyup', M.atto_equation.update_preview, this, elementid); - content.one('#atto_equation_equation').on('mouseup', M.atto_equation.update_preview, this, elementid); + this._content = Y.Node.create(template({ + elementid: this.get('host').get('elementid'), + component: COMPONENTNAME, + library: library, + CSS: CSS + })); - content.delegate('click', M.atto_equation.select_library_item, '#atto_equation_library button', this, elementid); + this._content.one(SELECTORS.SUBMIT).on('click', this._setEquation, this); + this._content.one(SELECTORS.EQUATION_TEXT).on('valuechange', this._updatePreview, this); + this._content.one(SELECTORS.EQUATION_TEXT).on('mouseup', this._updatePreview, this); + this._content.one(SELECTORS.EQUATION_TEXT).on('keyup', this._updatePreview, this); + this._content.delegate('click', this._selectLibraryItem, SELECTORS.LIBRARY_BUTTON, this); - return content; + return this._content; }, /** - * Reponse to button presses in the tex library panels. + * Reponse to button presses in the TeX library panels. * - * @method select_library_item - * @param Event event - * @param string elementid - * @return string + * @method _selectLibraryItem + * @param {EventFacade} e + * @return {string} + * @private */ - select_library_item : function(event, elementid) { - var tex = event.currentTarget.getAttribute('data-tex'); + _selectLibraryItem: function(e) { + var tex = e.currentTarget.getAttribute('data-tex'); - event.preventDefault(); + e.preventDefault(); - input = event.currentTarget.ancestor('.atto_form').one('textarea'); + input = e.currentTarget.ancestor('.atto_form').one('textarea'); value = input.get('value'); - value = value.substring(0, this.lastcursorpos) + tex + value.substring(this.lastcursorpos, value.length); + value = value.substring(0, this._lastCursorPos) + tex + value.substring(this._lastCursorPos, value.length); input.set('value', value); input.focus(); - var focusPoint = this.lastcursorpos + tex.length, + var focusPoint = this._lastCursorPos + tex.length, realInput = input.getDOMNode(); if (typeof realInput.selectionStart === "number") { // Modern browsers have selectionStart and selectionEnd to control the cursor position. @@ -333,51 +361,95 @@ M.atto_equation = M.atto_equation || { range.select(); } // Focus must be set before updating the preview for the cursor box to be in the correct location. - M.atto_equation.update_preview(false, elementid); + this._updatePreview(false); }, /** * Return the HTML for rendering the library of predefined buttons. * - * @method get_library_html - * @param string elementid - * @return string + * @method _getLibraryContent + * @return {string} + * @private */ - get_library_html : function(elementid) { - var content = '
                                        ', i = 0, group = 1; - content += ''; - content += '
                                        '; - for (group = 1; group < 5; group++) { - content += '
                                        '; - var examples = this.library['group' + group].split("\n"); - for (i = 0; i < examples.length; i++) { - if (examples[i]) { - examples[i] = Y.Escape.html(examples[i]); - content += ''; - } + _getLibraryContent: function() { + var template = Y.Handlebars.compile(TEMPLATES.LIBRARY), + library = this.get('library'), + content = ''; + + // Helper to iterate over a newline separated string. + Y.Handlebars.registerHelper('split', function(delimiter, str, options) { + var parts, + current, + out; + if (typeof delimiter === "undefined" || typeof str === "undefined") { + Y.log('Handlebars split helper: String and delimiter are required.', 'debug', 'moodle-atto_equation-button'); + return ''; } - content += '
                                        '; - } - content += '
                                        '; - content += '
                                        '; + + out = ''; + parts = str.trim().split(delimiter); + while (parts.length > 0) { + current = parts.shift(); + out += options.fn(current); + } + + return out; + }); + content = template({ + elementid: this.get('host').get('elementid'), + component: COMPONENTNAME, + library: library, + CSS: CSS + }); var url = M.cfg.wwwroot + '/lib/editor/atto/plugins/equation/ajax.php'; var params = { sesskey: M.cfg.sesskey, - contextid: this.contextids[elementid], - action : 'filtertext', - text : content + contextid: this.get('contextid'), + action: 'filtertext', + text: content }; - preview = Y.io(url, { sync: true, data: params, method: 'POST'}); + preview = Y.io(url, { + sync: true, + data: params, + method: 'POST' + }); if (preview.status === 200) { content = preview.responseText; } return content; } -}; +}, { + ATTRS: { + /** + * Whether the TeX filter is currently active. + * + * @attribute texfilteractive + * @type Boolean + */ + texfilteractive: { + value: false + }, + /** + * The contextid to use when generating this preview. + * + * @attribute contextid + * @type String + */ + contextid: { + value: null + }, + + /** + * The content of the example library. + * + * @attribute library + * @type object + */ + library: { + value: {} + } + } +}); diff --git a/lib/editor/atto/plugins/equation/yui/src/button/meta/button.json b/lib/editor/atto/plugins/equation/yui/src/button/meta/button.json index 11747f5bbc2..c0d749fae02 100644 --- a/lib/editor/atto/plugins/equation/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/equation/yui/src/button/meta/button.json @@ -1,11 +1,10 @@ { - "moodle-atto_equation-button": { - "requires": [ - "node", - "escape", - "io", - "event-valuechange", - "tabview" - ] - } + "moodle-atto_equation-button": { + "requires": [ + "moodle-editor_atto-plugin", + "io", + "event-valuechange", + "tabview" + ] + } } diff --git a/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button-debug.js b/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button-debug.js index c650967735f..bd0465ef67c 100644 --- a/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button-debug.js +++ b/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button-debug.js @@ -15,88 +15,85 @@ YUI.add('moodle-atto_fontcolor-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor font color plugin. - * - * @package editor-atto +/* + * @package atto_fontcolor * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_fontcolor = M.atto_fontcolor || { - dialogue : null, - init : function(params) { - var plugin = 'fontcolor'; - var rgb_white = '#FFFFFF', - rgb_red = '#EF4540', - rgb_yellow = '#FFCF35', - rgb_green = '#98CA3E', - rgb_blue = '#7D9FD3', - rgb_black = '#333333'; +/** + * @module moodle-atto_align-button + */ - var click_white = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, 'transparent'); - }; - var click_red = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_red); - }; - var click_yellow = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_yellow); - }; - var click_green = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_green); - }; - var click_blue = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_blue); - }; - var click_black = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_black); - }; +/** + * Atto text editor fontcolor plugin. + * + * @namespace M.atto_fontcolor + * @class button + * @extends M.editor_atto.EditorPlugin + */ - var buttoncss = 'width: 20px; height: 20px; border: 1px solid #CCC; background-color: '; - var white = '
                                        '; - var red = '
                                        '; - var yellow = '
                                        '; - var green = '
                                        '; - var blue = '
                                        '; - var black = '
                                        '; +var colors = [ + { + name: 'white', + color: '#FFFFFF' + }, { + name: 'red', + color: '#EF4540' + }, { + name: 'yellow', + color: '#FFCF35' + }, { + name: 'green', + color: '#98CA3E' + }, { + name: 'blue', + color: '#7D9FD3' + }, { + name: 'black', + color: '#333333' + } + ]; - var iconurl = M.util.image_url('e/text_color', 'core'); +Y.namespace('M.atto_fontcolor').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var items = []; + Y.Array.each(colors, function(color) { + items.push({ + text: '
                                        ', + callbackArgs: color.color, + callback: this._changeStyle + }); + }); - M.editor_atto.add_toolbar_menu(params.elementid, - plugin, - iconurl, - params.group, - [ - {'text' : white, 'handler' : click_white}, - {'text' : red, 'handler' : click_red}, - {'text' : yellow, 'handler' : click_yellow}, - {'text' : green, 'handler' : click_green}, - {'text' : blue, 'handler' : click_blue}, - {'text' : black, 'handler' : click_black} - ], - false, - false, - '4', - '#333333'); + this.addToolbarMenu({ + icon: 'e/text_color', + overlayWidth: '4', + menuColor: '#333333', + globalItemConfig: { + callback: this._changeStyle + }, + items: items + }); }, /** - * Handle to change the editor font color. - * @param event e - The event that triggered this. - * @param string elementid - the elemen id of menu icon. - * @param string color - The color for the background. + * Change the font color to the specified color. + * + * @method _changeStyle + * @param {EventFacade} e + * @param {string} color The new font color + * @private */ - change_color : function(e, elementid, color) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('foreColor', 0, color); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + _changeStyle: function(e, color) { + document.execCommand('forecolor', 0, color); + + // Mark as updated + this.markUpdated(); } -}; +}); }, '@VERSION@'); diff --git a/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button-min.js b/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button-min.js index d948f37e39e..0017bcb018e 100644 --- a/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button-min.js +++ b/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_fontcolor-button",function(e,t){M.atto_fontcolor=M.atto_fontcolor||{dialogue:null,init:function(e){var t="fontcolor",n="#FFFFFF",r="#EF4540",i="#FFCF35",s="#98CA3E",o="#7D9FD3",u="#333333",a=function(e,t){M.atto_fontcolor.change_color(e,t,"transparent")},f=function(e,t){M.atto_fontcolor.change_color(e,t,r)},l=function(e,t){M.atto_fontcolor.change_color(e,t,i)},c=function(e,t){M.atto_fontcolor.change_color(e,t,s)},h=function(e,t){M.atto_fontcolor.change_color(e,t,o)},p=function(e,t){M.atto_fontcolor.change_color(e,t,u)},d="width: 20px; height: 20px; border: 1px solid #CCC; background-color: ",v='
                                        ',m='
                                        ',g='
                                        ',y='
                                        ',b='
                                        ',w='
                                        ',E=M.util.image_url("e/text_color","core");M.editor_atto.add_toolbar_menu(e.elementid,t,E,e.group,[{text:v,handler:a},{text:m,handler:f},{text:g,handler:l},{text:y,handler:c},{text:b,handler:h},{text:w,handler:p}],!1,!1,"4","#333333")},change_color:function(e,t,n){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("foreColor",0,n),M.editor_atto.text_updated(t)}}},"@VERSION@"); +YUI.add("moodle-atto_fontcolor-button",function(e,t){var n=[{name:"white",color:"#FFFFFF"},{name:"red",color:"#EF4540"},{name:"yellow",color:"#FFCF35"},{name:"green",color:"#98CA3E"},{name:"blue",color:"#7D9FD3"},{name:"black",color:"#333333"}];e.namespace("M.atto_fontcolor").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var t=[];e.Array.each(n,function(e){t.push({text:'
                                        ',callbackArgs:e.color,callback:this._changeStyle})}),this.addToolbarMenu({icon:"e/text_color",overlayWidth:"4",menuColor:"#333333",globalItemConfig:{callback:this._changeStyle},items:t})},_changeStyle:function(e,t){document.execCommand("forecolor",0,t),this.markUpdated()}})},"@VERSION@"); diff --git a/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button.js b/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button.js index c650967735f..bd0465ef67c 100644 --- a/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button.js +++ b/lib/editor/atto/plugins/fontcolor/yui/build/moodle-atto_fontcolor-button/moodle-atto_fontcolor-button.js @@ -15,88 +15,85 @@ YUI.add('moodle-atto_fontcolor-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor font color plugin. - * - * @package editor-atto +/* + * @package atto_fontcolor * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_fontcolor = M.atto_fontcolor || { - dialogue : null, - init : function(params) { - var plugin = 'fontcolor'; - var rgb_white = '#FFFFFF', - rgb_red = '#EF4540', - rgb_yellow = '#FFCF35', - rgb_green = '#98CA3E', - rgb_blue = '#7D9FD3', - rgb_black = '#333333'; +/** + * @module moodle-atto_align-button + */ - var click_white = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, 'transparent'); - }; - var click_red = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_red); - }; - var click_yellow = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_yellow); - }; - var click_green = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_green); - }; - var click_blue = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_blue); - }; - var click_black = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_black); - }; +/** + * Atto text editor fontcolor plugin. + * + * @namespace M.atto_fontcolor + * @class button + * @extends M.editor_atto.EditorPlugin + */ - var buttoncss = 'width: 20px; height: 20px; border: 1px solid #CCC; background-color: '; - var white = '
                                        '; - var red = '
                                        '; - var yellow = '
                                        '; - var green = '
                                        '; - var blue = '
                                        '; - var black = '
                                        '; +var colors = [ + { + name: 'white', + color: '#FFFFFF' + }, { + name: 'red', + color: '#EF4540' + }, { + name: 'yellow', + color: '#FFCF35' + }, { + name: 'green', + color: '#98CA3E' + }, { + name: 'blue', + color: '#7D9FD3' + }, { + name: 'black', + color: '#333333' + } + ]; - var iconurl = M.util.image_url('e/text_color', 'core'); +Y.namespace('M.atto_fontcolor').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var items = []; + Y.Array.each(colors, function(color) { + items.push({ + text: '
                                        ', + callbackArgs: color.color, + callback: this._changeStyle + }); + }); - M.editor_atto.add_toolbar_menu(params.elementid, - plugin, - iconurl, - params.group, - [ - {'text' : white, 'handler' : click_white}, - {'text' : red, 'handler' : click_red}, - {'text' : yellow, 'handler' : click_yellow}, - {'text' : green, 'handler' : click_green}, - {'text' : blue, 'handler' : click_blue}, - {'text' : black, 'handler' : click_black} - ], - false, - false, - '4', - '#333333'); + this.addToolbarMenu({ + icon: 'e/text_color', + overlayWidth: '4', + menuColor: '#333333', + globalItemConfig: { + callback: this._changeStyle + }, + items: items + }); }, /** - * Handle to change the editor font color. - * @param event e - The event that triggered this. - * @param string elementid - the elemen id of menu icon. - * @param string color - The color for the background. + * Change the font color to the specified color. + * + * @method _changeStyle + * @param {EventFacade} e + * @param {string} color The new font color + * @private */ - change_color : function(e, elementid, color) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('foreColor', 0, color); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + _changeStyle: function(e, color) { + document.execCommand('forecolor', 0, color); + + // Mark as updated + this.markUpdated(); } -}; +}); }, '@VERSION@'); diff --git a/lib/editor/atto/plugins/fontcolor/yui/src/button/js/button.js b/lib/editor/atto/plugins/fontcolor/yui/src/button/js/button.js index 71d6bea31ae..51990c269f9 100644 --- a/lib/editor/atto/plugins/fontcolor/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/fontcolor/yui/src/button/js/button.js @@ -13,85 +13,82 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor font color plugin. - * - * @package editor-atto +/* + * @package atto_fontcolor * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_fontcolor = M.atto_fontcolor || { - dialogue : null, - init : function(params) { - var plugin = 'fontcolor'; - var rgb_white = '#FFFFFF', - rgb_red = '#EF4540', - rgb_yellow = '#FFCF35', - rgb_green = '#98CA3E', - rgb_blue = '#7D9FD3', - rgb_black = '#333333'; +/** + * @module moodle-atto_align-button + */ - var click_white = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, 'transparent'); - }; - var click_red = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_red); - }; - var click_yellow = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_yellow); - }; - var click_green = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_green); - }; - var click_blue = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_blue); - }; - var click_black = function(e, elementid) { - M.atto_fontcolor.change_color(e, elementid, rgb_black); - }; +/** + * Atto text editor fontcolor plugin. + * + * @namespace M.atto_fontcolor + * @class button + * @extends M.editor_atto.EditorPlugin + */ - var buttoncss = 'width: 20px; height: 20px; border: 1px solid #CCC; background-color: '; - var white = '
                                        '; - var red = '
                                        '; - var yellow = '
                                        '; - var green = '
                                        '; - var blue = '
                                        '; - var black = '
                                        '; +var colors = [ + { + name: 'white', + color: '#FFFFFF' + }, { + name: 'red', + color: '#EF4540' + }, { + name: 'yellow', + color: '#FFCF35' + }, { + name: 'green', + color: '#98CA3E' + }, { + name: 'blue', + color: '#7D9FD3' + }, { + name: 'black', + color: '#333333' + } + ]; - var iconurl = M.util.image_url('e/text_color', 'core'); +Y.namespace('M.atto_fontcolor').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var items = []; + Y.Array.each(colors, function(color) { + items.push({ + text: '
                                        ', + callbackArgs: color.color, + callback: this._changeStyle + }); + }); - M.editor_atto.add_toolbar_menu(params.elementid, - plugin, - iconurl, - params.group, - [ - {'text' : white, 'handler' : click_white}, - {'text' : red, 'handler' : click_red}, - {'text' : yellow, 'handler' : click_yellow}, - {'text' : green, 'handler' : click_green}, - {'text' : blue, 'handler' : click_blue}, - {'text' : black, 'handler' : click_black} - ], - false, - false, - '4', - '#333333'); + this.addToolbarMenu({ + icon: 'e/text_color', + overlayWidth: '4', + menuColor: '#333333', + globalItemConfig: { + callback: this._changeStyle + }, + items: items + }); }, /** - * Handle to change the editor font color. - * @param event e - The event that triggered this. - * @param string elementid - the elemen id of menu icon. - * @param string color - The color for the background. + * Change the font color to the specified color. + * + * @method _changeStyle + * @param {EventFacade} e + * @param {string} color The new font color + * @private */ - change_color : function(e, elementid, color) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('foreColor', 0, color); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + _changeStyle: function(e, color) { + document.execCommand('forecolor', 0, color); + + // Mark as updated + this.markUpdated(); } -}; +}); diff --git a/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button-debug.js b/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button-debug.js index d1feb4d812f..32233dad876 100644 --- a/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button-debug.js +++ b/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button-debug.js @@ -15,48 +15,106 @@ YUI.add('moodle-atto_html-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor html plugin. - * - * @package editor-atto +/* + * @package atto_html * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_html = M.atto_html || { + +/** + * @module moodle-atto_html-button + */ + +/** + * Atto text editor HTML plugin. + * + * @namespace M.atto_html + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_html').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addButton({ + icon: 'e/source_code', + callback: this._toggleHTML + }); + }, + /** - * Are we in html editing mode or not? + * Toggle the view between the content editable div, and the textarea, + * updating the content as it goes. + * + * @method _toggleHTML + * @private */ - ishtml : false, + _toggleHTML: function() { + // Toggle the HTML status. + this.set('isHTML', !this.get('isHTML')); - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - var textarea = M.editor_atto.get_textarea_node(elementid), - atto = M.editor_atto.get_editable_node(elementid); + // Now make the UI changes. + this._showHTML(); + }, - if (M.atto_html.ishtml) { - M.editor_atto.enable_all_widgets(elementid); - // Copy the text to the contenteditable div. - M.editor_atto.update_from_textarea(elementid); - textarea.hide(); - atto.show(); - atto.focus(); - } else { - M.editor_atto.disable_all_widgets(elementid); - M.editor_atto.enable_widget(elementid, 'html'); - M.editor_atto.text_updated(elementid); - atto.hide(); - textarea.show(); - textarea.focus(); - } + /** + * Set the current state of the textarea and contenteditable div + * according to the isHTML property. + * + * @method _showHTML + * @private + */ + _showHTML: function() { + var host = this.get('host'); + if (!this.get('isHTML')) { + // Enable all plugins. + host.enablePlugins(); - M.atto_html.ishtml = !M.atto_html.ishtml; - }; + // Copy the text to the contenteditable div. + host.updateFromTextArea(); - var iconurl = M.util.image_url('e/source_code', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'html', iconurl, params.group, click); + // Hide the textarea, and show the editor. + host.textarea.hide(); + this.editor.show(); + + // Focus on the editor. + host.focus(); + + // And re-mark everything as updated. + this.markUpdated(); + } else { + // Disable all plugins. + host.disablePlugins(); + + // And then re-enable this one. + host.enablePlugins(this.name); + + // Copy the text to the contenteditable div. + host.updateOriginal(); + + // Hide the editor, and show the textarea. + this.editor.hide(); + host.textarea.show(); + + // Focus on the textarea. + host.textarea.focus(); + } } -}; +}, { + ATTRS: { + /** + * The current state for the HTML view. If true, the HTML source is + * shown in a textarea, otherwise the contenteditable area is + * displayed. + * + * @attribute isHTML + * @type Boolean + * @default false + */ + isHTML: { + value: false + } + } +}); -}, '@VERSION@', {"requires": ["node", "event-valuechange"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin", "event-valuechange"]}); diff --git a/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button-min.js b/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button-min.js index d0efdf30013..d974624e214 100644 --- a/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button-min.js +++ b/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button-min.js @@ -1 +1 @@ -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),M.editor_atto.update_from_textarea(t),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"]}); +YUI.add("moodle-atto_html-button",function(e,t){e.namespace("M.atto_html").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addButton({icon:"e/source_code",callback:this._toggleHTML})},_toggleHTML:function(){this.set("isHTML",!this.get("isHTML")),this._showHTML()},_showHTML:function(){var e=this.get("host");this.get("isHTML")?(e.disablePlugins(),e.enablePlugins(this.name),e.updateOriginal(),this.editor.hide(),e.textarea.show(),e.textarea.focus()):(e.enablePlugins(),e.updateFromTextArea(),e.textarea.hide(),this.editor.show(),e.focus(),this.markUpdated())}},{ATTRS:{isHTML:{value:!1}}})},"@VERSION@",{requires:["moodle-editor_atto-plugin","event-valuechange"]}); diff --git a/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button.js b/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button.js index d1feb4d812f..32233dad876 100644 --- a/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button.js +++ b/lib/editor/atto/plugins/html/yui/build/moodle-atto_html-button/moodle-atto_html-button.js @@ -15,48 +15,106 @@ YUI.add('moodle-atto_html-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor html plugin. - * - * @package editor-atto +/* + * @package atto_html * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_html = M.atto_html || { + +/** + * @module moodle-atto_html-button + */ + +/** + * Atto text editor HTML plugin. + * + * @namespace M.atto_html + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_html').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addButton({ + icon: 'e/source_code', + callback: this._toggleHTML + }); + }, + /** - * Are we in html editing mode or not? + * Toggle the view between the content editable div, and the textarea, + * updating the content as it goes. + * + * @method _toggleHTML + * @private */ - ishtml : false, + _toggleHTML: function() { + // Toggle the HTML status. + this.set('isHTML', !this.get('isHTML')); - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - var textarea = M.editor_atto.get_textarea_node(elementid), - atto = M.editor_atto.get_editable_node(elementid); + // Now make the UI changes. + this._showHTML(); + }, - if (M.atto_html.ishtml) { - M.editor_atto.enable_all_widgets(elementid); - // Copy the text to the contenteditable div. - M.editor_atto.update_from_textarea(elementid); - textarea.hide(); - atto.show(); - atto.focus(); - } else { - M.editor_atto.disable_all_widgets(elementid); - M.editor_atto.enable_widget(elementid, 'html'); - M.editor_atto.text_updated(elementid); - atto.hide(); - textarea.show(); - textarea.focus(); - } + /** + * Set the current state of the textarea and contenteditable div + * according to the isHTML property. + * + * @method _showHTML + * @private + */ + _showHTML: function() { + var host = this.get('host'); + if (!this.get('isHTML')) { + // Enable all plugins. + host.enablePlugins(); - M.atto_html.ishtml = !M.atto_html.ishtml; - }; + // Copy the text to the contenteditable div. + host.updateFromTextArea(); - var iconurl = M.util.image_url('e/source_code', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'html', iconurl, params.group, click); + // Hide the textarea, and show the editor. + host.textarea.hide(); + this.editor.show(); + + // Focus on the editor. + host.focus(); + + // And re-mark everything as updated. + this.markUpdated(); + } else { + // Disable all plugins. + host.disablePlugins(); + + // And then re-enable this one. + host.enablePlugins(this.name); + + // Copy the text to the contenteditable div. + host.updateOriginal(); + + // Hide the editor, and show the textarea. + this.editor.hide(); + host.textarea.show(); + + // Focus on the textarea. + host.textarea.focus(); + } } -}; +}, { + ATTRS: { + /** + * The current state for the HTML view. If true, the HTML source is + * shown in a textarea, otherwise the contenteditable area is + * displayed. + * + * @attribute isHTML + * @type Boolean + * @default false + */ + isHTML: { + value: false + } + } +}); -}, '@VERSION@', {"requires": ["node", "event-valuechange"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin", "event-valuechange"]}); diff --git a/lib/editor/atto/plugins/html/yui/src/button/js/button.js b/lib/editor/atto/plugins/html/yui/src/button/js/button.js index 5d148f3a4b0..b4b813273dc 100644 --- a/lib/editor/atto/plugins/html/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/html/yui/src/button/js/button.js @@ -13,45 +13,103 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor html plugin. - * - * @package editor-atto +/* + * @package atto_html * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_html = M.atto_html || { + +/** + * @module moodle-atto_html-button + */ + +/** + * Atto text editor HTML plugin. + * + * @namespace M.atto_html + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_html').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addButton({ + icon: 'e/source_code', + callback: this._toggleHTML + }); + }, + /** - * Are we in html editing mode or not? + * Toggle the view between the content editable div, and the textarea, + * updating the content as it goes. + * + * @method _toggleHTML + * @private */ - ishtml : false, + _toggleHTML: function() { + // Toggle the HTML status. + this.set('isHTML', !this.get('isHTML')); - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - var textarea = M.editor_atto.get_textarea_node(elementid), - atto = M.editor_atto.get_editable_node(elementid); + // Now make the UI changes. + this._showHTML(); + }, - if (M.atto_html.ishtml) { - M.editor_atto.enable_all_widgets(elementid); - // Copy the text to the contenteditable div. - M.editor_atto.update_from_textarea(elementid); - textarea.hide(); - atto.show(); - atto.focus(); - } else { - M.editor_atto.disable_all_widgets(elementid); - M.editor_atto.enable_widget(elementid, 'html'); - M.editor_atto.text_updated(elementid); - atto.hide(); - textarea.show(); - textarea.focus(); - } + /** + * Set the current state of the textarea and contenteditable div + * according to the isHTML property. + * + * @method _showHTML + * @private + */ + _showHTML: function() { + var host = this.get('host'); + if (!this.get('isHTML')) { + // Enable all plugins. + host.enablePlugins(); - M.atto_html.ishtml = !M.atto_html.ishtml; - }; + // Copy the text to the contenteditable div. + host.updateFromTextArea(); - var iconurl = M.util.image_url('e/source_code', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'html', iconurl, params.group, click); + // Hide the textarea, and show the editor. + host.textarea.hide(); + this.editor.show(); + + // Focus on the editor. + host.focus(); + + // And re-mark everything as updated. + this.markUpdated(); + } else { + // Disable all plugins. + host.disablePlugins(); + + // And then re-enable this one. + host.enablePlugins(this.name); + + // Copy the text to the contenteditable div. + host.updateOriginal(); + + // Hide the editor, and show the textarea. + this.editor.hide(); + host.textarea.show(); + + // Focus on the textarea. + host.textarea.focus(); + } } -}; +}, { + ATTRS: { + /** + * The current state for the HTML view. If true, the HTML source is + * shown in a textarea, otherwise the contenteditable area is + * displayed. + * + * @attribute isHTML + * @type Boolean + * @default false + */ + isHTML: { + value: false + } + } +}); diff --git a/lib/editor/atto/plugins/html/yui/src/button/meta/button.json b/lib/editor/atto/plugins/html/yui/src/button/meta/button.json index 71a63dd799c..04a00abcd8a 100644 --- a/lib/editor/atto/plugins/html/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/html/yui/src/button/meta/button.json @@ -1,8 +1,8 @@ { - "moodle-atto_html-button": { - "requires": [ - "node", - "event-valuechange" - ] - } + "moodle-atto_html-button": { + "requires": [ + "moodle-editor_atto-plugin", + "event-valuechange" + ] + } } 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 0dd4d4aee30..1b319caf399 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,14 +15,29 @@ 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 . -var SELECTORS = { - TAGS: 'img' - }, - CSS = { +/* + * @package atto_image + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @module moodle-atto_image_alignment-button + */ + +/** + * Atto image selection tool. + * + * @namespace M.atto_image + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var CSS = { INPUTALIGNMENT: 'atto_image_alignment', INPUTALT: 'atto_image_altentry', INPUTHEIGHT: 'atto_image_heightentry', - INPUTSUMBIT: 'atto_image_urlentrysubmit', + INPUTSUBMIT: 'atto_image_urlentrysubmit', INPUTURL: 'atto_image_urlentry', INPUTWIDTH: 'atto_image_widthentry', IMAGEALTWARNING: 'atto_image_altwarning', @@ -30,416 +45,250 @@ var SELECTORS = { IMAGEPRESENTATION: 'atto_image_presentation', IMAGEPREVIEW: 'atto_image_preview' }, - ALIGNMENTS, - ALIGNMENT; + ALIGNMENTS = [ + // Vertical alignment. + { + name: 'baseline', + str: 'alignment_baseline', + value: 'vertical-align' + }, { + name: 'sub', + str: 'alignment_sub', + value: 'vertical-align' + }, { + name: 'super', + str: 'alignment_super', + value: 'vertical-align' + }, { + name: 'top', + str: 'alignment_top', + value: 'vertical-align' + }, { + name: 'text-top', + str: 'alignment_texttop', + value: 'vertical-align' + }, { + name: 'middle', + str: 'alignment_middle', + value: 'vertical-align' + }, { + name: 'bottom', + str: 'alignment_bottom', + value: 'vertical-align' + }, { + name: 'text-bottom', + str: 'alignment_textbottom', + value: 'vertical-align' + }, -/** - * Alignment class to aid with image alignment. - * - * @class ALIGNMENT - * @constructor - * @param {String} value - * @param {String} style - */ -ALIGNMENT = function(value, style) { - this.value = value; - this.style = style; - this.regex = new RegExp(this._regex_escape(style) + ' *: *' + this._regex_escape(value)); -}; -ALIGNMENT.prototype = { - - /** - * The value of this alignment instance. - * @property value - * @type {String} - */ - value: null, - - /** - * The style this alignment instance will use. - * @property style - * @type {String} - */ - style: null, - - /** - * A regex to match this alignment instance in use. - * @property regex - * @type {RegExp} - */ - regex: null, - - /** - * Tests a given style string to check if this instance is used within it. - * @method test - * @param {String} str - * @returns {Boolean} - */ - test: function(str) { - return this.regex.test(str); - }, - - /** - * Escapes a string for use in a RegExp definition. - * @method _regex_escape - * @private - * @param str - * @returns {String} - */ - _regex_escape: function(str) { - return str.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, "\\$1"); - }, - - /** - * Applys this style to a given node. - * @method apply - * @param {Node} node - */ - apply: function(node) { - var style = node.getAttribute('style'); - if (style !== '' && style.substr(style.length - 1, 1) !== ';') { - style += ';'; + // Floats. + { + name: 'left', + str: 'alignment_left', + value: 'float' + }, { + name: 'right', + str: 'alignment_right', + value: 'float' } - style += this.style + ': ' + this.value + ';'; - }, + ]; + +var COMPONENTNAME = 'atto_image', + + TEMPLATE = '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + + // Add the repository browser button. + '{{#if showFilepicker}}' + + '' + + '{{/if}}' + + + // Add the Alt box. + '' + + '' + + '' + + '
                                        ' + + + // Add the presentation select box. + '' + + '' + + '
                                        ' + + + // Add the width entry box. + '' + + '' + + '
                                        ' + + + // Add the height entry box. + '' + + '' + + '
                                        ' + + + // Add the alignment selector. + '' + + '' + + '
                                        ' + + + // Add the image preview. + '' + + '
                                        ' + + '' + + '
                                        ' + + + // Add the submit button and close the form. + '' + + '
                                        ' + + '
                                        ', + + IMAGETEMPLATE = '' + + '{{alt}}'; + +Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + /** + * A reference to the current selection at the time that the dialogue + * was opened. + * + * @property _currentSelection + * @type Range + * @private + */ + _currentSelection: null, /** - * Returns this alignment instance as a select option. - * @method to_select_option - * @returns {string} + * The most recently selected image. + * + * @param _selectedImage + * @type Node + * @private */ - to_select_option: function() { - var str = M.util.get_string('alignment_'+this.value.replace('-', ''), 'atto_image'); - value = this.style + ': '+ this.value; - return ''; - } -}; + _selectedImage: null, -/** - * An array containing all of the valid alignments an image can have. - * @type {ALIGNMENT[]} - */ -ALIGNMENTS = [ - // Vertical alignment. - new ALIGNMENT('baseline', 'vertical-align'), - new ALIGNMENT('sub', 'vertical-align'), - new ALIGNMENT('super', 'vertical-align'), - new ALIGNMENT('top', 'vertical-align'), - new ALIGNMENT('text-top', 'vertical-align'), - new ALIGNMENT('middle', 'vertical-align'), - new ALIGNMENT('bottom', 'vertical-align'), - new ALIGNMENT('text-bottom', 'vertical-align'), - // Floats. - new ALIGNMENT('left', 'float'), - new ALIGNMENT('right', 'float') -]; + /** + * A reference to the currently open form. + * + * @param _form + * @type Node + * @private + */ + _form: null, -/** - * Atto text editor image plugin. - * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -M.atto_image = M.atto_image || { - dialogue: null, - selection: null, - currentlyselected : {}, - lastselectedimage : null, - init: function(params) { - var display_chooser = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_image.selection = M.editor_atto.get_selection(); - if (M.atto_image.selection !== false) { - var dialogue; - if (!M.atto_image.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_image.dialogue; - } - - dialogue.set('bodyContent', M.atto_image.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createimage', 'atto_image')); - dialogue.render(); - dialogue.centerDialogue(); - M.atto_image.dialogue = dialogue; - dialogue.show(); - } - }; - - 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); - M.editor_atto.currentlyselected = M.editor_atto.currentlyselected || {}; - M.editor_atto.currentlyselected[params.elementid] = null; - - // 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. - M.editor_atto.on('atto:selectionchanged', function(e) { - if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes, false)) { - M.editor_atto.add_widget_highlight(e.elementid, 'image'); - M.editor_atto.currentlyselected[e.elementid] = e.selectedNodes; - } else { - M.editor_atto.remove_widget_highlight(e.elementid, 'image'); - M.editor_atto.currentlyselected[e.elementid] = null; - } + initializer: function() { + this.addButton({ + icon: 'e/insert_edit_image', + callback: this._displayDialogue, + tags: 'img', + tagMatchRequiresAll: false }); }, - open_filepicker: function(e) { - var elementid = this.getAttribute('data-editor'); - e.preventDefault(); - M.editor_atto.show_filepicker(elementid, 'image', M.atto_image.filepicker_callback); + /** + * Display the image editing tool. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { + return; + } + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createimage', COMPONENTNAME), + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); }, - filepicker_callback: function(params) { + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @return {Node} The content to place in the dialogue. + * @private + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + elementid: this.get('host').get('elementid'), + CSS: CSS, + component: COMPONENTNAME, + showFilepicker: this.get('host').canShowFilepicker('image'), + alignments: ALIGNMENTS + })); + + this._form = content; + + // Configure the view of the current image. + this._applyImageProperties(this._form); + + this._form.one('.' + CSS.INPUTURL).on('blur', this._urlChanged, this); + this._form.one('.' + CSS.INPUTSUBMIT).on('click', this._setImage, this); + this._form.one('.' + CSS.IMAGEBROWSER).on('click', function() { + this.get('host').showFilepicker('image', this._filepickerCallback, this); + }, this); + + return content; + }, + + /** + * Update the dialogue after an image was selected in the File Picker. + * + * @method _filepickerCallback + * @param {object} params The parameters provided by the filepicker + * containing information about the image. + * @private + */ + _filepickerCallback: function(params) { if (params.url !== '') { - var input = Y.one('#' + CSS.INPUTURL); + var input = this._form.one('.' + CSS.INPUTURL), + self = this; input.set('value', params.url); // Auto set the width and height. var image = new Image(); image.onload = function() { - Y.one('#' + CSS.INPUTWIDTH).set('value', this.width); - Y.one('#' + CSS.INPUTHEIGHT).set('value', this.height); - Y.one('#' + CSS.IMAGEPREVIEW).set('src', this.src); - Y.one('#' + CSS.IMAGEPREVIEW).setStyle('display', 'inline'); + self._form.one('.' + CSS.INPUTWIDTH).set('value', this.width); + self._form.one('.' + CSS.INPUTHEIGHT).set('value', this.height); + self._form.one('.' + CSS.IMAGEPREVIEW).set('src', this.src); + self._form.one('.' + CSS.IMAGEPREVIEW).setStyle('display', 'inline'); + + // Centre the dialogue once the preview image has loaded. + self.getDialogue().centerDialogue(); }; image.src = params.url; } }, - url_changed: function() { - var input = Y.one('#' + CSS.INPUTURL); - if (input.get('value') !== '') { - // Auto set the width and height. - var image = new Image(); - image.onload = function() { - var input; - - input = Y.one('#' + CSS.INPUTWIDTH); - if (input.get('value') === '') { - input.set('value', this.width); - } - input = Y.one('#' + CSS.INPUTHEIGHT); - if (input.get('value') === '') { - input.set('value', this.height); - } - input = Y.one('#' + CSS.IMAGEPREVIEW); - input.set('src', this.src); - input.setStyle('display', 'inline'); - }; - image.src = input.get('value'); - } - }, - set_image: function(e, elementid) { - var form = e.currentTarget.ancestor('.atto_form'), - url = form.one('#' + CSS.INPUTURL).get('value'), - alt = form.one('#' + CSS.INPUTALT).get('value'), - width = form.one('#' + CSS.INPUTWIDTH).get('value'), - height = form.one('#' + CSS.INPUTHEIGHT).get('value'), - alignment = form.one('#' + CSS.INPUTALIGNMENT).get('value'), - presentation = form.one('#' + CSS.IMAGEPRESENTATION).get('checked'), - imagehtml; - - e.preventDefault(); - - if (alt === '' && !presentation) { - form.one('#' + CSS.IMAGEALTWARNING).setStyle('display', 'block'); - form.one('#' + CSS.INPUTALT).setAttribute('aria-invalid', true); - form.one('#' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', true); - return; - } else { - form.one('#' + CSS.IMAGEALTWARNING).setStyle('display', 'none'); - form.one('#' + CSS.INPUTALT).setAttribute('aria-invalid', false); - form.one('#' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', false); - } - - M.atto_image.dialogue.hide(); - - M.editor_atto.focus(elementid); - if (url !== '') { - if (this.lastselectedimage) { - M.editor_atto.set_selection(M.editor_atto.get_selection_from_node(this.lastselectedimage)); - } else { - M.editor_atto.set_selection(M.atto_image.selection); - } - imagehtml = '' + Y.Escape.html(alt) + ' 0) { - properties.width = width; - } - if (height > 0) { - properties.height = height; - } - for (i in ALIGNMENTS) { - if (ALIGNMENTS[i].test(style)) { - properties.align = ALIGNMENTS[i]; - break; - } - } - properties.src = image.getAttribute('src'); - properties.alt = image.getAttribute('alt') || ''; - properties.presentation = (image.get('role') === 'presentation'); - return properties; - } - return false; - }, - get_form_content: function(elementid) { - - // String collection for quick refernce. - var str = { - alignment: M.util.get_string('alignment', 'atto_image'), - alt: M.util.get_string('enteralt', 'atto_image'), - browse: M.util.get_string('browserepositories', 'atto_image'), - create: M.util.get_string('createimage', 'atto_image'), - height: M.util.get_string('height', 'atto_image'), - presentation: M.util.get_string('presentation', 'atto_image'), - presentationrequired: M.util.get_string('presentationoraltrequired', 'atto_image'), - preview: M.util.get_string('preview', 'atto_image'), - width: M.util.get_string('width', 'atto_image'), - url: M.util.get_string('enterurl', 'atto_image') - }, - html, - i; - - - // Start the form. - html = '
                                        ' + - '' + - '' + - '
                                        '; - - if (M.editor_atto.can_show_filepicker(elementid, 'image')) { - // Add the repository browser button. - html += '' + - '
                                        '; - } - - // Add the Alt box. - html += '' + - '' + - '' + - '
                                        '; - - // Add the presentation select box. - html += '' + - '' + - '
                                        '; - - // Add the width entry box. - html += '' + - '' + - '
                                        '; - - // Add the height entry box. - html += '' + - '' + - '
                                        '; - - // Add the alignment selector. - html += '' + - '' + - '
                                        '; - - // Add the image preview. - html += '' + - '' + - '
                                        ' + - '
                                        '; - - // Add the submit button and close the form. - html += '' + - '
                                        ' + - '
                                        '; - - var content = Y.Node.create(html); - this._apply_image_properties(content, elementid); - - content.one('#' + CSS.INPUTURL).on('blur', M.atto_image.url_changed, this); - content.one('#' + CSS.INPUTSUMBIT).on('click', M.atto_image.set_image, this, elementid); - if (M.editor_atto.can_show_filepicker(elementid, 'image')) { - content.one('#' + CSS.IMAGEBROWSER).on('click', M.atto_image.open_filepicker); - } - return content; - }, /** * Applies properties of an existing image to the image dialogue for editing. * - * @method _apply_image_properties - * @private + * @method _applyImageProperties * @param {Node} form - * @param {string} elementid + * @private */ - _apply_image_properties: function(form, elementid) { - var properties = this._get_selected_image_properties(elementid), - img = form.one('#' + CSS.IMAGEPREVIEW); + _applyImageProperties: function(form) { + var properties = this._getSelectedImageProperties(), + img = form.one('.' + CSS.IMAGEPREVIEW); if (properties === false) { img.setStyle('display', 'none'); @@ -453,23 +302,174 @@ M.atto_image = M.atto_image || { img.setStyle('display', properties.display); } if (properties.width) { - form.one('#' + CSS.INPUTWIDTH).set('value', properties.width); + form.one('.' + CSS.INPUTWIDTH).set('value', properties.width); } if (properties.height) { - form.one('#' + CSS.INPUTHEIGHT).set('value', properties.height); + form.one('.' + CSS.INPUTHEIGHT).set('value', properties.height); } if (properties.alt) { - form.one('#' + CSS.INPUTALT).set('value', properties.alt); + form.one('.' + CSS.INPUTALT).set('value', properties.alt); } if (properties.src) { - form.one('#' + CSS.INPUTURL).set('value', properties.src); + form.one('.' + CSS.INPUTURL).set('value', properties.src); img.setAttribute('src', properties.src); } if (properties.presentation) { - form.one('#' + CSS.IMAGEPRESENTATION).set('checked', 'checked'); + form.one('.' + CSS.IMAGEPRESENTATION).set('checked', 'checked'); + } + }, + + /** + * Gets the properties of the currently selected image. + * + * The first image only if multiple images are selected. + * + * @method _getSelectedImageProperties + * @return {object} + * @private + */ + _getSelectedImageProperties: function() { + var properties = { + src: null, + alt :null, + width: null, + height: null, + align: null, + display: 'inline', + presentation: false + }, + + // Get the current selection. + images = this.get('host').getSelectedNodes(), + i, width, height, style; + + if (images) { + images = images.filter('img'); + } + + if (images && images.size()) { + image = images.item(0); + this._selectedImage = image; + + style = image.getAttribute('style'); + width = parseInt(image.getAttribute('width'), 10); + height = parseInt(image.getAttribute('height'), 10); + + if (width > 0) { + properties.width = width; + } + if (height > 0) { + properties.height = height; + } + for (i in ALIGNMENTS) { + if (ALIGNMENTS[i].name === style) { + properties.align = ALIGNMENTS[i]; + break; + } + } + properties.src = image.getAttribute('src'); + properties.alt = image.getAttribute('alt') || ''; + properties.presentation = (image.get('role') === 'presentation'); + return properties; + } + + // No image selected - clean up. + this._selectedImage = null; + return false; + }, + + /** + * Update the form when the URL was changed. This includes updating the + * height, width, and image preview. + * + * @method _urlChanged + * @private + */ + _urlChanged: function() { + var input = this._form.one('.' + CSS.INPUTURL), + self = this; + + if (input.get('value') !== '') { + // Auto set the width and height. + var image = new Image(); + image.onload = function() { + var input; + + input = self._form.one('.' + CSS.INPUTWIDTH); + if (input.get('value') === '') { + input.set('value', this.width); + } + input = self._form.one('.' + CSS.INPUTHEIGHT); + if (input.get('value') === '') { + input.set('value', this.height); + } + input = self._form.one('.' + CSS.IMAGEPREVIEW); + input.set('src', this.src); + input.setStyle('display', 'inline'); + }; + image.src = input.get('value'); + } + }, + + /** + * Update the image in the contenteditable. + * + * @method _setImage + * @param {EventFacade} e + * @private + */ + _setImage: function(e) { + var form = this._form, + url = form.one('.' + CSS.INPUTURL).get('value'), + alt = form.one('.' + CSS.INPUTALT).get('value'), + width = form.one('.' + CSS.INPUTWIDTH).get('value'), + height = form.one('.' + CSS.INPUTHEIGHT).get('value'), + alignment = form.one('.' + CSS.INPUTALIGNMENT).get('value'), + presentation = form.one('.' + CSS.IMAGEPRESENTATION).get('checked'), + imagehtml, + host = this.get('host'); + + e.preventDefault(); + + if (alt === '' && !presentation) { + form.one('.' + CSS.IMAGEALTWARNING).setStyle('display', 'block'); + form.one('.' + CSS.INPUTALT).setAttribute('aria-invalid', true); + form.one('.' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', true); + return; + } else { + form.one('.' + CSS.IMAGEALTWARNING).setStyle('display', 'none'); + form.one('.' + CSS.INPUTALT).setAttribute('aria-invalid', false); + form.one('.' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', false); + } + + this.getDialogue({ + focusAfterHide: null + }).hide(); + + // Focus on the editor in preparation for inserting the image. + host.focus(); + if (url !== '') { + if (this._selectedImage) { + host.setSelection(host.getSelectionFromNode(this._selectedImage)); + } else { + host.setSelection(this._currentSelection); + } + template = Y.Handlebars.compile(IMAGETEMPLATE); + imagehtml = template({ + url: url, + alt: alt, + width: width, + height: height, + presentation: presentation, + alignment: alignment + }); + + this.get('host').insertContentAtFocusPoint(imagehtml); + + this.markUpdated(); } } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 5aec326d218..56856e1bb04 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){var n={TAGS:"img"},r={INPUTALIGNMENT:"atto_image_alignment",INPUTALT:"atto_image_altentry",INPUTHEIGHT:"atto_image_heightentry",INPUTSUMBIT:"atto_image_urlentrysubmit",INPUTURL:"atto_image_urlentry",INPUTWIDTH:"atto_image_widthentry",IMAGEALTWARNING:"atto_image_altwarning",IMAGEBROWSER:"openimagebrowser",IMAGEPRESENTATION:"atto_image_presentation",IMAGEPREVIEW:"atto_image_preview"},i,s;s=function(e,t){this.value=e,this.style=t,this.regex=new RegExp(this._regex_escape(t)+" *: *"+this._regex_escape(e))},s.prototype={value:null,style:null,regex:null,test:function(e){return this.regex.test(e)},_regex_escape:function(e){return e.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g,"\\$1")},apply:function(e){var t=e.getAttribute("style");t!==""&&t.substr(t.length-1,1)!==";"&&(t+=";"),t+=this.style+": "+this.value+";"},to_select_option:function(){var e=M.util.get_string("alignment_"+this.value.replace("-",""),"atto_image");return value=this.style+": "+this.value,'"}},i=[new s("baseline","vertical-align"),new s("sub","vertical-align"),new s("super","vertical-align"),new s("top","vertical-align"),new s("text-top","vertical-align"),new s("middle","vertical-align"),new s("bottom","vertical-align"),new s("text-bottom","vertical-align"),new s("left","float"),new s("right","float")],M.atto_image=M.atto_image||{dialogue:null,selection:null,currentlyselected:{},lastselectedimage:null,init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_image.selection=M.editor_atto.get_selection();if(M.atto_image.selection!==!1){var n;M.atto_image.dialogue?n=M.atto_image.dialogue:n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.set("bodyContent",M.atto_image.get_form_content(t)),n.set("headerContent",M.util.get_string("createimage","atto_image")),n.render(),n.centerDialogue(),M.atto_image.dialogue=n,n.show()}},r=M.util.image_url("e/insert_edit_image","core");M.editor_atto.add_toolbar_button(e.elementid,"image",r,e.group,t),M.editor_atto.currentlyselected=M.editor_atto.currentlyselected||{},M.editor_atto.currentlyselected[e.elementid]=null,M.editor_atto.on("atto:selectionchanged",function(e){M.editor_atto.selection_filter_matches(e.elementid,n.TAGS,e.selectedNodes,!1)?(M.editor_atto.add_widget_highlight(e.elementid,"image"),M.editor_atto.currentlyselected[e.elementid]=e.selectedNodes):(M.editor_atto.remove_widget_highlight(e.elementid,"image"),M.editor_atto.currentlyselected[e.elementid]=null)})},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("#"+r.INPUTURL);n.set("value",t.url);var i=new Image;i.onload=function(){e.one("#"+r.INPUTWIDTH).set("value",this.width),e.one("#"+r.INPUTHEIGHT).set("value",this.height),e.one("#"+r.IMAGEPREVIEW).set("src",this.src),e.one("#"+r.IMAGEPREVIEW).setStyle("display","inline")},i.src=t.url}},url_changed:function(){var t=e.one("#"+r.INPUTURL);if(t.get("value")!==""){var n=new Image;n.onload=function(){var t;t=e.one("#"+r.INPUTWIDTH),t.get("value")===""&&t.set("value",this.width),t=e.one("#"+r.INPUTHEIGHT),t.get("value")===""&&t.set("value",this.height),t=e.one("#"+r.IMAGEPREVIEW),t.set("src",this.src),t.setStyle("display","inline")},n.src=t.get("value")}},set_image:function(t,n){var i=t.currentTarget.ancestor(".atto_form"),s=i.one("#"+r.INPUTURL).get("value"),o=i.one("#"+r.INPUTALT).get("value"),u=i.one("#"+r.INPUTWIDTH).get("value"),a=i.one("#"+r.INPUTHEIGHT).get("value"),f=i.one("#"+r.INPUTALIGNMENT).get("value"),l=i.one("#"+r.IMAGEPRESENTATION).get("checked"),c;t.preventDefault();if(o===""&&!l){i.one("#"+r.IMAGEALTWARNING).setStyle("display","block"),i.one("#"+r.INPUTALT).setAttribute("aria-invalid",!0),i.one("#"+r.IMAGEPRESENTATION).setAttribute("aria-invalid",!0);return}i.one("#"+r.IMAGEALTWARNING).setStyle("display","none"),i.one("#"+r.INPUTALT).setAttribute("aria-invalid",!1),i.one("#"+r.IMAGEPRESENTATION).setAttribute("aria-invalid",!1),M.atto_image.dialogue.hide(),M.editor_atto.focus(n),s!==""&&(this.lastselectedimage?M.editor_atto.set_selection(M.editor_atto.get_selection_from_node(this.lastselectedimage)):M.editor_atto.set_selection(M.atto_image.selection),c=''+e.Escape.html(o)+'0&&(t.width=o),u>0&&(t.height=u);for(r in i)if(i[r].test(a)){t.align=i[r];break}return t.src=s.getAttribute("src"),t.alt=s.getAttribute("alt")||"",t.presentation=s.get("role")==="presentation",t}return!1},get_form_content:function(t){var n={alignment:M.util.get_string("alignment","atto_image"),alt:M.util.get_string("enteralt","atto_image"),browse:M.util.get_string("browserepositories","atto_image"),create:M.util.get_string("createimage","atto_image"),height:M.util.get_string("height","atto_image"),presentation:M.util.get_string("presentation","atto_image"),presentationrequired:M.util.get_string("presentationoraltrequired","atto_image"),preview:M.util.get_string("preview","atto_image"),width:M.util.get_string("width","atto_image"),url:M.util.get_string("enterurl","atto_image")},s,o;s='
                                        "+''+"
                                        ",M.editor_atto.can_show_filepicker -(t,"image")&&(s+='"+"
                                        "),s+='"+'"+''+"
                                        ",s+=''+'"+"
                                        ",s+='"+''+"
                                        ",s+='"+''+"
                                        ",s+='"+'
                                        ",s+='"+''+'
                                        '+"
                                        ",s+='"+"
                                        "+"
                                        ";var u=e.Node.create(s);return this._apply_image_properties(u,t),u.one("#"+r.INPUTURL).on("blur",M.atto_image.url_changed,this),u.one("#"+r.INPUTSUMBIT).on("click",M.atto_image.set_image,this,t),M.editor_atto.can_show_filepicker(t,"image")&&u.one("#"+r.IMAGEBROWSER).on("click",M.atto_image.open_filepicker),u},_apply_image_properties:function(e,t){var n=this._get_selected_image_properties(t),i=e.one("#"+r.IMAGEPREVIEW);if(n===!1){i.setStyle("display","none");return}n.align&&n.align.apply(i),n.display&&i.setStyle("display",n.display),n.width&&e.one("#"+r.INPUTWIDTH).set("value",n.width),n.height&&e.one("#"+r.INPUTHEIGHT).set("value",n.height),n.alt&&e.one("#"+r.INPUTALT).set("value",n.alt),n.src&&(e.one("#"+r.INPUTURL).set("value",n.src),i.setAttribute("src",n.src)),n.presentation&&e.one("#"+r.IMAGEPRESENTATION).set("checked","checked")}}},"@VERSION@",{requires:["node","escape"]}); +YUI.add("moodle-atto_image-button",function(e,t){var n={INPUTALIGNMENT:"atto_image_alignment",INPUTALT:"atto_image_altentry",INPUTHEIGHT:"atto_image_heightentry",INPUTSUBMIT:"atto_image_urlentrysubmit",INPUTURL:"atto_image_urlentry",INPUTWIDTH:"atto_image_widthentry",IMAGEALTWARNING:"atto_image_altwarning",IMAGEBROWSER:"openimagebrowser",IMAGEPRESENTATION:"atto_image_presentation",IMAGEPREVIEW:"atto_image_preview"},r=[{name:"baseline",str:"alignment_baseline",value:"vertical-align"},{name:"sub",str:"alignment_sub",value:"vertical-align"},{name:"super",str:"alignment_super",value:"vertical-align"},{name:"top",str:"alignment_top",value:"vertical-align"},{name:"text-top",str:"alignment_texttop",value:"vertical-align"},{name:"middle",str:"alignment_middle",value:"vertical-align"},{name:"bottom",str:"alignment_bottom",value:"vertical-align"},{name:"text-bottom",str:"alignment_textbottom",value:"vertical-align"},{name:"left",str:"alignment_left",value:"float"},{name:"right",str:"alignment_right",value:"float"}],i="atto_image",s='

                                        {{#if showFilepicker}}{{/if}}





                                        ',o='{{alt}}';e.namespace("M.atto_image").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,_selectedImage:null,_form:null,initializer:function(){this.addButton({icon:"e/insert_edit_image",callback:this._displayDialogue,tags:"img",tagMatchRequiresAll:!1})},_displayDialogue:function(){this._currentSelection=this.get("host").getSelection();if(this._currentSelection===!1)return;var e=this.getDialogue({headerContent:M.util.get_string("createimage",i),focusAfterHide:!0});e.set("bodyContent",this._getDialogueContent()).show()},_getDialogueContent:function(){var t=e.Handlebars.compile(s),o=e.Node.create(t({elementid:this.get("host").get("elementid"),CSS:n,component:i,showFilepicker:this.get("host").canShowFilepicker("image"),alignments:r}));return this._form=o,this._applyImageProperties(this._form),this._form.one("."+n.INPUTURL).on("blur",this._urlChanged,this),this._form.one("."+n.INPUTSUBMIT).on("click",this._setImage,this),this._form.one("."+n.IMAGEBROWSER).on("click",function(){this.get("host").showFilepicker("image",this._filepickerCallback,this)},this),o},_filepickerCallback:function(e){if(e.url!==""){var t=this._form.one("."+n.INPUTURL),r=this;t.set("value",e.url);var i=new Image;i.onload=function(){r._form.one("."+n.INPUTWIDTH).set("value",this.width),r._form.one("."+n.INPUTHEIGHT).set("value",this.height),r._form.one("."+n.IMAGEPREVIEW).set("src",this.src),r._form.one("."+n.IMAGEPREVIEW).setStyle("display","inline"),r.getDialogue().centerDialogue()},i.src=e.url}},_applyImageProperties:function(e){var t=this._getSelectedImageProperties(),r=e.one("."+n.IMAGEPREVIEW);if(t===!1){r.setStyle("display","none");return}t.align&&t.align.apply(r),t.display&&r.setStyle("display",t.display),t.width&&e.one("."+n.INPUTWIDTH).set("value",t.width),t.height&&e.one("."+n.INPUTHEIGHT).set("value",t.height),t.alt&&e.one("."+n.INPUTALT).set("value",t.alt),t.src&&(e.one("."+n.INPUTURL).set("value",t.src),r.setAttribute("src",t.src)),t.presentation&&e.one("."+n.IMAGEPRESENTATION).set("checked","checked")},_getSelectedImageProperties:function(){var e={src:null,alt:null,width:null,height:null,align:null,display:"inline",presentation:!1},t=this.get("host").getSelectedNodes(),n,i,s,o;t&&(t=t.filter("img"));if(t&&t.size()){image=t.item(0),this._selectedImage=image,o=image.getAttribute("style"),i=parseInt(image.getAttribute("width"),10),s=parseInt(image.getAttribute("height"),10),i>0&&(e.width=i),s>0&&(e.height=s);for(n in r)if(r[n].name===o){e.align=r[n];break}return e.src=image.getAttribute("src"),e.alt=image.getAttribute("alt")||"",e.presentation=image.get("role")==="presentation",e}return this._selectedImage=null,!1},_urlChanged:function(){var e=this._form.one("."+n.INPUTURL),t=this;if(e.get("value")!==""){var r=new Image;r +.onload=function(){var e;e=t._form.one("."+n.INPUTWIDTH),e.get("value")===""&&e.set("value",this.width),e=t._form.one("."+n.INPUTHEIGHT),e.get("value")===""&&e.set("value",this.height),e=t._form.one("."+n.IMAGEPREVIEW),e.set("src",this.src),e.setStyle("display","inline")},r.src=e.get("value")}},_setImage:function(t){var r=this._form,i=r.one("."+n.INPUTURL).get("value"),s=r.one("."+n.INPUTALT).get("value"),u=r.one("."+n.INPUTWIDTH).get("value"),a=r.one("."+n.INPUTHEIGHT).get("value"),f=r.one("."+n.INPUTALIGNMENT).get("value"),l=r.one("."+n.IMAGEPRESENTATION).get("checked"),c,h=this.get("host");t.preventDefault();if(s===""&&!l){r.one("."+n.IMAGEALTWARNING).setStyle("display","block"),r.one("."+n.INPUTALT).setAttribute("aria-invalid",!0),r.one("."+n.IMAGEPRESENTATION).setAttribute("aria-invalid",!0);return}r.one("."+n.IMAGEALTWARNING).setStyle("display","none"),r.one("."+n.INPUTALT).setAttribute("aria-invalid",!1),r.one("."+n.IMAGEPRESENTATION).setAttribute("aria-invalid",!1),this.getDialogue({focusAfterHide:null}).hide(),h.focus(),i!==""&&(this._selectedImage?h.setSelection(h.getSelectionFromNode(this._selectedImage)):h.setSelection(this._currentSelection),template=e.Handlebars.compile(o),c=template({url:i,alt:s,width:u,height:a,presentation:l,alignment:f}),this.get("host").insertContentAtFocusPoint(c),this.markUpdated())}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 0dd4d4aee30..1b319caf399 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,14 +15,29 @@ 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 . -var SELECTORS = { - TAGS: 'img' - }, - CSS = { +/* + * @package atto_image + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @module moodle-atto_image_alignment-button + */ + +/** + * Atto image selection tool. + * + * @namespace M.atto_image + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var CSS = { INPUTALIGNMENT: 'atto_image_alignment', INPUTALT: 'atto_image_altentry', INPUTHEIGHT: 'atto_image_heightentry', - INPUTSUMBIT: 'atto_image_urlentrysubmit', + INPUTSUBMIT: 'atto_image_urlentrysubmit', INPUTURL: 'atto_image_urlentry', INPUTWIDTH: 'atto_image_widthentry', IMAGEALTWARNING: 'atto_image_altwarning', @@ -30,416 +45,250 @@ var SELECTORS = { IMAGEPRESENTATION: 'atto_image_presentation', IMAGEPREVIEW: 'atto_image_preview' }, - ALIGNMENTS, - ALIGNMENT; + ALIGNMENTS = [ + // Vertical alignment. + { + name: 'baseline', + str: 'alignment_baseline', + value: 'vertical-align' + }, { + name: 'sub', + str: 'alignment_sub', + value: 'vertical-align' + }, { + name: 'super', + str: 'alignment_super', + value: 'vertical-align' + }, { + name: 'top', + str: 'alignment_top', + value: 'vertical-align' + }, { + name: 'text-top', + str: 'alignment_texttop', + value: 'vertical-align' + }, { + name: 'middle', + str: 'alignment_middle', + value: 'vertical-align' + }, { + name: 'bottom', + str: 'alignment_bottom', + value: 'vertical-align' + }, { + name: 'text-bottom', + str: 'alignment_textbottom', + value: 'vertical-align' + }, -/** - * Alignment class to aid with image alignment. - * - * @class ALIGNMENT - * @constructor - * @param {String} value - * @param {String} style - */ -ALIGNMENT = function(value, style) { - this.value = value; - this.style = style; - this.regex = new RegExp(this._regex_escape(style) + ' *: *' + this._regex_escape(value)); -}; -ALIGNMENT.prototype = { - - /** - * The value of this alignment instance. - * @property value - * @type {String} - */ - value: null, - - /** - * The style this alignment instance will use. - * @property style - * @type {String} - */ - style: null, - - /** - * A regex to match this alignment instance in use. - * @property regex - * @type {RegExp} - */ - regex: null, - - /** - * Tests a given style string to check if this instance is used within it. - * @method test - * @param {String} str - * @returns {Boolean} - */ - test: function(str) { - return this.regex.test(str); - }, - - /** - * Escapes a string for use in a RegExp definition. - * @method _regex_escape - * @private - * @param str - * @returns {String} - */ - _regex_escape: function(str) { - return str.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, "\\$1"); - }, - - /** - * Applys this style to a given node. - * @method apply - * @param {Node} node - */ - apply: function(node) { - var style = node.getAttribute('style'); - if (style !== '' && style.substr(style.length - 1, 1) !== ';') { - style += ';'; + // Floats. + { + name: 'left', + str: 'alignment_left', + value: 'float' + }, { + name: 'right', + str: 'alignment_right', + value: 'float' } - style += this.style + ': ' + this.value + ';'; - }, + ]; + +var COMPONENTNAME = 'atto_image', + + TEMPLATE = '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + + // Add the repository browser button. + '{{#if showFilepicker}}' + + '' + + '{{/if}}' + + + // Add the Alt box. + '' + + '' + + '' + + '
                                        ' + + + // Add the presentation select box. + '' + + '' + + '
                                        ' + + + // Add the width entry box. + '' + + '' + + '
                                        ' + + + // Add the height entry box. + '' + + '' + + '
                                        ' + + + // Add the alignment selector. + '' + + '' + + '
                                        ' + + + // Add the image preview. + '' + + '
                                        ' + + '' + + '
                                        ' + + + // Add the submit button and close the form. + '' + + '
                                        ' + + '
                                        ', + + IMAGETEMPLATE = '' + + '{{alt}}'; + +Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + /** + * A reference to the current selection at the time that the dialogue + * was opened. + * + * @property _currentSelection + * @type Range + * @private + */ + _currentSelection: null, /** - * Returns this alignment instance as a select option. - * @method to_select_option - * @returns {string} + * The most recently selected image. + * + * @param _selectedImage + * @type Node + * @private */ - to_select_option: function() { - var str = M.util.get_string('alignment_'+this.value.replace('-', ''), 'atto_image'); - value = this.style + ': '+ this.value; - return ''; - } -}; + _selectedImage: null, -/** - * An array containing all of the valid alignments an image can have. - * @type {ALIGNMENT[]} - */ -ALIGNMENTS = [ - // Vertical alignment. - new ALIGNMENT('baseline', 'vertical-align'), - new ALIGNMENT('sub', 'vertical-align'), - new ALIGNMENT('super', 'vertical-align'), - new ALIGNMENT('top', 'vertical-align'), - new ALIGNMENT('text-top', 'vertical-align'), - new ALIGNMENT('middle', 'vertical-align'), - new ALIGNMENT('bottom', 'vertical-align'), - new ALIGNMENT('text-bottom', 'vertical-align'), - // Floats. - new ALIGNMENT('left', 'float'), - new ALIGNMENT('right', 'float') -]; + /** + * A reference to the currently open form. + * + * @param _form + * @type Node + * @private + */ + _form: null, -/** - * Atto text editor image plugin. - * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -M.atto_image = M.atto_image || { - dialogue: null, - selection: null, - currentlyselected : {}, - lastselectedimage : null, - init: function(params) { - var display_chooser = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_image.selection = M.editor_atto.get_selection(); - if (M.atto_image.selection !== false) { - var dialogue; - if (!M.atto_image.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_image.dialogue; - } - - dialogue.set('bodyContent', M.atto_image.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createimage', 'atto_image')); - dialogue.render(); - dialogue.centerDialogue(); - M.atto_image.dialogue = dialogue; - dialogue.show(); - } - }; - - 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); - M.editor_atto.currentlyselected = M.editor_atto.currentlyselected || {}; - M.editor_atto.currentlyselected[params.elementid] = null; - - // 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. - M.editor_atto.on('atto:selectionchanged', function(e) { - if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes, false)) { - M.editor_atto.add_widget_highlight(e.elementid, 'image'); - M.editor_atto.currentlyselected[e.elementid] = e.selectedNodes; - } else { - M.editor_atto.remove_widget_highlight(e.elementid, 'image'); - M.editor_atto.currentlyselected[e.elementid] = null; - } + initializer: function() { + this.addButton({ + icon: 'e/insert_edit_image', + callback: this._displayDialogue, + tags: 'img', + tagMatchRequiresAll: false }); }, - open_filepicker: function(e) { - var elementid = this.getAttribute('data-editor'); - e.preventDefault(); - M.editor_atto.show_filepicker(elementid, 'image', M.atto_image.filepicker_callback); + /** + * Display the image editing tool. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { + return; + } + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createimage', COMPONENTNAME), + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); }, - filepicker_callback: function(params) { + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @return {Node} The content to place in the dialogue. + * @private + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + elementid: this.get('host').get('elementid'), + CSS: CSS, + component: COMPONENTNAME, + showFilepicker: this.get('host').canShowFilepicker('image'), + alignments: ALIGNMENTS + })); + + this._form = content; + + // Configure the view of the current image. + this._applyImageProperties(this._form); + + this._form.one('.' + CSS.INPUTURL).on('blur', this._urlChanged, this); + this._form.one('.' + CSS.INPUTSUBMIT).on('click', this._setImage, this); + this._form.one('.' + CSS.IMAGEBROWSER).on('click', function() { + this.get('host').showFilepicker('image', this._filepickerCallback, this); + }, this); + + return content; + }, + + /** + * Update the dialogue after an image was selected in the File Picker. + * + * @method _filepickerCallback + * @param {object} params The parameters provided by the filepicker + * containing information about the image. + * @private + */ + _filepickerCallback: function(params) { if (params.url !== '') { - var input = Y.one('#' + CSS.INPUTURL); + var input = this._form.one('.' + CSS.INPUTURL), + self = this; input.set('value', params.url); // Auto set the width and height. var image = new Image(); image.onload = function() { - Y.one('#' + CSS.INPUTWIDTH).set('value', this.width); - Y.one('#' + CSS.INPUTHEIGHT).set('value', this.height); - Y.one('#' + CSS.IMAGEPREVIEW).set('src', this.src); - Y.one('#' + CSS.IMAGEPREVIEW).setStyle('display', 'inline'); + self._form.one('.' + CSS.INPUTWIDTH).set('value', this.width); + self._form.one('.' + CSS.INPUTHEIGHT).set('value', this.height); + self._form.one('.' + CSS.IMAGEPREVIEW).set('src', this.src); + self._form.one('.' + CSS.IMAGEPREVIEW).setStyle('display', 'inline'); + + // Centre the dialogue once the preview image has loaded. + self.getDialogue().centerDialogue(); }; image.src = params.url; } }, - url_changed: function() { - var input = Y.one('#' + CSS.INPUTURL); - if (input.get('value') !== '') { - // Auto set the width and height. - var image = new Image(); - image.onload = function() { - var input; - - input = Y.one('#' + CSS.INPUTWIDTH); - if (input.get('value') === '') { - input.set('value', this.width); - } - input = Y.one('#' + CSS.INPUTHEIGHT); - if (input.get('value') === '') { - input.set('value', this.height); - } - input = Y.one('#' + CSS.IMAGEPREVIEW); - input.set('src', this.src); - input.setStyle('display', 'inline'); - }; - image.src = input.get('value'); - } - }, - set_image: function(e, elementid) { - var form = e.currentTarget.ancestor('.atto_form'), - url = form.one('#' + CSS.INPUTURL).get('value'), - alt = form.one('#' + CSS.INPUTALT).get('value'), - width = form.one('#' + CSS.INPUTWIDTH).get('value'), - height = form.one('#' + CSS.INPUTHEIGHT).get('value'), - alignment = form.one('#' + CSS.INPUTALIGNMENT).get('value'), - presentation = form.one('#' + CSS.IMAGEPRESENTATION).get('checked'), - imagehtml; - - e.preventDefault(); - - if (alt === '' && !presentation) { - form.one('#' + CSS.IMAGEALTWARNING).setStyle('display', 'block'); - form.one('#' + CSS.INPUTALT).setAttribute('aria-invalid', true); - form.one('#' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', true); - return; - } else { - form.one('#' + CSS.IMAGEALTWARNING).setStyle('display', 'none'); - form.one('#' + CSS.INPUTALT).setAttribute('aria-invalid', false); - form.one('#' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', false); - } - - M.atto_image.dialogue.hide(); - - M.editor_atto.focus(elementid); - if (url !== '') { - if (this.lastselectedimage) { - M.editor_atto.set_selection(M.editor_atto.get_selection_from_node(this.lastselectedimage)); - } else { - M.editor_atto.set_selection(M.atto_image.selection); - } - imagehtml = '' + Y.Escape.html(alt) + ' 0) { - properties.width = width; - } - if (height > 0) { - properties.height = height; - } - for (i in ALIGNMENTS) { - if (ALIGNMENTS[i].test(style)) { - properties.align = ALIGNMENTS[i]; - break; - } - } - properties.src = image.getAttribute('src'); - properties.alt = image.getAttribute('alt') || ''; - properties.presentation = (image.get('role') === 'presentation'); - return properties; - } - return false; - }, - get_form_content: function(elementid) { - - // String collection for quick refernce. - var str = { - alignment: M.util.get_string('alignment', 'atto_image'), - alt: M.util.get_string('enteralt', 'atto_image'), - browse: M.util.get_string('browserepositories', 'atto_image'), - create: M.util.get_string('createimage', 'atto_image'), - height: M.util.get_string('height', 'atto_image'), - presentation: M.util.get_string('presentation', 'atto_image'), - presentationrequired: M.util.get_string('presentationoraltrequired', 'atto_image'), - preview: M.util.get_string('preview', 'atto_image'), - width: M.util.get_string('width', 'atto_image'), - url: M.util.get_string('enterurl', 'atto_image') - }, - html, - i; - - - // Start the form. - html = '
                                        ' + - '' + - '' + - '
                                        '; - - if (M.editor_atto.can_show_filepicker(elementid, 'image')) { - // Add the repository browser button. - html += '' + - '
                                        '; - } - - // Add the Alt box. - html += '' + - '' + - '' + - '
                                        '; - - // Add the presentation select box. - html += '' + - '' + - '
                                        '; - - // Add the width entry box. - html += '' + - '' + - '
                                        '; - - // Add the height entry box. - html += '' + - '' + - '
                                        '; - - // Add the alignment selector. - html += '' + - '' + - '
                                        '; - - // Add the image preview. - html += '' + - '' + - '
                                        ' + - '
                                        '; - - // Add the submit button and close the form. - html += '' + - '
                                        ' + - '
                                        '; - - var content = Y.Node.create(html); - this._apply_image_properties(content, elementid); - - content.one('#' + CSS.INPUTURL).on('blur', M.atto_image.url_changed, this); - content.one('#' + CSS.INPUTSUMBIT).on('click', M.atto_image.set_image, this, elementid); - if (M.editor_atto.can_show_filepicker(elementid, 'image')) { - content.one('#' + CSS.IMAGEBROWSER).on('click', M.atto_image.open_filepicker); - } - return content; - }, /** * Applies properties of an existing image to the image dialogue for editing. * - * @method _apply_image_properties - * @private + * @method _applyImageProperties * @param {Node} form - * @param {string} elementid + * @private */ - _apply_image_properties: function(form, elementid) { - var properties = this._get_selected_image_properties(elementid), - img = form.one('#' + CSS.IMAGEPREVIEW); + _applyImageProperties: function(form) { + var properties = this._getSelectedImageProperties(), + img = form.one('.' + CSS.IMAGEPREVIEW); if (properties === false) { img.setStyle('display', 'none'); @@ -453,23 +302,174 @@ M.atto_image = M.atto_image || { img.setStyle('display', properties.display); } if (properties.width) { - form.one('#' + CSS.INPUTWIDTH).set('value', properties.width); + form.one('.' + CSS.INPUTWIDTH).set('value', properties.width); } if (properties.height) { - form.one('#' + CSS.INPUTHEIGHT).set('value', properties.height); + form.one('.' + CSS.INPUTHEIGHT).set('value', properties.height); } if (properties.alt) { - form.one('#' + CSS.INPUTALT).set('value', properties.alt); + form.one('.' + CSS.INPUTALT).set('value', properties.alt); } if (properties.src) { - form.one('#' + CSS.INPUTURL).set('value', properties.src); + form.one('.' + CSS.INPUTURL).set('value', properties.src); img.setAttribute('src', properties.src); } if (properties.presentation) { - form.one('#' + CSS.IMAGEPRESENTATION).set('checked', 'checked'); + form.one('.' + CSS.IMAGEPRESENTATION).set('checked', 'checked'); + } + }, + + /** + * Gets the properties of the currently selected image. + * + * The first image only if multiple images are selected. + * + * @method _getSelectedImageProperties + * @return {object} + * @private + */ + _getSelectedImageProperties: function() { + var properties = { + src: null, + alt :null, + width: null, + height: null, + align: null, + display: 'inline', + presentation: false + }, + + // Get the current selection. + images = this.get('host').getSelectedNodes(), + i, width, height, style; + + if (images) { + images = images.filter('img'); + } + + if (images && images.size()) { + image = images.item(0); + this._selectedImage = image; + + style = image.getAttribute('style'); + width = parseInt(image.getAttribute('width'), 10); + height = parseInt(image.getAttribute('height'), 10); + + if (width > 0) { + properties.width = width; + } + if (height > 0) { + properties.height = height; + } + for (i in ALIGNMENTS) { + if (ALIGNMENTS[i].name === style) { + properties.align = ALIGNMENTS[i]; + break; + } + } + properties.src = image.getAttribute('src'); + properties.alt = image.getAttribute('alt') || ''; + properties.presentation = (image.get('role') === 'presentation'); + return properties; + } + + // No image selected - clean up. + this._selectedImage = null; + return false; + }, + + /** + * Update the form when the URL was changed. This includes updating the + * height, width, and image preview. + * + * @method _urlChanged + * @private + */ + _urlChanged: function() { + var input = this._form.one('.' + CSS.INPUTURL), + self = this; + + if (input.get('value') !== '') { + // Auto set the width and height. + var image = new Image(); + image.onload = function() { + var input; + + input = self._form.one('.' + CSS.INPUTWIDTH); + if (input.get('value') === '') { + input.set('value', this.width); + } + input = self._form.one('.' + CSS.INPUTHEIGHT); + if (input.get('value') === '') { + input.set('value', this.height); + } + input = self._form.one('.' + CSS.IMAGEPREVIEW); + input.set('src', this.src); + input.setStyle('display', 'inline'); + }; + image.src = input.get('value'); + } + }, + + /** + * Update the image in the contenteditable. + * + * @method _setImage + * @param {EventFacade} e + * @private + */ + _setImage: function(e) { + var form = this._form, + url = form.one('.' + CSS.INPUTURL).get('value'), + alt = form.one('.' + CSS.INPUTALT).get('value'), + width = form.one('.' + CSS.INPUTWIDTH).get('value'), + height = form.one('.' + CSS.INPUTHEIGHT).get('value'), + alignment = form.one('.' + CSS.INPUTALIGNMENT).get('value'), + presentation = form.one('.' + CSS.IMAGEPRESENTATION).get('checked'), + imagehtml, + host = this.get('host'); + + e.preventDefault(); + + if (alt === '' && !presentation) { + form.one('.' + CSS.IMAGEALTWARNING).setStyle('display', 'block'); + form.one('.' + CSS.INPUTALT).setAttribute('aria-invalid', true); + form.one('.' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', true); + return; + } else { + form.one('.' + CSS.IMAGEALTWARNING).setStyle('display', 'none'); + form.one('.' + CSS.INPUTALT).setAttribute('aria-invalid', false); + form.one('.' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', false); + } + + this.getDialogue({ + focusAfterHide: null + }).hide(); + + // Focus on the editor in preparation for inserting the image. + host.focus(); + if (url !== '') { + if (this._selectedImage) { + host.setSelection(host.getSelectionFromNode(this._selectedImage)); + } else { + host.setSelection(this._currentSelection); + } + template = Y.Handlebars.compile(IMAGETEMPLATE); + imagehtml = template({ + url: url, + alt: alt, + width: width, + height: height, + presentation: presentation, + alignment: alignment + }); + + this.get('host').insertContentAtFocusPoint(imagehtml); + + this.markUpdated(); } } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 f0b0e9fb8cd..f2bd4ad03c1 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,14 +13,29 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -var SELECTORS = { - TAGS: 'img' - }, - CSS = { +/* + * @package atto_image + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @module moodle-atto_image_alignment-button + */ + +/** + * Atto image selection tool. + * + * @namespace M.atto_image + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var CSS = { INPUTALIGNMENT: 'atto_image_alignment', INPUTALT: 'atto_image_altentry', INPUTHEIGHT: 'atto_image_heightentry', - INPUTSUMBIT: 'atto_image_urlentrysubmit', + INPUTSUBMIT: 'atto_image_urlentrysubmit', INPUTURL: 'atto_image_urlentry', INPUTWIDTH: 'atto_image_widthentry', IMAGEALTWARNING: 'atto_image_altwarning', @@ -28,416 +43,250 @@ var SELECTORS = { IMAGEPRESENTATION: 'atto_image_presentation', IMAGEPREVIEW: 'atto_image_preview' }, - ALIGNMENTS, - ALIGNMENT; + ALIGNMENTS = [ + // Vertical alignment. + { + name: 'baseline', + str: 'alignment_baseline', + value: 'vertical-align' + }, { + name: 'sub', + str: 'alignment_sub', + value: 'vertical-align' + }, { + name: 'super', + str: 'alignment_super', + value: 'vertical-align' + }, { + name: 'top', + str: 'alignment_top', + value: 'vertical-align' + }, { + name: 'text-top', + str: 'alignment_texttop', + value: 'vertical-align' + }, { + name: 'middle', + str: 'alignment_middle', + value: 'vertical-align' + }, { + name: 'bottom', + str: 'alignment_bottom', + value: 'vertical-align' + }, { + name: 'text-bottom', + str: 'alignment_textbottom', + value: 'vertical-align' + }, -/** - * Alignment class to aid with image alignment. - * - * @class ALIGNMENT - * @constructor - * @param {String} value - * @param {String} style - */ -ALIGNMENT = function(value, style) { - this.value = value; - this.style = style; - this.regex = new RegExp(this._regex_escape(style) + ' *: *' + this._regex_escape(value)); -}; -ALIGNMENT.prototype = { - - /** - * The value of this alignment instance. - * @property value - * @type {String} - */ - value: null, - - /** - * The style this alignment instance will use. - * @property style - * @type {String} - */ - style: null, - - /** - * A regex to match this alignment instance in use. - * @property regex - * @type {RegExp} - */ - regex: null, - - /** - * Tests a given style string to check if this instance is used within it. - * @method test - * @param {String} str - * @returns {Boolean} - */ - test: function(str) { - return this.regex.test(str); - }, - - /** - * Escapes a string for use in a RegExp definition. - * @method _regex_escape - * @private - * @param str - * @returns {String} - */ - _regex_escape: function(str) { - return str.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, "\\$1"); - }, - - /** - * Applys this style to a given node. - * @method apply - * @param {Node} node - */ - apply: function(node) { - var style = node.getAttribute('style'); - if (style !== '' && style.substr(style.length - 1, 1) !== ';') { - style += ';'; + // Floats. + { + name: 'left', + str: 'alignment_left', + value: 'float' + }, { + name: 'right', + str: 'alignment_right', + value: 'float' } - style += this.style + ': ' + this.value + ';'; - }, + ]; + +var COMPONENTNAME = 'atto_image', + + TEMPLATE = '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + + // Add the repository browser button. + '{{#if showFilepicker}}' + + '' + + '{{/if}}' + + + // Add the Alt box. + '' + + '' + + '' + + '
                                        ' + + + // Add the presentation select box. + '' + + '' + + '
                                        ' + + + // Add the width entry box. + '' + + '' + + '
                                        ' + + + // Add the height entry box. + '' + + '' + + '
                                        ' + + + // Add the alignment selector. + '' + + '' + + '
                                        ' + + + // Add the image preview. + '' + + '
                                        ' + + '' + + '
                                        ' + + + // Add the submit button and close the form. + '' + + '
                                        ' + + '
                                        ', + + IMAGETEMPLATE = '' + + '{{alt}}'; + +Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + /** + * A reference to the current selection at the time that the dialogue + * was opened. + * + * @property _currentSelection + * @type Range + * @private + */ + _currentSelection: null, /** - * Returns this alignment instance as a select option. - * @method to_select_option - * @returns {string} + * The most recently selected image. + * + * @param _selectedImage + * @type Node + * @private */ - to_select_option: function() { - var str = M.util.get_string('alignment_'+this.value.replace('-', ''), 'atto_image'); - value = this.style + ': '+ this.value; - return ''; - } -}; + _selectedImage: null, -/** - * An array containing all of the valid alignments an image can have. - * @type {ALIGNMENT[]} - */ -ALIGNMENTS = [ - // Vertical alignment. - new ALIGNMENT('baseline', 'vertical-align'), - new ALIGNMENT('sub', 'vertical-align'), - new ALIGNMENT('super', 'vertical-align'), - new ALIGNMENT('top', 'vertical-align'), - new ALIGNMENT('text-top', 'vertical-align'), - new ALIGNMENT('middle', 'vertical-align'), - new ALIGNMENT('bottom', 'vertical-align'), - new ALIGNMENT('text-bottom', 'vertical-align'), - // Floats. - new ALIGNMENT('left', 'float'), - new ALIGNMENT('right', 'float') -]; + /** + * A reference to the currently open form. + * + * @param _form + * @type Node + * @private + */ + _form: null, -/** - * Atto text editor image plugin. - * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -M.atto_image = M.atto_image || { - dialogue: null, - selection: null, - currentlyselected : {}, - lastselectedimage : null, - init: function(params) { - var display_chooser = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_image.selection = M.editor_atto.get_selection(); - if (M.atto_image.selection !== false) { - var dialogue; - if (!M.atto_image.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_image.dialogue; - } - - dialogue.set('bodyContent', M.atto_image.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createimage', 'atto_image')); - dialogue.render(); - dialogue.centerDialogue(); - M.atto_image.dialogue = dialogue; - dialogue.show(); - } - }; - - 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); - M.editor_atto.currentlyselected = M.editor_atto.currentlyselected || {}; - M.editor_atto.currentlyselected[params.elementid] = null; - - // 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. - M.editor_atto.on('atto:selectionchanged', function(e) { - if (M.editor_atto.selection_filter_matches(e.elementid, SELECTORS.TAGS, e.selectedNodes, false)) { - M.editor_atto.add_widget_highlight(e.elementid, 'image'); - M.editor_atto.currentlyselected[e.elementid] = e.selectedNodes; - } else { - M.editor_atto.remove_widget_highlight(e.elementid, 'image'); - M.editor_atto.currentlyselected[e.elementid] = null; - } + initializer: function() { + this.addButton({ + icon: 'e/insert_edit_image', + callback: this._displayDialogue, + tags: 'img', + tagMatchRequiresAll: false }); }, - open_filepicker: function(e) { - var elementid = this.getAttribute('data-editor'); - e.preventDefault(); - M.editor_atto.show_filepicker(elementid, 'image', M.atto_image.filepicker_callback); + /** + * Display the image editing tool. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { + return; + } + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createimage', COMPONENTNAME), + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); }, - filepicker_callback: function(params) { + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @return {Node} The content to place in the dialogue. + * @private + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE), + content = Y.Node.create(template({ + elementid: this.get('host').get('elementid'), + CSS: CSS, + component: COMPONENTNAME, + showFilepicker: this.get('host').canShowFilepicker('image'), + alignments: ALIGNMENTS + })); + + this._form = content; + + // Configure the view of the current image. + this._applyImageProperties(this._form); + + this._form.one('.' + CSS.INPUTURL).on('blur', this._urlChanged, this); + this._form.one('.' + CSS.INPUTSUBMIT).on('click', this._setImage, this); + this._form.one('.' + CSS.IMAGEBROWSER).on('click', function() { + this.get('host').showFilepicker('image', this._filepickerCallback, this); + }, this); + + return content; + }, + + /** + * Update the dialogue after an image was selected in the File Picker. + * + * @method _filepickerCallback + * @param {object} params The parameters provided by the filepicker + * containing information about the image. + * @private + */ + _filepickerCallback: function(params) { if (params.url !== '') { - var input = Y.one('#' + CSS.INPUTURL); + var input = this._form.one('.' + CSS.INPUTURL), + self = this; input.set('value', params.url); // Auto set the width and height. var image = new Image(); image.onload = function() { - Y.one('#' + CSS.INPUTWIDTH).set('value', this.width); - Y.one('#' + CSS.INPUTHEIGHT).set('value', this.height); - Y.one('#' + CSS.IMAGEPREVIEW).set('src', this.src); - Y.one('#' + CSS.IMAGEPREVIEW).setStyle('display', 'inline'); + self._form.one('.' + CSS.INPUTWIDTH).set('value', this.width); + self._form.one('.' + CSS.INPUTHEIGHT).set('value', this.height); + self._form.one('.' + CSS.IMAGEPREVIEW).set('src', this.src); + self._form.one('.' + CSS.IMAGEPREVIEW).setStyle('display', 'inline'); + + // Centre the dialogue once the preview image has loaded. + self.getDialogue().centerDialogue(); }; image.src = params.url; } }, - url_changed: function() { - var input = Y.one('#' + CSS.INPUTURL); - if (input.get('value') !== '') { - // Auto set the width and height. - var image = new Image(); - image.onload = function() { - var input; - - input = Y.one('#' + CSS.INPUTWIDTH); - if (input.get('value') === '') { - input.set('value', this.width); - } - input = Y.one('#' + CSS.INPUTHEIGHT); - if (input.get('value') === '') { - input.set('value', this.height); - } - input = Y.one('#' + CSS.IMAGEPREVIEW); - input.set('src', this.src); - input.setStyle('display', 'inline'); - }; - image.src = input.get('value'); - } - }, - set_image: function(e, elementid) { - var form = e.currentTarget.ancestor('.atto_form'), - url = form.one('#' + CSS.INPUTURL).get('value'), - alt = form.one('#' + CSS.INPUTALT).get('value'), - width = form.one('#' + CSS.INPUTWIDTH).get('value'), - height = form.one('#' + CSS.INPUTHEIGHT).get('value'), - alignment = form.one('#' + CSS.INPUTALIGNMENT).get('value'), - presentation = form.one('#' + CSS.IMAGEPRESENTATION).get('checked'), - imagehtml; - - e.preventDefault(); - - if (alt === '' && !presentation) { - form.one('#' + CSS.IMAGEALTWARNING).setStyle('display', 'block'); - form.one('#' + CSS.INPUTALT).setAttribute('aria-invalid', true); - form.one('#' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', true); - return; - } else { - form.one('#' + CSS.IMAGEALTWARNING).setStyle('display', 'none'); - form.one('#' + CSS.INPUTALT).setAttribute('aria-invalid', false); - form.one('#' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', false); - } - - M.atto_image.dialogue.hide(); - - M.editor_atto.focus(elementid); - if (url !== '') { - if (this.lastselectedimage) { - M.editor_atto.set_selection(M.editor_atto.get_selection_from_node(this.lastselectedimage)); - } else { - M.editor_atto.set_selection(M.atto_image.selection); - } - imagehtml = '' + Y.Escape.html(alt) + ' 0) { - properties.width = width; - } - if (height > 0) { - properties.height = height; - } - for (i in ALIGNMENTS) { - if (ALIGNMENTS[i].test(style)) { - properties.align = ALIGNMENTS[i]; - break; - } - } - properties.src = image.getAttribute('src'); - properties.alt = image.getAttribute('alt') || ''; - properties.presentation = (image.get('role') === 'presentation'); - return properties; - } - return false; - }, - get_form_content: function(elementid) { - - // String collection for quick refernce. - var str = { - alignment: M.util.get_string('alignment', 'atto_image'), - alt: M.util.get_string('enteralt', 'atto_image'), - browse: M.util.get_string('browserepositories', 'atto_image'), - create: M.util.get_string('createimage', 'atto_image'), - height: M.util.get_string('height', 'atto_image'), - presentation: M.util.get_string('presentation', 'atto_image'), - presentationrequired: M.util.get_string('presentationoraltrequired', 'atto_image'), - preview: M.util.get_string('preview', 'atto_image'), - width: M.util.get_string('width', 'atto_image'), - url: M.util.get_string('enterurl', 'atto_image') - }, - html, - i; - - - // Start the form. - html = '
                                        ' + - '' + - '' + - '
                                        '; - - if (M.editor_atto.can_show_filepicker(elementid, 'image')) { - // Add the repository browser button. - html += '' + - '
                                        '; - } - - // Add the Alt box. - html += '' + - '' + - '' + - '
                                        '; - - // Add the presentation select box. - html += '' + - '' + - '
                                        '; - - // Add the width entry box. - html += '' + - '' + - '
                                        '; - - // Add the height entry box. - html += '' + - '' + - '
                                        '; - - // Add the alignment selector. - html += '' + - '' + - '
                                        '; - - // Add the image preview. - html += '' + - '' + - '
                                        ' + - '
                                        '; - - // Add the submit button and close the form. - html += '' + - '
                                        ' + - '
                                        '; - - var content = Y.Node.create(html); - this._apply_image_properties(content, elementid); - - content.one('#' + CSS.INPUTURL).on('blur', M.atto_image.url_changed, this); - content.one('#' + CSS.INPUTSUMBIT).on('click', M.atto_image.set_image, this, elementid); - if (M.editor_atto.can_show_filepicker(elementid, 'image')) { - content.one('#' + CSS.IMAGEBROWSER).on('click', M.atto_image.open_filepicker); - } - return content; - }, /** * Applies properties of an existing image to the image dialogue for editing. * - * @method _apply_image_properties - * @private + * @method _applyImageProperties * @param {Node} form - * @param {string} elementid + * @private */ - _apply_image_properties: function(form, elementid) { - var properties = this._get_selected_image_properties(elementid), - img = form.one('#' + CSS.IMAGEPREVIEW); + _applyImageProperties: function(form) { + var properties = this._getSelectedImageProperties(), + img = form.one('.' + CSS.IMAGEPREVIEW); if (properties === false) { img.setStyle('display', 'none'); @@ -451,20 +300,171 @@ M.atto_image = M.atto_image || { img.setStyle('display', properties.display); } if (properties.width) { - form.one('#' + CSS.INPUTWIDTH).set('value', properties.width); + form.one('.' + CSS.INPUTWIDTH).set('value', properties.width); } if (properties.height) { - form.one('#' + CSS.INPUTHEIGHT).set('value', properties.height); + form.one('.' + CSS.INPUTHEIGHT).set('value', properties.height); } if (properties.alt) { - form.one('#' + CSS.INPUTALT).set('value', properties.alt); + form.one('.' + CSS.INPUTALT).set('value', properties.alt); } if (properties.src) { - form.one('#' + CSS.INPUTURL).set('value', properties.src); + form.one('.' + CSS.INPUTURL).set('value', properties.src); img.setAttribute('src', properties.src); } if (properties.presentation) { - form.one('#' + CSS.IMAGEPRESENTATION).set('checked', 'checked'); + form.one('.' + CSS.IMAGEPRESENTATION).set('checked', 'checked'); + } + }, + + /** + * Gets the properties of the currently selected image. + * + * The first image only if multiple images are selected. + * + * @method _getSelectedImageProperties + * @return {object} + * @private + */ + _getSelectedImageProperties: function() { + var properties = { + src: null, + alt :null, + width: null, + height: null, + align: null, + display: 'inline', + presentation: false + }, + + // Get the current selection. + images = this.get('host').getSelectedNodes(), + i, width, height, style; + + if (images) { + images = images.filter('img'); + } + + if (images && images.size()) { + image = images.item(0); + this._selectedImage = image; + + style = image.getAttribute('style'); + width = parseInt(image.getAttribute('width'), 10); + height = parseInt(image.getAttribute('height'), 10); + + if (width > 0) { + properties.width = width; + } + if (height > 0) { + properties.height = height; + } + for (i in ALIGNMENTS) { + if (ALIGNMENTS[i].name === style) { + properties.align = ALIGNMENTS[i]; + break; + } + } + properties.src = image.getAttribute('src'); + properties.alt = image.getAttribute('alt') || ''; + properties.presentation = (image.get('role') === 'presentation'); + return properties; + } + + // No image selected - clean up. + this._selectedImage = null; + return false; + }, + + /** + * Update the form when the URL was changed. This includes updating the + * height, width, and image preview. + * + * @method _urlChanged + * @private + */ + _urlChanged: function() { + var input = this._form.one('.' + CSS.INPUTURL), + self = this; + + if (input.get('value') !== '') { + // Auto set the width and height. + var image = new Image(); + image.onload = function() { + var input; + + input = self._form.one('.' + CSS.INPUTWIDTH); + if (input.get('value') === '') { + input.set('value', this.width); + } + input = self._form.one('.' + CSS.INPUTHEIGHT); + if (input.get('value') === '') { + input.set('value', this.height); + } + input = self._form.one('.' + CSS.IMAGEPREVIEW); + input.set('src', this.src); + input.setStyle('display', 'inline'); + }; + image.src = input.get('value'); + } + }, + + /** + * Update the image in the contenteditable. + * + * @method _setImage + * @param {EventFacade} e + * @private + */ + _setImage: function(e) { + var form = this._form, + url = form.one('.' + CSS.INPUTURL).get('value'), + alt = form.one('.' + CSS.INPUTALT).get('value'), + width = form.one('.' + CSS.INPUTWIDTH).get('value'), + height = form.one('.' + CSS.INPUTHEIGHT).get('value'), + alignment = form.one('.' + CSS.INPUTALIGNMENT).get('value'), + presentation = form.one('.' + CSS.IMAGEPRESENTATION).get('checked'), + imagehtml, + host = this.get('host'); + + e.preventDefault(); + + if (alt === '' && !presentation) { + form.one('.' + CSS.IMAGEALTWARNING).setStyle('display', 'block'); + form.one('.' + CSS.INPUTALT).setAttribute('aria-invalid', true); + form.one('.' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', true); + return; + } else { + form.one('.' + CSS.IMAGEALTWARNING).setStyle('display', 'none'); + form.one('.' + CSS.INPUTALT).setAttribute('aria-invalid', false); + form.one('.' + CSS.IMAGEPRESENTATION).setAttribute('aria-invalid', false); + } + + this.getDialogue({ + focusAfterHide: null + }).hide(); + + // Focus on the editor in preparation for inserting the image. + host.focus(); + if (url !== '') { + if (this._selectedImage) { + host.setSelection(host.getSelectionFromNode(this._selectedImage)); + } else { + host.setSelection(this._currentSelection); + } + template = Y.Handlebars.compile(IMAGETEMPLATE); + imagehtml = template({ + url: url, + alt: alt, + width: width, + height: height, + presentation: presentation, + alignment: alignment + }); + + this.get('host').insertContentAtFocusPoint(imagehtml); + + this.markUpdated(); } } -}; +}); diff --git a/lib/editor/atto/plugins/image/yui/src/button/meta/button.json b/lib/editor/atto/plugins/image/yui/src/button/meta/button.json index 3a97310a174..4d7f220f1aa 100644 --- a/lib/editor/atto/plugins/image/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/image/yui/src/button/meta/button.json @@ -1,8 +1,7 @@ { - "moodle-atto_image-button": { - "requires": [ - "node", - "escape" - ] - } + "moodle-atto_image-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button-debug.js b/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button-debug.js index 223be234408..9dc6ee5aae3 100644 --- a/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button-debug.js +++ b/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button-debug.js @@ -15,63 +15,58 @@ YUI.add('moodle-atto_indent-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor indent plugin. - * +/* * @package atto_indent * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_indent = M.atto_indent || { - init : function(params) { - var iconurl, indent, outdent; - indent = function(e, elementid) { - var editable; - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } +/** + * @module moodle-atto_indent-button + */ +/** + * Atto text editor indent plugin. + * + * @namespace M.atto_indent + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_indent').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addButton({ // This is adding a
                                        which is not ideal but that is the easiest to put in place // for now. When disabling the styleWithCSS, some browser will use
                                        so we cannot // rely on it for
                                        s, and that would not work when indenting lists either.... // Handling it ourselves is even worse as it would require to get a parent and wrap // a div with a margin around it. Considering that multiple

                                        should end up in the // same

                                        , that table cells should not be wrapped, and that lists work differently too. - document.execCommand('indent', false, null); + icon: 'e/increase_indent', + title: 'indent', + buttonName: 'indent', + callback: function() { + document.execCommand('indent', false, null); - // Some browsers add style attributes to the blockquote, let's get rid of them. - // It is really tricky to figure out what blockquote was just added, so removing - // the styles on all of them seems OK. - // Eg. Chrome changes the selection after adding the blockquote, so we cannot target it. - // IE adds a dir attribute to the blockquote too, but it's probably OK to leave it... - editable = M.editor_atto.get_editable_node(elementid); - editable.all('blockquote').removeAttribute('style'); + // Some browsers add style attributes to the blockquote, let's get rid of them. + // It is really tricky to figure out what blockquote was just added, so removing + // the styles on all of them seems OK. + // Eg. Chrome changes the selection after adding the blockquote, so we cannot target it. + // IE adds a dir attribute to the blockquote too, but it's probably OK to leave it... + this.editor.all('blockquote').removeAttribute('style'); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - outdent = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); + // Mark the text as having been updated. + this.markUpdated(); } - document.execCommand('outdent', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; + }); - iconurl = M.util.image_url('e/decrease_indent', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'indent', iconurl, params.group, outdent, - 'outdent', M.util.get_string('outdent', 'atto_indent')); - - iconurl = M.util.image_url('e/increase_indent', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'indent', iconurl, params.group, indent, - 'indent', M.util.get_string('indent', 'atto_indent')); + this.addBasicButton({ + exec: 'outdent', + icon: 'e/decrease_indent', + title: 'outdent' + }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button-min.js b/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button-min.js index 6a88d2579c9..034421df301 100644 --- a/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button-min.js +++ b/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_indent-button",function(e,t){M.atto_indent=M.atto_indent||{init:function(e){var t,n,r;n=function(e,t){var n;e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("indent",!1,null),n=M.editor_atto.get_editable_node(t),n.all("blockquote").removeAttribute("style"),M.editor_atto.text_updated(t)},r=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("outdent",!1,null),M.editor_atto.text_updated(t)},t=M.util.image_url("e/decrease_indent","core"),M.editor_atto.add_toolbar_button(e.elementid,"indent",t,e.group,r,"outdent",M.util.get_string("outdent","atto_indent")),t=M.util.image_url("e/increase_indent","core"),M.editor_atto.add_toolbar_button(e.elementid,"indent",t,e.group,n,"indent",M.util.get_string("indent","atto_indent"))}}},"@VERSION@",{requires:["node"]}); +YUI.add("moodle-atto_indent-button",function(e,t){e.namespace("M.atto_indent").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addButton({icon:"e/increase_indent",title:"indent",buttonName:"indent",callback:function(){document.execCommand("indent",!1,null),this.editor.all("blockquote").removeAttribute("style"),this.markUpdated()}}),this.addBasicButton({exec:"outdent",icon:"e/decrease_indent",title:"outdent"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button.js b/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button.js index 223be234408..9dc6ee5aae3 100644 --- a/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button.js +++ b/lib/editor/atto/plugins/indent/yui/build/moodle-atto_indent-button/moodle-atto_indent-button.js @@ -15,63 +15,58 @@ YUI.add('moodle-atto_indent-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor indent plugin. - * +/* * @package atto_indent * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_indent = M.atto_indent || { - init : function(params) { - var iconurl, indent, outdent; - indent = function(e, elementid) { - var editable; - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } +/** + * @module moodle-atto_indent-button + */ +/** + * Atto text editor indent plugin. + * + * @namespace M.atto_indent + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_indent').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addButton({ // This is adding a
                                        which is not ideal but that is the easiest to put in place // for now. When disabling the styleWithCSS, some browser will use
                                        so we cannot // rely on it for
                                        s, and that would not work when indenting lists either.... // Handling it ourselves is even worse as it would require to get a parent and wrap // a div with a margin around it. Considering that multiple

                                        should end up in the // same

                                        , that table cells should not be wrapped, and that lists work differently too. - document.execCommand('indent', false, null); + icon: 'e/increase_indent', + title: 'indent', + buttonName: 'indent', + callback: function() { + document.execCommand('indent', false, null); - // Some browsers add style attributes to the blockquote, let's get rid of them. - // It is really tricky to figure out what blockquote was just added, so removing - // the styles on all of them seems OK. - // Eg. Chrome changes the selection after adding the blockquote, so we cannot target it. - // IE adds a dir attribute to the blockquote too, but it's probably OK to leave it... - editable = M.editor_atto.get_editable_node(elementid); - editable.all('blockquote').removeAttribute('style'); + // Some browsers add style attributes to the blockquote, let's get rid of them. + // It is really tricky to figure out what blockquote was just added, so removing + // the styles on all of them seems OK. + // Eg. Chrome changes the selection after adding the blockquote, so we cannot target it. + // IE adds a dir attribute to the blockquote too, but it's probably OK to leave it... + this.editor.all('blockquote').removeAttribute('style'); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - outdent = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); + // Mark the text as having been updated. + this.markUpdated(); } - document.execCommand('outdent', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; + }); - iconurl = M.util.image_url('e/decrease_indent', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'indent', iconurl, params.group, outdent, - 'outdent', M.util.get_string('outdent', 'atto_indent')); - - iconurl = M.util.image_url('e/increase_indent', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'indent', iconurl, params.group, indent, - 'indent', M.util.get_string('indent', 'atto_indent')); + this.addBasicButton({ + exec: 'outdent', + icon: 'e/decrease_indent', + title: 'outdent' + }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/indent/yui/src/button/js/button.js b/lib/editor/atto/plugins/indent/yui/src/button/js/button.js index 8cdbf334480..fe7433cf9d0 100644 --- a/lib/editor/atto/plugins/indent/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/indent/yui/src/button/js/button.js @@ -13,60 +13,55 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor indent plugin. - * +/* * @package atto_indent * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_indent = M.atto_indent || { - init : function(params) { - var iconurl, indent, outdent; - indent = function(e, elementid) { - var editable; - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } +/** + * @module moodle-atto_indent-button + */ +/** + * Atto text editor indent plugin. + * + * @namespace M.atto_indent + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_indent').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addButton({ // This is adding a
                                        which is not ideal but that is the easiest to put in place // for now. When disabling the styleWithCSS, some browser will use
                                        so we cannot // rely on it for
                                        s, and that would not work when indenting lists either.... // Handling it ourselves is even worse as it would require to get a parent and wrap // a div with a margin around it. Considering that multiple

                                        should end up in the // same

                                        , that table cells should not be wrapped, and that lists work differently too. - document.execCommand('indent', false, null); + icon: 'e/increase_indent', + title: 'indent', + buttonName: 'indent', + callback: function() { + document.execCommand('indent', false, null); - // Some browsers add style attributes to the blockquote, let's get rid of them. - // It is really tricky to figure out what blockquote was just added, so removing - // the styles on all of them seems OK. - // Eg. Chrome changes the selection after adding the blockquote, so we cannot target it. - // IE adds a dir attribute to the blockquote too, but it's probably OK to leave it... - editable = M.editor_atto.get_editable_node(elementid); - editable.all('blockquote').removeAttribute('style'); + // Some browsers add style attributes to the blockquote, let's get rid of them. + // It is really tricky to figure out what blockquote was just added, so removing + // the styles on all of them seems OK. + // Eg. Chrome changes the selection after adding the blockquote, so we cannot target it. + // IE adds a dir attribute to the blockquote too, but it's probably OK to leave it... + this.editor.all('blockquote').removeAttribute('style'); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - outdent = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); + // Mark the text as having been updated. + this.markUpdated(); } - document.execCommand('outdent', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; + }); - iconurl = M.util.image_url('e/decrease_indent', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'indent', iconurl, params.group, outdent, - 'outdent', M.util.get_string('outdent', 'atto_indent')); - - iconurl = M.util.image_url('e/increase_indent', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'indent', iconurl, params.group, indent, - 'indent', M.util.get_string('indent', 'atto_indent')); + this.addBasicButton({ + exec: 'outdent', + icon: 'e/decrease_indent', + title: 'outdent' + }); } -}; +}); diff --git a/lib/editor/atto/plugins/indent/yui/src/button/meta/button.json b/lib/editor/atto/plugins/indent/yui/src/button/meta/button.json index 812a3bc7858..c7b92c47d82 100644 --- a/lib/editor/atto/plugins/indent/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/indent/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_indent-button": { - "requires": ["node"] - } + "moodle-atto_indent-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } 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 5c095951e0f..dcba9e9652a 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,50 +15,37 @@ 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 . +/* + * @package atto_italic + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_italic-button */ -var SELECTORS = { - TAGS : 'i' -}; /** * Atto text editor italic plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_italic + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_italic = M.atto_italic || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('italic', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - 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}); +Y.namespace('M.atto_italic').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'italic', - // 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. - M.editor_atto.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'); - } + // Key code for the keyboard shortcut which triggers this button: + keys: '73', + + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'i' }); } -}; +}); -}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 a2f065346a9..6a64c7040d0 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),M.editor_atto.add_button_shortcut({action:"italic",keys:73}),M.editor_atto.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"]}); +YUI.add("moodle-atto_italic-button",function(e,t){e.namespace("M.atto_italic").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"italic",keys:"73",tags:"i"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 5c095951e0f..dcba9e9652a 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,50 +15,37 @@ 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 . +/* + * @package atto_italic + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_italic-button */ -var SELECTORS = { - TAGS : 'i' -}; /** * Atto text editor italic plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_italic + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_italic = M.atto_italic || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('italic', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - 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}); +Y.namespace('M.atto_italic').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'italic', - // 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. - M.editor_atto.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'); - } + // Key code for the keyboard shortcut which triggers this button: + keys: '73', + + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'i' }); } -}; +}); -}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 97db19d4a88..8823c30d803 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,47 +13,34 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_italic + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_italic-button */ -var SELECTORS = { - TAGS : 'i' -}; /** * Atto text editor italic plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_italic + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_italic = M.atto_italic || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('italic', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - 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}); +Y.namespace('M.atto_italic').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'italic', - // 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. - M.editor_atto.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'); - } + // Key code for the keyboard shortcut which triggers this button: + keys: '73', + + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'i' }); } -}; +}); 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 6a0efa9d9bc..d1ba4c9bd64 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,7 @@ { - "moodle-atto_italic-button": { - "requires": ["node", "moodle-editor_atto-editor-shortcut"] - } + "moodle-atto_italic-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } 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 ecc840b6eef..077e2363021 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,226 +15,231 @@ 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 . +/* + * @package atto_link + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_link-button */ -var SELECTORS = { - TAGS : 'a' -}; /** * Atto text editor link plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_link + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_link = M.atto_link || { - /** - * The window used to get the link details. - * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, + +var COMPONENTNAME = 'atto_link', + CSS = { + NEWWINDOW: 'atto_link_openinnewwindow' + }, + TEMPLATE = '' + + '
                                        ' + + '' + + '
                                        ' + + + // Add the repository browser button. + '{{#if showFilepicker}}' + + '' + + '
                                        ' + + '{{/if}}' + + '' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        '; +Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The selection object returned by the browser. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @property selection + * @property _currentSelection * @type Range - * @default null + * @private */ - selection : null, + _currentSelection: null, /** - * Display the chooser dialogue. + * A reference to the dialogue content. * - * @method init - * @param Event e - * @param string elementid + * @property _content + * @type Node + * @private */ - display_chooser : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_link.selection = M.editor_atto.get_selection(); - if (M.atto_link.selection !== false && (!M.atto_link.selection.collapsed)) { - var dialogue; - if (!M.atto_link.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_link.dialogue; - } + _content: null, - dialogue.render(); - dialogue.set('bodyContent', M.atto_link.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createlink', 'atto_link')); - - M.atto_link.resolve_anchors(); - - dialogue.show(); - M.atto_link.dialogue = dialogue; - } + initializer: function() { + this.addButton({ + icon: 'e/insert_edit_link', + callback: this._displayDialogue, + tags: 'a' + }); }, /** - * Add this button to the form. + * Display the link editor. * - * @method init - * @param {Object} params + * @method _displayDialogue + * @private */ - 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. - M.editor_atto.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'); - } + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false || this._currentSelection.collapsed) { + return; + } + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createlink', COMPONENTNAME), + focusAfterHide: true }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()); + + // Resolve anchors in the selected text. + this._resolveAnchors(); + dialogue.show(); }, /** * If there is selected text and it is part of an anchor link, * extract the url (and target) from the link (and set them in the form). * - * @method resolve_anchors + * @method _resolveAnchors + * @private */ - resolve_anchors : function() { + _resolveAnchors: function() { // Find the first anchor tag in the selection. - var selectednode = M.editor_atto.get_selection_parent_node(), + var selectednode = this.get('host').getSelectionParentNode(), anchornodes, anchornode, - url; + url, + target; // Note this is a document fragment and YUI doesn't like them. if (!selectednode) { return; } - anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode)); - + anchornodes = this._findSelectedAnchors(Y.one(selectednode)); if (anchornodes.length > 0) { anchornode = anchornodes[0]; - M.atto_link.selection = M.editor_atto.get_selection_from_node(anchornode); + this._currentSelection = this.get('host').getSelectionFromNode(anchornode); url = anchornode.getAttribute('href'); target = anchornode.getAttribute('target'); if (url !== '') { - Y.one('#atto_link_urlentry').set('value', url); + this._content.one('.url').setAttribute('value', url); } if (target === '_blank') { - Y.one('#atto_link_openinnewwindow').set('checked', 'checked'); + this._content.one('.newwindow').setAttribute('checked', 'checked'); } else { - Y.one('#atto_link_openinnewwindow').set('checked', ''); + this._content.one('.newwindow').removeAttribute('checked'); } } }, /** - * Open the repository file picker. + * Update the dialogue after an image was selected in the File Picker. * - * @method open_filepicker - * @param Event e + * @method _filepickerCallback + * @param {object} params The parameters provided by the filepicker + * containing information about the image. + * @private */ - open_filepicker : function(e) { - var elementid = this.getAttribute('data-editor'); - e.preventDefault(); + _filepickerCallback: function(params) { + this.getDialogue() + .set('focusAfterHide', null) + .hide(); - M.editor_atto.show_filepicker(elementid, 'link', M.atto_link.filepicker_callback); - }, - - /** - * Called by the file picker when a link has been chosen. - * - * @method filepicker_callback - * @param {Object} params - contains selected url. - */ - filepicker_callback : function(params) { - M.atto_link.dialogue.hide(); if (params.url !== '') { - M.editor_atto.set_selection(M.atto_link.selection); + this.get('host').setSelection(this._currentSelection); document.execCommand('unlink', false, null); document.execCommand('createLink', false, params.url); } }, /** - * The OK button has been pressed - make the changes to the source. + * The link was inserted, so make changes to the editor source. * - * @method set_link - * @param Event e + * @method _setLink + * @param {EventFacade} e + * @private */ - set_link : function(e, elementid) { + _setLink: function(e) { var input, target, selectednode, anchornodes, value; - e.preventDefault(); - M.atto_link.dialogue.hide(); + var host = this.get('host'); - input = e.currentTarget.ancestor('.atto_form').one('input[type=url]'); + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + + input = this._content.one('.url'); value = input.get('value'); if (value !== '') { - M.editor_atto.set_selection(M.atto_link.selection); + this.editor.focus(); + host.setSelection(this._currentSelection); document.execCommand('unlink', false, null); document.execCommand('createLink', false, value); // Now set the target. - selectednode = M.editor_atto.get_selection_parent_node(); + selectednode = host.getSelectionParentNode(); // Note this is a document fragment and YUI doesn't like them. if (!selectednode) { return; } - anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode)); + anchornodes = this._findSelectedAnchors(Y.one(selectednode)); Y.Array.each(anchornodes, function(anchornode) { - target = e.currentTarget.ancestor('.atto_form').one('input[type=checkbox]'); + target = this._content.one('.newwindow'); if (target.get('checked')) { anchornode.setAttribute('target', '_blank'); } else { anchornode.removeAttribute('target'); } - }); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + }, this); + + this.markUpdated(); } }, /** * Look up and down for the nearest anchor tags that are least partly contained in the selection. * - * @method find_selected_anchors - * @param Node node - * @return Node|false + * @method _findSelectedAnchors + * @param {Node} node The node to search under for the selected anchor. + * @return {Node|Boolean} The Node, or false if not found. + * @private */ - find_selected_anchors : function(node) { - var tagname = node.get('tagName'), hit, hits; + _findSelectedAnchors: function(node) { + var tagname = node.get('tagName'), + hit, hits; + // Direct hit. if (tagname && tagname.toLowerCase() === 'a') { return [node]; } + // Search down but check that each node is part of the selection. hits = []; node.all('a').each(function(n) { - if (!hit && M.editor_atto.selection_contains_node(n)) { + if (!hit && this.get('host').selectionContainsNode(n)) { hits.push(n); } }); @@ -250,44 +255,33 @@ M.atto_link = M.atto_link || { }, /** - * Return the HTML of the form to show in the dialogue. + * Generates the content of the dialogue. * - * @method get_form_content - * @param string elementid - * @return string + * @method _getDialogueContent + * @return {Node} Node containing the dialogue content + * @private */ - get_form_content : function(elementid) { - var html = '
                                        ' + - '' + - '
                                        '; - if (M.editor_atto.can_show_filepicker(elementid, 'link')) { - html += '' + - '
                                        '; - } - html += '' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        '; + _getDialogueContent: function() { + var canShowFilepicker = this.get('host').canShowFilepicker('link'), + template = Y.Handlebars.compile(TEMPLATE); - var content = Y.Node.create(html); + this._content = Y.Node.create(template({ + showFilepicker: canShowFilepicker, + component: COMPONENTNAME, + CSS: CSS + })); - content.one('#atto_link_urlentrysubmit').on('click', M.atto_link.set_link, this, elementid); - if (M.editor_atto.can_show_filepicker(elementid, 'link')) { - content.one('#openlinkbrowser').on('click', M.atto_link.open_filepicker); + this._content.one('.submit').on('click', this._setLink, this); + if (canShowFilepicker) { + this._content.one('.openlinkbrowser').on('click', function(e) { + e.preventDefault(); + this.get('host').showFilepicker('link', this._filepickerCallback, this); + }, this); } - return content; + + return this._content; } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 bdd8e03930e..2b145903e6b 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){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),M.editor_atto.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='
                                        "+'
                                        ';M.editor_atto.can_show_filepicker(t,"link")&&(n+='"+"
                                        "),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="atto_link",r={NEWWINDOW:"atto_link_openinnewwindow"},i='

                                        {{#if showFilepicker}}
                                        {{/if}}

                                        ';e.namespace("M.atto_link").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,_content:null,initializer:function(){this.addButton({icon:"e/insert_edit_link",callback:this._displayDialogue,tags:"a"})},_displayDialogue:function(){this._currentSelection=this.get("host").getSelection();if(this._currentSelection===!1||this._currentSelection.collapsed)return;var e=this.getDialogue({headerContent:M.util.get_string("createlink",n),focusAfterHide:!0});e.set("bodyContent",this._getDialogueContent()),this._resolveAnchors(),e.show()},_resolveAnchors:function(){var t=this.get("host").getSelectionParentNode(),n,r,i,s;if(!t)return;n=this._findSelectedAnchors(e.one(t)),n.length>0&&(r=n[0],this._currentSelection=this.get("host").getSelectionFromNode(r),i=r.getAttribute("href"),s=r.getAttribute("target"),i!==""&&this._content.one(".url").setAttribute("value",i),s==="_blank"?this._content.one(".newwindow").setAttribute("checked","checked"):this._content.one(".newwindow").removeAttribute("checked"))},_filepickerCallback:function(e){this.getDialogue().set("focusAfterHide",null).hide(),e.url!==""&&(this.get("host").setSelection(this._currentSelection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,e.url))},_setLink:function(t){var n,r,i,s,o,u=this.get("host");t.preventDefault(),this.getDialogue({focusAfterHide:null}).hide(),n=this._content.one(".url"),o=n.get("value");if(o!==""){this.editor.focus(),u.setSelection(this._currentSelection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,o),i=u.getSelectionParentNode();if(!i)return;s=this._findSelectedAnchors(e.one(i)),e.Array.each(s,function(e){r=this._content.one(".newwindow"),r.get("checked")?e.setAttribute("target","_blank"):e.removeAttribute("target")},this),this.markUpdated()}},_findSelectedAnchors:function(e){var t=e.get("tagName"),n,r;return t&&t.toLowerCase()==="a"?[e]:(r=[],e.all("a").each(function(e){!n&&this.get("host").selectionContainsNode(e)&&r.push(e)}),r.length>0?r:(n=e.ancestor("a"),n?[n]:[]))},_getDialogueContent:function(){var t=this.get("host").canShowFilepicker("link"),s=e.Handlebars.compile(i);return this._content=e.Node.create(s({showFilepicker:t,component:n,CSS:r})),this._content.one(".submit").on("click",this._setLink,this),t&&this._content.one(".openlinkbrowser").on("click",function(e){e.preventDefault(),this.get("host").showFilepicker("link",this._filepickerCallback,this)},this),this._content}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 ecc840b6eef..077e2363021 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,226 +15,231 @@ 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 . +/* + * @package atto_link + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_link-button */ -var SELECTORS = { - TAGS : 'a' -}; /** * Atto text editor link plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_link + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_link = M.atto_link || { - /** - * The window used to get the link details. - * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, + +var COMPONENTNAME = 'atto_link', + CSS = { + NEWWINDOW: 'atto_link_openinnewwindow' + }, + TEMPLATE = '' + + '
                                        ' + + '' + + '
                                        ' + + + // Add the repository browser button. + '{{#if showFilepicker}}' + + '' + + '
                                        ' + + '{{/if}}' + + '' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        '; +Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The selection object returned by the browser. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @property selection + * @property _currentSelection * @type Range - * @default null + * @private */ - selection : null, + _currentSelection: null, /** - * Display the chooser dialogue. + * A reference to the dialogue content. * - * @method init - * @param Event e - * @param string elementid + * @property _content + * @type Node + * @private */ - display_chooser : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_link.selection = M.editor_atto.get_selection(); - if (M.atto_link.selection !== false && (!M.atto_link.selection.collapsed)) { - var dialogue; - if (!M.atto_link.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_link.dialogue; - } + _content: null, - dialogue.render(); - dialogue.set('bodyContent', M.atto_link.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createlink', 'atto_link')); - - M.atto_link.resolve_anchors(); - - dialogue.show(); - M.atto_link.dialogue = dialogue; - } + initializer: function() { + this.addButton({ + icon: 'e/insert_edit_link', + callback: this._displayDialogue, + tags: 'a' + }); }, /** - * Add this button to the form. + * Display the link editor. * - * @method init - * @param {Object} params + * @method _displayDialogue + * @private */ - 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. - M.editor_atto.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'); - } + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false || this._currentSelection.collapsed) { + return; + } + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createlink', COMPONENTNAME), + focusAfterHide: true }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()); + + // Resolve anchors in the selected text. + this._resolveAnchors(); + dialogue.show(); }, /** * If there is selected text and it is part of an anchor link, * extract the url (and target) from the link (and set them in the form). * - * @method resolve_anchors + * @method _resolveAnchors + * @private */ - resolve_anchors : function() { + _resolveAnchors: function() { // Find the first anchor tag in the selection. - var selectednode = M.editor_atto.get_selection_parent_node(), + var selectednode = this.get('host').getSelectionParentNode(), anchornodes, anchornode, - url; + url, + target; // Note this is a document fragment and YUI doesn't like them. if (!selectednode) { return; } - anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode)); - + anchornodes = this._findSelectedAnchors(Y.one(selectednode)); if (anchornodes.length > 0) { anchornode = anchornodes[0]; - M.atto_link.selection = M.editor_atto.get_selection_from_node(anchornode); + this._currentSelection = this.get('host').getSelectionFromNode(anchornode); url = anchornode.getAttribute('href'); target = anchornode.getAttribute('target'); if (url !== '') { - Y.one('#atto_link_urlentry').set('value', url); + this._content.one('.url').setAttribute('value', url); } if (target === '_blank') { - Y.one('#atto_link_openinnewwindow').set('checked', 'checked'); + this._content.one('.newwindow').setAttribute('checked', 'checked'); } else { - Y.one('#atto_link_openinnewwindow').set('checked', ''); + this._content.one('.newwindow').removeAttribute('checked'); } } }, /** - * Open the repository file picker. + * Update the dialogue after an image was selected in the File Picker. * - * @method open_filepicker - * @param Event e + * @method _filepickerCallback + * @param {object} params The parameters provided by the filepicker + * containing information about the image. + * @private */ - open_filepicker : function(e) { - var elementid = this.getAttribute('data-editor'); - e.preventDefault(); + _filepickerCallback: function(params) { + this.getDialogue() + .set('focusAfterHide', null) + .hide(); - M.editor_atto.show_filepicker(elementid, 'link', M.atto_link.filepicker_callback); - }, - - /** - * Called by the file picker when a link has been chosen. - * - * @method filepicker_callback - * @param {Object} params - contains selected url. - */ - filepicker_callback : function(params) { - M.atto_link.dialogue.hide(); if (params.url !== '') { - M.editor_atto.set_selection(M.atto_link.selection); + this.get('host').setSelection(this._currentSelection); document.execCommand('unlink', false, null); document.execCommand('createLink', false, params.url); } }, /** - * The OK button has been pressed - make the changes to the source. + * The link was inserted, so make changes to the editor source. * - * @method set_link - * @param Event e + * @method _setLink + * @param {EventFacade} e + * @private */ - set_link : function(e, elementid) { + _setLink: function(e) { var input, target, selectednode, anchornodes, value; - e.preventDefault(); - M.atto_link.dialogue.hide(); + var host = this.get('host'); - input = e.currentTarget.ancestor('.atto_form').one('input[type=url]'); + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + + input = this._content.one('.url'); value = input.get('value'); if (value !== '') { - M.editor_atto.set_selection(M.atto_link.selection); + this.editor.focus(); + host.setSelection(this._currentSelection); document.execCommand('unlink', false, null); document.execCommand('createLink', false, value); // Now set the target. - selectednode = M.editor_atto.get_selection_parent_node(); + selectednode = host.getSelectionParentNode(); // Note this is a document fragment and YUI doesn't like them. if (!selectednode) { return; } - anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode)); + anchornodes = this._findSelectedAnchors(Y.one(selectednode)); Y.Array.each(anchornodes, function(anchornode) { - target = e.currentTarget.ancestor('.atto_form').one('input[type=checkbox]'); + target = this._content.one('.newwindow'); if (target.get('checked')) { anchornode.setAttribute('target', '_blank'); } else { anchornode.removeAttribute('target'); } - }); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + }, this); + + this.markUpdated(); } }, /** * Look up and down for the nearest anchor tags that are least partly contained in the selection. * - * @method find_selected_anchors - * @param Node node - * @return Node|false + * @method _findSelectedAnchors + * @param {Node} node The node to search under for the selected anchor. + * @return {Node|Boolean} The Node, or false if not found. + * @private */ - find_selected_anchors : function(node) { - var tagname = node.get('tagName'), hit, hits; + _findSelectedAnchors: function(node) { + var tagname = node.get('tagName'), + hit, hits; + // Direct hit. if (tagname && tagname.toLowerCase() === 'a') { return [node]; } + // Search down but check that each node is part of the selection. hits = []; node.all('a').each(function(n) { - if (!hit && M.editor_atto.selection_contains_node(n)) { + if (!hit && this.get('host').selectionContainsNode(n)) { hits.push(n); } }); @@ -250,44 +255,33 @@ M.atto_link = M.atto_link || { }, /** - * Return the HTML of the form to show in the dialogue. + * Generates the content of the dialogue. * - * @method get_form_content - * @param string elementid - * @return string + * @method _getDialogueContent + * @return {Node} Node containing the dialogue content + * @private */ - get_form_content : function(elementid) { - var html = '
                                        ' + - '' + - '
                                        '; - if (M.editor_atto.can_show_filepicker(elementid, 'link')) { - html += '' + - '
                                        '; - } - html += '' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        '; + _getDialogueContent: function() { + var canShowFilepicker = this.get('host').canShowFilepicker('link'), + template = Y.Handlebars.compile(TEMPLATE); - var content = Y.Node.create(html); + this._content = Y.Node.create(template({ + showFilepicker: canShowFilepicker, + component: COMPONENTNAME, + CSS: CSS + })); - content.one('#atto_link_urlentrysubmit').on('click', M.atto_link.set_link, this, elementid); - if (M.editor_atto.can_show_filepicker(elementid, 'link')) { - content.one('#openlinkbrowser').on('click', M.atto_link.open_filepicker); + this._content.one('.submit').on('click', this._setLink, this); + if (canShowFilepicker) { + this._content.one('.openlinkbrowser').on('click', function(e) { + e.preventDefault(); + this.get('host').showFilepicker('link', this._filepickerCallback, this); + }, this); } - return content; + + return this._content; } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 fe0ab67359e..efd47b92204 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,226 +13,231 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_link + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_link-button */ -var SELECTORS = { - TAGS : 'a' -}; /** * Atto text editor link plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_link + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_link = M.atto_link || { - /** - * The window used to get the link details. - * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, + +var COMPONENTNAME = 'atto_link', + CSS = { + NEWWINDOW: 'atto_link_openinnewwindow' + }, + TEMPLATE = '' + + '
                                        ' + + '' + + '
                                        ' + + + // Add the repository browser button. + '{{#if showFilepicker}}' + + '' + + '
                                        ' + + '{{/if}}' + + '' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        '; +Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The selection object returned by the browser. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @property selection + * @property _currentSelection * @type Range - * @default null + * @private */ - selection : null, + _currentSelection: null, /** - * Display the chooser dialogue. + * A reference to the dialogue content. * - * @method init - * @param Event e - * @param string elementid + * @property _content + * @type Node + * @private */ - display_chooser : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_link.selection = M.editor_atto.get_selection(); - if (M.atto_link.selection !== false && (!M.atto_link.selection.collapsed)) { - var dialogue; - if (!M.atto_link.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_link.dialogue; - } + _content: null, - dialogue.render(); - dialogue.set('bodyContent', M.atto_link.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createlink', 'atto_link')); - - M.atto_link.resolve_anchors(); - - dialogue.show(); - M.atto_link.dialogue = dialogue; - } + initializer: function() { + this.addButton({ + icon: 'e/insert_edit_link', + callback: this._displayDialogue, + tags: 'a' + }); }, /** - * Add this button to the form. + * Display the link editor. * - * @method init - * @param {Object} params + * @method _displayDialogue + * @private */ - 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. - M.editor_atto.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'); - } + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false || this._currentSelection.collapsed) { + return; + } + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createlink', COMPONENTNAME), + focusAfterHide: true }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()); + + // Resolve anchors in the selected text. + this._resolveAnchors(); + dialogue.show(); }, /** * If there is selected text and it is part of an anchor link, * extract the url (and target) from the link (and set them in the form). * - * @method resolve_anchors + * @method _resolveAnchors + * @private */ - resolve_anchors : function() { + _resolveAnchors: function() { // Find the first anchor tag in the selection. - var selectednode = M.editor_atto.get_selection_parent_node(), + var selectednode = this.get('host').getSelectionParentNode(), anchornodes, anchornode, - url; + url, + target; // Note this is a document fragment and YUI doesn't like them. if (!selectednode) { return; } - anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode)); - + anchornodes = this._findSelectedAnchors(Y.one(selectednode)); if (anchornodes.length > 0) { anchornode = anchornodes[0]; - M.atto_link.selection = M.editor_atto.get_selection_from_node(anchornode); + this._currentSelection = this.get('host').getSelectionFromNode(anchornode); url = anchornode.getAttribute('href'); target = anchornode.getAttribute('target'); if (url !== '') { - Y.one('#atto_link_urlentry').set('value', url); + this._content.one('.url').setAttribute('value', url); } if (target === '_blank') { - Y.one('#atto_link_openinnewwindow').set('checked', 'checked'); + this._content.one('.newwindow').setAttribute('checked', 'checked'); } else { - Y.one('#atto_link_openinnewwindow').set('checked', ''); + this._content.one('.newwindow').removeAttribute('checked'); } } }, /** - * Open the repository file picker. + * Update the dialogue after an image was selected in the File Picker. * - * @method open_filepicker - * @param Event e + * @method _filepickerCallback + * @param {object} params The parameters provided by the filepicker + * containing information about the image. + * @private */ - open_filepicker : function(e) { - var elementid = this.getAttribute('data-editor'); - e.preventDefault(); + _filepickerCallback: function(params) { + this.getDialogue() + .set('focusAfterHide', null) + .hide(); - M.editor_atto.show_filepicker(elementid, 'link', M.atto_link.filepicker_callback); - }, - - /** - * Called by the file picker when a link has been chosen. - * - * @method filepicker_callback - * @param {Object} params - contains selected url. - */ - filepicker_callback : function(params) { - M.atto_link.dialogue.hide(); if (params.url !== '') { - M.editor_atto.set_selection(M.atto_link.selection); + this.get('host').setSelection(this._currentSelection); document.execCommand('unlink', false, null); document.execCommand('createLink', false, params.url); } }, /** - * The OK button has been pressed - make the changes to the source. + * The link was inserted, so make changes to the editor source. * - * @method set_link - * @param Event e + * @method _setLink + * @param {EventFacade} e + * @private */ - set_link : function(e, elementid) { + _setLink: function(e) { var input, target, selectednode, anchornodes, value; - e.preventDefault(); - M.atto_link.dialogue.hide(); + var host = this.get('host'); - input = e.currentTarget.ancestor('.atto_form').one('input[type=url]'); + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + + input = this._content.one('.url'); value = input.get('value'); if (value !== '') { - M.editor_atto.set_selection(M.atto_link.selection); + this.editor.focus(); + host.setSelection(this._currentSelection); document.execCommand('unlink', false, null); document.execCommand('createLink', false, value); // Now set the target. - selectednode = M.editor_atto.get_selection_parent_node(); + selectednode = host.getSelectionParentNode(); // Note this is a document fragment and YUI doesn't like them. if (!selectednode) { return; } - anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode)); + anchornodes = this._findSelectedAnchors(Y.one(selectednode)); Y.Array.each(anchornodes, function(anchornode) { - target = e.currentTarget.ancestor('.atto_form').one('input[type=checkbox]'); + target = this._content.one('.newwindow'); if (target.get('checked')) { anchornode.setAttribute('target', '_blank'); } else { anchornode.removeAttribute('target'); } - }); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + }, this); + + this.markUpdated(); } }, /** * Look up and down for the nearest anchor tags that are least partly contained in the selection. * - * @method find_selected_anchors - * @param Node node - * @return Node|false + * @method _findSelectedAnchors + * @param {Node} node The node to search under for the selected anchor. + * @return {Node|Boolean} The Node, or false if not found. + * @private */ - find_selected_anchors : function(node) { - var tagname = node.get('tagName'), hit, hits; + _findSelectedAnchors: function(node) { + var tagname = node.get('tagName'), + hit, hits; + // Direct hit. if (tagname && tagname.toLowerCase() === 'a') { return [node]; } + // Search down but check that each node is part of the selection. hits = []; node.all('a').each(function(n) { - if (!hit && M.editor_atto.selection_contains_node(n)) { + if (!hit && this.get('host').selectionContainsNode(n)) { hits.push(n); } }); @@ -248,41 +253,30 @@ M.atto_link = M.atto_link || { }, /** - * Return the HTML of the form to show in the dialogue. + * Generates the content of the dialogue. * - * @method get_form_content - * @param string elementid - * @return string + * @method _getDialogueContent + * @return {Node} Node containing the dialogue content + * @private */ - get_form_content : function(elementid) { - var html = '
                                        ' + - '' + - '
                                        '; - if (M.editor_atto.can_show_filepicker(elementid, 'link')) { - html += '' + - '
                                        '; - } - html += '' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        '; + _getDialogueContent: function() { + var canShowFilepicker = this.get('host').canShowFilepicker('link'), + template = Y.Handlebars.compile(TEMPLATE); - var content = Y.Node.create(html); + this._content = Y.Node.create(template({ + showFilepicker: canShowFilepicker, + component: COMPONENTNAME, + CSS: CSS + })); - content.one('#atto_link_urlentrysubmit').on('click', M.atto_link.set_link, this, elementid); - if (M.editor_atto.can_show_filepicker(elementid, 'link')) { - content.one('#openlinkbrowser').on('click', M.atto_link.open_filepicker); + this._content.one('.submit').on('click', this._setLink, this); + if (canShowFilepicker) { + this._content.one('.openlinkbrowser').on('click', function(e) { + e.preventDefault(); + this.get('host').showFilepicker('link', this._filepickerCallback, this); + }, this); } - return content; + + return this._content; } -}; +}); diff --git a/lib/editor/atto/plugins/link/yui/src/button/meta/button.json b/lib/editor/atto/plugins/link/yui/src/button/meta/button.json index 41593ed2074..674df029d84 100644 --- a/lib/editor/atto/plugins/link/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/link/yui/src/button/meta/button.json @@ -1,8 +1,7 @@ { - "moodle-atto_link-button": { - "requires": [ - "node", - "escape" - ] - } + "moodle-atto_link-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/managefiles/manage.php b/lib/editor/atto/plugins/managefiles/manage.php index fe6abb6b03c..ff6922bdf56 100644 --- a/lib/editor/atto/plugins/managefiles/manage.php +++ b/lib/editor/atto/plugins/managefiles/manage.php @@ -34,6 +34,7 @@ $accepted_types = optional_param('accepted_types', '*', PARAM_RAW); // TODO Not $return_types = optional_param('return_types', null, PARAM_INT); $areamaxbytes = optional_param('areamaxbytes', FILE_AREA_MAX_BYTES_UNLIMITED, PARAM_INT); $contextid = optional_param('context', SYSCONTEXTID, PARAM_INT); +$elementid = optional_param('elementid', '', PARAM_TEXT); $context = context::instance_by_id($contextid); if ($context->contextlevel == CONTEXT_MODULE) { @@ -74,7 +75,7 @@ $options = array( 'accepted_types' => $accepted_types, 'areamaxbytes' => $areamaxbytes, 'return_types' => $return_types, - 'context' => $context + 'context' => $context, ); $usercontext = context_user::instance($USER->id); @@ -86,7 +87,7 @@ foreach ($files as $file) { } $mform = new atto_managefiles_manage_form(null, - array('options' => $options, 'draftitemid' => $itemid, 'files' => $filenames), + array('options' => $options, 'draftitemid' => $itemid, 'files' => $filenames, 'elementid' => $elementid), 'post', '', array('id' => 'atto_managefiles_manageform')); if ($data = $mform->get_data()) { @@ -102,7 +103,7 @@ if ($data = $mform->get_data()) { } $filenames = array_diff_key($filenames, $data->deletefile); $mform = new atto_managefiles_manage_form(null, - array('options' => $options, 'draftitemid' => $itemid, 'files' => $filenames), + array('options' => $options, 'draftitemid' => $itemid, 'files' => $filenames, 'elementid' => $data->elementid), 'post', '', array('id' => 'atto_managefiles_manageform')); } } diff --git a/lib/editor/atto/plugins/managefiles/manage_form.php b/lib/editor/atto/plugins/managefiles/manage_form.php index ca5ba7691c5..50bb8dd5dfa 100644 --- a/lib/editor/atto/plugins/managefiles/manage_form.php +++ b/lib/editor/atto/plugins/managefiles/manage_form.php @@ -38,12 +38,13 @@ require_once($CFG->libdir."/formslib.php"); class atto_managefiles_manage_form extends moodleform { function definition() { - global $PAGE; + global $PAGE, $USER; $mform = $this->_form; $mform->setDisableShortforms(true); $itemid = $this->_customdata['draftitemid']; + $elementid = $this->_customdata['elementid']; $options = $this->_customdata['options']; $files = $this->_customdata['files']; @@ -63,6 +64,8 @@ class atto_managefiles_manage_form extends moodleform { $mform->setType('context', PARAM_INT); $mform->addElement('hidden', 'areamaxbytes'); $mform->setType('areamaxbytes', PARAM_INT); + $mform->addElement('hidden', 'elementid'); + $mform->setType('elementid', PARAM_TEXT); $mform->addElement('filemanager', 'files_filemanager', '', null, $options); @@ -87,11 +90,17 @@ class atto_managefiles_manage_form extends moodleform { $mform->addElement('submit', 'delete', get_string('deleteselected', 'atto_managefiles')); $PAGE->requires->yui_module('moodle-atto_managefiles-usedfiles', 'M.atto_managefiles.usedfiles.init', - array(array_flip($files))); + array(array( + 'files' => array_flip($files), + 'usercontext' => context_user::instance($USER->id)->id, + 'itemid' => $itemid, + 'elementid' => $elementid, + ))); $this->set_data(array( 'files_filemanager' => $itemid, 'itemid' => $itemid, + 'elementid' => $elementid, 'subdirs' => $options['subdirs'], 'maxbytes' => $options['maxbytes'], 'areamaxbytes' => $options['areamaxbytes'], 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 9372ad7f954..59199a492cd 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 @@ -16,152 +16,117 @@ YUI.add('moodle-atto_managefiles-button', function (Y, NAME) { // along with Moodle. If not, see . /** - * Atto text editor managefiles plugin. - * * @package atto_managefiles * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_managefiles = M.atto_managefiles || { +/** + * @module moodle-atto-managefiles-button + */ + +/** + * Atto text editor managefiles plugin. + * + * @namespace M.atto_link + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +var LOGNAME = 'atto_managefiles'; + +Y.namespace('M.atto_managefiles').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The ID of the current editor. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @type {String} + * @property _currentSelection + * @type Range + * @private */ - currentElementId: null, + _currentSelection: null, - /** - * The dialogue to select a character. - * - * @type {M.core.dialogue} - */ - dialogue: null, - - /** - * The parameters for each instance of Atto. - * - * @type {Object} Where keys are the element ID of each editor. - */ - params: {}, - - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init : function(params) { - - if (params.disabled) { + initializer: function() { + if (this.get('disabled')) { return; } - // Get the itemid from the filepicker options. - if (!params.area.itemid - && M.editor_atto.filepickeroptions[params.elementid] - && M.editor_atto.filepickeroptions[params.elementid].image - && M.editor_atto.filepickeroptions[params.elementid].image.itemid) { - params.area.itemid = M.editor_atto.filepickeroptions[params.elementid].image.itemid; + var host = this.get('host'), + area = this.get('area'), + options = host.get('filepickeroptions'); + + if (options.image && options.image.itemid) { + area.itemid = options.image.itemid; + this.set('area', area); } else { - console.log('Plugin managefiles not available because itemid is missing.'); + Y.log('Plugin managefiles not available because itemid is missing.', + 'warn', LOGNAME); return; } - M.atto_managefiles.params[params.elementid] = params; - var click = function(e, elementid) { - var dialogue, - iframe; + this.addButton({ + icon: 'e/manage_files', + callback: this._displayDialogue + }); + }, - e.preventDefault(); - M.atto_managefiles.currentElementId = elementid; + /** + * Display the manage files. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function(e) { + e.preventDefault(); - // Initialising the dialogue. - if (!M.atto_managefiles.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true, - width: '800px' - }); + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('managefiles', LOGNAME), + width: '800px', + focusAfterHide: true + }); - // Setting up the basics of the dialogue. - dialogue.set('headerContent', M.util.get_string('managefiles', 'atto_managefiles')); - M.atto_managefiles.dialogue = dialogue; - dialogue.render(); - dialogue.centerDialogue(); - } else { - dialogue = M.atto_managefiles.dialogue; - } + var iframe = Y.Node.create(''); + // We set the height here because otherwise it is really small. That might not look + // very nice on mobile devices, but we considered that enough for now. + iframe.setStyles({ + height: '700px', + border: 'none', + width: '100%' + }); + iframe.setAttribute('src', this._getIframeURL()); + dialogue.set('bodyContent', iframe) + .show(); - iframe = Y.Node.create(''); - // We set the height here because otherwise it is really small. That might not look - // very nice on mobile devices, but we considered that enough for now. - iframe.setStyle('height', '700px'); - iframe.setStyle('border', 'none'); - iframe.setStyle('width', '100%'); - iframe.setAttribute('src', M.atto_managefiles.getIframeURL()); - - dialogue.set('bodyContent', iframe); - dialogue.show(); - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - // Add toolbar button. - var iconurl = M.util.image_url('e/manage_files', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'managefiles', iconurl, params.group, click); + this.markUpdated(); }, /** * Returns the URL to the file manager. * + * @param _getIframeURL * @return {String} URL + * @private */ - getIframeURL: function() { - var key, - params, - url = ''; - - url = M.cfg.wwwroot + '/lib/editor/atto/plugins/managefiles/manage.php?'; - params = M.atto_managefiles.params[M.atto_managefiles.currentElementId]; - for (key in params.area) { - url += encodeURIComponent(key) + '=' + encodeURIComponent(params.area[key]) + '&'; - } - - return url; - }, - - /** - * Return the list of files used in the area. - * - * @return {Object} List of files used where the keys are the name of the files, the value is true. - */ - getUsedFiles: function() { - var elementid = M.atto_managefiles.currentElementId, - editableNode = M.editor_atto.get_editable_node(elementid), - 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'), - filename = '', - match = '', - usedFiles = {}; - - while ((match = pattern.exec(content)) !== null) { - filename = unescape(match[1]); - usedFiles[filename] = true; - } - - return usedFiles; + _getIframeURL: function() { + var args = Y.mix({ + elementid: this.get('host').get('elementid') + }, + this.get('area')); + return M.cfg.wwwroot + '/lib/editor/atto/plugins/managefiles/manage.php?' + + Y.QueryString.stringify(args); } - -}; +}, { + ATTRS: { + disabled: { + value: true + }, + area: { + value: {} + } + } +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 8e311dd40cd..163ae3060cf 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){var n="atto_managefiles";e.namespace("M.atto_managefiles").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,initializer:function(){if(this.get("disabled"))return;var e=this.get("host"),t=this.get("area"),n=e.get("filepickeroptions");if(!n.image||!n.image.itemid)return;t.itemid=n.image.itemid,this.set("area",t),this.addButton({icon:"e/manage_files",callback:this._displayDialogue})},_displayDialogue:function(t){t.preventDefault();var r=this.getDialogue({headerContent:M.util.get_string("managefiles",n),width:"800px",focusAfterHide:!0}),i=e.Node.create("");i.setStyles({height:"700px",border:"none",width:"100%"}),i.setAttribute("src",this._getIframeURL()),r.set("bodyContent",i).show(),this.markUpdated()},_getIframeURL:function(){var t=e.mix({elementid:this.get("host").get("elementid")},this.get("area"));return M.cfg.wwwroot+"/lib/editor/atto/plugins/managefiles/manage.php?"+e.QueryString.stringify(t)}},{ATTRS:{disabled:{value:!0},area:{value:{}}}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 9372ad7f954..1434a96e9df 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 @@ -16,152 +16,115 @@ YUI.add('moodle-atto_managefiles-button', function (Y, NAME) { // along with Moodle. If not, see . /** - * Atto text editor managefiles plugin. - * * @package atto_managefiles * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_managefiles = M.atto_managefiles || { +/** + * @module moodle-atto-managefiles-button + */ + +/** + * Atto text editor managefiles plugin. + * + * @namespace M.atto_link + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +var LOGNAME = 'atto_managefiles'; + +Y.namespace('M.atto_managefiles').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The ID of the current editor. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @type {String} + * @property _currentSelection + * @type Range + * @private */ - currentElementId: null, + _currentSelection: null, - /** - * The dialogue to select a character. - * - * @type {M.core.dialogue} - */ - dialogue: null, - - /** - * The parameters for each instance of Atto. - * - * @type {Object} Where keys are the element ID of each editor. - */ - params: {}, - - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init : function(params) { - - if (params.disabled) { + initializer: function() { + if (this.get('disabled')) { return; } - // Get the itemid from the filepicker options. - if (!params.area.itemid - && M.editor_atto.filepickeroptions[params.elementid] - && M.editor_atto.filepickeroptions[params.elementid].image - && M.editor_atto.filepickeroptions[params.elementid].image.itemid) { - params.area.itemid = M.editor_atto.filepickeroptions[params.elementid].image.itemid; + var host = this.get('host'), + area = this.get('area'), + options = host.get('filepickeroptions'); + + if (options.image && options.image.itemid) { + area.itemid = options.image.itemid; + this.set('area', area); } else { - console.log('Plugin managefiles not available because itemid is missing.'); return; } - M.atto_managefiles.params[params.elementid] = params; - var click = function(e, elementid) { - var dialogue, - iframe; + this.addButton({ + icon: 'e/manage_files', + callback: this._displayDialogue + }); + }, - e.preventDefault(); - M.atto_managefiles.currentElementId = elementid; + /** + * Display the manage files. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function(e) { + e.preventDefault(); - // Initialising the dialogue. - if (!M.atto_managefiles.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true, - width: '800px' - }); + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('managefiles', LOGNAME), + width: '800px', + focusAfterHide: true + }); - // Setting up the basics of the dialogue. - dialogue.set('headerContent', M.util.get_string('managefiles', 'atto_managefiles')); - M.atto_managefiles.dialogue = dialogue; - dialogue.render(); - dialogue.centerDialogue(); - } else { - dialogue = M.atto_managefiles.dialogue; - } + var iframe = Y.Node.create(''); + // We set the height here because otherwise it is really small. That might not look + // very nice on mobile devices, but we considered that enough for now. + iframe.setStyles({ + height: '700px', + border: 'none', + width: '100%' + }); + iframe.setAttribute('src', this._getIframeURL()); + dialogue.set('bodyContent', iframe) + .show(); - iframe = Y.Node.create(''); - // We set the height here because otherwise it is really small. That might not look - // very nice on mobile devices, but we considered that enough for now. - iframe.setStyle('height', '700px'); - iframe.setStyle('border', 'none'); - iframe.setStyle('width', '100%'); - iframe.setAttribute('src', M.atto_managefiles.getIframeURL()); - - dialogue.set('bodyContent', iframe); - dialogue.show(); - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - // Add toolbar button. - var iconurl = M.util.image_url('e/manage_files', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'managefiles', iconurl, params.group, click); + this.markUpdated(); }, /** * Returns the URL to the file manager. * + * @param _getIframeURL * @return {String} URL + * @private */ - getIframeURL: function() { - var key, - params, - url = ''; - - url = M.cfg.wwwroot + '/lib/editor/atto/plugins/managefiles/manage.php?'; - params = M.atto_managefiles.params[M.atto_managefiles.currentElementId]; - for (key in params.area) { - url += encodeURIComponent(key) + '=' + encodeURIComponent(params.area[key]) + '&'; - } - - return url; - }, - - /** - * Return the list of files used in the area. - * - * @return {Object} List of files used where the keys are the name of the files, the value is true. - */ - getUsedFiles: function() { - var elementid = M.atto_managefiles.currentElementId, - editableNode = M.editor_atto.get_editable_node(elementid), - 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'), - filename = '', - match = '', - usedFiles = {}; - - while ((match = pattern.exec(content)) !== null) { - filename = unescape(match[1]); - usedFiles[filename] = true; - } - - return usedFiles; + _getIframeURL: function() { + var args = Y.mix({ + elementid: this.get('host').get('elementid') + }, + this.get('area')); + return M.cfg.wwwroot + '/lib/editor/atto/plugins/managefiles/manage.php?' + + Y.QueryString.stringify(args); } - -}; +}, { + ATTRS: { + disabled: { + value: true + }, + area: { + value: {} + } + } +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles-debug.js b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles-debug.js index e05492a2c94..69a36956b5f 100644 --- a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles-debug.js +++ b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles-debug.js @@ -16,13 +16,23 @@ YUI.add('moodle-atto_managefiles-usedfiles', function (Y, NAME) { // along with Moodle. If not, see . /** - * Atto text editor managefiles usedfiles plugin. - * * @package atto_managefiles * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +/** + * @module moodle-atto_managefiles-usedfiles + */ + + +/** + * Atto text editor managefiles usedfiles plugin. + * + * @namespace M.atto_managefiles + * @class usedfiles + */ + /** * CSS constants. * @@ -47,26 +57,58 @@ var SELECTORS = { M.atto_managefiles = M.atto_managefiles || {}; M.atto_managefiles.usedfiles = M.atto_managefiles.usedfiles || { + /** + * The user context. + * + * @property _usercontext + * @type Number + * @private + */ + _usercontext: null, + + /** + * Area Item ID. + * + * @property _itemid + * @type String + * @private + */ + _itemid: null, + + /** + * The editor elementid + * + * @property _elementid + * @type String + * @private + */ + _elementid: null, + /** * Init function. * * @param {Object} allFiles The keys are the file names, the values are the hashes. * @return {Void} */ - init: function(allFiles) { + init: function(config) { + this._usercontext = config.usercontext; + this._itemid = config.itemid; + this._elementid = config.elementid; + + var allFiles = config.files; var form = Y.one(SELECTORS.FORM), usedFiles, missingFilesTxt, i; - if (!form || !window.parent - || !window.parent.M.atto_managefiles) { + if (!form || !window.parent) { + Y.log("Unable to find parent window", 'warn', 'moodle-atto_managemedia-usedfiles'); return; } - usedFiles = window.parent.M.atto_managefiles.getUsedFiles(); - unusedFiles = M.atto_managefiles.usedfiles.findUnusedFiles(allFiles, usedFiles); - missingFiles = M.atto_managefiles.usedfiles.findMissingFiles(allFiles, usedFiles); + usedFiles = this._getUsedFiles(); + unusedFiles = this.findUnusedFiles(allFiles, usedFiles); + missingFiles = this.findMissingFiles(allFiles, usedFiles); // There are some unused files. if (unusedFiles.length > 0) { @@ -97,6 +139,29 @@ M.atto_managefiles.usedfiles = M.atto_managefiles.usedfiles || { } }, + /** + * Return the list of files used in the area. + * + * @method _getUsedFiles + * @return {Object} List of files used where the keys are the name of the files, the value is true. + * @private + */ + _getUsedFiles: function() { + var content = Y.one(window.parent.document.getElementById(this._elementid + 'editable')), + baseUrl = M.cfg.wwwroot + '/draftfile.php/' + this._usercontext + '/user/draft/' + this._itemid + '/', + pattern = new RegExp(baseUrl.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g, '\\$&') + "(.+?)[\\?\"']", 'gm'), + filename = '', + match = '', + usedFiles = {}; + + while ((match = pattern.exec(content.get('innerHTML'))) !== null) { + filename = unescape(match[1]); + usedFiles[filename] = true; + } + + return usedFiles; + }, + /** * Return an array of unused files. * diff --git a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles-min.js b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles-min.js index fce7798e301..3894cba602b 100644 --- a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles-min.js +++ b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_managefiles-usedfiles",function(e,t){var n={HASMISSINGFILES:"has-missing-files",HASUNUSEDFILES:"has-unused-files"},r={FILEANCESTOR:".fitem_fcheckbox",FORM:"#atto_managefiles_manageform",MISSINGFILES:".missing-files"};M.atto_managefiles=M.atto_managefiles||{},M.atto_managefiles.usedfiles=M.atto_managefiles.usedfiles||{init:function(t){var i=e.one(r.FORM),s,o,u;if(!i||!window.parent||!window.parent.M.atto_managefiles)return;s=window.parent.M.atto_managefiles.getUsedFiles(),unusedFiles=M.atto_managefiles.usedfiles.findUnusedFiles(t,s),missingFiles=M.atto_managefiles.usedfiles.findMissingFiles(t,s),unusedFiles.length>0?(i.all('input[type=checkbox][name^="deletefile"]').each(function(t){e.Array.indexOf(unusedFiles,t.getData("filename"))===-1&&t.ancestor(r.FILEANCESTOR).remove()}),i.addClass(n.HASUNUSEDFILES)):i.removeClass(n.HASUNUSEDFILES);if(missingFiles.length>0){o="
                                          ";for(u=0;u"+e.Escape.html(missingFiles[u])+"";o+="
                                        ",i.one(r.MISSINGFILES).setHTML("").append(o),i.addClass(n.HASMISSINGFILES)}else i.removeClass(n.HASMISSINGFILES)},findUnusedFiles:function(e,t){var n,r=[];for(n in e)t[n]||r.push(n);return r},findMissingFiles:function(e,t){var n,r=[];for(n in t)e[n]||r.push(n);return r}}},"@VERSION@",{requires:["node","escape"]}); +YUI.add("moodle-atto_managefiles-usedfiles",function(e,t){var n={HASMISSINGFILES:"has-missing-files",HASUNUSEDFILES:"has-unused-files"},r={FILEANCESTOR:".fitem_fcheckbox",FORM:"#atto_managefiles_manageform",MISSINGFILES:".missing-files"};M.atto_managefiles=M.atto_managefiles||{},M.atto_managefiles.usedfiles=M.atto_managefiles.usedfiles||{_usercontext:null,_itemid:null,_elementid:null,init:function(t){this._usercontext=t.usercontext,this._itemid=t.itemid,this._elementid=t.elementid;var i=t.files,s=e.one(r.FORM),o,u,a;if(!s||!window.parent)return;o=this._getUsedFiles(),unusedFiles=this.findUnusedFiles(i,o),missingFiles=this.findMissingFiles(i,o),unusedFiles.length>0?(s.all('input[type=checkbox][name^="deletefile"]').each(function(t){e.Array.indexOf(unusedFiles,t.getData("filename"))===-1&&t.ancestor(r.FILEANCESTOR).remove()}),s.addClass(n.HASUNUSEDFILES)):s.removeClass(n.HASUNUSEDFILES);if(missingFiles.length>0){u="
                                          ";for(a=0;a"+e.Escape.html(missingFiles[a])+"";u+="
                                        ",s.one(r.MISSINGFILES).setHTML("").append(u),s.addClass(n.HASMISSINGFILES)}else s.removeClass(n.HASMISSINGFILES)},_getUsedFiles:function(){var t=e.one(window.parent.document.getElementById(this._elementid+"editable")),n=M.cfg.wwwroot+"/draftfile.php/"+this._usercontext+"/user/draft/"+this._itemid+"/",r=new RegExp(n.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g,"\\$&")+"(.+?)[\\?\"']","gm"),i="",s="",o={};while((s=r.exec(t.get("innerHTML")))!==null)i=unescape(s[1]),o[i]=!0;return o},findUnusedFiles:function(e,t){var n,r=[];for(n in e)t[n]||r.push(n);return r},findMissingFiles:function(e,t){var n,r=[];for(n in t)e[n]||r.push(n);return r}}},"@VERSION@",{requires:["node","escape"]}); diff --git a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles.js b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles.js index e05492a2c94..30447d6c85b 100644 --- a/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles.js +++ b/lib/editor/atto/plugins/managefiles/yui/build/moodle-atto_managefiles-usedfiles/moodle-atto_managefiles-usedfiles.js @@ -16,13 +16,23 @@ YUI.add('moodle-atto_managefiles-usedfiles', function (Y, NAME) { // along with Moodle. If not, see . /** - * Atto text editor managefiles usedfiles plugin. - * * @package atto_managefiles * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +/** + * @module moodle-atto_managefiles-usedfiles + */ + + +/** + * Atto text editor managefiles usedfiles plugin. + * + * @namespace M.atto_managefiles + * @class usedfiles + */ + /** * CSS constants. * @@ -47,26 +57,57 @@ var SELECTORS = { M.atto_managefiles = M.atto_managefiles || {}; M.atto_managefiles.usedfiles = M.atto_managefiles.usedfiles || { + /** + * The user context. + * + * @property _usercontext + * @type Number + * @private + */ + _usercontext: null, + + /** + * Area Item ID. + * + * @property _itemid + * @type String + * @private + */ + _itemid: null, + + /** + * The editor elementid + * + * @property _elementid + * @type String + * @private + */ + _elementid: null, + /** * Init function. * * @param {Object} allFiles The keys are the file names, the values are the hashes. * @return {Void} */ - init: function(allFiles) { + init: function(config) { + this._usercontext = config.usercontext; + this._itemid = config.itemid; + this._elementid = config.elementid; + + var allFiles = config.files; var form = Y.one(SELECTORS.FORM), usedFiles, missingFilesTxt, i; - if (!form || !window.parent - || !window.parent.M.atto_managefiles) { + if (!form || !window.parent) { return; } - usedFiles = window.parent.M.atto_managefiles.getUsedFiles(); - unusedFiles = M.atto_managefiles.usedfiles.findUnusedFiles(allFiles, usedFiles); - missingFiles = M.atto_managefiles.usedfiles.findMissingFiles(allFiles, usedFiles); + usedFiles = this._getUsedFiles(); + unusedFiles = this.findUnusedFiles(allFiles, usedFiles); + missingFiles = this.findMissingFiles(allFiles, usedFiles); // There are some unused files. if (unusedFiles.length > 0) { @@ -97,6 +138,29 @@ M.atto_managefiles.usedfiles = M.atto_managefiles.usedfiles || { } }, + /** + * Return the list of files used in the area. + * + * @method _getUsedFiles + * @return {Object} List of files used where the keys are the name of the files, the value is true. + * @private + */ + _getUsedFiles: function() { + var content = Y.one(window.parent.document.getElementById(this._elementid + 'editable')), + baseUrl = M.cfg.wwwroot + '/draftfile.php/' + this._usercontext + '/user/draft/' + this._itemid + '/', + pattern = new RegExp(baseUrl.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g, '\\$&') + "(.+?)[\\?\"']", 'gm'), + filename = '', + match = '', + usedFiles = {}; + + while ((match = pattern.exec(content.get('innerHTML'))) !== null) { + filename = unescape(match[1]); + usedFiles[filename] = true; + } + + return usedFiles; + }, + /** * Return an array of unused files. * diff --git a/lib/editor/atto/plugins/managefiles/yui/src/button/build.json b/lib/editor/atto/plugins/managefiles/yui/src/button/build.json index 072e7ba922e..b56a9756793 100644 --- a/lib/editor/atto/plugins/managefiles/yui/src/button/build.json +++ b/lib/editor/atto/plugins/managefiles/yui/src/button/build.json @@ -1,15 +1,10 @@ { - "name": "moodle-atto_managefiles-button", - "builds": { - "moodle-atto_managefiles-button": { - "jsfiles": [ - "button.js" - ] - }, - "moodle-atto_managefiles-usedfiles": { - "jsfiles": [ - "usedfiles.js" - ] + "name": "moodle-atto_managefiles-button", + "builds": { + "moodle-atto_managefiles-button": { + "jsfiles": [ + "button.js" + ] + } } - } } 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 c7c914fcd06..3ba25e56f79 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 @@ -14,149 +14,114 @@ // along with Moodle. If not, see . /** - * Atto text editor managefiles plugin. - * * @package atto_managefiles * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_managefiles = M.atto_managefiles || { +/** + * @module moodle-atto-managefiles-button + */ + +/** + * Atto text editor managefiles plugin. + * + * @namespace M.atto_link + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +var LOGNAME = 'atto_managefiles'; + +Y.namespace('M.atto_managefiles').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The ID of the current editor. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @type {String} + * @property _currentSelection + * @type Range + * @private */ - currentElementId: null, + _currentSelection: null, - /** - * The dialogue to select a character. - * - * @type {M.core.dialogue} - */ - dialogue: null, - - /** - * The parameters for each instance of Atto. - * - * @type {Object} Where keys are the element ID of each editor. - */ - params: {}, - - /** - * Init. - * - * @param {Object} params - * - * @return {Void} - */ - init : function(params) { - - if (params.disabled) { + initializer: function() { + if (this.get('disabled')) { return; } - // Get the itemid from the filepicker options. - if (!params.area.itemid - && M.editor_atto.filepickeroptions[params.elementid] - && M.editor_atto.filepickeroptions[params.elementid].image - && M.editor_atto.filepickeroptions[params.elementid].image.itemid) { - params.area.itemid = M.editor_atto.filepickeroptions[params.elementid].image.itemid; + var host = this.get('host'), + area = this.get('area'), + options = host.get('filepickeroptions'); + + if (options.image && options.image.itemid) { + area.itemid = options.image.itemid; + this.set('area', area); } else { - console.log('Plugin managefiles not available because itemid is missing.'); + Y.log('Plugin managefiles not available because itemid is missing.', + 'warn', LOGNAME); return; } - M.atto_managefiles.params[params.elementid] = params; - var click = function(e, elementid) { - var dialogue, - iframe; + this.addButton({ + icon: 'e/manage_files', + callback: this._displayDialogue + }); + }, - e.preventDefault(); - M.atto_managefiles.currentElementId = elementid; + /** + * Display the manage files. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function(e) { + e.preventDefault(); - // Initialising the dialogue. - if (!M.atto_managefiles.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true, - width: '800px' - }); + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('managefiles', LOGNAME), + width: '800px', + focusAfterHide: true + }); - // Setting up the basics of the dialogue. - dialogue.set('headerContent', M.util.get_string('managefiles', 'atto_managefiles')); - M.atto_managefiles.dialogue = dialogue; - dialogue.render(); - dialogue.centerDialogue(); - } else { - dialogue = M.atto_managefiles.dialogue; - } + var iframe = Y.Node.create(''); + // We set the height here because otherwise it is really small. That might not look + // very nice on mobile devices, but we considered that enough for now. + iframe.setStyles({ + height: '700px', + border: 'none', + width: '100%' + }); + iframe.setAttribute('src', this._getIframeURL()); + dialogue.set('bodyContent', iframe) + .show(); - iframe = Y.Node.create(''); - // We set the height here because otherwise it is really small. That might not look - // very nice on mobile devices, but we considered that enough for now. - iframe.setStyle('height', '700px'); - iframe.setStyle('border', 'none'); - iframe.setStyle('width', '100%'); - iframe.setAttribute('src', M.atto_managefiles.getIframeURL()); - - dialogue.set('bodyContent', iframe); - dialogue.show(); - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - // Add toolbar button. - var iconurl = M.util.image_url('e/manage_files', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'managefiles', iconurl, params.group, click); + this.markUpdated(); }, /** * Returns the URL to the file manager. * + * @param _getIframeURL * @return {String} URL + * @private */ - getIframeURL: function() { - var key, - params, - url = ''; - - url = M.cfg.wwwroot + '/lib/editor/atto/plugins/managefiles/manage.php?'; - params = M.atto_managefiles.params[M.atto_managefiles.currentElementId]; - for (key in params.area) { - url += encodeURIComponent(key) + '=' + encodeURIComponent(params.area[key]) + '&'; - } - - return url; - }, - - /** - * Return the list of files used in the area. - * - * @return {Object} List of files used where the keys are the name of the files, the value is true. - */ - getUsedFiles: function() { - var elementid = M.atto_managefiles.currentElementId, - editableNode = M.editor_atto.get_editable_node(elementid), - 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'), - filename = '', - match = '', - usedFiles = {}; - - while ((match = pattern.exec(content)) !== null) { - filename = unescape(match[1]); - usedFiles[filename] = true; - } - - return usedFiles; + _getIframeURL: function() { + var args = Y.mix({ + elementid: this.get('host').get('elementid') + }, + this.get('area')); + return M.cfg.wwwroot + '/lib/editor/atto/plugins/managefiles/manage.php?' + + Y.QueryString.stringify(args); } - -}; +}, { + ATTRS: { + disabled: { + value: true + }, + area: { + value: {} + } + } +}); diff --git a/lib/editor/atto/plugins/managefiles/yui/src/button/meta/button.json b/lib/editor/atto/plugins/managefiles/yui/src/button/meta/button.json index 693c9e2bc19..2ae29850f11 100644 --- a/lib/editor/atto/plugins/managefiles/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/managefiles/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_managefiles-button": { - "requires": ["node"] - } + "moodle-atto_managefiles-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/managefiles/yui/src/button/meta/usedfiles.json b/lib/editor/atto/plugins/managefiles/yui/src/button/meta/usedfiles.json deleted file mode 100644 index bc6d7e011d3..00000000000 --- a/lib/editor/atto/plugins/managefiles/yui/src/button/meta/usedfiles.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "moodle-atto_managefiles-usedfiles": { - "requires": ["node", "escape"] - } -} diff --git a/lib/editor/atto/plugins/managefiles/yui/src/usedfiles/build.json b/lib/editor/atto/plugins/managefiles/yui/src/usedfiles/build.json new file mode 100644 index 00000000000..d4ec929f4d5 --- /dev/null +++ b/lib/editor/atto/plugins/managefiles/yui/src/usedfiles/build.json @@ -0,0 +1,10 @@ +{ + "name": "moodle-atto_managefiles-usedfiles", + "builds": { + "moodle-atto_managefiles-usedfiles": { + "jsfiles": [ + "usedfiles.js" + ] + } + } +} diff --git a/lib/editor/atto/plugins/managefiles/yui/src/button/js/usedfiles.js b/lib/editor/atto/plugins/managefiles/yui/src/usedfiles/js/usedfiles.js similarity index 66% rename from lib/editor/atto/plugins/managefiles/yui/src/button/js/usedfiles.js rename to lib/editor/atto/plugins/managefiles/yui/src/usedfiles/js/usedfiles.js index 47de626aed7..79bfc2f8c32 100644 --- a/lib/editor/atto/plugins/managefiles/yui/src/button/js/usedfiles.js +++ b/lib/editor/atto/plugins/managefiles/yui/src/usedfiles/js/usedfiles.js @@ -14,13 +14,23 @@ // along with Moodle. If not, see . /** - * Atto text editor managefiles usedfiles plugin. - * * @package atto_managefiles * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +/** + * @module moodle-atto_managefiles-usedfiles + */ + + +/** + * Atto text editor managefiles usedfiles plugin. + * + * @namespace M.atto_managefiles + * @class usedfiles + */ + /** * CSS constants. * @@ -45,26 +55,58 @@ var SELECTORS = { M.atto_managefiles = M.atto_managefiles || {}; M.atto_managefiles.usedfiles = M.atto_managefiles.usedfiles || { + /** + * The user context. + * + * @property _usercontext + * @type Number + * @private + */ + _usercontext: null, + + /** + * Area Item ID. + * + * @property _itemid + * @type String + * @private + */ + _itemid: null, + + /** + * The editor elementid + * + * @property _elementid + * @type String + * @private + */ + _elementid: null, + /** * Init function. * * @param {Object} allFiles The keys are the file names, the values are the hashes. * @return {Void} */ - init: function(allFiles) { + init: function(config) { + this._usercontext = config.usercontext; + this._itemid = config.itemid; + this._elementid = config.elementid; + + var allFiles = config.files; var form = Y.one(SELECTORS.FORM), usedFiles, missingFilesTxt, i; - if (!form || !window.parent - || !window.parent.M.atto_managefiles) { + if (!form || !window.parent) { + Y.log("Unable to find parent window", 'warn', 'moodle-atto_managemedia-usedfiles'); return; } - usedFiles = window.parent.M.atto_managefiles.getUsedFiles(); - unusedFiles = M.atto_managefiles.usedfiles.findUnusedFiles(allFiles, usedFiles); - missingFiles = M.atto_managefiles.usedfiles.findMissingFiles(allFiles, usedFiles); + usedFiles = this._getUsedFiles(); + unusedFiles = this.findUnusedFiles(allFiles, usedFiles); + missingFiles = this.findMissingFiles(allFiles, usedFiles); // There are some unused files. if (unusedFiles.length > 0) { @@ -95,6 +137,29 @@ M.atto_managefiles.usedfiles = M.atto_managefiles.usedfiles || { } }, + /** + * Return the list of files used in the area. + * + * @method _getUsedFiles + * @return {Object} List of files used where the keys are the name of the files, the value is true. + * @private + */ + _getUsedFiles: function() { + var content = Y.one(window.parent.document.getElementById(this._elementid + 'editable')), + baseUrl = M.cfg.wwwroot + '/draftfile.php/' + this._usercontext + '/user/draft/' + this._itemid + '/', + pattern = new RegExp(baseUrl.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g, '\\$&') + "(.+?)[\\?\"']", 'gm'), + filename = '', + match = '', + usedFiles = {}; + + while ((match = pattern.exec(content.get('innerHTML'))) !== null) { + filename = unescape(match[1]); + usedFiles[filename] = true; + } + + return usedFiles; + }, + /** * Return an array of unused files. * diff --git a/lib/editor/atto/plugins/managefiles/yui/src/usedfiles/meta/usedfiles.json b/lib/editor/atto/plugins/managefiles/yui/src/usedfiles/meta/usedfiles.json new file mode 100644 index 00000000000..089a2e80dee --- /dev/null +++ b/lib/editor/atto/plugins/managefiles/yui/src/usedfiles/meta/usedfiles.json @@ -0,0 +1,8 @@ +{ + "moodle-atto_managefiles-usedfiles": { + "requires": [ + "node", + "escape" + ] + } +} diff --git a/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-debug.js b/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-debug.js index 29c8ea89beb..dba9b7cf04b 100644 --- a/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-debug.js +++ b/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-debug.js @@ -15,110 +15,158 @@ YUI.add('moodle-atto_media-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor media plugin. - * - * @package editor-atto +/* + * @package atto_media * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_media = M.atto_media || { - dialogue : null, - selection : null, - init : function(params) { - if (!M.editor_atto.can_show_filepicker(params.elementid, 'media')) { - // Do not show this button if we can't browse repositories. +/** + * @module moodle-atto_media-button + */ + +/** + * Atto media selection tool. + * + * @namespace M.atto_media + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENTNAME = 'atto_media', + TEMPLATE = '' + + '
                                        ' + + '' + + '
                                        ' + + '' + + '' + + '' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        '; + +Y.namespace('M.atto_media').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + + /** + * A reference to the current selection at the time that the dialogue + * was opened. + * + * @property _currentSelection + * @type Range + * @private + */ + _currentSelection: null, + + /** + * A reference to the dialogue content. + * + * @property _content + * @type Node + * @private + */ + _content: null, + + initializer: function() { + this.addButton({ + icon: 'e/insert_edit_video', + callback: this._displayDialogue + }); + }, + + /** + * Display the media editing tool. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { return; } - var display_chooser = function(e, elementid) { + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createmedia', COMPONENTNAME), + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @return {Node} The content to place in the dialogue. + * @private + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE); + + this._content = Y.Node.create(template({ + component: COMPONENTNAME, + elementid: this.get('host').get('elementid') + })); + + this._content.one('.submit').on('click', this._setMedia, this); + this._content.one('.openmediabrowser').on('click', function(e) { e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_media.selection = M.editor_atto.get_selection(); - if (M.atto_media.selection !== false) { - var dialogue; - if (!M.atto_media.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_media.dialogue; - } + this.get('host').showFilepicker('media', this._filepickerCallback, this); + }, this); - dialogue.render(); - dialogue.set('bodyContent', M.atto_media.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createmedia', 'atto_media')); - dialogue.centerDialogue(); - dialogue.show(); - M.atto_media.dialogue = dialogue; - } - }; - - var iconurl = M.util.image_url('e/insert_edit_video', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'media', iconurl, params.group, display_chooser); + return this._content; }, - open_browser : function(e) { - var elementid = this.getAttribute('data-editor'); - e.preventDefault(); - M.editor_atto.show_filepicker(elementid, 'media', M.atto_media.filepicker_callback); - }, - filepicker_callback : function(params) { + /** + * Update the dialogue after an media was selected in the File Picker. + * + * @method _filepickerCallback + * @param {object} params The parameters provided by the filepicker + * containing information about the image. + * @private + */ + _filepickerCallback: function(params) { if (params.url !== '') { - var input = Y.one('#atto_media_urlentry'); - input.set('value', params.url); - input = Y.one('#atto_media_nameentry'); - input.set('value', params.file); + this._content.one('.urlentry') + .set('value', params.url); + this._content.one('.nameentry') + .set('value', params.file); } }, - set_media : function(e, elementid) { - e.preventDefault(); - M.atto_media.dialogue.hide(); - var input = e.currentTarget.ancestor('.atto_form').one('#atto_media_urlentry'); - var url = input.get('value'); - input = e.currentTarget.ancestor('.atto_form').one('#atto_media_nameentry'); - var name = input.get('value'); + /** + * Update the media in the contenteditable. + * + * @method setMedia + * @param {EventFacade} e + * @private + */ + _setMedia: function(e) { + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + + var form = e.currentTarget.ancestor('.atto_form'), + url = form.one('.urlentry').get('value'), + name = form.one('.nameentry').get('value'), + host = this.get('host'); if (url !== '' && name !== '') { - M.editor_atto.set_selection(M.atto_media.selection); + host.setSelection(this._currentSelection); var mediahtml = '' + name + ''; - M.editor_atto.insert_html_at_focus_point(mediahtml); - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + host.insertContentAtFocusPoint(mediahtml); + this.markUpdated(); } - }, - get_form_content : function(elementid) { - var content = Y.Node.create('
                                        ' + - '' + - '
                                        ' + - '' + - '' + - '' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        '); - - content.one('#atto_media_urlentrysubmit').on('click', M.atto_media.set_media, this, elementid); - content.one('#openmediabrowser').on('click', M.atto_media.open_browser); - return content; } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-min.js b/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-min.js index 3155c49bbb3..55b6e5e6b36 100644 --- a/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-min.js +++ b/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_media-button",function(e,t){M.atto_media=M.atto_media||{dialogue:null,selection:null,init:function(e){if(!M.editor_atto.can_show_filepicker(e.elementid,"media"))return;var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_media.selection=M.editor_atto.get_selection();if(M.atto_media.selection!==!1){var n;M.atto_media.dialogue?n=M.atto_media.dialogue:n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.render(),n.set("bodyContent",M.atto_media.get_form_content(t)),n.set("headerContent",M.util.get_string("createmedia","atto_media")),n.centerDialogue(),n.show(),M.atto_media.dialogue=n}},n=M.util.image_url("e/insert_edit_video","core");M.editor_atto.add_toolbar_button(e.elementid,"media",n,e.group,t)},open_browser:function(e){var t=this.getAttribute("data-editor");e.preventDefault(),M.editor_atto.show_filepicker(t,"media",M.atto_media.filepicker_callback)},filepicker_callback:function(t){if(t.url!==""){var n=e.one("#atto_media_urlentry");n.set("value",t.url),n=e.one("#atto_media_nameentry"),n.set("value",t.file)}},set_media:function(t,n){t.preventDefault(),M.atto_media.dialogue.hide();var r=t.currentTarget.ancestor(".atto_form").one("#atto_media_urlentry"),i=r.get("value");r=t.currentTarget.ancestor(".atto_form").one("#atto_media_nameentry");var s=r.get("value");if(i!==""&&s!==""){M.editor_atto.set_selection(M.atto_media.selection);var o=''+s+"";M.editor_atto.insert_html_at_focus_point(o),M.editor_atto.text_updated(n)}},get_form_content:function(t){var n=e.Node.create('
                                        "+'
                                        '+'"+'"+''+'
                                        '+"
                                        "+'"+"
                                        "+"
                                        ");return n.one("#atto_media_urlentrysubmit").on("click",M.atto_media.set_media,this,t),n.one("#openmediabrowser").on("click",M.atto_media.open_browser),n}}},"@VERSION@",{requires:["node","escape"]}); +YUI.add("moodle-atto_media-button",function(e,t){var n="atto_media",r='


                                        ';e.namespace("M.atto_media").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,_content:null,initializer:function(){this.addButton({icon:"e/insert_edit_video",callback:this._displayDialogue})},_displayDialogue:function(){this._currentSelection=this.get("host").getSelection();if(this._currentSelection===!1)return;var e=this.getDialogue({headerContent:M.util.get_string("createmedia",n),focusAfterHide:!0});e.set("bodyContent",this._getDialogueContent()).show()},_getDialogueContent:function(){var t=e.Handlebars.compile(r);return this._content=e.Node.create(t({component:n,elementid:this.get("host").get("elementid")})),this._content.one(".submit").on("click",this._setMedia,this),this._content.one(".openmediabrowser").on("click",function(e){e.preventDefault(),this.get("host").showFilepicker("media",this._filepickerCallback,this)},this),this._content},_filepickerCallback:function(e){e.url!==""&&(this._content.one(".urlentry").set("value",e.url),this._content.one(".nameentry").set("value",e.file))},_setMedia:function(t){t.preventDefault(),this.getDialogue({focusAfterHide:null}).hide();var n=t.currentTarget.ancestor(".atto_form"),r=n.one(".urlentry").get("value"),i=n.one(".nameentry").get("value"),s=this.get("host");if(r!==""&&i!==""){s.setSelection(this._currentSelection);var o=''+i+"";s.insertContentAtFocusPoint(o),this.markUpdated()}}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button.js b/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button.js index 29c8ea89beb..dba9b7cf04b 100644 --- a/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button.js +++ b/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button.js @@ -15,110 +15,158 @@ YUI.add('moodle-atto_media-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor media plugin. - * - * @package editor-atto +/* + * @package atto_media * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_media = M.atto_media || { - dialogue : null, - selection : null, - init : function(params) { - if (!M.editor_atto.can_show_filepicker(params.elementid, 'media')) { - // Do not show this button if we can't browse repositories. +/** + * @module moodle-atto_media-button + */ + +/** + * Atto media selection tool. + * + * @namespace M.atto_media + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENTNAME = 'atto_media', + TEMPLATE = '' + + '
                                        ' + + '' + + '
                                        ' + + '' + + '' + + '' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        '; + +Y.namespace('M.atto_media').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + + /** + * A reference to the current selection at the time that the dialogue + * was opened. + * + * @property _currentSelection + * @type Range + * @private + */ + _currentSelection: null, + + /** + * A reference to the dialogue content. + * + * @property _content + * @type Node + * @private + */ + _content: null, + + initializer: function() { + this.addButton({ + icon: 'e/insert_edit_video', + callback: this._displayDialogue + }); + }, + + /** + * Display the media editing tool. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { return; } - var display_chooser = function(e, elementid) { + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createmedia', COMPONENTNAME), + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @return {Node} The content to place in the dialogue. + * @private + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE); + + this._content = Y.Node.create(template({ + component: COMPONENTNAME, + elementid: this.get('host').get('elementid') + })); + + this._content.one('.submit').on('click', this._setMedia, this); + this._content.one('.openmediabrowser').on('click', function(e) { e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_media.selection = M.editor_atto.get_selection(); - if (M.atto_media.selection !== false) { - var dialogue; - if (!M.atto_media.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_media.dialogue; - } + this.get('host').showFilepicker('media', this._filepickerCallback, this); + }, this); - dialogue.render(); - dialogue.set('bodyContent', M.atto_media.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createmedia', 'atto_media')); - dialogue.centerDialogue(); - dialogue.show(); - M.atto_media.dialogue = dialogue; - } - }; - - var iconurl = M.util.image_url('e/insert_edit_video', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'media', iconurl, params.group, display_chooser); + return this._content; }, - open_browser : function(e) { - var elementid = this.getAttribute('data-editor'); - e.preventDefault(); - M.editor_atto.show_filepicker(elementid, 'media', M.atto_media.filepicker_callback); - }, - filepicker_callback : function(params) { + /** + * Update the dialogue after an media was selected in the File Picker. + * + * @method _filepickerCallback + * @param {object} params The parameters provided by the filepicker + * containing information about the image. + * @private + */ + _filepickerCallback: function(params) { if (params.url !== '') { - var input = Y.one('#atto_media_urlentry'); - input.set('value', params.url); - input = Y.one('#atto_media_nameentry'); - input.set('value', params.file); + this._content.one('.urlentry') + .set('value', params.url); + this._content.one('.nameentry') + .set('value', params.file); } }, - set_media : function(e, elementid) { - e.preventDefault(); - M.atto_media.dialogue.hide(); - var input = e.currentTarget.ancestor('.atto_form').one('#atto_media_urlentry'); - var url = input.get('value'); - input = e.currentTarget.ancestor('.atto_form').one('#atto_media_nameentry'); - var name = input.get('value'); + /** + * Update the media in the contenteditable. + * + * @method setMedia + * @param {EventFacade} e + * @private + */ + _setMedia: function(e) { + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + + var form = e.currentTarget.ancestor('.atto_form'), + url = form.one('.urlentry').get('value'), + name = form.one('.nameentry').get('value'), + host = this.get('host'); if (url !== '' && name !== '') { - M.editor_atto.set_selection(M.atto_media.selection); + host.setSelection(this._currentSelection); var mediahtml = '' + name + ''; - M.editor_atto.insert_html_at_focus_point(mediahtml); - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + host.insertContentAtFocusPoint(mediahtml); + this.markUpdated(); } - }, - get_form_content : function(elementid) { - var content = Y.Node.create('
                                        ' + - '' + - '
                                        ' + - '' + - '' + - '' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        '); - - content.one('#atto_media_urlentrysubmit').on('click', M.atto_media.set_media, this, elementid); - content.one('#openmediabrowser').on('click', M.atto_media.open_browser); - return content; } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/media/yui/src/button/js/button.js b/lib/editor/atto/plugins/media/yui/src/button/js/button.js index 2faa0a27cd2..0738fb2fa13 100644 --- a/lib/editor/atto/plugins/media/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/media/yui/src/button/js/button.js @@ -13,107 +13,155 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor media plugin. - * - * @package editor-atto +/* + * @package atto_media * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_media = M.atto_media || { - dialogue : null, - selection : null, - init : function(params) { - if (!M.editor_atto.can_show_filepicker(params.elementid, 'media')) { - // Do not show this button if we can't browse repositories. +/** + * @module moodle-atto_media-button + */ + +/** + * Atto media selection tool. + * + * @namespace M.atto_media + * @class Button + * @extends M.editor_atto.EditorPlugin + */ + +var COMPONENTNAME = 'atto_media', + TEMPLATE = '' + + '
                                        ' + + '' + + '
                                        ' + + '' + + '' + + '' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        '; + +Y.namespace('M.atto_media').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + + /** + * A reference to the current selection at the time that the dialogue + * was opened. + * + * @property _currentSelection + * @type Range + * @private + */ + _currentSelection: null, + + /** + * A reference to the dialogue content. + * + * @property _content + * @type Node + * @private + */ + _content: null, + + initializer: function() { + this.addButton({ + icon: 'e/insert_edit_video', + callback: this._displayDialogue + }); + }, + + /** + * Display the media editing tool. + * + * @method _displayDialogue + * @private + */ + _displayDialogue: function() { + // Store the current selection. + this._currentSelection = this.get('host').getSelection(); + if (this._currentSelection === false) { return; } - var display_chooser = function(e, elementid) { + + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createmedia', COMPONENTNAME), + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @return {Node} The content to place in the dialogue. + * @private + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE); + + this._content = Y.Node.create(template({ + component: COMPONENTNAME, + elementid: this.get('host').get('elementid') + })); + + this._content.one('.submit').on('click', this._setMedia, this); + this._content.one('.openmediabrowser').on('click', function(e) { e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_media.selection = M.editor_atto.get_selection(); - if (M.atto_media.selection !== false) { - var dialogue; - if (!M.atto_media.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_media.dialogue; - } + this.get('host').showFilepicker('media', this._filepickerCallback, this); + }, this); - dialogue.render(); - dialogue.set('bodyContent', M.atto_media.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createmedia', 'atto_media')); - dialogue.centerDialogue(); - dialogue.show(); - M.atto_media.dialogue = dialogue; - } - }; - - var iconurl = M.util.image_url('e/insert_edit_video', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'media', iconurl, params.group, display_chooser); + return this._content; }, - open_browser : function(e) { - var elementid = this.getAttribute('data-editor'); - e.preventDefault(); - M.editor_atto.show_filepicker(elementid, 'media', M.atto_media.filepicker_callback); - }, - filepicker_callback : function(params) { + /** + * Update the dialogue after an media was selected in the File Picker. + * + * @method _filepickerCallback + * @param {object} params The parameters provided by the filepicker + * containing information about the image. + * @private + */ + _filepickerCallback: function(params) { if (params.url !== '') { - var input = Y.one('#atto_media_urlentry'); - input.set('value', params.url); - input = Y.one('#atto_media_nameentry'); - input.set('value', params.file); + this._content.one('.urlentry') + .set('value', params.url); + this._content.one('.nameentry') + .set('value', params.file); } }, - set_media : function(e, elementid) { - e.preventDefault(); - M.atto_media.dialogue.hide(); - var input = e.currentTarget.ancestor('.atto_form').one('#atto_media_urlentry'); - var url = input.get('value'); - input = e.currentTarget.ancestor('.atto_form').one('#atto_media_nameentry'); - var name = input.get('value'); + /** + * Update the media in the contenteditable. + * + * @method setMedia + * @param {EventFacade} e + * @private + */ + _setMedia: function(e) { + e.preventDefault(); + this.getDialogue({ + focusAfterHide: null + }).hide(); + + var form = e.currentTarget.ancestor('.atto_form'), + url = form.one('.urlentry').get('value'), + name = form.one('.nameentry').get('value'), + host = this.get('host'); if (url !== '' && name !== '') { - M.editor_atto.set_selection(M.atto_media.selection); + host.setSelection(this._currentSelection); var mediahtml = '' + name + ''; - M.editor_atto.insert_html_at_focus_point(mediahtml); - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + host.insertContentAtFocusPoint(mediahtml); + this.markUpdated(); } - }, - get_form_content : function(elementid) { - var content = Y.Node.create('
                                        ' + - '' + - '
                                        ' + - '' + - '' + - '' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        '); - - content.one('#atto_media_urlentrysubmit').on('click', M.atto_media.set_media, this, elementid); - content.one('#openmediabrowser').on('click', M.atto_media.open_browser); - return content; } -}; +}); diff --git a/lib/editor/atto/plugins/media/yui/src/button/meta/button.json b/lib/editor/atto/plugins/media/yui/src/button/meta/button.json index 3632bf78635..e5446dba85e 100644 --- a/lib/editor/atto/plugins/media/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/media/yui/src/button/meta/button.json @@ -1,8 +1,7 @@ { - "moodle-atto_media-button": { - "requires": [ - "node", - "escape" - ] - } + "moodle-atto_media-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button-debug.js b/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button-debug.js index 6d71b846d78..6690d063510 100644 --- a/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button-debug.js +++ b/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button-debug.js @@ -15,39 +15,44 @@ YUI.add('moodle-atto_noautolink-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor noautolink plugin. - * - * @package editor-atto +/* + * @package atto_noautolink * @copyright 2014 Andrew Davis * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_noautolink = M.atto_noautolink || { + +/** + * @module moodle-atto_noautolink-button + */ + +/** + * Atto text editor noautolink plugin. + * + * @namespace M.atto_noautolink + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_noautolink').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addButton({ + icon: 'e/prevent_autolink', + callback: this._preventAutoLink + }); + }, + /** - * Initialise the plugin - Allow the user to mark text to be ignored by the glossary autolink filter. + * Prevent autolinking of the selected region. * - * @method init - * @param {Object} Initialisation settings for this plugin - * @param {string} params.elementid The editor identifier - * @param {string} params.group The button group + * @method _preventAutoLink + * @param {EventFacade} e + * @private */ - init: function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - - M.editor_atto.toggle_inline_selection_class(elementid, ['nolink']); - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - var iconurl = M.util.image_url('e/prevent_autolink', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'noautolink', iconurl, params.group, click); + _preventAutoLink: function() { + // Toggle inline selection class + this.get('host').toggleInlineSelectionClass(['nolink']); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button-min.js b/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button-min.js index af1e6ad62bf..f3d1f646a7f 100644 --- a/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button-min.js +++ b/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_noautolink-button",function(e,t){M.atto_noautolink=M.atto_noautolink||{init:function(e){var t=function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.editor_atto.toggle_inline_selection_class(t,["nolink"]),M.editor_atto.text_updated(t)},n=M.util.image_url("e/prevent_autolink","core");M.editor_atto.add_toolbar_button(e.elementid,"noautolink",n,e.group,t)}}},"@VERSION@",{requires:["node"]}); +YUI.add("moodle-atto_noautolink-button",function(e,t){e.namespace("M.atto_noautolink").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addButton({icon:"e/prevent_autolink",callback:this._preventAutoLink})},_preventAutoLink:function(){this.get("host").toggleInlineSelectionClass(["nolink"])}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button.js b/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button.js index 6d71b846d78..6690d063510 100644 --- a/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button.js +++ b/lib/editor/atto/plugins/noautolink/yui/build/moodle-atto_noautolink-button/moodle-atto_noautolink-button.js @@ -15,39 +15,44 @@ YUI.add('moodle-atto_noautolink-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor noautolink plugin. - * - * @package editor-atto +/* + * @package atto_noautolink * @copyright 2014 Andrew Davis * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_noautolink = M.atto_noautolink || { + +/** + * @module moodle-atto_noautolink-button + */ + +/** + * Atto text editor noautolink plugin. + * + * @namespace M.atto_noautolink + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_noautolink').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addButton({ + icon: 'e/prevent_autolink', + callback: this._preventAutoLink + }); + }, + /** - * Initialise the plugin - Allow the user to mark text to be ignored by the glossary autolink filter. + * Prevent autolinking of the selected region. * - * @method init - * @param {Object} Initialisation settings for this plugin - * @param {string} params.elementid The editor identifier - * @param {string} params.group The button group + * @method _preventAutoLink + * @param {EventFacade} e + * @private */ - init: function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - - M.editor_atto.toggle_inline_selection_class(elementid, ['nolink']); - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - var iconurl = M.util.image_url('e/prevent_autolink', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'noautolink', iconurl, params.group, click); + _preventAutoLink: function() { + // Toggle inline selection class + this.get('host').toggleInlineSelectionClass(['nolink']); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/noautolink/yui/src/button/js/button.js b/lib/editor/atto/plugins/noautolink/yui/src/button/js/button.js index c4bf5ef019d..415ff9d8899 100644 --- a/lib/editor/atto/plugins/noautolink/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/noautolink/yui/src/button/js/button.js @@ -13,36 +13,41 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor noautolink plugin. - * - * @package editor-atto +/* + * @package atto_noautolink * @copyright 2014 Andrew Davis * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_noautolink = M.atto_noautolink || { + +/** + * @module moodle-atto_noautolink-button + */ + +/** + * Atto text editor noautolink plugin. + * + * @namespace M.atto_noautolink + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_noautolink').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addButton({ + icon: 'e/prevent_autolink', + callback: this._preventAutoLink + }); + }, + /** - * Initialise the plugin - Allow the user to mark text to be ignored by the glossary autolink filter. + * Prevent autolinking of the selected region. * - * @method init - * @param {Object} Initialisation settings for this plugin - * @param {string} params.elementid The editor identifier - * @param {string} params.group The button group + * @method _preventAutoLink + * @param {EventFacade} e + * @private */ - init: function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - - M.editor_atto.toggle_inline_selection_class(elementid, ['nolink']); - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - var iconurl = M.util.image_url('e/prevent_autolink', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'noautolink', iconurl, params.group, click); + _preventAutoLink: function() { + // Toggle inline selection class + this.get('host').toggleInlineSelectionClass(['nolink']); } -}; +}); diff --git a/lib/editor/atto/plugins/noautolink/yui/src/button/meta/button.json b/lib/editor/atto/plugins/noautolink/yui/src/button/meta/button.json index a22405cc5ca..0c1ce68ded2 100644 --- a/lib/editor/atto/plugins/noautolink/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/noautolink/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_noautolink-button": { - "requires": ["node"] - } + "moodle-atto_noautolink-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } 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 7f82fc3ddd2..73d85dc57bd 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,49 +15,35 @@ 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 . +/* + * @package atto_orderedlist + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_orderedlist-button */ -var SELECTORS = { - TAGS : 'ol' -}; /** * Atto text editor orderedlist plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_orderedlist + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_orderedlist = M.atto_orderedlist || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('insertOrderedList', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/numbered_list', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'orderedlist', iconurl, params.group, click); +Y.namespace('M.atto_orderedlist').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'insertOrderedList', + icon: 'e/numbered_list', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'ol' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 cc6a5acd3b5..d383138f536 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){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),M.editor_atto.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"]}); +YUI.add("moodle-atto_orderedlist-button",function(e,t){e.namespace("M.atto_orderedlist").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"insertOrderedList",icon:"e/numbered_list",tags:"ol"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 7f82fc3ddd2..73d85dc57bd 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,49 +15,35 @@ 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 . +/* + * @package atto_orderedlist + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_orderedlist-button */ -var SELECTORS = { - TAGS : 'ol' -}; /** * Atto text editor orderedlist plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_orderedlist + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_orderedlist = M.atto_orderedlist || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('insertOrderedList', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/numbered_list', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'orderedlist', iconurl, params.group, click); +Y.namespace('M.atto_orderedlist').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'insertOrderedList', + icon: 'e/numbered_list', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'ol' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 d69a741e355..ba9b415dc10 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,46 +13,32 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_orderedlist + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_orderedlist-button */ -var SELECTORS = { - TAGS : 'ol' -}; /** * Atto text editor orderedlist plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_orderedlist + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_orderedlist = M.atto_orderedlist || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('insertOrderedList', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/numbered_list', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'orderedlist', iconurl, params.group, click); +Y.namespace('M.atto_orderedlist').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'insertOrderedList', + icon: 'e/numbered_list', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'ol' }); } -}; +}); diff --git a/lib/editor/atto/plugins/orderedlist/yui/src/button/meta/button.json b/lib/editor/atto/plugins/orderedlist/yui/src/button/meta/button.json index 08ed48a0e44..eebb905ca43 100644 --- a/lib/editor/atto/plugins/orderedlist/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/orderedlist/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_orderedlist-button": { - "requires": ["node"] - } + "moodle-atto_orderedlist-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button-debug.js b/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button-debug.js index 42f60c73c1e..21c7aa6d079 100644 --- a/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button-debug.js +++ b/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button-debug.js @@ -15,55 +15,74 @@ YUI.add('moodle-atto_rtl-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor rtl plugin. - * - * @package editor_atto +/* + * @package atto_rtl * @copyright 2014 Jerome Mouneyrac * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_rtl = M.atto_rtl || { - init : function(params) { - var click = function(e, elementid, direction) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); + +/** + * @module moodle-atto_rtl-button + */ + +/** + * Atto text editor rtl plugin. + * + * @namespace M.atto_rtl + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_rtl').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var direction; + + direction = 'ltr'; + this.addButton({ + icon: 'e/left_to_right', + title: direction, + buttonName: direction, + callback: this._toggleRTL, + callbackArgs: direction + }); + + direction = 'rtl'; + this.addButton({ + icon: 'e/right_to_left', + title: direction, + buttonName: direction, + callback: this._toggleRTL, + callbackArgs: direction + }); + }, + + /** + * Toggle the RTL/LTR values based on the supplied direction. + * + * @method _toggleRTL + * @param {EventFacade} e + * @param {String} direction + */ + _toggleRTL: function(e, direction) { + var host = this.get('host'), + selection = host.getSelection(); + if (selection) { + // Format the selection to be sure it has a tag parent (not the contenteditable). + var parentNode = host.formatSelectionBlock(), + parentDOMNode = parentNode.getDOMNode(); + + var currentDirection = parentDOMNode.getAttribute('dir'); + if (currentDirection === direction) { + parentDOMNode.removeAttribute("dir"); + } else { + parentDOMNode.setAttribute("dir", direction); } - M.atto_rtl.selection = M.editor_atto.get_selection(); - if (M.atto_rtl.selection !== false) { - - // Format the selection to be sure it has a tag parent (not the contenteditable). - var parentnode = M.editor_atto.format_selection_block(elementid); - parentnodeelement = parentnode.getDOMNode(); - - var currentdirection = parentnodeelement.getAttribute("dir"); - if (currentdirection === direction) { - parentnodeelement.removeAttribute("dir"); - } else { - parentnodeelement.setAttribute("dir", direction); - } - } - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - var rtlclick = function(e, elementid) { - click(e, elementid, 'rtl'); - }; - - var ltrclick = function(e, elementid) { - click(e, elementid, 'ltr'); - }; - - var iconurl = M.util.image_url('e/left_to_right', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'rtl', iconurl, params.group, ltrclick, 'ltr', M.util.get_string('ltr', 'atto_rtl')); - - iconurl = M.util.image_url('e/right_to_left', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'rtl', iconurl, params.group, rtlclick, 'rtl', M.util.get_string('rtl', 'atto_rtl')); + // Mark the text as having been updated. + this.markUpdated(); + } } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button-min.js b/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button-min.js index 5a2f480d62c..e13cd666ea8 100644 --- a/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button-min.js +++ b/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_rtl-button",function(e,t){M.atto_rtl=M.atto_rtl||{init:function(e){var t=function(e,t,n){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_rtl.selection=M.editor_atto.get_selection();if(M.atto_rtl.selection!==!1){var r=M.editor_atto.format_selection_block(t);parentnodeelement=r.getDOMNode();var i=parentnodeelement.getAttribute("dir");i===n?parentnodeelement.removeAttribute("dir"):parentnodeelement.setAttribute("dir",n)}M.editor_atto.text_updated(t)},n=function(e,n){t(e,n,"rtl")},r=function(e,n){t(e,n,"ltr")},i=M.util.image_url("e/left_to_right","core");M.editor_atto.add_toolbar_button(e.elementid,"rtl",i,e.group,r,"ltr",M.util.get_string("ltr","atto_rtl")),i=M.util.image_url("e/right_to_left","core"),M.editor_atto.add_toolbar_button(e.elementid,"rtl",i,e.group,n,"rtl",M.util.get_string("rtl","atto_rtl"))}}},"@VERSION@",{requires:["node"]}); +YUI.add("moodle-atto_rtl-button",function(e,t){e.namespace("M.atto_rtl").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var e;e="ltr",this.addButton({icon:"e/left_to_right",title:e,buttonName:e,callback:this._toggleRTL,callbackArgs:e}),e="rtl",this.addButton({icon:"e/right_to_left",title:e,buttonName:e,callback:this._toggleRTL,callbackArgs:e})},_toggleRTL:function(e,t){var n=this.get("host"),r=n.getSelection();if(r){var i=n.formatSelectionBlock(),s=i.getDOMNode(),o=s.getAttribute("dir");o===t?s.removeAttribute("dir"):s.setAttribute("dir",t),this.markUpdated()}}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button.js b/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button.js index 42f60c73c1e..21c7aa6d079 100644 --- a/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button.js +++ b/lib/editor/atto/plugins/rtl/yui/build/moodle-atto_rtl-button/moodle-atto_rtl-button.js @@ -15,55 +15,74 @@ YUI.add('moodle-atto_rtl-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor rtl plugin. - * - * @package editor_atto +/* + * @package atto_rtl * @copyright 2014 Jerome Mouneyrac * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_rtl = M.atto_rtl || { - init : function(params) { - var click = function(e, elementid, direction) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); + +/** + * @module moodle-atto_rtl-button + */ + +/** + * Atto text editor rtl plugin. + * + * @namespace M.atto_rtl + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_rtl').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var direction; + + direction = 'ltr'; + this.addButton({ + icon: 'e/left_to_right', + title: direction, + buttonName: direction, + callback: this._toggleRTL, + callbackArgs: direction + }); + + direction = 'rtl'; + this.addButton({ + icon: 'e/right_to_left', + title: direction, + buttonName: direction, + callback: this._toggleRTL, + callbackArgs: direction + }); + }, + + /** + * Toggle the RTL/LTR values based on the supplied direction. + * + * @method _toggleRTL + * @param {EventFacade} e + * @param {String} direction + */ + _toggleRTL: function(e, direction) { + var host = this.get('host'), + selection = host.getSelection(); + if (selection) { + // Format the selection to be sure it has a tag parent (not the contenteditable). + var parentNode = host.formatSelectionBlock(), + parentDOMNode = parentNode.getDOMNode(); + + var currentDirection = parentDOMNode.getAttribute('dir'); + if (currentDirection === direction) { + parentDOMNode.removeAttribute("dir"); + } else { + parentDOMNode.setAttribute("dir", direction); } - M.atto_rtl.selection = M.editor_atto.get_selection(); - if (M.atto_rtl.selection !== false) { - - // Format the selection to be sure it has a tag parent (not the contenteditable). - var parentnode = M.editor_atto.format_selection_block(elementid); - parentnodeelement = parentnode.getDOMNode(); - - var currentdirection = parentnodeelement.getAttribute("dir"); - if (currentdirection === direction) { - parentnodeelement.removeAttribute("dir"); - } else { - parentnodeelement.setAttribute("dir", direction); - } - } - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - var rtlclick = function(e, elementid) { - click(e, elementid, 'rtl'); - }; - - var ltrclick = function(e, elementid) { - click(e, elementid, 'ltr'); - }; - - var iconurl = M.util.image_url('e/left_to_right', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'rtl', iconurl, params.group, ltrclick, 'ltr', M.util.get_string('ltr', 'atto_rtl')); - - iconurl = M.util.image_url('e/right_to_left', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'rtl', iconurl, params.group, rtlclick, 'rtl', M.util.get_string('rtl', 'atto_rtl')); + // Mark the text as having been updated. + this.markUpdated(); + } } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/rtl/yui/src/button/js/button.js b/lib/editor/atto/plugins/rtl/yui/src/button/js/button.js index 3a76ba02e5d..b7d96f03a55 100755 --- a/lib/editor/atto/plugins/rtl/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/rtl/yui/src/button/js/button.js @@ -13,52 +13,71 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Atto text editor rtl plugin. - * - * @package editor_atto +/* + * @package atto_rtl * @copyright 2014 Jerome Mouneyrac * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_rtl = M.atto_rtl || { - init : function(params) { - var click = function(e, elementid, direction) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); + +/** + * @module moodle-atto_rtl-button + */ + +/** + * Atto text editor rtl plugin. + * + * @namespace M.atto_rtl + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_rtl').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var direction; + + direction = 'ltr'; + this.addButton({ + icon: 'e/left_to_right', + title: direction, + buttonName: direction, + callback: this._toggleRTL, + callbackArgs: direction + }); + + direction = 'rtl'; + this.addButton({ + icon: 'e/right_to_left', + title: direction, + buttonName: direction, + callback: this._toggleRTL, + callbackArgs: direction + }); + }, + + /** + * Toggle the RTL/LTR values based on the supplied direction. + * + * @method _toggleRTL + * @param {EventFacade} e + * @param {String} direction + */ + _toggleRTL: function(e, direction) { + var host = this.get('host'), + selection = host.getSelection(); + if (selection) { + // Format the selection to be sure it has a tag parent (not the contenteditable). + var parentNode = host.formatSelectionBlock(), + parentDOMNode = parentNode.getDOMNode(); + + var currentDirection = parentDOMNode.getAttribute('dir'); + if (currentDirection === direction) { + parentDOMNode.removeAttribute("dir"); + } else { + parentDOMNode.setAttribute("dir", direction); } - M.atto_rtl.selection = M.editor_atto.get_selection(); - if (M.atto_rtl.selection !== false) { - - // Format the selection to be sure it has a tag parent (not the contenteditable). - var parentnode = M.editor_atto.format_selection_block(elementid); - parentnodeelement = parentnode.getDOMNode(); - - var currentdirection = parentnodeelement.getAttribute("dir"); - if (currentdirection === direction) { - parentnodeelement.removeAttribute("dir"); - } else { - parentnodeelement.setAttribute("dir", direction); - } - } - - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - - var rtlclick = function(e, elementid) { - click(e, elementid, 'rtl'); - }; - - var ltrclick = function(e, elementid) { - click(e, elementid, 'ltr'); - }; - - var iconurl = M.util.image_url('e/left_to_right', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'rtl', iconurl, params.group, ltrclick, 'ltr', M.util.get_string('ltr', 'atto_rtl')); - - iconurl = M.util.image_url('e/right_to_left', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'rtl', iconurl, params.group, rtlclick, 'rtl', M.util.get_string('rtl', 'atto_rtl')); + // Mark the text as having been updated. + this.markUpdated(); + } } -}; +}); diff --git a/lib/editor/atto/plugins/rtl/yui/src/button/meta/button.json b/lib/editor/atto/plugins/rtl/yui/src/button/meta/button.json index 8f95ca8cff6..3a85a64a0cf 100755 --- a/lib/editor/atto/plugins/rtl/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/rtl/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_rtl-button": { - "requires": ["node"] - } + "moodle-atto_rtl-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } 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 56a17415f67..d6463649ab1 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,49 +15,35 @@ 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 . +/* + * @package atto_strike + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_strike-button */ -var SELECTORS = { - TAGS : 'strike' -}; /** * Atto text editor strike plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_strike + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_strike = M.atto_strike || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('strikeThrough', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/strikethrough', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'strike', iconurl, params.group, click); +Y.namespace('M.atto_strike').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'strikeThrough', + icon: 'e/strikethrough', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'strike' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 76cc7c1b945..3627c73bb05 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){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),M.editor_atto.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"]}); +YUI.add("moodle-atto_strike-button",function(e,t){e.namespace("M.atto_strike").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"strikeThrough",icon:"e/strikethrough",tags:"strike"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 56a17415f67..d6463649ab1 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,49 +15,35 @@ 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 . +/* + * @package atto_strike + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_strike-button */ -var SELECTORS = { - TAGS : 'strike' -}; /** * Atto text editor strike plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_strike + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_strike = M.atto_strike || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('strikeThrough', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/strikethrough', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'strike', iconurl, params.group, click); +Y.namespace('M.atto_strike').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'strikeThrough', + icon: 'e/strikethrough', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'strike' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 3e41a787843..0a7eab5cb1a 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,46 +13,32 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_strike + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_strike-button */ -var SELECTORS = { - TAGS : 'strike' -}; /** * Atto text editor strike plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_strike + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_strike = M.atto_strike || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('strikeThrough', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/strikethrough', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'strike', iconurl, params.group, click); +Y.namespace('M.atto_strike').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'strikeThrough', + icon: 'e/strikethrough', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'strike' }); } -}; +}); diff --git a/lib/editor/atto/plugins/strike/yui/src/button/meta/button.json b/lib/editor/atto/plugins/strike/yui/src/button/meta/button.json index 71772d22ca9..478fd801e4d 100644 --- a/lib/editor/atto/plugins/strike/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/strike/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_strike-button": { - "requires": ["node"] - } + "moodle-atto_strike-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } 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 995afffb80a..a9d5e22d7db 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,49 +15,34 @@ 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 . +/* + * @package atto_subscript + * @copyright 2014 Rosiana Wijaya + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_subscript-button */ -var SELECTORS = { - TAGS : 'sub' -}; /** * Atto text editor subscript plugin. * - * @package editor-atto - * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_subscript + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_subscript = M.atto_subscript || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('subscript', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/subscript', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'subscript', iconurl, params.group, click); +Y.namespace('M.atto_subscript').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'subscript', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'sub' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 f19b79a8b17..9510f931d8e 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){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),M.editor_atto.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"]}); +YUI.add("moodle-atto_subscript-button",function(e,t){e.namespace("M.atto_subscript").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"subscript",tags:"sub"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 995afffb80a..a9d5e22d7db 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,49 +15,34 @@ 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 . +/* + * @package atto_subscript + * @copyright 2014 Rosiana Wijaya + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_subscript-button */ -var SELECTORS = { - TAGS : 'sub' -}; /** * Atto text editor subscript plugin. * - * @package editor-atto - * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_subscript + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_subscript = M.atto_subscript || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('subscript', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/subscript', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'subscript', iconurl, params.group, click); +Y.namespace('M.atto_subscript').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'subscript', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'sub' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 fcb5b3e6184..337d3628e40 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,46 +13,31 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_subscript + * @copyright 2014 Rosiana Wijaya + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_subscript-button */ -var SELECTORS = { - TAGS : 'sub' -}; /** * Atto text editor subscript plugin. * - * @package editor-atto - * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_subscript + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_subscript = M.atto_subscript || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('subscript', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/subscript', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'subscript', iconurl, params.group, click); +Y.namespace('M.atto_subscript').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'subscript', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'sub' }); } -}; +}); diff --git a/lib/editor/atto/plugins/subscript/yui/src/button/meta/button.json b/lib/editor/atto/plugins/subscript/yui/src/button/meta/button.json index bc4597e3e74..5489a1bed9f 100644 --- a/lib/editor/atto/plugins/subscript/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/subscript/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { "moodle-atto_subscript-button": { - "requires": ["node"] + "requires": [ + "moodle-editor_atto-plugin" + ] } } 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 bdbf75dc868..bcad8e55b01 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,49 +15,34 @@ 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 . +/* + * @package atto_superscript + * @copyright 2014 Rosiana Wijaya + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_superscript-button */ -var SELECTORS = { - TAGS : 'sup' -}; /** * Atto text editor superscript plugin. * - * @package editor-atto - * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_superscript + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_superscript = M.atto_superscript || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('superscript', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/superscript', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'superscript', iconurl, params.group, click); +Y.namespace('M.atto_superscript').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'superscript', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'sup' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 f8c62cc350a..70ac08d0fc7 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){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),M.editor_atto.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"]}); +YUI.add("moodle-atto_superscript-button",function(e,t){e.namespace("M.atto_superscript").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"superscript",tags:"sup"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 bdbf75dc868..bcad8e55b01 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,49 +15,34 @@ 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 . +/* + * @package atto_superscript + * @copyright 2014 Rosiana Wijaya + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_superscript-button */ -var SELECTORS = { - TAGS : 'sup' -}; /** * Atto text editor superscript plugin. * - * @package editor-atto - * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_superscript + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_superscript = M.atto_superscript || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('superscript', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/superscript', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'superscript', iconurl, params.group, click); +Y.namespace('M.atto_superscript').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'superscript', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'sup' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 368c65f9de8..80bfeece74e 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,46 +13,31 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_superscript + * @copyright 2014 Rosiana Wijaya + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_superscript-button */ -var SELECTORS = { - TAGS : 'sup' -}; /** * Atto text editor superscript plugin. * - * @package editor-atto - * @copyright 2014 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_superscript + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_superscript = M.atto_superscript || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('superscript', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/superscript', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'superscript', iconurl, params.group, click); +Y.namespace('M.atto_superscript').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'superscript', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'sup' }); } -}; +}); diff --git a/lib/editor/atto/plugins/superscript/yui/src/button/meta/button.json b/lib/editor/atto/plugins/superscript/yui/src/button/meta/button.json index 1dd21566216..f1c3071b536 100644 --- a/lib/editor/atto/plugins/superscript/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/superscript/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { "moodle-atto_superscript-button": { - "requires": ["node"] + "requires": [ + "moodle-editor_atto-plugin" + ] } } 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 09385512d0d..9cf781fbf86 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 @@ -16,537 +16,194 @@ YUI.add('moodle-atto_table-button', function (Y, NAME) { // along with Moodle. If not, see . /** - * Selectors. - * - * @type {Object} + * @package atto_table + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @module moodle-atto_table-button */ -var SELECTORS = { - TAGS : 'table' -}; /** * Atto text editor table plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_table + * @class Button + * @extends M.editor_atto.EditorPlugin */ -M.atto_table = M.atto_table || { + +var COMPONENT = 'atto_table', + TEMPLATE = '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        {{{get_string "accessibilityhint" component}}}', + CONTEXTMENUTEMPLATE = '' + + ''; + + CSS = { + }; + +Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The window used to get the table details. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, - - /** - * The selection object returned by the browser. - * - * @property selection + * @property _currentSelection * @type Range - * @default null + * @private */ - selection : null, + _currentSelection: null, /** - * Yui image for table editing controls. + * The contextual menu that we can open. * - * @property menunode - * @type Y.Node - * @default null + * @property _contextMenu + * @type M.editor_atto.Menu + * @private */ - menunode : null, + _contextMenu: null, /** - * Popup menu for table controls + * The last modified target. * - * @property controlmenu - * @type M.editor_atto.controlmenu - * @default null + * @property _lastTarget + * @type Node + * @private */ - controlmenu : null, + _lastTarget: null, - /** - * Last clicked cell that opened the context menu. - * - * @property lasttarget - * @type Y.Node - * @default null - */ - lasttarget : null, - - /** - * Display the chooser dialogue. - * - * @method init - * @param Event e - * @param string elementid - */ - display_chooser : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_table.selection = M.editor_atto.get_selection(); - if (M.atto_table.selection !== false && (!M.atto_table.selection.collapsed)) { - var dialogue; - if (!M.atto_table.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_table.dialogue; - } - - dialogue.render(); - dialogue.set('bodyContent', M.atto_table.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createtable', 'atto_table')); - - dialogue.show(); - M.atto_table.dialogue = dialogue; - } - - }, - - /** - * Show the context menu - * - * @method show_menu - * @param Event e - * @param string elementid - */ - show_menu : function(e, elementid) { - var addhandlers = false; - - e.preventDefault(); - - if (this.controlmenu === null) { - addhandlers = true; - // Add event handlers for table control menus. - var bodycontent = ''; - - this.controlmenu = new M.editor_atto.controlmenu({ - headerText : M.util.get_string('edittable', 'atto_table'), - bodyContent : bodycontent - }); - } - // We store the cell of the last click (the control node is transient). - this.lasttarget = e.target.ancestor('.editor_atto_content td, .editor_atto_content th', true); - this.controlmenu.show(); - this.controlmenu.align(e.target, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]); - var bodynode = this.controlmenu.get('boundingBox'); - if (bodynode.one('a')) { - bodynode.one('a').focus(); - } - - if (addhandlers) { - bodynode.delegate('click', this.handle_table_control, 'a', this, elementid); - bodynode.delegate('key', this.handle_table_control, 'down:enter,space', 'a', this, elementid); - } - }, - - /** - * Determine the index of a row in a table column. - * - * @method get_row_index - * @param Y.Node node - */ - get_row_index : function(cell) { - var tablenode = cell.ancestor('table'), - rownode = cell.ancestor('tr'); - - if (!tablenode || !rownode) { - return; - } - - var rows = tablenode.all('tr'); - - return rows.indexOf(rownode); - }, - - /** - * Determine the index of a column in a table row. - * - * @method get_column_index - * @param Y.Node node - */ - get_column_index : function(cellnode) { - var rownode = cellnode.ancestor('tr'); - - if (!rownode) { - return; - } - - var cells = rownode.all('td, th'); - - return cells.indexOf(cellnode); - }, - - /** - * Delete the current row - * - * @method delete_row - * @param string elementid - */ - delete_row : function(elementid) { - var row = this.lasttarget.ancestor('tr'); - - if (row) { - // We do not remove rows with no cells (all headers). - if (row.one('td')) { - row.remove(true); - } - } - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move row up - * - * @method move_row_up - * @param string elementid - */ - move_row_up : function(elementid) { - var row = this.lasttarget.ancestor('tr'); - var prevrow = row.previous('tr'); - if (!row || !prevrow) { - return; - } - - row.swap(prevrow); - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move column left - * - * @method move_column_left - * @param string elementid - */ - move_column_left : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - var rows = this.lasttarget.ancestor('table').all('tr'); - var columncells = new Y.NodeList(); - var prevcells = new Y.NodeList(); - var hastd = false; - - rows.each(function(row) { - var cells = row.all('td, th'); - var cell = cells.item(columnindex), - cellprev = cells.item(columnindex-1); - columncells.push(cell); - if (cellprev) { - if (cellprev.get('tagName') === 'TD') { - hastd = true; - } - prevcells.push(cellprev); - } + initializer: function() { + this.addButton({ + icon: 'e/table', + callback: this._displayTableEditor, + tags: 'table' }); - if (hastd && prevcells.size() > 0) { - var i = 0; - for (i = 0; i < columncells.size(); i++) { - var cell = columncells.item(i); - var prevcell = prevcells.item(i); - - cell.swap(prevcell); - } - } - // Cleanup. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move column right - * - * @method move_column_right - * @param string elementid - */ - move_column_right : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - var rows = this.lasttarget.ancestor('table').all('tr'); - var columncells = new Y.NodeList(); - var nextcells = new Y.NodeList(); - var hastd = false; - - rows.each(function(row) { - var cells = row.all('td, th'); - var cell = cells.item(columnindex), - cellnext = cells.item(columnindex+1); - if (cell.get('tagName') === 'TD') { - hastd = true; - } - columncells.push(cell); - if (cellnext) { - nextcells.push(cellnext); - } - }); - - if (hastd && nextcells.size() > 0) { - var i = 0; - for (i = 0; i < columncells.size(); i++) { - var cell = columncells.item(i); - var nextcell = nextcells.item(i); - - cell.swap(nextcell); - } - } - // Cleanup. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move row down - * - * @method move_row_down - * @param string elementid - */ - move_row_down : function(elementid) { - var row = this.lasttarget.ancestor('tr'); - var nextrow = row.next('tr'); - if (!row || !nextrow) { - return; - } - - row.swap(nextrow); - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Delete the current column - * - * @method delete_column - * @param string elementid - */ - delete_column : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - var rows = this.lasttarget.ancestor('table').all('tr'); - var columncells = new Y.NodeList(); - var hastd = false; - - rows.each(function(row) { - var cells = row.all('td, th'); - var cell = cells.item(columnindex); - if (cell.get('tagName') === 'TD') { - hastd = true; - } - columncells.push(cell); - }); - - if (hastd) { - columncells.remove(true); - } - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Add a row after the current row. - * - * @method add_row_after - * @param string elementid - */ - add_row_after : function(elementid) { - var rowindex = this.get_row_index(this.lasttarget); - - var tablebody = this.lasttarget.ancestor('table').one('tbody'); - if (!tablebody) { - // Not all tables have tbody. - tablebody = this.lasttarget.ancestor('table'); - rowindex += 1; - } - - var firstrow = tablebody.one('tr'); - if (!firstrow) { - firstrow = this.lasttarget.ancestor('table').one('tr'); - } - if (!firstrow) { - // Table has no rows. Boo. - return; - } - newrow = firstrow.cloneNode(true); - newrow.all('th, td').each(function (tablecell) { - if (tablecell.get('tagName') === 'TH') { - if (tablecell.getAttribute('scope') !== 'row') { - var newcell = Y.Node.create(''); - tablecell.replace(newcell); - tablecell = newcell; - } - } - tablecell.setHTML(' '); - }); - - tablebody.insert(newrow, rowindex); - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Add a column after the current column. - * - * @method add_column_after - * @param string elementid - */ - add_column_after : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - - var tablecell = this.lasttarget.ancestor('table'); - var rows = tablecell.all('tr'); - Y.each(rows, function(row) { - // Clone the first cell from the row so it has the same type/attributes (e.g. scope). - var newcell = row.one('td, th').cloneNode(true); - // Clear the content of the cell. - newcell.setHTML(' '); - - row.insert(newcell, columnindex + 1); - }, this); - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Handle a button click - this will either open the new table dialogue, - * or the edit table context menu. - * - * @method handle_button - * @param Y.Event event - * @param string elementid - */ - handle_button : function(event, elementid) { - var selection = M.editor_atto.get_selection_parent_node(); - var editable = M.editor_atto.get_editable_node(elementid); - var cell; - - if (!selection) { - return M.atto_table.display_chooser(event, elementid); - } - Y.one(selection).ancestors('th, td', true).each(function(node) { - if (editable.contains(node)) { - cell = node; - } - }); - - if (cell) { - event.target = cell; - return M.atto_table.show_menu(event, elementid); - } - return M.atto_table.display_chooser(event, elementid); - }, - - - /** - * Handle a selection from the table control menu. - * - * @method handle_table_control - * @param Y.Event event - * @param string elementid - */ - handle_table_control : function(event, elementid) { - event.preventDefault(); - - this.controlmenu.hide(); - - switch (event.target.get('id')) { - case 'addcolumnafter': - this.add_column_after(elementid); - break; - case 'addrowafter': - this.add_row_after(elementid); - break; - case 'deleterow': - this.delete_row(elementid); - break; - case 'deletecolumn': - this.delete_column(elementid); - break; - case 'moverowdown': - this.move_row_down(elementid); - break; - case 'moverowup': - this.move_row_up(elementid); - break; - case 'movecolumnleft': - this.move_column_left(elementid); - break; - case 'movecolumnright': - this.move_column_right(elementid); - break; - } - }, - - /** - * Add this button to the form. - * - * @method init - * @param {Object} params - */ - init : function(params) { - - if (!M.atto_table.menunode) { - // Used for inline table editing controls. - var img = Y.Node.create(''); - img.setAttrs({ - alt : M.util.get_string('edittable', 'atto_table'), - src : M.util.image_url('t/contextmenu', 'core'), - width : '12', - height : '12' - }); - var anchor = Y.Node.create(''); - anchor.appendChild(img); - anchor.addClass('atto_control'); - M.atto_table.menunode = anchor; - } - - var iconurl = M.util.image_url('e/table', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'table', iconurl, params.group, this.handle_button); - // Disable mozilla table controls. if (Y.UA.gecko) { document.execCommand("enableInlineTableEditing", false, false); 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. - M.editor_atto.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'); - } - }); }, /** - * The OK button has been pressed - make the changes to the source. + * Display the table tool. * - * @method set_table - * @param Event e + * @method _displayDialogue + * @private */ - set_table : function(e, elementid) { + _displayDialogue: function() { + // Store the current cursor position. + this._currentSelection = this.get('host').getSelection(); + + if (this._currentSelection !== false && (!this._currentSelection.collapsed)) { + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createtable', COMPONENT), + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + } + }, + + /** + * Display the appropriate table editor. + * + * If the current selection includes a table, then we show the + * contextual menu, otherwise show the table creation dialogue. + * + * @method _displayTableEditor + * @param {EventFacade} e + * @private + */ + _displayTableEditor: function(e) { + var selection = this.get('host').getSelectionParentNode(), + cell; + + if (!selection) { + // We don't have a current selection at all, so show the standard dialogue. + return this._displayDialogue(e); + } + + // Check all of the table cells found in the selection. + Y.one(selection).ancestors('th, td', true).each(function(node) { + if (this.editor.contains(node)) { + cell = node; + } + }, this); + + if (cell) { + // Add the cell to the EventFacade to save duplication in when showing the menu. + e.tableCell = cell; + return this._showTableMenu(e); + } + + return this._displayDialogue(e); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE); + this._content = Y.Node.create(template({ + CSS: CSS, + elementid: this.get('host').get('elementid'), + component: COMPONENT + })); + + // Handle table setting. + this._content.one('.submit').on('click', this._setTable, this); + + return this._content; + }, + + /** + * Handle creation of a new table. + * + * @method _setTable + * @param {EventFacade} e + * @private + */ + _setTable: function(e) { var caption, rows, cols, @@ -555,14 +212,19 @@ M.atto_table = M.atto_table || { i, j; e.preventDefault(); - M.atto_table.dialogue.hide(); - caption = e.currentTarget.ancestor('.atto_form').one('#atto_table_caption'); - rows = e.currentTarget.ancestor('.atto_form').one('#atto_table_rows'); - cols = e.currentTarget.ancestor('.atto_form').one('#atto_table_columns'); - headers = e.currentTarget.ancestor('.atto_form').one('#atto_table_headers'); + // Hide the dialogue. + this.getDialogue({ + focusAfterHide: null + }).hide(); - M.editor_atto.set_selection(M.atto_table.selection); + caption = e.currentTarget.ancestor('.atto_form').one('.caption'); + rows = e.currentTarget.ancestor('.atto_form').one('.rows'); + cols = e.currentTarget.ancestor('.atto_form').one('.columns'); + headers = e.currentTarget.ancestor('.atto_form').one('.headers'); + + // Set the selection. + this.get('host').setSelection(this._currentSelection); // Note there are some spaces inserted in the cells and before and after, so that users have somewhere to click. var nl = "\n"; @@ -593,54 +255,366 @@ M.atto_table = M.atto_table || { tablehtml += '' + nl; tablehtml += '' + nl + '
                                        '; - M.editor_atto.insert_html_at_focus_point(tablehtml); + this.get('host').insertContentAtFocusPoint(tablehtml); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + // Mark the content as updated. + this.markUpdated(); }, /** - * Return the HTML of the form to show in the dialogue. + * Display the table menu. * - * @method get_form_content - * @param string elementid - * @return string + * @method _showTableMenu + * @param {EventFacade} e + * @private */ - get_form_content : function(elementid) { - var content = Y.Node.create('
                                        ' + - '' + - '' + - '
                                        ' + - '' + - '' + - '
                                        ' + - '' + - '' + - '
                                        ' + - '' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + M.util.get_string('accessibilityhint', 'atto_table')); + _showTableMenu: function(e) { + e.preventDefault(); - content.one('#atto_table_submit').on('click', M.atto_table.set_table, this, elementid); - return content; + var boundingBox; + + if (!this._contextMenu) { + var template = Y.Handlebars.compile(CONTEXTMENUTEMPLATE), + content = Y.Node.create(template({ + elementid: this.get('host').get('elementid'), + component: COMPONENT + })); + + this._contextMenu = new Y.M.editor_atto.Menu({ + headerText: M.util.get_string('edittable', 'atto_table'), + bodyContent: content + }); + + // Add event handlers for table control menus. + boundingBox = this._contextMenu.get('boundingBox'); + boundingBox.delegate('click', this._handleTableChange, 'a', this); + boundingBox.delegate('key', this._handleTableChange, 'down:enter,space', 'a', this); + } + boundingBox = this._contextMenu.get('boundingBox'); + + // We store the cell of the last click (the control node is transient). + this._lastTarget = e.tableCell.ancestor('.editor_atto_content td, .editor_atto_content th', true); + + // Show the context menu, and align to the current position. + this._contextMenu.show(); + this._contextMenu.align(e.tableCell, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]); + + // If there are any anchors in the bounding box, focus on the first. + if (boundingBox.one('a')) { + boundingBox.one('a').focus(); + } + }, + + /** + * Handle a selection from the table control menu. + * + * @method _handleTableChange + * @param {EventFacade} e + * @private + */ + _handleTableChange: function(e) { + e.preventDefault(); + + // Hide the context menu. + this._contextMenu.hide(); + + // Make our changes. + switch (e.target.getData('change')) { + case 'addcolumnafter': + this._addColumnAfter(); + break; + case 'addrowafter': + this._addRowAfter(); + break; + case 'deleterow': + this._deleteRow(); + break; + case 'deletecolumn': + this._deleteColumn(); + break; + case 'moverowdown': + this._moveRowDown(); + break; + case 'moverowup': + this._moveRowUp(); + break; + case 'movecolumnleft': + this._moveColumnLeft(); + break; + case 'movecolumnright': + this._moveColumnRight(); + break; + } + }, + + /** + * Determine the index of a row in a table column. + * + * @method _getRowIndex + * @param {Node} cell + * @private + */ + _getRowIndex: function(cell) { + var tablenode = cell.ancestor('table'), + rownode = cell.ancestor('tr'); + + if (!tablenode || !rownode) { + return; + } + + var rows = tablenode.all('tr'); + + return rows.indexOf(rownode); + }, + + /** + * Determine the index of a column in a table row. + * + * @method _getColumnIndex + * @param {Node} cellnode + * @private + */ + _getColumnIndex: function(cellnode) { + var rownode = cellnode.ancestor('tr'); + + if (!rownode) { + return; + } + + var cells = rownode.all('td, th'); + + return cells.indexOf(cellnode); + }, + + /** + * Delete the current row. + * + * @method _deleteRow + * @private + */ + _deleteRow: function() { + var row = this._lastTarget.ancestor('tr'); + + if (row) { + // We do not remove rows with no cells (all headers). + if (row.one('td')) { + row.remove(true); + } + } + + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Move row up + * + * @method _moveRowUp + * @private + */ + _moveRowUp: function() { + var row = this._lastTarget.ancestor('tr'); + var prevrow = row.previous('tr'); + if (!row || !prevrow) { + return; + } + + row.swap(prevrow); + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Move column left + * + * @method _moveColumnLeft + * @private + */ + _moveColumnLeft: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + var rows = this._lastTarget.ancestor('table').all('tr'); + var columncells = new Y.NodeList(); + var prevcells = new Y.NodeList(); + var hastd = false; + + rows.each(function(row) { + var cells = row.all('td, th'); + var cell = cells.item(columnindex), + cellprev = cells.item(columnindex-1); + columncells.push(cell); + if (cellprev) { + if (cellprev.get('tagName') === 'TD') { + hastd = true; + } + prevcells.push(cellprev); + } + }); + + if (hastd && prevcells.size() > 0) { + var i = 0; + for (i = 0; i < columncells.size(); i++) { + var cell = columncells.item(i); + var prevcell = prevcells.item(i); + + cell.swap(prevcell); + } + } + // Cleanup. + this.markUpdated(); + }, + + /** + * Move column right. + * + * @method _moveColumnRight + * @private + */ + _moveColumnRight: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + var rows = this._lastTarget.ancestor('table').all('tr'); + var columncells = new Y.NodeList(); + var nextcells = new Y.NodeList(); + var hastd = false; + + rows.each(function(row) { + var cells = row.all('td, th'); + var cell = cells.item(columnindex), + cellnext = cells.item(columnindex+1); + if (cell.get('tagName') === 'TD') { + hastd = true; + } + columncells.push(cell); + if (cellnext) { + nextcells.push(cellnext); + } + }); + + if (hastd && nextcells.size() > 0) { + var i = 0; + for (i = 0; i < columncells.size(); i++) { + var cell = columncells.item(i); + var nextcell = nextcells.item(i); + + cell.swap(nextcell); + } + } + // Cleanup. + this.markUpdated(); + }, + + /** + * Move row down. + * + * @method _moveRowDown + * @private + */ + _moveRowDown: function() { + var row = this._lastTarget.ancestor('tr'); + var nextrow = row.next('tr'); + if (!row || !nextrow) { + return; + } + + row.swap(nextrow); + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Delete the current column. + * + * @method _deleteColumn + * @private + */ + _deleteColumn: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + var rows = this._lastTarget.ancestor('table').all('tr'); + var columncells = new Y.NodeList(); + var hastd = false; + + rows.each(function(row) { + var cells = row.all('td, th'); + var cell = cells.item(columnindex); + if (cell.get('tagName') === 'TD') { + hastd = true; + } + columncells.push(cell); + }); + + if (hastd) { + columncells.remove(true); + } + + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Add a row after the current row. + * + * @method _addRowAfter + * @private + */ + _addRowAfter: function() { + var rowindex = this._getRowIndex(this._lastTarget); + + var tablebody = this._lastTarget.ancestor('table').one('tbody'); + if (!tablebody) { + // Not all tables have tbody. + tablebody = this._lastTarget.ancestor('table'); + rowindex += 1; + } + + var firstrow = tablebody.one('tr'); + if (!firstrow) { + firstrow = this._lastTarget.ancestor('table').one('tr'); + } + if (!firstrow) { + // Table has no rows. Boo. + return; + } + newrow = firstrow.cloneNode(true); + newrow.all('th, td').each(function (tablecell) { + if (tablecell.get('tagName') === 'TH') { + if (tablecell.getAttribute('scope') !== 'row') { + var newcell = Y.Node.create(''); + tablecell.replace(newcell); + tablecell = newcell; + } + } + tablecell.setHTML(' '); + }); + + tablebody.insert(newrow, rowindex); + + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Add a column after the current column. + * + * @method _addColumnAfter + * @private + */ + _addColumnAfter: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + + var tablecell = this._lastTarget.ancestor('table'); + var rows = tablecell.all('tr'); + Y.each(rows, function(row) { + // Clone the first cell from the row so it has the same type/attributes (e.g. scope). + var newcell = row.one('td, th').cloneNode(true); + // Clear the content of the cell. + newcell.setHTML(' '); + + row.insert(newcell, columnindex + 1); + }, this); + + // Clean the HTML. + this.markUpdated(); } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape", "event", "event-valuechange"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin", "moodle-editor_atto-menu", "event", "event-valuechange"]}); 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 d943b6adb5a..da3625dce3d 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){var n={TAGS:"table"};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="
                                        ",this.controlmenu=new M.editor_atto.controlmenu({headerText:M.util.get_string("edittable","atto_table"),bodyContent:i})}this.lasttarget=t.target.ancestor(".editor_atto_content td, .editor_atto_content th",!0),this.controlmenu.show(),this.controlmenu.align(t.target,[e.WidgetPositionAlign.TL,e.WidgetPositionAlign.BL]);var s=this.controlmenu.get("boundingBox");s.one("a")&&s.one("a").focus(),r&&(s.delegate("click",this.handle_table_control,"a",this,n),s.delegate("key",this.handle_table_control,"down:enter,space","a",this,n))},get_row_index:function(e){var t=e.ancestor("table"),n=e.ancestor("tr");if(!t||!n)return;var r=t.all("tr");return r.indexOf(n)},get_column_index:function(e){var t=e.ancestor("tr");if(!t)return;var n=t.all("td, th");return n.indexOf(e)},delete_row:function(e){var t=this.lasttarget.ancestor("tr");t&&t.one("td")&&t.remove(!0),M.editor_atto.text_updated(e)},move_row_up:function(e){var t=this.lasttarget.ancestor("tr"),n=t.previous("tr");if(!t||!n)return;t.swap(n),M.editor_atto.text_updated(e)},move_column_left:function(t){var n=this.get_column_index(this.lasttarget),r=this.lasttarget.ancestor("table").all("tr"),i=new e.NodeList,s=new e.NodeList,o=!1;r.each(function(e){var t=e.all("td, th"),r=t.item(n),u=t.item(n-1);i.push(r),u&&(u.get("tagName")==="TD"&&(o=!0),s.push(u))});if(o&&s.size()>0){var u=0;for(u=0;u0){var u=0;for(u=0;u");t.replace(n),t=n}t.setHTML(" ")}),r.insert(newrow,n),M.editor_atto.text_updated(t)},add_column_after:function(t){var n=this.get_column_index(this.lasttarget),r=this.lasttarget.ancestor("table"),i=r.all("tr");e.each(i,function(e){var t=e.one("td, th").cloneNode(!0);t.setHTML(" "),e.insert(t,n+1)},this),M.editor_atto.text_updated(t)},handle_button:function(t,n){var r=M.editor_atto.get_selection_parent_node(),i=M.editor_atto.get_editable_node(n),s;return r?(e.one(r).ancestors("th, td",!0).each(function(e){i.contains(e)&&(s=e)}),s?(t.target=s,M.atto_table.show_menu(t,n)):M.atto_table.display_chooser(t,n)):M.atto_table.display_chooser(t,n)},handle_table_control:function(e,t){e.preventDefault(),this.controlmenu.hide();switch(e.target.get("id")){case"addcolumnafter":this.add_column_after(t);break;case"addrowafter":this.add_row_after(t);break;case"deleterow":this.delete_row(t);break;case"deletecolumn":this.delete_column(t);break;case"moverowdown":this.move_row_down(t);break;case"moverowup":this.move_row_up(t);break;case"movecolumnleft":this.move_column_left(t);break;case"movecolumnright":this.move_column_right(t)}},init:function(t){if(!M.atto_table.menunode){var r=e.Node.create("");r.setAttrs({alt:M.util.get_string("edittable","atto_table"),src:M.util.image_url("t/contextmenu","core"),width:"12",height:"12"});var i=e.Node.create('');i.appendChild(r),i.addClass("atto_control"),M.atto_table.menunode=i}var s=M.util.image_url("e/table","core");M.editor_atto.add_toolbar_button(t.elementid,"table",s,t.group,this.handle_button),e.UA.gecko&&(document.execCommand("enableInlineTableEditing",!1,!1),document.execCommand("enableObjectResizing",!1,!1)),M.editor_atto.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,"table"):M.editor_atto.remove_widget_highlight(e.elementid,"table")})},set_table:function(t,n){var r,i,s,o,u,a,f;t.preventDefault(),M.atto_table.dialogue.hide(),r=t.currentTarget.ancestor(".atto_form").one("#atto_table_caption"),i=t.currentTarget.ancestor(".atto_form").one("#atto_table_rows"),s=t.currentTarget.ancestor(".atto_form").one("#atto_table_columns"),o=t.currentTarget.ancestor(".atto_form").one("#atto_table_headers"),M.editor_atto.set_selection(M.atto_table.selection);var l="\n";u="
                                        "+l+""+l,u+=""+l,a=0;if(o.get("value")==="columns"||o.get("value")==="both"){a=1,u+=""+l+""+l;for(f=0;f'+l;u+=""+l+""+l}u+=""+l;for(;a"+l;for(f=0;f"+l:u+=''+l;u+=""+l}u+=""+l,u+="
                                        "+e.Escape.html(r.get("value"))+"
                                        "+l+"
                                        ",M.editor_atto.insert_html_at_focus_point(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"]}); +YUI.add("moodle-atto_table-button",function(e,t){var n="atto_table",r='






                                        {{{get_string "accessibilityhint" component}}}',i='
                                        ';CSS={},e.namespace("M.atto_table").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_currentSelection:null,_contextMenu:null,_lastTarget:null,initializer:function(){this.addButton({icon:"e/table",callback:this._displayTableEditor,tags:"table"}),e.UA.gecko&&(document.execCommand("enableInlineTableEditing",!1,!1),document.execCommand("enableObjectResizing",!1,!1))},_displayDialogue:function(){this._currentSelection=this.get("host").getSelection();if(this._currentSelection!==!1&&!this._currentSelection.collapsed){var e=this.getDialogue({headerContent:M.util.get_string("createtable",n),focusAfterHide:!0});e.set("bodyContent",this._getDialogueContent()).show()}},_displayTableEditor:function(t){var n=this.get("host").getSelectionParentNode(),r;return n?(e.one(n).ancestors("th, td",!0).each(function(e){this.editor.contains(e)&&(r=e)},this),r?(t.tableCell=r,this._showTableMenu(t)):this._displayDialogue(t)):this._displayDialogue(t)},_getDialogueContent:function(){var t=e.Handlebars.compile(r);return this._content=e.Node.create(t({CSS:CSS,elementid:this.get("host").get("elementid"),component:n})),this._content.one(".submit").on("click",this._setTable,this),this._content},_setTable:function(t){var n,r,i,s,o,u,a;t.preventDefault(),this.getDialogue({focusAfterHide:null}).hide(),n=t.currentTarget.ancestor(".atto_form").one(".caption"),r=t.currentTarget.ancestor(".atto_form").one(".rows"),i=t.currentTarget.ancestor(".atto_form").one(".columns"),s=t.currentTarget.ancestor(".atto_form").one(".headers"),this.get("host").setSelection(this._currentSelection);var f="\n";o="
                                        "+f+""+f,o+=""+f,u=0;if(s.get("value")==="columns"||s.get("value")==="both"){u=1,o+=""+f+""+f;for(a=0;a'+f;o+=""+f+""+f}o+=""+f;for(;u"+f;for(a=0;a"+f:o+=''+f;o+=""+f}o+=""+f,o+="
                                        "+e.Escape.html(n.get("value"))+"
                                        "+f+"
                                        ",this.get("host").insertContentAtFocusPoint(o),this.markUpdated()},_showTableMenu:function(t){t.preventDefault();var r;if(!this._contextMenu){var s=e.Handlebars.compile(i),o=e.Node.create(s({elementid:this.get("host").get("elementid"),component:n}));this._contextMenu=new e.M.editor_atto.Menu({headerText:M.util.get_string("edittable","atto_table"),bodyContent:o}),r=this._contextMenu.get("boundingBox"),r.delegate("click",this._handleTableChange,"a",this),r.delegate("key",this._handleTableChange,"down:enter,space","a",this)}r=this._contextMenu.get("boundingBox"),this._lastTarget=t.tableCell.ancestor(".editor_atto_content td, .editor_atto_content th",!0),this._contextMenu.show(),this._contextMenu.align(t.tableCell,[e.WidgetPositionAlign.TL,e.WidgetPositionAlign.BL]),r.one("a")&&r.one("a").focus()},_handleTableChange:function(e){e.preventDefault(),this._contextMenu.hide();switch(e.target.getData("change")){case"addcolumnafter":this._addColumnAfter();break;case"addrowafter":this._addRowAfter();break;case"deleterow":this._deleteRow();break;case"deletecolumn":this._deleteColumn();break;case"moverowdown":this._moveRowDown();break;case"moverowup":this._moveRowUp();break;case"movecolumnleft":this._moveColumnLeft();break;case"movecolumnright":this._moveColumnRight()}},_getRowIndex:function(e){var t=e.ancestor("table"),n=e.ancestor("tr");if(!t||!n)return;var r=t.all("tr");return r.indexOf(n)},_getColumnIndex:function(e){var t=e.ancestor("tr");if(!t)return;var n=t.all("td, th");return n.indexOf(e)},_deleteRow:function(){var e=this._lastTarget.ancestor("tr");e&&e.one("td")&&e.remove(!0),this.markUpdated()},_moveRowUp:function(){var e=this._lastTarget.ancestor("tr"),t=e.previous("tr");if(!e||!t)return;e.swap(t),this.markUpdated()},_moveColumnLeft:function(){var t=this._getColumnIndex(this._lastTarget),n=this._lastTarget.ancestor +("table").all("tr"),r=new e.NodeList,i=new e.NodeList,s=!1;n.each(function(e){var n=e.all("td, th"),o=n.item(t),u=n.item(t-1);r.push(o),u&&(u.get("tagName")==="TD"&&(s=!0),i.push(u))});if(s&&i.size()>0){var o=0;for(o=0;o0){var o=0;for(o=0;o");t.replace(n),t=n}t.setHTML(" ")}),n.insert(newrow,t),this.markUpdated()},_addColumnAfter:function(){var t=this._getColumnIndex(this._lastTarget),n=this._lastTarget.ancestor("table"),r=n.all("tr");e.each(r,function(e){var n=e.one("td, th").cloneNode(!0);n.setHTML(" "),e.insert(n,t+1)},this),this.markUpdated()}})},"@VERSION@",{requires:["moodle-editor_atto-plugin","moodle-editor_atto-menu","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 09385512d0d..9cf781fbf86 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 @@ -16,537 +16,194 @@ YUI.add('moodle-atto_table-button', function (Y, NAME) { // along with Moodle. If not, see . /** - * Selectors. - * - * @type {Object} + * @package atto_table + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @module moodle-atto_table-button */ -var SELECTORS = { - TAGS : 'table' -}; /** * Atto text editor table plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_table + * @class Button + * @extends M.editor_atto.EditorPlugin */ -M.atto_table = M.atto_table || { + +var COMPONENT = 'atto_table', + TEMPLATE = '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        {{{get_string "accessibilityhint" component}}}', + CONTEXTMENUTEMPLATE = '' + + ''; + + CSS = { + }; + +Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The window used to get the table details. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, - - /** - * The selection object returned by the browser. - * - * @property selection + * @property _currentSelection * @type Range - * @default null + * @private */ - selection : null, + _currentSelection: null, /** - * Yui image for table editing controls. + * The contextual menu that we can open. * - * @property menunode - * @type Y.Node - * @default null + * @property _contextMenu + * @type M.editor_atto.Menu + * @private */ - menunode : null, + _contextMenu: null, /** - * Popup menu for table controls + * The last modified target. * - * @property controlmenu - * @type M.editor_atto.controlmenu - * @default null + * @property _lastTarget + * @type Node + * @private */ - controlmenu : null, + _lastTarget: null, - /** - * Last clicked cell that opened the context menu. - * - * @property lasttarget - * @type Y.Node - * @default null - */ - lasttarget : null, - - /** - * Display the chooser dialogue. - * - * @method init - * @param Event e - * @param string elementid - */ - display_chooser : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_table.selection = M.editor_atto.get_selection(); - if (M.atto_table.selection !== false && (!M.atto_table.selection.collapsed)) { - var dialogue; - if (!M.atto_table.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_table.dialogue; - } - - dialogue.render(); - dialogue.set('bodyContent', M.atto_table.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createtable', 'atto_table')); - - dialogue.show(); - M.atto_table.dialogue = dialogue; - } - - }, - - /** - * Show the context menu - * - * @method show_menu - * @param Event e - * @param string elementid - */ - show_menu : function(e, elementid) { - var addhandlers = false; - - e.preventDefault(); - - if (this.controlmenu === null) { - addhandlers = true; - // Add event handlers for table control menus. - var bodycontent = ''; - - this.controlmenu = new M.editor_atto.controlmenu({ - headerText : M.util.get_string('edittable', 'atto_table'), - bodyContent : bodycontent - }); - } - // We store the cell of the last click (the control node is transient). - this.lasttarget = e.target.ancestor('.editor_atto_content td, .editor_atto_content th', true); - this.controlmenu.show(); - this.controlmenu.align(e.target, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]); - var bodynode = this.controlmenu.get('boundingBox'); - if (bodynode.one('a')) { - bodynode.one('a').focus(); - } - - if (addhandlers) { - bodynode.delegate('click', this.handle_table_control, 'a', this, elementid); - bodynode.delegate('key', this.handle_table_control, 'down:enter,space', 'a', this, elementid); - } - }, - - /** - * Determine the index of a row in a table column. - * - * @method get_row_index - * @param Y.Node node - */ - get_row_index : function(cell) { - var tablenode = cell.ancestor('table'), - rownode = cell.ancestor('tr'); - - if (!tablenode || !rownode) { - return; - } - - var rows = tablenode.all('tr'); - - return rows.indexOf(rownode); - }, - - /** - * Determine the index of a column in a table row. - * - * @method get_column_index - * @param Y.Node node - */ - get_column_index : function(cellnode) { - var rownode = cellnode.ancestor('tr'); - - if (!rownode) { - return; - } - - var cells = rownode.all('td, th'); - - return cells.indexOf(cellnode); - }, - - /** - * Delete the current row - * - * @method delete_row - * @param string elementid - */ - delete_row : function(elementid) { - var row = this.lasttarget.ancestor('tr'); - - if (row) { - // We do not remove rows with no cells (all headers). - if (row.one('td')) { - row.remove(true); - } - } - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move row up - * - * @method move_row_up - * @param string elementid - */ - move_row_up : function(elementid) { - var row = this.lasttarget.ancestor('tr'); - var prevrow = row.previous('tr'); - if (!row || !prevrow) { - return; - } - - row.swap(prevrow); - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move column left - * - * @method move_column_left - * @param string elementid - */ - move_column_left : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - var rows = this.lasttarget.ancestor('table').all('tr'); - var columncells = new Y.NodeList(); - var prevcells = new Y.NodeList(); - var hastd = false; - - rows.each(function(row) { - var cells = row.all('td, th'); - var cell = cells.item(columnindex), - cellprev = cells.item(columnindex-1); - columncells.push(cell); - if (cellprev) { - if (cellprev.get('tagName') === 'TD') { - hastd = true; - } - prevcells.push(cellprev); - } + initializer: function() { + this.addButton({ + icon: 'e/table', + callback: this._displayTableEditor, + tags: 'table' }); - if (hastd && prevcells.size() > 0) { - var i = 0; - for (i = 0; i < columncells.size(); i++) { - var cell = columncells.item(i); - var prevcell = prevcells.item(i); - - cell.swap(prevcell); - } - } - // Cleanup. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move column right - * - * @method move_column_right - * @param string elementid - */ - move_column_right : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - var rows = this.lasttarget.ancestor('table').all('tr'); - var columncells = new Y.NodeList(); - var nextcells = new Y.NodeList(); - var hastd = false; - - rows.each(function(row) { - var cells = row.all('td, th'); - var cell = cells.item(columnindex), - cellnext = cells.item(columnindex+1); - if (cell.get('tagName') === 'TD') { - hastd = true; - } - columncells.push(cell); - if (cellnext) { - nextcells.push(cellnext); - } - }); - - if (hastd && nextcells.size() > 0) { - var i = 0; - for (i = 0; i < columncells.size(); i++) { - var cell = columncells.item(i); - var nextcell = nextcells.item(i); - - cell.swap(nextcell); - } - } - // Cleanup. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move row down - * - * @method move_row_down - * @param string elementid - */ - move_row_down : function(elementid) { - var row = this.lasttarget.ancestor('tr'); - var nextrow = row.next('tr'); - if (!row || !nextrow) { - return; - } - - row.swap(nextrow); - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Delete the current column - * - * @method delete_column - * @param string elementid - */ - delete_column : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - var rows = this.lasttarget.ancestor('table').all('tr'); - var columncells = new Y.NodeList(); - var hastd = false; - - rows.each(function(row) { - var cells = row.all('td, th'); - var cell = cells.item(columnindex); - if (cell.get('tagName') === 'TD') { - hastd = true; - } - columncells.push(cell); - }); - - if (hastd) { - columncells.remove(true); - } - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Add a row after the current row. - * - * @method add_row_after - * @param string elementid - */ - add_row_after : function(elementid) { - var rowindex = this.get_row_index(this.lasttarget); - - var tablebody = this.lasttarget.ancestor('table').one('tbody'); - if (!tablebody) { - // Not all tables have tbody. - tablebody = this.lasttarget.ancestor('table'); - rowindex += 1; - } - - var firstrow = tablebody.one('tr'); - if (!firstrow) { - firstrow = this.lasttarget.ancestor('table').one('tr'); - } - if (!firstrow) { - // Table has no rows. Boo. - return; - } - newrow = firstrow.cloneNode(true); - newrow.all('th, td').each(function (tablecell) { - if (tablecell.get('tagName') === 'TH') { - if (tablecell.getAttribute('scope') !== 'row') { - var newcell = Y.Node.create(''); - tablecell.replace(newcell); - tablecell = newcell; - } - } - tablecell.setHTML(' '); - }); - - tablebody.insert(newrow, rowindex); - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Add a column after the current column. - * - * @method add_column_after - * @param string elementid - */ - add_column_after : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - - var tablecell = this.lasttarget.ancestor('table'); - var rows = tablecell.all('tr'); - Y.each(rows, function(row) { - // Clone the first cell from the row so it has the same type/attributes (e.g. scope). - var newcell = row.one('td, th').cloneNode(true); - // Clear the content of the cell. - newcell.setHTML(' '); - - row.insert(newcell, columnindex + 1); - }, this); - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Handle a button click - this will either open the new table dialogue, - * or the edit table context menu. - * - * @method handle_button - * @param Y.Event event - * @param string elementid - */ - handle_button : function(event, elementid) { - var selection = M.editor_atto.get_selection_parent_node(); - var editable = M.editor_atto.get_editable_node(elementid); - var cell; - - if (!selection) { - return M.atto_table.display_chooser(event, elementid); - } - Y.one(selection).ancestors('th, td', true).each(function(node) { - if (editable.contains(node)) { - cell = node; - } - }); - - if (cell) { - event.target = cell; - return M.atto_table.show_menu(event, elementid); - } - return M.atto_table.display_chooser(event, elementid); - }, - - - /** - * Handle a selection from the table control menu. - * - * @method handle_table_control - * @param Y.Event event - * @param string elementid - */ - handle_table_control : function(event, elementid) { - event.preventDefault(); - - this.controlmenu.hide(); - - switch (event.target.get('id')) { - case 'addcolumnafter': - this.add_column_after(elementid); - break; - case 'addrowafter': - this.add_row_after(elementid); - break; - case 'deleterow': - this.delete_row(elementid); - break; - case 'deletecolumn': - this.delete_column(elementid); - break; - case 'moverowdown': - this.move_row_down(elementid); - break; - case 'moverowup': - this.move_row_up(elementid); - break; - case 'movecolumnleft': - this.move_column_left(elementid); - break; - case 'movecolumnright': - this.move_column_right(elementid); - break; - } - }, - - /** - * Add this button to the form. - * - * @method init - * @param {Object} params - */ - init : function(params) { - - if (!M.atto_table.menunode) { - // Used for inline table editing controls. - var img = Y.Node.create(''); - img.setAttrs({ - alt : M.util.get_string('edittable', 'atto_table'), - src : M.util.image_url('t/contextmenu', 'core'), - width : '12', - height : '12' - }); - var anchor = Y.Node.create(''); - anchor.appendChild(img); - anchor.addClass('atto_control'); - M.atto_table.menunode = anchor; - } - - var iconurl = M.util.image_url('e/table', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'table', iconurl, params.group, this.handle_button); - // Disable mozilla table controls. if (Y.UA.gecko) { document.execCommand("enableInlineTableEditing", false, false); 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. - M.editor_atto.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'); - } - }); }, /** - * The OK button has been pressed - make the changes to the source. + * Display the table tool. * - * @method set_table - * @param Event e + * @method _displayDialogue + * @private */ - set_table : function(e, elementid) { + _displayDialogue: function() { + // Store the current cursor position. + this._currentSelection = this.get('host').getSelection(); + + if (this._currentSelection !== false && (!this._currentSelection.collapsed)) { + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createtable', COMPONENT), + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + } + }, + + /** + * Display the appropriate table editor. + * + * If the current selection includes a table, then we show the + * contextual menu, otherwise show the table creation dialogue. + * + * @method _displayTableEditor + * @param {EventFacade} e + * @private + */ + _displayTableEditor: function(e) { + var selection = this.get('host').getSelectionParentNode(), + cell; + + if (!selection) { + // We don't have a current selection at all, so show the standard dialogue. + return this._displayDialogue(e); + } + + // Check all of the table cells found in the selection. + Y.one(selection).ancestors('th, td', true).each(function(node) { + if (this.editor.contains(node)) { + cell = node; + } + }, this); + + if (cell) { + // Add the cell to the EventFacade to save duplication in when showing the menu. + e.tableCell = cell; + return this._showTableMenu(e); + } + + return this._displayDialogue(e); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE); + this._content = Y.Node.create(template({ + CSS: CSS, + elementid: this.get('host').get('elementid'), + component: COMPONENT + })); + + // Handle table setting. + this._content.one('.submit').on('click', this._setTable, this); + + return this._content; + }, + + /** + * Handle creation of a new table. + * + * @method _setTable + * @param {EventFacade} e + * @private + */ + _setTable: function(e) { var caption, rows, cols, @@ -555,14 +212,19 @@ M.atto_table = M.atto_table || { i, j; e.preventDefault(); - M.atto_table.dialogue.hide(); - caption = e.currentTarget.ancestor('.atto_form').one('#atto_table_caption'); - rows = e.currentTarget.ancestor('.atto_form').one('#atto_table_rows'); - cols = e.currentTarget.ancestor('.atto_form').one('#atto_table_columns'); - headers = e.currentTarget.ancestor('.atto_form').one('#atto_table_headers'); + // Hide the dialogue. + this.getDialogue({ + focusAfterHide: null + }).hide(); - M.editor_atto.set_selection(M.atto_table.selection); + caption = e.currentTarget.ancestor('.atto_form').one('.caption'); + rows = e.currentTarget.ancestor('.atto_form').one('.rows'); + cols = e.currentTarget.ancestor('.atto_form').one('.columns'); + headers = e.currentTarget.ancestor('.atto_form').one('.headers'); + + // Set the selection. + this.get('host').setSelection(this._currentSelection); // Note there are some spaces inserted in the cells and before and after, so that users have somewhere to click. var nl = "\n"; @@ -593,54 +255,366 @@ M.atto_table = M.atto_table || { tablehtml += '' + nl; tablehtml += '' + nl + '
                                        '; - M.editor_atto.insert_html_at_focus_point(tablehtml); + this.get('host').insertContentAtFocusPoint(tablehtml); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + // Mark the content as updated. + this.markUpdated(); }, /** - * Return the HTML of the form to show in the dialogue. + * Display the table menu. * - * @method get_form_content - * @param string elementid - * @return string + * @method _showTableMenu + * @param {EventFacade} e + * @private */ - get_form_content : function(elementid) { - var content = Y.Node.create('
                                        ' + - '' + - '' + - '
                                        ' + - '' + - '' + - '
                                        ' + - '' + - '' + - '
                                        ' + - '' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + M.util.get_string('accessibilityhint', 'atto_table')); + _showTableMenu: function(e) { + e.preventDefault(); - content.one('#atto_table_submit').on('click', M.atto_table.set_table, this, elementid); - return content; + var boundingBox; + + if (!this._contextMenu) { + var template = Y.Handlebars.compile(CONTEXTMENUTEMPLATE), + content = Y.Node.create(template({ + elementid: this.get('host').get('elementid'), + component: COMPONENT + })); + + this._contextMenu = new Y.M.editor_atto.Menu({ + headerText: M.util.get_string('edittable', 'atto_table'), + bodyContent: content + }); + + // Add event handlers for table control menus. + boundingBox = this._contextMenu.get('boundingBox'); + boundingBox.delegate('click', this._handleTableChange, 'a', this); + boundingBox.delegate('key', this._handleTableChange, 'down:enter,space', 'a', this); + } + boundingBox = this._contextMenu.get('boundingBox'); + + // We store the cell of the last click (the control node is transient). + this._lastTarget = e.tableCell.ancestor('.editor_atto_content td, .editor_atto_content th', true); + + // Show the context menu, and align to the current position. + this._contextMenu.show(); + this._contextMenu.align(e.tableCell, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]); + + // If there are any anchors in the bounding box, focus on the first. + if (boundingBox.one('a')) { + boundingBox.one('a').focus(); + } + }, + + /** + * Handle a selection from the table control menu. + * + * @method _handleTableChange + * @param {EventFacade} e + * @private + */ + _handleTableChange: function(e) { + e.preventDefault(); + + // Hide the context menu. + this._contextMenu.hide(); + + // Make our changes. + switch (e.target.getData('change')) { + case 'addcolumnafter': + this._addColumnAfter(); + break; + case 'addrowafter': + this._addRowAfter(); + break; + case 'deleterow': + this._deleteRow(); + break; + case 'deletecolumn': + this._deleteColumn(); + break; + case 'moverowdown': + this._moveRowDown(); + break; + case 'moverowup': + this._moveRowUp(); + break; + case 'movecolumnleft': + this._moveColumnLeft(); + break; + case 'movecolumnright': + this._moveColumnRight(); + break; + } + }, + + /** + * Determine the index of a row in a table column. + * + * @method _getRowIndex + * @param {Node} cell + * @private + */ + _getRowIndex: function(cell) { + var tablenode = cell.ancestor('table'), + rownode = cell.ancestor('tr'); + + if (!tablenode || !rownode) { + return; + } + + var rows = tablenode.all('tr'); + + return rows.indexOf(rownode); + }, + + /** + * Determine the index of a column in a table row. + * + * @method _getColumnIndex + * @param {Node} cellnode + * @private + */ + _getColumnIndex: function(cellnode) { + var rownode = cellnode.ancestor('tr'); + + if (!rownode) { + return; + } + + var cells = rownode.all('td, th'); + + return cells.indexOf(cellnode); + }, + + /** + * Delete the current row. + * + * @method _deleteRow + * @private + */ + _deleteRow: function() { + var row = this._lastTarget.ancestor('tr'); + + if (row) { + // We do not remove rows with no cells (all headers). + if (row.one('td')) { + row.remove(true); + } + } + + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Move row up + * + * @method _moveRowUp + * @private + */ + _moveRowUp: function() { + var row = this._lastTarget.ancestor('tr'); + var prevrow = row.previous('tr'); + if (!row || !prevrow) { + return; + } + + row.swap(prevrow); + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Move column left + * + * @method _moveColumnLeft + * @private + */ + _moveColumnLeft: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + var rows = this._lastTarget.ancestor('table').all('tr'); + var columncells = new Y.NodeList(); + var prevcells = new Y.NodeList(); + var hastd = false; + + rows.each(function(row) { + var cells = row.all('td, th'); + var cell = cells.item(columnindex), + cellprev = cells.item(columnindex-1); + columncells.push(cell); + if (cellprev) { + if (cellprev.get('tagName') === 'TD') { + hastd = true; + } + prevcells.push(cellprev); + } + }); + + if (hastd && prevcells.size() > 0) { + var i = 0; + for (i = 0; i < columncells.size(); i++) { + var cell = columncells.item(i); + var prevcell = prevcells.item(i); + + cell.swap(prevcell); + } + } + // Cleanup. + this.markUpdated(); + }, + + /** + * Move column right. + * + * @method _moveColumnRight + * @private + */ + _moveColumnRight: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + var rows = this._lastTarget.ancestor('table').all('tr'); + var columncells = new Y.NodeList(); + var nextcells = new Y.NodeList(); + var hastd = false; + + rows.each(function(row) { + var cells = row.all('td, th'); + var cell = cells.item(columnindex), + cellnext = cells.item(columnindex+1); + if (cell.get('tagName') === 'TD') { + hastd = true; + } + columncells.push(cell); + if (cellnext) { + nextcells.push(cellnext); + } + }); + + if (hastd && nextcells.size() > 0) { + var i = 0; + for (i = 0; i < columncells.size(); i++) { + var cell = columncells.item(i); + var nextcell = nextcells.item(i); + + cell.swap(nextcell); + } + } + // Cleanup. + this.markUpdated(); + }, + + /** + * Move row down. + * + * @method _moveRowDown + * @private + */ + _moveRowDown: function() { + var row = this._lastTarget.ancestor('tr'); + var nextrow = row.next('tr'); + if (!row || !nextrow) { + return; + } + + row.swap(nextrow); + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Delete the current column. + * + * @method _deleteColumn + * @private + */ + _deleteColumn: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + var rows = this._lastTarget.ancestor('table').all('tr'); + var columncells = new Y.NodeList(); + var hastd = false; + + rows.each(function(row) { + var cells = row.all('td, th'); + var cell = cells.item(columnindex); + if (cell.get('tagName') === 'TD') { + hastd = true; + } + columncells.push(cell); + }); + + if (hastd) { + columncells.remove(true); + } + + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Add a row after the current row. + * + * @method _addRowAfter + * @private + */ + _addRowAfter: function() { + var rowindex = this._getRowIndex(this._lastTarget); + + var tablebody = this._lastTarget.ancestor('table').one('tbody'); + if (!tablebody) { + // Not all tables have tbody. + tablebody = this._lastTarget.ancestor('table'); + rowindex += 1; + } + + var firstrow = tablebody.one('tr'); + if (!firstrow) { + firstrow = this._lastTarget.ancestor('table').one('tr'); + } + if (!firstrow) { + // Table has no rows. Boo. + return; + } + newrow = firstrow.cloneNode(true); + newrow.all('th, td').each(function (tablecell) { + if (tablecell.get('tagName') === 'TH') { + if (tablecell.getAttribute('scope') !== 'row') { + var newcell = Y.Node.create(''); + tablecell.replace(newcell); + tablecell = newcell; + } + } + tablecell.setHTML(' '); + }); + + tablebody.insert(newrow, rowindex); + + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Add a column after the current column. + * + * @method _addColumnAfter + * @private + */ + _addColumnAfter: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + + var tablecell = this._lastTarget.ancestor('table'); + var rows = tablecell.all('tr'); + Y.each(rows, function(row) { + // Clone the first cell from the row so it has the same type/attributes (e.g. scope). + var newcell = row.one('td, th').cloneNode(true); + // Clear the content of the cell. + newcell.setHTML(' '); + + row.insert(newcell, columnindex + 1); + }, this); + + // Clean the HTML. + this.markUpdated(); } -}; +}); -}, '@VERSION@', {"requires": ["node", "escape", "event", "event-valuechange"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin", "moodle-editor_atto-menu", "event", "event-valuechange"]}); 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 29dcf8983b5..f0e52b76d44 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 @@ -14,537 +14,194 @@ // along with Moodle. If not, see . /** - * Selectors. - * - * @type {Object} + * @package atto_table + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @module moodle-atto_table-button */ -var SELECTORS = { - TAGS : 'table' -}; /** * Atto text editor table plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_table + * @class Button + * @extends M.editor_atto.EditorPlugin */ -M.atto_table = M.atto_table || { + +var COMPONENT = 'atto_table', + TEMPLATE = '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        ' + + '' + + '
                                        ' + + '
                                        ' + + '
                                        {{{get_string "accessibilityhint" component}}}', + CONTEXTMENUTEMPLATE = '' + + '
                                        '; + + CSS = { + }; + +Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { /** - * The window used to get the table details. + * A reference to the current selection at the time that the dialogue + * was opened. * - * @property dialogue - * @type M.core.dialogue - * @default null - */ - dialogue : null, - - /** - * The selection object returned by the browser. - * - * @property selection + * @property _currentSelection * @type Range - * @default null + * @private */ - selection : null, + _currentSelection: null, /** - * Yui image for table editing controls. + * The contextual menu that we can open. * - * @property menunode - * @type Y.Node - * @default null + * @property _contextMenu + * @type M.editor_atto.Menu + * @private */ - menunode : null, + _contextMenu: null, /** - * Popup menu for table controls + * The last modified target. * - * @property controlmenu - * @type M.editor_atto.controlmenu - * @default null + * @property _lastTarget + * @type Node + * @private */ - controlmenu : null, + _lastTarget: null, - /** - * Last clicked cell that opened the context menu. - * - * @property lasttarget - * @type Y.Node - * @default null - */ - lasttarget : null, - - /** - * Display the chooser dialogue. - * - * @method init - * @param Event e - * @param string elementid - */ - display_chooser : function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - M.atto_table.selection = M.editor_atto.get_selection(); - if (M.atto_table.selection !== false && (!M.atto_table.selection.collapsed)) { - var dialogue; - if (!M.atto_table.dialogue) { - dialogue = new M.core.dialogue({ - visible: false, - modal: true, - close: true, - draggable: true - }); - } else { - dialogue = M.atto_table.dialogue; - } - - dialogue.render(); - dialogue.set('bodyContent', M.atto_table.get_form_content(elementid)); - dialogue.set('headerContent', M.util.get_string('createtable', 'atto_table')); - - dialogue.show(); - M.atto_table.dialogue = dialogue; - } - - }, - - /** - * Show the context menu - * - * @method show_menu - * @param Event e - * @param string elementid - */ - show_menu : function(e, elementid) { - var addhandlers = false; - - e.preventDefault(); - - if (this.controlmenu === null) { - addhandlers = true; - // Add event handlers for table control menus. - var bodycontent = ''; - - this.controlmenu = new M.editor_atto.controlmenu({ - headerText : M.util.get_string('edittable', 'atto_table'), - bodyContent : bodycontent - }); - } - // We store the cell of the last click (the control node is transient). - this.lasttarget = e.target.ancestor('.editor_atto_content td, .editor_atto_content th', true); - this.controlmenu.show(); - this.controlmenu.align(e.target, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]); - var bodynode = this.controlmenu.get('boundingBox'); - if (bodynode.one('a')) { - bodynode.one('a').focus(); - } - - if (addhandlers) { - bodynode.delegate('click', this.handle_table_control, 'a', this, elementid); - bodynode.delegate('key', this.handle_table_control, 'down:enter,space', 'a', this, elementid); - } - }, - - /** - * Determine the index of a row in a table column. - * - * @method get_row_index - * @param Y.Node node - */ - get_row_index : function(cell) { - var tablenode = cell.ancestor('table'), - rownode = cell.ancestor('tr'); - - if (!tablenode || !rownode) { - return; - } - - var rows = tablenode.all('tr'); - - return rows.indexOf(rownode); - }, - - /** - * Determine the index of a column in a table row. - * - * @method get_column_index - * @param Y.Node node - */ - get_column_index : function(cellnode) { - var rownode = cellnode.ancestor('tr'); - - if (!rownode) { - return; - } - - var cells = rownode.all('td, th'); - - return cells.indexOf(cellnode); - }, - - /** - * Delete the current row - * - * @method delete_row - * @param string elementid - */ - delete_row : function(elementid) { - var row = this.lasttarget.ancestor('tr'); - - if (row) { - // We do not remove rows with no cells (all headers). - if (row.one('td')) { - row.remove(true); - } - } - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move row up - * - * @method move_row_up - * @param string elementid - */ - move_row_up : function(elementid) { - var row = this.lasttarget.ancestor('tr'); - var prevrow = row.previous('tr'); - if (!row || !prevrow) { - return; - } - - row.swap(prevrow); - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move column left - * - * @method move_column_left - * @param string elementid - */ - move_column_left : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - var rows = this.lasttarget.ancestor('table').all('tr'); - var columncells = new Y.NodeList(); - var prevcells = new Y.NodeList(); - var hastd = false; - - rows.each(function(row) { - var cells = row.all('td, th'); - var cell = cells.item(columnindex), - cellprev = cells.item(columnindex-1); - columncells.push(cell); - if (cellprev) { - if (cellprev.get('tagName') === 'TD') { - hastd = true; - } - prevcells.push(cellprev); - } + initializer: function() { + this.addButton({ + icon: 'e/table', + callback: this._displayTableEditor, + tags: 'table' }); - if (hastd && prevcells.size() > 0) { - var i = 0; - for (i = 0; i < columncells.size(); i++) { - var cell = columncells.item(i); - var prevcell = prevcells.item(i); - - cell.swap(prevcell); - } - } - // Cleanup. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move column right - * - * @method move_column_right - * @param string elementid - */ - move_column_right : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - var rows = this.lasttarget.ancestor('table').all('tr'); - var columncells = new Y.NodeList(); - var nextcells = new Y.NodeList(); - var hastd = false; - - rows.each(function(row) { - var cells = row.all('td, th'); - var cell = cells.item(columnindex), - cellnext = cells.item(columnindex+1); - if (cell.get('tagName') === 'TD') { - hastd = true; - } - columncells.push(cell); - if (cellnext) { - nextcells.push(cellnext); - } - }); - - if (hastd && nextcells.size() > 0) { - var i = 0; - for (i = 0; i < columncells.size(); i++) { - var cell = columncells.item(i); - var nextcell = nextcells.item(i); - - cell.swap(nextcell); - } - } - // Cleanup. - M.editor_atto.text_updated(elementid); - }, - - /** - * Move row down - * - * @method move_row_down - * @param string elementid - */ - move_row_down : function(elementid) { - var row = this.lasttarget.ancestor('tr'); - var nextrow = row.next('tr'); - if (!row || !nextrow) { - return; - } - - row.swap(nextrow); - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Delete the current column - * - * @method delete_column - * @param string elementid - */ - delete_column : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - var rows = this.lasttarget.ancestor('table').all('tr'); - var columncells = new Y.NodeList(); - var hastd = false; - - rows.each(function(row) { - var cells = row.all('td, th'); - var cell = cells.item(columnindex); - if (cell.get('tagName') === 'TD') { - hastd = true; - } - columncells.push(cell); - }); - - if (hastd) { - columncells.remove(true); - } - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Add a row after the current row. - * - * @method add_row_after - * @param string elementid - */ - add_row_after : function(elementid) { - var rowindex = this.get_row_index(this.lasttarget); - - var tablebody = this.lasttarget.ancestor('table').one('tbody'); - if (!tablebody) { - // Not all tables have tbody. - tablebody = this.lasttarget.ancestor('table'); - rowindex += 1; - } - - var firstrow = tablebody.one('tr'); - if (!firstrow) { - firstrow = this.lasttarget.ancestor('table').one('tr'); - } - if (!firstrow) { - // Table has no rows. Boo. - return; - } - newrow = firstrow.cloneNode(true); - newrow.all('th, td').each(function (tablecell) { - if (tablecell.get('tagName') === 'TH') { - if (tablecell.getAttribute('scope') !== 'row') { - var newcell = Y.Node.create(''); - tablecell.replace(newcell); - tablecell = newcell; - } - } - tablecell.setHTML(' '); - }); - - tablebody.insert(newrow, rowindex); - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Add a column after the current column. - * - * @method add_column_after - * @param string elementid - */ - add_column_after : function(elementid) { - var columnindex = this.get_column_index(this.lasttarget); - - var tablecell = this.lasttarget.ancestor('table'); - var rows = tablecell.all('tr'); - Y.each(rows, function(row) { - // Clone the first cell from the row so it has the same type/attributes (e.g. scope). - var newcell = row.one('td, th').cloneNode(true); - // Clear the content of the cell. - newcell.setHTML(' '); - - row.insert(newcell, columnindex + 1); - }, this); - - // Clean the HTML. - M.editor_atto.text_updated(elementid); - }, - - /** - * Handle a button click - this will either open the new table dialogue, - * or the edit table context menu. - * - * @method handle_button - * @param Y.Event event - * @param string elementid - */ - handle_button : function(event, elementid) { - var selection = M.editor_atto.get_selection_parent_node(); - var editable = M.editor_atto.get_editable_node(elementid); - var cell; - - if (!selection) { - return M.atto_table.display_chooser(event, elementid); - } - Y.one(selection).ancestors('th, td', true).each(function(node) { - if (editable.contains(node)) { - cell = node; - } - }); - - if (cell) { - event.target = cell; - return M.atto_table.show_menu(event, elementid); - } - return M.atto_table.display_chooser(event, elementid); - }, - - - /** - * Handle a selection from the table control menu. - * - * @method handle_table_control - * @param Y.Event event - * @param string elementid - */ - handle_table_control : function(event, elementid) { - event.preventDefault(); - - this.controlmenu.hide(); - - switch (event.target.get('id')) { - case 'addcolumnafter': - this.add_column_after(elementid); - break; - case 'addrowafter': - this.add_row_after(elementid); - break; - case 'deleterow': - this.delete_row(elementid); - break; - case 'deletecolumn': - this.delete_column(elementid); - break; - case 'moverowdown': - this.move_row_down(elementid); - break; - case 'moverowup': - this.move_row_up(elementid); - break; - case 'movecolumnleft': - this.move_column_left(elementid); - break; - case 'movecolumnright': - this.move_column_right(elementid); - break; - } - }, - - /** - * Add this button to the form. - * - * @method init - * @param {Object} params - */ - init : function(params) { - - if (!M.atto_table.menunode) { - // Used for inline table editing controls. - var img = Y.Node.create(''); - img.setAttrs({ - alt : M.util.get_string('edittable', 'atto_table'), - src : M.util.image_url('t/contextmenu', 'core'), - width : '12', - height : '12' - }); - var anchor = Y.Node.create(''); - anchor.appendChild(img); - anchor.addClass('atto_control'); - M.atto_table.menunode = anchor; - } - - var iconurl = M.util.image_url('e/table', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'table', iconurl, params.group, this.handle_button); - // Disable mozilla table controls. if (Y.UA.gecko) { document.execCommand("enableInlineTableEditing", false, false); 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. - M.editor_atto.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'); - } - }); }, /** - * The OK button has been pressed - make the changes to the source. + * Display the table tool. * - * @method set_table - * @param Event e + * @method _displayDialogue + * @private */ - set_table : function(e, elementid) { + _displayDialogue: function() { + // Store the current cursor position. + this._currentSelection = this.get('host').getSelection(); + + if (this._currentSelection !== false && (!this._currentSelection.collapsed)) { + var dialogue = this.getDialogue({ + headerContent: M.util.get_string('createtable', COMPONENT), + focusAfterHide: true + }); + + // Set the dialogue content, and then show the dialogue. + dialogue.set('bodyContent', this._getDialogueContent()) + .show(); + } + }, + + /** + * Display the appropriate table editor. + * + * If the current selection includes a table, then we show the + * contextual menu, otherwise show the table creation dialogue. + * + * @method _displayTableEditor + * @param {EventFacade} e + * @private + */ + _displayTableEditor: function(e) { + var selection = this.get('host').getSelectionParentNode(), + cell; + + if (!selection) { + // We don't have a current selection at all, so show the standard dialogue. + return this._displayDialogue(e); + } + + // Check all of the table cells found in the selection. + Y.one(selection).ancestors('th, td', true).each(function(node) { + if (this.editor.contains(node)) { + cell = node; + } + }, this); + + if (cell) { + // Add the cell to the EventFacade to save duplication in when showing the menu. + e.tableCell = cell; + return this._showTableMenu(e); + } + + return this._displayDialogue(e); + }, + + /** + * Return the dialogue content for the tool, attaching any required + * events. + * + * @method _getDialogueContent + * @private + * @return {Node} The content to place in the dialogue. + */ + _getDialogueContent: function() { + var template = Y.Handlebars.compile(TEMPLATE); + this._content = Y.Node.create(template({ + CSS: CSS, + elementid: this.get('host').get('elementid'), + component: COMPONENT + })); + + // Handle table setting. + this._content.one('.submit').on('click', this._setTable, this); + + return this._content; + }, + + /** + * Handle creation of a new table. + * + * @method _setTable + * @param {EventFacade} e + * @private + */ + _setTable: function(e) { var caption, rows, cols, @@ -553,14 +210,19 @@ M.atto_table = M.atto_table || { i, j; e.preventDefault(); - M.atto_table.dialogue.hide(); - caption = e.currentTarget.ancestor('.atto_form').one('#atto_table_caption'); - rows = e.currentTarget.ancestor('.atto_form').one('#atto_table_rows'); - cols = e.currentTarget.ancestor('.atto_form').one('#atto_table_columns'); - headers = e.currentTarget.ancestor('.atto_form').one('#atto_table_headers'); + // Hide the dialogue. + this.getDialogue({ + focusAfterHide: null + }).hide(); - M.editor_atto.set_selection(M.atto_table.selection); + caption = e.currentTarget.ancestor('.atto_form').one('.caption'); + rows = e.currentTarget.ancestor('.atto_form').one('.rows'); + cols = e.currentTarget.ancestor('.atto_form').one('.columns'); + headers = e.currentTarget.ancestor('.atto_form').one('.headers'); + + // Set the selection. + this.get('host').setSelection(this._currentSelection); // Note there are some spaces inserted in the cells and before and after, so that users have somewhere to click. var nl = "\n"; @@ -591,51 +253,363 @@ M.atto_table = M.atto_table || { tablehtml += '' + nl; tablehtml += '' + nl + '
                                        '; - M.editor_atto.insert_html_at_focus_point(tablehtml); + this.get('host').insertContentAtFocusPoint(tablehtml); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + // Mark the content as updated. + this.markUpdated(); }, /** - * Return the HTML of the form to show in the dialogue. + * Display the table menu. * - * @method get_form_content - * @param string elementid - * @return string + * @method _showTableMenu + * @param {EventFacade} e + * @private */ - get_form_content : function(elementid) { - var content = Y.Node.create('
                                        ' + - '' + - '' + - '
                                        ' + - '' + - '' + - '
                                        ' + - '' + - '' + - '
                                        ' + - '' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + - '' + - '
                                        ' + - '
                                        ' + - '
                                        ' + M.util.get_string('accessibilityhint', 'atto_table')); + _showTableMenu: function(e) { + e.preventDefault(); - content.one('#atto_table_submit').on('click', M.atto_table.set_table, this, elementid); - return content; + var boundingBox; + + if (!this._contextMenu) { + var template = Y.Handlebars.compile(CONTEXTMENUTEMPLATE), + content = Y.Node.create(template({ + elementid: this.get('host').get('elementid'), + component: COMPONENT + })); + + this._contextMenu = new Y.M.editor_atto.Menu({ + headerText: M.util.get_string('edittable', 'atto_table'), + bodyContent: content + }); + + // Add event handlers for table control menus. + boundingBox = this._contextMenu.get('boundingBox'); + boundingBox.delegate('click', this._handleTableChange, 'a', this); + boundingBox.delegate('key', this._handleTableChange, 'down:enter,space', 'a', this); + } + boundingBox = this._contextMenu.get('boundingBox'); + + // We store the cell of the last click (the control node is transient). + this._lastTarget = e.tableCell.ancestor('.editor_atto_content td, .editor_atto_content th', true); + + // Show the context menu, and align to the current position. + this._contextMenu.show(); + this._contextMenu.align(e.tableCell, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]); + + // If there are any anchors in the bounding box, focus on the first. + if (boundingBox.one('a')) { + boundingBox.one('a').focus(); + } + }, + + /** + * Handle a selection from the table control menu. + * + * @method _handleTableChange + * @param {EventFacade} e + * @private + */ + _handleTableChange: function(e) { + e.preventDefault(); + + // Hide the context menu. + this._contextMenu.hide(); + + // Make our changes. + switch (e.target.getData('change')) { + case 'addcolumnafter': + this._addColumnAfter(); + break; + case 'addrowafter': + this._addRowAfter(); + break; + case 'deleterow': + this._deleteRow(); + break; + case 'deletecolumn': + this._deleteColumn(); + break; + case 'moverowdown': + this._moveRowDown(); + break; + case 'moverowup': + this._moveRowUp(); + break; + case 'movecolumnleft': + this._moveColumnLeft(); + break; + case 'movecolumnright': + this._moveColumnRight(); + break; + } + }, + + /** + * Determine the index of a row in a table column. + * + * @method _getRowIndex + * @param {Node} cell + * @private + */ + _getRowIndex: function(cell) { + var tablenode = cell.ancestor('table'), + rownode = cell.ancestor('tr'); + + if (!tablenode || !rownode) { + return; + } + + var rows = tablenode.all('tr'); + + return rows.indexOf(rownode); + }, + + /** + * Determine the index of a column in a table row. + * + * @method _getColumnIndex + * @param {Node} cellnode + * @private + */ + _getColumnIndex: function(cellnode) { + var rownode = cellnode.ancestor('tr'); + + if (!rownode) { + return; + } + + var cells = rownode.all('td, th'); + + return cells.indexOf(cellnode); + }, + + /** + * Delete the current row. + * + * @method _deleteRow + * @private + */ + _deleteRow: function() { + var row = this._lastTarget.ancestor('tr'); + + if (row) { + // We do not remove rows with no cells (all headers). + if (row.one('td')) { + row.remove(true); + } + } + + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Move row up + * + * @method _moveRowUp + * @private + */ + _moveRowUp: function() { + var row = this._lastTarget.ancestor('tr'); + var prevrow = row.previous('tr'); + if (!row || !prevrow) { + return; + } + + row.swap(prevrow); + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Move column left + * + * @method _moveColumnLeft + * @private + */ + _moveColumnLeft: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + var rows = this._lastTarget.ancestor('table').all('tr'); + var columncells = new Y.NodeList(); + var prevcells = new Y.NodeList(); + var hastd = false; + + rows.each(function(row) { + var cells = row.all('td, th'); + var cell = cells.item(columnindex), + cellprev = cells.item(columnindex-1); + columncells.push(cell); + if (cellprev) { + if (cellprev.get('tagName') === 'TD') { + hastd = true; + } + prevcells.push(cellprev); + } + }); + + if (hastd && prevcells.size() > 0) { + var i = 0; + for (i = 0; i < columncells.size(); i++) { + var cell = columncells.item(i); + var prevcell = prevcells.item(i); + + cell.swap(prevcell); + } + } + // Cleanup. + this.markUpdated(); + }, + + /** + * Move column right. + * + * @method _moveColumnRight + * @private + */ + _moveColumnRight: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + var rows = this._lastTarget.ancestor('table').all('tr'); + var columncells = new Y.NodeList(); + var nextcells = new Y.NodeList(); + var hastd = false; + + rows.each(function(row) { + var cells = row.all('td, th'); + var cell = cells.item(columnindex), + cellnext = cells.item(columnindex+1); + if (cell.get('tagName') === 'TD') { + hastd = true; + } + columncells.push(cell); + if (cellnext) { + nextcells.push(cellnext); + } + }); + + if (hastd && nextcells.size() > 0) { + var i = 0; + for (i = 0; i < columncells.size(); i++) { + var cell = columncells.item(i); + var nextcell = nextcells.item(i); + + cell.swap(nextcell); + } + } + // Cleanup. + this.markUpdated(); + }, + + /** + * Move row down. + * + * @method _moveRowDown + * @private + */ + _moveRowDown: function() { + var row = this._lastTarget.ancestor('tr'); + var nextrow = row.next('tr'); + if (!row || !nextrow) { + return; + } + + row.swap(nextrow); + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Delete the current column. + * + * @method _deleteColumn + * @private + */ + _deleteColumn: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + var rows = this._lastTarget.ancestor('table').all('tr'); + var columncells = new Y.NodeList(); + var hastd = false; + + rows.each(function(row) { + var cells = row.all('td, th'); + var cell = cells.item(columnindex); + if (cell.get('tagName') === 'TD') { + hastd = true; + } + columncells.push(cell); + }); + + if (hastd) { + columncells.remove(true); + } + + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Add a row after the current row. + * + * @method _addRowAfter + * @private + */ + _addRowAfter: function() { + var rowindex = this._getRowIndex(this._lastTarget); + + var tablebody = this._lastTarget.ancestor('table').one('tbody'); + if (!tablebody) { + // Not all tables have tbody. + tablebody = this._lastTarget.ancestor('table'); + rowindex += 1; + } + + var firstrow = tablebody.one('tr'); + if (!firstrow) { + firstrow = this._lastTarget.ancestor('table').one('tr'); + } + if (!firstrow) { + // Table has no rows. Boo. + return; + } + newrow = firstrow.cloneNode(true); + newrow.all('th, td').each(function (tablecell) { + if (tablecell.get('tagName') === 'TH') { + if (tablecell.getAttribute('scope') !== 'row') { + var newcell = Y.Node.create(''); + tablecell.replace(newcell); + tablecell = newcell; + } + } + tablecell.setHTML(' '); + }); + + tablebody.insert(newrow, rowindex); + + // Clean the HTML. + this.markUpdated(); + }, + + /** + * Add a column after the current column. + * + * @method _addColumnAfter + * @private + */ + _addColumnAfter: function() { + var columnindex = this._getColumnIndex(this._lastTarget); + + var tablecell = this._lastTarget.ancestor('table'); + var rows = tablecell.all('tr'); + Y.each(rows, function(row) { + // Clone the first cell from the row so it has the same type/attributes (e.g. scope). + var newcell = row.one('td, th').cloneNode(true); + // Clear the content of the cell. + newcell.setHTML(' '); + + row.insert(newcell, columnindex + 1); + }, this); + + // Clean the HTML. + this.markUpdated(); } -}; +}); diff --git a/lib/editor/atto/plugins/table/yui/src/button/meta/button.json b/lib/editor/atto/plugins/table/yui/src/button/meta/button.json index b36d2785778..f3130f23c99 100644 --- a/lib/editor/atto/plugins/table/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/table/yui/src/button/meta/button.json @@ -1,10 +1,10 @@ { - "moodle-atto_table-button": { - "requires": [ - "node", - "escape", - "event", - "event-valuechange" - ] - } + "moodle-atto_table-button": { + "requires": [ + "moodle-editor_atto-plugin", + "moodle-editor_atto-menu", + "event", + "event-valuechange" + ] + } } diff --git a/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button-debug.js b/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button-debug.js index e60d30481d1..d125c8c5003 100644 --- a/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button-debug.js +++ b/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button-debug.js @@ -15,68 +15,81 @@ YUI.add('moodle-atto_title-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_title + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @module moodle-atto_title-button + */ + /** * Atto text editor title plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_title + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_title = M.atto_title || { - init : function(params) { - var click_h3 = function(e, elementid) { - M.atto_title.change_title(e, elementid, '

                                        '); - }; - var click_h4 = function(e, elementid) { - M.atto_title.change_title(e, elementid, '

                                        '); - }; - var click_h5 = function(e, elementid) { - M.atto_title.change_title(e, elementid, '

                                        '); - }; - var click_pre = function(e, elementid) { - M.atto_title.change_title(e, elementid, '
                                        ');
                                        -        };
                                        -        var click_p = function(e, elementid) {
                                        -            M.atto_title.change_title(e, elementid, '

                                        '); - }; - var h3 = M.util.get_string('h3', 'atto_title'); - var h4 = M.util.get_string('h4', 'atto_title'); - var h5 = M.util.get_string('h5', 'atto_title'); - var pre = M.util.get_string('pre', 'atto_title'); - var p = M.util.get_string('p', 'atto_title'); +var component = 'atto_title', + styles = [ + { + text: 'h3', + callbackArgs: '

                                        ' + }, + { + text: 'h4', + callbackArgs: '

                                        ' + }, + { + text: 'h5', + callbackArgs: '

                                        ' + }, + { + text: 'pre', + callbackArgs: '
                                        '
                                        +        },
                                        +        {
                                        +            text: 'p',
                                        +            callbackArgs: '

                                        ' + } + ]; - var iconurl = M.util.image_url('e/styleprops', 'core'); - - M.editor_atto.add_toolbar_menu(params.elementid, - 'title', - iconurl, - params.group, - [ - {'text' : h3, 'handler' : click_h3}, - {'text' : h4, 'handler' : click_h4}, - {'text' : h5, 'handler' : click_h5}, - {'text' : pre, 'handler' : click_pre}, - {'text' : p, 'handler' : click_p} - ]); +Y.namespace('M.atto_title').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var items = []; + Y.Array.each(styles, function(style) { + items.push({ + text: M.util.get_string(style.text, component), + callbackArgs: style.callbackArgs + }); + }); + this.addToolbarMenu({ + icon: 'e/styleprops', + globalItemConfig: { + callback: this._changeStyle + }, + items: items + }); }, /** - * Handle a choice from the menu (insert the node in the text editor matching elementid). - * @param event e - The event that triggered this. - * @param string elementid - The id of the editor - * @param string node - The html to insert + * Change the title to the specified style. + * + * @method _changeStyle + * @param {EventFacade} e + * @param {string} color The new style + * @private */ - change_title : function(e, elementid, node) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('formatBlock', false, node); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + _changeStyle: function(e, style) { + document.execCommand('formatBlock', false, style); + + // Mark as updated + this.markUpdated(); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button-min.js b/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button-min.js index 1c110c7b018..82eccb813a9 100644 --- a/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button-min.js +++ b/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button-min.js @@ -1 +1 @@ -YUI.add("moodle-atto_title-button",function(e,t){M.atto_title=M.atto_title||{init:function(e){var t=function(e,t){M.atto_title.change_title(e,t,"

                                        ")},n=function(e,t){M.atto_title.change_title(e,t,"

                                        ")},r=function(e,t){M.atto_title.change_title(e,t,"

                                        ")},i=function(e,t){M.atto_title.change_title(e,t,"
                                        ")},s=function(e,t){M.atto_title.change_title(e,t,"

                                        ")},o=M.util.get_string("h3","atto_title"),u=M.util.get_string("h4","atto_title"),a=M.util.get_string("h5","atto_title"),f=M.util.get_string("pre","atto_title"),l=M.util.get_string("p","atto_title"),c=M.util.image_url("e/styleprops","core");M.editor_atto.add_toolbar_menu(e.elementid,"title",c,e.group,[{text:o,handler:t},{text:u,handler:n},{text:a,handler:r},{text:f,handler:i},{text:l,handler:s}])},change_title:function(e,t,n){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),document.execCommand("formatBlock",!1,n),M.editor_atto.text_updated(t)}}},"@VERSION@",{requires:["node"]}); +YUI.add("moodle-atto_title-button",function(e,t){var n="atto_title",r=[{text:"h3",callbackArgs:"

                                        "},{text:"h4",callbackArgs:"

                                        "},{text:"h5",callbackArgs:"

                                        "},{text:"pre",callbackArgs:"
                                        "},{text:"p",callbackArgs:"

                                        "}];e.namespace("M.atto_title").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){var t=[];e.Array.each(r,function(e){t.push({text:M.util.get_string(e.text,n),callbackArgs:e.callbackArgs})}),this.addToolbarMenu({icon:"e/styleprops",globalItemConfig:{callback:this._changeStyle},items:t})},_changeStyle:function(e,t){document.execCommand("formatBlock",!1,t),this.markUpdated()}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button.js b/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button.js index e60d30481d1..d125c8c5003 100644 --- a/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button.js +++ b/lib/editor/atto/plugins/title/yui/build/moodle-atto_title-button/moodle-atto_title-button.js @@ -15,68 +15,81 @@ YUI.add('moodle-atto_title-button', function (Y, NAME) { // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_title + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @module moodle-atto_title-button + */ + /** * Atto text editor title plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_title + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_title = M.atto_title || { - init : function(params) { - var click_h3 = function(e, elementid) { - M.atto_title.change_title(e, elementid, '

                                        '); - }; - var click_h4 = function(e, elementid) { - M.atto_title.change_title(e, elementid, '

                                        '); - }; - var click_h5 = function(e, elementid) { - M.atto_title.change_title(e, elementid, '

                                        '); - }; - var click_pre = function(e, elementid) { - M.atto_title.change_title(e, elementid, '
                                        ');
                                        -        };
                                        -        var click_p = function(e, elementid) {
                                        -            M.atto_title.change_title(e, elementid, '

                                        '); - }; - var h3 = M.util.get_string('h3', 'atto_title'); - var h4 = M.util.get_string('h4', 'atto_title'); - var h5 = M.util.get_string('h5', 'atto_title'); - var pre = M.util.get_string('pre', 'atto_title'); - var p = M.util.get_string('p', 'atto_title'); +var component = 'atto_title', + styles = [ + { + text: 'h3', + callbackArgs: '

                                        ' + }, + { + text: 'h4', + callbackArgs: '

                                        ' + }, + { + text: 'h5', + callbackArgs: '

                                        ' + }, + { + text: 'pre', + callbackArgs: '
                                        '
                                        +        },
                                        +        {
                                        +            text: 'p',
                                        +            callbackArgs: '

                                        ' + } + ]; - var iconurl = M.util.image_url('e/styleprops', 'core'); - - M.editor_atto.add_toolbar_menu(params.elementid, - 'title', - iconurl, - params.group, - [ - {'text' : h3, 'handler' : click_h3}, - {'text' : h4, 'handler' : click_h4}, - {'text' : h5, 'handler' : click_h5}, - {'text' : pre, 'handler' : click_pre}, - {'text' : p, 'handler' : click_p} - ]); +Y.namespace('M.atto_title').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var items = []; + Y.Array.each(styles, function(style) { + items.push({ + text: M.util.get_string(style.text, component), + callbackArgs: style.callbackArgs + }); + }); + this.addToolbarMenu({ + icon: 'e/styleprops', + globalItemConfig: { + callback: this._changeStyle + }, + items: items + }); }, /** - * Handle a choice from the menu (insert the node in the text editor matching elementid). - * @param event e - The event that triggered this. - * @param string elementid - The id of the editor - * @param string node - The html to insert + * Change the title to the specified style. + * + * @method _changeStyle + * @param {EventFacade} e + * @param {string} color The new style + * @private */ - change_title : function(e, elementid, node) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('formatBlock', false, node); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + _changeStyle: function(e, style) { + document.execCommand('formatBlock', false, style); + + // Mark as updated + this.markUpdated(); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); diff --git a/lib/editor/atto/plugins/title/yui/src/button/js/button.js b/lib/editor/atto/plugins/title/yui/src/button/js/button.js index 3b0127fc345..80bfad15f1f 100644 --- a/lib/editor/atto/plugins/title/yui/src/button/js/button.js +++ b/lib/editor/atto/plugins/title/yui/src/button/js/button.js @@ -13,65 +13,78 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_title + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @module moodle-atto_title-button + */ + /** * Atto text editor title plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_title + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_title = M.atto_title || { - init : function(params) { - var click_h3 = function(e, elementid) { - M.atto_title.change_title(e, elementid, '

                                        '); - }; - var click_h4 = function(e, elementid) { - M.atto_title.change_title(e, elementid, '

                                        '); - }; - var click_h5 = function(e, elementid) { - M.atto_title.change_title(e, elementid, '

                                        '); - }; - var click_pre = function(e, elementid) { - M.atto_title.change_title(e, elementid, '
                                        ');
                                        -        };
                                        -        var click_p = function(e, elementid) {
                                        -            M.atto_title.change_title(e, elementid, '

                                        '); - }; - var h3 = M.util.get_string('h3', 'atto_title'); - var h4 = M.util.get_string('h4', 'atto_title'); - var h5 = M.util.get_string('h5', 'atto_title'); - var pre = M.util.get_string('pre', 'atto_title'); - var p = M.util.get_string('p', 'atto_title'); +var component = 'atto_title', + styles = [ + { + text: 'h3', + callbackArgs: '

                                        ' + }, + { + text: 'h4', + callbackArgs: '

                                        ' + }, + { + text: 'h5', + callbackArgs: '

                                        ' + }, + { + text: 'pre', + callbackArgs: '
                                        '
                                        +        },
                                        +        {
                                        +            text: 'p',
                                        +            callbackArgs: '

                                        ' + } + ]; - var iconurl = M.util.image_url('e/styleprops', 'core'); - - M.editor_atto.add_toolbar_menu(params.elementid, - 'title', - iconurl, - params.group, - [ - {'text' : h3, 'handler' : click_h3}, - {'text' : h4, 'handler' : click_h4}, - {'text' : h5, 'handler' : click_h5}, - {'text' : pre, 'handler' : click_pre}, - {'text' : p, 'handler' : click_p} - ]); +Y.namespace('M.atto_title').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + var items = []; + Y.Array.each(styles, function(style) { + items.push({ + text: M.util.get_string(style.text, component), + callbackArgs: style.callbackArgs + }); + }); + this.addToolbarMenu({ + icon: 'e/styleprops', + globalItemConfig: { + callback: this._changeStyle + }, + items: items + }); }, /** - * Handle a choice from the menu (insert the node in the text editor matching elementid). - * @param event e - The event that triggered this. - * @param string elementid - The id of the editor - * @param string node - The html to insert + * Change the title to the specified style. + * + * @method _changeStyle + * @param {EventFacade} e + * @param {string} color The new style + * @private */ - change_title : function(e, elementid, node) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('formatBlock', false, node); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + _changeStyle: function(e, style) { + document.execCommand('formatBlock', false, style); + + // Mark as updated + this.markUpdated(); } -}; +}); diff --git a/lib/editor/atto/plugins/title/yui/src/button/meta/button.json b/lib/editor/atto/plugins/title/yui/src/button/meta/button.json index c073041342e..18e0aab9659 100644 --- a/lib/editor/atto/plugins/title/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/title/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_title-button": { - "requires": ["node"] - } + "moodle-atto_title-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } 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 2eb63f9fd89..91894955151 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,50 +15,37 @@ 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 . +/* + * @package atto_underline + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_underline-button */ -var SELECTORS = { - TAGS : 'u' -}; /** * Atto text editor underline plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_underline + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_underline = M.atto_underline || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('underline', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - 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}); +Y.namespace('M.atto_underline').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'underline', - // 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. - M.editor_atto.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'); - } + // Key code for the keyboard shortcut which triggers this button: + keys: '85', + + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'u' }); } -}; +}); -}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 4a5f5dada6f..b81cee34be7 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),M.editor_atto.add_button_shortcut({action:"underline",keys:85}),M.editor_atto.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"]}); +YUI.add("moodle-atto_underline-button",function(e,t){e.namespace("M.atto_underline").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"underline",keys:"85",tags:"u"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 2eb63f9fd89..91894955151 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,50 +15,37 @@ 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 . +/* + * @package atto_underline + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_underline-button */ -var SELECTORS = { - TAGS : 'u' -}; /** * Atto text editor underline plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_underline + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_underline = M.atto_underline || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('underline', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - 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}); +Y.namespace('M.atto_underline').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'underline', - // 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. - M.editor_atto.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'); - } + // Key code for the keyboard shortcut which triggers this button: + keys: '85', + + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'u' }); } -}; +}); -}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 c2f0b3246f5..cb27d25d653 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,47 +13,34 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_underline + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_underline-button */ -var SELECTORS = { - TAGS : 'u' -}; /** * Atto text editor underline plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_underline + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_underline = M.atto_underline || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('underline', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - 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}); +Y.namespace('M.atto_underline').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'underline', - // 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. - M.editor_atto.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'); - } + // Key code for the keyboard shortcut which triggers this button: + keys: '85', + + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'u' }); } -}; +}); 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 8e9cea14ddd..27420341a90 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,7 @@ { - "moodle-atto_underline-button": { - "requires": ["node", "moodle-editor_atto-editor-shortcut"] - } + "moodle-atto_underline-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } 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 6143f87a008..50a76a4da80 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 @@ -16,132 +16,166 @@ YUI.add('moodle-atto_undo-button', function (Y, NAME) { // along with Moodle. If not, see . /** - * Atto text editor undo plugin. - * - * @package editor-undo + * @component atto_undo * @copyright 2014 Jerome Mouneyrac * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_undo = M.atto_undo || { + +/** + * @module moodle-atto_undo-button + */ + +/** + * Atto text editor undo plugin. + * + * @namespace M.atto_undo + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_undo').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + /** + * The maximum saved number of undo steps. + * + * @property _maxUndos + * @type {Number} The maximum number of saved undos. + * @default 40 + * @private + */ + _maxUndos: 40, /** - * Property used to cache the result of testing the undo/redo browser support. + * History of edits. * - * @property browsersupportsundo - * @type {Boolean} or null - * @default null + * @property _undoStack + * @type {Array} The elements of the array are the html strings that make a snapshot + * @private */ - browsersupportsundo : null, + _undoStack: null, /** - * Handle a click on either button (passed via cmd) + * History of edits. * - * @method click_handler - * @param {Y.Event} The click event - * @param {String} The id for the editor - * @param {String} The button clicked (undo or redo) + * @property _redoStack + * @type {Array} The elements of the array are the html strings that make a snapshot + * @private */ - click_handler : function(e, elementid, cmd) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand(cmd, false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + _redoStack: null, + + /** + * Add the buttons to the toolbar + * + * @method initializer + */ + initializer: function() { + // Initialise the undo and redo stacks. + this._undoStack = []; + this._redoStack = []; + + this.addButton({ + icon: 'e/undo', + callback: this._undoHandler, + buttonName: 'undo', + keys: 90 + }); + + this.addButton({ + icon: 'e/redo', + callback: this._redoHandler, + buttonName: 'redo', + keys: 89 + }); + + this.get('host').on('atto:selectionchanged', this._changeListener, this); }, /** * Handle a click on undo * - * @method undo_handler - * @param {Y.Event} The click event - * @param {String} The id for the editor + * @method _undoHandler + * @private */ - undo_handler : function(e, elementid) { - M.atto_undo.click_handler(e, elementid, 'undo'); + _undoHandler: function() { + var html = this.editor.getHTML(); + + this._redoStack.push(html); + var last = this._undoStack.pop(); + if (last === html) { + last = this._undoStack.pop(); + } + if (last) { + this.editor.setHTML(last); + // Put it back in the undo stack so a new event wont clear the redo stack. + this._undoStack.push(last); + this.highlightButtons('redo'); + } + + if (this._undoStack.length === 0) { + // If there are no undos left, unhighlight the undo button. + this.unHighlightButtons('undo'); + } }, /** * Handle a click on redo * - * @method redo_handler - * @param {Y.Event} The click event - * @param {String} The id for the editor + * @method _redoHandler + * @param {Event} The click event + * @private */ - redo_handler : function(e, elementid) { - M.atto_undo.click_handler(e, elementid, 'redo'); + _redoHandler: function(e) { + e.preventDefault(); + var html = this.editor.getHTML(); + + this._undoStack.push(html); + var last = this._redoStack.pop(); + this.editor.setHTML(last); + this._undoStack.push(last); }, /** - * Do a feature test to see if undo/redo is buggy in this browser. + * If we are significantly different from the last saved version, save a new version. * - * @method test_undo_support - * @return {Boolean} true if undo/redo is functional. + * @method _changeListener + * @param {EventFacade} The click event + * @private */ - test_undo_support : function() { - - // Check now if other browser supports it. - // Save the focussed element. - var activeelement = document.activeElement; - - // Creating a temp div to test if the browser support the undo execCommand. - var undosupport = false; - var foo = Y.Node.create('

                                        a
                                        '); - Y.one('body').prepend(foo); - foo.focus(); - - try { - document.execCommand('insertText', false, 'b'); - if (foo.getHTML() === 'ba') { - document.execCommand('undo', false); - if (foo.getHTML() === 'a') { - document.execCommand('redo', false); - if (foo.getHTML() === 'ba') { - undosupport = true; - } - } + _changeListener: function(e) { + if (e.event.type.indexOf('key') !== -1) { + // These are the 4 arrow keys. + if ((e.event.keyCode !== 39) && + (e.event.keyCode !== 37) && + (e.event.keyCode !== 40) && + (e.event.keyCode !== 38)) { + // Skip this event type. We only want focus/mouse/arrow events. + return; } - } catch (undosupportexception) { - // IE9 gives us an invalid parameter error on document.execCommand('insertText'...). - // The try/catch catches when the execCommands fail. - return false; } - // Remove the tmp contenteditable and reset the focussed element. - Y.one('body').removeChild(foo); - activeelement.focus(); - - return undosupport; - }, - - /** - * Add the buttons to the toolbar - * - * @method init - * @param {object} params containing elementid and group - */ - init : function(params) { - - // Retrieve undobrowsersupport global variable. - if (M.atto_undo.browsersupportsundo === null) { - M.atto_undo.browsersupportsundo = M.atto_undo.test_undo_support(); + if (typeof this._undoStack === 'undefined') { + this._undoStack = []; } - // Add the undo/redo buttons. - if (M.atto_undo.browsersupportsundo) { - // Undo button. - var iconurl = M.util.image_url('e/undo', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'undo', iconurl, params.group, M.atto_undo.undo_handler, 'undo', M.util.get_string('undo', 'atto_undo')); + var last = this._undoStack[this._undoStack.length-1]; + var html = this.editor.getHTML(); + if (last !== html) { + this._undoStack.push(this.editor.getHTML()); + this._redoStack = []; + this.unHighlightButtons('redo'); + } - // 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}); + while (this._undoStack.length > this._maxUndos) { + this._undoStack.shift(); + } + + // Show in the buttons if undo/redo is possible. + if (this._undoStack.length) { + this.highlightButtons('undo'); + } else { + this.unHighlightButtons('undo'); } } -}; +}); -}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 df0ab2c9358..0c1a4ef5789 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")),M.editor_atto.add_button_shortcut({action:"redo",keys:89})}}}},"@VERSION@",{requires:["node","moodle-editor_atto-editor-shortcut"]}); +YUI.add("moodle-atto_undo-button",function(e,t){e.namespace("M.atto_undo").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{_maxUndos:40,_undoStack:null,_redoStack:null,initializer:function(){this._undoStack=[],this._redoStack=[],this.addButton({icon:"e/undo",callback:this._undoHandler,buttonName:"undo",keys:90}),this.addButton({icon:"e/redo",callback:this._redoHandler,buttonName:"redo",keys:89}),this.get("host").on("atto:selectionchanged",this._changeListener,this)},_undoHandler:function(){var e=this.editor.getHTML();this._redoStack.push(e);var t=this._undoStack.pop();t===e&&(t=this._undoStack.pop()),t&&(this.editor.setHTML(t),this._undoStack.push(t),this.highlightButtons("redo")),this._undoStack.length===0&&this.unHighlightButtons("undo")},_redoHandler:function(e){e.preventDefault();var t=this.editor.getHTML();this._undoStack.push(t);var n=this._redoStack.pop();this.editor.setHTML(n),this._undoStack.push(n)},_changeListener:function(e){if(e.event.type.indexOf("key")!==-1&&e.event.keyCode!==39&&e.event.keyCode!==37&&e.event.keyCode!==40&&e.event.keyCode!==38)return;typeof this._undoStack=="undefined"&&(this._undoStack=[]);var t=this._undoStack[this._undoStack.length-1],n=this.editor.getHTML();t!==n&&(this._undoStack.push(this.editor.getHTML()),this._redoStack=[],this.unHighlightButtons("redo"));while(this._undoStack.length>this._maxUndos)this._undoStack.shift();this._undoStack.length?this.highlightButtons("undo"):this.unHighlightButtons("undo")}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 6143f87a008..50a76a4da80 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 @@ -16,132 +16,166 @@ YUI.add('moodle-atto_undo-button', function (Y, NAME) { // along with Moodle. If not, see . /** - * Atto text editor undo plugin. - * - * @package editor-undo + * @component atto_undo * @copyright 2014 Jerome Mouneyrac * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_undo = M.atto_undo || { + +/** + * @module moodle-atto_undo-button + */ + +/** + * Atto text editor undo plugin. + * + * @namespace M.atto_undo + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_undo').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + /** + * The maximum saved number of undo steps. + * + * @property _maxUndos + * @type {Number} The maximum number of saved undos. + * @default 40 + * @private + */ + _maxUndos: 40, /** - * Property used to cache the result of testing the undo/redo browser support. + * History of edits. * - * @property browsersupportsundo - * @type {Boolean} or null - * @default null + * @property _undoStack + * @type {Array} The elements of the array are the html strings that make a snapshot + * @private */ - browsersupportsundo : null, + _undoStack: null, /** - * Handle a click on either button (passed via cmd) + * History of edits. * - * @method click_handler - * @param {Y.Event} The click event - * @param {String} The id for the editor - * @param {String} The button clicked (undo or redo) + * @property _redoStack + * @type {Array} The elements of the array are the html strings that make a snapshot + * @private */ - click_handler : function(e, elementid, cmd) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand(cmd, false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + _redoStack: null, + + /** + * Add the buttons to the toolbar + * + * @method initializer + */ + initializer: function() { + // Initialise the undo and redo stacks. + this._undoStack = []; + this._redoStack = []; + + this.addButton({ + icon: 'e/undo', + callback: this._undoHandler, + buttonName: 'undo', + keys: 90 + }); + + this.addButton({ + icon: 'e/redo', + callback: this._redoHandler, + buttonName: 'redo', + keys: 89 + }); + + this.get('host').on('atto:selectionchanged', this._changeListener, this); }, /** * Handle a click on undo * - * @method undo_handler - * @param {Y.Event} The click event - * @param {String} The id for the editor + * @method _undoHandler + * @private */ - undo_handler : function(e, elementid) { - M.atto_undo.click_handler(e, elementid, 'undo'); + _undoHandler: function() { + var html = this.editor.getHTML(); + + this._redoStack.push(html); + var last = this._undoStack.pop(); + if (last === html) { + last = this._undoStack.pop(); + } + if (last) { + this.editor.setHTML(last); + // Put it back in the undo stack so a new event wont clear the redo stack. + this._undoStack.push(last); + this.highlightButtons('redo'); + } + + if (this._undoStack.length === 0) { + // If there are no undos left, unhighlight the undo button. + this.unHighlightButtons('undo'); + } }, /** * Handle a click on redo * - * @method redo_handler - * @param {Y.Event} The click event - * @param {String} The id for the editor + * @method _redoHandler + * @param {Event} The click event + * @private */ - redo_handler : function(e, elementid) { - M.atto_undo.click_handler(e, elementid, 'redo'); + _redoHandler: function(e) { + e.preventDefault(); + var html = this.editor.getHTML(); + + this._undoStack.push(html); + var last = this._redoStack.pop(); + this.editor.setHTML(last); + this._undoStack.push(last); }, /** - * Do a feature test to see if undo/redo is buggy in this browser. + * If we are significantly different from the last saved version, save a new version. * - * @method test_undo_support - * @return {Boolean} true if undo/redo is functional. + * @method _changeListener + * @param {EventFacade} The click event + * @private */ - test_undo_support : function() { - - // Check now if other browser supports it. - // Save the focussed element. - var activeelement = document.activeElement; - - // Creating a temp div to test if the browser support the undo execCommand. - var undosupport = false; - var foo = Y.Node.create('
                                        a
                                        '); - Y.one('body').prepend(foo); - foo.focus(); - - try { - document.execCommand('insertText', false, 'b'); - if (foo.getHTML() === 'ba') { - document.execCommand('undo', false); - if (foo.getHTML() === 'a') { - document.execCommand('redo', false); - if (foo.getHTML() === 'ba') { - undosupport = true; - } - } + _changeListener: function(e) { + if (e.event.type.indexOf('key') !== -1) { + // These are the 4 arrow keys. + if ((e.event.keyCode !== 39) && + (e.event.keyCode !== 37) && + (e.event.keyCode !== 40) && + (e.event.keyCode !== 38)) { + // Skip this event type. We only want focus/mouse/arrow events. + return; } - } catch (undosupportexception) { - // IE9 gives us an invalid parameter error on document.execCommand('insertText'...). - // The try/catch catches when the execCommands fail. - return false; } - // Remove the tmp contenteditable and reset the focussed element. - Y.one('body').removeChild(foo); - activeelement.focus(); - - return undosupport; - }, - - /** - * Add the buttons to the toolbar - * - * @method init - * @param {object} params containing elementid and group - */ - init : function(params) { - - // Retrieve undobrowsersupport global variable. - if (M.atto_undo.browsersupportsundo === null) { - M.atto_undo.browsersupportsundo = M.atto_undo.test_undo_support(); + if (typeof this._undoStack === 'undefined') { + this._undoStack = []; } - // Add the undo/redo buttons. - if (M.atto_undo.browsersupportsundo) { - // Undo button. - var iconurl = M.util.image_url('e/undo', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'undo', iconurl, params.group, M.atto_undo.undo_handler, 'undo', M.util.get_string('undo', 'atto_undo')); + var last = this._undoStack[this._undoStack.length-1]; + var html = this.editor.getHTML(); + if (last !== html) { + this._undoStack.push(this.editor.getHTML()); + this._redoStack = []; + this.unHighlightButtons('redo'); + } - // 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}); + while (this._undoStack.length > this._maxUndos) { + this._undoStack.shift(); + } + + // Show in the buttons if undo/redo is possible. + if (this._undoStack.length) { + this.highlightButtons('undo'); + } else { + this.unHighlightButtons('undo'); } } -}; +}); -}, '@VERSION@', {"requires": ["node", "moodle-editor_atto-editor-shortcut"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 98d2f6cbc5c..d95b725234b 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 @@ -14,129 +14,163 @@ // along with Moodle. If not, see . /** - * Atto text editor undo plugin. - * - * @package editor-undo + * @component atto_undo * @copyright 2014 Jerome Mouneyrac * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -M.atto_undo = M.atto_undo || { + +/** + * @module moodle-atto_undo-button + */ + +/** + * Atto text editor undo plugin. + * + * @namespace M.atto_undo + * @class button + * @extends M.editor_atto.EditorPlugin + */ + +Y.namespace('M.atto_undo').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + /** + * The maximum saved number of undo steps. + * + * @property _maxUndos + * @type {Number} The maximum number of saved undos. + * @default 40 + * @private + */ + _maxUndos: 40, /** - * Property used to cache the result of testing the undo/redo browser support. + * History of edits. * - * @property browsersupportsundo - * @type {Boolean} or null - * @default null + * @property _undoStack + * @type {Array} The elements of the array are the html strings that make a snapshot + * @private */ - browsersupportsundo : null, + _undoStack: null, /** - * Handle a click on either button (passed via cmd) + * History of edits. * - * @method click_handler - * @param {Y.Event} The click event - * @param {String} The id for the editor - * @param {String} The button clicked (undo or redo) + * @property _redoStack + * @type {Array} The elements of the array are the html strings that make a snapshot + * @private */ - click_handler : function(e, elementid, cmd) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand(cmd, false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); + _redoStack: null, + + /** + * Add the buttons to the toolbar + * + * @method initializer + */ + initializer: function() { + // Initialise the undo and redo stacks. + this._undoStack = []; + this._redoStack = []; + + this.addButton({ + icon: 'e/undo', + callback: this._undoHandler, + buttonName: 'undo', + keys: 90 + }); + + this.addButton({ + icon: 'e/redo', + callback: this._redoHandler, + buttonName: 'redo', + keys: 89 + }); + + this.get('host').on('atto:selectionchanged', this._changeListener, this); }, /** * Handle a click on undo * - * @method undo_handler - * @param {Y.Event} The click event - * @param {String} The id for the editor + * @method _undoHandler + * @private */ - undo_handler : function(e, elementid) { - M.atto_undo.click_handler(e, elementid, 'undo'); + _undoHandler: function() { + var html = this.editor.getHTML(); + + this._redoStack.push(html); + var last = this._undoStack.pop(); + if (last === html) { + last = this._undoStack.pop(); + } + if (last) { + this.editor.setHTML(last); + // Put it back in the undo stack so a new event wont clear the redo stack. + this._undoStack.push(last); + this.highlightButtons('redo'); + } + + if (this._undoStack.length === 0) { + // If there are no undos left, unhighlight the undo button. + this.unHighlightButtons('undo'); + } }, /** * Handle a click on redo * - * @method redo_handler - * @param {Y.Event} The click event - * @param {String} The id for the editor + * @method _redoHandler + * @param {Event} The click event + * @private */ - redo_handler : function(e, elementid) { - M.atto_undo.click_handler(e, elementid, 'redo'); + _redoHandler: function(e) { + e.preventDefault(); + var html = this.editor.getHTML(); + + this._undoStack.push(html); + var last = this._redoStack.pop(); + this.editor.setHTML(last); + this._undoStack.push(last); }, /** - * Do a feature test to see if undo/redo is buggy in this browser. + * If we are significantly different from the last saved version, save a new version. * - * @method test_undo_support - * @return {Boolean} true if undo/redo is functional. + * @method _changeListener + * @param {EventFacade} The click event + * @private */ - test_undo_support : function() { - - // Check now if other browser supports it. - // Save the focussed element. - var activeelement = document.activeElement; - - // Creating a temp div to test if the browser support the undo execCommand. - var undosupport = false; - var foo = Y.Node.create('
                                        a
                                        '); - Y.one('body').prepend(foo); - foo.focus(); - - try { - document.execCommand('insertText', false, 'b'); - if (foo.getHTML() === 'ba') { - document.execCommand('undo', false); - if (foo.getHTML() === 'a') { - document.execCommand('redo', false); - if (foo.getHTML() === 'ba') { - undosupport = true; - } - } + _changeListener: function(e) { + if (e.event.type.indexOf('key') !== -1) { + // These are the 4 arrow keys. + if ((e.event.keyCode !== 39) && + (e.event.keyCode !== 37) && + (e.event.keyCode !== 40) && + (e.event.keyCode !== 38)) { + // Skip this event type. We only want focus/mouse/arrow events. + return; } - } catch (undosupportexception) { - // IE9 gives us an invalid parameter error on document.execCommand('insertText'...). - // The try/catch catches when the execCommands fail. - return false; } - // Remove the tmp contenteditable and reset the focussed element. - Y.one('body').removeChild(foo); - activeelement.focus(); - - return undosupport; - }, - - /** - * Add the buttons to the toolbar - * - * @method init - * @param {object} params containing elementid and group - */ - init : function(params) { - - // Retrieve undobrowsersupport global variable. - if (M.atto_undo.browsersupportsundo === null) { - M.atto_undo.browsersupportsundo = M.atto_undo.test_undo_support(); + if (typeof this._undoStack === 'undefined') { + this._undoStack = []; } - // Add the undo/redo buttons. - if (M.atto_undo.browsersupportsundo) { - // Undo button. - var iconurl = M.util.image_url('e/undo', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'undo', iconurl, params.group, M.atto_undo.undo_handler, 'undo', M.util.get_string('undo', 'atto_undo')); + var last = this._undoStack[this._undoStack.length-1]; + var html = this.editor.getHTML(); + if (last !== html) { + this._undoStack.push(this.editor.getHTML()); + this._redoStack = []; + this.unHighlightButtons('redo'); + } - // 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}); + while (this._undoStack.length > this._maxUndos) { + this._undoStack.shift(); + } + + // Show in the buttons if undo/redo is possible. + if (this._undoStack.length) { + this.highlightButtons('undo'); + } else { + this.unHighlightButtons('undo'); } } -}; +}); 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 1e574b9dbaf..520e0b82e20 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,7 @@ { - "moodle-atto_undo-button": { - "requires": ["node", "moodle-editor_atto-editor-shortcut"] - } + "moodle-atto_undo-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } 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 6ab94d6fb24..abe24ce7505 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,49 +15,35 @@ 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 . +/* + * @package atto_unlink + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_unlink-button */ -var SELECTORS = { - TAGS : 'a' -}; /** * Atto text editor unlink plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_unlink + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_unlink = M.atto_unlink || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('unlink', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/remove_link', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'unlink', iconurl, params.group, click); +Y.namespace('M.atto_unlink').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'unlink', + icon: 'e/remove_link', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'a' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 980573aa576..2e2111a7c0f 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){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),M.editor_atto.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"]}); +YUI.add("moodle-atto_unlink-button",function(e,t){e.namespace("M.atto_unlink").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"unlink",icon:"e/remove_link",tags:"a"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 6ab94d6fb24..abe24ce7505 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,49 +15,35 @@ 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 . +/* + * @package atto_unlink + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_unlink-button */ -var SELECTORS = { - TAGS : 'a' -}; /** * Atto text editor unlink plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_unlink + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_unlink = M.atto_unlink || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('unlink', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/remove_link', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'unlink', iconurl, params.group, click); +Y.namespace('M.atto_unlink').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'unlink', + icon: 'e/remove_link', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'a' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 add917386e7..e2aade20fc1 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,46 +13,32 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_unlink + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_unlink-button */ -var SELECTORS = { - TAGS : 'a' -}; /** * Atto text editor unlink plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_unlink + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_unlink = M.atto_unlink || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('unlink', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/remove_link', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'unlink', iconurl, params.group, click); +Y.namespace('M.atto_unlink').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'unlink', + icon: 'e/remove_link', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'a' }); } -}; +}); diff --git a/lib/editor/atto/plugins/unlink/yui/src/button/meta/button.json b/lib/editor/atto/plugins/unlink/yui/src/button/meta/button.json index 448646904ac..dd73f16db1d 100644 --- a/lib/editor/atto/plugins/unlink/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/unlink/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_unlink-button": { - "requires": ["node"] - } + "moodle-atto_unlink-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } 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 cd6916ee3bf..db223b63dd7 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,49 +15,35 @@ 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 . +/* + * @package atto_unorderedlist + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_unorderedlist-button */ -var SELECTORS = { - TAGS : 'ul' -}; /** * Atto text editor unorderedlist plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_unorderedlist + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_unorderedlist = M.atto_unorderedlist || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('insertUnorderedList', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/bullet_list', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'unorderedlist', iconurl, params.group, click); +Y.namespace('M.atto_unorderedlist').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'insertUnorderedList', + icon: 'e/bullet_list', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'ul' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 f9d354c1d5d..00e93d33ecc 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){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),M.editor_atto.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"]}); +YUI.add("moodle-atto_unorderedlist-button",function(e,t){e.namespace("M.atto_unorderedlist").Button=e.Base.create("button",e.M.editor_atto.EditorPlugin,[],{initializer:function(){this.addBasicButton({exec:"insertUnorderedList",icon:"e/bullet_list",tags:"ul"})}})},"@VERSION@",{requires:["moodle-editor_atto-plugin"]}); 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 cd6916ee3bf..db223b63dd7 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,49 +15,35 @@ 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 . +/* + * @package atto_unorderedlist + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_unorderedlist-button */ -var SELECTORS = { - TAGS : 'ul' -}; /** * Atto text editor unorderedlist plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_unorderedlist + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_unorderedlist = M.atto_unorderedlist || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('insertUnorderedList', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/bullet_list', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'unorderedlist', iconurl, params.group, click); +Y.namespace('M.atto_unorderedlist').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'insertUnorderedList', + icon: 'e/bullet_list', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'ul' }); } -}; +}); -}, '@VERSION@', {"requires": ["node"]}); +}, '@VERSION@', {"requires": ["moodle-editor_atto-plugin"]}); 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 f882172caa6..7997bcba676 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,46 +13,32 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/* + * @package atto_unorderedlist + * @copyright 2013 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** - * Selectors. - * - * @type {Object} + * @module moodle-atto_unorderedlist-button */ -var SELECTORS = { - TAGS : 'ul' -}; /** * Atto text editor unorderedlist plugin. * - * @package editor-atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.atto_unorderedlist + * @class button + * @extends M.editor_atto.EditorPlugin */ -M.atto_unorderedlist = M.atto_unorderedlist || { - init : function(params) { - var click = function(e, elementid) { - e.preventDefault(); - if (!M.editor_atto.is_active(elementid)) { - M.editor_atto.focus(elementid); - } - document.execCommand('insertUnorderedList', false, null); - // Clean the YUI ids from the HTML. - M.editor_atto.text_updated(elementid); - }; - var iconurl = M.util.image_url('e/bullet_list', 'core'); - M.editor_atto.add_toolbar_button(params.elementid, 'unorderedlist', iconurl, params.group, click); +Y.namespace('M.atto_unorderedlist').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], { + initializer: function() { + this.addBasicButton({ + exec: 'insertUnorderedList', + icon: 'e/bullet_list', - // 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. - M.editor_atto.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'); - } + // Watch the following tags and add/remove highlighting as appropriate: + tags: 'ul' }); } -}; +}); diff --git a/lib/editor/atto/plugins/unorderedlist/yui/src/button/meta/button.json b/lib/editor/atto/plugins/unorderedlist/yui/src/button/meta/button.json index 58307eb3208..e680e5494eb 100644 --- a/lib/editor/atto/plugins/unorderedlist/yui/src/button/meta/button.json +++ b/lib/editor/atto/plugins/unorderedlist/yui/src/button/meta/button.json @@ -1,5 +1,7 @@ { - "moodle-atto_unorderedlist-button": { - "requires": ["node"] - } + "moodle-atto_unorderedlist-button": { + "requires": [ + "moodle-editor_atto-plugin" + ] + } } diff --git a/lib/editor/atto/styles.css b/lib/editor/atto/styles.css index 48f89366374..a754ce555e8 100755 --- a/lib/editor/atto/styles.css +++ b/lib/editor/atto/styles.css @@ -72,8 +72,8 @@ div.editor_atto_toolbar button::-moz-focus-inner { } div.editor_atto_toolbar button img.icon { - padding: 1px; - margin: 1px 0; + padding: 0px; + margin: 2px 0; /* The following is dedicated to the beloved IE8, clashing with Bootstrap. God bless you IE. */ vertical-align: text-bottom; width: auto; @@ -113,8 +113,6 @@ div.editor_atto_toolbar div.atto_group { color: black; } .atto_menuentry { - border-bottom: 1px solid #eee; - padding: 2px; clear: left; } @@ -171,7 +169,7 @@ div.editor_atto_content:hover .atto_control { display: block; } -.yui3-controlmenu-hidden { +.yui3-menu-hidden { display: none; } .editor_atto_controlmenu li { @@ -207,4 +205,43 @@ div.editor_atto_content:hover .atto_control { -moz-force-broken-image-icon:1; min-width:24px; min-height:24px; -} \ No newline at end of file +} + +.moodle-dialogue-base .editor_atto_menu .moodle-dialogue-content .moodle-dialogue-bd { + position: absolute; + text-align:left; + z-index: 1000; + display: block; + background-color: #fff; + border: 1px solid #ccc; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: 5px 5px 20px 0 #666666; + -moz-box-shadow: 5px 5px 20px 0 #666666; + box-shadow: 5px 5px 20px 0 #666666; + padding: 0px; +} + +.editor_atto_menu .menu { + margin: 0px; +} + +.editor_atto_menu .menu a { + display: block; + padding: 4px 1em 4px 1em; + color: #333333; +} + +.editor_atto_menu .menu a:hover { + color: #ffffff;background-color: #0088cc; +} +.editor_atto_menu .menu a.hidden { + display: none; +} +.editor_atto_menu .menu img { + vertical-align: middle; +} +.editor_atto_menu .menu > li { + display: block; +} 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 deleted file mode 100644 index 76a4c809646..00000000000 --- a/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-debug.js +++ /dev/null @@ -1,263 +0,0 @@ -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 deleted file mode 100644 index 679b5f4ba69..00000000000 --- a/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut-min.js +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 1ab16eb317f..00000000000 --- a/lib/editor/atto/yui/build/moodle-editor_atto-editor-shortcut/moodle-editor_atto-editor-shortcut.js +++ /dev/null @@ -1,262 +0,0 @@ -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 183b29eefdc..be16ef5e852 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 @@ -16,38 +16,55 @@ YUI.add('moodle-editor_atto-editor', function (Y, NAME) { // along with Moodle. If not, see . /** - * Atto editor. + * The Atto WYSIWG pluggable editor, written for Moodle. * + * @module moodle-editor_atto-editor * @package editor_atto * @copyright 2013 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @main moodle-editor_atto-editor */ /** - * Classes constants. + * @module moodle-editor_atto-editor + * @submodule editor-base */ -CSS = { - CONTENT: 'editor_atto_content', - CONTENTWRAPPER: 'editor_atto_content_wrap', - TOOLBAR: 'editor_atto_toolbar', - WRAPPER: 'editor_atto', - HIGHLIGHT: 'highlight' -}; + +var LOGNAME = 'moodle-editor_atto-editor'; +var CSS = { + CONTENT: 'editor_atto_content', + CONTENTWRAPPER: 'editor_atto_content_wrap', + TOOLBAR: 'editor_atto_toolbar', + WRAPPER: 'editor_atto', + HIGHLIGHT: 'highlight' + }; /** - * Atto editor main class. - * Common functions required by editor plugins. + * The Atto editor for Moodle. * - * @package editor_atto - * @copyright 2013 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @namespace M.editor_atto + * @class Editor + * @constructor + * @uses M.editor_atto.EditorClean + * @uses M.editor_atto.EditorFilepicker + * @uses M.editor_atto.EditorSelection + * @uses M.editor_atto.EditorStyling + * @uses M.editor_atto.EditorTextArea + * @uses M.editor_atto.EditorToolbar + * @uses M.editor_atto.EditorToolbarNav */ -M.editor_atto = M.editor_atto || { + +function Editor() { + Editor.superclass.constructor.apply(this, arguments); +} + +Y.extend(Editor, Y.Base, { /** * List of known block level tags. * Taken from "https://developer.mozilla.org/en-US/docs/HTML/Block-level_elements". * + * @property BLOCK_TAGS * @type {Array} */ BLOCK_TAGS : [ @@ -83,924 +100,946 @@ M.editor_atto = M.editor_atto || { 'table', 'tfoot', 'ul', - 'video'], + 'video' + ], PLACEHOLDER_FONTNAME: 'yui-tmp', ALL_NODES_SELECTOR: '[style],font[face]', FONT_FAMILY: 'fontFamily', /** - * List of attached button handlers to prevent duplicates. - */ - buttonhandlers : {}, - - /** - * List of attached handlers. - */ - textupdatedhandlers : {}, - - /** - * List of YUI overlays for custom menus. - */ - menus : {}, - - /** - * List of attached menu handlers to prevent duplicates. - */ - menuhandlers : {}, - - /** - * List of file picker options for specific editor instances. - */ - filepickeroptions : {}, - - /** - * List of buttons and menus that have been added to the toolbar. - */ - widgets : {}, - - /** - * List of saved selections per editor instance. - */ - selections : {}, - - focusfromclick : false, - - /** - * Set to true after events have been published for M.editor_atto. - * @param eventspublished - * @type boolean - */ - eventspublished : false, - - /** - * A unique identifier for the last selection recorded. - * @param lastselection - * @type string - */ - lastselection : null, - - /** - * Set to true after the first editor has been initialised. + * The wrapper containing the editor. * - * "The first transport is away. The first transport is away." - * ―Lieutenant Romas Navander, during the Battle of Hoth + * @property _wrapper + * @type Node + * @private + */ + _wrapper: null, + + /** + * A reference to the content editable Node. * - * @param firstinit - * @type boolean + * @property editor + * @type Node */ - firstinit : true, + editor: null, /** - * Toggle a menu. - * @param event e - */ - showhide_menu_handler : function(e) { - e.preventDefault(); - var disabled = this.getAttribute('disabled'); - var overlayid = this.getAttribute('data-menu'); - var overlay = M.editor_atto.menus[overlayid]; - var menu = overlay.get('bodyContent'); - if (overlay.get('visible') || disabled) { - overlay.hide(); - menu.detach('clickoutside'); - } else { - menu.on('clickoutside', function(ev) { - if ((ev.target.ancestor() !== this) && (ev.target !== this)) { - if (overlay.get('visible')) { - menu.detach('clickoutside'); - overlay.hide(); - } - } - }, this); - - overlay.align(Y.one(Y.config.doc.body), [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]); - overlay.show(); - var icon = e.target.ancestor('button', true).one('img'); - overlay.align(icon, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]); - overlay.get('boundingBox').one('a').focus(); - } - }, - - /** - * Handle clicks on editor buttons. - * @param event e - */ - buttonclicked_handler : function(e) { - var elementid = this.getAttribute('data-editor'); - var plugin = this.getAttribute('data-plugin'); - var button = this.getAttribute('data-button'); - 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(); - } - - if (M.editor_atto.is_enabled(elementid, plugin, button)) { - // Pass it on. - handler = M.editor_atto.buttonhandlers[handler]; - return handler(e, elementid); - } - }, - - /** - * 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, toolbar = M.editor_atto.get_toolbar_node(elementid); - for (plugin in M.editor_atto.widgets) { - element = toolbar.one('.atto_' + plugin + '_button'); - - if (element) { - element.setAttribute('disabled', 'true'); - } - } - }, - - /** - * Get the node of the original textarea element that this editor replaced. + * A reference to the original text area. * - * @param string elementid, the element id of this editor. - * @return Y.Node + * @property textarea + * @type 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)); - }, + textarea: null, /** - * Get the node of the toolbar container for this editor. + * A reference to the label associated with the original text area. * - * @param string elementid, the element id of this editor. - * @return Y.Node + * @property textareaLabel + * @type 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')); - }, + textareaLabel: null, /** - * Get the node of the contenteditable container for this editor. + * A reference to the list of plugins. * - * @param string elementid, the element id of this editor. - * @return Y.Node + * @property plugins + * @type object */ - 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')); - }, + plugins: null, - /** - * 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. - * @param string buttonname, optional - used when a plugin has multiple buttons. - */ - is_enabled : function(elementid, plugin, button) { - var buttonpath = plugin; - if (button) { - buttonpath += '_' + button; - } - var element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + buttonpath + '_button'); + initializer: function() { + var template; - return !element.hasAttribute('disabled'); - }, + // Note - it is not safe to use a CSS selector like '#' + elementid because the id + // may have colons in it - e.g. quiz. + this.textarea = Y.one(document.getElementById(this.get('elementid'))); - /** - * 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. - * @param string plugin, the name of the plugin that created the widget. - * @param string buttonname, optional - used when a plugin has multiple buttons. - */ - enable_widget : 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.removeAttribute('disabled'); - } - }, - - /** - * 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. - */ - enable_all_widgets : function(elementid) { - var path, element; - for (path in M.editor_atto.widgets) { - element = M.editor_atto.get_toolbar_node(elementid).one('.atto_' + path + '_button'); - - if (element) { - element.removeAttribute('disabled'); - } - } - }, - - /** - * Add a content update handler to be called whenever the content is updated. - * - * @param string elementid - the id of the textarea we created this editor from. - * @handler function callback - The function to do the cleaning. - * @param object context - the context to set for the callback. - * @handler function handler - A function to call when the button is clicked. - */ - add_text_updated_handler : function(elementid, callback) { - if (!(elementid in M.editor_atto.textupdatedhandlers)) { - M.editor_atto.textupdatedhandlers[elementid] = []; - } - M.editor_atto.textupdatedhandlers[elementid].push(callback); - }, - - /** - * Add a button to the toolbar belonging to the editor for element with id "elementid". - * @param string elementid - the id of the textarea we created this editor from. - * @param string plugin - the plugin defining the button - * @param string icon - the html used for the content of the button - * @param string groupname - the group the button should be appended to. - * @param array entries - List of menu entries with the string (entry.text) and the handlers (entry.handler). - * @param string buttonname - (optional) a name for the button. Required if a plugin creates more than one button. - * @param string buttontitle - (optional) a title for the button. Required if a plugin creates more than one button. - * @param int overlaywidth - the overlay width size in 'ems'. - * @param string menucolor - menu icon background color - */ - add_toolbar_menu : function(elementid, plugin, iconurl, groupname, entries, buttonname, buttontitle, overlaywidth, menucolor) { - var toolbar = M.editor_atto.get_toolbar_node(elementid), - group = toolbar.one('.atto_group.' + groupname + '_group'), - currentfocus, - button, - buttonpath, - expimgurl; - - if (buttonname) { - buttonpath = plugin + '_' + buttonname; - } else { - buttonname = ''; - buttonpath = plugin; + if (!this.textarea) { + // No text area found. + Y.log('Text area not found - unable to setup editor for ' + this.get('elementid'), + 'error', LOGNAME); + return; } - if (!buttontitle) { - buttontitle = M.util.get_string('pluginname', 'atto_' + plugin); + this._wrapper = Y.Node.create('
                                        '); + template = Y.Handlebars.compile('
                                        '); + this.editor = Y.Node.create(template({ + elementid: this.get('elementid'), + CSS: CSS + })); + + // Add a labelled-by attribute to the contenteditable. + this.textareaLabel = Y.one('[for="' + this.get('elementid') + '"]'); + if (this.textareaLabel) { + this.textareaLabel.generateID(); + this.editor.setAttribute('aria-labelledby', this.textareaLabel.get("id")); } - if ((typeof overlaywidth) === 'undefined') { - overlaywidth = '14'; - } - if ((typeof menucolor) === 'undefined') { - menucolor = 'transparent'; - } + // Add everything to the wrapper. + this.setupToolbar(); - if (!group) { - group = Y.Node.create('
                                        '); - toolbar.append(group); - } - expimgurl = M.util.image_url('t/expanded', 'moodle'); - button = Y.Node.create(''); + // Editable content wrapper. + var content = Y.Node.create('
                                        '); + content.appendChild(this.editor); + this._wrapper.appendChild(content); - group.append(button); + // Style the editor. + this.editor.setStyle('minHeight', (1.2 * (this.textarea.getAttribute('rows'))) + 'em'); + // Disable odd inline CSS styles. + this.disableCssStyling(); - 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()); - } + // Add the toolbar and editable zone to the page. + this.textarea.get('parentNode').insert(this._wrapper, this.textarea); - // Save the name of the plugin. - M.editor_atto.widgets[buttonpath] = buttonpath; + // Hide the old textarea. + this.textarea.hide(); - var menu = Y.Node.create('
                                        '); - var i = 0, entry = {}; + // Copy the text to the contenteditable div. + this.updateFromTextArea(); - for (i = 0; i < entries.length; i++) { - entry = entries[i]; - var insidemenu = Y.Node.create(''); - insidemenu.on("keydown", M.editor_atto.menu_item_arrow_key_handler, null, button); - menu.append(insidemenu); - if (!M.editor_atto.buttonhandlers[plugin + '_action_' + i]) { - Y.one('body').delegate('click', M.editor_atto.buttonclicked_handler, '.atto_' + buttonpath + '_action_' + i); - // Activate the link on space or enter. - Y.one('body').delegate('key', M.editor_atto.buttonclicked_handler, '32,enter', '.atto_' + buttonpath + '_action_' + i); - M.editor_atto.buttonhandlers[buttonpath + '_action_' + i] = entry.handler; - } - } + // Publish the events that are defined by this editor. + this.publishEvents(); - if (!M.editor_atto.buttonhandlers[buttonpath]) { - Y.one('body').delegate('click', M.editor_atto.showhide_menu_handler, '.atto_' + buttonpath + '_button'); - M.editor_atto.buttonhandlers[buttonpath] = true; - } + // Add handling for saving and restoring selections on cursor/focus changes. + this.setupSelectionWatchers(); - var overlay = new M.core.dialogue({ - bodyContent : menu, - visible : false, - width: overlaywidth + 'em', - closeButton: false, - center : false, - render: true - }); - - M.editor_atto.menus[buttonpath + '_' + elementid] = overlay; - overlay.align(button, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]); - overlay.headerNode.hide(); - }, - - /** - * Handle arrow key on the menu items. - * - * @param event e the key event. - * @param Y.Node the button calling the menu.. - */ - menu_item_arrow_key_handler : function(e, button) { - var siblings; - - // Intercept the down and left keys. - if (e.keyCode === 40 || e.keyCode === 37) { - e.preventDefault(); - var nextsibling = e.currentTarget.get('nextSibling'); - - // If no next sibling the we are the last sibling, go to the first one. - if(nextsibling === null) { - siblings = e.currentTarget.siblings(); - nextsibling = siblings.item(0); - } - - nextsibling.get('firstChild').focus(); - } else if (e.keyCode === 38 || e.keyCode === 39) { - // Intercept the up and right keys. - e.preventDefault(); - var previoussibling = e.currentTarget.get('previousSibling'); - - // If no preious sibling the we are the first sibling, go to the last one. - if(previoussibling === null) { - siblings = e.currentTarget.siblings(); - previoussibling = siblings.item(siblings.size() - 1); - } - - previoussibling.get('firstChild').focus(); - } else if (e.keyCode === 9 || e.keyCode === 27) { - // On the tab or esc key we close the menu. - e.preventDefault(); - var overlay = M.editor_atto.menus[button.getAttribute('data-menu')]; - var menu = overlay.get('bodyContent'); - overlay.hide(); - menu.detach('clickoutside'); - // Put back the focus on the button. - button.focus(); - - } - }, - - /** - * Add a button to the toolbar belonging to the editor for element with id "elementid". - * @param string elementid - the id of the textarea we created this editor from. - * @param string plugin - the plugin defining the button. - * @param string icon - the url to the image for the icon - * @param string groupname - the group the button should be appended to. - * @handler function handler- A function to call when the button is clicked. - * @param string buttonname - (optional) a name for the button. Required if a plugin creates more than one button. - * @param string buttontitle - (optional) a title for the button. Required if a plugin creates more than one button. - */ - add_toolbar_button : function(elementid, plugin, iconurl, groupname, handler, buttonname, buttontitle) { - var toolbar = M.editor_atto.get_toolbar_node(elementid), - group = toolbar.one('.atto_group.' + groupname + '_group'), - button, - buttonpath, - currentfocus; - - if (buttonname) { - buttonpath = plugin + '_' + buttonname; - } else { - buttonname = ''; - buttonpath = plugin; - } - - if (!buttontitle) { - buttontitle = M.util.get_string('pluginname', 'atto_' + plugin); - } - - if (!group) { - group = Y.Node.create('
                                        '); - toolbar.append(group); - } - button = Y.Node.create(''); - - group.append(button); - - 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()); - } - - // We only need to attach this once. - if (!M.editor_atto.buttonhandlers[buttonpath]) { - Y.one('body').delegate('click', M.editor_atto.buttonclicked_handler, '.atto_' + buttonpath + '_button'); - M.editor_atto.buttonhandlers[buttonpath] = handler; - } - - // Save the name of the plugin. - M.editor_atto.widgets[buttonpath] = buttonpath; - - }, - - /** - * Work out if the cursor is in the editable area for this editor instance. - * @param string elementid of this editor - * @return bool - */ - is_active : function(elementid) { - var range = rangy.createRange(), - editable = M.editor_atto.get_editable_node(elementid), - selection = rangy.getSelection(); - - if (!selection.rangeCount) { - return false; - } - - range.selectNode(editable.getDOMNode()); - - return range.intersectsRange(selection.getRangeAt(0)); + // Setup plugins. + this.setupPlugins(); }, /** * Focus on the editable area for this editor. - * @param string elementid of this editor - */ - focus : function(elementid) { - M.editor_atto.get_editable_node(elementid).focus(); - }, - - /** - * Copy and clean the text from the textarea into the contenteditable div. - * If the text is empty, provide a default paragraph tag to hold the content. * - * @param string elementid of this editor + * @method focus + * @chainable */ - update_from_textarea : function(elementid) { - var editable = M.editor_atto.get_editable_node(elementid); - var textarea = M.editor_atto.get_textarea_node(elementid); + focus: function() { + this.editor.focus(); - // Clear it first. - editable.setHTML(''); - - // Copy text to editable div. - editable.append(textarea.get('value')); - - // Clean it. - editable.cleanHTML(); - - // Insert a paragraph in the empty contenteditable div. - if (editable.getHTML() === '') { - if (Y.UA.ie && Y.UA.ie < 10) { - editable.setHTML('

                                        '); - } else { - editable.setHTML('


                                        '); - } - } + return this; }, /** - * Initialise the editor - * @param object params for this editor instance. + * Publish events for this editor instance. + * + * @method publishEvents + * @private + * @chainable */ - init : function(params) { - // Some things we only want to do on the first init. - var firstinit = this.firstinit; - this.firstinit = false; - var wrapper = Y.Node.create('
                                        '); - var atto = Y.Node.create('
                                        '); - - var toolbar = Y.Node.create('