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
-->
-
- +
@@ -36,75 +36,56 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=436084 -