Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<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
var Shopify = Shopify || {};
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 %}
</script>
@shuska7763

This comment has been minimized.

Copy link

commented Jul 12, 2016

Is it possible to have the options greyed out and disabled instead of hidden?

@DanWebb

This comment has been minimized.

Copy link

commented Sep 30, 2016

There's an issue in some themes that the elements won't have loaded in by the time this code runs (even when it's added at the very bottom of theme.liquid). In that case adding a $(function() { ... or equivalent surrounding lines 92-103 may help.

@superninja098

This comment has been minimized.

Copy link

commented Oct 21, 2016

To have the options greyed out & disabled, just remove this piece of code:

else {
  $(this).addClass('soldout').hide().find(':radio').removeAttr('checked').attr('disabled','disabled');
}
@LETSTRUCK

This comment has been minimized.

Copy link

commented Nov 10, 2016

I love this code and it worked for a couple of months. Now all of a sudden the options are not updating to only show what is available after the initial load of the page. When selecting a variant after the first option it says UNAVAILABLE rather than the normal ADD TO CART.

Any suggestions?

Thanks so much in advance, Aaron

@anark

This comment has been minimized.

Copy link

commented Nov 11, 2016

Shopify.uniq is no longer available so this is no longer working.

@darleenw

This comment has been minimized.

Copy link

commented Nov 11, 2016

Is there a an update to use in place of Shopify.uniq?

@MichalHoss

This comment has been minimized.

Copy link

commented Nov 21, 2016

I've found this video- it uses this snippets and it works: https://youtu.be/dNjMDv5kWig

@darleenw

This comment has been minimized.

Copy link

commented Nov 22, 2016

Thanks MichalHoss - the youtube does have slightly different method, and works.

@rmanke

This comment has been minimized.

Copy link

commented Nov 23, 2016

Seems to be working for me. Thanks!

Should I be worried it will stop working?

@MichalHoss

This comment has been minimized.

Copy link

commented Jan 11, 2017

Hi,
Can someone here help me with making this appear rtl? I can't find the part that creats the option's label before the select, so each of my "select" are right aligned, but the labels are floating (i guess) left..
I tried to use css but the page loads rtl and then it jumps back left..

@knauso

This comment has been minimized.

Copy link

commented Jan 26, 2017

There is a conflict when there is ONLY ONE variant option used on product page.
All is well when there are two or three variant options but in case client is using only one, then switch price/image or hiding the
undesired will not work properly

Changes to this piece of code, undesired has been commented out:

// 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]);
     // }
@xhorntail

This comment has been minimized.

Copy link

commented Jan 31, 2017

Any ideas on how to implement this in the new sectioned themes? I'm at a loss.

@maxp85

This comment has been minimized.

Copy link

commented Feb 14, 2017

I'm having the same issue than xhorntail with the sectioned theme Jumpstart. When I try this tutorial: https://help.shopify.com/themes/customization/navigation/link-product-options-in-menus , it works perfectly on my product page but not on the section featured product of my home page.

Did someone has the same issue and found a solution ?

@jonathanmoore

This comment has been minimized.

Copy link

commented Feb 24, 2017

I'm the creator of the premium District theme, and this question comes up extremely often in support. Now that all the themes have updated to sections, this great guide stopped working. I spent some time this afternoon modifying the snippet to work with some of the changes sectioned themes saw.

  • Added required methods from the deprecated options_selection.js
  • Triggers an initial variant change
  • Hides sold out variants with only one option (@knauso)

I have verified that it works with our District theme, and while it should work in theory with other sectioned themes it has not been tested.

https://gist.github.com/jonathanmoore/c0e0e503aa732bf1c05b7a7be4230c61

@simina89

This comment has been minimized.

Copy link

commented Jun 9, 2017

I read in one of the comments that in order to have the options greyed out & disabled, to remove a piece of code:
else {
$(this).addClass('soldout').hide().find(':radio').removeAttr('checked').attr('disabled','disabled');
}

The problem is that if I remove this piece of code, then the linked-options do not work anymore. Therefore the question is:
How to HIDE linked options BUT have DISABLED/GRAYED-OUT the products that are out of stock?

For example:
T-Shirt has 2 sizes and 3 colors as follows:
Sizes: S and M
Color: Black - available only for size S
Color: Blue - available for both size S and M
Color: White - available for both size S and M
Color White for size M is SOLD OUT

So in this context, I would like for color Black not be visible for size M, and color white to visible but grayed out for size M

What are the changes to be made to the above posted code to make this work?

Many thanks.

@namurray

This comment has been minimized.

Copy link

commented Jul 25, 2017

@simina89 - uncomment that line and instead remove .hide() from it. So should look like this:

$(this).addClass('soldout').hide().find(':radio').removeAttr('checked').attr('disabled','disabled');

you can also go ahead and remove .show() from the line above so it looks like:

$(this).removeClass('soldout').find(':radio').removeAttr('disabled','disabled').removeAttr('checked');

both .hide() and .show() are jQuery buddies that do exactly what they say they do, so you're just taking away that behavior.
so long as the class .soldout has style applied to it you should be good to go.

@rajat-143

This comment has been minimized.

Copy link

commented Oct 23, 2017

How To add please select option with this code. I have added this code and now by default variants are selected. I want please select option in the drop down and main image will show rather than showing first variant with image as default.

Thanks

@KevinHitchins

This comment has been minimized.

Copy link

commented Nov 11, 2017

I have the OOTSB Turbo theme. The code works in the editor but when viewing on the Live page the product page needs to be refreshed each time for the code to work. Any ideas how I can fix this?

@babyoriginals

This comment has been minimized.

Copy link

commented Dec 20, 2017

I have the same problem as you KevinHitchins - page needs to be refreshed to get this to work. Have you had any luck since?

@ghost

This comment has been minimized.

Copy link

commented Jan 25, 2018

KevinHitchins and babyoriginals, I'm also wanting to use the OOTSB Turbo theme and have not been able to replace my existing theme for the same reason. Reached out to both Shopify support and OOTSB support, but neither were able to resolve the issue or commit to a future fix/update. Unfortunately my store absolutely requires this functionality so am completely out of luck until it is resolved. Shopify "Experts" have also been reluctant to try to fix this. Did either one of you manage to get this working yet? If so, please post an update to these comments, and I will do the same. Thank you.

@davidbowick

This comment has been minimized.

Copy link

commented Jan 31, 2018

Is it possible to get an update for Slate?

@codinginfotech

This comment has been minimized.

Copy link

commented Feb 6, 2018

use "jQuery.unique" in the place of "Shopify.uniq"

@realbaker

This comment has been minimized.

Copy link

commented Feb 7, 2018

This code works great on the product detail page, however it does not get applied within the Quick Shop modal window. I've got {% include 'linked-options' %} at the end of my theme.liquid file, but I'm not sure if the scripts need to be added somewhere else to work within the quick shop modal (it's fancybox with the Mobilia OOTSB theme). Any help would be greatly appreciated!

@uzairqadeer

This comment has been minimized.

Copy link

commented Mar 13, 2018

Uncaught TypeError: Shopify.uniq is not a function
I am seeing this error
How can i solve that?

@ghost

This comment has been minimized.

Copy link

commented Jul 11, 2018

I'm having the same problem as several others, the page needs to be manually refreshed each time to get this to work. Still wanting to use the OOTSB Turbo Theme. Very frustrating. Please let me know if you figured this out. Cheers!

@sanzencode

This comment has been minimized.

Copy link

commented Jul 13, 2018

I get a page jump to the top after completion of selections I am trying to stop. I think it relates to this piece of code. Anyone have any thoughts on what in the code snippet can be causing that? How to stop it? Thanks!!

@MrLenh

This comment has been minimized.

Copy link

commented Sep 5, 2018

i'm using Debut Theme and after implement this, nothing is happen. Anyone can help me?

@Retrogresison

This comment has been minimized.

Copy link

commented Sep 12, 2018

This code works great for us using the Fasionopolism theme but - how do we only hide unavailable variants (such as a color/size that doesn't exist) and leave sold out variants to still show up but say 'sold out'?

@thousandzero

This comment has been minimized.

Copy link

commented Sep 18, 2018

Hey Please help me. Everything tried but not working for me.

jQuery(function($) {
{% if product.available and product.variants.size > 1 %}
new Shopify.OptionSelectors('product-selectors', {
product: {{ product | json }},
onVariantSelected: selectCallback,
enableHistoryState: true
});

{% comment %}
Use color swatch and linked options (copyright by @carolineschnapp)
{% endcomment %}
{% if section.settings.use_color_swatch and product.available and product.options.size > 1 %}
Shopify.linkOptionSelectors({{ product | json }});
{% endif %} 

{% if section.settings.use_color_swatch != true %}
jQuery('.single-option-selector').selectize();
jQuery('.selectize-input input').attr("disabled","disabled");
{% endif %}

{% endif %}
@eddyparkinson

This comment has been minimized.

Copy link

commented Oct 23, 2018

Uncaught TypeError: Shopify.uniq is not a function

Fix 1

From https://ecommerce.shopify.com/c/ecommerce-design/t/how-to-hide-irrelevant-variant-in-debut-theme-385309

var Shopify = Shopify || {};
  
  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 = {};

Fix 2

@codinginfotech says

use "jQuery.unique" in the place of "Shopify.uniq"

@jodiedwards09

This comment has been minimized.

Copy link

commented Oct 30, 2018

I have tried this on symmetry theme but its not working can anyone help please?

@chefmungus

This comment has been minimized.

Copy link

commented Jan 22, 2019

@eddyparkinson I implemented both these fixes as well as removing defer="defer" from the vendor.js load and still nothing doing. Preview link below, any help would be much appreciated.

https://8hk4yjvzez82ip57-1011974210.shopifypreview.com - Navigate to the Hats product in the catalog for the best example.

Uncaught TypeError: Shopify.uniq is not a function

Fix 1

From https://ecommerce.shopify.com/c/ecommerce-design/t/how-to-hide-irrelevant-variant-in-debut-theme-385309

var Shopify = Shopify || {};
  
  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 = {};

Fix 2

@codinginfotech says

use "jQuery.unique" in the place of "Shopify.uniq"

@impactcolor

This comment has been minimized.

Copy link

commented Jan 29, 2019

I'm getting Cannot read property 'length' of undefined on the loop that goes on
availableOptions = Shopify.optionsMap[key];
any idea how to solve this?

@VickyFi

This comment has been minimized.

Copy link

commented Jul 4, 2019

Hello, I get this error "availableOptions is undefined". Do you have any suggestions for that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.