2011-05-08 Ryosuke Niwa <rniwa@webkit.org>
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 May 2011 03:29:42 +0000 (03:29 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 May 2011 03:29:42 +0000 (03:29 +0000)
        Reviewed by Kent Tamura.

        selectstart event does not fire when selection is made via select all
        https://bugs.webkit.org/show_bug.cgi?id=60376

        Added tests to ensure selectstart event is fired when a user selects all contents
        and script can prevent such selection change in selectstart's event handler.

        * fast/events/selectstart-on-selectall-expected.txt: Added.
        * fast/events/selectstart-on-selectall.html: Added.
        * fast/events/selectstart-prevent-selectall-expected.txt: Added.
        * fast/events/selectstart-prevent-selectall.html: Added.
2011-05-08  Ryosuke Niwa  <rniwa@webkit.org>

        Reviewed by Kent Tamura.

        selectstart event does not fire when selection is made via select all
        https://bugs.webkit.org/show_bug.cgi?id=60376

        Fire selectstart event when a user selects all contents (i.e. document.execCommand('SelectAll')) in
        document, editable region, or text control.

        Tests: editing/selection/selectstart-on-selectall.html
               editing/selection/selectstart-prevent-selectall.html

        * dom/Node.h: Removed canSelectAll and selectAll as they are left over from WMLSelectElement.
        * editing/FrameSelection.cpp:
        (WebCore::FrameSelection::selectAll): Dispatch selectstart event on selectStartTarget, which is
        input element or textarea element when the current selection is inside a shadow DOM, and the root
        editable element if it's inside a non-shadow editable region, and the body element otherwise.
        * html/HTMLSelectElement.h: Made canSelectAll and selectAll public since they are no longer
        declared in Node.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@86041 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/events/selectstart-on-selectall-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/selectstart-on-selectall.html [new file with mode: 0644]
LayoutTests/fast/events/selectstart-prevent-selectall-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/selectstart-prevent-selectall.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Node.h
Source/WebCore/editing/FrameSelection.cpp
Source/WebCore/html/HTMLSelectElement.h

index b1fefa5..0936471 100644 (file)
@@ -1,3 +1,18 @@
+2011-05-08  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Reviewed by Kent Tamura.
+
+        selectstart event does not fire when selection is made via select all
+        https://bugs.webkit.org/show_bug.cgi?id=60376
+
+        Added tests to ensure selectstart event is fired when a user selects all contents
+        and script can prevent such selection change in selectstart's event handler.
+
+        * fast/events/selectstart-on-selectall-expected.txt: Added.
+        * fast/events/selectstart-on-selectall.html: Added.
+        * fast/events/selectstart-prevent-selectall-expected.txt: Added.
+        * fast/events/selectstart-prevent-selectall.html: Added.
+
 2011-05-08  Abhishek Arya  <inferno@chromium.org>
 
         Unreviewed.
diff --git a/LayoutTests/fast/events/selectstart-on-selectall-expected.txt b/LayoutTests/fast/events/selectstart-on-selectall-expected.txt
new file mode 100644 (file)
index 0000000..66f741d
--- /dev/null
@@ -0,0 +1,5 @@
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > P > BODY > HTML > #document to 61 of #text > P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+This test ensures selectstart event fires when selecting all.
+
+PASS
diff --git a/LayoutTests/fast/events/selectstart-on-selectall.html b/LayoutTests/fast/events/selectstart-on-selectall.html
new file mode 100644 (file)
index 0000000..2563f95
--- /dev/null
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<body onselectstart="handler(event)">
+<p>This test ensures selectstart event fires when selecting all.</p>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpEditingCallbacks();
+}
+
+var targetWasBody = true;
+var handlerCount = 0;
+var listenerCount = 0;
+
+function handler(event) {
+    if (event.target != document.body)
+        targetWasBody = false;
+    handlerCount++;
+}
+
+document.body.addEventListener('selectstart', function (event) {
+    if (event.target != document.body)
+        targetWasBody = false;
+    listenerCount++;
+});
+
+document.execCommand('SelectAll', false, null);
+
+if (handlerCount != 1)
+    document.writeln("FAIL: selectionstart's event handler was called " + handlerCount + ' times');
+else if (listenerCount != 1)
+    document.writeln("FAIL: selectionstart's event listener was called " + listenerCount + ' times');
+else if (!targetWasBody)
+    document.writeln("FAIL: target node wasn't body");
+else if (window.getSelection().toString() != document.body.innerText)
+    document.writeln("FAIL: some contents on document was not selected");
+else
+    document.writeln("PASS");
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/selectstart-prevent-selectall-expected.txt b/LayoutTests/fast/events/selectstart-prevent-selectall-expected.txt
new file mode 100644 (file)
index 0000000..d9e6006
--- /dev/null
@@ -0,0 +1,16 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > SECTION > BODY > HTML > #document to 1 of DIV > SECTION > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > SECTION > BODY > HTML > #document to 0 of DIV > SECTION > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldEndEditingInDOMRange:range from 0 of DIV > SECTION > BODY > HTML > #document to 1 of DIV > SECTION > BODY > HTML > #document
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+This test ensures selectstart event fires when selecting all and script can prevent the selection change.
+
+div: PASS
+input: PASS
+
diff --git a/LayoutTests/fast/events/selectstart-prevent-selectall.html b/LayoutTests/fast/events/selectstart-prevent-selectall.html
new file mode 100644 (file)
index 0000000..2323ebe
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<body onselectstart="event.preventDefault();">
+<p>This test ensures selectstart event fires when selecting all and script can prevent the selection change.</p>
+<section id="test">
+<div onselectstart="handlerOnDivWasCalled = true;" contenteditable>hello</div>
+<input onselectstart="event.preventDefault();" type="text" value="world">
+</section>
+<pre><script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpEditingCallbacks();
+}
+
+var handlerOnDivWasCalled = false;
+var div = document.getElementsByTagName('div')[0];
+div.focus();
+window.getSelection().setPosition(div.firstChild, 1);
+document.execCommand('SelectAll', false, null);
+var range = window.getSelection().getRangeAt(0);
+document.write('div: ');
+if (!handlerOnDivWasCalled)
+    document.writeln('FAIL - handler on div was never called');
+else if (range.startOffset != 1 || range.endOffset != 1)
+    document.writeln('FAIL - selection changed');
+else
+    document.writeln('PASS');
+
+var input = document.getElementsByTagName('input')[0];
+input.focus();
+input.selectionStart = 1;
+input.selectionEnd = 1;
+document.execCommand('SelectAll', false, null);
+document.writeln('input: ' + (input.selectionStart == 1 || input.selectionEnd == 1 ? 'PASS' : 'FAIL'));
+
+document.getElementById('test').style.display = 'none';
+
+</script></pre>
+</body>
+</html>
index 43b4eab..9ff786f 100644 (file)
@@ -1,3 +1,24 @@
+2011-05-08  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Reviewed by Kent Tamura.
+
+        selectstart event does not fire when selection is made via select all
+        https://bugs.webkit.org/show_bug.cgi?id=60376
+
+        Fire selectstart event when a user selects all contents (i.e. document.execCommand('SelectAll')) in
+        document, editable region, or text control.
+
+        Tests: editing/selection/selectstart-on-selectall.html
+               editing/selection/selectstart-prevent-selectall.html
+
+        * dom/Node.h: Removed canSelectAll and selectAll as they are left over from WMLSelectElement.
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::selectAll): Dispatch selectstart event on selectStartTarget, which is
+        input element or textarea element when the current selection is inside a shadow DOM, and the root
+        editable element if it's inside a non-shadow editable region, and the body element otherwise.
+        * html/HTMLSelectElement.h: Made canSelectAll and selectAll public since they are no longer
+        declared in Node.
+
 2011-05-08  Luke Macpherson   <macpherson@chromium.org>
 
         Reviewed by Eric Seidel.
