Skip to content

Instantly share code, notes, and snippets.

@kyleboehlen
Created December 22, 2021 19:36
Show Gist options
  • Save kyleboehlen/fd4ce2f4d24a16b74b1e4a30c914f32d to your computer and use it in GitHub Desktop.
Save kyleboehlen/fd4ce2f4d24a16b74b1e4a30c914f32d to your computer and use it in GitHub Desktop.
Shopify Hide Unavailable Variants
<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
*/
/* Modified by Mark and Kyle Boehlen Dec 2021 https://www.kyleboehlen.com
- Added variables, moved call to product.liquid.
- Added switch (variable) to show sold out
- Added secound for loop to add in sold out variants into the selectors at the end
- Added reference to jquery in product.liquid
*/
// Set up some variables that identify the selection, in this theme it is located in product-form.liquid line 98
var selectionobject = '.form__input--select' // '.single-option-selector'
var select0 = selectionobject + ':eq(0)'
var select1 = selectionobject + ':eq(1)'
var select2 = selectionobject + ':eq(2)'
// Set up a variable as a switch for showing sold out items
var showsoldout = true
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(select0);
break;
case 1:
var key = jQuery(select0).val();
var selector = jQuery(select1);
break;
case 2:
var key = jQuery(select0).val();
key += ' / ' + jQuery(select1).val();
var selector = jQuery(select2);
}
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.
// Start with available variants
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]);
}
}
}
// If we are showing the sold out items - then we will add them in a second loop so that the selectors get instock options first
if (showsoldout) {
for (var s=0; s<product.variants.length; s++) {
var variant = product.variants[s];
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]);
}
}
}
} // End if soldout
// 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(select0).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(select1).change(function() {
if (product.options.length === 3) Shopify.updateOptionsInSelector(2);
return true;
});
};
// added - making the script fire on page load
Shopify.linkOptionSelectors({{ product | json}});
{% 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(select0);
selector.trigger('change');
{% if product.options.size == 1 %}
{% for variant in product.variants %}
{% unless variant.available %}
jQuery(select0).filter(function() { return jQuery(this).text().trim() === {{ variant.title | json }}; }).remove();
{% endunless %}
{% endfor %}
jQuery(select0).trigger('change');
{% endif %}
});
</script>
@Johneltonsbrain
Copy link

Is this supposed to work with Debut theme?

@ramizibrahimovic
Copy link

{% render 'product-options-linked' %}
Hi all, sorry for the noob question :/
i have the flex theme that does not have product.liquid and would love to try out the snippet. How can that be implemented?
Thanks a lot!
Best, Ramiz

@Pancakes04
Copy link

Any way for this work on 'Ride' 2.0 theme? This theme doesn't have a product.liquid section which is the only reason as to why this isn't working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment