Shopify themes, liquid, logos, and UX
Hi,
I would apreciate if someone could help me hiding the unavailable variants.
I already create the following snippet:
<script> // (c) Copyright 2016 Caroline Schnapp. All Rights Reserved. Contact: mllegeorgesand@gmail.com // See https://docs.shopify.com/themes/customization/navigation/link-product-options-in-menus // Modified by Jonathan Moore (Style Hatch) https://github.com/jonathanmoore /* Updated to work with sectioned themes - Added required methods from the deprecated options_selection.js - Triggers an initial variant change - Hides sold out variants with only one option */ window.addEventListener('DOMContentLoaded', function() { var Shopify = Shopify || {}; // Required functionality from depricated options_selection.js Shopify.arrayIncludes = function(e, t) { for (var n = 0; n < e.length; n++) if (e[n] == t) return !0; return !1 }, Shopify.uniq = function(e) { for (var t = [], n = 0; n < e.length; n++) Shopify.arrayIncludes(t, e[n]) || t.push(e[n]); return t } Shopify.optionsMap = {}; Shopify.updateOptionsInSelector = function(selectorIndex) { switch (selectorIndex) { case 0: var key = 'root'; var selector = jQuery('.single-option-selector:eq(0)'); break; case 1: var key = jQuery('.single-option-selector:eq(0)').val(); var selector = jQuery('.single-option-selector:eq(1)'); break; case 2: var key = jQuery('.single-option-selector:eq(0)').val(); key += ' / ' + jQuery('.single-option-selector:eq(1)').val(); var selector = jQuery('.single-option-selector:eq(2)'); } var initialValue = selector.val(); selector.empty(); var availableOptions = Shopify.optionsMap[key]; for (var i=0; i<availableOptions.length; i++) { var option = availableOptions[i]; var newOption = jQuery('<option></option>').val(option).html(option); selector.append(newOption); } jQuery('.swatch[data-option-index="' + selectorIndex + '"] .swatch-element').each(function() { if (jQuery.inArray($(this).attr('data-value'), availableOptions) !== -1) { $(this).removeClass('soldout').show().find(':radio').removeAttr('disabled','disabled').removeAttr('checked'); } else { $(this).addClass('soldout').hide().find(':radio').removeAttr('checked').attr('disabled','disabled'); } }); if (jQuery.inArray(initialValue, availableOptions) !== -1) { selector.val(initialValue); } selector.trigger('change'); }; Shopify.linkOptionSelectors = function(product) { // Building our mapping object. for (var i=0; i<product.variants.length; i++) { var variant = product.variants[i]; if (variant.available) { // Gathering values for the 1st drop-down. Shopify.optionsMap['root'] = Shopify.optionsMap['root'] || []; Shopify.optionsMap['root'].push(variant.option1); Shopify.optionsMap['root'] = Shopify.uniq(Shopify.optionsMap['root']); // Gathering values for the 2nd drop-down. if (product.options.length > 1) { var key = variant.option1; Shopify.optionsMap[key] = Shopify.optionsMap[key] || []; Shopify.optionsMap[key].push(variant.option2); Shopify.optionsMap[key] = Shopify.uniq(Shopify.optionsMap[key]); } // Gathering values for the 3rd drop-down. if (product.options.length === 3) { var key = variant.option1 + ' / ' + variant.option2; Shopify.optionsMap[key] = Shopify.optionsMap[key] || []; Shopify.optionsMap[key].push(variant.option3); Shopify.optionsMap[key] = Shopify.uniq(Shopify.optionsMap[key]); } } } // Update options right away. Shopify.updateOptionsInSelector(0); if (product.options.length > 1) Shopify.updateOptionsInSelector(1); if (product.options.length === 3) Shopify.updateOptionsInSelector(2); // When there is an update in the first dropdown. jQuery(".single-option-selector:eq(0)").change(function() { Shopify.updateOptionsInSelector(1); if (product.options.length === 3) Shopify.updateOptionsInSelector(2); return true; }); // When there is an update in the second dropdown. jQuery(".single-option-selector:eq(1)").change(function() { if (product.options.length === 3) Shopify.updateOptionsInSelector(2); return true; }); }; {% if product.available and product.options.size > 1 %} var $addToCartForm = $('form[action="/cart/add"]'); if (window.MutationObserver && $addToCartForm.length) { if (typeof observer === 'object' && typeof observer.disconnect === 'function') { observer.disconnect(); } var config = { childList: true, subtree: true }; var observer = new MutationObserver(function() { Shopify.linkOptionSelectors({{ product | json }}); observer.disconnect(); }); observer.observe($addToCartForm[0], config); } {% endif %} var selector = jQuery('.single-option-selector:eq(0)'); selector.trigger('change'); {% if product.options.size == 1 %} {% for variant in product.variants %} {% unless variant.available %} jQuery('.single-option-selector option').filter(function() { return jQuery(this).text().trim() === {{ variant.title | json }}; }).remove(); {% endunless %} {% endfor %} jQuery('.single-option-selector').trigger('change'); {% endif %} }); </script>
And I also added the Render tag to theme.liquid.
Because It's a paid theme I need to find its equivalent of the ".single-option-selector" tag on the snippet I've created.
After trying all day with no results, I would be grateful if someone could help me!
Store : https://shop-flm96.myshopify.com/
Thanks,
Frank
@Frank_LM The Class you're looking for in prestige is ".ProductForm__Item", but none of these will actually make the code run on the page. After Following instructions here, here and here, I've found none of the proposed solutions have worked for me. Super annoying, because I have a supplier breathing down my neck for displaying products I don't have in stock.
I'd also really like a solution to this problem - hundreds of products on our site has multiple options, and we've already had more than a few calls from customers angry they can't order a product that doesn't exist.
At risk of sounding like a massive whinger, I feel like variant linking should really be a native feature. The fact they aren't linked by default feels more like a bug than a feature.
@Frank_LM have you found a solution to hide unavailable variants on prestige theme yet?
Im trying to implement the same code in Prestige without luck, have you been able to find any solutions?
Any shopify experts on here want to address this? Also at the risk of sounding like a massive whinger, why the hell would Shopify sell a theme that wasn't coded to show sold out variants as grayed out or 'X"ed out, i'e, unavailable? Isn't that standard on retail websites? I wish there was a way to get my money back, didn't notice this until we started building our shop.
@maggie_m1 - this will need some theme coding edits to make this tweak, it is not a single line code, will take few hours to do it
That's true. Being a premium theme, I agree with @maggie_m1, it should have such an important functionality for the overall Customer Experience and the conversion % of the page.
Other premium themes such as District or Testament do this very well out of the box, while other themes such as Impulse have a different methodology to do achieve similar results. But with prestige, its just not possible without code customization.
I write this to help others find a theme with this functionality, to express my frustration with the Prestige Theme, and to maybe motivate Prestige to implement this.
Having known this from the beginning, I probably wouldn't have bought Prestige, but one of the previously mentioned themes.
I finally managed to custom my Prestige theme however this has huge limitation.
When the price has been changed, variants will be hidden or appear according to new price.
Limitation1:
First selected product needs to have all variant in the product.
This code doesn't show variants that first selected product doesn't have.
Limitation2:
This code supposes to have 2 option. It doesn't support more than 2 option.
This code would work at function _updateProductPrices in theme.js.
You can try inserting the code before if (!newVariant) { line.
var varOptions =[];
this.productData['variants'].forEach(function (variant) {
if(variant['option1'] !== null && newVariant !== null){
if (variant['option1'] === newVariant['option1']) {
varOptions.push(variant['option2']);
}
}
});
var varForm = this.element.querySelector('.ProductForm__Variants');
var varForm1= varForm.childNodes[1].childNodes[1];
for (var i = 0; i < varForm1.childNodes.length; i++) {
var li = varForm1.childNodes[i];
if(newVariant == null && (i+1 < varForm1.childNodes.length) ){ //hidden exepct order
li.hidden=true;
}else if(li !== null && varOptions !== null){
for (var j = 0; j < varOptions.length ; j++){
if(li.innerHTML.includes(varOptions[j])){
li.hidden=false;
break;
}else{
li.hidden=true;
}
}
}
}//end for
I hope this code helps someone and someone can help my code.
I'm just chipping to say I'm also really hoping that there is a way to hide unavailable (sold out) variants.
I might try your code Yo-da - but I'm not sure I understand the 2 limitations you have stated.
"First selected product needs to have all variant in the product." - please could you explain what this means exactly? What is the 'selected product'
"This code supposes to have 2 option. It doesn't support more than 2 option." - 2 options for what exactly?
thanks
This is an old thread, but the problem still persists. I did try your code, but discovered certain limitations. The unavailable variants don't hide unless you manually select the first variant (so when you first load a product, all of the variants are visible regardless of availability).
Also, for products with a single variant, it broke the ability to have the product image swap based on variant selected.
So I think this code definitely has promise, so I like your invitation "I hope this code helps someone and someone can help my code." If anyone has found the solution or updated this code...people are still trying to figure out how to hide unavailable variants on Prestige.
Following up, anyone have a solution yet? I'm also trying to grey-out or at the least hide sold out variants. Not having much luck.
@okw - it will need code editor, not a single line code, but can be done
Hi,
Just wondering if there has been any update with this?
I am wanting to grey out or cross out the unavailable variants similar to attached. Any help will be greatly appreciated!
Hello,
Wanted to know if you ever got this resolved.
I am looking for the same things.
Thanks
I ended up hiring someone to code it since I couldn't find a solution anywhere.
Hello, may you please provide contact info for the person you hired? I need this done for my site as well. It'd be a huge help.
Yes thank you
It will not allow a private message. May you please email me at Support@ebonywigcartel.com @okw
@EWCartel I think your private messaging is turned off. Check your settings-preference-private messenger
@okw This is weird but I clicked on my avatar, chose settings, and no option for messenger.
Is this it?
@okw Are you able to send me the contact details also? I never got this sorted 😞
Thank you so much!
I developed solution, where sold-out variants with a grey color, and available variants have a black color.
Are you ready to take your business to the next level? Look no further than the latest ...
By SarahF_Shopify Apr 15, 2024We’re keeping the ball rolling to make sure you’re always ahead of the game. So buckle ...
By JasonH Apr 8, 2024Portrait of Stephen positioned next to an image of planet Earth, with the Stephen's World ...
By JasonH Mar 18, 2024