1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @fileoverview A class for walking tables.
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * NOTE: This class has a very different interface than the other walkers.
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * This means it does not lend itself easily to e.g. decorators.
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * TODO (stoarca): This might be able to be fixed by breaking it up into
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * separate walkers for cell, row and column.
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.provide('cvox.TableWalker');
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.AbstractWalker');
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.BrailleUtil');
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.DescriptionUtil');
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.DomUtil');
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.NavDescription');
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.TraverseTable');
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @constructor
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @extends {cvox.AbstractWalker}
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker = function() {
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.AbstractWalker.call(this);
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * Only used as a cache for faster lookup.
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {!cvox.TraverseTable}
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.tt = new cvox.TraverseTable(null);
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.inherits(cvox.TableWalker, cvox.AbstractWalker);
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @override
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.next = function(sel) {
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO (stoarca): See bug 6677953
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.nextRow(sel);
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @override
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.sync = function(sel) {
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.goTo_(sel, goog.bind(function(position) {
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return this.tt.goToCell(position);
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @override
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @suppress {checkTypes} actual parameter 2 of
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * cvox.AbstractMsgs.prototype.getMsg does not match formal parameter
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * found   : Array.<number>
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * required: (Array.<string>|null|undefined)
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.getDescription = function(prevSel, sel) {
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var position = this.syncPosition_(sel);
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!position) {
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return [];
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.tt.goToCell(position);
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var descs = cvox.DescriptionUtil.getCollectionDescription(prevSel, sel);
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (descs.length == 0) {
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    descs.push(new cvox.NavDescription({
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      annotation: cvox.ChromeVox.msgs.getMsg('empty_cell')
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }));
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return descs;
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @override
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.getBraille = function(prevSel, sel) {
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var ret = new cvox.NavBraille({});
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var position = this.syncPosition_(sel);
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (position) {
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var text =
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        cvox.BrailleUtil.getTemplated(prevSel.start.node, sel.start.node);
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    text.append(' ' + ++position[0] + '/' + ++position[1]);
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return new cvox.NavBraille({text: text});
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @override
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.getGranularityMsg = goog.abstractMethod;
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** Table Actions. */
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the first cell of the table that this selection is inside.
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The selection for first cell of the table.
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.goToFirstCell = function(sel) {
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.goTo_(sel, goog.bind(function(position) {
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return this.tt.goToCell([0, 0]);
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the last cell of the table that this selection is inside.
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The selection for the last cell of the table.
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.goToLastCell = function(sel) {
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.goTo_(sel, goog.bind(function(position) {
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return this.tt.goToLastCell();
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the first cell of the row that the selection is in.
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The selection for the first cell in the row.
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.goToRowFirstCell = function(sel) {
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.goTo_(sel, goog.bind(function(position) {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return this.tt.goToCell([position[0], 0]);
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the last cell of the row that the selection is in.
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The selection for the last cell in the row.
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.goToRowLastCell = function(sel) {
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.goTo_(sel, goog.bind(function(position) {
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return this.tt.goToRowLastCell();
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the first cell of the column that the selection is in.
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The selection for the first cell in the col.
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.goToColFirstCell = function(sel) {
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.goTo_(sel, goog.bind(function(position) {
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return this.tt.goToCell([0, position[1]]);
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the last cell of the column that the selection is in.
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The selection for the last cell in the col.
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.goToColLastCell = function(sel) {
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.goTo_(sel, goog.bind(function(position) {
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return this.tt.goToColLastCell();
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the first cell in the row after the current selection.
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The selection for the first cell in the next
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * row.
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.nextRow = function(sel) {
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.goTo_(sel, goog.bind(function(position) {
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return this.tt.goToCell([position[0] + (sel.isReversed() ? -1 : 1),
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              position[1]]);
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the first cell in the column after the current selection.
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The selection for the first cell in the
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * next col.
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.nextCol = function(sel) {
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.goTo_(sel, goog.bind(function(position) {
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return this.tt.goToCell([position[0],
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              position[1] + (sel.isReversed() ? -1 : 1)]);
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }, this));
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The current selection.
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The resulting selection.
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.announceHeaders = function(sel) {
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.ChromeVox.tts.speak(this.getHeaderText_(sel),
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           cvox.AbstractTts.QUEUE_MODE_FLUSH,
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           cvox.AbstractTts.PERSONALITY_ANNOTATION);
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return sel;
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The current selection.
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The resulting selection.
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.speakTableLocation = function(sel) {
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cvox.ChromeVox.navigationManager.speakDescriptionArray(
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      this.getLocationDescription_(sel),
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      cvox.AbstractTts.QUEUE_MODE_FLUSH,
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      null);
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return sel;
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The current selection.
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The resulting selection.
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @expose
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.exitShifterContent = function(sel) {
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var tableNode = this.getTableNode_(sel);
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!tableNode) {
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return null;
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var nextNode = cvox.DomUtil.directedNextLeafNode(tableNode, false);
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return cvox.CursorSelection.fromNode(nextNode);
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/** End of actions. */
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the text content of the header(s) of the cell that contains sel.
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!string} The header text.
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.getHeaderText_ = function(sel) {
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.tt.initialize(this.getTableNode_(sel));
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var position = this.tt.findNearestCursor(sel.start.node);
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!position) {
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return cvox.ChromeVox.msgs.getMsg('not_inside_table');
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!this.tt.goToCell(position)) {
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return cvox.ChromeVox.msgs.getMsg('not_inside_table');
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return (
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      this.getRowHeaderText_(position) +
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ' ' +
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      this.getColHeaderText_(position));
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the location description.
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel A valid selection.
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {Array.<cvox.NavDescription>} The location description.
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @suppress {checkTypes} actual parameter 2 of
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * cvox.AbstractMsgs.prototype.getMsg does not match
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * formal parameter
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * found   : Array.<number>
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * required: (Array.<string>|null|undefined)
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.getLocationDescription_ = function(sel) {
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var locationInfo = this.getLocationInfo(sel);
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (locationInfo == null) {
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return null;
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return [new cvox.NavDescription({
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    text: cvox.ChromeVox.msgs.getMsg('table_location', locationInfo)
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  })];
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the text content of the row header(s) of the cell that contains sel.
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!Array.<number>} position The selection.
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!string} The header text.
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.getRowHeaderText_ = function(position) {
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(stoarca): OPTMZ Replace with join();
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var rowHeaderText = '';
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var rowHeaders = this.tt.getCellRowHeaders();
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rowHeaders.length == 0) {
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var firstCellInRow = this.tt.getCellAt([position[0], 0]);
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rowHeaderText += cvox.DomUtil.collapseWhitespace(
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        cvox.DomUtil.getValue(firstCellInRow) + ' ' +
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            cvox.DomUtil.getName(firstCellInRow));
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return cvox.ChromeVox.msgs.getMsg('row_header') + rowHeaderText;
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var i = 0; i < rowHeaders.length; ++i) {
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rowHeaderText += cvox.DomUtil.collapseWhitespace(
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        cvox.DomUtil.getValue(rowHeaders[i]) + ' ' +
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            cvox.DomUtil.getName(rowHeaders[i]));
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rowHeaderText == '') {
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return cvox.ChromeVox.msgs.getMsg('empty_row_header');
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return cvox.ChromeVox.msgs.getMsg('row_header') + rowHeaderText;
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the text content of the col header(s) of the cell that contains sel.
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!Array.<number>} position The selection.
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {!string} The header text.
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.getColHeaderText_ = function(position) {
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(stoarca): OPTMZ Replace with join();
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var colHeaderText = '';
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var colHeaders = this.tt.getCellColHeaders();
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (colHeaders.length == 0) {
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var firstCellInCol = this.tt.getCellAt([0, position[1]]);
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    colHeaderText += cvox.DomUtil.collapseWhitespace(
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        cvox.DomUtil.getValue(firstCellInCol) + ' ' +
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        cvox.DomUtil.getName(firstCellInCol));
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return cvox.ChromeVox.msgs.getMsg('column_header') + colHeaderText;
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var i = 0; i < colHeaders.length; ++i) {
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    colHeaderText += cvox.DomUtil.collapseWhitespace(
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        cvox.DomUtil.getValue(colHeaders[i]) + ' ' +
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            cvox.DomUtil.getName(colHeaders[i]));
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (colHeaderText == '') {
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return cvox.ChromeVox.msgs.getMsg('empty_row_header');
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return cvox.ChromeVox.msgs.getMsg('column_header') + colHeaderText;
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the location info of sel within the containing table.
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {Array.<number>} The location info:
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *  [row index, row count, col index, col count].
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.getLocationInfo = function(sel) {
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.tt.initialize(this.getTableNode_(sel));
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var position = this.tt.findNearestCursor(sel.start.node);
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!position) {
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return null;
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // + 1 to account for 0-indexed
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return [
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    position[0] + 1,
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.tt.rowCount,
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    position[1] + 1,
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    this.tt.colCount
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ].map(function(x) {return cvox.ChromeVox.msgs.getNumber(x);});
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns true if sel is inside a table.
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {boolean} True if inside a table node.
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.isInTable = function(sel) {
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.getTableNode_(sel) != null;
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Wrapper for going to somewhere so that boilerplate is not repeated.
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection from which to base the
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * movement.
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {function(Array.<number>):boolean} f The function to use for moving.
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns true on success and false on failure.
382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {cvox.CursorSelection} The resulting selection.
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.goTo_ = function(sel, f) {
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.tt.initialize(this.getTableNode_(sel));
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var position = this.tt.findNearestCursor(sel.end.node);
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!position) {
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return null;
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.tt.goToCell(position);
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!f(position)) {
393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return null;
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return cvox.CursorSelection.fromNode(this.tt.getCell()).
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      setReversed(sel.isReversed());
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Returns the nearest table node containing the end of the selection
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {Node} The table node containing sel. null if not in a table.
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.getTableNode_ = function(sel) {
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return cvox.DomUtil.getContainingTable(sel.end.node);
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Sync the backing traversal utility to the given selection.
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {!cvox.CursorSelection} sel The selection.
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {Array.<number>} The position [x, y] of the selection.
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.TableWalker.prototype.syncPosition_ = function(sel) {
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var tableNode = this.getTableNode_(sel);
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.tt.initialize(tableNode);
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we need to align the TraverseTable with our sel because our walker
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // uses parts of it (for example isSpanned relies on being at a specific cell)
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.tt.findNearestCursor(sel.end.node);
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
422