Skip to content

Instantly share code, notes, and snippets.

@mr-pinzhang
Created January 23, 2025 15:10
Show Gist options
  • Save mr-pinzhang/b5c6da7fa912b271f32f3a64915a2018 to your computer and use it in GitHub Desktop.
Save mr-pinzhang/b5c6da7fa912b271f32f3a64915a2018 to your computer and use it in GitHub Desktop.
function uniq(arr) {
return Array.from(new Set(arr));
}
function createOptionsMap(productJsonMap) {
const nextOptionMap = new Map();
for (const variant of productJsonMap.variants) {
if (!variant.available) continue;
let optionKey = 'root';
let options = nextOptionMap.get(optionKey) ?? [];
options.push(variant.option1);
nextOptionMap.set(optionKey, uniq(options));
if (productJsonMap.options.length > 1) {
optionKey = variant.option1;
options = nextOptionMap.get(optionKey) ?? [];
options.push(variant.option2);
nextOptionMap.set(optionKey, uniq(options));
}
if (productJsonMap.options.length === 3) {
optionKey = [variant.option1, variant.option2].join('/');
options = nextOptionMap.get(optionKey) ?? [];
options.push(variant.option3);
nextOptionMap.set(optionKey, uniq(options));
}
}
return nextOptionMap;
}
function getInputs() {
return document.querySelectorAll(`[data-type=swatches] input[type=radio]`);
}
function getInputBy(value) {
return document.querySelectorAll(`[data-type=swatches] input[type=radio][value=${value}]`)[0];
}
function getInputLabelBy(value) {
const input = getInputBy(value);
return document.querySelectorAll(`[data-type=swatches] label[for=${input.id}]`)[0];
}
function hideOption(value) {
const label = getInputLabelBy(value);
label.hidden = true;
}
function showOption(value) {
const label = getInputLabelBy(value);
label.hidden = false;
}
function renderOptionsBy(optionsMap) {
let availableOptions = [];
const rootOptions = optionsMap.get('root');
for (const rootOption of rootOptions) {
const rootInput = getInputBy(rootOption);
if (!rootInput.checked) continue;
availableOptions.push(rootOption);
const secondaryOptions = optionsMap.get(rootOption);
for (const secondaryOption of secondaryOptions) {
availableOptions.push(secondaryOption);
const tertiaryOptions = optionsMap.get([rootOption, secondaryOption].join('/'));
for (const tertiaryOption of tertiaryOptions) {
availableOptions.push(tertiaryOption);
}
}
}
availableOptions = uniq(availableOptions);
getInputs().forEach((input) => {
const value = input.value;
if (availableOptions.includes(value)) {
showOption(value);
} else {
hideOption(value);
}
});
}
{% if product.available and product.options.size > 1 %}
const optionsMap = createOptionsMap({{ product | json }});
const renderOptions = () => renderOptionsBy(optionsMap);
const form = document.querySelectorAll('form[action="/cart/add"]');
if (window.MutationObserver && form.length) {
if (typeof observer === 'object' && typeof observer.disconnect === 'function') {
observer.disconnect();
}
const observer = new MutationObserver(() => {
renderOptions();
getInputs().forEach((input) => {
input.removeEventListener('change', renderOptions);
input.addEventListener('change', renderOptions);
});
observer.disconnect();
});
observer.observe(form[0], {childList: true, subtree: true});
}
{% endif %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment