1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
// 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 DOM utility functions to aid in table navigation.
*/
goog.provide('cvox.TableUtil');
goog.require('cvox.XpathUtil');
/**
* Utility function to check if a particular table cell is a candidate
* header cell.
* @param {Node} cell The table cell.
* @return {boolean} Whether or not the table cell is acting as a header cell.
*/
cvox.TableUtil.checkIfHeader = function(cell) {
/*
* Headers are defined here as <TH> or <TD> elements. <TD> elements when
* serving as header cells must have either:
* - The scope attribute defined
* - Their IDs referenced in the header content attribute of another <TD> or
* <TH> element.
* This function does not check whether this cell is referenced by another
* <TD>. So this function by itself will not be able to gather all possible
* header cells when applied across all table cells.
*
* Please Note:
* The HTML5 spec specifies that only header <TH> elements can be headers
* ( http://dev.w3.org/html5/spec/tabular-data.html#row-header ) but the
* HTML4 spec says that <TD> elements can act as headers if they have a
* scope attribute defined
* ( http://www.w3.org/TR/html401/struct/tables.html#h-11.2.6 ). In the
* interest of providing meaningful header information for all tables, here
* we take the position that <TD> elements can act as headers.
*/
return ((cell.tagName == 'TH') ||
cell.hasAttribute('scope') || (cell.hasAttribute('role') &&
((cell.getAttribute('role') == 'rowheader') ||
(cell.getAttribute('role') == 'columnheader'))));
};
/**
* Utility function to determine colgroup structure. Builds an array that
* associates a column number to a particular col group.
* @param {Array} colGroups An array of all the colgroup elements in a
* particular table.
* @return {Array} An array that maps indexes representing table columns
* to indexes into the colGroups array.
*/
cvox.TableUtil.determineColGroups = function(colGroups) {
var colToColGroup = [];
if (colGroups.length == 0) {
return colToColGroup;
}
// A colgroup has either a series of col element children or a span
// attribute. If it has col children, ignore the span attribute
for (var colGroupCtr = 0; colGroupCtr < colGroups.length;
colGroupCtr++) {
var currentColGroup = colGroups[colGroupCtr];
var childCols = cvox.TableUtil.getColNodes(currentColGroup);
if (childCols.length > 0) {
for (var colNodeCtr = 0; colNodeCtr < childCols.length;
colNodeCtr++) {
var colElement = childCols[colNodeCtr];
if (colElement.hasAttribute('span')) {
var span = parseInt(colElement.getAttribute('span'), 10);
for (var s = 0; s < span; s++) {
colToColGroup.push(colGroupCtr);
}
} else {
colToColGroup.push(colGroupCtr);
}
}
} else {
// No children of the current colgroup. Does it have a span attribute?
if (currentColGroup.hasAttribute('span')) {
var span = parseInt(currentColGroup.getAttribute('span'), 10);
for (var s = 0; s < span; s++) {
colToColGroup.push(colGroupCtr);
}
} else {
// Default span value is 1
colToColGroup.push(colGroupCtr);
}
}
}
return colToColGroup;
};
/**
* Utility function to push an element into a given array only if that element
* is not already contained in the array.
* @param {Array} givenArray The given array.
* @param {Node} givenElement The given element.
*/
cvox.TableUtil.pushIfNotContained = function(givenArray, givenElement) {
if (givenArray.indexOf(givenElement) == -1) {
givenArray.push(givenElement);
}
};
/**
* Returns a JavaScript array of all the non-nested rows in the given table.
*
* @param {Node} table A table node.
* @return {Array} An array of all the child rows of the active table.
*/
cvox.TableUtil.getChildRows = function(table) {
return cvox.XpathUtil.evalXPath('child::tbody/tr | child::thead/tr | ' +
'child::*[attribute::role="row"]', table);
};
/**
* Returns a JavaScript array of all the child cell <TD> or <TH> or
* role='gridcell' nodes of the given row.
*
* @param {Node} rowNode The specified row node.
* @return {Array} An array of all the child cells of the given row node.
*/
cvox.TableUtil.getChildCells = function(rowNode) {
return cvox.XpathUtil.evalXPath('child::td | child::th | ' +
'child::*[attribute::role="gridcell"] |' +
'child::*[attribute::role="rowheader"] |' +
'child::*[attribute::role="columnheader"]', rowNode);
};
/**
* Returns a JavaScript array containing the cell in the active table
* with the given ID.
*
* @param {Node} table A table node.
* @param {string} cellID The specified ID.
* @return {Array} An array containing the cell with the specified ID.
*/
cvox.TableUtil.getCellWithID = function(table, cellID) {
return cvox.XpathUtil.evalXPath('id(\'' + cellID + '\')', table);
};
/**
* Returns a Javascript array containing the colgroup elements in the
* active table.
*
* @param {Node} table A table node.
* @return {Array} An array of all the colgroup elements in the active table.
*/
cvox.TableUtil.getColGroups = function(table) {
return cvox.XpathUtil.evalXPath('child::colgroup', table);
};
/**
* Returns a Javascript array containing the child col elements of the given
* colgroup element.
*
* @param {Node} colGroupNode The specified <COLGROUP> element.
* @return {Array} An array of all of the child col elements of the given
* colgroup element.
*/
cvox.TableUtil.getColNodes = function(colGroupNode) {
return cvox.XpathUtil.evalXPath('child::col', colGroupNode);
};
|