index c288d1f..daf1c00 100644 (file)
@@ -415,10 +415,6 @@ public:
     // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of
     // css-transform:capitalize breaking up precomposed characters and ligatures.
     virtual int maxCharacterOffset() const;
-    
-    // FIXME: We should try to find a better location for these methods.
-    virtual bool canSelectAll() const { return false; }
-    virtual void selectAll() { }
 
     // Whether or not a selection can be started in this object
     virtual bool canStartSelection() const;
index 7750374..4ce4e9f 100644 (file)
@@ -43,6 +43,7 @@
 #include "HTMLFormElement.h"
 #include "HTMLFrameElementBase.h"
 #include "HTMLInputElement.h"
+#include "HTMLSelectElement.h"
 #include "HTMLNames.h"
 #include "HitTestRequest.h"
 #include "HitTestResult.h"
@@ -1452,25 +1453,43 @@ void FrameSelection::selectFrameElementInParentIfFullySelected()
 void FrameSelection::selectAll()
 {
     Document* document = m_frame->document();
-    
-    if (document->focusedNode() && document->focusedNode()->canSelectAll()) {
-        document->focusedNode()->selectAll();
-        return;
+
+    if (document->focusedNode() && document->focusedNode()->hasTagName(selectTag)) {
+        HTMLSelectElement* selectElement = static_cast<HTMLSelectElement*>(document->focusedNode());
+        if (selectElement->canSelectAll()) {
+            selectElement->selectAll();
+            return;
+        }
     }
-    
+
     Node* root = 0;
-    if (isContentEditable())
+    Node* selectStartTarget = 0;
+    if (isContentEditable()) {
         root = highestEditableRoot(m_selection.start());
-    else {
+        if (Node* shadowRoot = shadowTreeRootNode())
+            selectStartTarget = shadowRoot->shadowHost();
+        else
+            selectStartTarget = root;
+    } else {
         root = shadowTreeRootNode();
-        if (!root)
+        if (root)
+            selectStartTarget = root->shadowHost();
+        else {
             root = document->documentElement();
+            selectStartTarget = document->body();
+        }
     }
     if (!root)
         return;
+
+    if (selectStartTarget && !selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)))
+        return;
+
     VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root));
+
     if (shouldChangeSelection(newSelection))
         setSelection(newSelection);
+
     selectFrameElementInParentIfFullySelected();
     notifyRendererOfSelectionChange(true);
 }
index e6e1bec..0d985f3 100644 (file)
@@ -88,6 +88,9 @@ public:
 
     virtual void updateValidity() { setNeedsValidityCheck(); }
 
+    virtual bool canSelectAll() const;
+    virtual void selectAll();
+
 protected:
     HTMLSelectElement(const QualifiedName&, Document*, HTMLFormElement*);
 
@@ -96,8 +99,6 @@ private:
     
     virtual bool isKeyboardFocusable(KeyboardEvent*) const;
     virtual bool isMouseFocusable() const;
-    virtual bool canSelectAll() const;
-    virtual void selectAll();
 
     virtual void recalcStyle(StyleChange);