Index: chrome/browser/resources/access_chromevox/chromevox/injected/user_commands.js |
=================================================================== |
--- chrome/browser/resources/access_chromevox/chromevox/injected/user_commands.js (revision 0) |
+++ chrome/browser/resources/access_chromevox/chromevox/injected/user_commands.js (revision 0) |
@@ -0,0 +1,1343 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+goog.provide('cvox.ChromeVoxUserCommands'); |
+ |
+goog.require('cvox.AbstractEarcons'); |
+goog.require('cvox.ChromeVox'); |
+goog.require('cvox.ChromeVoxSearch'); |
+goog.require('cvox.ExtensionBridge'); |
+goog.require('cvox.SelectionUtil'); |
+ |
+/** |
+ * @fileoverview High level commands that the user can invoke using hotkeys. |
+ */ |
+cvox.ChromeVoxUserCommands = function() { }; |
+ |
+/** |
+ * @type {number} |
+ */ |
+cvox.ChromeVoxUserCommands.silenceLevel = 0; |
+ |
+/** |
+ * @type {Object} |
+ */ |
+cvox.ChromeVoxUserCommands.commands = {}; |
+ |
+/** |
+ * Stops speech. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['stopSpeech'] = function() { |
+ cvox.ChromeVox.tts.stop(); |
+ return false; |
+}; |
+ |
+/** |
+ * Moves forward and speaks the result. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['forward'] = function() { |
+ cvox.ChromeVoxUserCommands.silenceEventWatchers_(); |
+ cvox.ChromeVox.navigationManager.next(); |
+ cvox.ChromeVoxUserCommands.finishNavCommand(''); |
+ return false; |
+}; |
+ |
+/** |
+ * Moves backward and speaks the result. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['backward'] = function() { |
+ cvox.ChromeVoxUserCommands.silenceEventWatchers_(); |
+ cvox.ChromeVox.navigationManager.previous(); |
+ cvox.ChromeVoxUserCommands.finishNavCommand(''); |
+ return false; |
+}; |
+ |
+/** |
+ * Moves up to a different navigation strategy and speaks a summary of the |
+ * current position. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousGranularity'] = function() { |
+ cvox.ChromeVox.navigationManager.up(); |
+ var strategy = cvox.ChromeVox.navigationManager.getStrategy(); |
+ if (strategy == 'SELECTION') { |
+ strategy = cvox.ChromeVox.navigationManager.getGranularity(); |
+ } |
+ cvox.ChromeVoxUserCommands.finishNavCommand(strategy + ' '); |
+ return false; |
+}; |
+ |
+/** |
+ * Moves down to a different navigation strategy and speaks a summary of the |
+ * current position. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextGranularity'] = function() { |
+ cvox.ChromeVox.navigationManager.down(); |
+ var strategy = cvox.ChromeVox.navigationManager.getStrategy(); |
+ if (strategy == 'SELECTION') { |
+ strategy = cvox.ChromeVox.navigationManager.getGranularity(); |
+ } |
+ cvox.ChromeVoxUserCommands.finishNavCommand(strategy + ' '); |
+ return false; |
+}; |
+ |
+/** |
+ * This is a NOP command. It is needed in case we would like |
+ * to swallow certain keys via mapping them to a NOP operation. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nop'] = function() { |
+ /* do nothing */ |
+ return false; |
+}; |
+ |
+/** |
+ * Perform all of the actions that should happen at the end of any |
+ * navigation operation: update the lens, play earcons, and speak the |
+ * description of the object that was navigated to. |
+ * |
+ * @param {string} messagePrefixStr The string to be prepended to what |
+ * is spoken to the user. |
+ */ |
+cvox.ChromeVoxUserCommands.finishNavCommand = function(messagePrefixStr) { |
+ cvox.ChromeVox.lens.updateText(); |
+ var message = cvox.ChromeVox.navigationManager.getCurrentDescription(); |
+ // Remove all whitespace from the beginning and end, and collapse all |
+ // inner strings of whitespace to a single space. |
+ message = message.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, ''); |
+ setTimeout(function() { |
+ cvox.ChromeVox.navigationManager.setFocus(); |
+ }, 0); |
+ cvox.SelectionUtil.scrollToSelection(window.getSelection()); |
+ cvox.ChromeVox.tts.speak(messagePrefixStr + message, 0, null); |
+ cvox.ChromeVoxUserCommands.playEarcons(); |
+}; |
+ |
+/** |
+ * Play earcons for the object that was most recently navigated to. |
+ */ |
+cvox.ChromeVoxUserCommands.playEarcons = function() { |
+ var ancestors = cvox.ChromeVox.navigationManager.getChangedAncestors(); |
+ var earcons = []; |
+ for (var i = 0; i < ancestors.length; i++) { |
+ var node = ancestors[i]; |
+ switch (node.tagName) { |
+ case 'BUTTON': |
+ earcons.push(cvox.AbstractEarcons.BUTTON); |
+ break; |
+ case 'A': |
+ earcons.push(cvox.AbstractEarcons.LINK); |
+ break; |
+ case 'LI': |
+ earcons.push(cvox.AbstractEarcons.LIST_ITEM); |
+ break; |
+ case 'SELECT': |
+ earcons.push(cvox.AbstractEarcons.LISTBOX); |
+ break; |
+ case 'TEXTAREA': |
+ earcons.push(cvox.AbstractEarcons.EDITABLE_TEXT); |
+ break; |
+ case 'INPUT': |
+ switch (node.type) { |
+ case 'submit': |
+ case 'reset': |
+ earcons.push(cvox.AbstractEarcons.BUTTON); |
+ break; |
+ case 'checkbox': |
+ case 'radio': |
+ if (node.value) { |
+ earcons.push(cvox.AbstractEarcons.CHECK_ON); |
+ } else { |
+ earcons.push(cvox.AbstractEarcons.CHECK_OFF); |
+ } |
+ break; |
+ default: |
+ if (cvox.DomUtil.isInputTypeText(node)) { |
+ // 'text', 'password', etc. |
+ earcons.push(cvox.AbstractEarcons.EDITABLE_TEXT); |
+ } |
+ break; |
+ } |
+ } |
+ } |
+ |
+ for (var j = 0; j < earcons.length; j++) { |
+ cvox.ChromeVox.earcons.playEarcon(earcons[j]); |
+ } |
+}; |
+ |
+/** |
+ * Find the next occurrence of an item defined by the given predicate. |
+ * @param {function(Array.<Node>)} predicate A function taking a node as a |
+ * parameter and returning true if it's what to search for. |
+ * @param {string} errorStr A string to speak if the item couldn't be found. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.findNextAndSpeak_ = function(predicate, |
+ errorStr) { |
+ cvox.ChromeVoxUserCommands.silenceEventWatchers_(); |
+ if (!cvox.ChromeVox.navigationManager.findNext(predicate)) { |
+ cvox.ChromeVox.tts.speak(errorStr, 0, null); |
+ return; |
+ } |
+ cvox.ChromeVoxUserCommands.finishNavCommand(''); |
+}; |
+ |
+/** |
+ * Find the next occurrence of an item defined by the given predicate. |
+ * @param {function(Array.<Node>)} predicate A function taking a node as a |
+ * parameter and returning true if it's what to search for. |
+ * @param {string} errorStr A string to speak if the item couldn't be found. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.findPreviousAndSpeak_ = function(predicate, |
+ errorStr) { |
+ cvox.ChromeVoxUserCommands.silenceEventWatchers_(); |
+ if (!cvox.ChromeVox.navigationManager.findPrevious(predicate)) { |
+ cvox.ChromeVox.tts.speak(errorStr, 0, null); |
+ return; |
+ } |
+ cvox.ChromeVoxUserCommands.finishNavCommand(''); |
+}; |
+ |
+/** |
+ * @param {Array} arr Array of nodes. |
+ * @param {string} tagName The name of the tag. |
+ * @return {boolean} True if obj is in the array. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.containsTagName_ = function(arr, tagName) { |
+ var i = arr.length; |
+ while (i--) { |
+ if (arr[i].tagName == tagName) { |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Temporarily silence event watchers, then automatically un-silence them |
+ * after a short delay. This prevents us from speaking that something has |
+ * focused when the focusing was a result of a ChromeVox action. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.silenceEventWatchers_ = function() { |
+ cvox.ChromeVoxUserCommands.silenceLevel += 1; |
+ setTimeout(function() { |
+ cvox.ChromeVoxUserCommands.silenceLevel -= 1; |
+ }, 100); |
+}; |
+ |
+/** |
+ * Handles TAB navigation by putting focus at the user's position. |
+ * This function will create dummy nodes if there is nothing that |
+ * is focusable at the current position. |
+ * |
+ * @return {boolean} Always return true since we rely on the default action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['handleTab'] = function() { |
+ // Clean up after any previous runs |
+ var previousDummySpan = document.getElementById('ChromeVoxTabDummySpan'); |
+ if (previousDummySpan) { |
+ previousDummySpan.parentNode.removeChild(previousDummySpan); |
+ } |
+ |
+ // Hide the search widget if it is shown. |
+ cvox.ChromeVoxSearch.hide(); |
+ |
+ var tagName = 'A'; |
+ // If the user is already focused on a link or control, |
+ // nothing more needs to be done. |
+ if ((document.activeElement.tagName == tagName) || |
+ cvox.DomUtil.isControl(document.activeElement)) { |
+ return true; |
+ } |
+ |
+ // Try to find something reasonable to focus on in the current selection. |
+ var sel = window.getSelection(); |
+ if (sel == null || sel.anchorNode == null || sel.focusNode == null) { |
+ return true; |
+ } |
+ if (sel.anchorNode.tagName && |
+ ((sel.anchorNode.tagName == tagName) || |
+ cvox.DomUtil.isControl(sel.anchorNode))) { |
+ sel.anchorNode.focus(); |
+ return true; |
+ } |
+ if (sel.focusNode.tagName && |
+ ((sel.focusNode.tagName == tagName) || |
+ cvox.DomUtil.isControl(sel.focusNode))) { |
+ sel.focusNode.focus(); |
+ return true; |
+ } |
+ if (sel.anchorNode.parentNode.tagName && |
+ ((sel.anchorNode.parentNode.tagName == tagName) || |
+ cvox.DomUtil.isControl(sel.anchorNode.parentNode))) { |
+ sel.anchorNode.parentNode.focus(); |
+ return true; |
+ } |
+ if (sel.focusNode.parentNode.tagName && |
+ ((sel.focusNode.parentNode.tagName == tagName) || |
+ cvox.DomUtil.isControl(sel.focusNode))) { |
+ sel.focusNode.parentNode.focus(); |
+ return true; |
+ } |
+ |
+ // Create a dummy span immediately before the current position and focus |
+ // on it so that the default tab action will start off as close to the |
+ // user's current position as possible. |
+ var span = document.createElement('span'); |
+ span.id = 'ChromeVoxTabDummySpan'; |
+ sel.anchorNode.parentNode.insertBefore(span, sel.anchorNode); |
+ span.tabIndex = -1; |
+ span.focus(); |
+ return true; |
+}; |
+ |
+/** |
+ * Toggles between searching and browsing. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['toggleSearchWidget'] = function() { |
+ if (cvox.ChromeVoxSearch.isActive()) { |
+ cvox.ChromeVoxSearch.hide(); |
+ cvox.ChromeVox.tts.speak('Browse', 0, null); |
+ } else { |
+ cvox.ChromeVoxSearch.show(); |
+ cvox.ChromeVox.tts.speak('Search', 0, null); |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Cycles through the Text-To-Speech Engines. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextTtsEngine'] = function() { |
+ cvox.ChromeVox.tts.nextEngine(); |
+ return false; |
+}; |
+ |
+/** |
+ * Decreases the tts rate. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['decreaseTtsRate'] = function() { |
+ cvox.ChromeVox.tts.decreaseProperty('Rate'); |
+ return false; |
+}; |
+ |
+/** |
+ * Increases the tts rate. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['increaseTtsRate'] = function() { |
+ cvox.ChromeVox.tts.increaseProperty('Rate'); |
+ return false; |
+}; |
+ |
+/** |
+ * Decreases the tts pitch. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['decreaseTtsPitch'] = function() { |
+ cvox.ChromeVox.tts.decreaseProperty('Pitch'); |
+ return false; |
+}; |
+ |
+/** |
+ * Increases the tts pitch. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['increaseTtsPitch'] = function() { |
+ cvox.ChromeVox.tts.increaseProperty('Pitch'); |
+ return false; |
+}; |
+ |
+/** |
+ * Decreases the tts volume. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['decreaseTtsVolume'] = function() { |
+ cvox.ChromeVox.tts.decreaseProperty('Volume'); |
+ return false; |
+}; |
+ |
+/** |
+ * Increases the tts volume. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['increaseTtsVolume'] = function() { |
+ cvox.ChromeVox.tts.increaseProperty('Volume'); |
+ return false; |
+}; |
+ |
+/** |
+ * Shows the bookmark manager |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['showBookmarkManager'] = function() { |
+ cvox.ExtensionBridge.send({ |
+ 'target': 'BookmarkManager', |
+ 'action': 'open'}); |
+ return false; |
+}; |
+ |
+/** |
+ * Debug function - useful for quickly trying out some behavior |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['debug'] = function() { |
+ alert('ok'); |
+ return false; |
+}; |
+ |
+// |
+// Jump commands - jump to the next / previous node of a certain category |
+// |
+ |
+/** |
+ * Next checkbox. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextCheckbox'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.checkboxPredicate_, |
+ 'No next checkbox.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous checkbox. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousCheckbox'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.checkboxPredicate_, |
+ 'No previous checkbox.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next radio button. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextRadio'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.radioPredicate_, |
+ 'No next radio button.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous radio button. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousRadio'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.radioPredicate_, |
+ 'No previous radio button.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next slider. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextSlider'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.sliderPredicate_, |
+ 'No next slider.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous slider. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousSlider'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.sliderPredicate_, |
+ 'No previous slider.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next graphic. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextGraphic'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.graphicPredicate_, |
+ 'No next graphic.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous graphic. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousGraphic'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.graphicPredicate_, |
+ 'No previous graphic.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next button. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextButton'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.buttonPredicate_, |
+ 'No next button.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous button. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousButton'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.buttonPredicate_, |
+ 'No previous button.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next combo box. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextComboBox'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.comboBoxPredicate_, |
+ 'No next combo box.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous combo box. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousComboBox'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.comboBoxPredicate_, |
+ 'No previous combo box.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next editable text field. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextEditText'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.editTextPredicate_, |
+ 'No next editable text field.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous editable text field. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousEditText'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.editTextPredicate_, |
+ 'No previous editable text field.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next heading. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextHeading'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.headingPredicate_, |
+ 'No next heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous heading. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousHeading'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.headingPredicate_, |
+ 'No previous heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next heading level 1. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextHeading1'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading1Predicate_, |
+ 'No next level 1 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous heading level 1. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousHeading1'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading1Predicate_, |
+ 'No previous level 1 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next heading level 2. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextHeading2'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading2Predicate_, |
+ 'No next level 2 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous heading level 2. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousHeading2'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading2Predicate_, |
+ 'No previous level 2 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next heading level 3. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextHeading3'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading3Predicate_, |
+ 'No next level 3 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous heading level 3. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousHeading3'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading3Predicate_, |
+ 'No previous level 3 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next heading level 4. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextHeading4'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading4Predicate_, |
+ 'No next level 4 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous heading level 4. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousHeading4'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading4Predicate_, |
+ 'No previous level 4 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next heading level 5. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextHeading5'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading5Predicate_, |
+ 'No next level 5 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous heading level 5. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousHeading5'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading5Predicate_, |
+ 'No previous level 5 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next heading level 6. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextHeading6'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading6Predicate_, |
+ 'No next level 6 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous heading level 6. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousHeading6'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.heading6Predicate_, |
+ 'No previous level 6 heading.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next not-link. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextNotLink'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.notLinkPredicate_, |
+ 'No next item that isn\'t a link.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous not-link. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousNotLink'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.notLinkPredicate_, |
+ 'No previous item that isn\'t a link.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next link. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextLink'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.linkPredicate_, |
+ 'No next link.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous link. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousLink'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.linkPredicate_, |
+ 'No previous link.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next table. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextTable'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.tablePredicate_, |
+ 'No next table.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous table. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousTable'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.tablePredicate_, |
+ 'No previous table.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next list. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextList'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.listPredicate_, |
+ 'No next list.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous list. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousList'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.listPredicate_, |
+ 'No previous list.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next list item. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextListItem'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.listItemPredicate_, |
+ 'No next list item.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous list item. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousListItem'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.listItemPredicate_, |
+ 'No previous list item.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next blockquote. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextBlockquote'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.blockquotePredicate_, |
+ 'No next blockquote.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous blockquote. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousBlockquote'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.blockquotePredicate_, |
+ 'No previous blockquote.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Next form field. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['nextFormField'] = function() { |
+ cvox.ChromeVoxUserCommands.findNextAndSpeak_( |
+ cvox.ChromeVoxUserCommands.formFieldPredicate_, |
+ 'No next form field.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Previous form field. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['previousFormField'] = function() { |
+ cvox.ChromeVoxUserCommands.findPreviousAndSpeak_( |
+ cvox.ChromeVoxUserCommands.formFieldPredicate_, |
+ 'No previous form field.'); |
+ return false; |
+}; |
+ |
+/** |
+ * Attempts to do something reasonable given the current item that the user is |
+ * on. |
+ * For example, if the user is on a chunk of text that contains a link, navigate |
+ * to that link. If there are multiple links in that chunk, bring up a menu to |
+ * let the user choose which link they meant to click on. |
+ * |
+ * @return {boolean} Always return false since we want to prevent the default |
+ * action. |
+ */ |
+cvox.ChromeVoxUserCommands.commands['actOnCurrentItem'] = function() { |
+ var actionTaken = cvox.ChromeVox.navigationManager.actOnCurrentItem(); |
+ if (!actionTaken) { |
+ cvox.ChromeVox.tts.speak('No actions available.', 0, null); |
+ } |
+ return false; |
+}; |
+ |
+ |
+// |
+// Predicates - functions that take an array of ancestor nodes that have |
+// changed and returns true if a certain category has been found. Used for |
+// implementing functions like nextCheckbox / prevCheckbox, and so on. |
+// |
+ |
+/** |
+ * Checkbox. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a checkbox. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.checkboxPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].role == 'checkbox') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'checkbox') { |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Radio button. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a radio button. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.radioPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].role == 'radio') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'radio') { |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Slider. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a slider. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.sliderPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].role == 'slider') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'range') { |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Graphic. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a graphic. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.graphicPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].tagName == 'IMG') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'img') { |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Button. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a button. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.buttonPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].role == 'button') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'BUTTON') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'submit') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'reset') { |
+ return true; |
+ } |
+ } |
+}; |
+ |
+/** |
+ * Combo box. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a combo box. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.comboBoxPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].role == 'combobox') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'SELECT') { |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Editable text field. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains an editable text field. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.editTextPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].role == 'textbox') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'TEXTAREA') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'INPUT') { |
+ return cvox.DomUtil.isInputTypeText(nodes[i]); |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Heading. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a heading. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.headingPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].role == 'heading') { |
+ return true; |
+ } |
+ switch (nodes[i].tagName) { |
+ case 'H1': |
+ case 'H2': |
+ case 'H3': |
+ case 'H4': |
+ case 'H5': |
+ case 'H6': |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Heading level 1. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a heading level 1. |
+ * TODO: handle ARIA headings with ARIA heading levels? |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.heading1Predicate_ = function(nodes) { |
+ return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H1'); |
+}; |
+ |
+/** |
+ * Heading level 2. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a heading level 2. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.heading2Predicate_ = function(nodes) { |
+ return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H2'); |
+}; |
+ |
+/** |
+ * Heading level 3. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a heading level 3. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.heading3Predicate_ = function(nodes) { |
+ return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H3'); |
+}; |
+ |
+/** |
+ * Heading level 4. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a heading level 4. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.heading4Predicate_ = function(nodes) { |
+ return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H4'); |
+}; |
+ |
+/** |
+ * Heading level 5. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a heading level 5. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.heading5Predicate_ = function(nodes) { |
+ return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H5'); |
+}; |
+ |
+/** |
+ * Heading level 6. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a heading level 6. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.heading6Predicate_ = function(nodes) { |
+ return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H6'); |
+}; |
+ |
+/** |
+ * Not-link. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if none of the items in the array is a link. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.notLinkPredicate_ = function(nodes) { |
+ return !cvox.ChromeVoxUserCommands.linkPredicate_(nodes); |
+}; |
+ |
+/** |
+ * Link. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a link. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.linkPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].role == 'link') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'A') { |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * Table. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a table. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.tablePredicate_ = function(nodes) { |
+ return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'TABLE'); |
+}; |
+ |
+/** |
+ * List. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a list. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.listPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].tagName == 'UL') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'OL') { |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
+ |
+/** |
+ * List item. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a list item. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.listItemPredicate_ = function(nodes) { |
+ return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'TABLE'); |
+}; |
+ |
+/** |
+ * Blockquote. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains a blockquote. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.blockquotePredicate_ = function(nodes) { |
+ return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'BLOCKQUOTE'); |
+}; |
+ |
+/** |
+ * Form field. |
+ * @param {Array.<Node>} nodes An array of nodes to check. |
+ * @return {boolean} True if the array contains any type of form field. |
+ * @private |
+ */ |
+cvox.ChromeVoxUserCommands.formFieldPredicate_ = function(nodes) { |
+ for (var i = 0; i < nodes.length; i++) { |
+ if (nodes[i].role == 'button') { |
+ return true; |
+ } |
+ if (nodes[i].role == 'checkbox') { |
+ return true; |
+ } |
+ if (nodes[i].role == 'combobox') { |
+ return true; |
+ } |
+ if (nodes[i].role == 'radio') { |
+ return true; |
+ } |
+ if (nodes[i].role == 'slider') { |
+ return true; |
+ } |
+ if (nodes[i].role == 'spinbutton') { |
+ return true; |
+ } |
+ if (nodes[i].role == 'textbox') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'INPUT') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'SELECT') { |
+ return true; |
+ } |
+ if (nodes[i].tagName == 'BUTTON') { |
+ return true; |
+ } |
+ } |
+ return false; |
+}; |
Property changes on: chrome/browser/resources/access_chromevox/chromevox/injected/user_commands.js |
___________________________________________________________________ |
Added: svn:executable |
+ * |
Added: svn:eol-style |
+ LF |