Bug 960203 - Allow text selection handles to crossover in <input> and <textarea> elements. r=mleibovic
--- a/mobile/android/chrome/content/SelectionHandler.js
+++ b/mobile/android/chrome/content/SelectionHandler.js
@@ -556,16 +556,33 @@ var SelectionHandler = {
return (this._activeType == this.TYPE_SELECTION);
},
selectAll: function sh_selectAll(aElement) {
this.startSelection(aElement, { mode : this.SELECT_ALL });
},
/*
+ * Helper function for moving the selection inside an editable element.
+ *
+ * @param aAnchorX the stationary handle's x-coordinate in client coordinates
+ * @param aX the moved handle's x-coordinate in client coordinates
+ * @param aCaretPos the current position of the caret
+ */
+ _moveSelectionInEditable: function sh_moveSelectionInEditable(aAnchorX, aX, aCaretPos) {
+ let anchorOffset = aX < aAnchorX ? this._targetElement.selectionEnd
+ : this._targetElement.selectionStart;
+ let newOffset = aCaretPos.offset;
+ let [start, end] = anchorOffset <= newOffset ?
+ [anchorOffset, newOffset] :
+ [newOffset, anchorOffset];
+ this._targetElement.setSelectionRange(start, end);
+ },
+
+ /*
* Moves the selection as the user drags a selection handle.
*
* @param aIsStartHandle whether the user is moving the start handle (as opposed to the end handle)
* @param aX, aY selection point in client coordinates
*/
_moveSelection: function sh_moveSelection(aIsStartHandle, aX, aY) {
// XXX We should be smarter about the coordinates we pass to caretPositionFromPoint, especially
// in editable targets. We should factor out the logic that's currently in _sendMouseEvents.
@@ -592,28 +609,28 @@ var SelectionHandler = {
}
let selection = this._getSelection();
// The handles work the same on both LTR and RTL pages, but the anchor/focus nodes
// are reversed, so we need to reverse the logic to extend the selection.
if ((aIsStartHandle && !this._isRTL) || (!aIsStartHandle && this._isRTL)) {
if (targetIsEditable) {
- // XXX This will just collapse the selection if the start handle goes past the end handle.
- this._targetElement.selectionStart = caretPos.offset;
+ let anchorX = this._isRTL ? this._cache.start.x : this._cache.end.x;
+ this._moveSelectionInEditable(anchorX, aX, caretPos);
} else {
let focusNode = selection.focusNode;
let focusOffset = selection.focusOffset;
selection.collapse(caretPos.offsetNode, caretPos.offset);
selection.extend(focusNode, focusOffset);
}
} else {
if (targetIsEditable) {
- // XXX This will just collapse the selection if the end handle goes past the start handle.
- this._targetElement.selectionEnd = caretPos.offset;
+ let anchorX = this._isRTL ? this._cache.end.x : this._cache.start.x;
+ this._moveSelectionInEditable(anchorX, aX, caretPos);
} else {
selection.extend(caretPos.offsetNode, caretPos.offset);
}
}
},
_sendMouseEvents: function sh_sendMouseEvents(aX, aY, useShift) {
// If we're positioning a cursor in an input field, make sure the handle