Bug 947505 - Right-click in a designMode document should display a context menu. r=mbrubeck, r=sfoster

This commit is contained in:
Aleh Zasypkin 2014-01-17 10:47:02 +01:00
parent 60f2a41803
commit 0d63994188
3 changed files with 107 additions and 11 deletions

View File

@ -83,19 +83,25 @@ let Util = {
aElement instanceof Ci.nsIDOMHTMLTextAreaElement);
},
/**
* Checks whether aElement's content can be edited either if it(or any of its
* parents) has "contenteditable" attribute set to "true" or aElement's
* ownerDocument is in design mode.
*/
isEditableContent: function isEditableContent(aElement) {
if (!aElement)
return false;
if (aElement.isContentEditable || aElement.designMode == "on")
return true;
return false;
return !!aElement && (aElement.isContentEditable ||
this.isOwnerDocumentInDesignMode(aElement));
},
isEditable: function isEditable(aElement) {
if (!aElement)
if (!aElement) {
return false;
if (this.isTextInput(aElement) || this.isEditableContent(aElement))
}
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
@ -106,7 +112,15 @@ let Util = {
return true;
}
return aElement.ownerDocument && aElement.ownerDocument.designMode == "on";
return false;
},
/**
* Checks whether aElement's owner document has design mode turned on.
*/
isOwnerDocumentInDesignMode: function(aElement) {
return !!aElement && !!aElement.ownerDocument &&
aElement.ownerDocument.designMode == "on";
},
isMultilineInput: function isMultilineInput(aElement) {

View File

@ -105,6 +105,8 @@ var ContextMenuHandler = {
if (Util.isTextInput(this._target)) {
// select all text in the input control
this._target.select();
} else if (Util.isEditableContent(this._target)) {
this._target.ownerDocument.execCommand("selectAll", false);
} else {
// select the entire document
content.getSelection().selectAllChildren(content.document);
@ -121,7 +123,7 @@ var ContextMenuHandler = {
} else {
Util.dumpLn("error: target element does not support nsIDOMNSEditableElement");
}
} else if (this._target.isContentEditable) {
} else if (Util.isEditableContent(this._target)) {
try {
this._target.ownerDocument.execCommand("paste",
false,
@ -145,7 +147,7 @@ var ContextMenuHandler = {
} else {
Util.dumpLn("error: target element does not support nsIDOMNSEditableElement");
}
} else if (this._target.isContentEditable) {
} else if (Util.isEditableContent(this._target)) {
try {
this._target.ownerDocument.execCommand("cut", false);
} catch (ex) {
@ -259,7 +261,9 @@ var ContextMenuHandler = {
break;
}
// is the target contentEditable (not just inheriting contentEditable)
else if (elem.contentEditable == "true") {
// or the entire document in designer mode.
else if (elem.contentEditable == "true" ||
Util.isOwnerDocumentInDesignMode(elem)) {
this._target = elem;
isEditableText = true;
isText = true;

View File

@ -709,6 +709,84 @@ gTests.push({
run: getReopenTest(sendContextMenuClickToElement, sendTap)
});
gTests.push({
desc: "Bug 947505 - Right-click in a designMode document should display a " +
"context menu",
run: function test() {
info(chromeRoot + "browser_context_menu_tests_02.html");
yield addTab(chromeRoot + "browser_context_menu_tests_02.html");
purgeEventQueue();
emptyClipboard();
ContextUI.dismiss();
yield waitForCondition(() => !ContextUI.navbarVisible);
let tabWindow = Browser.selectedTab.browser.contentWindow;
let testSpan = tabWindow.document.getElementById("text1");
// Case #1: Document isn't in design mode and nothing is selected.
tabWindow.document.designMode = "off";
// Simulate right mouse click to reproduce the same step as noted in the
// appropriate bug. It's valid for non-touch case only.
synthesizeNativeMouseRDown(Browser.selectedTab.browser, 10, 10);
synthesizeNativeMouseRUp(Browser.selectedTab.browser, 10, 10);
yield waitForCondition(() => ContextUI.navbarVisible);
ok(ContextUI.navbarVisible, "Navbar is visible on context menu action.");
ok(ContextUI.tabbarVisible, "Tabbar is visible on context menu action.");
ContextUI.dismiss();
yield waitForCondition(() => !ContextUI.navbarVisible);
// Case #2: Document isn't in design mode and text is selected.
tabWindow.getSelection().selectAllChildren(testSpan);
let promise = waitForEvent(tabWindow.document, "popupshown");
sendContextMenuClickToSelection(tabWindow);
yield promise;
checkContextUIMenuItemVisibility(["context-copy", "context-search"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
// Case #3: Document is in design mode and nothing is selected.
tabWindow.document.designMode = "on";
tabWindow.getSelection().removeAllRanges();
promise = waitForEvent(tabWindow.document, "popupshown");
sendContextMenuClickToElement(tabWindow, testSpan);
yield promise;
checkContextUIMenuItemVisibility(["context-select-all", "context-select"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
// Case #4: Document is in design mode and text is selected.
tabWindow.getSelection().selectAllChildren(testSpan);
promise = waitForEvent(tabWindow.document, "popupshown");
sendContextMenuClickToSelection(tabWindow);
yield promise;
checkContextUIMenuItemVisibility(["context-cut", "context-copy",
"context-select-all", "context-select",
"context-search"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
Browser.closeTab(Browser.selectedTab, { forceClose: true });
}
});
function test() {
setDevPixelEqualToPx();
runTests();