Bug 48418

Summary: @spellcheck attribute at the child of contentEditable node is ignored.
Product: WebKit Reporter: Hajime Morrita <morrita>
Component: HTML EditingAssignee: Hajime Morrita <morrita>
Status: RESOLVED FIXED    
Severity: Normal CC: eric, jiapu.mail, ojan
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: PC   
OS: All   
Attachments:
Description Flags
repro
none
Patch
none
Patch
none
Patch
none
removed 'parent' from test
none
Patch tkent: review+

Hajime Morrita
Reported 2010-10-27 05:00:37 PDT
Created attachment 72013 [details] repro @spellcheck attribute is ignored when it is given at the node ascendant of the contentEditable element (not the contentEditable element itself.) <div contentEditable="true"> <div>Here is spellcheck=true: [<span spellcheck="true" >test should be checked here.</span>]</div> <div>Here is spellcheck=false: [<span spellcheck="false">text should NOT be checked here, but does.</span>]</div> </div> Currently @spellcheck is checked against focused node, which is an editable root at the case of rich text editing (not form.) We should check the node under the selection(caret) at that case.
Attachments
repro (801 bytes, text/html)
2010-10-27 05:00 PDT, Hajime Morrita
no flags
Patch (11.56 KB, patch)
2010-11-01 04:26 PDT, Hajime Morrita
no flags
Patch (11.45 KB, patch)
2010-11-01 19:20 PDT, Hajime Morrita
no flags
Patch (12.74 KB, patch)
2010-11-01 19:30 PDT, Hajime Morrita
no flags
removed 'parent' from test (12.48 KB, patch)
2010-11-01 20:29 PDT, Hajime Morrita
no flags
Patch (12.52 KB, patch)
2010-11-01 22:15 PDT, Hajime Morrita
tkent: review+
Hajime Morrita
Comment 1 2010-11-01 04:26:52 PDT
Kent Tamura
Comment 2 2010-11-01 18:55:01 PDT
Comment on attachment 72494 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=72494&action=review > LayoutTests/editing/spelling/spelling-attribute-at-child-expected.txt:14 > +PASS layoutTestController.hasSpellingMarker(1, 2) is true The readability of the test result is not good. Every test looks to check the same thing, layoutTestController.hasSpellingMarker(1, 2). How about testSpellCheckingEnabled() returns the boolean result of hasSpellingMarker(), and call shouldBe() at the top level like shouldBeFalse('testSpellCheckingEnabled(undefined, false))? > WebCore/editing/Editor.cpp:2130 > + return isSpellCheckingEnabledFor(m_frame->selection()->start().node()); Why m_frame->selection()->start().node() instead of document()->focusedNode() ?
Ryosuke Niwa
Comment 3 2010-11-01 19:12:00 PDT
Comment on attachment 72494 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=72494&action=review > LayoutTests/editing/spelling/script-tests/spelling-attribute-at-child.js:15 > + root.innerHTML = "<div id='parent' contentEditable>Foo <span id='child'>[]</span> Baz</div>"; > + var parent = document.getElementById("parent"); > + if (undefined != parentValue) > + parent.spellcheck = parentValue; > + var child = document.getElementById("child"); > + if (undefined != childValue) > + child.spellcheck = childValue; I think it's cleaner to pass the entire markup to this function rather than passing boolean values and modifying DOM by script like this. You can then remove id attributes (you can just make a contract that there's exactly one span and do var text = document.elementsByTagName('span')[0].firstChild. > LayoutTests/editing/spelling/script-tests/spelling-attribute-at-child.js:22 > + shouldBe("layoutTestController.hasSpellingMarker(1, 2)", expectedEnabled ? "true" : "false"); I don't think this is a really nice usage of shouldBe. I personally like calling testPassed / testFailed manually with more descriptive message. See See http://trac.webkit.org/browser/trunk/LayoutTests/editing/execCommand/script-tests/query-command-state.js for an example. >> LayoutTests/editing/spelling/spelling-attribute-at-child-expected.txt:14 >> +PASS layoutTestController.hasSpellingMarker(1, 2) is true > > The readability of the test result is not good. Every test looks to check the same thing, layoutTestController.hasSpellingMarker(1, 2). > > How about testSpellCheckingEnabled() returns the boolean result of hasSpellingMarker(), and call shouldBe() at the top level like shouldBeFalse('testSpellCheckingEnabled(undefined, false))? I agree with Kent. These results look cryptic. We need to look at the actual script to know what the test is doing.
Hajime Morrita
Comment 4 2010-11-01 19:20:13 PDT
Hajime Morrita
Comment 5 2010-11-01 19:22:42 PDT
Oops, I've missed Ryosuke's comment. I'll address it soon.
Hajime Morrita
Comment 6 2010-11-01 19:30:44 PDT
Hajime Morrita
Comment 7 2010-11-01 19:39:48 PDT
Hi Kent-san, Ryosuke, thank you for reviewing this! > The readability of the test result is not good. Every test looks to check the same thing, layoutTestController.hasSpellingMarker(1, 2). > > How about testSpellCheckingEnabled() returns the boolean result of hasSpellingMarker(), and call shouldBe() at the top level like shouldBeFalse('testSpellCheckingEnabled(undefined, false))? Sounds better. Passing markup itself looks bette too as Ryosuke mentioned. I rewrote to such. > > > WebCore/editing/Editor.cpp:2130 > > + return isSpellCheckingEnabledFor(m_frame->selection()->start().node()); > > Why m_frame->selection()->start().node() instead of document()->focusedNode() ? This is the point of this fix. For <input> or <text> focusNode() is OK. For contentEditable nodes, the focus is on editable root, instead of where the caret is. And such node could have @spellcheck attribute. I think it is OK to call it isSpellCheckingEnabledInFocusedNode() because the caret node is a child of actual focused node and it's a detail of WebCore. So WebKit layer, who is calling this API, doesn't need to know that.
Ryosuke Niwa
Comment 8 2010-11-01 19:52:54 PDT
Comment on attachment 72619 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=72619&action=review > LayoutTests/editing/spelling/script-tests/spelling-attribute-at-child.js:10 > + var parent = document.getElementById("parent"); parent is never used. > LayoutTests/editing/spelling/script-tests/spelling-attribute-at-child.js:30 > +shouldBeFalse("testSpellChecking(\"<div id='parent' contentEditable>Foo <span spellcheck='false' id='child'>[]</span> Baz</div>\")"); > +shouldBeTrue("testSpellChecking(\"<div id='parent' contentEditable>Foo <span id='child'>[]</span> Baz</div>\")"); > +shouldBeTrue("testSpellChecking(\"<div id='parent' contentEditable>Foo <span spellcheck='true' id='child'>[]</span> Baz</div>\")"); > +shouldBeFalse("testSpellChecking(\"<div id='parent' spellcheck='false' contentEditable>Foo <span spellcheck='false' id='child'>[]</span> Baz</div>\")"); > +shouldBeFalse("testSpellChecking(\"<div id='parent' spellcheck='false' contentEditable>Foo <span id='child'>[]</span> Baz</div>\")"); > +shouldBeTrue("testSpellChecking(\"<div id='parent' spellcheck='false' contentEditable>Foo <span spellcheck='true' id='child'>[]</span> Baz</div>\")"); > +shouldBeFalse("testSpellChecking(\"<div id='parent' spellcheck='true' contentEditable>Foo <span spellcheck='false' id='child'>[]</span> Baz</div>\")"); > +shouldBeTrue("testSpellChecking(\"<div id='parent' spellcheck='true' contentEditable>Foo <span id='child'>[]</span> Baz</div>\")"); > +shouldBeTrue("testSpellChecking(\"<div id='parent' spellcheck='true' contentEditable>Foo <span spellcheck='true' id='child'>[]</span> Baz</div>\")"); You don't need parent here. You don't even need id='child' if you do what I said in the earlier comment but I used to put id="test" all the time so I guess it's up to you.
Hajime Morrita
Comment 9 2010-11-01 20:29:11 PDT
Created attachment 72623 [details] removed 'parent' from test
Ryosuke Niwa
Comment 10 2010-11-01 21:51:15 PDT
Comment on attachment 72623 [details] removed 'parent' from test View in context: https://bugs.webkit.org/attachment.cgi?id=72623&action=review > LayoutTests/editing/spelling/script-tests/spelling-attribute-at-child.js:11 > + var child = document.getElementById("child"); > + var text = child.firstChild; Sorry, I keep adding comments but you can rewrite this just in one line: var text = document.getElementById('child').firstChild. > LayoutTests/editing/spelling/script-tests/spelling-attribute-at-child.js:12 > + sel.setBaseAndExtent(text, 1, text, 1); You can do window.getSelection().setPosition(text, 1) here as well. Then you can get rid of "sel" variable. > LayoutTests/editing/spelling/spelling-attribute-at-child-expected.txt:6 > +PASS testSpellChecking("<div contentEditable>Foo <span spellcheck='false' id='child'>[]</span> Baz</div>") is false Maybe rename testSpellChecking to childHasSpellingMarker so that the test reads as: PASS childHasSpellingMarker(~~) is true/false
Hajime Morrita
Comment 11 2010-11-01 22:15:08 PDT
Hajime Morrita
Comment 12 2010-11-01 22:17:18 PDT
> > LayoutTests/editing/spelling/script-tests/spelling-attribute-at-child.js:11 > > + var child = document.getElementById("child"); > > + var text = child.firstChild; > > Sorry, I keep adding comments but you can rewrite this just in one line: var text = document.getElementById('child').firstChild. Done. > > > LayoutTests/editing/spelling/script-tests/spelling-attribute-at-child.js:12 > > + sel.setBaseAndExtent(text, 1, text, 1); > > You can do window.getSelection().setPosition(text, 1) here as well. Then you can get rid of "sel" variable. > Done. > > LayoutTests/editing/spelling/spelling-attribute-at-child-expected.txt:6 > > +PASS testSpellChecking("<div contentEditable>Foo <span spellcheck='false' id='child'>[]</span> Baz</div>") is false > > Maybe rename testSpellChecking to childHasSpellingMarker so that the test reads as: PASS childHasSpellingMarker(~~) is true/false Done. Wow, the code goes further concise than original version.
Kent Tamura
Comment 13 2010-11-01 22:19:29 PDT
Comment on attachment 72629 [details] Patch ok
Hajime Morrita
Comment 14 2010-11-01 22:31:02 PDT
Note You need to log in before you can comment on or make changes to this bug.