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 Defines the ContentEditableExtractor class.
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.provide('cvox.ContentEditableExtractor');
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.Cursor');
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)goog.require('cvox.TraverseUtil');
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Extracts the text and line break information from a contenteditable region.
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @constructor
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ContentEditableExtractor = function() {
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * The extracted, flattened, text.
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {string}
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @private
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.text_ = '';
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * The start cursor/selection index.
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {number}
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @private
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.start_ = 0;
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * The end cursor/selection index.
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {number}
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @private
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.end_ = 0;
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * Map from line index to a data structure containing the start
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * and end index within the line.
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {Object.<number, {startIndex: number, endIndex: number}>}
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @private
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.lines_ = {};
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * Map from 0-based character index to 0-based line index.
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {Array.<number>}
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @private
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.characterToLineMap_ = [];
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Update the metadata.
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Element} element The DOM element that's contentEditable.
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ContentEditableExtractor.prototype.update = function(element) {
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /**
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * Map from line index to a data structure containing the start
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * and end index within the line.
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   * @type {Object.<number, {startIndex: number, endIndex: number}>}
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   */
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var lines = {0: {startIndex: 0, endIndex: 0}};
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var startCursor = new cvox.Cursor(element, 0, '');
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var endCursor = startCursor.clone();
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var range = document.createRange();
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var rect;
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var lineIndex = 0;
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var lastBottom = null;
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var text = '';
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var textSize = 0;
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var selectionStartIndex = -1;
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var selectionEndIndex = -1;
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var sel = window.getSelection();
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var selectionStart = new cvox.Cursor(sel.baseNode, sel.baseOffset, '');
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var selectionEnd = new cvox.Cursor(sel.extentNode, sel.extentOffset, '');
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var setStart = false;
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var setEnd = false;
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (true) {
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var entered = [];
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var left = [];
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var c = cvox.TraverseUtil.forwardsChar(endCursor, entered, left);
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var done = false;
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!c) {
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      done = true;
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (var i = 0; i < left.length && !done; i++) {
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (left[i] == element) {
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        done = true;
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (done) {
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    range.setStart(startCursor.node, startCursor.index);
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    range.setEnd(endCursor.node, endCursor.index);
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rect = range.getBoundingClientRect();
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!rect || rect.width == 0 || rect.height == 0) {
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (lastBottom !== null &&
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        rect.bottom != lastBottom &&
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        textSize > 0 &&
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        text.substr(-1).match(/\S/) &&
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        c.match(/\S/)) {
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      text += '\n';
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      textSize++;
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (startCursor.node != endCursor.node && endCursor.index > 0) {
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      range.setStart(endCursor.node, endCursor.index - 1);
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      rect = range.getBoundingClientRect();
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!rect || rect.width == 0 || rect.height == 0) {
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        continue;
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!setStart &&
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        selectionStartIndex == -1 &&
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        endCursor.node == selectionStart.node &&
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        endCursor.index >= selectionStart.index) {
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (endCursor.index > selectionStart.index) {
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        selectionStartIndex = textSize;
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      } else {
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        setStart = true;
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!setEnd &&
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        selectionEndIndex == -1 &&
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        endCursor.node == selectionEnd.node &&
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        endCursor.index >= selectionEnd.index) {
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (endCursor.index > selectionEnd.index) {
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        selectionEndIndex = textSize;
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      } else {
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        setEnd = true;
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (lastBottom === null) {
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // This is the first character we've successfully measured on this
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // line. Save the vertical position but don't do anything else.
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      lastBottom = rect.bottom;
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else if (rect.bottom != lastBottom) {
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      lines[lineIndex].endIndex = textSize;
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      lineIndex++;
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      lines[lineIndex] = {startIndex: textSize, endIndex: textSize};
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      lastBottom = rect.bottom;
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    text += c;
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    textSize++;
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    startCursor = endCursor.clone();
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (setStart) {
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      selectionStartIndex = textSize;
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      setStart = false;
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (setEnd) {
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      selectionEndIndex = textSize;
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      setEnd = false;
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Finish up the last line.
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  lines[lineIndex].endIndex = textSize;
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create a map from character index to line number.
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  var characterToLineMap = [];
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (var i = 0; i <= lineIndex; i++) {
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (var j = lines[i].startIndex; j <= lines[i].endIndex; j++) {
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      characterToLineMap[j] = i;
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Finish updating fields.
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.text_ = text;
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.characterToLineMap_ = characterToLineMap;
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.lines_ = lines;
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.start_ = selectionStartIndex >= 0 ? selectionStartIndex : text.length;
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  this.end_ = selectionEndIndex >= 0 ? selectionEndIndex : text.length;
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Get the text.
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {string} The extracted, flattened, text.
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ContentEditableExtractor.prototype.getText = function() {
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.text_;
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {number} The start cursor/selection index.
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ContentEditableExtractor.prototype.getStartIndex = function() {
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.start_;
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {number} The end cursor/selection index.
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ContentEditableExtractor.prototype.getEndIndex = function() {
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.end_;
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Get the line number corresponding to a particular index.
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {number} index The 0-based character index.
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {number} The 0-based line number corresponding to that character.
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ContentEditableExtractor.prototype.getLineIndex = function(index) {
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.characterToLineMap_[index];
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Get the start character index of a line.
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {number} index The 0-based line index.
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {number} The 0-based index of the first character in this line.
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ContentEditableExtractor.prototype.getLineStart = function(index) {
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.lines_[index].startIndex;
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/**
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Get the end character index of a line.
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {number} index The 0-based line index.
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @return {number} The 0-based index of the end of this line.
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)cvox.ContentEditableExtractor.prototype.getLineEnd = function(index) {
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return this.lines_[index].endIndex;
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
236