Skip to content

Instantly share code, notes, and snippets.

@kyleboehlen
Created December 22, 2021 19:36
Show Gist options
  • Select an option

  • Save kyleboehlen/fd4ce2f4d24a16b74b1e4a30c914f32d to your computer and use it in GitHub Desktop.

Select an option

Save kyleboehlen/fd4ce2f4d24a16b74b1e4a30c914f32d to your computer and use it in GitHub Desktop.

Revisions

  1. kyleboehlen created this gist Dec 22, 2021.
    189 changes: 189 additions & 0 deletions product-options-linked.liquid
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,189 @@
    <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>