1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5/** 6 * @fileoverview A class representing a DOM selection conveyed through 7 * CursorSelection idioms. 8 * A PageSelection is just a DOM selection. The class itself manages a single 9 * CursorSelection that surrounds a fragment on the page. It also provides an 10 * extend operation to either grow or shrink the selection given a 11 * CursorSelection. The class handles correctly moving the internal 12 * CursorSelection and providing immediate access to a full description of the 13 * selection at any time. 14 */ 15 16goog.provide('cvox.PageSelection'); 17 18goog.require('cvox.AbstractEarcons'); 19goog.require('cvox.CursorSelection'); 20goog.require('cvox.NavDescription'); 21 22/** 23 * @constructor 24 * @param {!cvox.CursorSelection} sel The initial selection. 25 */ 26cvox.PageSelection = function(sel) { 27 this.sel_ = sel.clone(); 28 this.sel_.select(); 29 this.wasBegin_ = true; 30}; 31 32 33/** 34 * Gets a description for the DOM selection during the course of navigation. 35 * @param {cvox.AbstractShifter} navShifter Used to obtain walker-based 36 * descriptions. 37 * @param {!cvox.CursorSelection} prevSel Previous CursorSelection in 38 * navigation. 39 * @param {!cvox.CursorSelection} curSel Current CursorSelection in navigation. 40 * @return {Array.<cvox.NavDescription>} The new description. 41 */ 42cvox.PageSelection.prototype.getDescription = 43 function(navShifter, prevSel, curSel) { 44 var desc = []; 45 if (this.sel_.isReversed() != curSel.isReversed()) { 46 // A shrinking selection. 47 desc = navShifter.getDescription(curSel, prevSel); 48 desc[0].annotation = cvox.ChromeVox.msgs.getMsg('describe_unselected'); 49 desc[0].pushEarcon(cvox.AbstractEarcons.SELECTION_REVERSE); 50 } else { 51 // A growing selection. 52 desc = navShifter.getDescription(prevSel, curSel); 53 desc[0].annotation = cvox.ChromeVox.msgs.getMsg('describe_selected'); 54 desc[0].pushEarcon(cvox.AbstractEarcons.SELECTION); 55 if (!this.wasBegin_ && this.sel_.absEquals(curSel.clone().normalize())) { 56 // A selection has inverted across the start cursor. Describe it. 57 var prevDesc = navShifter.getDescription(curSel, prevSel); 58 prevDesc[0].annotation = 59 cvox.ChromeVox.msgs.getMsg('describe_unselected'); 60 prevDesc[0].pushEarcon(cvox.AbstractEarcons.SELECTION_REVERSE); 61 prevDesc[0].pushEarcon(cvox.AbstractEarcons.WRAP); 62 desc = prevDesc.concat(desc); 63 } 64 } 65 return desc; 66}; 67 68 69/** 70 * Gets a full description for the entire DOM selection. 71 * Use this description when you want to describe the entire selection 72 * represented by this instance. 73 * 74 * @return {Array.<cvox.NavDescription>} The new description. 75 */ 76cvox.PageSelection.prototype.getFullDescription = function() { 77 return [new cvox.NavDescription( 78 {text: window.getSelection().toString(), 79 context: cvox.ChromeVox.msgs.getMsg('selection_is')})]; 80}; 81 82 83/** 84 * Extends this selection. 85 * @param {!cvox.CursorSelection} sel Extend DOM selection to the selection. 86 * @return {boolean} True if the extension occurred, false if the PageSelection 87 * was reset to sel. 88 */ 89cvox.PageSelection.prototype.extend = function(sel) { 90 if (!this.sel_.directedBefore(sel)) { 91 // Do not allow for crossed selections. This restarts a page selection that 92 // has been collapsed. This occurs when two CursorSelection's point away 93 // from one another. 94 this.sel_ = sel.clone(); 95 } else { 96 // Otherwise, it is assumed that the CursorSelection's are in directed 97 // document order. The CursorSelection's are either pointing in the same 98 // direction or towards one another. In the first case, shrink/extend this 99 // PageSelection to the end of "sel". In the second case, shrink/extend this 100 // PageSelection to the start of "sel". 101 this.sel_.end = this.sel_.isReversed() == sel.isReversed() ? 102 sel.end.clone() : sel.start.clone(); 103 } 104 this.sel_.select(); 105 this.wasBegin_ = false; 106 return !this.sel_.absEquals(sel); 107}; 108