-
-
Save carolineschnapp/11352987 to your computer and use it in GitHub Desktop.
<div> | |
<label for="sort-by">Sort by</label> | |
<select id="sort-by"> | |
<option value="manual">Featured</option> | |
<option value="price-ascending">Price: Low to High</option> | |
<option value="price-descending">Price: High to Low</option> | |
<option value="title-ascending">A-Z</option> | |
<option value="title-descending">Z-A</option> | |
<option value="created-ascending">Oldest to Newest</option> | |
<option value="created-descending">Newest to Oldest</option> | |
<option value="best-selling">Best Selling</option> | |
</select> | |
</div> | |
<script> | |
Shopify.queryParams = {}; | |
if (location.search.length) { | |
for (var aKeyValue, i = 0, aCouples = location.search.substr(1).split('&'); i < aCouples.length; i++) { | |
aKeyValue = aCouples[i].split('='); | |
if (aKeyValue.length > 1) { | |
Shopify.queryParams[decodeURIComponent(aKeyValue[0])] = decodeURIComponent(aKeyValue[1]); | |
} | |
} | |
} | |
jQuery('#sort-by') | |
.val('{{ collection.sort_by | default: collection.default_sort_by | escape }}') | |
.bind('change', function() { | |
Shopify.queryParams.sort_by = jQuery(this).val(); | |
location.search = jQuery.param(Shopify.queryParams).replace(/\+/g, '%20'); | |
}); | |
</script> |
Hey guys, is there a way to change the font of the text inside the drop down?
Thanks!
Hey all. This is a great code and I'm thankful for everyone's contribution.
I tried installing this on a new Shopify theme built with Slate, and I ran into some problems with the original code. I then swapped the JS with what @marcobiedermann posted but I had to add "sort_by" to the last line to make it work properly.
After a few tries and some help with the code, here is what I am using in my <script> tag that is working. Thanks again everyone for your contributions!
document.querySelector('#sort-by').addEventListener('change', function() {
const urlSearchParams = new URLSearchParams(
window.location.search.indexOf("sort_by") > -1
? window.location.search.replace(/sort_by/gi,"")
: window.location.search
);
urlSearchParams.set(this.name, this.value);
window.location = `?sort_by${urlSearchParams}`;
});
I've took your code @james-zedd and made it so it renders the current selected option:
<div id="sort-by-container"></div>
<script>
var currentURL = new URL(window.location);
var currentParams = currentURL.searchParams.get('sort_by');
var urlSearchParams = new URLSearchParams(
window.location.search.indexOf("sort_by") > -1
? window.location.search.replace(/sort_by/gi,"")
: window.location.search
);
var render = function (template, node) {
node.innerHTML = template;
node.querySelector('#sort-by').addEventListener('change', function() {
urlSearchParams.set(this.name, this.value);
window.location = `?sort_by${urlSearchParams}`;
});
};
var SortOptions = [{
label: 'Featured',
value: 'manual'
}, {
label: 'Price: Low to High',
value: 'price-ascending'
}, {
label: 'Price: High to Low',
value: 'price-descending'
}, {
label: 'A-Z',
value: 'title-ascending'
}, {
label: 'Z-A',
value: 'title-descending'
}, {
label: 'Oldest to Newest',
value: 'created-ascending'
}, {
label: 'Newest to Oldest',
value: 'created-descending'
}, {
label: 'Best Selling',
value: 'best-selling'
}];
var template = `
<div>
<label for="sort-by">Sort by</label>
<select id="sort-by">
${SortOptions.map((item) =>
`<option value="${item.value}" ${currentParams === item.value ? 'selected' : ''}>${item.label}</option>`
).join('')}
</select>
</div>
`;
render(template, document.querySelector('#sort-by-container'));
</script>
I was able to add this without much difficulty using the Radiance theme. Thank you!
Got any ideas on how I can make the items show up in RANDOM order first? Because I have 9000 different items, it's always the first 30 or so that get the most exposure which isn't fair... I want a random product list THEN let the user do a sort.
Thanks everyone for your awesome contribution on this. Helped me a lot. I used @james-zedd code. Only one thing I added to preserve current selection in dropdown. Below is my updated code.
Shopify.queryParams = {};
{% comment %} console.log("location", location); {% endcomment %}
if (location.search.length) {
for (var aKeyValue, i = 0, aCouples = location.search.substr(1).split('&'); i < aCouples.length; i++) {
aKeyValue = aCouples[i].split('=');
if (aKeyValue.length > 1) {
Shopify.queryParams[decodeURIComponent(aKeyValue[0])] = decodeURIComponent(aKeyValue[1]);
}
}
}
if (Shopify.queryParams.sort_by) {
document.querySelector('#sort-by').value = Shopify.queryParams.sort_by;
} else {
document.querySelector('#sort-by').value = "manual";
}
document.querySelector('#sort-by').addEventListener('change', function() {
const urlSearchParams = new URLSearchParams(
window.location.search.indexOf("sort_by") > -1
? window.location.search.replace(/sort_by/gi,"")
: window.location.search
);
urlSearchParams.set(this.name, this.value);
window.location = `?sort_by${urlSearchParams}`;
});
I took your code @zomars and it seems to work just fine although I have some issues to get it working together with the search query on the search results page.
Has anybody been able to get that work on the search page?
You need to re-add the search query in the window.location
line @ tomaszbujnowicz
Thanks @zomars but I think I have just figured it out.
Filtering search results based on these values is not possible at the moment - at least this is what I read in the docs.
I'll need to find another way, however your code works just fine for other than search results pages. Thanks ;)
y'all trippin'
const $sorter = $('.js-collection-sort')
let sortBy = false
if (window.location.search.length) {
sortBy = new URLSearchParams(window.location.search).get('sort_by')
}
//preserve current selection
// set sort value to present query
if(sortBy) {
$sorter.val(sortBy)
}
$sorter.on('change', (e) => {
const { value } = e.currentTarget
window.location = `?sort_by=${value}`
})
@james-zedd and @zomars thank you it works great :)
Thanks everyone, this is just what I needed? I've used your code @james-zedd and although it works perfectly, it always shows 'Featured' rather than the current selected sort order. @zomars I tried your code as you say you got it to 'preserve current selection in dropdown' which I THINK is what I mean, but that code doesn't sort at all for me. Can either of you/anyone help me show the current sort order in the drop down? Thank you in advance!
I wanted something lean like @eballeste, but I also wanted to make sure that it's dependency free, that existing URL parameters are preserved, and that the active sorting method is correctly selected when a page loads. I wrote more details in a post about the right way to add a sort by dropdown in Shopify.
Thanks, it worked great. I wanted to manipulate my code rather than relying on Shopify. Just clarification for everyone else.
Put this code inside the Collection.Liquid which can be found in your Templates Folder
<div>
<label for="sort-by">Sort by</label>
<select id="sort-by">
<option value="manual">Featured</option>
<option value="price-ascending">Price: Low to High</option>
<option value="price-descending">Price: High to Low</option>
<option value="title-ascending">A-Z</option>
<option value="title-descending">Z-A</option>
<option value="created-ascending">Oldest to Newest</option>
<option value="created-descending">Newest to Oldest</option>
<option value="best-selling">Best Selling</option>
</select>
</div>
<script>
And put this code into your theme.js which can be found in your Assets Folder
Shopify.queryParams = {};
if(location.search.length) {
for(var aKeyValue, i = 0, aCouples = location.search.substr(1).split('&'); i < aCouples.length; i++) {
aKeyValue = aCouples[i].split('=');
if (aKeyValue.length > 1) {
Shopify.queryParams[decodeURIComponent(aKeyValue[0])] = decodeURIComponent(aKeyValue[1]);
}
}
}
document.querySelector('.sort-by').addEventListener('change', (e) => {
const { value } = e.currentTarget;
Shopify.queryParams.sort_by = value;
location.search = new URLSearchParams(Shopify.queryParams).toString();
});
If you want to play around with moving the sort and changing colors etc. use CSS. You can do so by going into theme.scss.liquid which can be found in your Assets Folder
e.g. Adding the following at the end of your CSS page.
body.template-collection #sort-by {
margin-left: 30%;
}
body is the body of the page.
template-collection is the class of that body.
sort-by is the id of where you want to use CSS.
You can right-click on your website page and find all of this information. Then its easier to find what you want to and play around with CSS.
Inspect:
CSS:
After reading through the above comments and being overwhelmed, I went with this guide and it worked perfectly with a fresh ThemeKit theme posted by @cfxd:
@coppinger thanks for the good vibes and happy that it worked!
Simply add the following.
<select class="custom-select" name="sort_by" onchange="javascript:location.href = window.location.href.split('?')[0] + `?sort_by=${this.value}`;">
{% for option in collection.sort_options %}
<option value="{{ option.value }}" {% if option.value == collection.sort_by %}selected{% endif %}>{{ option.name }}</option>
{% endfor %}
</select>
After reading all the above, here is what I think makes the most sense:
<div id="sort">
<div class="sort-title">Sort by:</div>
<select name="sort_by" id="sort-by">
<option value="manual">Featured</option>
<option value="price-ascending">Price: Low to High</option>
<option value="price-descending">Price: High to Low</option>
</select>
</div>
const sorter = document.querySelector('#sort-by');
if (sorter) {
sorter.addEventListener('change', function () {
const urlSearchParams = new URLSearchParams(window.location.search);
urlSearchParams.set(this.name, this.value);
window.location = `?${urlSearchParams}`;
});
}
if (window.location.search.length) {
sortBy = new URLSearchParams(window.location.search).get('sort_by');
if (sorter) {
sorter.value = sortBy
}
}
Simply add the following.
<select class="custom-select" name="sort_by" onchange="javascript:location.href = window.location.href.split('?')[0] + `?sort_by=${this.value}`;"> {% for option in collection.sort_options %} <option value="{{ option.value }}" {% if option.value == collection.sort_by %}selected{% endif %}>{{ option.name }}</option> {% endfor %} </select>
thanks, this is should be the best answer
I signed in just to let everyone know that after much googling. Shopify has this feature but its not well know.
i decided to post this to clarify how to set the default sort type.
From your Shopify admin, go to Products > Collections.
Click a collection.
In the Products section, click the drop-down list beside Sort, and then select a sort order.
If you select Manually, then you can click and drag the products in the list to reorder them.
You can also click and select one or more products in the list. Click Move to reorder them to a specific position in the collection.
Your should be notified that it was been updated.
This helped me keep my new arrivals collection sorted by newest .
you can set each collection as desired.
Your welcome.
Simply add the following.
<select class="custom-select" name="sort_by" onchange="javascript:location.href = window.location.href.split('?')[0] + `?sort_by=${this.value}`;"> {% for option in collection.sort_options %} <option value="{{ option.value }}" {% if option.value == collection.sort_by %}selected{% endif %}>{{ option.name }}</option> {% endfor %} </select>
thanks, this is should be the best answer
This worked , and is the simplest and best. No external JS required
Would anyone know of a way to get the same output as using ?sort_by=best-selling but programatically?
I've remade the search/filter/sort system on my landing page using a mix of js and liquid, i'm able to sort and query by any of the product's information provided by the product object, but i can't seem to find a way to query the number of times a product has been sold in order to get the best selling items.
Can anyone help me out with this?
my store is on at: store.streamspell.com in case anyone wants to better understand my case...
Would anyone know of a way to get the same output as using ?sort_by=best-selling but programatically?
I've remade the search/filter/sort system on my landing page using a mix of js and liquid, i'm able to sort and query by any of the product's information provided by the product object, but i can't seem to find a way to query the number of times a product has been sold in order to get the best selling items.
Can anyone help me out with this?
my store is on at: store.streamspell.com in case anyone wants to better understand my case...
hacky but maybe create a collection that is sorted by best seller and output that collection w/liquid and work with that?
Would anyone know of a way to get the same output as using ?sort_by=best-selling but programatically?
I've remade the search/filter/sort system on my landing page using a mix of js and liquid, i'm able to sort and query by any of the product's information provided by the product object, but i can't seem to find a way to query the number of times a product has been sold in order to get the best selling items.
Can anyone help me out with this?
my store is on at: store.streamspell.com in case anyone wants to better understand my case...hacky but maybe create a collection that is sorted by best seller and output that collection w/liquid and work with that?
That's actually the only way i was able to achieve the result i wanted.
I created a collection with that sort by default and looped through it getting the product id and setting an index value to each product.id based on their position in the new collection. That did the trick but may not be a very scalable solution for stores with large amounts of product data.
I really wish there was at least a way to see what kind of logic shopify uses in their default sort by.
Anyways, thanks!
Hi All,
Would someone be able to help me with arranging the drop down filter to display the tag values in this order:
- Size 00
- Size 0
- Size 1
- Size 2
- ...
- Size 10
- Size 11
(instead of the current order as in the image attached below)
I've tried a few things but unsuccessful in the past few weeks. Any help would be heaps appreciated.
FYI, I am using the Venture theme of Shopify. Thank you in advance!
Hello everyone,
any ideas in how to exclude variants with price lower than 1 euro, when filtering by price?
The store has samples in every product, it is affecting the price sort :\
<div>
<label for="sort-by">Sort by</label>
<select id="sort-by">
<option value="manual">Featured</option>
<option value="price-ascending">Price: Low to High</option>
<option value="price-descending">Price: High to Low</option>
<option value="title-ascending">A-Z</option>
<option value="title-descending">Z-A</option>
<option value="created-ascending">Oldest to Newest</option>
<option value="created-descending">Newest to Oldest</option>
<option value="best-selling">Best Selling</option>
</select>
</div>
<script>
Shopify.queryParams = {};
if (location.search.length) {
for (var aKeyValue, i = 0, aCouples = location.search.substr(1).split('&'); i < aCouples.length; i++) {
aKeyValue = aCouples[i].split('=');
if (aKeyValue.length > 1) {
Shopify.queryParams[decodeURIComponent(aKeyValue[0])] = decodeURIComponent(aKeyValue[1]);
}
}
}
jQuery('#sort-by')
.val('{{ collection.sort_by | default: collection.default_sort_by | escape }}')
.bind('change', function() {
Shopify.queryParams.sort_by = jQuery(this).val();
location.search = jQuery.param(Shopify.queryParams).replace(/\+/g, '%20');
});
</script>
Thank you all for the codes! It worked for me on the Debut theme. I was just wondering if anyone knew how to add space below the sort by drop down menu as it is currently touching the product image below it. Thanks
Thank you soo much. Its working perfectly fine for me. Huge Thanks.
What should I need to do, if I want to do it with ajax...
Thanks for any suggestion.