Title: [235490] trunk
Revision
235490
Author
[email protected]
Date
2018-08-29 17:26:11 -0700 (Wed, 29 Aug 2018)

Log Message

[Datalist] Display prefix-matched suggestions first
https://bugs.webkit.org/show_bug.cgi?id=189106

Reviewed by Tim Horton.

Source/WebCore:

In order to increase suggestion relevancy, we should display suggestions that have
the same prefix as the input value first. In order to achieve this, we can place
the suggestions into two buckets, one that contains prefix-matched values and
another that contains only substring-matched values.

TextFieldInputType::suggestions() can be called up to three times before we
display the values. In order to avoid generating the same suggestions multiple
times, the most recent values can be stored and reused. We clear the cached values
whenever the datalist element is modified or when the suggestions view is hidden.

Finally, removed logic to de-duplicate the list of suggested values. This behavior
is not a part of the specification and leads to unnecessary slowdown when
populating the suggestions view.

Test: fast/forms/datalist/datalist-textinput-suggestions-order.html

* html/TextFieldInputType.cpp:
(WebCore::TextFieldInputType::listAttributeTargetChanged):
(WebCore::TextFieldInputType::suggestions):
(WebCore::TextFieldInputType::didCloseSuggestions):
* html/TextFieldInputType.h:
* platform/DataListSuggestionsClient.h:

LayoutTests:

Added a test to verify that prefix-matched suggestions are shown before other
matches.

* fast/forms/datalist/datalist-textinput-suggestions-order-expected.txt: Added.
* fast/forms/datalist/datalist-textinput-suggestions-order.html: Added.
* platform/ios/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (235489 => 235490)


--- trunk/LayoutTests/ChangeLog	2018-08-30 00:20:26 UTC (rev 235489)
+++ trunk/LayoutTests/ChangeLog	2018-08-30 00:26:11 UTC (rev 235490)
@@ -1,3 +1,17 @@
+2018-08-29  Aditya Keerthi  <[email protected]>
+
+        [Datalist] Display prefix-matched suggestions first
+        https://bugs.webkit.org/show_bug.cgi?id=189106
+
+        Reviewed by Tim Horton.
+
+        Added a test to verify that prefix-matched suggestions are shown before other
+        matches.
+
+        * fast/forms/datalist/datalist-textinput-suggestions-order-expected.txt: Added.
+        * fast/forms/datalist/datalist-textinput-suggestions-order.html: Added.
+        * platform/ios/TestExpectations:
+
 2018-08-29  Olivia Barnett  <[email protected]>
 
         Implement the Web Share API

Added: trunk/LayoutTests/fast/forms/datalist/datalist-textinput-suggestions-order-expected.txt (0 => 235490)


--- trunk/LayoutTests/fast/forms/datalist/datalist-textinput-suggestions-order-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/datalist/datalist-textinput-suggestions-order-expected.txt	2018-08-30 00:26:11 UTC (rev 235490)
@@ -0,0 +1,11 @@
+Test to verify that prefix-matched values are displayed first
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS input.value is "Orange"
+PASS input.value is "Apple"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/forms/datalist/datalist-textinput-suggestions-order.html (0 => 235490)


--- trunk/LayoutTests/fast/forms/datalist/datalist-textinput-suggestions-order.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/datalist/datalist-textinput-suggestions-order.html	2018-08-30 00:26:11 UTC (rev 235490)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+
+<input id="fruit" list="fruits" type="text"/>
+<datalist id="fruits">
+    <option>Orange</option>
+    <option>Pear</option>
+    <option>Apple</option>
+</datalist>
+
+<script>
+
+description('Test to verify that prefix-matched values are displayed first');
+
+var input = document.getElementById("fruit");
+
+UIHelper.activateElement(input);
+eventSender.keyDown("downArrow");
+eventSender.keyDown("\r");
+shouldBe('input.value', '"Orange"');
+
+input.value = "a";
+
+UIHelper.activateElement(input);
+eventSender.keyDown("downArrow");
+eventSender.keyDown("\r");
+shouldBe('input.value', '"Apple"');
+
+</script>
+
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/platform/ios/TestExpectations (235489 => 235490)


--- trunk/LayoutTests/platform/ios/TestExpectations	2018-08-30 00:20:26 UTC (rev 235489)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2018-08-30 00:26:11 UTC (rev 235490)
@@ -3121,6 +3121,7 @@
 webkit.org/b/186714 fast/forms/datalist/datalist-textinput-keydown.html [ Skip ]
 fast/forms/datalist/datalist-searchinput-appearance.html [ Skip ]
 fast/forms/datalist/datalist-textinput-appearance.html  [ Skip ]
+fast/forms/datalist/datalist-textinput-suggestions-order.html [ Skip ]
 
 # We are only accepting GLSL3 for macOS. 
 webkit.org/b/187982 webgl/2.0.0/conformance2/glsl3 [ Skip ]

Modified: trunk/Source/WebCore/ChangeLog (235489 => 235490)


