Bug 364914 - Do not spell check the contents of a textarea until it's focused for the first time; r=ehsan

This commit is contained in:
Quentin Headen 2011-10-16 22:06:24 -04:00
parent e4053e0029
commit e85f53bf15
14 changed files with 150 additions and 49 deletions

View File

@ -23,16 +23,33 @@ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
const Cc = Components.classes;
const Ci = Components.interfaces;
function openContextMenuFor(element, shiftkey) {
function openContextMenuFor(element, shiftkey, shouldWaitForFocus) {
// Context menu should be closed before we open it again.
is(contextMenu.state, "closed", "checking if popup is closed");
if (lastElement)
lastElement.blur();
element.focus();
lastElement = element;
var eventDetails = { type : "contextmenu", button : 2, shiftKey : shiftkey };
synthesizeMouse(element, 2, 2, eventDetails, element.ownerDocument.defaultView);
//Some elements need time to focus and spellcheck before any tests are
//run on them.
if(shouldWaitForFocus)
{
if (lastElement)
lastElement.blur();
element.focus();
SimpleTest.executeSoon(function() {
lastElement = element;
var eventDetails = { type : "contextmenu", button : 2, shiftKey : shiftkey };
synthesizeMouse(element, 2, 2, eventDetails, element.ownerDocument.defaultView);
});
}
else
{
if (lastElement)
lastElement.blur();
element.focus();
lastElement = element;
var eventDetails = { type : "contextmenu", button : 2, shiftKey : shiftkey };
synthesizeMouse(element, 2, 2, eventDetails, element.ownerDocument.defaultView);
}
}
function closeContextMenu() {
@ -421,7 +438,7 @@ function runTest(testNum) {
"---", null,
"context-inspect", true]);
closeContextMenu();
openContextMenuFor(textarea); // Invoke context menu for next test.
openContextMenuFor(textarea, false, true); // Invoke context menu for next test, but wait for the spellcheck.
break;
case 12:

View File

@ -1163,6 +1163,10 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
// Use async reflow and painting for text widgets to improve
// performance.
editorFlags |= nsIPlaintextEditor::eEditorUseAsyncUpdatesMask;
// Spell check is diabled at creation time. It is enabled once
// the editor comes into focus.
editorFlags |= nsIPlaintextEditor::eEditorSkipSpellCheck;
bool shouldInitializeEditor = false;
nsCOMPtr<nsIEditor> newEditor; // the editor that we might create

View File

@ -12,7 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338427
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=338427">Mozilla Bug 338427</a>
<p id="display"></p>
<div id="content">
<textarea id="editor" lang="testing-XX"></textarea>
<textarea id="editor" lang="testing-XX" spellcheck="true"></textarea>
</div>
<pre id="test">

View File

@ -77,6 +77,8 @@ interface nsIPlaintextEditor : nsISupports
const long eEditorRightToLeft = 0x2000;
// when this flag is set, the internal direction of the editor is LTR.
const long eEditorLeftToRight = 0x4000;
// when this flag is set, the editor's text content is not spell checked.
const long eEditorSkipSpellCheck = 0x8000;
/*
* The valid values for newlines handling.

View File

@ -396,8 +396,8 @@ protected:
bool CanEnableSpellCheck()
{
// Check for password/readonly/disabled, which are not spellchecked
// regardless of DOM
return !IsPasswordEditor() && !IsReadonly() && !IsDisabled();
// regardless of DOM. Also, check to see if spell check should be skipped or not.
return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() && !ShouldSkipSpellCheck();
}
public:
@ -695,6 +695,11 @@ public:
{
return (mFlags & nsIPlaintextEditor::eEditorDontEchoPassword) != 0;
}
PRBool ShouldSkipSpellCheck() const
{
return (mFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) != 0;
}
bool IsTabbable() const
{

View File

@ -905,6 +905,17 @@ nsEditorEventListener::Focus(nsIDOMEvent* aEvent)
if (mEditor->IsDisabled()) {
return NS_OK;
}
// If the spell check skip flag is still enabled from creation time,
// disable it because focused editors are allowed to spell check.
PRUint32 currentFlags = 0;
mEditor->GetFlags(&currentFlags);
if(currentFlags & nsIPlaintextEditor::eEditorSkipSpellCheck)
{
currentFlags ^= nsIPlaintextEditor::eEditorSkipSpellCheck;
mEditor->SetFlags(currentFlags);
}
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));

View File

@ -64,47 +64,57 @@ function paste(str) {
getEditor().pasteTransferable(trans);
}
function runTest() {
gMisspeltWords = ["haz", "cheezburger"];
is(isSpellingCheckOk(), true, "All misspellings before editing are accounted for.");
function runOnFocus() {
var edit = document.getElementById("edit");
append(" becaz I'm a lolcat!");
edit.removeEventListener("focus", runOnFocus, false);
SimpleTest.executeSoon(function() {
gMisspeltWords.push("becaz");
gMisspeltWords.push("lolcat");
is(isSpellingCheckOk(), true, "All misspellings after typing are accounted for.");
// Now, type an invalid word, and instead of hitting "space" at the end, just blur
// the textarea and see if the spell check after the blur event catches it.
append(" workd");
edit.blur();
gMisspeltWords = ["haz", "cheezburger"];
is(isSpellingCheckOk(), true, "All misspellings before editing are accounted for.");
append(" becaz I'm a lolcat!");
SimpleTest.executeSoon(function() {
gMisspeltWords.push("workd");
is(isSpellingCheckOk(), true, "All misspellings after blur are accounted for.");
gMisspeltWords.push("becaz");
gMisspeltWords.push("lolcat");
is(isSpellingCheckOk(), true, "All misspellings after typing are accounted for.");
// Also, test the case when we're entering the first word in a textarea
gMisspeltWords = ["workd"];
edit.value = "";
append("workd ");
// Now, type an invalid word, and instead of hitting "space" at the end, just blur
// the textarea and see if the spell check after the blur event catches it.
append(" workd");
edit.blur();
SimpleTest.executeSoon(function() {
is(isSpellingCheckOk(), true, "Misspelling in the first entered word is accounted for.");
gMisspeltWords.push("workd");
is(isSpellingCheckOk(), true, "All misspellings after blur are accounted for.");
// Make sure that pasting would also trigger spell checking for the previous word
// Also, test the case when we're entering the first word in a textarea
gMisspeltWords = ["workd"];
edit.value = "";
append("workd");
paste(" x");
append("workd ");
SimpleTest.executeSoon(function() {
is(isSpellingCheckOk(), true, "Misspelling is accounted for after pasting.");
is(isSpellingCheckOk(), true, "Misspelling in the first entered word is accounted for.");
SimpleTest.finish();
// Make sure that pasting would also trigger spell checking for the previous word
gMisspeltWords = ["workd"];
edit.value = "";
append("workd");
paste(" x");
SimpleTest.executeSoon(function() {
is(isSpellingCheckOk(), true, "Misspelling is accounted for after pasting.");
SimpleTest.finish();
});
});
});
});
});
}
function runTest()
{
var edit = document.getElementById("edit");
edit.addEventListener("focus", runOnFocus, false);
edit.focus();
}
function isSpellingCheckOk() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");

View File

@ -30,16 +30,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=636465
SimpleTest.waitForExplicitFinish();
function runTest() {
var x = document.getElementById("x");
x.focus();
setTimeout(function(){
x.blur();
setTimeout(function(){
var x = document.getElementById("x");
var spellCheckTrue = snapshotWindow(window);
x.setAttribute("spellcheck", "false");
setTimeout(function(){
setTimeout(function(){
var spellCheckFalse = snapshotWindow(window);
x.setAttribute("spellcheck", "true");
x.focus();
setTimeout(function(){
x.blur();
setTimeout(function(){
var spellCheckTrueAgain = snapshotWindow(window);
x.removeAttribute("spellcheck");

View File

@ -18,18 +18,32 @@ needs-focus == passwd-4.html passwd-ref.html
== emptypasswd-2.html emptypasswd-ref.html
== caret_on_positioned.html caret_on_positioned-ref.html
fails-if(Android) != spellcheck-input-disabled.html spellcheck-input-ref.html
== spellcheck-input-attr-before.html spellcheck-input-ref.html
== spellcheck-input-attr-after.html spellcheck-input-ref.html
== spellcheck-input-attr-inherit.html spellcheck-input-ref.html
== spellcheck-input-attr-dynamic.html spellcheck-input-ref.html
== spellcheck-input-attr-dynamic-inherit.html spellcheck-input-ref.html
== spellcheck-input-property-dynamic.html spellcheck-input-ref.html
== spellcheck-input-property-dynamic-inherit.html spellcheck-input-ref.html
== spellcheck-input-attr-dynamic-override.html spellcheck-input-ref.html
== spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-ref.html
== spellcheck-input-property-dynamic-override.html spellcheck-input-ref.html
== spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-ref.html
== spellcheck-textarea-attr.html spellcheck-textarea-ref.html
== spellcheck-input-attr-before.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-attr-before.html spellcheck-input-ref.html
== spellcheck-input-attr-after.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-attr-after.html spellcheck-input-ref.html
== spellcheck-input-attr-inherit.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-attr-inherit.html spellcheck-input-ref.html
== spellcheck-input-attr-dynamic.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-attr-dynamic.html spellcheck-input-ref.html
== spellcheck-input-attr-dynamic-inherit.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-attr-dynamic-inherit.html spellcheck-input-ref.html
== spellcheck-input-property-dynamic.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-property-dynamic.html spellcheck-input-ref.html
== spellcheck-input-property-dynamic-inherit.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-property-dynamic-inherit.html spellcheck-input-ref.html
== spellcheck-input-attr-dynamic-override.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-attr-dynamic-override.html spellcheck-input-ref.html
== spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-ref.html
== spellcheck-input-property-dynamic-override.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-property-dynamic-override.html spellcheck-input-ref.html
== spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-nofocus-ref.html
!= spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-ref.html
== spellcheck-textarea-attr.html spellcheck-textarea-nofocus-ref.html
!= spellcheck-textarea-attr.html spellcheck-textarea-ref.html
== spellcheck-textarea-focused.html spellcheck-textarea-ref.html
!= spellcheck-textarea-nofocus.html spellcheck-textarea-ref.html
fails-if(Android) != spellcheck-textarea-disabled.html spellcheck-textarea-ref.html
fails-if(Android) != spellcheck-textarea-attr-inherit.html spellcheck-textarea-ref.html
fails-if(Android) != spellcheck-textarea-attr-dynamic.html spellcheck-textarea-ref.html

View File

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
<input type="text" value="blahblahblah" spellcheck="true">
</body>
</html>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<textarea id="testBox">blahblahblah</textarea>
<script type="text/javascript">
//Adding focus to the textbox should trigger a spellcheck
document.getElementById("testBox").focus();
</script>
</body>
</html>

View File

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
<textarea spellcheck="true">blahblahblah</textarea>
</body>
</html>

View File

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
<textarea>blahblahblah</textarea>
</body>
</html>

View File

@ -2,5 +2,9 @@
<html>
<body>
<textarea spellcheck="true">blahblahblah</textarea>
<script type="text/javascript">
var box = document.getElementsByTagName("textarea")[0];
box.focus(); //Bring the textbox into focus, triggering a spellcheck
</script>
</body>
</html>