Bug 433860 - No spelling suggestions for text inputs when contenteditable node in document; r=gavin

This commit is contained in:
Ehsan Akhgari 2010-06-01 14:08:38 -04:00
parent 9e95234e50
commit d52ae1cb31
4 changed files with 140 additions and 46 deletions

View File

@ -87,7 +87,7 @@ function nsContextMenu(aXulMenu, aBrowser) {
this.isContentSelected = false;
this.shouldDisplay = true;
this.isDesignMode = false;
this.possibleSpellChecking = false;
this.onEditableArea = false;
this.ellipsis = "\u2026";
try {
this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
@ -367,7 +367,7 @@ nsContextMenu.prototype = {
var canSpell = InlineSpellCheckerUI.canSpellCheck;
var onMisspelling = InlineSpellCheckerUI.overMisspelling;
this.showItem("spell-check-enabled", canSpell);
this.showItem("spell-separator", canSpell || this.possibleSpellChecking);
this.showItem("spell-separator", canSpell || this.onEditableArea);
if (canSpell) {
document.getElementById("spell-check-enabled")
.setAttribute("checked", InlineSpellCheckerUI.enabled);
@ -395,7 +395,7 @@ nsContextMenu.prototype = {
InlineSpellCheckerUI.addDictionaryListToMenu(dictMenu, dictSep);
this.showItem("spell-add-dictionaries-main", false);
}
else if (this.possibleSpellChecking) {
else if (this.onEditableArea) {
// when there is no spellchecker but we might be able to spellcheck
// add the add to dictionaries item. This will ensure that people
// with no dictionaries will be able to download them
@ -503,7 +503,7 @@ nsContextMenu.prototype = {
this.inFrame = false;
this.hasBGImage = false;
this.bgImageURL = "";
this.possibleSpellChecking = false;
this.onEditableArea = false;
// Clear any old spellchecking items from the menu, this used to
// be in the menu hiding code but wasn't getting called in all
@ -552,7 +552,7 @@ nsContextMenu.prototype = {
// allow spellchecking UI on all writable text boxes except passwords
if (this.onTextInput && ! this.target.readOnly &&
this.target.type != "password") {
this.possibleSpellChecking = true;
this.onEditableArea = true;
InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
}
@ -561,7 +561,7 @@ nsContextMenu.prototype = {
else if (this.target instanceof HTMLTextAreaElement) {
this.onTextInput = true;
if (!this.target.readOnly) {
this.possibleSpellChecking = true;
this.onEditableArea = true;
InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
}
@ -662,39 +662,41 @@ nsContextMenu.prototype = {
this.inFrame = true;
// if the document is editable, show context menu like in text inputs
var win = this.target.ownerDocument.defaultView;
if (win) {
var isEditable = false;
try {
var editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIEditingSession);
if (editingSession.windowIsEditable(win) &&
this.getComputedStyle(this.target, "-moz-user-modify") == "read-write") {
isEditable = true;
if (!this.onEditableArea) {
var win = this.target.ownerDocument.defaultView;
if (win) {
var isEditable = false;
try {
var editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIEditingSession);
if (editingSession.windowIsEditable(win) &&
this.getComputedStyle(this.target, "-moz-user-modify") == "read-write") {
isEditable = true;
}
}
catch(ex) {
// If someone built with composer disabled, we can't get an editing session.
}
}
catch(ex) {
// If someone built with composer disabled, we can't get an editing session.
}
if (isEditable) {
this.onTextInput = true;
this.onKeywordField = false;
this.onImage = false;
this.onLoadedImage = false;
this.onCompletedImage = false;
this.onMathML = false;
this.inFrame = false;
this.hasBGImage = false;
this.isDesignMode = true;
this.possibleSpellChecking = true;
InlineSpellCheckerUI.init(editingSession.getEditorForWindow(win));
var canSpell = InlineSpellCheckerUI.canSpellCheck;
InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
this.showItem("spell-check-enabled", canSpell);
this.showItem("spell-separator", canSpell);
if (isEditable) {
this.onTextInput = true;
this.onKeywordField = false;
this.onImage = false;
this.onLoadedImage = false;
this.onCompletedImage = false;
this.onMathML = false;
this.inFrame = false;
this.hasBGImage = false;
this.isDesignMode = true;
this.onEditableArea = true;
InlineSpellCheckerUI.init(editingSession.getEditorForWindow(win));
var canSpell = InlineSpellCheckerUI.canSpellCheck;
InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
this.showItem("spell-check-enabled", canSpell);
this.showItem("spell-separator", canSpell);
}
}
}
},

View File

@ -18,6 +18,9 @@ Browser context menu subtest.
<source src="bogus.duh" type="video/durrrr;">
</video>
<iframe id="test-iframe" width="98" height="98" style="border: 1px solid black"></iframe>
<textarea id="test-textarea">chssseesbbbie</textarea> <!-- a weird word which generates only one suggestion -->
<div id="test-contenteditable" contenteditable="true">chssseefsbbbie</div> <!-- a more weird word which generates no suggestions -->
<input id="test-input-spellcheck" type="text" spellcheck="true" autofocus value="prodkjfgigrty"> <!-- this one also generates one suggestion -->
</body>
</html>

View File

@ -49,14 +49,27 @@ function getVisibleMenuItems(aMenu) {
key = key.toLowerCase();
if (item.nodeName == "menuitem") {
ok(item.id, "child menuitem #" + i + " has an ID");
var isSpellSuggestion = item.className == "spell-suggestion";
if (isSpellSuggestion) {
is(item.id, "", "child menuitem #" + i + " is a spelling suggestion");
} else {
ok(item.id, "child menuitem #" + i + " has an ID");
}
ok(item.label.length, "menuitem " + item.id + " has a label");
ok(key, "menuitem " + item.id + " has an access key");
if (accessKeys[key])
ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
else
accessKeys[key] = item.id;
items.push(item.id);
if (isSpellSuggestion) {
is(key, "", "Spell suggestions shouldn't have an access key");
items.push("*" + item.label);
} else if (item.id.indexOf("spell-check-dictionary-") != 0 &&
item.id != "spell-no-suggestions") {
ok(key, "menuitem " + item.id + " has an access key");
if (accessKeys[key])
ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
else
accessKeys[key] = item.id;
}
if (!isSpellSuggestion) {
items.push(item.id);
}
items.push(!item.disabled);
} else if (item.nodeName == "menuseparator") {
ok(true, "--- seperator id is " + item.id);
@ -306,7 +319,78 @@ function runTest(testNum) {
"context-viewsource", true,
"context-viewinfo", true]);
closeContextMenu();
openContextMenuFor(textarea); // Invoke context menu for next test.
break;
case 12:
// Context menu for textarea
checkContextMenu(["*chubbiness", true, // spelling suggestion
"spell-add-to-dictionary", true,
"---", null,
"context-undo", false,
"---", null,
"context-cut", false,
"context-copy", false,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", true,
"---", null,
"spell-check-enabled", true,
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null]);
closeContextMenu();
openContextMenuFor(contenteditable); // Invoke context menu for next test.
break;
case 13:
// Context menu for contenteditable
checkContextMenu(["spell-no-suggestions", false,
"spell-add-to-dictionary", true,
"---", null,
"context-undo", false,
"---", null,
"context-cut", false,
"context-copy", false,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", true,
"---", null,
"spell-check-enabled", true,
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null]);
closeContextMenu();
openContextMenuFor(inputspell); // Invoke context menu for next test.
break;
case 14:
// Context menu for spell-check input
checkContextMenu(["*prodigality", true, // spelling suggestion
"spell-add-to-dictionary", true,
"---", null,
"context-undo", false,
"---", null,
"context-cut", false,
"context-copy", false,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", true,
"---", null,
"spell-check-enabled", true,
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null]);
closeContextMenu();
subwindow.close();
SimpleTest.finish();
return;
@ -331,7 +415,8 @@ function runTest(testNum) {
var testNum = 1;
var subwindow, chromeWin, contextMenu;
var text, link, mailto, input, img, canvas, video, iframe;
var text, link, mailto, input, img, canvas, video, iframe,
textarea, contenteditable, inputspell;
function startTest() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
@ -356,6 +441,9 @@ function startTest() {
video_bad = subwindow.document.getElementById("test-video-bad");
video_bad2 = subwindow.document.getElementById("test-video-bad2");
iframe = subwindow.document.getElementById("test-iframe");
textarea = subwindow.document.getElementById("test-textarea");
contenteditable = subwindow.document.getElementById("test-contenteditable");
inputspell = subwindow.document.getElementById("test-input-spellcheck");
contextMenu.addEventListener("popupshown", function() { runTest(++testNum); }, false);
runTest(1);

View File

@ -218,7 +218,8 @@ InlineSpellChecker.prototype = {
this.mDictionaryNames.push(list[i]);
var item = menu.ownerDocument.createElement("menuitem");
item.setAttribute("label", displayName);
item.setAttribute("id", "spell-check-dictionary-" + list[i]);
item.label = displayName;
item.setAttribute("type", "checkbox");
this.mDictionaryItems.push(item);
if (curlang == list[i]) {