--- trunk/Source/WebCore/ChangeLog	2018-08-30 00:20:26 UTC (rev 235489)
+++ trunk/Source/WebCore/ChangeLog	2018-08-30 00:26:11 UTC (rev 235490)
@@ -1,3 +1,33 @@
+2018-08-29  Aditya Keerthi  <[email protected]>
+
+        [Datalist] Display prefix-matched suggestions first
+        https://bugs.webkit.org/show_bug.cgi?id=189106
+
+        Reviewed by Tim Horton.
+
+        In order to increase suggestion relevancy, we should display suggestions that have
+        the same prefix as the input value first. In order to achieve this, we can place
+        the suggestions into two buckets, one that contains prefix-matched values and
+        another that contains only substring-matched values.
+
+        TextFieldInputType::suggestions() can be called up to three times before we
+        display the values. In order to avoid generating the same suggestions multiple
+        times, the most recent values can be stored and reused. We clear the cached values
+        whenever the datalist element is modified or when the suggestions view is hidden.
+
+        Finally, removed logic to de-duplicate the list of suggested values. This behavior
+        is not a part of the specification and leads to unnecessary slowdown when
+        populating the suggestions view.
+
+        Test: fast/forms/datalist/datalist-textinput-suggestions-order.html
+
+        * html/TextFieldInputType.cpp:
+        (WebCore::TextFieldInputType::listAttributeTargetChanged):
+        (WebCore::TextFieldInputType::suggestions):
+        (WebCore::TextFieldInputType::didCloseSuggestions):
+        * html/TextFieldInputType.h:
+        * platform/DataListSuggestionsClient.h:
+
 2018-08-29  Olivia Barnett  <[email protected]>
 
         Implement the Web Share API

Modified: trunk/Source/WebCore/html/TextFieldInputType.cpp (235489 => 235490)


--- trunk/Source/WebCore/html/TextFieldInputType.cpp	2018-08-30 00:20:26 UTC (rev 235489)
+++ trunk/Source/WebCore/html/TextFieldInputType.cpp	2018-08-30 00:26:11 UTC (rev 235490)
@@ -799,6 +799,8 @@
 
 void TextFieldInputType::listAttributeTargetChanged()
 {
+    m_cachedSuggestions = std::make_pair(String(), Vector<String>());
+
     if (!m_dataListDropdownIndicator)
         return;
 
@@ -823,10 +825,16 @@
     return element()->document().view()->contentsToRootView(element()->renderer()->absoluteBoundingBoxRect());
 }
 
-Vector<String> TextFieldInputType::suggestions() const
+Vector<String> TextFieldInputType::suggestions()
 {
     Vector<String> suggestions;
+    Vector<String> matchesContainingValue;
 
+    String elementValue = element()->value();
+
+    if (!m_cachedSuggestions.first.isNull() && equalIgnoringASCIICase(m_cachedSuggestions.first, elementValue))
+        return m_cachedSuggestions.second;
+
     if (auto dataList = element()->dataList()) {
         Ref<HTMLCollection> options = dataList->options();
         for (unsigned i = 0; auto* option = downcast<HTMLOptionElement>(options->item(i)); ++i) {
@@ -834,11 +842,18 @@
                 continue;
 
             String value = sanitizeValue(option->value());
-            if (!suggestions.contains(value) && (element()->value().isEmpty() || value.containsIgnoringASCIICase(element()->value())))
+            if (elementValue.isEmpty())
                 suggestions.append(value);
+            else if (value.startsWithIgnoringASCIICase(elementValue))
+                suggestions.append(value);
+            else if (value.containsIgnoringASCIICase(elementValue))
+                matchesContainingValue.append(value);
         }
     }
 
+    suggestions.appendVector(matchesContainingValue);
+    m_cachedSuggestions = std::make_pair(elementValue, suggestions);
+
     return suggestions;
 }
 
@@ -849,6 +864,7 @@
 
 void TextFieldInputType::didCloseSuggestions()
 {
+    m_cachedSuggestions = std::make_pair(String(), Vector<String>());
     m_suggestionPicker = nullptr;
     if (element()->renderer())
         element()->renderer()->repaint();

Modified: trunk/Source/WebCore/html/TextFieldInputType.h (235489 => 235490)


--- trunk/Source/WebCore/html/TextFieldInputType.h	2018-08-30 00:20:26 UTC (rev 235489)
+++ trunk/Source/WebCore/html/TextFieldInputType.h	2018-08-30 00:26:11 UTC (rev 235490)
@@ -131,7 +131,7 @@
 
     // DataListSuggestionsClient
     IntRect elementRectInRootViewCoordinates() const final;
-    Vector<String> suggestions() const final;
+    Vector<String> suggestions() final;
     void didSelectDataListOption(const String&) final;
     void didCloseSuggestions() final;
 
@@ -138,6 +138,7 @@
     void dataListButtonElementWasClicked() final;
     RefPtr<DataListButtonElement> m_dataListDropdownIndicator;
 
+    std::pair<String, Vector<String>> m_cachedSuggestions;
     std::unique_ptr<DataListSuggestionPicker> m_suggestionPicker;
 #endif
 

Modified: trunk/Source/WebCore/platform/DataListSuggestionsClient.h (235489 => 235490)


--- trunk/Source/WebCore/platform/DataListSuggestionsClient.h	2018-08-30 00:20:26 UTC (rev 235489)
+++ trunk/Source/WebCore/platform/DataListSuggestionsClient.h	2018-08-30 00:26:11 UTC (rev 235490)
@@ -37,7 +37,7 @@
     virtual ~DataListSuggestionsClient() = default;
 
     virtual IntRect elementRectInRootViewCoordinates() const = 0;
-    virtual Vector<String> suggestions() const = 0;
+    virtual Vector<String> suggestions() = 0;
 
     virtual void didSelectDataListOption(const String&) = 0;
     virtual void didCloseSuggestions() = 0;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to