MDL-44760 editor_atto: Address issues with focus when closing menus

Safari fires it's events in a slightly different order for the focusoutside
event which causes the focusAfterHide to be called *after* we change focus.

As a result, we must keep track of the menus which are currently open and
remove their focusAfterHide.
This commit is contained in:
Andrew Nicols 2014-04-09 15:26:32 +08:00
parent 28c247a735
commit c63f90539a
13 changed files with 105 additions and 18 deletions

View File

@ -626,15 +626,27 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
this._hideInvalidEntries(boundingBox);
// Clear the focusAfterHide for any other menus which may be open.
Y.Array.each(this.get('host').openMenus, function(menu) {
menu.set('focusAfterHide', null);
});
// Ensure that we focus on the button in the toolbar when we tab back to the menu.
var creatorButton = this.buttons[this.name];
this.get('host')._setTabFocus(creatorButton);
// Show the context menu, and align to the current position.
this._contextMenu.show();
this._contextMenu.align(this.buttons.table, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]);
this._contextMenu.set('focusAfterHide', this.buttons[this.name]);
this._contextMenu.set('focusAfterHide', creatorButton);
// If there are any anchors in the bounding box, focus on the first.
if (boundingBox.one('a')) {
boundingBox.one('a').focus();
}
// Add this menu to the list of open menus.
this.get('host').openMenus = [this._contextMenu];
},
/**

File diff suppressed because one or more lines are too long

View File

@ -626,15 +626,27 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
this._hideInvalidEntries(boundingBox);
// Clear the focusAfterHide for any other menus which may be open.
Y.Array.each(this.get('host').openMenus, function(menu) {
menu.set('focusAfterHide', null);
});
// Ensure that we focus on the button in the toolbar when we tab back to the menu.
var creatorButton = this.buttons[this.name];
this.get('host')._setTabFocus(creatorButton);
// Show the context menu, and align to the current position.
this._contextMenu.show();
this._contextMenu.align(this.buttons.table, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]);
this._contextMenu.set('focusAfterHide', this.buttons[this.name]);
this._contextMenu.set('focusAfterHide', creatorButton);
// If there are any anchors in the bounding box, focus on the first.
if (boundingBox.one('a')) {
boundingBox.one('a').focus();
}
// Add this menu to the list of open menus.
this.get('host').openMenus = [this._contextMenu];
},
/**

View File

@ -624,15 +624,27 @@ Y.namespace('M.atto_table').Button = Y.Base.create('button', Y.M.editor_atto.Edi
this._hideInvalidEntries(boundingBox);
// Clear the focusAfterHide for any other menus which may be open.
Y.Array.each(this.get('host').openMenus, function(menu) {
menu.set('focusAfterHide', null);
});
// Ensure that we focus on the button in the toolbar when we tab back to the menu.
var creatorButton = this.buttons[this.name];
this.get('host')._setTabFocus(creatorButton);
// Show the context menu, and align to the current position.
this._contextMenu.show();
this._contextMenu.align(this.buttons.table, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]);
this._contextMenu.set('focusAfterHide', this.buttons[this.name]);
this._contextMenu.set('focusAfterHide', creatorButton);
// If there are any anchors in the bounding box, focus on the first.
if (boundingBox.one('a')) {
boundingBox.one('a').focus();
}
// Add this menu to the list of open menus.
this.get('host').openMenus = [this._contextMenu];
},
/**

View File

@ -652,6 +652,14 @@ EditorToolbar.prototype = {
*/
toolbar: null,
/**
* A reference to any currently open menus in the toolbar.
*
* @property openMenus
* @type Array
*/
openMenus: null,
/**
* Setup the toolbar on the editor.
*
@ -660,6 +668,7 @@ EditorToolbar.prototype = {
*/
setupToolbar: function() {
this.toolbar = Y.Node.create('<div class="' + CSS.TOOLBAR + '" role="toolbar" aria-live="off"/>');
this.openMenus = [];
this._wrapper.appendChild(this.toolbar);
if (this.textareaLabel) {
@ -732,6 +741,10 @@ EditorToolbarNav.prototype = {
'down:37,39',
'.' + CSS.TOOLBAR,
this);
this._wrapper.delegate('focus',
function(e) {
this._setTabFocus(e.currentTarget);
}, '.' + CSS.TOOLBAR + ' button', this);
return this;
},

File diff suppressed because one or more lines are too long

View File

@ -649,6 +649,14 @@ EditorToolbar.prototype = {
*/
toolbar: null,
/**
* A reference to any currently open menus in the toolbar.
*
* @property openMenus
* @type Array
*/
openMenus: null,
/**
* Setup the toolbar on the editor.
*
@ -657,6 +665,7 @@ EditorToolbar.prototype = {
*/
setupToolbar: function() {
this.toolbar = Y.Node.create('<div class="' + CSS.TOOLBAR + '" role="toolbar" aria-live="off"/>');
this.openMenus = [];
this._wrapper.appendChild(this.toolbar);
if (this.textareaLabel) {
@ -729,6 +738,10 @@ EditorToolbarNav.prototype = {
'down:37,39',
'.' + CSS.TOOLBAR,
this);
this._wrapper.delegate('focus',
function(e) {
this._setTabFocus(e.currentTarget);
}, '.' + CSS.TOOLBAR + ' button', this);
return this;
},

View File

@ -575,6 +575,11 @@ EditorPluginButtons.prototype = {
this._chooseMenuItem, '.atto_menuentry a', this, config);
}
// Clear the focusAfterHide for any other menus which may be open.
Y.Array.each(this.get('host').openMenus, function(menu) {
menu.set('focusAfterHide', null);
});
// Ensure that we focus on this button next time.
var creatorButton = this.buttons[config.buttonName];
creatorButton.focus();
@ -585,15 +590,14 @@ 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]);
this.get('host').openMenus = [menuDialogue];
},
/**

File diff suppressed because one or more lines are too long

View File

@ -573,6 +573,11 @@ EditorPluginButtons.prototype = {
this._chooseMenuItem, '.atto_menuentry a', this, config);
}
// Clear the focusAfterHide for any other menus which may be open.
Y.Array.each(this.get('host').openMenus, function(menu) {
menu.set('focusAfterHide', null);
});
// Ensure that we focus on this button next time.
var creatorButton = this.buttons[config.buttonName];
creatorButton.focus();
@ -583,15 +588,14 @@ 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]);
this.get('host').openMenus = [menuDialogue];
},
/**

View File

@ -427,6 +427,11 @@ EditorPluginButtons.prototype = {
this._chooseMenuItem, '.atto_menuentry a', this, config);
}
// Clear the focusAfterHide for any other menus which may be open.
Y.Array.each(this.get('host').openMenus, function(menu) {
menu.set('focusAfterHide', null);
});
// Ensure that we focus on this button next time.
var creatorButton = this.buttons[config.buttonName];
creatorButton.focus();
@ -437,15 +442,14 @@ 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]);
this.get('host').openMenus = [menuDialogue];
},
/**

View File

@ -56,6 +56,10 @@ EditorToolbarNav.prototype = {
'down:37,39',
'.' + CSS.TOOLBAR,
this);
this._wrapper.delegate('focus',
function(e) {
this._setTabFocus(e.currentTarget);
}, '.' + CSS.TOOLBAR + ' button', this);
return this;
},

View File

@ -41,6 +41,14 @@ EditorToolbar.prototype = {
*/
toolbar: null,
/**
* A reference to any currently open menus in the toolbar.
*
* @property openMenus
* @type Array
*/
openMenus: null,
/**
* Setup the toolbar on the editor.
*
@ -49,6 +57,7 @@ EditorToolbar.prototype = {
*/
setupToolbar: function() {
this.toolbar = Y.Node.create('<div class="' + CSS.TOOLBAR + '" role="toolbar" aria-live="off"/>');
this.openMenus = [];
this._wrapper.appendChild(this.toolbar);
if (this.textareaLabel) {