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

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: Rebase. Created 4 years, 4 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 17 matching lines...) Expand all
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 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698