| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview Processes events related to editing text and emits the | 6 * @fileoverview Processes events related to editing text and emits the |
| 7 * appropriate spoken and braille feedback. | 7 * appropriate spoken and braille feedback. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 goog.provide('editing.TextEditHandler'); | 10 goog.provide('editing.TextEditHandler'); |
| 11 | 11 |
| 12 goog.require('AutomationTreeWalker'); | 12 goog.require('AutomationTreeWalker'); |
| 13 goog.require('AutomationUtil'); | 13 goog.require('AutomationUtil'); |
| 14 goog.require('Output'); | 14 goog.require('Output'); |
| 15 goog.require('Output.EventType'); | 15 goog.require('Output.EventType'); |
| 16 goog.require('cursors.Cursor'); | 16 goog.require('cursors.Cursor'); |
| 17 goog.require('cursors.Range'); | 17 goog.require('cursors.Range'); |
| 18 goog.require('cvox.ChromeVoxEditableTextBase'); | 18 goog.require('cvox.ChromeVoxEditableTextBase'); |
| 19 | 19 |
| 20 goog.scope(function() { | 20 goog.scope(function() { |
| 21 var AutomationEvent = chrome.automation.AutomationEvent; | 21 var AutomationEvent = chrome.automation.AutomationEvent; |
| 22 var AutomationNode = chrome.automation.AutomationNode; | 22 var AutomationNode = chrome.automation.AutomationNode; |
| 23 var Cursor = cursors.Cursor; | 23 var Cursor = cursors.Cursor; |
| 24 var Dir = AutomationUtil.Dir; | 24 var Dir = constants.Dir; |
| 25 var EventType = chrome.automation.EventType; | 25 var EventType = chrome.automation.EventType; |
| 26 var Range = cursors.Range; | 26 var Range = cursors.Range; |
| 27 var RoleType = chrome.automation.RoleType; | 27 var RoleType = chrome.automation.RoleType; |
| 28 var Movement = cursors.Movement; | 28 var Movement = cursors.Movement; |
| 29 var Unit = cursors.Unit; | 29 var Unit = cursors.Unit; |
| 30 | 30 |
| 31 /** | 31 /** |
| 32 * A handler for automation events in a focused text field or editable root | 32 * A handler for automation events in a focused text field or editable root |
| 33 * such as a |contenteditable| subtree. | 33 * such as a |contenteditable| subtree. |
| 34 * @constructor | 34 * @constructor |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 if (!this.multiline) | 134 if (!this.multiline) |
| 135 return 0; | 135 return 0; |
| 136 var breaks = this.node_.lineBreaks || []; | 136 var breaks = this.node_.lineBreaks || []; |
| 137 var index = 0; | 137 var index = 0; |
| 138 while (index < breaks.length && breaks[index] <= charIndex) | 138 while (index < breaks.length && breaks[index] <= charIndex) |
| 139 ++index; | 139 ++index; |
| 140 return index; | 140 return index; |
| 141 }, | 141 }, |
| 142 | 142 |
| 143 /** @override */ | 143 /** @override */ |
| 144 describeLine: function(lineIndex, triggeredByUser) { |
| 145 if (!this.node_.state.richlyEditable) { |
| 146 cvox.ChromeVoxEditableTextBase.prototype.describeLine.call( |
| 147 this, lineIndex, triggeredByUser); |
| 148 return; |
| 149 } |
| 150 var line = this.getSelectedAutomationLine_(); |
| 151 if (line) { |
| 152 new Output().withRichSpeech(line, null, Output.EventType.NAVIGATE) |
| 153 .go(); |
| 154 } |
| 155 }, |
| 156 |
| 157 /** @override */ |
| 144 getLineStart: function(lineIndex) { | 158 getLineStart: function(lineIndex) { |
| 145 if (!this.multiline || lineIndex == 0) | 159 if (!this.multiline || lineIndex == 0) |
| 146 return 0; | 160 return 0; |
| 147 var breaks = this.getLineBreaks_(); | 161 var breaks = this.getLineBreaks_(); |
| 148 return breaks[lineIndex - 1] || this.node_.value.length; | 162 return breaks[lineIndex - 1] || this.node_.value.length; |
| 149 }, | 163 }, |
| 150 | 164 |
| 151 /** @override */ | 165 /** @override */ |
| 152 getLineEnd: function(lineIndex) { | 166 getLineEnd: function(lineIndex) { |
| 153 var breaks = this.getLineBreaks_(); | 167 var breaks = this.getLineBreaks_(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 171 return this.node_.lineBreaks || []; | 185 return this.node_.lineBreaks || []; |
| 172 }, | 186 }, |
| 173 | 187 |
| 174 /** @private */ | 188 /** @private */ |
| 175 outputBraille_: function() { | 189 outputBraille_: function() { |
| 176 var isFirstLine = false; // First line in a multiline field. | 190 var isFirstLine = false; // First line in a multiline field. |
| 177 var output = new Output(); | 191 var output = new Output(); |
| 178 var range; | 192 var range; |
| 179 if (this.multiline) { | 193 if (this.multiline) { |
| 180 var lineIndex = this.getLineIndex(this.start); | 194 var lineIndex = this.getLineIndex(this.start); |
| 181 if (lineIndex == 0) { | 195 if (this.node_.state.richlyEditable) { |
| 182 isFirstLine = true; | 196 range = this.getSelectedAutomationLine_(); |
| 183 output.formatForBraille('$name', this.node_); | 197 } else { |
| 198 if (lineIndex == 0) { |
| 199 isFirstLine = true; |
| 200 output.formatForBraille('$name', this.node_); |
| 201 } |
| 202 range = new Range( |
| 203 new Cursor(this.node_, this.getLineStart(lineIndex)), |
| 204 new Cursor(this.node_, this.getLineEnd(lineIndex))); |
| 184 } | 205 } |
| 185 range = new Range( | 206 range = new Range( |
| 186 new Cursor(this.node_, this.getLineStart(lineIndex)), | 207 new Cursor(this.node_, this.getLineStart(lineIndex)), |
| 187 new Cursor(this.node_, this.getLineEnd(lineIndex))); | 208 new Cursor(this.node_, this.getLineEnd(lineIndex))); |
| 188 } else { | 209 } else { |
| 189 range = Range.fromNode(this.node_); | 210 range = Range.fromNode(this.node_); |
| 190 } | 211 } |
| 191 output.withBraille(range, null, Output.EventType.NAVIGATE); | 212 if (range) |
| 213 output.withBraille(range, null, Output.EventType.NAVIGATE); |
| 192 if (isFirstLine) | 214 if (isFirstLine) |
| 193 output.formatForBraille('@tag_textarea'); | 215 output.formatForBraille('@tag_textarea'); |
| 194 output.go(); | 216 output.go(); |
| 217 }, |
| 218 |
| 219 /** |
| 220 * @return {Range} |
| 221 * @private |
| 222 */ |
| 223 getSelectedAutomationLine_: function() { |
| 224 if (!this.node_.root.anchorObject || !this.node_.root.focusObject) |
| 225 return null; |
| 226 |
| 227 var start = Cursor.fromNode(this.node_.root.anchorObject); |
| 228 start = start.move(Unit.LINE, Movement.BOUND, Dir.BACKWARD); |
| 229 var end = Cursor.fromNode(this.node_.root.focusObject); |
| 230 end = end.move(Unit.LINE, Movement.BOUND, Dir.FORWARD); |
| 231 return new Range(start, end); |
| 195 } | 232 } |
| 196 }; | 233 }; |
| 197 | 234 |
| 198 /** | 235 /** |
| 199 * @param {!AutomationNode} node The root editable node, i.e. the root of a | 236 * @param {!AutomationNode} node The root editable node, i.e. the root of a |
| 200 * contenteditable subtree or a text field. | 237 * contenteditable subtree or a text field. |
| 201 * @return {editing.TextEditHandler} | 238 * @return {editing.TextEditHandler} |
| 202 */ | 239 */ |
| 203 editing.TextEditHandler.createForNode = function(node) { | 240 editing.TextEditHandler.createForNode = function(node) { |
| 204 var rootFocusedEditable = null; | 241 var rootFocusedEditable = null; |
| 205 var testNode = node; | 242 var testNode = node; |
| 206 | 243 |
| 207 do { | 244 do { |
| 208 if (testNode.state.focused && testNode.state.editable) | 245 if (testNode.state.focused && testNode.state.editable) |
| 209 rootFocusedEditable = testNode; | 246 rootFocusedEditable = testNode; |
| 210 testNode = testNode.parent; | 247 testNode = testNode.parent; |
| 211 } while (testNode); | 248 } while (testNode); |
| 212 | 249 |
| 213 if (rootFocusedEditable) | 250 if (rootFocusedEditable) |
| 214 return new TextFieldTextEditHandler(rootFocusedEditable); | 251 return new TextFieldTextEditHandler(rootFocusedEditable); |
| 215 | 252 |
| 216 return null; | 253 return null; |
| 217 }; | 254 }; |
| 218 | 255 |
| 219 }); | 256 }); |
| OLD | NEW |