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

Unified Diff: chrome/browser/resources/access_chromevox/chromevis/injected/lens.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/chromevis/injected/lens.js
===================================================================
--- chrome/browser/resources/access_chromevox/chromevis/injected/lens.js (revision 0)
+++ chrome/browser/resources/access_chromevox/chromevis/injected/lens.js (revision 0)
@@ -0,0 +1,554 @@
+// 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 Creates a CSS lens for displaying magnified text.
+ */
+
+goog.provide('chromevis.ChromeVisLens');
+
+goog.require('cvox.BuildConfig');
+goog.require('cvox.ExtensionBridge');
+goog.require('cvox.SelectionUtil');
+
+/**
+ * Constructor for CSS lens. Initializes the lens settings.
+ * @constructor
+ */
+chromevis.ChromeVisLens = function() {
+
+ /**
+ * The current amount of padding (in pixels) between the text
+ * and the sides of the lens
+ * @type {number}
+ * @private
+ */
+ this.padding_ = 5;
+
+ /**
+ * The maximum width of the bubble lens (in pixels)
+ * @type {number}
+ * @private
+ */
+ this.maxBubbleWidth_ = 700;
+
+ /**
+ * The minimum width of the bubble lens (in pixels)
+ * @type {number}
+ * @private
+ */
+ this.minBubbleWidth_ = 25;
+
+ /**
+ * Whether or not the lens is currently displayed
+ * @type {boolean}
+ * @private
+ */
+ this.isLensDisplayed_ = false;
+
+ /**
+ * Whether or not the lens is currently centered
+ * @type {boolean}
+ */
+ this.isCentered = true;
+
+ /**
+ * The current magnification multiplier
+ * @type {number}
+ */
+ this.multiplier = 1.5;
+
+ /**
+ * The current text color
+ * @type {string}
+ */
+ this.textColor = '#FFFFFF';
+
+ /**
+ * The current lens background color
+ * @type {string}
+ */
+ this.bgColor = '#000000';
+
+ /**
+ * Whether the lens is currently anchored to the top of the page
+ * @type {boolean}
+ */
+ this.isAnchored = true;
+
+ /**
+ * The current ChromeVis lens object
+ * @type {Element}
+ */
+ this.lens = chromevis.ChromeVisLens.ACTIVE_DOC.createElement('span');
+
+ this.initializeLens_();
+};
+
+
+/**
+ * The name of the special div that contains settings specified by the
+ * background page
+ * @type {string}
+ * @const
+ */
+chromevis.ChromeVisLens.EL_ID = 'chromeVisBackground2LensDiv';
+
+/**
+ * The name of the attribute specifying whether the lens is centered
+ * @type {string}
+ * @const
+ */
+chromevis.ChromeVisLens.CENTER_ATTRB = 'data-isCentered';
+
+/**
+ * The name of the attribute specifying the lens magnification
+ * @type {string}
+ * @const
+ */
+chromevis.ChromeVisLens.MULT_ATTRB = 'data-textMag';
+
+/**
+ * The name of the attribute specifying the lens text color
+ * @type {string}
+ * @const
+ */
+chromevis.ChromeVisLens.TXT_COLOR_ATTRB = 'data-textColor';
+
+/**
+ * The name of the attribute specifying the lens background color
+ * @type {string}
+ * @const
+ */
+chromevis.ChromeVisLens.BG_COLOR_ATTRB = 'data-bgColor';
+
+/**
+ * The name of the attribute specifying whether the lens is anchored
+ * @type {string}
+ * @const
+ */
+chromevis.ChromeVisLens.ANCHOR_ATTRB = 'data-isAnchored';
+
+/**
+ * The active document
+ * @type {Document}
+ * @const
+ */
+chromevis.ChromeVisLens.ACTIVE_DOC = window.document;
+
+
+/**
+ * Initializes the ChromeVis lens with settings pulled from background page.
+ * @private
+ */
+chromevis.ChromeVisLens.prototype.initializeLens_ = function() {
+ this.initializeLensCSS_();
+
+ this.lens.style.display = 'none';
+ chromevis.ChromeVisLens.ACTIVE_DOC.body.appendChild(this.lens);
+
+ this.setupMessageListener_();
+
+ this.updateAnchorLens();
+};
+
+
+/**
+ * Listens for an event fired from the extension that indicates the background
+ * page is requesting the lens to update. This event was dispatched to a known
+ * div in the shared DOM (chromeVisBackground2LensDiv) and the div has
+ * attributes known to the lens that contain lens setting information. The
+ * lens reads information from the div and then updates appropriately.
+ * @private
+ */
+chromevis.ChromeVisLens.prototype.setupMessageListener_ = function() {
+ if (BUILD_TYPE != BUILD_TYPE_CHROME) {
+ return;
+ }
+ var self = this;
+ cvox.ExtensionBridge.addMessageListener(function(message, port) {
+ switch (message.data) {
+ case 'data-isAnchored':
+ self.setAnchoredLens(message.value);
+ self.isAnchored ? self.updateAnchorLens() : self.updateBubbleLens();
+ break;
+ case 'data-isCentered':
+ self.isCentered = message.value;
+ if (!self.isAnchored) {
+ self.updateBubbleLens();
+ }
+ break;
+ case 'data-textMag':
+ var multData = message.value;
+ if (multData != null) {
+ self.multiplier = parseFloat(multData);
+ self.setMagnification();
+ // Must update position of lens after text size has changed
+ self.isAnchored ? self.updateAnchorLens() : self.updateBubbleLens();
+ }
+ break;
+ case 'data-textColor':
+ var textColorData = message.value;
+ if (textColorData != null) {
+ self.textColor = textColorData;
+ self.setTextColor();
+ }
+ break;
+ case 'data-bgColor':
+ var bgColorData = message.value;
+ if (bgColorData != null) {
+ self.bgColor = bgColorData;
+ self.setBgColor();
+ }
+ break;
+ }
+ });
+};
+
+
+/**
+ * Displays or hides the lens.
+ * @param {boolean} show Whether or not the lens should be shown.
+ */
+chromevis.ChromeVisLens.prototype.showLens = function(show) {
+ show ? this.lens.style.display = 'block' :
+ this.lens.style.display = 'none';
+
+ this.isLensDisplayed_ = show;
+
+ this.isLensDisplayed_ ? this.updateText() : document.body.style.marginTop = 0;
+};
+
+
+/**
+ * Initializes the lens CSS.
+ * @private
+ */
+chromevis.ChromeVisLens.prototype.initializeLensCSS_ = function() {
+ this.lens.style.backgroundColor = this.bgColor;
+
+ // Style settings
+ this.lens.style.borderColor = '#000000';
+ this.lens.style.borderWidth = 'medium';
+ this.lens.style.borderStyle = 'groove';
+
+ this.lens.style.position = 'absolute';
+
+ // Note: there is no specified maximum value for the zIndex.
+ // Occasionally there will be a website that has an element with a zIndex
+ // higher than this one. The only fix is to manually go here and increase
+ // the zIndex.
+ this.lens.style.zIndex = 100000000000;
+
+ this.lens.style.minHeight = 5 + 'px';
+
+ this.lens.style.webkitBorderRadius = '7px';
+
+ // Class setting - this special class name means ChromeVis will
+ // not try to select text content inside the lens.
+ this.lens.className = cvox.TraverseUtil.SKIP_CLASS;
+};
+
+
+/**
+ * Sets whether the lens is anchored to the top of the page or whether it floats
+ * near the selected text.
+ * @param {boolean} anchored Whether or not the lens is anchored.
+ */
+chromevis.ChromeVisLens.prototype.setAnchoredLens = function(anchored) {
+ this.isAnchored = anchored;
+ if ((this.isLensDisplayed_) && (!this.isAnchored)) {
+ document.body.style.marginTop = 0;
+ }
+};
+
+
+/**
+ * Refreshes the position of the anchor lens on the page. This is usually done
+ * in response to scrolling or a window resize.
+ */
+chromevis.ChromeVisLens.prototype.updateAnchorLens = function() {
+ this.lens.style.top = window.scrollY + 'px';
+ this.lens.style.minWidth = (window.innerWidth - 50) + 'px';
+ this.lens.style.maxWidth = (window.innerWidth - 50) + 'px';
+
+ this.lens.style.left = 10 + 'px';
+ this.lens.style.right = 100 + 'px';
+
+ // Push rest of document down underneath anchor lens.
+ // Does not work with documents that have absolutely positioned
+ // elements - because absolutely positioned element margins
+ // never collapse with global margins.
+
+ var bod = document.body;
+ // need to add 10 to the computed style to take into account the margin
+ var str_ht = window.getComputedStyle(this.lens, null).height;
+ var ht = parseInt(str_ht.substr(0, str_ht.length - 2), 10) + 20;
+ bod.style.marginTop = ht + 'px';
+};
+
+
+/**
+ * Refreshes the position of the bubble lens on the page. This is done in
+ * response to the selection changing or the window resizing.
+ */
+chromevis.ChromeVisLens.prototype.updateBubbleLens = function() {
+ var sel = window.getSelection();
+ var pos = cvox.SelectionUtil.findSelPosition(sel);
+
+ var top;
+ var left;
+ if (pos == null) {
+ top = 0;
+ left = 0;
+ }
+ top = pos[0];
+ left = pos[1];
+
+ this.lens.style.minWidth = 0;
+
+ // Calculate maximum lens width
+ var parent;
+ var maxw;
+ if (this.isCentered) {
+ // Want width with lens centered in the parent element
+ // So maxwidth is width of parent
+ parent = sel.getRangeAt(0).commonAncestorContainer;
+ while (!parent.offsetWidth) {
+ parent = parent.parentNode;
+ }
+ maxw = Math.min(this.maxBubbleWidth_, parent.offsetWidth);
+ } else {
+ // Align the left edge of the lens with the left edge of the selection
+ // So find maxwidth with left edge aligned
+ maxw = Math.min(this.maxBubbleWidth_,
+ ((document.body.clientWidth - left) - 16));
+ }
+
+ this.lens.style.maxWidth = maxw + 'px';
+ // Now calculate lens left position
+ // First check if actual width is larger than maxWidth
+ if (this.lens.firstChild.scrollWidth > maxw) {
+ var shiftLeft = this.lens.firstChild.scrollWidth - maxw;
+
+ this.lens.style.maxWidth = this.lens.firstChild.scrollWidth + 'px';
+ this.lens.style.left = (left - shiftLeft) + 'px';
+ } else {
+ if (this.isCentered) {
+ // Center the lens in the parent element
+ var pleft = 0;
+ var obj = parent;
+
+ if (obj.offsetParent) {
+ pleft = obj.offsetLeft;
+ obj = obj.offsetParent;
+ while (obj !== null) {
+ pleft += obj.offsetLeft;
+ obj = obj.offsetParent;
+ }
+ }
+
+ this.lens.style.left =
+ Math.ceil((pleft + (parent.offsetWidth / 2)) -
+ (this.lens.firstChild.scrollWidth / 2)) +
+ 'px';
+ } else {
+ // Align the left edge of the lens with the left edge of the selection
+ this.lens.style.left = left + 'px';
+ }
+ }
+ this.lens.style.right = 'auto';
+
+ // Calculate lens height and top position
+ var str_ht = window.getComputedStyle(this.lens, null).height;
+ var ht = parseInt(str_ht.substr(0, str_ht.length - 2), 10) + 20;
+
+ var actualTop = top - ht;
+ if (actualTop < 0) {
+ this.lens.style.top = 5 + 'px';
+ } else {
+ this.lens.style.top = actualTop + 'px';
+ }
+};
+
+
+/**
+ * Update the text displayed inside the lens. This is done in response to the
+ * selection changing.
+ */
+chromevis.ChromeVisLens.prototype.updateText = function() {
+ if (this.isLensDisplayed_) {
+ // Need to replace current lens node due to Webkit caching some
+ // display settings between lens changes.
+ chromevis.ChromeVisLens.ACTIVE_DOC = window.document;
+ chromevis.ChromeVisLens.ACTIVE_DOC.body.removeChild(this.lens);
+ this.lens = chromevis.ChromeVisLens.ACTIVE_DOC.createElement('span');
+
+ this.initializeLensCSS_();
+
+ chromevis.ChromeVisLens.ACTIVE_DOC.body.appendChild(this.lens);
+
+ var sel = window.getSelection();
+ var selectedText = sel.toString();
+
+ if (selectedText == null) {
+ // No selection, but still need to update the lens so it
+ // has a consistent appearance
+ selectedText = '';
+ }
+
+ while (this.lens.firstChild) {
+ this.lens.removeChild(this.lens.firstChild);
+ }
+
+ var clonedNode = document.createElement('div');
+
+ // To preserve new lines in selected text, need to create child div nodes
+ // of the new element.
+ // This also guards against selected text that includes HTML tags.
+ var newSelectedText = '';
+ var childNode = document.createElement('div');
+
+ for (var i = 0; i < selectedText.length; i++) {
+ if ((selectedText.charCodeAt(i) == 10)) {
+ childNode.textContent = newSelectedText;
+ clonedNode.appendChild(childNode);
+ childNode = document.createElement('div');
+ newSelectedText = '';
+ } else {
+ newSelectedText = newSelectedText + selectedText.charAt(i);
+ }
+ }
+ childNode.textContent = newSelectedText;
+ clonedNode.appendChild(childNode);
+
+ // Style settings
+ clonedNode.style.fontFamily = 'Verdana, Arial, Helvetica, sans-serif';
+ clonedNode.style.fontWeight = 'normal';
+ clonedNode.style.fontStyle = 'normal';
+ clonedNode.style.color = this.textColor;
+ clonedNode.style.textDecoration = 'none';
+ clonedNode.style.textAlign = 'left';
+ clonedNode.style.lineHeight = 1.2;
+
+ this.lens.appendChild(clonedNode);
+
+ this.magnifyText_();
+ this.padText_();
+ this.isAnchored ? this.updateAnchorLens() : this.updateBubbleLens();
+ }
+};
+
+
+/**
+ * Updates the lens in response to a window resize.
+ */
+chromevis.ChromeVisLens.prototype.updateResized = function() {
+ this.isAnchored ? this.updateAnchorLens() : this.updateBubbleLens();
+};
+
+
+/**
+ * Updates the lens in response to the document being scrolled;
+ */
+chromevis.ChromeVisLens.prototype.updateScrolled = function() {
+ if (this.isAnchored) {
+ this.updateAnchorLens();
+
+ if (this.isLensDisplayed_) {
+ // Force redraw to counteract scroll acceleration problem
+ // Workaround: hide lens, check offsetHeight, display lens
+ // this forces a redraw
+ // TODO: file Chrome bug, get rid of this
+ this.lens.style.display = 'none';
+ var redrawFix = this.lens.offsetHeight;
+ this.lens.style.display = 'block';
+ }
+ }
+};
+
+
+/**
+ * Adjusts the text magnification.
+ * @private
+ */
+chromevis.ChromeVisLens.prototype.magnifyText_ = function() {
+ var adjustment = (this.multiplier * 100) + '%';
+
+ if (this.lens.firstChild) {
+ if (this.lens.firstChild.hasChildNodes()) {
+ var children = this.lens.firstChild.childNodes;
+
+ for (var i = 0; i < children.length; i++) {
+ children[i].style.fontSize = adjustment;
+ }
+ }
+ }
+};
+
+
+/**
+ * Adjusts the padding around the text inside the lens.
+ * @private
+ */
+chromevis.ChromeVisLens.prototype.padText_ = function() {
+ if (this.padding_ < 0) {
+ return;
+ }
+ this.lens.style.padding_ = this.padding_ + 'px';
+};
+
+
+/**
+ * Sets the text magnification multiplier.
+ */
+chromevis.ChromeVisLens.prototype.setMagnification = function() {
+ this.magnifyText_();
+ this.padText_();
+};
+
+
+/**
+ * Returns the current text size multiplier for magnification.
+ * @return {number} The current text size multiplier.
+ */
+chromevis.ChromeVisLens.prototype.getMagnification = function() {
+ return this.multiplier;
+};
+
+
+/**
+ * Returns the current background color.
+ * @return {string} The lens background color.
+ */
+chromevis.ChromeVisLens.prototype.getBgColor = function() {
+ return this.bgColor;
+};
+
+
+/**
+ * Updates the lens background color.
+ */
+chromevis.ChromeVisLens.prototype.setBgColor = function() {
+ this.lens.style.backgroundColor = this.bgColor;
+};
+
+
+/**
+ * Returns the current text color.
+ * @return {string} The lens text color.
+ */
+chromevis.ChromeVisLens.prototype.getTextColor = function() {
+ return this.textColor;
+};
+
+
+/**
+ * Updates the lens text color.
+ */
+chromevis.ChromeVisLens.prototype.setTextColor = function() {
+ if (this.lens.firstChild) {
+ this.lens.firstChild.style.color = this.textColor;
+ }
+};
Property changes on: chrome/browser/resources/access_chromevox/chromevis/injected/lens.js
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698