forked from JonoHall/linked-options
-
Notifications
You must be signed in to change notification settings - Fork 0
/
linked-options.liquid
87 lines (76 loc) · 3.52 KB
/
linked-options.liquid
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<script>
const products = {{ product | json }};
const options = {{ product.options | json }};
//check if there is a variant in the url (i.e. ?variant=123), also validate it
const urlParams = new URLSearchParams(window.location.search);
const urlVariantId = (urlParams.has('variant') && (products.variants.filter((item)=>item["id"] == urlParams.get('variant')).length > 0)) ? urlParams.get('variant') : false;
const seletedVariant = (urlVariantId) ? products.variants.filter((item)=>item["id"] == urlVariantId)[0] : false;
const selectContainer = document.getElementsByClassName("product-form__input product-form__input--dropdown");
const selects = document.getElementsByClassName("select__select");
//adds the default option i.e. "Select Type..."
function setDefaultOption(select,selected = false) {
optionText = "Select " + select.productOption + "...";
select.add(new Option(optionText), select[0]);
if(selected == false || !seletedVariant){
select.selectedIndex = 0;
}
}
function removeUrlVariant() {
window.history.replaceState('object', document.title, location.href.replace(location.search, ''));
}
//removes all the options of a select so it can be rebuilt
function removeOptions(select) {
var i, L = select.options.length - 1;
for(i = L; i >= 0; i--) {
select.remove(i);
}
}
//generates valid options based on the parent selector
function validOptions(select,parent) {
if(parent.selectedIndex == 0) {
select.selectedIndex = 0;
selectContainer[select.optionIndex].style.display = 'none';
} else {
removeOptions(select);
setDefaultOption(select);
var optionText = "option"+select.optionIndex;
var childOptionText = "option"+(select.optionIndex + 1);
//(filter)get a list of valid variants, (map)create a new array from the option propery, (set)get a set of unique elements
var filteredVariants = new Set(products.variants.filter((item)=>item[optionText] === parent.value).map(a => a[childOptionText]));
filteredVariants.forEach(function(variant) {
var selectOption = new Option(variant,variant);
selectOption.selected = (variant == seletedVariant[childOptionText]);
select.add(selectOption);
});
}
}
function updateChildSelect(select,parentSelect) {
if(parentSelect.selectedIndex == 0) {
select.selectedIndex = 0;
selectContainer[select.optionIndex].style.display = 'none';
} else {
validOptions(select,parentSelect);
selectContainer[select.optionIndex].style.display = '';
}
}
options.forEach(function(productOption, selectPos) {
const select = selects[selectPos];
select.optionIndex = selectPos;
select.productOption = productOption;
(select.optionIndex == 0) ? setDefaultOption(select, seletedVariant) : validOptions(select,selects[select.optionIndex-1]);
if(select.optionIndex < (options.length - 1)){
select.addEventListener('change', function(){
updateChildSelect(selects[select.optionIndex+1],select);
});
}
select.addEventListener('change', function(){ removeUrlVariant() });
});
//fixes Chrome autofill of the selectors when moving back/forward through page history. Not ideal as it will refresh the selectors after displaying them. Not sure how to improve.
window.onpageshow = function() {
if(selects[0].selectedIndex != 0 && !seletedVariant){
selects[0].selectedIndex = 0;
selects[0].dispatchEvent(new Event("change", { bubbles: true }));
}
selects[0].dispatchEvent(new Event("change", { bubbles: true }));
};
</script>