1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * @fileoverview ChromeVox predicates for the automation extension API.
9 goog.provide('AutomationPredicate');
10 goog.provide('AutomationPredicate.Binary');
11 goog.provide('AutomationPredicate.Unary');
13 goog.scope(function() {
14 var RoleType = chrome.automation.RoleType;
19 AutomationPredicate = function() {};
22 * @typedef {function(chrome.automation.AutomationNode) : boolean}
24 AutomationPredicate.Unary;
27 * @typedef {function(chrome.automation.AutomationNode,
28 * chrome.automation.AutomationNode) : boolean}
30 AutomationPredicate.Binary;
33 * Constructs a predicate given a role.
34 * @param {RoleType} role
35 * @return {AutomationPredicate.Unary}
37 AutomationPredicate.withRole = function(role) {
38 return function(node) {
39 return node.role == role;
43 /** @type {AutomationPredicate.Unary} */
44 AutomationPredicate.checkBox = AutomationPredicate.withRole(RoleType.checkBox);
45 /** @type {AutomationPredicate.Unary} */
46 AutomationPredicate.comboBox = AutomationPredicate.withRole(RoleType.comboBox);
47 /** @type {AutomationPredicate.Unary} */
48 AutomationPredicate.editText = AutomationPredicate.withRole(RoleType.textField);
49 /** @type {AutomationPredicate.Unary} */
50 AutomationPredicate.heading = AutomationPredicate.withRole(RoleType.heading);
51 /** @type {AutomationPredicate.Unary} */
52 AutomationPredicate.inlineTextBox =
53 AutomationPredicate.withRole(RoleType.inlineTextBox);
54 /** @type {AutomationPredicate.Unary} */
55 AutomationPredicate.link = AutomationPredicate.withRole(RoleType.link);
56 /** @type {AutomationPredicate.Unary} */
57 AutomationPredicate.table = AutomationPredicate.withRole(RoleType.table);
60 * @param {chrome.automation.AutomationNode} node
63 AutomationPredicate.button = function(node) {
64 return /button/i.test(node.role);
68 * @param {chrome.automation.AutomationNode} node
71 AutomationPredicate.formField = function(node) {
74 case 'buttonDropDown':
80 case 'disclosureTriangle':
101 * @param {chrome.automation.AutomationNode} node
104 AutomationPredicate.landmark = function(node) {
108 case 'complementary':
120 * @param {chrome.automation.AutomationNode} node
123 AutomationPredicate.visitedLink = function(node) {
124 return node.state.visited;
128 * @param {chrome.automation.AutomationNode} node
131 AutomationPredicate.focused = function(node) {
132 return node.state.focused;
136 * @param {chrome.automation.AutomationNode} node
139 AutomationPredicate.leaf = function(node) {
140 return !node.firstChild ||
141 node.role == RoleType.button ||
142 node.role == RoleType.buttonDropDown ||
143 node.role == RoleType.popUpButton ||
144 node.role == RoleType.slider ||
145 node.role == RoleType.textField ||
146 node.children.every(function(n) {
147 return n.state.invisible;
152 * @param {chrome.automation.AutomationNode} node
155 AutomationPredicate.leafWithText = function(node) {
156 return AutomationPredicate.leaf(node) &&
157 !!(node.name || node.value);
161 * Matches against non-inline textbox 'nodes' which have an equivalent in the
163 * @param {chrome.automation.AutomationNode} node
166 AutomationPredicate.leafDomNode = function(node) {
167 return AutomationPredicate.leaf(node) ||
168 node.role == RoleType.staticText;
172 * @param {chrome.automation.AutomationNode} first
173 * @param {chrome.automation.AutomationNode} second
176 AutomationPredicate.linebreak = function(first, second) {
177 // TODO(dtseng): Use next/previousOnLin once available.
178 var fl = first.location;
179 var sl = second.location;
180 return fl.top != sl.top ||
181 (fl.top + fl.height != sl.top + sl.height);
185 * Leaf nodes that should be ignored while traversing the automation tree. For
186 * example, apply this predicate when moving to the next element.
187 * @param {chrome.automation.AutomationNode} node
190 AutomationPredicate.shouldIgnoreLeaf = function(node) {
191 if (node.name || node.value)
194 return AutomationPredicate.leaf(node) &&
195 (node.role == RoleType.client ||
196 node.role == RoleType.div ||
197 node.role == RoleType.group ||
198 node.role == RoleType.image ||
199 node.role == RoleType.staticText);