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

Side by Side Diff: chrome/browser/resources/access_chromevox/scripts/axsjax/axsjax.js

Issue 6254007: Adding ChromeVox as a component extensions (enabled only for ChromeOS, for no... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 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 | Annotate | Revision Log
Property Changes:
Added: svn:executable
+ *
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 goog.provide('cvox.AxsJAX');
6
7 goog.require('cvox.ChromeVox');
8 goog.require('cvox.DomUtil');
9 goog.require('cvox.XpathUtil');
10
11 /**
12 * @fileoverview AxsJAX - JavaScript library for enhancing the accessibility
13 * of AJAX apps through WAI-ARIA.
14 * Note that this is a ChromeVox specific version of AxsJAX that has been
15 * optimized and refactored for ChromeVox.
16 */
17
18 /**
19 * Class of scripts for improving accessibility of Web 2.0 Apps.
20 * @param {boolean} useTabKeyFix Whether or not to try syncing to the last
21 * marked position when the user presses the
22 * tab key.
23 * @constructor
24 */
25 cvox.AxsJAX = function(useTabKeyFix) {
26 this.ID_NUM_ = 0;
27 this.tabbingStartPosNode_ = null;
28 this.tabKeyFixOn_ = false;
29 this.lastFocusedNode = null;
30 this.inputFocused = false;
31
32 var self = this;
33
34 //Monitor focus and blur
35 this.addFocusBlurMonitors();
36
37 //Activate the tab key fix if needed
38 if (useTabKeyFix) {
39 this.tabKeyFixOn_ = true;
40 document.addEventListener('keypress',
41 function(event) {
42 self.tabKeyHandler(event, self);
43 },
44 true);
45 // Record in a custom DOM property:
46 document.body.AXSJAX_TABKEYFIX_ADDED = true;
47 }
48 };
49
50
51 /**
52 * Adds focus/blur handlers to the current active document.
53 * This should be invoked when AxsJAX is first initialized and
54 * when a new active document has been set.
55 */
56 cvox.AxsJAX.prototype.addFocusBlurMonitors = function() {
57 var activeDoc = this.getActiveDocument();
58 var self = this;
59 //These return "true" so that any page actions based on
60 //focus and blur will still occur.
61 var focusHandler = function(evt) {
62 self.lastFocusedNode = evt.target;
63 if ((evt.target.tagName == 'INPUT') ||
64 (evt.target.tagName == 'SELECT') ||
65 (evt.target.tagName == 'TEXTAREA')) {
66 self.inputFocused = true;
67 }
68 return true;
69 };
70 activeDoc.addEventListener('focus', focusHandler, true);
71
72 var blurHandler = function(evt) {
73 self.lastFocusedNode = null;
74 if ((evt.target.tagName == 'INPUT') ||
75 (evt.target.tagName == 'SELECT') ||
76 (evt.target.tagName == 'TEXTAREA')) {
77 self.inputFocused = false;
78 }
79 return true;
80 };
81 activeDoc.addEventListener('blur', blurHandler, true);
82 };
83
84
85 /**
86 * This function is not needed in Chrome Vox and is a no-op. It is available
87 * only as a compatibility shim for existing AxsJAX scripts.
88 *
89 * @param {Node} targetNode Dummy node - this is not used.
90 */
91 cvox.AxsJAX.prototype.setActiveParent = function(targetNode) {
92 };
93
94
95 /**
96 * This function is not needed in Chrome Vox and is the same as just calling
97 * "document".
98 * Gets the document for the active parent.
99 * @return {Node} The document that is the ancestor for the active parent.
100 */
101 cvox.AxsJAX.prototype.getActiveDocument = function() {
102 return document;
103 };
104
105
106 /**
107 * Speaks a given node using ChromeVox.
108 * @param {Node} targetNode The HTML node to be spoken.
109 */
110 cvox.AxsJAX.prototype.speakNode = function(targetNode) {
111 ChromeVox.tts.speak(DomUtil.getText(targetNode), 0, null);
112 };
113
114
115 /**
116 * Speaks the given textString using ChromeVox.
117 * @param {String} textString The text to be spoken.
118 */
119 cvox.AxsJAX.prototype.speakText = function(textString) {
120 ChromeVox.tts.speak(textString, 0, null);
121 };
122
123 /**
124 * Speaks the given textString using ChromeVox.
125 * This function is the same as speakText as is available only as a
126 * compatibility shim for existing AxsJAX scripts.
127 *
128 * @param {String} textString The text to be spoken.
129 *
130 */
131 cvox.AxsJAX.prototype.speakTextViaNode = function(textString) {
132 ChromeVox.tts.speak(textString, 0, null);
133 };
134
135 /**
136 * Puts alt='' for all images that are children of the target node that
137 * have no alt text defined. This is a bandage fix to prevent screen readers
138 * from rambling on by reading the URL string of the image.
139 * A real fix for this problem should be to either use appropriate alt text for
140 * the images or explicitly put alt='' for images that have no semantic value.
141 * @param {Node} targetNode The target node of this operation.
142 */
143 cvox.AxsJAX.prototype.putNullForNoAltImages = function(targetNode) {
144 var images = targetNode.getElementsByTagName('img');
145 for (var i = 0, image; image = images[i]; i++) {
146 if (!image.alt) {
147 image.alt = '';
148 }
149 }
150 };
151
152
153 /**
154 * Dispatches a left click event on the element that is the targetNode.
155 * Clicks go in the sequence of mousedown, mouseup, and click.
156 * This functionality already exists in DomUtil, so this method simply
157 * redirects to that.
158 *
159 * @param {Node} targetNode The target node of this operation.
160 * @param {boolean} shiftKey Specifies if shift is held down.
161 */
162 cvox.AxsJAX.prototype.clickElem = function(targetNode, shiftKey) {
163 DomUtil.clickElem(targetNode, shiftKey);
164 };
165
166 /**
167 * Dispatches a key event on the element that is the targetNode.
168 * @param {Node} targetNode The target node of this operation.
169 * @param {String} theKey The key to use for this operation.
170 * This can be any single printable character or ENTER.
171 * @param {Boolean} holdCtrl Whether or not the Ctrl key should be held for
172 * this operation.
173 * @param {Boolean} holdAlt Whether or not the Alt key should be held for
174 * this operation.
175 * @param {Boolean} holdShift Whether or not the Shift key should be held
176 * for this operation.
177 */
178 cvox.AxsJAX.prototype.sendKey = function(targetNode, theKey,
179 holdCtrl, holdAlt, holdShift) {
180 var keyCode = 0;
181 var charCode = 0;
182 if (theKey == 'ENTER') {
183 keyCode = 13;
184 }
185 else if (theKey.length == 1) {
186 charCode = theKey.charCodeAt(0);
187 }
188 var activeDoc = this.getActiveDocument();
189 var evt = activeDoc.createEvent('KeyboardEvent');
190 evt.initKeyEvent('keypress', true, true, null, holdCtrl,
191 holdAlt, holdShift, false, keyCode, charCode);
192 targetNode.dispatchEvent(evt);
193 };
194
195 /**
196 * Assigns an ID to the targetNode.
197 * If targetNode already has an ID, this is a no-op.
198 * Always returns the ID of targetNode.
199 * If targetNode is null, we return ''
200 * @param {Node} targetNode The target node of this operation.
201 * @param {String} opt_prefixString
202 * Prefix to help ensure the uniqueness of the ID.
203 * This is optional; if null, it will use "AxsJAX_ID_".
204 * @return {string} The ID that the targetNode now has.
205 */
206 cvox.AxsJAX.prototype.assignId = function(targetNode, opt_prefixString) {
207 if (!targetNode) {
208 return '';
209 }
210 if (targetNode.id) {
211 return targetNode.id;
212 }
213 var prefix = opt_prefixString || 'AxsJAX_ID_';
214 targetNode.id = prefix + this.ID_NUM_++;
215 return targetNode.id;
216 };
217
218 /**
219 * Marks the current position by remembering what the last focusable node was.
220 * The focusable node will be the targetNode if it has a focus() function, or
221 * if it does not, the first descendent node that it has which does.
222 * If the targetNode itself and all of its descendents have no focus() function,
223 * this function will complete with failure.
224 * If the cvox.AxsJAX.tabKeyHandler is used, then it will put the focus on this
225 * node.
226 * @param {Node} targetNode The target node of this operation.
227 * @return {Boolean} True if the position was marked successfully.
228 * False if failed.
229 */
230 cvox.AxsJAX.prototype.markPosition = function(targetNode) {
231 if (!targetNode) {
232 return false;
233 }
234 ChromeVox.navigationManager.syncToNode(targetNode);
235 if ((targetNode.tagName == 'A') || (targetNode.tagName == 'INPUT')) {
236 this.tabbingStartPosNode_ = targetNode;
237 return true;
238 }
239 var allDescendants = targetNode.getElementsByTagName('*');
240 for (var i = 0, currentNode; currentNode = allDescendants[i]; i++) {
241 if ((currentNode.tagName == 'A') ||
242 (currentNode.tagName == 'INPUT') ||
243 (currentNode.hasAttribute('tabindex') &&
244 (currentNode.tabIndex != -1))) {
245 this.tabbingStartPosNode_ = currentNode;
246 return true;
247 }
248 }
249 return false;
250 };
251
252 /**
253 * Restores the focus .
254 * Usage:
255 * var myAxsJAXObj = new AxsJAX();
256 * document.addEventListener('keypress',
257 * function(event){
258 * myAxsJAXObj.tabKeyHandler(event,myAxsJAXObj);
259 * },
260 * true);
261 * @param {Event} evt The event.
262 * @param {Object} selfRef The AxsJAX object. A self reference is needed here
263 * since this in an event handler does NOT refer to the
264 * AxsJAX object.
265 * @return {Boolean} Always returns true to pass the tab key along.
266 */
267 cvox.AxsJAX.prototype.tabKeyHandler = function(evt, selfRef) {
268 if (!selfRef.tabKeyFixOn_) {
269 return true;
270 }
271 if ((evt.keyCode == 9) && (selfRef.tabbingStartPosNode_)) {
272 selfRef.tabbingStartPosNode_.focus();
273 selfRef.tabbingStartPosNode_ = null;
274 }
275 return true;
276 };
277
278 /**
279 * Scrolls to the targetNode and speaks it.
280 * This will automatically mark the position; this should be used if you are
281 * navigating through content.
282 * @param {Node} targetNode The HTML node to be spoken.
283 */
284 cvox.AxsJAX.prototype.goTo = function(targetNode) {
285 this.speakNode(targetNode);
286 targetNode.scrollIntoView(true);
287 this.markPosition(targetNode);
288 };
289
290
291 /**
292 * Sets the attribute of the targetNode to the value.
293 * Use this rather than a direct set attribute to abstract away ARIA
294 * naming changes.
295 * @param {Node} targetNode The HTML node to have the attribute set on.
296 * @param {string} attribute The attribute to set.
297 * @param {string?} value The value the attribute should be set to.
298 */
299 cvox.AxsJAX.prototype.setAttributeOf = function(targetNode, attribute, value) {
300 if (!targetNode) {
301 return;
302 }
303 //Add the aria- to attributes
304 attribute = attribute.toLowerCase();
305 switch (attribute) {
306 case 'live':
307 attribute = 'aria-live';
308 break;
309 case 'activedescendant':
310 attribute = 'aria-activedescendant';
311 break;
312 case 'atomic':
313 attribute = 'aria-atomic';
314 break;
315 default:
316 break;
317 }
318 targetNode.setAttribute(attribute, value);
319 };
320
321 /**
322 * Gets the attribute of the targetNode.
323 * Use this rather than a direct get attribute to abstract away ARIA
324 * naming changes.
325 * @param {Node} targetNode The HTML node to get the attribute of.
326 * @param {string} attribute The attribute to get the value of.
327 * @return {string} The value of the attribute of the targetNode.
328 */
329 cvox.AxsJAX.prototype.getAttributeOf = function(targetNode, attribute) {
330 return targetNode.getAttribute(attribute);
331 };
332
333 /**
334 * Removes the attribute of the targetNode.
335 * Use this rather than a direct remove attribute to abstract away ARIA
336 * naming changes.
337 * @param {Node} targetNode The HTML node to remove the attribute from.
338 * @param {string} attribute The attribute to be removed.
339 */
340 cvox.AxsJAX.prototype.removeAttributeOf = function(targetNode, attribute) {
341 if (targetNode && targetNode.removeAttribute) {
342 targetNode.removeAttribute(attribute);
343 }
344 };
345
346 /**
347 * This is a no-op for ChromeVox since ChromeVox is the AT and does not need to
348 * be synced. This function is available only as a compatibility shim.
349 *
350 * @param {Node} targetNode The HTML node to force the AT to sync to.
351 */
352 cvox.AxsJAX.prototype.forceATSync = function(targetNode) {
353
354 };
355
356 /**
357 * Given an XPath expression and rootNode, it returns an array of children nodes
358 * that match.
359 * This functionality already exists in XpathUtil, so this method simply
360 * redirects to that.
361 * @param {string} expression The XPath expression to evaluate.
362 * @param {Node} rootNode The HTML node to start evaluating the XPath from.
363 * @return {Array} The array of children nodes that match.
364 */
365 cvox.AxsJAX.prototype.evalXPath = function(expression, rootNode) {
366 return cvox.XpathUtil.evalXPath(expression, rootNode);
367 };
368
369 /**
370 * This function initializes an AxsJAX script by calling a given initialization
371 * routine after the page load event has been generated. Using
372 * this method instead of attaching the event listener directly is recommended
373 * to enable testability of the application.
374 *
375 * @param {Function!} initFunction The initialization function to invoke.
376 */
377 cvox.AxsJAX.initializeOnLoad = function(initFunction) {
378 window.addEventListener('load', function() {
379 initFunction();
380 }, true);
381 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698