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