Bug 1023418 - (p0) Auto-selecting a phone number does not stop at element breaks, r=mfinkle

This commit is contained in:
Mark Capella 2014-07-30 11:29:54 -04:00
Родитель c1f48dce0b
Коммит 7449ef9663
1 изменённых файлов: 78 добавлений и 37 удалений

Просмотреть файл

@ -4,6 +4,9 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Define elements that bound phone number containers.
const PHONE_NUMBER_CONTAINERS = "td,div";
var SelectionHandler = {
HANDLE_TYPE_START: "START",
HANDLE_TYPE_MIDDLE: "MIDDLE",
@ -317,42 +320,6 @@ var SelectionHandler = {
return false;
}
if (this._isPhoneNumber(selection.toString())) {
let anchorNode = selection.anchorNode;
let anchorOffset = selection.anchorOffset;
let focusNode = null;
let focusOffset = null;
while (this._isPhoneNumber(selection.toString().trim())) {
focusNode = selection.focusNode;
focusOffset = selection.focusOffset;
selection.modify("extend", "forward", "word");
// if we hit the end of the text on the page, we can't advance the selection
if (focusNode == selection.focusNode && focusOffset == selection.focusOffset) {
break;
}
}
// reverse selection
selection.collapse(focusNode, focusOffset);
selection.extend(anchorNode, anchorOffset);
anchorNode = focusNode;
anchorOffset = focusOffset
while (this._isPhoneNumber(selection.toString().trim())) {
focusNode = selection.focusNode;
focusOffset = selection.focusOffset;
selection.modify("extend", "backward", "word");
// if we hit the end of the text on the page, we can't advance the selection
if (focusNode == selection.focusNode && focusOffset == selection.focusOffset) {
break;
}
}
selection.collapse(focusNode, focusOffset);
selection.extend(anchorNode, anchorOffset);
}
// Add a listener to end the selection if it's removed programatically
selection.QueryInterface(Ci.nsISelectionPrivate).addSelectionListener(this);
this._activeType = this.TYPE_SELECTION;
@ -389,7 +356,16 @@ var SelectionHandler = {
if (aOptions.mode == this.SELECT_AT_POINT) {
// Clear any ranges selected outside SelectionHandler, by code such as Find-In-Page.
this._contentWindow.getSelection().removeAllRanges();
return this._domWinUtils.selectAtPoint(aOptions.x, aOptions.y, Ci.nsIDOMWindowUtils.SELECT_WORDNOSPACE);
if (!this._domWinUtils.selectAtPoint(aOptions.x, aOptions.y, Ci.nsIDOMWindowUtils.SELECT_WORDNOSPACE)) {
return false;
}
// Perform additional phone-number "smart selection".
if (this._isPhoneNumber(this._getSelection().toString())) {
this._selectSmartPhoneNumber();
}
return true;
}
if (aOptions.mode != this.SELECT_ALL) {
@ -429,6 +405,71 @@ var SelectionHandler = {
return true;
},
/*
* Called to expand a selection that appears to represent a phone number. This enhances the basic
* SELECT_WORDNOSPACE logic employed in performSelection() in response to long-tap / selecting text.
*/
_selectSmartPhoneNumber: function() {
this._extendPhoneNumberSelection("forward");
this._reversePhoneNumberSelectionDir();
this._extendPhoneNumberSelection("backward");
this._reversePhoneNumberSelectionDir();
},
/*
* Extend the current phone number selection in the requested direction.
*/
_extendPhoneNumberSelection: function(direction) {
let selection = this._getSelection();
// Extend the phone number selection until we find a boundry.
while (true) {
// Save current focus position, and extend the selection.
let focusNode = selection.focusNode;
let focusOffset = selection.focusOffset;
selection.modify("extend", direction, "character");
// If the selection doesn't change, (can't extend further), we're done.
if (selection.focusNode == focusNode && selection.focusOffset == focusOffset) {
return;
}
// Don't extend past a valid phone number.
if (!this._isPhoneNumber(selection.toString().trim())) {
// Backout the undesired selection extend, and we're done.
selection.collapse(selection.anchorNode, selection.anchorOffset);
selection.extend(focusNode, focusOffset);
return;
}
// Don't extend the selection into a new container.
if (selection.focusNode != focusNode) {
let nextContainer = (selection.focusNode instanceof Text) ?
selection.focusNode.parentNode : selection.focusNode;
if (nextContainer.mozMatchesSelector &&
nextContainer.mozMatchesSelector(PHONE_NUMBER_CONTAINERS)) {
// Backout the undesired selection extend, and we're done.
selection.collapse(selection.anchorNode, selection.anchorOffset);
selection.extend(focusNode, focusOffset);
return
}
}
}
},
/*
* Reverse the the selection direction, swapping anchorNode <-+-> focusNode.
*/
_reversePhoneNumberSelectionDir: function(direction) {
let selection = this._getSelection();
let anchorNode = selection.anchorNode;
let anchorOffset = selection.anchorOffset;
selection.collapse(selection.focusNode, selection.focusOffset);
selection.extend(anchorNode, anchorOffset);
},
/* Return true if the current selection (given by aPositions) is near to where the coordinates passed in */
_selectionNearClick: function(aX, aY, aPositions) {
let distance = 0;