blob: d2a8ff1959b30af8515b30d74ea5dd6a2bd00fe9 [file] [log] [blame]
// Copyright 2014 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.
/**
* @fileoverview Some utilities for defining what groups are.
*/
goog.provide('cvox.GroupUtil');
goog.require('cvox.AriaUtil');
goog.require('cvox.DomUtil');
/**
* If a node contains more characters than this, it should not be treated
* as a leaf node by the smart navigation algorithm.
*
* This number was determined by looking at the average number of
* characters in a paragraph:
* http://www.fullondesign.co.uk/design/usability/
* 285-how-many-characters-per-a-page-is-normal.htm
* and then trying it out on a few popular websites (CNN, BBC,
* Google Search, etc.) and making sure it made sense.
* @type {number}
* @private
* @const
*/
cvox.GroupUtil.MAX_CHARCOUNT_ = 1500;
/**
* If a node contains any of these elements, it should not be treated
* as a leaf node by the smart navigation algorithm.
* @type {string}
* @private
* @const
*/
cvox.GroupUtil.BREAKOUT_SELECTOR_ = 'blockquote,' +
'button,' +
'code,' +
'form,' +
'frame,' +
'h1,' +
'h2,' +
'h3,' +
'h4,' +
'h5,' +
'h6,' +
'hr,' +
'iframe,' +
'input,' +
'object,' +
'ol,' +
'p,' +
'pre,' +
'select,' +
'table,' +
'tr,' +
'ul,' +
'math,' +
// This takes care of MathJax expressions.
'span.math,' +
// TODO (sorge) Do we want to group all math or only display math?
// '[mode="display"],' +
// Aria widget roles
'[role~="alert ' +
'alertdialog ' +
'button ' +
'checkbox ' +
'combobox ' +
'dialog ' +
'log ' +
'marquee ' +
'menubar ' +
'progressbar ' +
'radio ' +
'radiogroup ' +
'scrollbar ' +
'slider ' +
'spinbutton ' +
'status ' +
'tab ' +
'tabpanel ' +
'textbox ' +
'toolbar ' +
'tooltip ' +
'treeitem ' +
// Aria structure roles
'article ' +
'document ' +
'group ' +
'heading ' +
'img ' +
'list ' +
'math ' +
'region ' +
'row ' +
'separator"]';
/**
* Returns true if this is a leaf node for groups.
* true for a node => true for all child nodes
* true if node has no children
* @param {!Node} node The node to check.
* @return {boolean} true if this is at the "leaf node" level or lower
* for this granularity.
*/
cvox.GroupUtil.isLeafNode = function(node) {
// TODO (stoarca): Write test to make sure that this function satisfies
// the restriction given above.
if (node.tagName == 'LABEL') {
return cvox.DomUtil.isLeafNode(node);
}
if (cvox.DomUtil.isLeafNode(node)) {
return true;
}
if (!cvox.DomUtil.isSemanticElt(node)) {
var breakingNodes = node.querySelectorAll(
cvox.GroupUtil.BREAKOUT_SELECTOR_);
for (var i = 0; i < breakingNodes.length; ++i) {
if (cvox.DomUtil.hasContent(breakingNodes[i])) {
return false;
}
}
}
if (cvox.AriaUtil.isCompositeControl(node) &&
!cvox.DomUtil.isFocusable(node)) {
return false;
}
var content = cvox.DomUtil.collapseWhitespace(
cvox.DomUtil.getValue(node) + ' ' +
cvox.DomUtil.getName(node));
if (content.length > cvox.GroupUtil.MAX_CHARCOUNT_) {
return false;
}
if (content.replace(/\s/g, '') === '') {
// Text only contains whitespace
return false;
}
return true;
};