';
+ '';
var DISABLED = 'disabled',
HIGHLIGHT = 'highlight',
@@ -340,6 +327,7 @@ EditorPluginButtons.prototype = {
} else {
buttonClass = buttonClass + '_' + config.buttonName;
}
+ config.buttonClass = buttonClass;
// Normalize icon configuration.
config = this._normalizeIcon(config);
@@ -495,6 +483,7 @@ EditorPluginButtons.prototype = {
} else {
buttonClass = buttonClass + '_' + config.buttonName;
}
+ config.buttonClass = buttonClass;
// Normalize icon configuration.
config = this._normalizeIcon(config);
@@ -529,7 +518,7 @@ EditorPluginButtons.prototype = {
// Add the standard click handler to the menu.
this._buttonHandlers.push(
this.toolbar.delegate('click', this._showToolbarMenu, '.' + buttonClass, this, config),
- this.toolbar.delegate('key', this._showToolbarMenu, '40, 32, enter', '.' + buttonClass, this, config)
+ this.toolbar.delegate('key', this._showToolbarMenuAndFocus, '40, 32, enter', '.' + buttonClass, this, config)
);
// Add the button reference to the buttons array for later reference.
@@ -575,45 +564,15 @@ EditorPluginButtons.prototype = {
}
config.overlayWidth = parseInt(config.overlayWidth, 10) + 'em';
- // Create the actual button.
- var template = Y.Handlebars.compile(MENUDIALOGUE),
- menu = Y.Node.create(template({
- config: config
- }));
+ this.menus[config.buttonClass] = new Y.M.editor_atto.Menu(config);
- // Create the dialogue.
- this.menus[config.buttonClass] = new M.core.dialogue({
- bodyContent: menu,
- width: null,
- visible: false,
- center: false,
- closeButton: false,
- responsive: false,
- extraClasses: ['editor_atto_menu']
- });
-
- menuDialogue = this.menus[config.buttonClass];
-
- // Hide the header node entirely.
- menuDialogue.headerNode.hide();
-
- // Handle menu item selection.
- this._buttonHandlers.push(
- menu.delegate('click', this._chooseMenuItem, '.atto_menuentry a', this, config, menuDialogue),
-
- // Select the menu item on space, and enter.
- menu.delegate('key', this._chooseMenuItem, '32, enter', '.atto_menuentry', this, config, menuDialogue),
-
- // Move up and down the menu on up/down.
- menu.delegate('key', this._menuKeyboardNavigation, 'down:38,40', '.menu', this),
-
- // Hide the menu on left/right.
- menu.delegate('key', this._hideMenu, 'down:37,39', '.menu', this, menuDialogue)
- );
+ this.menus[config.buttonClass].get('contentBox').delegate('click',
+ this._chooseMenuItem, '.atto_menuentry a', this, config);
}
// Ensure that we focus on this button next time.
var creatorButton = this.buttons[config.buttonName];
+ creatorButton.focus();
this.get('host')._setTabFocus(creatorButton);
// Get a reference to the menu dialogue.
@@ -621,36 +580,31 @@ EditorPluginButtons.prototype = {
// Focus on the button by default after hiding this menu.
menuDialogue.set('focusAfterHide', creatorButton);
+ menuDialogue.on('focusAfterHide', function(e) {
+ console.log(e);
+ });
// Display the menu.
menuDialogue.show();
// Position it next to the button which opened it.
menuDialogue.align(this.buttons[config.buttonName], [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]);
-
- // And focus on the first element in the menu.
- menuDialogue.get('boundingBox').one('a').focus();
-
- // Hide the menu when clicking outside of it.
- this._menuHideHandlers.push(
- menuDialogue.get('boundingBox').on('focusoutside', this._hideMenu, this, menuDialogue)
- );
},
/**
- * Hide a menu, removing all of the event handlers which trigger the hide.
+ * Display a toolbar menu and focus upon the first item.
*
- * @method _hideMenu
+ * @method _showToolbarMenuAndFocus
* @param {EventFacade} e
- * @param {M.core.dialogue} menuDialogue The Dialogue to hide.
+ * @param {object} config The configuration for the whole toolbar.
+ * @param {Number} [config.overlayWidth=14] The width of the menu
* @private
*/
- _hideMenu: function(e, menuDialogue) {
- if (menuDialogue.get('preventHideMenu') === true) {
- return;
- }
- menuDialogue.hide();
- new Y.EventHandle(this._menuHideHandlers).detach();
+ _showToolbarMenuAndFocus: function(e, config) {
+ this._showToolbarMenu(e, config);
+
+ // Focus on the first element in the menu.
+ this.menus[config.buttonClass].get('boundingBox').one('a').focus();
},
/**
@@ -663,12 +617,14 @@ EditorPluginButtons.prototype = {
* @private
*/
_chooseMenuItem: function(e, config, menuDialogue) {
- // Get the index from the clicked anchor.
+ // Get the index from the clicked anchor.
var index = e.target.ancestor('a', true).getData('index'),
// And the normalized callback configuration.
buttonConfig = this._normalizeCallback(config.items[index], config.globalItemConfig);
+ menuDialogue = this.menus[config.buttonClass];
+
// Prevent the dialogue to be closed because of some browser weirdness.
menuDialogue.set('preventHideMenu', true);
@@ -678,9 +634,10 @@ EditorPluginButtons.prototype = {
// Cancel the hide menu prevention.
menuDialogue.set('preventHideMenu', false);
+ console.log('Menu item chosen');
// Set the focus after hide so that focus is returned to the editor and changes are made correctly.
menuDialogue.set('focusAfterHide', this.get('host').editor);
- this._hideMenu(e, menuDialogue);
+ menuDialogue.hide(e);
},
/**
@@ -982,71 +939,6 @@ EditorPluginButtons.prototype = {
return this;
},
- /**
- * Implement arrow-key navigation for the items in a toolbar menu.
- *
- * @method _menuKeyboardNavigation
- * @param {EventFacade} e The keyboard event.
- * @private
- */
- _menuKeyboardNavigation: function(e) {
- // Prevent the default browser behaviour.
- e.preventDefault();
-
- // Get a list of all buttons in the menu.
- var buttons = e.currentTarget.all('a[role="menuitem"]');
-
- // On cursor moves we loops through the buttons.
- var found = false,
- index = 0,
- direction = 1,
- checkCount = 0,
- current = e.target.ancestor('a[role="menuitem"]', true);
-
- // Determine which button is currently selected.
- while (!found && index < buttons.size()) {
- if (buttons.item(index) === current) {
- found = true;
- } else {
- index++;
- }
- }
-
- if (!found) {
- Y.log("Unable to find this menu item in the menu", 'debug', LOGNAME);
- return;
- }
-
- if (e.keyCode === 38) {
- // Moving up so reverse the direction.
- direction = -1;
- }
-
- // Try to find the next
- do {
- index += direction;
- if (index < 0) {
- index = buttons.size() - 1;
- } else if (index >= buttons.size()) {
- // Handle wrapping.
- index = 0;
- }
- next = buttons.item(index);
-
- // Add a counter to ensure we don't get stuck in a loop if there's only one visible menu item.
- checkCount++;
- // Loop while:
- // * we are not in a loop and have not already checked every button; and
- // * we are on a different button; and
- // * the next menu item is not hidden.
- } while (checkCount < buttons.size() && next !== current && next.hasAttribute('hidden'));
-
- if (next) {
- next.focus();
- }
- },
-
-
/**
* Get the default meta key to use with keyboard events.
*
diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-plugin/moodle-editor_atto-plugin-min.js b/lib/editor/atto/yui/build/moodle-editor_atto-plugin/moodle-editor_atto-plugin-min.js
index 1119c46e4f6..c3911c462d1 100644
--- a/lib/editor/atto/yui/build/moodle-editor_atto-plugin/moodle-editor_atto-plugin-min.js
+++ b/lib/editor/atto/yui/build/moodle-editor_atto-plugin/moodle-editor_atto-plugin-min.js
@@ -1,2 +1,2 @@
-YUI.add("moodle-editor_atto-plugin",function(e,t){function n(){n.superclass.constructor.apply(this,arguments)}function c(){}function h(){}var r=".atto_group.",i="_group";e.extend(n,e.Base,{name:null,editor:null,toolbar:null,initializer:function(e){this.name=e.name,this.toolbar=e.toolbar,this.editor=e.editor,this.buttons={},this.buttonNames=[],this.buttonStates={},this.menus={},this._primaryKeyboardShortcut=[],this._buttonHandlers=[],this._menuHideHandlers=[]},markUpdated:function(){return this.get("host").updateOriginal()}},{NAME:"editorPlugin",ATTRS:{host:{writeOnce:!0},group:{writeOnce:!0,getter:function(t){var n=this.toolbar.one(r+t+i);return n||(n=e.Node.create(''),this.toolbar.append(n)),n}}}}),e.namespace("M.editor_atto").EditorPlugin=n;var s='',o='
';
+ '';
var DISABLED = 'disabled',
HIGHLIGHT = 'highlight',
@@ -340,6 +327,7 @@ EditorPluginButtons.prototype = {
} else {
buttonClass = buttonClass + '_' + config.buttonName;
}
+ config.buttonClass = buttonClass;
// Normalize icon configuration.
config = this._normalizeIcon(config);
@@ -493,6 +481,7 @@ EditorPluginButtons.prototype = {
} else {
buttonClass = buttonClass + '_' + config.buttonName;
}
+ config.buttonClass = buttonClass;
// Normalize icon configuration.
config = this._normalizeIcon(config);
@@ -527,7 +516,7 @@ EditorPluginButtons.prototype = {
// Add the standard click handler to the menu.
this._buttonHandlers.push(
this.toolbar.delegate('click', this._showToolbarMenu, '.' + buttonClass, this, config),
- this.toolbar.delegate('key', this._showToolbarMenu, '40, 32, enter', '.' + buttonClass, this, config)
+ this.toolbar.delegate('key', this._showToolbarMenuAndFocus, '40, 32, enter', '.' + buttonClass, this, config)
);
// Add the button reference to the buttons array for later reference.
@@ -573,45 +562,15 @@ EditorPluginButtons.prototype = {
}
config.overlayWidth = parseInt(config.overlayWidth, 10) + 'em';
- // Create the actual button.
- var template = Y.Handlebars.compile(MENUDIALOGUE),
- menu = Y.Node.create(template({
- config: config
- }));
+ this.menus[config.buttonClass] = new Y.M.editor_atto.Menu(config);
- // Create the dialogue.
- this.menus[config.buttonClass] = new M.core.dialogue({
- bodyContent: menu,
- width: null,
- visible: false,
- center: false,
- closeButton: false,
- responsive: false,
- extraClasses: ['editor_atto_menu']
- });
-
- menuDialogue = this.menus[config.buttonClass];
-
- // Hide the header node entirely.
- menuDialogue.headerNode.hide();
-
- // Handle menu item selection.
- this._buttonHandlers.push(
- menu.delegate('click', this._chooseMenuItem, '.atto_menuentry a', this, config, menuDialogue),
-
- // Select the menu item on space, and enter.
- menu.delegate('key', this._chooseMenuItem, '32, enter', '.atto_menuentry', this, config, menuDialogue),
-
- // Move up and down the menu on up/down.
- menu.delegate('key', this._menuKeyboardNavigation, 'down:38,40', '.menu', this),
-
- // Hide the menu on left/right.
- menu.delegate('key', this._hideMenu, 'down:37,39', '.menu', this, menuDialogue)
- );
+ this.menus[config.buttonClass].get('contentBox').delegate('click',
+ this._chooseMenuItem, '.atto_menuentry a', this, config);
}
// Ensure that we focus on this button next time.
var creatorButton = this.buttons[config.buttonName];
+ creatorButton.focus();
this.get('host')._setTabFocus(creatorButton);
// Get a reference to the menu dialogue.
@@ -619,36 +578,31 @@ EditorPluginButtons.prototype = {
// Focus on the button by default after hiding this menu.
menuDialogue.set('focusAfterHide', creatorButton);
+ menuDialogue.on('focusAfterHide', function(e) {
+ console.log(e);
+ });
// Display the menu.
menuDialogue.show();
// Position it next to the button which opened it.
menuDialogue.align(this.buttons[config.buttonName], [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]);
-
- // And focus on the first element in the menu.
- menuDialogue.get('boundingBox').one('a').focus();
-
- // Hide the menu when clicking outside of it.
- this._menuHideHandlers.push(
- menuDialogue.get('boundingBox').on('focusoutside', this._hideMenu, this, menuDialogue)
- );
},
/**
- * Hide a menu, removing all of the event handlers which trigger the hide.
+ * Display a toolbar menu and focus upon the first item.
*
- * @method _hideMenu
+ * @method _showToolbarMenuAndFocus
* @param {EventFacade} e
- * @param {M.core.dialogue} menuDialogue The Dialogue to hide.
+ * @param {object} config The configuration for the whole toolbar.
+ * @param {Number} [config.overlayWidth=14] The width of the menu
* @private
*/
- _hideMenu: function(e, menuDialogue) {
- if (menuDialogue.get('preventHideMenu') === true) {
- return;
- }
- menuDialogue.hide();
- new Y.EventHandle(this._menuHideHandlers).detach();
+ _showToolbarMenuAndFocus: function(e, config) {
+ this._showToolbarMenu(e, config);
+
+ // Focus on the first element in the menu.
+ this.menus[config.buttonClass].get('boundingBox').one('a').focus();
},
/**
@@ -661,12 +615,14 @@ EditorPluginButtons.prototype = {
* @private
*/
_chooseMenuItem: function(e, config, menuDialogue) {
- // Get the index from the clicked anchor.
+ // Get the index from the clicked anchor.
var index = e.target.ancestor('a', true).getData('index'),
// And the normalized callback configuration.
buttonConfig = this._normalizeCallback(config.items[index], config.globalItemConfig);
+ menuDialogue = this.menus[config.buttonClass];
+
// Prevent the dialogue to be closed because of some browser weirdness.
menuDialogue.set('preventHideMenu', true);
@@ -676,9 +632,10 @@ EditorPluginButtons.prototype = {
// Cancel the hide menu prevention.
menuDialogue.set('preventHideMenu', false);
+ console.log('Menu item chosen');
// Set the focus after hide so that focus is returned to the editor and changes are made correctly.
menuDialogue.set('focusAfterHide', this.get('host').editor);
- this._hideMenu(e, menuDialogue);
+ menuDialogue.hide(e);
},
/**
@@ -978,70 +935,6 @@ EditorPluginButtons.prototype = {
return this;
},
- /**
- * Implement arrow-key navigation for the items in a toolbar menu.
- *
- * @method _menuKeyboardNavigation
- * @param {EventFacade} e The keyboard event.
- * @private
- */
- _menuKeyboardNavigation: function(e) {
- // Prevent the default browser behaviour.
- e.preventDefault();
-
- // Get a list of all buttons in the menu.
- var buttons = e.currentTarget.all('a[role="menuitem"]');
-
- // On cursor moves we loops through the buttons.
- var found = false,
- index = 0,
- direction = 1,
- checkCount = 0,
- current = e.target.ancestor('a[role="menuitem"]', true);
-
- // Determine which button is currently selected.
- while (!found && index < buttons.size()) {
- if (buttons.item(index) === current) {
- found = true;
- } else {
- index++;
- }
- }
-
- if (!found) {
- return;
- }
-
- if (e.keyCode === 38) {
- // Moving up so reverse the direction.
- direction = -1;
- }
-
- // Try to find the next
- do {
- index += direction;
- if (index < 0) {
- index = buttons.size() - 1;
- } else if (index >= buttons.size()) {
- // Handle wrapping.
- index = 0;
- }
- next = buttons.item(index);
-
- // Add a counter to ensure we don't get stuck in a loop if there's only one visible menu item.
- checkCount++;
- // Loop while:
- // * we are not in a loop and have not already checked every button; and
- // * we are on a different button; and
- // * the next menu item is not hidden.
- } while (checkCount < buttons.size() && next !== current && next.hasAttribute('hidden'));
-
- if (next) {
- next.focus();
- }
- },
-
-
/**
* Get the default meta key to use with keyboard events.
*
diff --git a/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js b/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js
index b1a00551de2..80dc30320db 100644
--- a/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js
+++ b/lib/editor/atto/yui/src/editor/js/editor-plugin-buttons.js
@@ -35,20 +35,7 @@ var MENUTEMPLATE = '' +
'' +
'' +
- '',
- MENUDIALOGUE = '' +
- '
';
+ '';
var DISABLED = 'disabled',
HIGHLIGHT = 'highlight',
@@ -197,6 +184,7 @@ EditorPluginButtons.prototype = {
} else {
buttonClass = buttonClass + '_' + config.buttonName;
}
+ config.buttonClass = buttonClass;
// Normalize icon configuration.
config = this._normalizeIcon(config);
@@ -352,6 +340,7 @@ EditorPluginButtons.prototype = {
} else {
buttonClass = buttonClass + '_' + config.buttonName;
}
+ config.buttonClass = buttonClass;
// Normalize icon configuration.
config = this._normalizeIcon(config);
@@ -386,7 +375,7 @@ EditorPluginButtons.prototype = {
// Add the standard click handler to the menu.
this._buttonHandlers.push(
this.toolbar.delegate('click', this._showToolbarMenu, '.' + buttonClass, this, config),
- this.toolbar.delegate('key', this._showToolbarMenu, '40, 32, enter', '.' + buttonClass, this, config)
+ this.toolbar.delegate('key', this._showToolbarMenuAndFocus, '40, 32, enter', '.' + buttonClass, this, config)
);
// Add the button reference to the buttons array for later reference.
@@ -432,45 +421,15 @@ EditorPluginButtons.prototype = {
}
config.overlayWidth = parseInt(config.overlayWidth, 10) + 'em';
- // Create the actual button.
- var template = Y.Handlebars.compile(MENUDIALOGUE),
- menu = Y.Node.create(template({
- config: config
- }));
+ this.menus[config.buttonClass] = new Y.M.editor_atto.Menu(config);
- // Create the dialogue.
- this.menus[config.buttonClass] = new M.core.dialogue({
- bodyContent: menu,
- width: null,
- visible: false,
- center: false,
- closeButton: false,
- responsive: false,
- extraClasses: ['editor_atto_menu']
- });
-
- menuDialogue = this.menus[config.buttonClass];
-
- // Hide the header node entirely.
- menuDialogue.headerNode.hide();
-
- // Handle menu item selection.
- this._buttonHandlers.push(
- menu.delegate('click', this._chooseMenuItem, '.atto_menuentry a', this, config, menuDialogue),
-
- // Select the menu item on space, and enter.
- menu.delegate('key', this._chooseMenuItem, '32, enter', '.atto_menuentry', this, config, menuDialogue),
-
- // Move up and down the menu on up/down.
- menu.delegate('key', this._menuKeyboardNavigation, 'down:38,40', '.menu', this),
-
- // Hide the menu on left/right.
- menu.delegate('key', this._hideMenu, 'down:37,39', '.menu', this, menuDialogue)
- );
+ this.menus[config.buttonClass].get('contentBox').delegate('click',
+ this._chooseMenuItem, '.atto_menuentry a', this, config);
}
// Ensure that we focus on this button next time.
var creatorButton = this.buttons[config.buttonName];
+ creatorButton.focus();
this.get('host')._setTabFocus(creatorButton);
// Get a reference to the menu dialogue.
@@ -478,36 +437,31 @@ EditorPluginButtons.prototype = {
// Focus on the button by default after hiding this menu.
menuDialogue.set('focusAfterHide', creatorButton);
+ menuDialogue.on('focusAfterHide', function(e) {
+ console.log(e);
+ });
// Display the menu.
menuDialogue.show();
// Position it next to the button which opened it.
menuDialogue.align(this.buttons[config.buttonName], [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]);
-
- // And focus on the first element in the menu.
- menuDialogue.get('boundingBox').one('a').focus();
-
- // Hide the menu when clicking outside of it.
- this._menuHideHandlers.push(
- menuDialogue.get('boundingBox').on('focusoutside', this._hideMenu, this, menuDialogue)
- );
},
/**
- * Hide a menu, removing all of the event handlers which trigger the hide.
+ * Display a toolbar menu and focus upon the first item.
*
- * @method _hideMenu
+ * @method _showToolbarMenuAndFocus
* @param {EventFacade} e
- * @param {M.core.dialogue} menuDialogue The Dialogue to hide.
+ * @param {object} config The configuration for the whole toolbar.
+ * @param {Number} [config.overlayWidth=14] The width of the menu
* @private
*/
- _hideMenu: function(e, menuDialogue) {
- if (menuDialogue.get('preventHideMenu') === true) {
- return;
- }
- menuDialogue.hide();
- new Y.EventHandle(this._menuHideHandlers).detach();
+ _showToolbarMenuAndFocus: function(e, config) {
+ this._showToolbarMenu(e, config);
+
+ // Focus on the first element in the menu.
+ this.menus[config.buttonClass].get('boundingBox').one('a').focus();
},
/**
@@ -520,12 +474,14 @@ EditorPluginButtons.prototype = {
* @private
*/
_chooseMenuItem: function(e, config, menuDialogue) {
- // Get the index from the clicked anchor.
+ // Get the index from the clicked anchor.
var index = e.target.ancestor('a', true).getData('index'),
// And the normalized callback configuration.
buttonConfig = this._normalizeCallback(config.items[index], config.globalItemConfig);
+ menuDialogue = this.menus[config.buttonClass];
+
// Prevent the dialogue to be closed because of some browser weirdness.
menuDialogue.set('preventHideMenu', true);
@@ -535,9 +491,10 @@ EditorPluginButtons.prototype = {
// Cancel the hide menu prevention.
menuDialogue.set('preventHideMenu', false);
+ console.log('Menu item chosen');
// Set the focus after hide so that focus is returned to the editor and changes are made correctly.
menuDialogue.set('focusAfterHide', this.get('host').editor);
- this._hideMenu(e, menuDialogue);
+ menuDialogue.hide(e);
},
/**
@@ -839,71 +796,6 @@ EditorPluginButtons.prototype = {
return this;
},
- /**
- * Implement arrow-key navigation for the items in a toolbar menu.
- *
- * @method _menuKeyboardNavigation
- * @param {EventFacade} e The keyboard event.
- * @private
- */
- _menuKeyboardNavigation: function(e) {
- // Prevent the default browser behaviour.
- e.preventDefault();
-
- // Get a list of all buttons in the menu.
- var buttons = e.currentTarget.all('a[role="menuitem"]');
-
- // On cursor moves we loops through the buttons.
- var found = false,
- index = 0,
- direction = 1,
- checkCount = 0,
- current = e.target.ancestor('a[role="menuitem"]', true);
-
- // Determine which button is currently selected.
- while (!found && index < buttons.size()) {
- if (buttons.item(index) === current) {
- found = true;
- } else {
- index++;
- }
- }
-
- if (!found) {
- Y.log("Unable to find this menu item in the menu", 'debug', LOGNAME);
- return;
- }
-
- if (e.keyCode === 38) {
- // Moving up so reverse the direction.
- direction = -1;
- }
-
- // Try to find the next
- do {
- index += direction;
- if (index < 0) {
- index = buttons.size() - 1;
- } else if (index >= buttons.size()) {
- // Handle wrapping.
- index = 0;
- }
- next = buttons.item(index);
-
- // Add a counter to ensure we don't get stuck in a loop if there's only one visible menu item.
- checkCount++;
- // Loop while:
- // * we are not in a loop and have not already checked every button; and
- // * we are on a different button; and
- // * the next menu item is not hidden.
- } while (checkCount < buttons.size() && next !== current && next.hasAttribute('hidden'));
-
- if (next) {
- next.focus();
- }
- },
-
-
/**
* Get the default meta key to use with keyboard events.
*
diff --git a/lib/editor/atto/yui/src/editor/js/menu.js b/lib/editor/atto/yui/src/editor/js/menu.js
index 5c907d90903..d0558683ace 100644
--- a/lib/editor/atto/yui/src/editor/js/menu.js
+++ b/lib/editor/atto/yui/src/editor/js/menu.js
@@ -23,6 +23,20 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+var MENUDIALOGUE = '' +
+ '