diff --git a/toolkit/spatial-navigation/SpatialNavigation.js b/toolkit/spatial-navigation/SpatialNavigation.js index 682a0e10512..0bca6a7fe18 100644 --- a/toolkit/spatial-navigation/SpatialNavigation.js +++ b/toolkit/spatial-navigation/SpatialNavigation.js @@ -35,7 +35,7 @@ * ***** END LICENSE BLOCK ***** */ /** - * + * * Import this module through * * Components.utils.import("resource://gre/modules/SpatialNavigation.js"); @@ -58,7 +58,7 @@ var SpatialNavigation = { init: function(browser, callback) { browser.addEventListener("keypress", function (event) { _onInputKeyPress(event, callback) }, true); }, - + uninit: function() { } }; @@ -119,34 +119,62 @@ function _onInputKeyPress (event, callback) { if (!PrefObserver['xulContentEnabled'] && doc instanceof Ci.nsIDOMXULDocument) return ; - // check to see if we are in a textarea or text input element, and if so, + // Check to see if we are in a textarea or text input element, and if so, // ensure that we let the arrow keys work properly. if (target instanceof Ci.nsIDOMHTMLHtmlElement) { _focusNextUsingCmdDispatcher(key, callback); return; } - if ((target instanceof Ci.nsIDOMHTMLInputElement && (target.type == "text" || target.type == "password")) || - target instanceof Ci.nsIDOMHTMLTextAreaElement ) { - - // if there is any selection at all, just ignore - if (target.selectionEnd - target.selectionStart > 0) - return; - - // if there is no text, there is nothing special to do. - if (target.textLength > 0) { - if (key == PrefObserver['keyCodeRight'] || - key == PrefObserver['keyCodeDown'] ) { - // we are moving forward into the document - if (target.textLength != target.selectionEnd) + // If it is a single-line input fields ... + if (target instanceof Ci.nsIDOMHTMLInputElement && + (target.type == "text" || target.type == "password")) { + + // Up/Down should not care and just move. However, Right/Left + // should check the following before move. + if (key != PrefObserver['keyCodeUp'] && + key != PrefObserver['keyCodeDown']) { + + // If there is any selection at all, then do not move. + if (target.selectionEnd - target.selectionStart > 0) + return; + + // If there is text, check if it is okay to move. + if (target.textLength > 0) { + // Cursor not at the beginning. + if (key == PrefObserver['keyCodeLeft'] && + target.selectionStart != 0) + return; + + // Cursor not at the end. + if (key == PrefObserver['keyCodeRight'] && + target.textLength != target.selectionEnd) return; } - else - { - // we are at the start of the text, okay to move + } + } + // If it is a multi-line input field ... + else if (target instanceof Ci.nsIDOMHTMLTextAreaElement) { + + // If there is any selection at all, again just ignore + if (target.selectionEnd - target.selectionStart > 0) + return; + + // If there is text, there check if it is okay to move. + if (target.textLength > 0) { + if (key == PrefObserver['keyCodeUp'] || + key == PrefObserver['keyCodeLeft']) { + // Cursor not at the beginning. if (target.selectionStart != 0) return; } + else { + if (key == PrefObserver['keyCodeDown'] || + key == PrefObserver['keyCodeRight']) + // Cursor not at the end. + if (target.selectionEnd != target.textLength) + return; + } } } @@ -173,7 +201,7 @@ function _onInputKeyPress (event, callback) { return Ci.nsIDOMNodeFilter.FILTER_SKIP; return Ci.nsIDOMNodeFilter.FILTER_ACCEPT; } - + if ((node instanceof Ci.nsIDOMHTMLButtonElement || node instanceof Ci.nsIDOMHTMLInputElement || node instanceof Ci.nsIDOMHTMLLinkElement || @@ -182,7 +210,7 @@ function _onInputKeyPress (event, callback) { node instanceof Ci.nsIDOMHTMLTextAreaElement) && node.disabled == false) return Ci.nsIDOMNodeFilter.FILTER_ACCEPT; - + return Ci.nsIDOMNodeFilter.FILTER_SKIP; } @@ -193,7 +221,7 @@ function _onInputKeyPress (event, callback) { var treeWalker = doc.createTreeWalker(doc, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, snavfilter, false); var nextNode; - + while ((nextNode = treeWalker.nextNode())) { if (nextNode == target) @@ -208,13 +236,13 @@ function _onInputKeyPress (event, callback) { var distance = _spatialDistance(key, focusedRect, nextRect); //dump("looking at: " + nextNode + " " + distance); - + if (distance <= distanceToBestElement && distance > 0) { distanceToBestElement = distance; bestElementToFocus = nextNode; } } - + if (bestElementToFocus != null) { //dump("focusing element " + bestElementToFocus.nodeName + " " + bestElementToFocus) + "id=" + bestElementToFocus.getAttribute("id"); @@ -230,7 +258,7 @@ function _onInputKeyPress (event, callback) { if (callback != undefined) callback(bestElementToFocus); - + } else { // couldn't find anything. just advance and hope. _focusNextUsingCmdDispatcher(key, callback); @@ -278,7 +306,7 @@ function _isRectInDirection(key, focusedRect, anotherRect) function _inflateRect(rect, value) { var newRect = new Object(); - + newRect.left = rect.left - value; newRect.top = rect.top - value; newRect.right = rect.right + value; @@ -310,7 +338,7 @@ function _spatialDistance(key, a, b) // |---| // |---| // - + if (a.top > b.bottom) { // the b rect is above a. mx = a.left; @@ -323,7 +351,7 @@ function _spatialDistance(key, a, b) mx = a.left; my = a.bottom; nx = b.right; - ny = b.top; + ny = b.top; } else { mx = a.left; @@ -342,7 +370,7 @@ function _spatialDistance(key, a, b) // |---| // |---| // - + if (a.top > b.bottom) { // the b rect is above a. mx = a.right; @@ -355,7 +383,7 @@ function _spatialDistance(key, a, b) mx = a.right; my = a.bottom; nx = b.left; - ny = b.top; + ny = b.top; } else { mx = a.right; my = 0; @@ -370,7 +398,7 @@ function _spatialDistance(key, a, b) // |---| // |---| // - + if (a.left > b.right) { // the b rect is to the left of a. mx = a.left; @@ -382,7 +410,7 @@ function _spatialDistance(key, a, b) mx = a.right; my = a.top; nx = b.left; - ny = b.bottom; + ny = b.bottom; } else { // both b and a share some common x's. mx = 0; @@ -398,7 +426,7 @@ function _spatialDistance(key, a, b) // |---| |---| |---| // |---| |---| |---| // - + if (a.left > b.right) { // the b rect is to the left of a. mx = a.left; @@ -410,7 +438,7 @@ function _spatialDistance(key, a, b) mx = a.right; my = a.bottom; nx = b.left; - ny = b.top; + ny = b.top; } else { // both b and a share some common x's. mx = 0; @@ -419,7 +447,7 @@ function _spatialDistance(key, a, b) ny = b.top; } } - + var scopedRect = _inflateRect(a, gRectFudge); if (key == PrefObserver['keyCodeLeft'] || @@ -434,13 +462,13 @@ function _spatialDistance(key, a, b) 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; } diff --git a/toolkit/spatial-navigation/tests/Makefile.in b/toolkit/spatial-navigation/tests/Makefile.in index 97bc9e9bfdc..fd1568bd7bd 100644 --- a/toolkit/spatial-navigation/tests/Makefile.in +++ b/toolkit/spatial-navigation/tests/Makefile.in @@ -50,11 +50,10 @@ MOCHI_TESTS = chrome/test_snav.xul \ chrome/test_snav_selects.xul \ chrome/test_snav_prefDisabled.xul \ chrome/test_snav_prefKeyCode.xul \ + chrome/test_snav_textFields.xul \ chrome/SpatialNavUtils.js \ $(NULL) -# bug 447671 chrome/test_snav_textFields.xul \ - include $(topsrcdir)/config/rules.mk libs:: $(MOCHI_TESTS) $(MOCHI_CONTENT) diff --git a/toolkit/spatial-navigation/tests/chrome/test_snav_textFields.xul b/toolkit/spatial-navigation/tests/chrome/test_snav_textFields.xul index 470e847e154..e2ed0ef48ef 100644 --- a/toolkit/spatial-navigation/tests/chrome/test_snav_textFields.xul +++ b/toolkit/spatial-navigation/tests/chrome/test_snav_textFields.xul @@ -6,14 +6,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=436084 --> - + @@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=436084

- +

@@ -36,75 +36,56 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=436084 -