Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4219)

Unified Diff: chrome/browser/resources/chromeos/switch_access/switch_access.js

Issue 2738893003: Use keys 1 through 3 to switch between and click on focusable elements. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/chromeos/accessibility/switch_access_event_handler.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/resources/chromeos/switch_access/switch_access.js
diff --git a/chrome/browser/resources/chromeos/switch_access/switch_access.js b/chrome/browser/resources/chromeos/switch_access/switch_access.js
index 5b35495f867bbb23f49876b9496628f1582a6585..1a9d91b2de9caae091f07c689aabad743b8ac98a 100644
--- a/chrome/browser/resources/chromeos/switch_access/switch_access.js
+++ b/chrome/browser/resources/chromeos/switch_access/switch_access.js
@@ -2,24 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-var AutomationNode = chrome.automation.AutomationNode;
+let AutomationNode = chrome.automation.AutomationNode;
+let debuggingEnabled = true;
/**
* @constructor
*/
-var SwitchAccess = function() {
+let SwitchAccess = function() {
console.log("Switch access is enabled");
// Currently selected node.
/** @private {AutomationNode} */
this.node_ = null;
+ // Root node (i.e., the desktop).
+ /** @private {AutomationNode} */
+ this.root_ = null;
+
// List of nodes to push to / pop from in case this.node_ is lost.
/** @private {!Array<!AutomationNode>} */
this.ancestorList_ = [];
chrome.automation.getDesktop(function(desktop) {
this.node_ = desktop;
+ this.root_ = desktop;
console.log("AutomationNode for desktop is loaded");
this.printDetails_();
@@ -31,26 +37,274 @@ var SwitchAccess = function() {
console.log("2 = go to next element");
this.moveToNext_();
} else if (event.key === "3") {
- console.log("3 = go to child element");
- this.moveToFirstChild_();
- } else if (event.key === "4") {
- console.log("4 = go to parent element");
- this.moveToParent_();
- } else if (event.key === "5") {
- console.log("5 is not yet implemented");
- console.log("\n");
+ console.log("3 = do default on element");
+ this.doDefault_();
+ } else if (debuggingEnabled) {
+ if (event.key === "6") {
+ console.log("6 = go to previous element (debug mode)");
+ this.debugMoveToPrevious_();
+ } else if (event.key === "7") {
+ console.log("7 = go to next element (debug mode)");
+ this.debugMoveToNext_();
+ } else if (event.key === "8") {
+ console.log("8 = go to child element (debug mode)");
+ this.debugMoveToFirstChild_();
+ } else if (event.key === "9") {
+ console.log("9 = go to parent element (debug mode)");
+ this.debugMoveToParent_();
+ }
+ }
+ if (this.node_) {
+ chrome.accessibilityPrivate.setFocusRing([this.node_.location]);
}
- chrome.accessibilityPrivate.setFocusRing([this.node_.location]);
}.bind(this));
}.bind(this));
};
SwitchAccess.prototype = {
/**
- * Move to the previous sibling of this.node_ if it has one.
+ * Set this.node_ to the previous interesting node. If no interesting node
+ * comes before this.node_, set this.node_ to the last interesting node.
+ *
+ * @private
*/
moveToPrevious_: function() {
- var previous = this.node_.previousSibling;
+ let prev = null;
+ if (this.node_) {
+ prev = this.getPreviousNode_(this.node_);
+ }
+ if (prev) {
+ this.node_ = prev;
+ } else if (this.root_) {
+ console.log("Reached the first interesting node. Restarting with last.");
+ this.node_ = this.getInterestingDescendant_(this.root_, false);
+ } else {
+ console.log("Found no interesting nodes to visit");
+ }
+ this.printNode_(this.node_);
+ console.log("\n");
+ },
+
+ /**
+ * Set this.node_ to the next interesting node. If no interesting node comes
+ * after this.node_, set this.node_ to the first interesting node.
+ *
+ * @private
+ */
+ moveToNext_: function() {
+ let next = null;
+ if (this.node_) {
+ next = this.getNextNode_(this.node_);
+ }
+ if (next) {
+ this.node_ = next;
+ } else if (this.root_) {
+ console.log("Reached the last interesting node. Restarting with first.");
+ this.node_ = this.getInterestingDescendant_(this.root_, true);
+ } else {
+ console.log("Found no interesting nodes to visit");
+ }
+ this.printNode_(this.node_);
+ console.log("\n");
+ },
+
+ /**
+ * Given a flat list of nodes in pre-order that are considered interesting,
+ * get the node that comes after |node|.
+ *
+ * @param {!AutomationNode} node
+ * @return {AutomationNode}
+ * @private
+ */
+ getNextNode_: function(node) {
+ // Check descendants.
+ let descendant = this.getInterestingDescendant_(node, true);
+ if (descendant) {
+ return descendant;
+ }
+
+ // No interesting descendant. Check right-siblings and their descendants.
+ let siblingOrDescendant =
+ this.getInterestingSiblingOrDescendant_(node, false);
+ if (siblingOrDescendant) {
+ return siblingOrDescendant;
+ }
+
+ // No interesting right-sibling or descendant of it. Check ancestors and
+ // other relatives that come after |node|.
+ let ancestorOrRelative =
+ this.getInterestingAncestorOrRelative_(node, false);
+ if (ancestorOrRelative) {
+ return ancestorOrRelative;
+ }
+
+ // No interesting node found after |node|, so return null.
+ return null;
+ },
+
+ /**
+ * Given a flat list of nodes in pre-order that are considered interesting,
+ * get the node that comes before |node|.
+ *
+ * @param {!AutomationNode} node
+ * @return {AutomationNode}
+ * @private
+ */
+ getPreviousNode_: function(node) {
+ // Check left-siblings and their descendants.
+ let siblingOrDescendant =
+ this.getInterestingSiblingOrDescendant_(node, true);
+ if (siblingOrDescendant) {
+ return siblingOrDescendant;
+ }
+
+ // No interesting left-sibling or descendant of it. Check ancestors and
+ // other relatives that come before |node|.
+ let ancestorOrRelative = this.getInterestingAncestorOrRelative_(node, true);
+ if (ancestorOrRelative) {
+ return ancestorOrRelative;
+ }
+
+ // No interesting node found before |node|, so return null.
+ return null;
+ },
+
+
+ /**
+ * Find a descendant of |node| that is considered interesting.
+ * If |startAtFirstChild| is true, this function will start by checking the
+ * lowest index child, one level below |node|.
+ * If |startAtFirstChild| is false, this function will start by checking the
+ * leaf descendants of the highest index child.
+ *
+ * @param {!AutomationNode} node
+ * @param {boolean} startAtFirstChild
+ * @return {AutomationNode}
+ * @private
+ */
+ getInterestingDescendant_: function(node, startAtFirstChild) {
+ if (startAtFirstChild) {
+ let child = node.firstChild;
+ while (child) {
+ if (this.isInteresting_(child)) {
dmazzoni 2017/03/09 00:00:01 Right now you have calls to isInteresting througho
elichtenberg 2017/03/09 19:31:44 Done.
+ return child;
+ }
+ let descendant = this.getInterestingDescendant_(child, true);
+ if (descendant) {
+ return descendant;
+ }
+ child = child.nextSibling;
+ }
+ } else {
+ let child = node.lastChild;
+ while (child) {
+ let descendant = this.getInterestingDescendant_(child, false);
+ if (descendant) {
+ return descendant;
+ }
+ if (this.isInteresting_(child)) {
+ return child;
+ }
+ child = child.previousSibling;
+ }
+ }
+ return null;
+ },
+
+ /**
+ * Find a sibling or descendant of a sibling of |node| that is considered
+ * interesting.
+ * If |checkPreviousSibling| is true, this function will only look at |node|'s
+ * lower index sibilngs, and it will first check the sibling's descendants.
+ * If |checkPreviousSibling| is false, this function will only look at
+ * |node|'s higher index siblings, and it will check the sibling before its
+ * descendants.
+ *
+ * @param {!AutomationNode} node
+ * @param {boolean} checkPreviousSibling
+ * @return {AutomationNode}
+ * @private
+ */
+ getInterestingSiblingOrDescendant_: function(node, checkPreviousSibling) {
+ if (checkPreviousSibling) {
+ let sibling = node.previousSibling;
+ while (sibling) {
+ let descendant = this.getInterestingDescendant_(sibling, false);
+ if (descendant) {
+ return descendant;
+ }
+ if (this.isInteresting_(sibling)) {
+ return sibling;
+ }
+ sibling = sibling.previousSibling;
+ }
+ } else {
+ let sibling = node.nextSibling;
+ while (sibling) {
+ if (this.isInteresting_(sibling)) {
+ return sibling;
+ }
+ let descendant = this.getInterestingDescendant_(sibling, true);
+ if (descendant) {
+ return descendant;
+ }
+ sibling = sibling.nextSibling;
+ }
+ }
+ return null;
+ },
+
+ /**
+ * Find an ancestor or other relative of |node| that is considered
+ * interesting.
+ * If |findPrevious| is true, will check nodes that come before |node| in
+ * pre-order, starting with |node|'s parent.
+ * If |findPrevious| is false, will check nodes that come after |node| in
+ * pre-order, not including any descendants or direct ancestors.
+ *
+ * @param {!AutomationNode} node
+ * @param {boolean} findPrevious
+ * @return {AutomationNode}
+ * @private
+ */
+ getInterestingAncestorOrRelative_: function(node, findPrevious) {
+ let ancestor = node.parent;
+ while (ancestor) {
+ if (findPrevious && this.isInteresting_(ancestor)) {
+ return ancestor;
+ }
+ let relative =
+ this.getInterestingSiblingOrDescendant_(ancestor, findPrevious);
+ if (relative) {
+ return relative;
+ }
+ ancestor = ancestor.parent;
+ }
+ return null;
+ },
+
+ /**
+ * Returns true if |node| is interesting.
+ *
+ * @param {!AutomationNode} node
+ * @return {boolean}
+ * @private
+ */
+ isInteresting_: function(node) {
+ if (node.state && node.state.focusable) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+
+ /**
+ * Move to the previous sibling of this.node_ if it has one.
+ *
+ * @private
+ */
+ debugMoveToPrevious_: function() {
+ let previous = this.node_.previousSibling;
if (previous) {
this.node_ = previous;
this.printDetails_();
@@ -62,9 +316,11 @@ SwitchAccess.prototype = {
/**
* Move to the next sibling of this.node_ if it has one.
+ *
+ * @private
*/
- moveToNext_: function() {
- var next = this.node_.nextSibling;
+ debugMoveToNext_: function() {
+ let next = this.node_.nextSibling;
if (next) {
this.node_ = next;
this.printDetails_();
@@ -76,9 +332,11 @@ SwitchAccess.prototype = {
/**
* Move to the first child of this.node_ if it has one.
+ *
+ * @private
*/
- moveToFirstChild_: function() {
- var child = this.node_.firstChild;
+ debugMoveToFirstChild_: function() {
+ let child = this.node_.firstChild;
if (child) {
this.ancestorList_.push(this.node_);
this.node_ = child;
@@ -93,9 +351,11 @@ SwitchAccess.prototype = {
* Move to the parent of this.node_ if it has one. If it does not have a
* parent but it is not the top level root node, then this.node_ lost track of
* its neighbors, and we move to an ancestor node.
+ *
+ * @private
*/
- moveToParent_: function() {
- var parent = this.node_.parent;
+ debugMoveToParent_: function() {
+ let parent = this.node_.parent;
if (parent) {
this.ancestorList_.pop();
this.node_ = parent;
@@ -106,13 +366,31 @@ SwitchAccess.prototype = {
} else {
console.log(
"Node could not find its parent, so moved to recent ancestor");
- var ancestor = this.ancestorList_.pop();
+ let ancestor = this.ancestorList_.pop();
this.node_ = ancestor;
this.printDetails_();
}
},
/**
+ * Perform the default action on the currently selected node.
+ *
+ * @private
+ */
+ doDefault_: function() {
+ let state = this.node_.state;
+ if (state && state.focusable) {
+ console.log("Node was focusable, doing default on it")
+ } else if (state) {
+ console.log("Node was not focusable, but still doing default");
+ } else {
+ console.log("Node has no state, still doing default");
+ }
+ console.log("\n");
+ this.node_.doDefault();
+ },
+
+ /**
* Print out details about the currently selected node and the list of
* ancestors.
*
@@ -137,7 +415,7 @@ SwitchAccess.prototype = {
if (!node.parent) {
console.log("At index " + node.indexInParent + ", has no parent");
} else {
- var numSiblings = node.parent.children.length;
+ let numSiblings = node.parent.children.length;
console.log(
"At index " + node.indexInParent + ", there are "
+ numSiblings + " siblings");
@@ -150,4 +428,4 @@ SwitchAccess.prototype = {
}
};
-new SwitchAccess();
+window.switchAccess = new SwitchAccess();
« no previous file with comments | « chrome/browser/chromeos/accessibility/switch_access_event_handler.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698