diff --git a/toolkit/spatial-navigation/spatial-navigation.js b/toolkit/spatial-navigation/spatial-navigation.js deleted file mode 100644 index 09f9032ece06..000000000000 --- a/toolkit/spatial-navigation/spatial-navigation.js +++ /dev/null @@ -1,344 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Spatial Navigation. - * - * The Initial Developer of the Original Code is Mozilla Corporation - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Doug Turner (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/** - * - * Import this module through - * - * Components.utils.import("resource://gre/modules/spatial-navigation.js"); - * - * Usage: - * - * - * var snav = new SpatialNavigation(browser_element, optional_callback); - * - * optional_callback will be called when a new element is focused. - * - * function optional_callback(element) {} - * - */ - - -var EXPORTED_SYMBOLS = ["SpatialNavigation"]; - -function SpatialNavigation (browser, callback) -{ - browser.addEventListener("keypress", function (event) { _onInputKeyPress(event, callback) }, true); -}; - -SpatialNavigation.prototype = { -}; - - -// Private stuff - -const Cc = Components.classes; -const Ci = Components.interfaces; - -function dump(msg) -{ - var console = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService); - console.logStringMessage("*** SNAV: " + msg); -} - -var gDirectionalBias = 10; -var gRectFudge = 1; - -function _onInputKeyPress (event, callback) { - - // If it isn't an arrow key, bail. - if (event.keyCode != event.DOM_VK_LEFT && - event.keyCode != event.DOM_VK_RIGHT && - event.keyCode != event.DOM_VK_UP && - event.keyCode != event.DOM_VK_DOWN ) - return; - - function snavfilter(node) { - - if (node instanceof Ci.nsIDOMHTMLLinkElement || - node instanceof Ci.nsIDOMHTMLAnchorElement) { - // if a anchor doesn't have a href, don't target it. - if (node.href == "") - return Ci.nsIDOMNodeFilter.FILTER_SKIP; - return Ci.nsIDOMNodeFilter.FILTER_ACCEPT; - } - - if (node instanceof Ci.nsIDOMHTMLInputElement || - node instanceof Ci.nsIDOMHTMLSelectElement || - node instanceof Ci.nsIDOMHTMLOptionElement) - return Ci.nsIDOMNodeFilter.FILTER_ACCEPT; - return Ci.nsIDOMNodeFilter.FILTER_SKIP; - } - var bestElementToFocus = null; - var distanceToBestElement = Infinity; - var focusedRect = _inflateRect(event.target.getBoundingClientRect(), - - gRectFudge); - var doc = event.target.ownerDocument; - - var treeWalker = doc.createTreeWalker(doc, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, snavfilter, false); - var nextNode; - - while ((nextNode = treeWalker.nextNode())) { - - if (nextNode == event.target) - continue; - - var nextRect = _inflateRect(nextNode.getBoundingClientRect(), - - gRectFudge); - - if (! _isRectInDirection(event, focusedRect, nextRect)) - continue; - - var distance = _spatialDistance(event, focusedRect, nextRect); - - if (distance <= distanceToBestElement && distance > 0) { - distanceToBestElement = distance; - bestElementToFocus = nextNode; - } - } - - if (bestElementToFocus != null) { - // dump("focusing element " + bestElementToFocus.nodeName + " " + bestElementToFocus); - // Wishing we could do element.focus() - doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).focus(bestElementToFocus); - - if (callback != undefined) - callback(bestElementToFocus); - - } else { - // couldn't find anything. just advance and hope. - // dump("advancing focus"); - var windowMediator = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator); - var window = windowMediator.getMostRecentWindow("navigator:browser"); - window.document.commandDispatcher.advanceFocus(); - - if (callback != undefined) - callback(null); - } - - event.preventDefault(); - event.stopPropagation(); -} - -function _isRectInDirection(event, focusedRect, anotherRect) -{ - if (event.keyCode == event.DOM_VK_LEFT) { - return (anotherRect.left < focusedRect.left); - } - - if (event.keyCode == event.DOM_VK_RIGHT) { - return (anotherRect.right > focusedRect.right); - } - - if (event.keyCode == event.DOM_VK_UP) { - return (anotherRect.top < focusedRect.top); - } - - if (event.keyCode == event.DOM_VK_DOWN) { - return (anotherRect.bottom > focusedRect.bottom); - } - return false; -} - -function _inflateRect(rect, value) -{ - var newRect = new Object(); - - newRect.left = rect.left - value; - newRect.top = rect.top - value; - newRect.right = rect.right + value; - newRect.bottom = rect.bottom + value; - return newRect; -} - -function _containsRect(a, b) -{ - return ( (b.left <= a.right) && - (b.right >= a.left) && - (b.top <= a.bottom) && - (b.bottom >= a.top) ); -} - -function _spatialDistance(event, a, b) -{ - var inlineNavigation = false; - var mx, my, nx, ny; - - if (event.keyCode == event.DOM_VK_LEFT) { - - // |---| - // |---| - // - // |---| |---| - // |---| |---| - // - // |---| - // |---| - // - - if (a.top > b.bottom) { - // the b rect is above a. - mx = a.left; - my = a.top; - nx = b.right; - ny = b.bottom; - } - else if (a.bottom < b.top) { - // the b rect is below a. - mx = a.left; - my = a.bottom; - nx = b.right; - ny = b.top; - } - else { - mx = a.left; - my = 0; - nx = b.right; - ny = 0; - } - } else if (event.keyCode == event.DOM_VK_RIGHT) { - - // |---| - // |---| - // - // |---| |---| - // |---| |---| - // - // |---| - // |---| - // - - if (a.top > b.bottom) { - // the b rect is above a. - mx = a.right; - my = a.top; - nx = b.left; - ny = b.bottom; - } - else if (a.bottom < b.top) { - // the b rect is below a. - mx = a.right; - my = a.bottom; - nx = b.left; - ny = b.top; - } else { - mx = a.right; - my = 0; - nx = b.left; - ny = 0; - } - } else if (event.keyCode == event.DOM_VK_UP) { - - // |---| |---| |---| - // |---| |---| |---| - // - // |---| - // |---| - // - - if (a.left > b.right) { - // the b rect is to the left of a. - mx = a.left; - my = a.top; - nx = b.right; - ny = b.bottom; - } else if (a.right < b.left) { - // the b rect is to the right of a - mx = a.right; - my = a.top; - nx = b.left; - ny = b.bottom; - } else { - // both b and a share some common x's. - mx = 0; - my = a.top; - nx = 0; - ny = b.bottom; - } - } else if (event.keyCode == event.DOM_VK_DOWN) { - - // |---| - // |---| - // - // |---| |---| |---| - // |---| |---| |---| - // - - if (a.left > b.right) { - // the b rect is to the left of a. - mx = a.left; - my = a.bottom; - nx = b.right; - ny = b.top; - } else if (a.right < b.left) { - // the b rect is to the right of a - mx = a.right; - my = a.bottom; - nx = b.left; - ny = b.top; - } else { - // both b and a share some common x's. - mx = 0; - my = a.bottom; - nx = 0; - ny = b.top; - } - } - - var scopedRect = _inflateRect(a, gRectFudge); - - if (event.keyCode == event.DOM_VK_LEFT || - event.keyCode == event.DOM_VK_RIGHT) { - scopedRect.left = 0; - scopedRect.right = Infinity; - inlineNavigation = _containsRect(scopedRect, b); - } - else if (event.keyCode == event.DOM_VK_UP || - event.keyCode == event.DOM_VK_DOWN) { - scopedRect.top = 0; - scopedRect.bottom = Infinity; - inlineNavigation = _containsRect(scopedRect, b); - } - - var d = Math.pow((mx-nx), 2) + Math.pow((my-ny), 2); - - // prefer elements directly aligned with the focused element - if (inlineNavigation) - d /= gDirectionalBias; - - return d; -} -