Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / chromevox / common / group_util.js
blobd2a8ff1959b30af8515b30d74ea5dd6a2bd00fe9
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.
5 /**
6  * @fileoverview Some utilities for defining what groups are.
7  */
10 goog.provide('cvox.GroupUtil');
12 goog.require('cvox.AriaUtil');
13 goog.require('cvox.DomUtil');
16 /**
17  * If a node contains more characters than this, it should not be treated
18  * as a leaf node by the smart navigation algorithm.
19  *
20  * This number was determined by looking at the average number of
21  * characters in a paragraph:
22  * http://www.fullondesign.co.uk/design/usability/
23  * 285-how-many-characters-per-a-page-is-normal.htm
24  * and then trying it out on a few popular websites (CNN, BBC,
25  * Google Search, etc.) and making sure it made sense.
26  * @type {number}
27  * @private
28  * @const
29  */
30 cvox.GroupUtil.MAX_CHARCOUNT_ = 1500;
33 /**
34  * If a node contains any of these elements, it should not be treated
35  * as a leaf node by the smart navigation algorithm.
36  * @type {string}
37  * @private
38  * @const
39  */
40 cvox.GroupUtil.BREAKOUT_SELECTOR_ = 'blockquote,' +
41     'button,' +
42     'code,' +
43     'form,' +
44     'frame,' +
45     'h1,' +
46     'h2,' +
47     'h3,' +
48     'h4,' +
49     'h5,' +
50     'h6,' +
51     'hr,' +
52     'iframe,' +
53     'input,' +
54     'object,' +
55     'ol,' +
56     'p,' +
57     'pre,' +
58     'select,' +
59     'table,' +
60     'tr,' +
61     'ul,' +
62     'math,' +
63   // This takes care of MathJax expressions.
64     'span.math,' +
65 // TODO (sorge) Do we want to group all math or only display math?
66 //    '[mode="display"],' +
67     // Aria widget roles
68     '[role~="alert ' +
69     'alertdialog ' +
70     'button ' +
71     'checkbox ' +
72     'combobox ' +
73     'dialog ' +
74     'log ' +
75     'marquee ' +
76     'menubar ' +
77     'progressbar ' +
78     'radio ' +
79     'radiogroup ' +
80     'scrollbar ' +
81     'slider ' +
82     'spinbutton ' +
83     'status ' +
84     'tab ' +
85     'tabpanel ' +
86     'textbox ' +
87     'toolbar ' +
88     'tooltip ' +
89     'treeitem ' +
90     // Aria structure roles
91     'article ' +
92     'document ' +
93     'group ' +
94     'heading ' +
95     'img ' +
96     'list ' +
97     'math ' +
98     'region ' +
99     'row ' +
100     'separator"]';
104  * Returns true if this is a leaf node for groups.
105  * true for a node => true for all child nodes
106  * true if node has no children
107  * @param {!Node} node The node to check.
108  * @return {boolean} true if this is at the "leaf node" level or lower
109  * for this granularity.
110  */
111 cvox.GroupUtil.isLeafNode = function(node) {
112   // TODO (stoarca): Write test to make sure that this function satisfies
113   // the restriction given above.
114   if (node.tagName == 'LABEL') {
115     return cvox.DomUtil.isLeafNode(node);
116   }
117   if (cvox.DomUtil.isLeafNode(node)) {
118     return true;
119   }
121   if (!cvox.DomUtil.isSemanticElt(node)) {
122     var breakingNodes = node.querySelectorAll(
123         cvox.GroupUtil.BREAKOUT_SELECTOR_);
125     for (var i = 0; i < breakingNodes.length; ++i) {
126       if (cvox.DomUtil.hasContent(breakingNodes[i])) {
127         return false;
128       }
129     }
130   }
132   if (cvox.AriaUtil.isCompositeControl(node) &&
133       !cvox.DomUtil.isFocusable(node)) {
134     return false;
135   }
137   var content = cvox.DomUtil.collapseWhitespace(
138       cvox.DomUtil.getValue(node) + ' ' +
139       cvox.DomUtil.getName(node));
140   if (content.length > cvox.GroupUtil.MAX_CHARCOUNT_) {
141     return false;
142   }
144   if (content.replace(/\s/g, '') === '') {
145     // Text only contains whitespace
146     return false;
147   }
149   return true;