1function createCombinationsBehavior(settings) { 2 var defaultSettings = { 3 contentEl: false, 4 fetchUrl: false 5 }; 6 7 return { 8 settings: $.extend({}, defaultSettings, settings), 9 params: { 10 availableCombinations: [], 11 availableAttributeIds: [] 12 }, 13 14 init: function () { 15 var $contentEl = $(this.settings.contentEl); 16 var $attributes = $('[data-attr]', $contentEl); 17 if ($attributes && $attributes.length > 0) { 18 var self = this; 19 20 $.each($attributes, function (i, attribute) { 21 var id = parseInt($(attribute).data('attr')); 22 self.params.availableAttributeIds.push(id); 23 }); 24 25 $attributes.on('change', function () { 26 self.processCombinations(); 27 }); 28 } 29 30 this.loadCombinations(); 31 }, 32 33 loadCombinations: function () { 34 var self = this; 35 36 $.ajax({ 37 cache: false, 38 url: self.settings.fetchUrl, 39 type: 'GET', 40 success: function (response) { 41 self.params.availableCombinations = response; 42 43 var selectedAttributes = self.getSelectedAttributes(); 44 if (selectedAttributes && selectedAttributes.length > 0) { 45 // unselect selected values if they are preselected but not available 46 var availableAttributes = $.grep(selectedAttributes, function (attribute) { 47 return attribute.values.length > 0; 48 }); 49 $.each(availableAttributes, function (i, attribute) { 50 var combinations = self.getCombinationsByAttributeId(attribute.id, [attribute]); 51 if (combinations && combinations.length > 0) { 52 if (!self.isAvailableCombination(combinations, [attribute])) { 53 self.unselectValues(attribute.values); 54 } 55 } else { 56 self.unselectValues(attribute.values); 57 } 58 }); 59 60 } 61 62 self.processCombinations(); 63 }, 64 error: function () { 65 self.params.availableCombinations = []; 66 } 67 }); 68 }, 69 70 processCombinations: function () { 71 var availableAttributeIds = this.params.availableAttributeIds; 72 if (availableAttributeIds.length === 0) 73 return; 74 75 var self = this; 76 77 // disable all attribute values if combinations isn't available 78 var availableCombinations = this.params.availableCombinations; 79 if (availableCombinations.length === 0) { 80 var valueIds = this.getAttributeValueIds(); 81 $.each(valueIds, function (i, valueId) { 82 self.toggleAttributeValue(valueId, false); 83 }); 84 85 return; 86 } 87 88 var selectedAttributes = self.getSelectedAttributes(); 89 90 $.each(availableAttributeIds, function (attrIndex, attributeId) { 91 var attibuteValueIds = self.getAttributeValueIds(attributeId); 92 $.each(attibuteValueIds, function (i, valueId) { 93 // get only previous attributes (if any) excluding the selection by current attribute 94 // and then check the combinations stock with current value 95 var availableAttributes = $.grep(selectedAttributes, function (attribute, selectedAttrIndex) { 96 return attrIndex > selectedAttrIndex && attribute.id !== attributeId && attribute.values.length > 0; 97 }); 98 availableAttributes.push({ id: attributeId, values: [valueId] }); 99 100 // check if available attributes exists in combinations 101 // otherwise just disable the value 102 var combinations = self.getCombinationsByAttributeId(attributeId, availableAttributes); 103 if (combinations && combinations.length > 0) { 104 self.toggleAttributeValue(valueId, self.isAvailableCombination(combinations, availableAttributes)); 105 } else { 106 self.toggleAttributeValue(valueId, false); 107 } 108 }); 109 }); 110 111 $(this).trigger({ type: "processed" }); 112 }, 113 114 getCombinationsByAttributeId: function (attributeId, processedAttributes) { 115 var availableCombinations = this.params.availableCombinations; 116 if (availableCombinations.length === 0) { 117 return; 118 }; 119 120 return $.grep(availableCombinations, function (combination) { 121 var found = $.grep(combination.Attributes, function (attribute) { 122 return attribute.Id === attributeId; 123 })[0]; 124 125 if (processedAttributes && processedAttributes.length > 0) { 126 $.each(processedAttributes, function (i, processedAttribute) { 127 found = found && $.grep(combination.Attributes, function (attribute) { 128 var attrbiuteIsFound = attribute.Id === processedAttribute.id; 129 130 // exclude unselected attribute values 131 if (processedAttribute.values.length > 0) { 132 $.each(processedAttribute.values, function (i, id) { 133 attrbiuteIsFound = attrbiuteIsFound && $.inArray(id, attribute.ValueIds) !== -1 134 }); 135 } 136 137 return attrbiuteIsFound; 138 })[0]; 139 }); 140 } 141 142 return found; 143 }); 144 }, 145 146 isAvailableCombination: function (combinations, attributes) { 147 // check if any combination have stock with specified values 148 // otherwise just disable the value 149 var existedCombinations = $.grep(combinations, function (combination) { 150 var valueIdsByCombinations = $.map(combination.Attributes, function (attribute) { 151 return attribute.ValueIds; 152 }); 153 var existedAttributes = $.grep(attributes, function (attribute) { 154 return $.grep(attribute.values, function (valueId) { 155 return $.inArray(valueId, valueIdsByCombinations) !== -1; 156 }) 157 }); 158 159 return combination.InStock && existedAttributes.length === attributes.length; 160 }); 161 162 return existedCombinations.length > 0;
163 }, 164 165 getAttributeValueIds: function (attributeId) { 166 var $contentEl = $(this.settings.contentEl); 167 var $scope = attributeId ? $('[data-attr=' + attributeId + ']', $contentEl) : $contentEl; 168 var $valueItems = $('[data-attr-value]', $scope); 169 if ($valueItems) { 170 return $.map($valueItems, function (item) { 171 return parseInt($(item).data('attr-value')); 172 }); 173 } 174 }, 175 176 toggleAttributeValue: function (valueId, enabled) { 177 var $contentEl = $(this.settings.contentEl); 178 var $value = $('[data-attr-value=' + valueId + ']', $contentEl); 179 if (enabled) { 180 $value.removeClass('disabled'); 181 } else { 182 $value.addClass('disabled'); 183 } 184 }, 185 186 unselectValues: function (valueIds) { 187 var $contentEl = $(this.settings.contentEl); 188 $.each(valueIds, function (i, valueId) { 189 var $value = $('[data-attr-value=' + valueId + ']', $contentEl); 190 $value.prop('selected', false); 191 $('input', $value).prop('checked', false); 192 // for image square 193 $value.removeClass('selected-value'); 194 }); 195 }, 196 197 getSelectedAttributes: function () { 198 var availableAttributeIds = this.params.availableAttributeIds; 199 if (availableAttributeIds.length > 0) { 200 var $contentEl = $(this.settings.contentEl); 201 202 return $.map(availableAttributeIds, function (attributeId) { 203 var selectedValues = []; 204 205 var $attribute = $('[data-attr=' + attributeId + ']', $contentEl); 206 var $attributeValues = $('[data-attr-value]', $attribute); 207 if ($attributeValues && $attributeValues.length > 0) { 208 $.each($attributeValues, function (i, value) { 209 var $value = $(value); 210 if ($value.is(':selected') || $('input', $value).is(':checked')) { 211 var id = parseInt($value.data('attr-value')); 212 selectedValues.push(id); 213 } 214 }); 215 } 216 217 return { 218 id: attributeId, 219 values: selectedValues 220 } 221 }); 222 } 223 } 224 } 225}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.