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

Unified Diff: chrome/browser/resources/access_chromevox/chromevox/injected/tools/search.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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/access_chromevox/chromevox/injected/tools/search.js
===================================================================
--- chrome/browser/resources/access_chromevox/chromevox/injected/tools/search.js (revision 0)
+++ chrome/browser/resources/access_chromevox/chromevox/injected/tools/search.js (revision 0)
@@ -0,0 +1,300 @@
+// 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.
+
+/**
+ * @fileoverview JavaScript for poppup up a search widget and performing
+ * search within a page.
+ */
+
+goog.provide('cvox.ChromeVoxSearch');
+
+goog.require('cvox.AbstractEarcons');
+goog.require('cvox.ChromeVox');
+goog.require('cvox.SelectionUtil');
+goog.require('cvox.XpathUtil');
+
+/**
+ * @type {Object}
+ */
+cvox.ChromeVoxSearch.txtNode = null;
+
+/**
+ * @type {boolean}
+ */
+cvox.ChromeVoxSearch.active = false;
+
+/**
+ * @type {Array?}
+ */
+cvox.ChromeVoxSearch.matchNodes = null;
+
+/**
+ * @type {number?}
+ */
+cvox.ChromeVoxSearch.matchNodesIndex = null;
+
+/**
+ * @type {boolean}
+ */
+cvox.ChromeVoxSearch.caseSensitive = false;
+
+/**
+ * Initializes the search widget.
+ */
+cvox.ChromeVoxSearch.init = function() {
+ cvox.ChromeVoxSearch.active = false;
+ cvox.ChromeVoxSearch.caseSensitive = false;
+ window.addEventListener('keypress', cvox.ChromeVoxSearch.processKeyPress,
+ true);
+ window.addEventListener('keydown', cvox.ChromeVoxSearch.processKeyDown,
+ true);
+ window.addEventListener('scroll', cvox.ChromeVoxSearch.scrollHandler,
+ true);
+};
+
+/**
+ * Returns whether or not the search widget is active.
+ *
+ * @return {boolean} True if the search widget is active.
+ */
+cvox.ChromeVoxSearch.isActive = function() {
+ return cvox.ChromeVoxSearch.active;
+};
+
+/**
+ * Displays the search widget.
+ */
+cvox.ChromeVoxSearch.show = function() {
+ cvox.ChromeVoxSearch.txtNode = document.createElement('div');
+ cvox.ChromeVoxSearch.txtNode.style['display'] = 'block';
+ cvox.ChromeVoxSearch.txtNode.style['position'] = 'absolute';
+ cvox.ChromeVoxSearch.txtNode.style['left'] = '2px';
+ cvox.ChromeVoxSearch.txtNode.style['top'] = (window.scrollY + 2) + 'px';
+ cvox.ChromeVoxSearch.txtNode.style['line-height'] = '1.2em';
+ cvox.ChromeVoxSearch.txtNode.style['z-index'] = '10001';
+ cvox.ChromeVoxSearch.txtNode.style['font-size'] = '20px';
+
+ document.body.insertBefore(cvox.ChromeVoxSearch.txtNode,
+ document.body.firstChild);
+ cvox.ChromeVoxSearch.active = true;
+};
+
+/**
+ * Keeps the search widget at the upperleft hand corner of the screen when
+ * the page scrolls.
+ */
+cvox.ChromeVoxSearch.scrollHandler = function() {
+ if (!cvox.ChromeVoxSearch.active) {
+ return;
+ }
+ cvox.ChromeVoxSearch.txtNode.style['top'] = (window.scrollY + 2) + 'px';
+};
+
+/**
+ * Handles the keyDown event when the search widget is active.
+ *
+ * @param {Object} evt The keyDown event.
+ * @return {boolean} Whether or not the event was handled.
+ */
+cvox.ChromeVoxSearch.processKeyDown = function(evt) {
+ if (!cvox.ChromeVoxSearch.active) {
+ return false;
+ }
+ if (evt.keyCode == 8) { // Backspace
+ var searchStr = cvox.ChromeVoxSearch.txtNode.textContent;
+ if (searchStr.length > 0) {
+ searchStr = searchStr.substring(searchStr, searchStr.length - 1);
+ cvox.ChromeVoxSearch.doSearch(searchStr,
+ cvox.ChromeVoxSearch.caseSensitive);
+ }
+ // Don't go to the previous page!
+ evt.preventDefault();
+ return true;
+ } else if (evt.keyCode == 40) { // Down arrow
+ cvox.ChromeVoxSearch.next();
+ return true;
+ } else if (evt.keyCode == 38) { // Up arrow
+ cvox.ChromeVoxSearch.prev();
+ return true;
+ } else if (evt.ctrlKey && evt.keyCode == 67) { // ctrl + c
+ cvox.ChromeVoxSearch.toggleCaseSensitivity();
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Adds the letter the user typed to the search string and updates the search.
+ *
+ * @param {Object} evt The keyPress event.
+ * @return {boolean} Whether or not the event was handled.
+ */
+cvox.ChromeVoxSearch.processKeyPress = function(evt) {
+ if (!cvox.ChromeVoxSearch.active) {
+ return false;
+ }
+ var searchStr = cvox.ChromeVoxSearch.txtNode.textContent +
+ String.fromCharCode(evt.charCode);
+ cvox.ChromeVoxSearch.doSearch(searchStr,
+ cvox.ChromeVoxSearch.caseSensitive);
+ evt.preventDefault();
+ evt.stopPropagation();
+ return true;
+};
+
+/**
+ * Toggles whether or not searches are case sensitive.
+ */
+cvox.ChromeVoxSearch.toggleCaseSensitivity = function() {
+ if (cvox.ChromeVoxSearch.caseSensitive) {
+ cvox.ChromeVoxSearch.caseSensitive = false;
+ cvox.ChromeVox.tts.speak('Ignoring case', 0, null);
+ } else {
+ cvox.ChromeVoxSearch.caseSensitive = true;
+ cvox.ChromeVox.tts.speak('Case sensitive', 0, null);
+ }
+};
+
+/**
+ * Performs the search and highlights and speaks the first result.
+ *
+ * @param {String} searchStr The text to search for.
+ * @param {boolean} caseSensitive Whether or not the search is case sensitive.
+ */
+cvox.ChromeVoxSearch.doSearch = function(searchStr, caseSensitive) {
+ cvox.ChromeVoxSearch.txtNode.textContent = '';
+
+ cvox.ChromeVoxSearch.matchNodes = new Array();
+ var potentialMatchNodes;
+ if (caseSensitive) {
+ potentialMatchNodes = cvox.XpathUtil.evalXPath(
+ './/text()[contains(.,"' + searchStr + '")]',
+ document.body);
+ } else {
+ searchStr = searchStr.toLowerCase();
+ potentialMatchNodes = cvox.XpathUtil.evalXPath(
+ './/text()[contains(translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", ' +
+ '"abcdefghijklmnopqrstuvwxyz"), "' + searchStr + '")]',
+ document.body);
+ }
+ // Only accept nodes that are considered to have content.
+ for (var i = 0, node; node = potentialMatchNodes[i]; i++) {
+ if (cvox.DomUtil.hasContent(node)) {
+ cvox.ChromeVoxSearch.matchNodes.push(node);
+ }
+ }
+
+ var firstNode = cvox.ChromeVoxSearch.matchNodes[0];
+
+ if (firstNode) {
+ cvox.ChromeVoxSearch.matchNodesIndex = 0;
+ var startIndex = 0;
+ if (caseSensitive) {
+ startIndex = firstNode.textContent.indexOf(searchStr);
+ } else {
+ startIndex = firstNode.textContent.toLowerCase().indexOf(searchStr);
+ }
+ cvox.SelectionUtil.selectText(firstNode, startIndex,
+ startIndex + searchStr.length);
+ cvox.ChromeVox.traverseContent.moveNext('sentence');
+ var sel = window.getSelection();
+ var range = sel.getRangeAt(0);
+ range.setStart(firstNode, startIndex);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ cvox.SelectionUtil.scrollToSelection(sel);
+ cvox.ChromeVox.tts.speak(window.getSelection() + '', 0, null);
+ } else {
+ // TODO (clchen): Replace this with an error sound once we have one defined.
+ cvox.ChromeVox.tts.stop();
+ cvox.ChromeVox.earcons.playEarcon(cvox.AbstractEarcons.WRAP);
+ }
+ cvox.ChromeVoxSearch.txtNode.textContent = searchStr;
+};
+
+/**
+ * Dismisses the search widget
+ */
+cvox.ChromeVoxSearch.hide = function() {
+ if (cvox.ChromeVoxSearch.active) {
+ cvox.ChromeVoxSearch.txtNode.parentNode.removeChild(
+ cvox.ChromeVoxSearch.txtNode);
+ cvox.ChromeVoxSearch.txtNode = null;
+ cvox.ChromeVoxSearch.active = false;
+ }
+};
+
+/**
+ * Goes to the next matching result, highlights it, and speaks it.
+ */
+cvox.ChromeVoxSearch.next = function() {
+ if (cvox.ChromeVoxSearch.matchNodes &&
+ (cvox.ChromeVoxSearch.matchNodes.length > 0)) {
+ cvox.ChromeVoxSearch.matchNodesIndex++;
+ if (cvox.ChromeVoxSearch.matchNodes.length >
+ cvox.ChromeVoxSearch.matchNodesIndex) {
+ var searchStr = cvox.ChromeVoxSearch.txtNode.textContent;
+ var targetNode = cvox.ChromeVoxSearch.matchNodes[
+ cvox.ChromeVoxSearch.matchNodesIndex];
+ var startIndex = 0;
+ if (cvox.ChromeVoxSearch.caseSensitive) {
+ startIndex = targetNode.textContent.indexOf(searchStr);
+ } else {
+ startIndex = targetNode.textContent.toLowerCase().indexOf(
+ searchStr.toLowerCase());
+ }
+ cvox.SelectionUtil.selectText(targetNode, startIndex,
+ startIndex + searchStr.length);
+ cvox.ChromeVox.traverseContent.moveNext('sentence');
+ var sel = window.getSelection();
+ var range = sel.getRangeAt(0);
+ range.setStart(targetNode, startIndex);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ cvox.SelectionUtil.scrollToSelection(sel);
+ cvox.ChromeVox.tts.speak(window.getSelection() + '', 0, null);
+ } else {
+ cvox.ChromeVox.earcons.playEarcon(cvox.AbstractEarcons.WRAP);
+ cvox.ChromeVoxSearch.matchNodesIndex = -1;
+ cvox.ChromeVoxSearch.next();
+ }
+ }
+};
+
+/**
+ * Goes to the previous matching result, highlights it, and speaks it.
+ */
+cvox.ChromeVoxSearch.prev = function() {
+ if (cvox.ChromeVoxSearch.matchNodes &&
+ (cvox.ChromeVoxSearch.matchNodes.length > 0)) {
+ cvox.ChromeVoxSearch.matchNodesIndex--;
+ if (cvox.ChromeVoxSearch.matchNodesIndex > -1) {
+ var searchStr = cvox.ChromeVoxSearch.txtNode.textContent;
+ var targetNode = cvox.ChromeVoxSearch.matchNodes[
+ cvox.ChromeVoxSearch.matchNodesIndex];
+ var startIndex = 0;
+ if (cvox.ChromeVoxSearch.caseSensitive) {
+ startIndex = targetNode.textContent.indexOf(searchStr);
+ } else {
+ startIndex = targetNode.textContent.toLowerCase().indexOf(
+ searchStr.toLowerCase());
+ }
+ cvox.SelectionUtil.selectText(targetNode, startIndex,
+ startIndex + searchStr.length);
+ cvox.ChromeVox.traverseContent.moveNext('sentence');
+ var sel = window.getSelection();
+ var range = sel.getRangeAt(0);
+ range.setStart(targetNode, startIndex);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ cvox.SelectionUtil.scrollToSelection(sel);
+ cvox.ChromeVox.tts.speak(window.getSelection() + '', 0, null);
+ } else {
+ cvox.ChromeVox.earcons.playEarcon(cvox.AbstractEarcons.WRAP);
+ cvox.ChromeVoxSearch.matchNodesIndex =
+ cvox.ChromeVoxSearch.matchNodes.length;
+ cvox.ChromeVoxSearch.prev();
+ }
+ }
+};
Property changes on: chrome/browser/resources/access_chromevox/chromevox/injected/tools/search.js
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698