MDL-44868 editor_atto: Prevent disable buttons to keep tabIndex

Now, if a button gets disabled but the tabIndex and the focus
are on that button, the focus and tabIndex are moves to its
closest neighbour.
This commit is contained in:
Frederic Massart
2014-03-31 16:47:32 +08:00
parent af31595b4b
commit b9d065edc4
8 changed files with 190 additions and 82 deletions
@@ -740,38 +740,50 @@ EditorToolbarNav.prototype = {
// Prevent the default browser behaviour.
e.preventDefault();
var buttons = this.toolbar.all('button');
// On cursor moves we loops through the buttons.
var found = false,
index = 0,
var buttons = this.toolbar.all('button'),
direction = 1,
checkCount = 0,
group,
candidate,
button,
current = e.target.ancestor('button', 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 button in the list of buttons", 'debug', LOGNAME);
return;
}
if (e.keyCode === 37) {
// Moving left so reverse the direction.
direction = -1;
}
// Try to find the next
button = this._findFirstFocusable(buttons, current, direction);
if (button) {
button.focus();
} else {
Y.log("Unable to find a button to focus on", 'debug', LOGNAME);
}
},
/**
* Find the first focusable button.
*
* @param {NodeList} buttons A list of nodes.
* @param {Node} startAt The node in the list to start the search from.
* @param {Number} direction The direction in which to search (1 or -1).
* @return {Node | Undefined} The Node or undefined.
* @method _findFirstFocusable
* @private
*/
_findFirstFocusable: function(buttons, startAt, direction) {
var checkCount = 0,
group,
candidate,
button,
index;
// Determine which button to start the search from.
index = buttons.indexOf(startAt);
if (index < -1) {
Y.log("Unable to find the button in the list of buttons", 'debug', LOGNAME);
index = 0;
}
// Try to find the next.
while (checkCount < buttons.size()) {
index += direction;
if (index < 0) {
@@ -802,12 +814,35 @@ EditorToolbarNav.prototype = {
break;
}
if (button) {
button.focus();
this._setTabFocus(button);
} else {
Y.log("Unable to find a button to focus on", 'debug', LOGNAME);
return button;
},
/**
* Check the tab focus.
*
* When we disable or hide a button, we should call this method to ensure that the
* focus is not currently set on an inaccessible button, otherwise tabbing to the toolbar
* would be impossible.
*
* @method checkTabFocus
* @chainable
*/
checkTabFocus: function() {
if (this._tabFocus) {
if (this._tabFocus.hasAttribute('disabled') || this._tabFocus.hasAttribute('hidden')
|| this._tabFocus.ancestor('.atto_group').hasAttribute('hidden')) {
// Find first available button.
button = this._findFirstFocusable(this.toolbar.all('button'), this._tabFocus, -1);
if (button) {
if (this._tabFocus.compareTo(document.activeElement)) {
// We should also move the focus, because the inaccessible button also has the focus.
button.focus();
}
this._setTabFocus(button);
}
}
}
return this;
},
/**
File diff suppressed because one or more lines are too long
@@ -737,37 +737,48 @@ EditorToolbarNav.prototype = {
// Prevent the default browser behaviour.
e.preventDefault();
var buttons = this.toolbar.all('button');
// On cursor moves we loops through the buttons.
var found = false,
index = 0,
var buttons = this.toolbar.all('button'),
direction = 1,
checkCount = 0,
group,
candidate,
button,
current = e.target.ancestor('button', 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 === 37) {
// Moving left so reverse the direction.
direction = -1;
}
// Try to find the next
button = this._findFirstFocusable(buttons, current, direction);
if (button) {
button.focus();
} else {
}
},
/**
* Find the first focusable button.
*
* @param {NodeList} buttons A list of nodes.
* @param {Node} startAt The node in the list to start the search from.
* @param {Number} direction The direction in which to search (1 or -1).
* @return {Node | Undefined} The Node or undefined.
* @method _findFirstFocusable
* @private
*/
_findFirstFocusable: function(buttons, startAt, direction) {
var checkCount = 0,
group,
candidate,
button,
index;
// Determine which button to start the search from.
index = buttons.indexOf(startAt);
if (index < -1) {
index = 0;
}
// Try to find the next.
while (checkCount < buttons.size()) {
index += direction;
if (index < 0) {
@@ -798,11 +809,35 @@ EditorToolbarNav.prototype = {
break;
}
if (button) {
button.focus();
this._setTabFocus(button);
} else {
return button;
},
/**
* Check the tab focus.
*
* When we disable or hide a button, we should call this method to ensure that the
* focus is not currently set on an inaccessible button, otherwise tabbing to the toolbar
* would be impossible.
*
* @method checkTabFocus
* @chainable
*/
checkTabFocus: function() {
if (this._tabFocus) {
if (this._tabFocus.hasAttribute('disabled') || this._tabFocus.hasAttribute('hidden')
|| this._tabFocus.ancestor('.atto_group').hasAttribute('hidden')) {
// Find first available button.
button = this._findFirstFocusable(this.toolbar.all('button'), this._tabFocus, -1);
if (button) {
if (this._tabFocus.compareTo(document.activeElement)) {
// We should also move the focus, because the inaccessible button also has the focus.
button.focus();
}
this._setTabFocus(button);
}
}
}
return this;
},
/**
@@ -881,6 +881,7 @@ EditorPluginButtons.prototype = {
}, this);
}
this.get('host').checkTabFocus();
return this;
},
File diff suppressed because one or more lines are too long
@@ -877,6 +877,7 @@ EditorPluginButtons.prototype = {
}, this);
}
this.get('host').checkTabFocus();
return this;
},
@@ -739,6 +739,7 @@ EditorPluginButtons.prototype = {
}, this);
}
this.get('host').checkTabFocus();
return this;
},
+62 -27
View File
@@ -70,38 +70,50 @@ EditorToolbarNav.prototype = {
// Prevent the default browser behaviour.
e.preventDefault();
var buttons = this.toolbar.all('button');
// On cursor moves we loops through the buttons.
var found = false,
index = 0,
var buttons = this.toolbar.all('button'),
direction = 1,
checkCount = 0,
group,
candidate,
button,
current = e.target.ancestor('button', 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 button in the list of buttons", 'debug', LOGNAME);
return;
}
if (e.keyCode === 37) {
// Moving left so reverse the direction.
direction = -1;
}
// Try to find the next
button = this._findFirstFocusable(buttons, current, direction);
if (button) {
button.focus();
} else {
Y.log("Unable to find a button to focus on", 'debug', LOGNAME);
}
},
/**
* Find the first focusable button.
*
* @param {NodeList} buttons A list of nodes.
* @param {Node} startAt The node in the list to start the search from.
* @param {Number} direction The direction in which to search (1 or -1).
* @return {Node | Undefined} The Node or undefined.
* @method _findFirstFocusable
* @private
*/
_findFirstFocusable: function(buttons, startAt, direction) {
var checkCount = 0,
group,
candidate,
button,
index;
// Determine which button to start the search from.
index = buttons.indexOf(startAt);
if (index < -1) {
Y.log("Unable to find the button in the list of buttons", 'debug', LOGNAME);
index = 0;
}
// Try to find the next.
while (checkCount < buttons.size()) {
index += direction;
if (index < 0) {
@@ -132,12 +144,35 @@ EditorToolbarNav.prototype = {
break;
}
if (button) {
button.focus();
this._setTabFocus(button);
} else {
Y.log("Unable to find a button to focus on", 'debug', LOGNAME);
return button;
},
/**
* Check the tab focus.
*
* When we disable or hide a button, we should call this method to ensure that the
* focus is not currently set on an inaccessible button, otherwise tabbing to the toolbar
* would be impossible.
*
* @method checkTabFocus
* @chainable
*/
checkTabFocus: function() {
if (this._tabFocus) {
if (this._tabFocus.hasAttribute('disabled') || this._tabFocus.hasAttribute('hidden')
|| this._tabFocus.ancestor('.atto_group').hasAttribute('hidden')) {
// Find first available button.
button = this._findFirstFocusable(this.toolbar.all('button'), this._tabFocus, -1);
if (button) {
if (this._tabFocus.compareTo(document.activeElement)) {
// We should also move the focus, because the inaccessible button also has the focus.
button.focus();
}
this._setTabFocus(button);
}
}
}
return this;
},
/**