-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix old results shown on predictive search #2249
Conversation
5e6ef87
to
9b0d555
Compare
assets/predictive-search.js
Outdated
const buttonIcon = searchForButton.innerHTML.replace( | ||
currentButtonText, | ||
"" | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separating from the button SVG can removed here by wrapping the translation string in a span
and searching for that; I'd recommend a data-attribute of data-search-term
over a class or any other selector type.
<span data-search-term>{{ 'templates.search.search_for' | t: terms: predictive_search.terms }}</span>
Note: There is a way in Liquid to put HTML in the translation string so you could wrap just the query, but I think that makes the translation string too difficult to work with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd suggest more grabbing the icon via it's class or element name 🤔 searchForButton.querySelector('svg')
It would be easier to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My point is that I don't believe this function even needs to know that there is an svg
in the HTML. Right now, this function is taking the innerHTML
of a <button>
and changing it by concatentating a string
and an svg
. However, there's nothing about the svg
that is going to change, so why include it? Adding a new span
would give the function a target element to inspect the text on.
updateSearchForTerm(previousTerm, newTerm) {
const searchForText = this.querySelector("#search-for-button [data-search-term]");
const currentText = searchForButton?.innerText;
if (currentText) {
if (currentText.match(new RegExp(previousTerm, "g")).length > 1) {
// The new term matches part of the button text and not just the search term, do not replace to avoid mistakes
return;
}
searchForText.innerText = currentButtonText.replace(previousTerm, newTerm);
}
}
assets/predictive-search.js
Outdated
@@ -263,6 +289,10 @@ class PredictiveSearch extends SearchForm { | |||
this.resultsMaxHeight = false | |||
this.predictiveSearchResults.removeAttribute('style'); | |||
} | |||
|
|||
clearResources() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use the existing closeResults
method for this instead? Is this additional method necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. Ill test a bit tomorrow some scenarios.
But no bugs/issue noticed 👍
sections/predictive-search.liquid
Outdated
@@ -7,7 +7,7 @@ | |||
%} | |||
<div id="predictive-search-results" role="listbox"> | |||
{%- if first_column_results_size > 0 or predictive_search.resources.products.size > 0 -%} | |||
<div class="predictive-search__results-groups-wrapper{% unless predictive_search.resources.products.size > 0 %} predictive-search__results-groups-wrapper--no-products{% endunless %}{% unless predictive_search.resources.queries.size > 0 or predictive_search.resources.collections.size > 0 %} predictive-search__results-groups-wrapper--no-suggestions{% endunless %}"> | |||
<div id="predictive-search__results-groups-wrapper" class="predictive-search__results-groups-wrapper{% unless predictive_search.resources.products.size > 0 %} predictive-search__results-groups-wrapper--no-products{% endunless %}{% unless predictive_search.resources.queries.size > 0 or predictive_search.resources.collections.size > 0 %} predictive-search__results-groups-wrapper--no-suggestions{% endunless %}"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see why you'd have the __
underscores there. But since we didn't use that same pattern for predictive-search-option-search-keywords
I think we should approach it the same way. With a -
instead.
assets/predictive-search.js
Outdated
const newSearchTerm = this.getQuery(); | ||
if (!this.searchTerm || !newSearchTerm.startsWith(this.searchTerm)) { | ||
// Hide the results when they are no longer relevant for the new search term | ||
this.closeResults(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't do what the function you had before did 🤔
Here are two video comparisons: using clearResources() & using closeResults(false)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested and it seemed to be fine, but maybe my internet was too fast to appreciate the difference. Thanks for the thorough testing!
b860ffc
to
1acec68
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's looking good 👍
I can see how the proposed change by Nathan would make sense too 👍 About wrapping the text in a span.
Not sure if we need the data attribute since we can select the span
element itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for owning this @FCalabria
It doesn't seem like the failing theme check step will be a blocker to merge. I see that the recent PRs have merged without this passing (example). But don't forget to rebase this first 🔂 🚢
I decided to use the data attribute because with the span i don't need the reference to the full button anymore, so i could delete that id.
Sure! I was waiting for you to finish reviewing to not mess up anything |
87ab664
to
52f37d1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎩 I just re-tophatted https://os2-demo.myshopify.com/?preview_theme_id=139285364758
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
PR Summary:
Hide stale results on the predictive search when writting a new query and refresh the "search for" button with the new term as soon as possible.
Why are these changes introduced?
Fixes #2199 and improves the user experience updating the "search for" button while the user types, instead of waiting for the predictive search query to resolve.
What approach did you take?
To fix the bug, delete the results and show the loading spinner when the new query is not an addition over the old one.
For the improvement, I used a search and replace technique modifying the html on the fly with JS. I could not figure out a way to identify the search term that wasn't just looking for the string itself (depending on the language the quote symbol and the term position changes). This can cause a problem when the user looks for exactly the label on the search button ("Search for...") which i avoided not replacing anything if there is more than one match.
Testing steps/scenarios
Demo links
Checklist