Bug 1166321 - [AccessFu] adding support for role='switch'. r=eeejay

---
 accessible/jsat/EventManager.jsm                   | 15 ++++++---
 accessible/jsat/OutputGenerator.jsm                | 36 ++++++++++++++--------
 accessible/jsat/TraversalRules.jsm                 | 13 ++++----
 .../mochitest/jsat/doc_content_integration.html    |  7 +++++
 accessible/tests/mochitest/jsat/doc_traversal.html |  2 ++
 accessible/tests/mochitest/jsat/jsatcommon.js      | 12 ++++++++
 .../mochitest/jsat/test_content_integration.html   | 12 ++++++++
 accessible/tests/mochitest/jsat/test_output.html   | 17 ++++++++++
 .../tests/mochitest/jsat/test_traversal.html       |  8 +++--
 .../en-US/chrome/accessibility/AccessFu.properties |  5 +++
 10 files changed, 102 insertions(+), 25 deletions(-)
This commit is contained in:
Yura Zenevich 2015-05-29 11:55:53 -04:00
parent 7335f3dc36
commit a96f1789dd
10 changed files with 102 additions and 25 deletions

View File

@ -174,10 +174,17 @@ this.EventManager.prototype = {
let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
let state = Utils.getState(event);
if (state.contains(States.CHECKED)) {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? 'check' : 'uncheck'));
if (aEvent.accessible.role === Roles.SWITCH) {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? 'on' : 'off'));
} else {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? 'check' : 'uncheck'));
}
} else if (state.contains(States.SELECTED)) {
this.present(
Presentation.

View File

@ -210,7 +210,7 @@ let OutputGenerator = {
aOutput.push({string: 'textInputType_' + typeName});
},
_addState: function _addState(aOutput, aState) {}, // jshint ignore:line
_addState: function _addState(aOutput, aState, aRoleStr) {}, // jshint ignore:line
_addRole: function _addRole(aOutput, aRoleStr) {}, // jshint ignore:line
@ -252,6 +252,7 @@ let OutputGenerator = {
'outlineitem': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'pagetab': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'graphic': INCLUDE_DESC,
'switch': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'pushbutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'checkbutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'radiobutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
@ -307,7 +308,7 @@ let OutputGenerator = {
let output = [];
if (aFlags & INCLUDE_DESC) {
this._addState(output, aState);
this._addState(output, aState, aRoleStr);
this._addType(output, aAccessible, aRoleStr);
this._addRole(output, aRoleStr);
}
@ -413,13 +414,15 @@ let OutputGenerator = {
* not.
*/
this.UtteranceGenerator = { // jshint ignore:line
__proto__: OutputGenerator,
__proto__: OutputGenerator, // jshint ignore:line
gActionMap: {
jump: 'jumpAction',
press: 'pressAction',
check: 'checkAction',
uncheck: 'uncheckAction',
on: 'onAction',
off: 'offAction',
select: 'selectAction',
unselect: 'unselectAction',
open: 'openAction',
@ -475,7 +478,7 @@ this.UtteranceGenerator = { // jshint ignore:line
objectOutputFunctions: {
__proto__: OutputGenerator.objectOutputFunctions,
__proto__: OutputGenerator.objectOutputFunctions, // jshint ignore:line
defaultFunc: function defaultFunc() {
return this.objectOutputFunctions._generateBaseOutput.apply(
@ -597,7 +600,7 @@ this.UtteranceGenerator = { // jshint ignore:line
aOutput.push({string: this._getOutputName(aRoleStr)});
},
_addState: function _addState(aOutput, aState) {
_addState: function _addState(aOutput, aState, aRoleStr) {
if (aState.contains(States.UNAVAILABLE)) {
aOutput.push({string: 'stateUnavailable'});
@ -613,8 +616,13 @@ this.UtteranceGenerator = { // jshint ignore:line
// regardless of the utterance ordering preference.
if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === 'browser') &&
aState.contains(States.CHECKABLE)) {
let statetr = aState.contains(States.CHECKED) ?
'stateChecked' : 'stateNotChecked';
let checked = aState.contains(States.CHECKED);
let statetr;
if (aRoleStr === 'switch') {
statetr = checked ? 'stateOn' : 'stateOff';
} else {
statetr = checked ? 'stateChecked' : 'stateNotChecked';
}
aOutput.push({string: statetr});
}
@ -662,7 +670,7 @@ this.UtteranceGenerator = { // jshint ignore:line
};
this.BrailleGenerator = { // jshint ignore:line
__proto__: OutputGenerator,
__proto__: OutputGenerator, // jshint ignore:line
genForContext: function genForContext(aContext) {
let output = OutputGenerator.genForContext.apply(this, arguments);
@ -699,7 +707,7 @@ this.BrailleGenerator = { // jshint ignore:line
objectOutputFunctions: {
__proto__: OutputGenerator.objectOutputFunctions,
__proto__: OutputGenerator.objectOutputFunctions, // jshint ignore:line
defaultFunc: function defaultFunc() {
return this.objectOutputFunctions._generateBaseOutput.apply(
@ -760,13 +768,17 @@ this.BrailleGenerator = { // jshint ignore:line
_useStateNotRole:
function _useStateNotRole(aAccessible, aRoleStr, aState, aFlags) {
let braille = [];
this._addState(braille, aState, aAccessible.role);
this._addState(braille, aState, aRoleStr);
this._addName(braille, aAccessible, aFlags);
this._addLandmark(braille, aAccessible);
return braille;
},
switch: function braille_generator_object_output_functions_switch() {
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
},
checkbutton: function checkbutton() {
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
},
@ -796,7 +808,7 @@ this.BrailleGenerator = { // jshint ignore:line
aBraille.push({string: this._getOutputName(aRoleStr)});
},
_addState: function _addState(aBraille, aState, aRole) {
_addState: function _addState(aBraille, aState, aRoleStr) {
if (aState.contains(States.CHECKABLE)) {
aBraille.push({
string: aState.contains(States.CHECKED) ?
@ -804,7 +816,7 @@ this.BrailleGenerator = { // jshint ignore:line
this._getOutputName('stateUnchecked')
});
}
if (aRole === Roles.TOGGLE_BUTTON) {
if (aRoleStr === 'toggle button') {
aBraille.push({
string: aState.contains(States.PRESSED) ?
this._getOutputName('statePressed') :

View File

@ -3,15 +3,13 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global PrefCache, Roles, Prefilters, States, Filters, Utils,
TraversalRules */
TraversalRules, Components, XPCOMUtils */
/* exported TraversalRules */
'use strict';
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
this.EXPORTED_SYMBOLS = ['TraversalRules']; // jshint ignore:line
@ -103,7 +101,8 @@ var gSimpleTraversalRoles =
Roles.GRID_CELL,
Roles.COLUMNHEADER,
Roles.ROWHEADER,
Roles.STATUSBAR];
Roles.STATUSBAR,
Roles.SWITCH];
var gSimpleMatchFunc = function gSimpleMatchFunc(aAccessible) {
// An object is simple, if it either has a single child lineage,
@ -240,7 +239,8 @@ this.TraversalRules = { // jshint ignore:line
Roles.RADIO_MENU_ITEM,
Roles.SLIDER,
Roles.CHECKBUTTON,
Roles.CHECK_MENU_ITEM]),
Roles.CHECK_MENU_ITEM,
Roles.SWITCH]),
Graphic: new BaseTraversalRule(
[Roles.GRAPHIC],
@ -302,7 +302,8 @@ this.TraversalRules = { // jshint ignore:line
Checkbox: new BaseTraversalRule(
[Roles.CHECKBUTTON,
Roles.CHECK_MENU_ITEM]),
Roles.CHECK_MENU_ITEM,
Roles.SWITCH /* A type of checkbox that represents on/off values */]),
_shouldSkipImage: function _shouldSkipImage(aAccessible) {
if (gSkipEmptyImages.value && aAccessible.name === '') {

View File

@ -55,6 +55,12 @@
'aria-valuetext', 'medium');
}
function toggleLight() {
var lightSwitch = document.getElementById('light');
lightSwitch.setAttribute('aria-checked',
lightSwitch.getAttribute('aria-checked') === 'true' ? 'false' : 'true');
}
</script>
<style>
#windows {
@ -100,6 +106,7 @@
</div>
<button id="home">Home</button>
<button id="fruit" aria-label="apple"></button>
<span id="light" role="switch" aria-label="Light" aria-checked="false" onclick="toggleLight()"></span>
<div id="live" aria-live="polite" aria-label="live">
<div id="slider" role="slider" aria-label="slider" aria-valuemin="0"
aria-valuemax="10" aria-valuenow="0"></div>

View File

@ -143,5 +143,7 @@
</table>
<div id="statusbar-1" role="status">Last sync:<span>2 days ago</span></div>
<div aria-label="Last sync: 30min ago" id="statusbar-2" role="status"></div>
<span id="switch-1" role="switch" aria-checked="false" aria-label="Light switch"></span>
</body>
</html>

View File

@ -617,6 +617,18 @@ function ExpectedCheckAction(aChecked, aOptions) {
ExpectedCheckAction.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedSwitchAction(aSwitched, aOptions) {
ExpectedPresent.call(this, {
eventType: 'action',
data: [{ string: aSwitched ? 'onAction' : 'offAction' }]
}, [{
eventType: AndroidEvent.VIEW_CLICKED,
checked: aSwitched
}], aOptions);
}
ExpectedSwitchAction.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedNameChange(aName, aOptions) {
ExpectedPresent.call(this, {
eventType: 'name-change',

View File

@ -58,10 +58,22 @@
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['apple', {'string': 'pushbutton'}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['Light', {"string": "stateOff"}, {'string': 'switch'}])],
// switch on
[ContentMessages.activateCurrent(),
new ExpectedClickAction({ no_android: true }),
new ExpectedSwitchAction(true)],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(['slider', '0', {'string': 'slider'}])],
// Simple traversal backward
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(['Light', {"string": "stateOn"}, {'string': 'switch'}])],
// switch off
[ContentMessages.activateCurrent(),
new ExpectedClickAction({ no_android: true }),
new ExpectedSwitchAction(false)],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(['apple', {'string': 'pushbutton'}])],
[ContentMessages.simpleMovePrevious,

View File

@ -488,6 +488,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
expectedUtterance: [["Last sync: 30min ago"],
["Last sync: 30min ago"]],
expectedBraille: [["Last sync: 30min ago"], ["Last sync: 30min ago"]]
}, {
accOrElmOrID: "switch-1",
expectedUtterance: [[{"string": "stateOn"}, {"string": "switch"},
"Simple switch"], ["Simple switch", {"string": "stateOn"},
{"string": "switch"}]],
expectedBraille: [[{"string": "stateCheckedAbbr"}, "Simple switch"],
["Simple switch", {"string": "stateCheckedAbbr"}]]
}, {
accOrElmOrID: "switch-2",
expectedUtterance: [[{"string": "stateOff"},
{"string": "switch"}, "Another switch"], ["Another switch",
{"string": "stateOff"}, {"string": "switch"}]],
expectedBraille: [
[{"string": "stateUncheckedAbbr"}, "Another switch"],
["Another switch", {"string": "stateUncheckedAbbr"}]]
}];
// Test all possible utterance order preference values.
@ -645,6 +660,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
</select>
<div id="statusbar-1" role="status">Last sync:<span>2 days ago</span></div>
<div aria-label="Last sync: 30min ago" id="statusbar-2" role="status"></div>
<span id="switch-1" role="switch" aria-label="Simple switch" aria-checked="true"></span>
<span id="switch-2" role="switch" aria-label="Another switch" aria-checked="false"></span>
</div>
</body>
</html>

View File

@ -56,7 +56,7 @@
'select-1-1', 'select-1-2', 'checkbox-1-2',
'select-1-3', 'input-1-5', 'button-1-3',
'button-2-1', 'button-2-2', 'button-2-3',
'button-2-4', 'checkbox-1-5']);
'button-2-4', 'checkbox-1-5', 'switch-1']);
queueTraversalSequence(gQueue, docAcc, TraversalRules.Button, null,
['button-1-1', 'button-1-2', 'button-1-3',
@ -67,7 +67,8 @@
['radio-1-1', 'radio-1-2']);
queueTraversalSequence(gQueue, docAcc, TraversalRules.Checkbox, null,
['checkbox-1-1', 'checkbox-1-2', 'checkbox-1-5']);
['checkbox-1-1', 'checkbox-1-2', 'checkbox-1-5',
'switch-1']);
queueTraversalSequence(gQueue, docAcc, TraversalRules.Combobox, null,
['select-1-1', 'select-1-2', 'select-1-3']);
@ -122,7 +123,8 @@
'1', 'Sunday', 'M', 'Week 1', '3', '4', '7', '2',
'5 8', 'gridcell4', 'Just an innocuous separator',
'Dirty Words', 'Meaning', 'Mud', 'Wet Dirt',
'Dirt', 'Messy Stuff', 'statusbar-1', 'statusbar-2']);
'Dirt', 'Messy Stuff', 'statusbar-1', 'statusbar-2',
'switch-1']);
gQueue.invoke();
}

View File

@ -32,6 +32,7 @@ outlineitem = outline item
pagetab = tab
propertypage = property page
graphic = graphic
switch = switch
pushbutton = button
checkbutton = check button
radiobutton = radio button
@ -127,6 +128,8 @@ jumpAction = jumped
pressAction = pressed
checkAction = checked
uncheckAction = unchecked
onAction = on
offAction = off
selectAction = selected
unselectAction = unselected
openAction = opened
@ -151,7 +154,9 @@ tabReload = reloading
# Object states
stateChecked = checked
stateOn = on
stateNotChecked = not checked
stateOff = off
statePressed = pressed
# No string for a not pressed toggle button
stateExpanded = expanded