Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js

Issue 2263513004: Add support for rich output inside of content editables. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@editable_nav
Patch Set: Test fixes. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 12 matching lines...) Expand all
166 * @private 180 * @private
167 */ 181 */
168 getLineBreaks_: function() { 182 getLineBreaks_: function() {
169 // node.lineBreaks is undefined when the multiline field has no line 183 // node.lineBreaks is undefined when the multiline field has no line
170 // breaks. 184 // breaks.
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 // First line in a multiline field.
191 var lineIndex = this.getLineIndex(this.start);
192 var isFirstLine = this.multiline && lineIndex == 0;
177 var output = new Output(); 193 var output = new Output();
178 var range; 194 var range;
179 if (this.multiline) { 195 if (this.node_.state.richlyEditable) {
180 var lineIndex = this.getLineIndex(this.start); 196 range = this.getSelectedAutomationLine_();
181 if (lineIndex == 0) { 197 } else if (this.multiline) {
182 isFirstLine = true; 198 if (isFirstLine)
183 output.formatForBraille('$name', this.node_); 199 output.formatForBraille('$name', this.node_);
184 }
185 range = new Range( 200 range = new Range(
186 new Cursor(this.node_, this.getLineStart(lineIndex)), 201 new Cursor(this.node_, this.getLineStart(lineIndex)),
187 new Cursor(this.node_, this.getLineEnd(lineIndex))); 202 new Cursor(this.node_, this.getLineEnd(lineIndex)));
188 } else { 203 } else {
189 range = Range.fromNode(this.node_); 204 range = Range.fromNode(this.node_);
190 } 205 }
191 output.withBraille(range, null, Output.EventType.NAVIGATE); 206 if (range)
207 output.withBraille(range, null, Output.EventType.NAVIGATE);
192 if (isFirstLine) 208 if (isFirstLine)
193 output.formatForBraille('@tag_textarea'); 209 output.formatForBraille('@tag_textarea');
194 output.go(); 210 output.go();
211 },
212
213 /**
214 * @return {Range}
215 * @private
216 */
217 getSelectedAutomationLine_: function() {
218 if (!this.node_.root.anchorObject || !this.node_.root.focusObject)
219 return null;
220
221 var start = Cursor.fromNode(this.node_.root.anchorObject);
222 start = start.move(Unit.LINE, Movement.BOUND, Dir.BACKWARD);
223 var end = Cursor.fromNode(this.node_.root.focusObject);
224 end = end.move(Unit.LINE, Movement.BOUND, Dir.FORWARD);
225 return new Range(start, end);
195 } 226 }
196 }; 227 };
197 228
198 /** 229 /**
199 * @param {!AutomationNode} node The root editable node, i.e. the root of a 230 * @param {!AutomationNode} node The root editable node, i.e. the root of a
200 * contenteditable subtree or a text field. 231 * contenteditable subtree or a text field.
201 * @return {editing.TextEditHandler} 232 * @return {editing.TextEditHandler}
202 */ 233 */
203 editing.TextEditHandler.createForNode = function(node) { 234 editing.TextEditHandler.createForNode = function(node) {
204 var rootFocusedEditable = null; 235 var rootFocusedEditable = null;
205 var testNode = node; 236 var testNode = node;
206 237
207 do { 238 do {
208 if (testNode.state.focused && testNode.state.editable) 239 if (testNode.state.focused && testNode.state.editable)
209 rootFocusedEditable = testNode; 240 rootFocusedEditable = testNode;
210 testNode = testNode.parent; 241 testNode = testNode.parent;
211 } while (testNode); 242 } while (testNode);
212 243
213 if (rootFocusedEditable) 244 if (rootFocusedEditable)
214 return new TextFieldTextEditHandler(rootFocusedEditable); 245 return new TextFieldTextEditHandler(rootFocusedEditable);
215 246
216 return null; 247 return null;
217 }; 248 };
218 249
219 }); 250 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698