Reputation: 121
I'm quite new to shopify, liquid and all that comes with it.
I try to implement predective search on shopify and I just don't know why I'm not even getting the alert of the Ajax call that is in the following code. I put it in my "theme.liquid" file right above the closing body tag. I assume if it would work, there should be the alert right when opening the page, no? Goki is a vendor, many products are shown when I search for it on my page. My code looks like this:
<script>
jQuery.getJSON("/search/suggest.json", {
"q": "goki",
"resources": {
"type": "product",
"limit": 4,
"options": {
"unavailable_products": "last",
"fields": "title,product_type,variants.title"
}
}
}).done(function(response) {
var productSuggestions = response.resources.results.products;
if (productSuggestions.length > 0) {
var firstProductSuggestion = productSuggestions[0];
alert("The title of the first product suggestion is: " + firstProductSuggestion.title);
}
});
</script>
Any help would be very very much appreciated! Thank you!
Upvotes: 0
Views: 1703
Reputation: 1
Please create an snippet name "predictive-search.liquid" and insert the below code inside the Snippet.After that include this snippet where you want to use.
document.addEventListener("DOMContentLoaded", function () {
const searchInput = document.getElementById("search-input");
const resultsContainer = document.getElementById("predictive-results");
const clearButton = document.getElementById("clear-search");
searchInput.addEventListener("input", function () {
let query = searchInput.value.trim();
// Show/hide clear button
clearButton.style.display = query.length > 0 ? "block" : "none";
if (query.length < 2) {
resultsContainer.innerHTML = "";
return;
}
fetch(`/search/suggest.json?q=${query}&resources[type]=product`)
.then(response => response.json())
.then(data => {
var s_url = `/search?q=${query}&type=product`;
//alert(s_url);
resultsContainer.innerHTML = "";
if (data.resources.results.products.length > 0) {
var k = 0;
let resultsHTML = "<ul>";
data.resources.results.products.forEach(product => {
if(k<5){
resultsHTML += `
<li>
<a href="${product.url}">
<img src="${product.image}" alt="${product.title}">
<span>${product.title}</span>
</a>
</li>
`;
}
k++;
});
resultsHTML += "</ul>";
if(k>5){
resultsHTML += "<p class='predictive_results_viewmore'><a href='"+s_url+"'>View more products</a></p>";
}
resultsContainer.innerHTML = resultsHTML;
} else {
resultsContainer.innerHTML = "<p class='predictive_results_notfound'>No products found</p>";
}
})
.catch(error => console.error("Error fetching product search:", error));
});
// Clear input when clicking the clear button
clearButton.addEventListener("click", function () {
searchInput.value = "";
resultsContainer.innerHTML = "";
clearButton.style.display = "none";
});
});
.search-container {
position: relative;
width: 100%;
max-width: 400px;
margin: 0 auto;
}
.search-box {
position: relative;
display: flex;
align-items: center;
background: #fff;
border: 1px solid rgba(54, 124, 54, 0.15);
border-radius: 5px;
padding: unset;
border-bottom: unset;
}
.search-icon {
display: flex;
align-items: center;
justify-content: center;
padding: 0 10px;
color: #888;
}
.search-icon svg {
width: 18px;
height: 18px;
}
#search-input {
flex: 1;
border: none;
outline: none;
padding: 8px;
font-size: 14px;
height: 40px;
}
.clear-button {
background: none;
border: none;
cursor: pointer;
display: flex;
align-items: center;
padding: 0 10px;
}
.clear-button svg {
width: 16px;
height: 16px;
color: #888;
}
.clear-button:hover svg {
color: #555;
}
.search-results {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: #fff;
border: 1px solid rgba(54, 124, 54, 0.15);
border-top: none; /* Ensures there's no double border between input and results */
border-radius: 0 0 5px 5px; /* Round only bottom corners */
max-height: 350px;
overflow-y: auto;
z-index: 1000;
-webkit-overflow-scrolling: touch;
}
.search-results ul {
list-style: none;
padding: 0;
margin: 0;
}
.search-results li {
padding: 2px 10px;
display: flex;
align-items: center;
border-bottom: 1px solid rgba(54, 124, 54, 0.15);
font-size: 12px;
margin: 0px;
}
.search-results li img {
width: 40px;
height: 40px;
object-fit: cover;
margin-right: 10px;
border-radius: 5px;
}
.search-results li a {
text-decoration: none;
color: #333;
display: flex;
align-items: center;
width: 100%;
}
.search-results li:hover {
background: #f4f4f4;
}
.coll-module-header{
padding-bottom: 50px !important;
}
.coll_search_container{
margin-bottom: 30px;
margin-left: 10px;
margin-right: 10px;
}
.predictive_results_viewmore{
font-size: 12px;
}
.predictive_results_notfound{
font-size: 12px;
}
<div class="search-container">
<div class="search-box">
<span class="search-icon">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</span>
<input type="text" id="search-input" placeholder="Search for products..." autocomplete="off">
<button id="clear-search" class="clear-button" style="display: none;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div id="predictive-results" class="search-results"></div>
</div>
Upvotes: 0
Reputation: 121
I solved it. I created an own variable AjaxData with all the 'resources' parameter before entering the JQuery call. There I don't use the variable to create the url, it's just used to define param in the call, not to change the url. -that's the trick
Upvotes: 0