- 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;