225 lines
7.8 KiB
JavaScript
225 lines
7.8 KiB
JavaScript
function createCombinationsBehavior(settings) {
|
|
var defaultSettings = {
|
|
contentEl: false,
|
|
fetchUrl: false
|
|
};
|
|
|
|
return {
|
|
settings: $.extend({}, defaultSettings, settings),
|
|
params: {
|
|
availableCombinations: [],
|
|
availableAttributeIds: []
|
|
},
|
|
|
|
init: function () {
|
|
var $contentEl = $(this.settings.contentEl);
|
|
var $attributes = $('[data-attr]', $contentEl);
|
|
if ($attributes && $attributes.length > 0) {
|
|
var self = this;
|
|
|
|
$.each($attributes, function (i, attribute) {
|
|
var id = parseInt($(attribute).data('attr'));
|
|
self.params.availableAttributeIds.push(id);
|
|
});
|
|
|
|
$attributes.on('change', function () {
|
|
self.processCombinations();
|
|
});
|
|
}
|
|
|
|
this.loadCombinations();
|
|
},
|
|
|
|
loadCombinations: function () {
|
|
var self = this;
|
|
|
|
$.ajax({
|
|
cache: false,
|
|
url: self.settings.fetchUrl,
|
|
type: 'GET',
|
|
success: function (response) {
|
|
self.params.availableCombinations = response;
|
|
|
|
var selectedAttributes = self.getSelectedAttributes();
|
|
if (selectedAttributes && selectedAttributes.length > 0) {
|
|
// unselect selected values if they are preselected but not available
|
|
var availableAttributes = $.grep(selectedAttributes, function (attribute) {
|
|
return attribute.values.length > 0;
|
|
});
|
|
$.each(availableAttributes, function (i, attribute) {
|
|
var combinations = self.getCombinationsByAttributeId(attribute.id, [attribute]);
|
|
if (combinations && combinations.length > 0) {
|
|
if (!self.isAvailableCombination(combinations, [attribute])) {
|
|
self.unselectValues(attribute.values);
|
|
}
|
|
} else {
|
|
self.unselectValues(attribute.values);
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
self.processCombinations();
|
|
},
|
|
error: function () {
|
|
self.params.availableCombinations = [];
|
|
}
|
|
});
|
|
},
|
|
|
|
processCombinations: function () {
|
|
var availableAttributeIds = this.params.availableAttributeIds;
|
|
if (availableAttributeIds.length === 0)
|
|
return;
|
|
|
|
var self = this;
|
|
|
|
// disable all attribute values if combinations isn't available
|
|
var availableCombinations = this.params.availableCombinations;
|
|
if (availableCombinations.length === 0) {
|
|
var valueIds = this.getAttributeValueIds();
|
|
$.each(valueIds, function (i, valueId) {
|
|
self.toggleAttributeValue(valueId, false);
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
var selectedAttributes = self.getSelectedAttributes();
|
|
|
|
$.each(availableAttributeIds, function (attrIndex, attributeId) {
|
|
var attibuteValueIds = self.getAttributeValueIds(attributeId);
|
|
$.each(attibuteValueIds, function (i, valueId) {
|
|
// get only previous attributes (if any) excluding the selection by current attribute
|
|
// and then check the combinations stock with current value
|
|
var availableAttributes = $.grep(selectedAttributes, function (attribute, selectedAttrIndex) {
|
|
return attrIndex > selectedAttrIndex && attribute.id !== attributeId && attribute.values.length > 0;
|
|
});
|
|
availableAttributes.push({ id: attributeId, values: [valueId] });
|
|
|
|
// check if available attributes exists in combinations
|
|
// otherwise just disable the value
|
|
var combinations = self.getCombinationsByAttributeId(attributeId, availableAttributes);
|
|
if (combinations && combinations.length > 0) {
|
|
self.toggleAttributeValue(valueId, self.isAvailableCombination(combinations, availableAttributes));
|
|
} else {
|
|
self.toggleAttributeValue(valueId, false);
|
|
}
|
|
});
|
|
});
|
|
|
|
$(this).trigger({ type: "processed" });
|
|
},
|
|
|
|
getCombinationsByAttributeId: function (attributeId, processedAttributes) {
|
|
var availableCombinations = this.params.availableCombinations;
|
|
if (availableCombinations.length === 0) {
|
|
return;
|
|
};
|
|
|
|
return $.grep(availableCombinations, function (combination) {
|
|
var found = $.grep(combination.Attributes, function (attribute) {
|
|
return attribute.Id === attributeId;
|
|
})[0];
|
|
|
|
if (processedAttributes && processedAttributes.length > 0) {
|
|
$.each(processedAttributes, function (i, processedAttribute) {
|
|
found = found && $.grep(combination.Attributes, function (attribute) {
|
|
var attrbiuteIsFound = attribute.Id === processedAttribute.id;
|
|
|
|
// exclude unselected attribute values
|
|
if (processedAttribute.values.length > 0) {
|
|
$.each(processedAttribute.values, function (i, id) {
|
|
attrbiuteIsFound = attrbiuteIsFound && $.inArray(id, attribute.ValueIds) !== -1
|
|
});
|
|
}
|
|
|
|
return attrbiuteIsFound;
|
|
})[0];
|
|
});
|
|
}
|
|
|
|
return found;
|
|
});
|
|
},
|
|
|
|
isAvailableCombination: function (combinations, attributes) {
|
|
// check if any combination have stock with specified values
|
|
// otherwise just disable the value
|
|
var existedCombinations = $.grep(combinations, function (combination) {
|
|
var valueIdsByCombinations = $.map(combination.Attributes, function (attribute) {
|
|
return attribute.ValueIds;
|
|
});
|
|
var existedAttributes = $.grep(attributes, function (attribute) {
|
|
return $.grep(attribute.values, function (valueId) {
|
|
return $.inArray(valueId, valueIdsByCombinations) !== -1;
|
|
})
|
|
});
|
|
|
|
return combination.InStock && existedAttributes.length === attributes.length;
|
|
});
|
|
|
|
return existedCombinations.length > 0;
|
|
},
|
|
|
|
getAttributeValueIds: function (attributeId) {
|
|
var $contentEl = $(this.settings.contentEl);
|
|
var $scope = attributeId ? $('[data-attr=' + attributeId + ']', $contentEl) : $contentEl;
|
|
var $valueItems = $('[data-attr-value]', $scope);
|
|
if ($valueItems) {
|
|
return $.map($valueItems, function (item) {
|
|
return parseInt($(item).data('attr-value'));
|
|
});
|
|
}
|
|
},
|
|
|
|
toggleAttributeValue: function (valueId, enabled) {
|
|
var $contentEl = $(this.settings.contentEl);
|
|
var $value = $('[data-attr-value=' + valueId + ']', $contentEl);
|
|
if (enabled) {
|
|
$value.removeClass('disabled');
|
|
} else {
|
|
$value.addClass('disabled');
|
|
}
|
|
},
|
|
|
|
unselectValues: function (valueIds) {
|
|
var $contentEl = $(this.settings.contentEl);
|
|
$.each(valueIds, function (i, valueId) {
|
|
var $value = $('[data-attr-value=' + valueId + ']', $contentEl);
|
|
$value.prop('selected', false);
|
|
$('input', $value).prop('checked', false);
|
|
// for image square
|
|
$value.removeClass('selected-value');
|
|
});
|
|
},
|
|
|
|
getSelectedAttributes: function () {
|
|
var availableAttributeIds = this.params.availableAttributeIds;
|
|
if (availableAttributeIds.length > 0) {
|
|
var $contentEl = $(this.settings.contentEl);
|
|
|
|
return $.map(availableAttributeIds, function (attributeId) {
|
|
var selectedValues = [];
|
|
|
|
var $attribute = $('[data-attr=' + attributeId + ']', $contentEl);
|
|
var $attributeValues = $('[data-attr-value]', $attribute);
|
|
if ($attributeValues && $attributeValues.length > 0) {
|
|
$.each($attributeValues, function (i, value) {
|
|
var $value = $(value);
|
|
if ($value.is(':selected') || $('input', $value).is(':checked')) {
|
|
var id = parseInt($value.data('attr-value'));
|
|
selectedValues.push(id);
|
|
}
|
|
});
|
|
}
|
|
|
|
return {
|
|
id: attributeId,
|
|
values: selectedValues
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} |