Commit 48df727c authored by Zach Helfinstein's avatar Zach Helfinstein Committed by Commit Bot

Update the rest of SwitchAccess to ES2015

Bug: 884297
Change-Id: Iff20201277983eed3d851279ed6e7042ae17d250
Reviewed-on: https://chromium-review.googlesource.com/1237554
Commit-Queue: Zach Helfinstein <zhelfins@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#593271}
parent 4f0593dd
......@@ -5,88 +5,59 @@
/**
* Class to handle interactions with the context menu, including moving through
* and selecting actions.
*
* @constructor
* @param {!AutomationManager} automationManager
* @param {!chrome.automation.AutomationNode} desktop
*/
function ContextMenuManager(automationManager, desktop) {
/**
* A list of the ContextMenu actions that are currently enabled.
* @private {!Array<ContextMenuManager.Action>}
*/
this.actions_ = [];
/**
* The parent automation manager.
* @private {!AutomationManager}
*/
this.automationManager_ = automationManager;
/**
* The root node of the screen.
* @private {!chrome.automation.AutomationNode}
*/
this.desktop_ = desktop;
/**
* The root node of the context menu.
* @private {chrome.automation.AutomationNode}
*/
this.menuNode_;
/**
* The current node of the context menu.
* @private {chrome.automation.AutomationNode}
*/
this.node_;
/**
* Keeps track of when we're in the context menu.
* @private {boolean}
*/
this.inContextMenu_ = false;
this.init_();
}
/**
* Actions available in the Context Menu.
* @enum {string}
* @const
*/
ContextMenuManager.Action = {
CLICK: 'click',
OPTIONS: 'options',
SCROLL_BACKWARD: 'scroll-backward',
SCROLL_DOWN: 'scroll-down',
SCROLL_FORWARD: 'scroll-forward',
SCROLL_LEFT: 'scroll-left',
SCROLL_RIGHT: 'scroll-right',
SCROLL_UP: 'scroll-up'
};
/**
* The ID for the div containing the context menu.
* @const
*/
ContextMenuManager.MenuId = 'switchaccess_contextmenu_actions';
class ContextMenuManager {
/**
* @param {!AutomationManager} automationManager
* @param {!chrome.automation.AutomationNode} desktop
*/
constructor(automationManager, desktop) {
/**
* A list of the ContextMenu actions that are currently enabled.
* @private {!Array<ContextMenuManager.Action>}
*/
this.actions_ = [];
/**
* The parent automation manager.
* @private {!AutomationManager}
*/
this.automationManager_ = automationManager;
/**
* The root node of the screen.
* @private {!chrome.automation.AutomationNode}
*/
this.desktop_ = desktop;
/**
* The root node of the context menu.
* @private {chrome.automation.AutomationNode}
*/
this.menuNode_;
/**
* The current node of the context menu.
* @private {chrome.automation.AutomationNode}
*/
this.node_;
/**
* Keeps track of when we're in the context menu.
* @private {boolean}
*/
this.inContextMenu_ = false;
ContextMenuManager.prototype = {
/**
* @private
*/
init_: function() {
// Listen for messages from the menu.
window.addEventListener('message', this.onMessageReceived_.bind(this));
},
this.init_();
}
/**
* Enter the context menu and highlight the first available action.
*
* @param {!Array<!ContextMenuManager.Action>} actions
*/
enter: function(actions) {
enter(actions) {
this.inContextMenu_ = true;
if (actions !== this.actions_) {
this.actions_ = actions;
......@@ -96,51 +67,51 @@ ContextMenuManager.prototype = {
this.node_ = this.menuNode();
this.moveForward();
},
}
/**
* Exits the context menu.
*/
exit: function() {
exit() {
this.clearFocusRing_();
this.inContextMenu_ = false;
if (this.node_)
this.node_ = null;
},
}
/**
* Move to the next available action in the menu. If this is no next action,
* select the whole context menu to loop again.
* @return {boolean} Whether this function had any effect.
*/
moveForward: function() {
moveForward() {
if (!this.node_ || !this.inContextMenu_)
return false;
this.clearFocusRing_();
let treeWalker = new AutomationTreeWalker(
const treeWalker = new AutomationTreeWalker(
this.node_, constants.Dir.FORWARD,
SwitchAccessPredicate.restrictions(this.menuNode()));
let node = treeWalker.next().node;
const node = treeWalker.next().node;
if (!node)
this.node_ = this.menuNode();
else
this.node_ = node;
this.updateFocusRing_();
return true;
},
}
/**
* Move to the previous available action in the context menu. If we're at the
* beginning of the list, start again at the end.
* @return {boolean} Whether this function had any effect.
*/
moveBackward: function() {
moveBackward() {
if (!this.node_ || !this.inContextMenu_)
return false;
this.clearFocusRing_();
let treeWalker = new AutomationTreeWalker(
const treeWalker = new AutomationTreeWalker(
this.node_, constants.Dir.BACKWARD,
SwitchAccessPredicate.restrictions(this.menuNode()));
let node = treeWalker.next().node;
......@@ -159,7 +130,7 @@ ContextMenuManager.prototype = {
this.node_ = node;
this.updateFocusRing_();
return true;
},
}
/**
* Perform the action indicated by the current button (or no action if the
......@@ -167,7 +138,7 @@ ContextMenuManager.prototype = {
* traditional navigation.
* @return {boolean} Whether this function had any effect.
*/
selectCurrentNode: function() {
selectCurrentNode() {
if (!this.node_ || !this.inContextMenu_)
return false;
......@@ -175,42 +146,50 @@ ContextMenuManager.prototype = {
this.node_.doDefault();
this.exit();
return true;
},
}
/**
* Get the menu node. If it's not defined, search for it.
* @return {!chrome.automation.AutomationNode}
*/
menuNode: function() {
menuNode() {
if (this.menuNode_)
return this.menuNode_;
let treeWalker = new AutomationTreeWalker(
const treeWalker = new AutomationTreeWalker(
this.desktop_, constants.Dir.FORWARD,
SwitchAccessPredicate.contextMenuDiscoveryRestrictions());
treeWalker.next();
if (treeWalker.node) {
this.menuNode_ = treeWalker.node;
const node = treeWalker.next().node;
if (node) {
this.menuNode_ = node;
return this.menuNode_;
}
console.log('Unable to find the context menu.');
return this.desktop_;
},
}
/**
* Clear the focus ring.
* @private
*/
clearFocusRing_: function() {
clearFocusRing_() {
this.updateFocusRing_(true);
},
}
/**
* @private
*/
init_() {
// Listen for messages from the menu.
window.addEventListener('message', this.onMessageReceived_.bind(this));
}
/**
* Receive a message from the context menu, and perform the appropriate
* action.
* @private
*/
onMessageReceived_: function(event) {
onMessageReceived_(event) {
this.exit();
if (event.data === ContextMenuManager.Action.CLICK)
......@@ -223,7 +202,7 @@ ContextMenuManager.prototype = {
event.data === ContextMenuManager.Action.SCROLL_LEFT ||
event.data === ContextMenuManager.Action.SCROLL_RIGHT)
this.automationManager_.scroll(event.data);
},
}
/**
* Send a message to the context menu to update the focus ring around the
......@@ -232,12 +211,34 @@ ContextMenuManager.prototype = {
* @private
* @param {boolean=} opt_clear If true, will clear the focus ring.
*/
updateFocusRing_: function(opt_clear) {
updateFocusRing_(opt_clear) {
if (!this.node_)
return;
let id = this.node_.htmlAttributes.id;
let onOrOff = opt_clear ? 'off' : 'on';
const id = this.node_.htmlAttributes.id;
const onOrOff = opt_clear ? 'off' : 'on';
MessageHandler.sendMessage(
MessageHandler.Destination.PANEL, 'setFocusRing', [id, onOrOff]);
}
}
/**
* Actions available in the Context Menu.
* @enum {string}
* @const
*/
ContextMenuManager.Action = {
CLICK: 'click',
OPTIONS: 'options',
SCROLL_BACKWARD: 'scroll-backward',
SCROLL_DOWN: 'scroll-down',
SCROLL_FORWARD: 'scroll-forward',
SCROLL_LEFT: 'scroll-left',
SCROLL_RIGHT: 'scroll-right',
SCROLL_UP: 'scroll-up'
};
/**
* The ID for the div containing the context menu.
* @const
*/
ContextMenuManager.MenuId = 'switchaccess_contextmenu_actions';
......@@ -4,56 +4,35 @@
/**
* Class to handle keyboard input.
*
* @constructor
* @param {SwitchAccessInterface} switchAccess
*/
function KeyboardHandler(switchAccess) {
class KeyboardHandler {
/**
* SwitchAccess reference.
*
* @private {SwitchAccessInterface}
* @param {!SwitchAccessInterface} switchAccess
*/
this.switchAccess_ = switchAccess;
constructor(switchAccess) {
/**
* SwitchAccess reference.
* @private {!SwitchAccessInterface}
*/
this.switchAccess_ = switchAccess;
this.init_();
}
KeyboardHandler.prototype = {
/**
* Set up key listener.
*
* @private
*/
init_: function() {
this.updateSwitchAccessKeys();
document.addEventListener('keyup', this.handleKeyEvent_.bind(this));
},
this.init_();
}
/**
* Update the keyboard keys captured by Switch Access to those stored in
* prefs.
*/
updateSwitchAccessKeys: function() {
updateSwitchAccessKeys() {
let keyCodes = [];
for (let command of this.switchAccess_.getCommands()) {
let keyCode = this.keyCodeFor_(command);
for (const command of this.switchAccess_.getCommands()) {
const keyCode = this.keyCodeFor_(command);
if ((keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0)) ||
(keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0)))
keyCodes.push(keyCode);
}
chrome.accessibilityPrivate.setSwitchAccessKeys(keyCodes);
},
/**
* Return the key code that |command| maps to.
*
* @param {string} command
* @return {number}
*/
keyCodeFor_: function(command) {
return this.switchAccess_.getNumberPref(command);
},
}
/**
* Run the command associated with the passed keyboard event.
......@@ -61,14 +40,32 @@ KeyboardHandler.prototype = {
* @param {!Event} event
* @private
*/
handleKeyEvent_: function(event) {
for (let command of this.switchAccess_.getCommands()) {
handleKeyEvent_(event) {
for (const command of this.switchAccess_.getCommands()) {
if (this.keyCodeFor_(command) === event.keyCode) {
let key = event.key.toUpperCase();
this.switchAccess_.runCommand(command);
this.switchAccess_.performedUserAction();
return;
}
}
},
};
}
/**
* Set up key listener.
* @private
*/
init_() {
this.updateSwitchAccessKeys();
document.addEventListener('keyup', this.handleKeyEvent_.bind(this));
}
/**
* Return the key code that |command| maps to.
*
* @param {string} command
* @return {number}
*/
keyCodeFor_(command) {
return this.switchAccess_.getNumberPref(command);
}
}
......@@ -3,55 +3,47 @@
// found in the LICENSE file.
/**
* Class to handle sending messages between the background page and the
* context menu.
*
* @constructor
* Handles sending messages between the background page and the context menu.
*/
function MessageHandler() {}
const MessageHandler = {
/**
* function setActions() takes a list of comma-separated action names,
* containing only letters and hyphens.
*/
SET_ACTIONS_REGEX: /setActions[(]((?:[a-zA-Z-]+,)*[a-zA-Z-]+)[)]/,
/**
* function setActions() takes a list of comma-separated action names,
* containing only letters and hyphens.
*/
MessageHandler.SET_ACTIONS_REGEX =
/setActions[(]((?:[a-zA-Z-]+,)*[a-zA-Z-]+)[)]/;
/**
* function setFocusRing() takes one element ID, containing only letters,
* hyphens, and underscores, and either 'on' or 'off'.
*/
MessageHandler.SET_FOCUS_RING_REGEX =
/setFocusRing[(]([a-zA-Z_-]+),((?:on)|(?:off))[)]/;
/**
* function setFocusRing() takes one element ID, containing only letters,
* hyphens, and underscores, and either 'on' or 'off'.
*/
SET_FOCUS_RING_REGEX: /setFocusRing[(]([a-zA-Z_-]+),((?:on)|(?:off))[)]/,
/**
* The possible destinations for messages.
* @enum {string}
* @const
*/
MessageHandler.Destination = {
BACKGROUND: 'background',
PANEL: 'panel.html'
};
/**
* The possible destinations for messages.
* @enum {string}
* @const
*/
Destination: {BACKGROUND: 'background', PANEL: 'panel.html'},
/**
* Sends a message to the Context Menu panel with the given name and
* parameters.
*
* @param {!MessageHandler.Destination} destination
* @param {string} messageName
* @param {Array<string>=} params
*/
MessageHandler.sendMessage = function(destination, messageName, params) {
let message = messageName;
if (params)
message += '(' + params.join(',') + ')';
/**
* Sends a message to the Context Menu panel with the given name and
* parameters.
*
* @param {!MessageHandler.Destination} destination
* @param {string} messageName
* @param {Array<string>=} opt_params
*/
sendMessage: (destination, messageName, opt_params) => {
let message = messageName;
if (opt_params)
message += '(' + opt_params.join(',') + ')';
let views = chrome.extension.getViews() || [];
for (let view of views)
if (view && view.location.href.includes(destination)) {
view.postMessage(message, window.location.origin);
return;
}
console.log('Couldn\'t find ' << destination);
const views = chrome.extension.getViews() || [];
for (const view of views)
if (view && view.location.href.includes(destination)) {
view.postMessage(message, window.location.origin);
return;
}
console.log('Couldn\'t find ', destination);
}
};
......@@ -4,43 +4,41 @@
/**
* Class to manage the options page.
*
* @constructor
*/
function SwitchAccessOptions() {
let background = chrome.extension.getBackgroundPage();
class SwitchAccessOptions {
constructor() {
const background = chrome.extension.getBackgroundPage();
/**
* SwitchAccess reference.
*
* @private {SwitchAccessInterface}
*/
this.switchAccess_ = background.switchAccess;
/**
* SwitchAccess reference.
* @private {!SwitchAccessInterface}
*/
this.switchAccess_ = background.switchAccess;
this.init_();
document.addEventListener('change', this.handleInputChange_.bind(this));
background.document.addEventListener(
'prefsUpdate', this.handlePrefsUpdate_.bind(this));
}
this.init_();
document.addEventListener('change', this.handleInputChange_.bind(this));
background.document.addEventListener(
'prefsUpdate', this.handlePrefsUpdate_.bind(this));
}
SwitchAccessOptions.prototype = {
/**
* Initialize the options page by setting all elements representing a user
* preference to show the correct value.
*
* @private
*/
init_: function() {
init_() {
document.getElementById('enableAutoScan').checked =
this.switchAccess_.getBooleanPref('enableAutoScan');
document.getElementById('autoScanTime').value =
this.switchAccess_.getNumberPref('autoScanTime') / 1000;
for (let command of this.switchAccess_.getCommands()) {
for (const command of this.switchAccess_.getCommands()) {
document.getElementById(command).value =
String.fromCharCode(this.switchAccess_.getNumberPref(command));
}
},
}
/**
* Handle a change by the user to an element representing a user preference.
......@@ -48,16 +46,16 @@ SwitchAccessOptions.prototype = {
* @param {!Event} event
* @private
*/
handleInputChange_: function(event) {
let input = event.target;
handleInputChange_(event) {
const input = event.target;
switch (input.id) {
case 'enableAutoScan':
this.switchAccess_.setPref(input.id, input.checked);
break;
case 'autoScanTime':
let oldVal = this.switchAccess_.getNumberPref(input.id);
let val = Number(input.value) * 1000;
let min = Number(input.min) * 1000;
const oldVal = this.switchAccess_.getNumberPref(input.id);
const val = Number(input.value) * 1000;
const min = Number(input.min) * 1000;
if (this.isValidScanTimeInput_(val, oldVal, min)) {
input.value = Number(input.value);
this.switchAccess_.setPref(input.id, val);
......@@ -67,17 +65,17 @@ SwitchAccessOptions.prototype = {
break;
default:
if (this.switchAccess_.getCommands().includes(input.id)) {
let keyCode = input.value.toUpperCase().charCodeAt(0);
const keyCode = input.value.toUpperCase().charCodeAt(0);
if (this.isValidKeyCode_(keyCode)) {
input.value = input.value.toUpperCase();
this.switchAccess_.setPref(input.id, keyCode);
} else {
let oldKeyCode = this.switchAccess_.getNumberPref(input.id);
const oldKeyCode = this.switchAccess_.getNumberPref(input.id);
input.value = String.fromCharCode(oldKeyCode);
}
}
}
},
}
/**
* Return true if |keyCode| is a letter or number, and if it is not already
......@@ -86,11 +84,11 @@ SwitchAccessOptions.prototype = {
* @param {number} keyCode
* @return {boolean}
*/
isValidKeyCode_: function(keyCode) {
isValidKeyCode_(keyCode) {
return ((keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0)) ||
(keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0))) &&
!this.switchAccess_.keyCodeIsUsed(keyCode);
},
}
/**
* Return true if the input is a valid autoScanTime input. Otherwise, return
......@@ -101,9 +99,9 @@ SwitchAccessOptions.prototype = {
* @param {number} min
* @return {boolean}
*/
isValidScanTimeInput_: function(value, oldValue, min) {
isValidScanTimeInput_(value, oldValue, min) {
return (value !== oldValue) && (value >= min);
},
}
/**
* Handle a change in user preferences.
......@@ -111,8 +109,8 @@ SwitchAccessOptions.prototype = {
* @param {!Event} event
* @private
*/
handlePrefsUpdate_: function(event) {
let updatedPrefs = event.detail;
handlePrefsUpdate_(event) {
const updatedPrefs = event.detail;
for (let key of Object.keys(updatedPrefs)) {
switch (key) {
case 'enableAutoScan':
......@@ -128,7 +126,7 @@ SwitchAccessOptions.prototype = {
}
}
}
};
}
document.addEventListener('DOMContentLoaded', function() {
new SwitchAccessOptions();
......
......@@ -4,32 +4,61 @@
/**
* Class to manage user preferences.
*
* @constructor
* @param {SwitchAccessInterface} switchAccess
*/
function SwitchAccessPrefs(switchAccess) {
class SwitchAccessPrefs {
/**
* SwitchAccess reference.
*
* @private {SwitchAccessInterface}
* @param {!SwitchAccessInterface} switchAccess
*/
this.switchAccess_ = switchAccess;
constructor(switchAccess) {
/**
* SwitchAccess reference.
* @private {!SwitchAccessInterface}
*/
this.switchAccess_ = switchAccess;
/**
* User preferences, initially set to the default preference values.
* @private
*/
this.prefs_ = Object.assign({}, DEFAULT_PREFS);
this.init_();
}
/**
* User preferences, initially set to the default preference values.
* Store any changes from chrome.storage.sync to this.prefs_, if this.prefs_
* is not already set to that value. If this.prefs_ changes, fire a
* prefsUpdate event.
*
* @param {!Object} storageChanges
* @param {string} areaName
* @private
*/
handleStorageChange_(storageChanges, areaName) {
let updatedPrefs = {};
for (const key of Object.keys(storageChanges)) {
if (this.prefs_[key] !== storageChanges[key].newValue) {
this.prefs_[key] = storageChanges[key].newValue;
updatedPrefs[key] = storageChanges[key].newValue;
}
}
if (Object.keys(updatedPrefs).length > 0) {
let event = new CustomEvent('prefsUpdate', {'detail': updatedPrefs});
document.dispatchEvent(event);
}
}
/**
* @private
*/
this.prefs_ = Object.assign({}, this.DEFAULT_PREFS);
for (let command of this.switchAccess_.getCommands())
this.prefs_[command] = this.switchAccess_.getDefaultKeyCodeFor(command);
init_() {
for (const command of this.switchAccess_.getCommands())
this.prefs_[command] = this.switchAccess_.getDefaultKeyCodeFor(command);
this.loadPrefs_();
chrome.storage.onChanged.addListener(this.handleStorageChange_.bind(this));
}
this.loadPrefs_();
chrome.storage.onChanged.addListener(this.handleStorageChange_.bind(this));
}
SwitchAccessPrefs.prototype = {
/**
* Asynchronously load the current preferences from chrome.storage.sync and
* store them in this.prefs_, if this.prefs_ is not already set to that value.
......@@ -37,45 +66,24 @@ SwitchAccessPrefs.prototype = {
*
* @private
*/
loadPrefs_: function() {
let defaultKeys = Object.keys(this.prefs_);
chrome.storage.sync.get(defaultKeys, function(loadedPrefs) {
loadPrefs_() {
const defaultKeys = Object.keys(this.prefs_);
chrome.storage.sync.get(defaultKeys, (loadedPrefs) => {
let updatedPrefs = {};
for (let key of Object.keys(loadedPrefs)) {
for (const key of Object.keys(loadedPrefs)) {
if (this.prefs_[key] !== loadedPrefs[key]) {
this.prefs_[key] = loadedPrefs[key];
updatedPrefs[key] = loadedPrefs[key];
}
}
if (Object.keys(updatedPrefs).length > 0) {
let event = new CustomEvent('prefsUpdate', {'detail': updatedPrefs});
const event = new CustomEvent('prefsUpdate', {'detail': updatedPrefs});
document.dispatchEvent(event);
}
}.bind(this));
},
/**
* Store any changes from chrome.storage.sync to this.prefs_, if this.prefs_
* is not already set to that value. If this.prefs_ changes, fire a
* prefsUpdate event.
*
* @param {!Object} storageChanges
* @param {string} areaName
* @private
*/
handleStorageChange_: function(storageChanges, areaName) {
let updatedPrefs = {};
for (let key of Object.keys(storageChanges)) {
if (this.prefs_[key] !== storageChanges[key].newValue) {
this.prefs_[key] = storageChanges[key].newValue;
updatedPrefs[key] = storageChanges[key].newValue;
}
}
if (Object.keys(updatedPrefs).length > 0) {
let event = new CustomEvent('prefsUpdate', {'detail': updatedPrefs});
document.dispatchEvent(event);
}
},
});
}
/**
* Set the value of the preference |key| to |value| in chrome.storage.sync.
......@@ -84,11 +92,11 @@ SwitchAccessPrefs.prototype = {
* @param {string} key
* @param {boolean|string|number} value
*/
setPref: function(key, value) {
setPref(key, value) {
let pref = {};
pref[key] = value;
chrome.storage.sync.set(pref);
},
}
/**
* Get the value of type 'boolean' of the preference |key|. Will throw a type
......@@ -97,13 +105,13 @@ SwitchAccessPrefs.prototype = {
* @param {string} key
* @return {boolean}
*/
getBooleanPref: function(key) {
let value = this.prefs_[key];
getBooleanPref(key) {
const value = this.prefs_[key];
if (typeof value === 'boolean')
return value;
else
throw new TypeError('No value of boolean type for key \'' + key + '\'');
},
}
/**
* Get the value of type 'number' of the preference |key|. Will throw a type
......@@ -112,13 +120,13 @@ SwitchAccessPrefs.prototype = {
* @param {string} key
* @return {number}
*/
getNumberPref: function(key) {
let value = this.prefs_[key];
getNumberPref(key) {
const value = this.prefs_[key];
if (typeof value === 'number')
return value;
else
throw new TypeError('No value of number type for key \'' + key + '\'');
},
}
/**
* Get the value of type 'string' of the preference |key|. Will throw a type
......@@ -127,13 +135,13 @@ SwitchAccessPrefs.prototype = {
* @param {string} key
* @return {string}
*/
getStringPref: function(key) {
let value = this.prefs_[key];
getStringPref(key) {
const value = this.prefs_[key];
if (typeof value === 'string')
return value;
else
throw new TypeError('No value of string type for key \'' + key + '\'');
},
}
/**
* Returns true if |keyCode| is already used to run a command from the
......@@ -142,19 +150,20 @@ SwitchAccessPrefs.prototype = {
* @param {number} keyCode
* @return {boolean}
*/
keyCodeIsUsed: function(keyCode) {
for (let command of this.switchAccess_.getCommands()) {
keyCodeIsUsed(keyCode) {
for (const command of this.switchAccess_.getCommands()) {
if (keyCode === this.prefs_[command])
return true;
}
return false;
},
}
}
/**
* The default value of all preferences besides command keyboard bindings.
* All preferences should be primitives to prevent changes to default values.
*
* @const
*/
DEFAULT_PREFS: {'enableAutoScan': false, 'autoScanTime': 800}
/**
* The default value of all preferences besides command keyboard bindings.
* All preferences should be primitives to prevent changes to default values.
*/
const DEFAULT_PREFS = {
'enableAutoScan': false,
'autoScanTime': 800
};
......@@ -4,59 +4,51 @@
/**
* Class to manage SwitchAccess and interact with other controllers.
*
* @constructor
* @implements {SwitchAccessInterface}
*/
function SwitchAccess() {
console.log('Switch access is enabled');
/**
* User commands.
*
* @private {Commands}
*/
this.commands_ = null;
/**
* User preferences.
*
* @private {SwitchAccessPrefs}
*/
this.switchAccessPrefs_ = null;
/**
* Handles changes to auto-scan.
*
* @private {AutoScanManager}
*/
this.autoScanManager_ = null;
/**
* Handles keyboard input.
*
* @private {KeyboardHandler}
*/
this.keyboardHandler_ = null;
/**
* Handles interactions with the accessibility tree, including moving to and
* selecting nodes.
*
* @private {AutomationManager}
*/
this.automationManager_ = null;
this.init_();
}
class SwitchAccess {
constructor() {
console.log('Switch access is enabled');
/**
* User commands.
* @private {Commands}
*/
this.commands_ = null;
/**
* User preferences.
* @private {SwitchAccessPrefs}
*/
this.switchAccessPrefs_ = null;
/**
* Handles changes to auto-scan.
* @private {AutoScanManager}
*/
this.autoScanManager_ = null;
/**
* Handles keyboard input.
* @private {KeyboardHandler}
*/
this.keyboardHandler_ = null;
/**
* Handles interactions with the accessibility tree, including moving to and
* selecting nodes.
* @private {AutomationManager}
*/
this.automationManager_ = null;
this.init_();
}
SwitchAccess.prototype = {
/**
* Set up preferences, controllers, and event listeners.
*
* @private
*/
init_: function() {
init_() {
this.commands_ = new Commands(this);
this.switchAccessPrefs_ = new SwitchAccessPrefs(this);
this.autoScanManager_ = new AutoScanManager(this);
......@@ -68,105 +60,98 @@ SwitchAccess.prototype = {
document.addEventListener(
'prefsUpdate', this.handlePrefsUpdate_.bind(this));
},
}
/**
* Jump to the context menu.
* @override
*/
enterContextMenu: function() {
enterContextMenu() {
if (this.automationManager_)
this.automationManager_.enterContextMenu();
},
}
/**
* Move to the next interesting node.
* @override
*/
moveForward: function() {
moveForward() {
if (this.automationManager_)
this.automationManager_.moveForward();
},
}
/**
* Move to the previous interesting node.
* @override
*/
moveBackward: function() {
moveBackward() {
if (this.automationManager_)
this.automationManager_.moveBackward();
},
}
/**
* Perform the default action on the current node.
*
* @override
*/
selectCurrentNode: function() {
selectCurrentNode() {
if (this.automationManager_)
this.automationManager_.selectCurrentNode();
},
}
/**
* Open the options page in a new tab.
*
* @override
*/
showOptionsPage: function() {
let optionsPage = {url: 'options.html'};
showOptionsPage() {
const optionsPage = {url: 'options.html'};
chrome.tabs.create(optionsPage);
},
}
/**
* Return a list of the names of all user commands.
*
* @override
* @return {!Array<string>}
*/
getCommands: function() {
getCommands() {
return this.commands_.getCommands();
},
}
/**
* Return the default key code for a command.
*
* @override
* @param {string} command
* @return {number}
*/
getDefaultKeyCodeFor: function(command) {
getDefaultKeyCodeFor(command) {
return this.commands_.getDefaultKeyCodeFor(command);
},
}
/**
* Run the function binding for the specified command.
*
* @override
* @param {string} command
*/
runCommand: function(command) {
runCommand(command) {
this.commands_.runCommand(command);
},
}
/**
* Perform actions as the result of actions by the user. Currently, restarts
* auto-scan if it is enabled.
*
* @override
*/
performedUserAction: function() {
performedUserAction() {
this.autoScanManager_.restartIfRunning();
},
}
/**
* Handle a change in user preferences.
*
* @param {!Event} event
* @private
*/
handlePrefsUpdate_: function(event) {
let updatedPrefs = event.detail;
for (let key of Object.keys(updatedPrefs)) {
handlePrefsUpdate_(event) {
const updatedPrefs = event.detail;
for (const key of Object.keys(updatedPrefs)) {
switch (key) {
case 'enableAutoScan':
this.autoScanManager_.setEnabled(updatedPrefs[key]);
......@@ -179,7 +164,7 @@ SwitchAccess.prototype = {
this.keyboardHandler_.updateSwitchAccessKeys();
}
}
},
}
/**
* Set the value of the preference |key| to |value| in chrome.storage.sync.
......@@ -189,9 +174,9 @@ SwitchAccess.prototype = {
* @param {string} key
* @param {boolean|string|number} value
*/
setPref: function(key, value) {
setPref(key, value) {
this.switchAccessPrefs_.setPref(key, value);
},
}
/**
* Get the value of type 'boolean' of the preference |key|. Will throw a type
......@@ -201,9 +186,9 @@ SwitchAccess.prototype = {
* @param {string} key
* @return {boolean}
*/
getBooleanPref: function(key) {
getBooleanPref(key) {
return this.switchAccessPrefs_.getBooleanPref(key);
},
}
/**
* Get the value of type 'number' of the preference |key|. Will throw a type
......@@ -213,9 +198,9 @@ SwitchAccess.prototype = {
* @param {string} key
* @return {number}
*/
getNumberPref: function(key) {
getNumberPref(key) {
return this.switchAccessPrefs_.getNumberPref(key);
},
}
/**
* Get the value of type 'string' of the preference |key|. Will throw a type
......@@ -225,9 +210,9 @@ SwitchAccess.prototype = {
* @param {string} key
* @return {string}
*/
getStringPref: function(key) {
getStringPref(key) {
return this.switchAccessPrefs_.getStringPref(key);
},
}
/**
* Returns true if |keyCode| is already used to run a command from the
......@@ -237,7 +222,7 @@ SwitchAccess.prototype = {
* @param {number} keyCode
* @return {boolean}
*/
keyCodeIsUsed: function(keyCode) {
keyCodeIsUsed(keyCode) {
return this.switchAccessPrefs_.keyCodeIsUsed(keyCode);
}
};
}
......@@ -4,43 +4,39 @@
/**
* Interface for controllers to interact with main SwitchAccess class.
*
* @interface
*/
function SwitchAccessInterface() {}
SwitchAccessInterface.prototype = {
class SwitchAccessInterface {
/**
* Jump to the context menu.
*/
enterContextMenu: function() {},
enterContextMenu() {}
/**
* Move to the next interesting node.
*/
moveForward: function() {},
moveForward() {}
/**
* Move to the previous interesting node.
*/
moveBackward: function() {},
moveBackward() {}
/**
* Perform the default action on the current node.
*/
selectCurrentNode: function() {},
selectCurrentNode() {}
/**
* Open the options page in a new tab.
*/
showOptionsPage: function() {},
showOptionsPage() {}
/**
* Return a list of the names of all user commands.
*
* @return {!Array<string>}
*/
getCommands: function() {},
getCommands() {}
/**
* Return the default key code for a command.
......@@ -48,20 +44,19 @@ SwitchAccessInterface.prototype = {
* @param {string} command
* @return {number}
*/
getDefaultKeyCodeFor: function(command) {},
getDefaultKeyCodeFor(command) {}
/**
* Run the function binding for the specified command.
*
* @param {string} command
*/
runCommand: function(command) {},
runCommand(command) {}
/**
* Perform actions as the result of actions by the user. Currently, restarts
* auto-scan if it is enabled.
*/
performedUserAction: function() {},
performedUserAction() {}
/**
* Set the value of the preference |key| to |value| in chrome.storage.sync.
......@@ -70,7 +65,7 @@ SwitchAccessInterface.prototype = {
* @param {string} key
* @param {boolean|string|number} value
*/
setPref: function(key, value) {},
setPref(key, value) {}
/**
* Get the value of type 'boolean' of the preference |key|. Will throw a type
......@@ -79,7 +74,7 @@ SwitchAccessInterface.prototype = {
* @param {string} key
* @return {boolean}
*/
getBooleanPref: function(key) {},
getBooleanPref(key) {}
/**
* Get the value of type 'number' of the preference |key|. Will throw a type
......@@ -88,7 +83,7 @@ SwitchAccessInterface.prototype = {
* @param {string} key
* @return {number}
*/
getNumberPref: function(key) {},
getNumberPref(key) {}
/**
* Get the value of type 'string' of the preference |key|. Will throw a type
......@@ -97,7 +92,7 @@ SwitchAccessInterface.prototype = {
* @param {string} key
* @return {string}
*/
getStringPref: function(key) {},
getStringPref(key) {}
/**
* Returns true if |keyCode| is already used to run a command from the
......@@ -106,5 +101,5 @@ SwitchAccessInterface.prototype = {
* @param {number} keyCode
* @return {boolean}
*/
keyCodeIsUsed: function(keyCode) {}
};
keyCodeIsUsed(keyCode) {}
}
......@@ -2,22 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function TestSupport() {}
TestSupport.prototype = {
const TestSupport = {
/**
* Connect |parent| and |children| to each other.
*
* @param {!Object} parent
* @param {Array<Object>} children
*/
setChildren: function(parent, children) {
setChildren: (parent, children) => {
// Connect parent to its children.
parent.children = children;
parent.firstChild = children[0];
parent.lastChild = children[children.length - 1];
for (let i = 0; i < children.length; i++) {
for (const i = 0; i < children.length; i++) {
let child = children[i];
// Connect children to their parent.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment