-
-
Save kyleboehlen/fd4ce2f4d24a16b74b1e4a30c914f32d to your computer and use it in GitHub Desktop.
<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> |
Hi,
How can I make this work in Venture theme? Thank you
Which theme was this tested on ? It is not mentioned in the comments and I have yet to find one with the hook you describe on line 21
Thx
@MrBillium I don't remember, but that class can be changed to whatever the class is in your theme.
Any update on this? I'm using dawn theme 3.0
I am very new to this but i followed the instructions exactly as posted and it is still offering options and showing them as unavailable. I am using the Masonry theme if that matters. Thank you in advance for your assistance.
// linked-options.liquid file in my theme:
<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').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 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 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>Caroline’s snippet won’t work with 2.0 themes and as far as I can tell, it hasn’t been solidly updated by anyone who has shared the code.
- This may be the most promising attempt currently, for Dawn theme. However there isn’t much feedback and I haven’t tried it myself yet.
- Here is a well-explained issue on the official Dawn repo, it’s worthwhile to follow it and add a comment or thumb-up adding your support as it's currently the 2nd most-commented issue of 500+ in the official repo, but don’t dump your shop code there, it’s not a place for personal code support. If this has enough support, maybe Shopify or some developer will solidly solve the issue for everyone. Most themes going forward will be based on Dawn so if there’s a solution on Dawn it’s likely to work on many themes.
Is this supposed to work with Debut theme?
{% 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
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.
This gist needs to be added to a new snippet called product-options-linked.liquid
The following also needs to be added to product.liquid