| Index: chrome/browser/resources/chromeos/switch_access/tree_walker.js
|
| diff --git a/chrome/browser/resources/chromeos/switch_access/tree_walker.js b/chrome/browser/resources/chromeos/switch_access/tree_walker.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3e53738220820a9b94fd98029d5e965b641cd49c
|
| --- /dev/null
|
| +++ b/chrome/browser/resources/chromeos/switch_access/tree_walker.js
|
| @@ -0,0 +1,240 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/**
|
| + * Class to move to the appropriate node in the accessibility tree.
|
| + *
|
| + * @constructor
|
| + */
|
| +let AutomationTreeWalker = function() {};
|
| +
|
| +AutomationTreeWalker.prototype = {
|
| + /**
|
| + * Return the next interesting node after |node|. If no interesting node comes
|
| + * after |node|, return the first interesting node.
|
| + *
|
| + * @param {AutomationNode} node
|
| + * @param {AutomationNode} root
|
| + * @return {AutomationNode}
|
| + */
|
| + moveToNext: function(node, root) {
|
| + if (node) {
|
| + let next = this.getNextNode_(node);
|
| + while (next && !this.isInteresting_(next))
|
| + next = this.getNextNode_(next);
|
| + if (next)
|
| + return next;
|
| + }
|
| +
|
| + if (root) {
|
| + console.log('Reached the last interesting node. Restarting with first.');
|
| + let next = root.firstChild;
|
| + while (next && !this.isInteresting_(next))
|
| + next = this.getNextNode_(next);
|
| + if (next)
|
| + return next;
|
| + }
|
| +
|
| + console.log('Found no interesting nodes to visit.');
|
| + return null;
|
| + },
|
| +
|
| + /**
|
| + * Returns the previous interesting node before |node|. If no interesting node
|
| + * comes before |node|, return the last interesting node.
|
| + *
|
| + * @param {AutomationNode} node
|
| + * @param {AutomationNode} root
|
| + * @return {AutomationNode}
|
| + */
|
| + moveToPrevious: function(node, root) {
|
| + if (node) {
|
| + let prev = this.getPreviousNode_(node);
|
| + while (prev && !this.isInteresting_(prev))
|
| + prev = this.getPreviousNode_(prev);
|
| + if (prev)
|
| + return prev;
|
| + }
|
| +
|
| + if (root) {
|
| + console.log('Reached the first interesting node. Restarting with last.')
|
| + let prev = this.getYoungestDescendant_(root);
|
| + while (prev && !this.isInteresting_(prev))
|
| + prev = this.getPreviousNode_(prev);
|
| + if (prev)
|
| + return prev;
|
| + }
|
| +
|
| + console.log('Found no interesting nodes to visit.')
|
| + return null;
|
| + },
|
| +
|
| + /**
|
| + * Given a flat list of nodes in pre-order, get the node that comes after
|
| + * |node|.
|
| + *
|
| + * @param {!AutomationNode} node
|
| + * @return {AutomationNode}
|
| + * @private
|
| + */
|
| + getNextNode_: function(node) {
|
| + // Check for child.
|
| + let child = node.firstChild;
|
| + if (child)
|
| + return child;
|
| +
|
| + // No child. Check for right-sibling.
|
| + let sibling = node.nextSibling;
|
| + if (sibling)
|
| + return sibling;
|
| +
|
| + // No right-sibling. Get right-sibling of closest ancestor.
|
| + let ancestor = node.parent;
|
| + while (ancestor) {
|
| + let aunt = ancestor.nextSibling;
|
| + if (aunt)
|
| + return aunt;
|
| + ancestor = ancestor.parent;
|
| + }
|
| +
|
| + // No node found after |node|, so return null.
|
| + return null;
|
| + },
|
| +
|
| + /**
|
| + * Given a flat list of nodes in pre-order, get the node that comes before
|
| + * |node|.
|
| + *
|
| + * @param {!AutomationNode} node
|
| + * @return {AutomationNode}
|
| + * @private
|
| + */
|
| + getPreviousNode_: function(node) {
|
| + // Check for left-sibling. Return its youngest descendant if it has one.
|
| + // Otherwise, return the sibling.
|
| + let sibling = node.previousSibling;
|
| + if (sibling) {
|
| + let descendant = this.getYoungestDescendant_(sibling);
|
| + if (descendant)
|
| + return descendant;
|
| + return sibling;
|
| + }
|
| +
|
| + // No left-sibling. Check for parent.
|
| + let parent = node.parent;
|
| + if (parent)
|
| + return parent;
|
| +
|
| + // No node found before |node|, so return null.
|
| + return null;
|
| + },
|
| +
|
| + /**
|
| + * Get the youngest descendant of |node| if it has one.
|
| + *
|
| + * @param {!AutomationNode} node
|
| + * @return {AutomationNode}
|
| + * @private
|
| + */
|
| + getYoungestDescendant_: function(node) {
|
| + if (!node.lastChild)
|
| + return null;
|
| +
|
| + while (node.lastChild)
|
| + node = node.lastChild;
|
| +
|
| + return node;
|
| + },
|
| +
|
| + /**
|
| + * Returns true if |node| is interesting.
|
| + *
|
| + * @param {!AutomationNode} node
|
| + * @return {boolean}
|
| + * @private
|
| + */
|
| + isInteresting_: function(node) {
|
| + return node.state && node.state.focusable;
|
| + },
|
| +
|
| + /**
|
| + * Return the next sibling of |node| if it has one.
|
| + *
|
| + * @param {AutomationNode} node
|
| + * @return {AutomationNode}
|
| + */
|
| + debugMoveToNext: function(node) {
|
| + if (!node)
|
| + return null;
|
| +
|
| + let next = node.nextSibling;
|
| + if (next) {
|
| + return next;
|
| + } else {
|
| + console.log('Node is last of siblings');
|
| + console.log('\n');
|
| + return null;
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Return the previous sibling of |node| if it has one.
|
| + *
|
| + * @param {AutomationNode} node
|
| + * @return {AutomationNode}
|
| + */
|
| + debugMoveToPrevious: function(node) {
|
| + if (!node)
|
| + return null;
|
| +
|
| + let prev = node.previousSibling;
|
| + if (prev) {
|
| + return prev;
|
| + } else {
|
| + console.log('Node is first of siblings');
|
| + console.log('\n');
|
| + return null;
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Return the first child of |node| if it has one.
|
| + *
|
| + * @param {AutomationNode} node
|
| + * @return {AutomationNode}
|
| + */
|
| + debugMoveToFirstChild: function(node) {
|
| + if (!node)
|
| + return null;
|
| +
|
| + let child = node.firstChild;
|
| + if (child) {
|
| + return child;
|
| + } else {
|
| + console.log('Node has no children');
|
| + console.log('\n');
|
| + return null;
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Return the parent of |node| if it has one.
|
| + *
|
| + * @param {AutomationNode} node
|
| + * @return {AutomationNode}
|
| + */
|
| + debugMoveToParent: function(node) {
|
| + if (!node)
|
| + return null;
|
| +
|
| + let parent = node.parent;
|
| + if (parent) {
|
| + return parent;
|
| + } else {
|
| + console.log('Node has no parent');
|
| + console.log('\n');
|
| + return null;
|
| + }
|
| + }
|
| +};
|
|
|