Bug 857862 - Fix: selection monocles don't display in content editable elements. r=sfoster

This commit is contained in:
Jim Mathies 2013-07-08 15:45:04 -05:00
parent 0c61c5d790
commit b284bfbd35
4 changed files with 44 additions and 12 deletions

View File

@ -185,6 +185,32 @@ let Util = {
aElement instanceof Ci.nsIDOMHTMLTextAreaElement);
},
isEditableContent: function isEditableContent(aElement) {
if (!aElement)
return false;
if (aElement.isContentEditable || aElement.designMode == "on")
return true;
return false;
},
isEditable: function isEditable(aElement) {
if (!aElement)
return false;
if (this.isTextInput(aElement) || this.isEditableContent(aElement))
return true;
// If a body element is editable and the body is the child of an
// iframe or div we can assume this is an advanced HTML editor
if ((aElement instanceof Ci.nsIDOMHTMLIFrameElement ||
aElement instanceof Ci.nsIDOMHTMLDivElement) &&
aElement.contentDocument &&
this.isEditableContent(aElement.contentDocument.body)) {
return true;
}
return aElement.ownerDocument && aElement.ownerDocument.designMode == "on";
},
isMultilineInput: function isMultilineInput(aElement) {
return (aElement instanceof Ci.nsIDOMHTMLTextAreaElement);
},

View File

@ -291,7 +291,7 @@ let Content = {
this.formAssistant.focusSync = false;
// A tap on a form input triggers touch input caret selection
if (Util.isTextInput(element) &&
if (Util.isEditable(element) &&
aEvent.mozInputSource == Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH) {
let { offsetX, offsetY } = Util.translateToTopLevelWindow(element);
sendAsyncMessage("Content:SelectionCaret", {

View File

@ -224,7 +224,7 @@ var SelectionHandler = {
}
// This should never happen, but we check to make sure
if (!this._targetIsEditable || !Util.isTextInput(this._targetElement)) {
if (!this._targetIsEditable) {
this._onFail("Unexpected, coordiates didn't find a text input element.");
return;
}
@ -402,7 +402,7 @@ var SelectionHandler = {
this._contentWindow = contentWindow;
this._contentOffset = offset;
this._domWinUtils = utils;
this._targetIsEditable = this._isTextInput(this._targetElement);
this._targetIsEditable = Util.isEditable(this._targetElement);
return true;
},
@ -618,12 +618,6 @@ var SelectionHandler = {
};
},
_isTextInput: function _isTextInput(aElement) {
return ((aElement instanceof Ci.nsIDOMHTMLInputElement &&
aElement.mozIsTextField(false)) ||
aElement instanceof Ci.nsIDOMHTMLTextAreaElement);
},
_getDocShell: function _getDocShell(aWindow) {
if (aWindow == null)
return null;

View File

@ -243,7 +243,7 @@ SelectionPrototype.prototype = {
clientPoint.yPos -= halfLineHeight;
// Modify selection based on monocle movement
if (this._targetIsEditable) {
if (this._targetIsEditable && !Util.isEditableContent(this._targetElement)) {
this._adjustEditableSelection(aMarker, clientPoint, aEndOfSelection);
} else {
this._adjustSelectionAtPoint(aMarker, clientPoint, aEndOfSelection);
@ -307,8 +307,7 @@ SelectionPrototype.prototype = {
let cp =
this._contentWindow.document.caretPositionFromPoint(constrainedPoint.xPos,
constrainedPoint.yPos);
if (!cp || (cp.offsetNode != this._targetElement &&
this._contentWindow.document.getBindingParent(cp.offsetNode) != this._targetElement)) {
if (!cp || !this._offsetNodeIsValid(cp.offsetNode)) {
return;
}
if (aMarker == "start") {
@ -319,6 +318,19 @@ SelectionPrototype.prototype = {
}
},
/*
* Make sure caretPositionFromPoint gave us an offset node that equals our
* editable, or in the case of getBindingParent identifies an anonymous
* element in chrome content within our target element. (navbar)
*/
_offsetNodeIsValid: function (aNode) {
if (aNode == this._targetElement ||
this._contentWindow.document.getBindingParent(aNode) == this._targetElement) {
return true;
}
return false;
},
/*
* _adjustSelectionAtPoint
*