{ "version": 3, "sources": [ "../../../../../Foundation/JavascriptCommon/code/scripts/common/formUtils.js", "../../../../../Foundation/JavascriptCommon/code/scripts/common/alertMessage.js", "../../../../../Foundation/JavascriptCommon/code/scripts/common/spinner.js", "../../../../Order/code/scripts/app/Cart/cartOperations.js", "Configurator/main.js" ], "names": [], "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACrHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC7MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "file": "Configurator.js", "sourcesContent": [ "define('common/formUtils',[\r\n],\r\n function () {\r\n\r\n // Clears and deactivates all invalid feedback text on form fields\r\n function clearInvalidFeedback(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" .is-invalid\").removeClass(\"is-invalid\");\r\n $(formId + \" .invalid-feedback\").empty();\r\n }\r\n\r\n // Fills in and activates invalid feedback text on form fields\r\n function displayInvalidFeedback(invalidFields, formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n if (invalidFields) {\r\n invalidFields.forEach(function (fieldMessage) {\r\n var field = $(formId + \" [name='\" + fieldMessage.FieldName + \"']\");\r\n field.addClass(\"is-invalid\");\r\n field.siblings(\".invalid-feedback\").append(fieldMessage.MessageText);\r\n });\r\n }\r\n }\r\n\r\n // Collects the data from all form fields and returns them as object,\r\n // using \"name\" attribute values from form fields as object property names.\r\n function collectFormData(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n // the serializeArray() jQuery method doesn't take the values from disabled fields, so first I'll\r\n // temporarily enable all disabled fields, and then disable them again\r\n var disabledFields = $(formId).find(\":input:disabled\").prop(\"disabled\", false);\r\n var serializedData = $(formId).serializeArray();\r\n disabledFields.prop(\"disabled\", true);\r\n var formData = {};\r\n serializedData.forEach(function (data) {\r\n formData[data.name] = data.value;\r\n });\r\n // serializeArray does not return anything for unchecked checkboxes, so we'll add them now with value false\r\n $(formId + \" input[type='checkbox']:not(:checked)\").each(function (index, element) {\r\n formData[element.name] = false;\r\n });\r\n // serializeArray returns \"on\" for checked checkboxes, so we'll set them to true now\r\n $(formId + \" input[type='checkbox']:checked\").each(function (index, element) {\r\n formData[element.name] = true;\r\n });\r\n return formData;\r\n }\r\n\r\n // Goes through all input elements on the form and fills them with data from the\r\n // given object, matching \"name\" attribute of the input element with object property name.\r\n function populateFormWithData(formId, data) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" :input\").each(function (index, element) { \r\n if (element.type === \"radio\" ||\r\n element.type === \"checkbox\")\r\n {\r\n if (data[element.name] !== undefined)\r\n $(element).prop(\"checked\", $(element).val().toString() === data[element.name].toString());\r\n }\r\n else if (element.type === \"text\" ||\r\n element.type === \"email\" ||\r\n element.type === \"tel\" ||\r\n element.type === \"password\" ||\r\n element.type === \"textarea\" ||\r\n element.type === \"select-one\")\r\n {\r\n if (data[element.name] !== undefined)\r\n $(element).val(data[element.name]);\r\n else\r\n $(element).val(null);\r\n }\r\n });\r\n }\r\n\r\n function disableFields(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" :input\").prop(\"disabled\", true);\r\n }\r\n\r\n function enableFields(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" :input\").prop(\"disabled\", false);\r\n }\r\n\r\n function initializeFloatingLabels(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" .floating-label-container\").each(function (index, element) {\r\n var inputElement = $(element).find(\":input\")[0];\r\n if (inputElement.value) $(element).addClass(\"active\");\r\n else $(element).removeClass(\"active\");\r\n });\r\n }\r\n\r\n function setFocus(selector, delay) {\r\n // sometimes focus has to be set with a delay, so that some other processes have time to finish before that (e.g. initializing floating labels)\r\n if (delay) setTimeout(() => { $(selector).focus(); }, delay);\r\n else $(selector).focus();\r\n }\r\n\r\n //adds the form token to the object for use with [ValidateAntiforgeryToken] attribute\r\n function useToken(data) { \r\n var token = $('input[name=\"__RequestVerificationToken\"]').val();\r\n data.__RequestVerificationToken = token;\r\n }\r\n\r\n return {\r\n clearInvalidFeedback: clearInvalidFeedback,\r\n displayInvalidFeedback: displayInvalidFeedback,\r\n collectFormData: collectFormData,\r\n populateFormWithData: populateFormWithData,\r\n disableFields: disableFields,\r\n enableFields: enableFields,\r\n initializeFloatingLabels: initializeFloatingLabels,\r\n setFocus: setFocus,\r\n useToken: useToken\r\n };\r\n });\r\n\n", "define('common/alertMessage',[\r\n],\r\n function () {\r\n\r\n const alertSelector = \"#alertMessage\";\r\n const allButtonsSelector = alertSelector + \" .modal-footer button\";\r\n const positions = {\r\n center: \"modal-dialog-centered\",\r\n top: \"modal-dialog-top\"\r\n };\r\n const defaultOptions = {\r\n position: \"center\",\r\n customClass: \"\"\r\n };\r\n const buttonSelector = {\r\n ok: allButtonsSelector + \".ok\",\r\n yes: allButtonsSelector + \".yes\",\r\n no: allButtonsSelector + \".no\",\r\n button1: allButtonsSelector + \".button1\",\r\n button2: allButtonsSelector + \".button2\"\r\n };\r\n\r\n function show(messageText, okCallback, options) {\r\n setIcon();\r\n setButtons(\"ok\", okCallback);\r\n setOptions(options, \"alert-show\");\r\n displayAlert(messageText);\r\n }\r\n\r\n function info(messageText, okCallback, options) {\r\n setIcon(\"info\");\r\n setButtons(\"ok\", okCallback);\r\n setOptions(options, \"alert-info\");\r\n displayAlert(messageText);\r\n }\r\n\r\n function warning(messageText, okCallback, options) {\r\n setIcon(\"warning\");\r\n setButtons(\"ok\", okCallback);\r\n setOptions(options, \"alert-warning\");\r\n displayAlert(messageText);\r\n }\r\n \r\n function error(messageText, okCallback, displayDefaultMessage, options) {\r\n setIcon(\"error\");\r\n setButtons(\"ok\", okCallback); \r\n setOptions(options, \"alert-error\");\r\n if (typeof messageText === 'undefined' || messageText === null) messageText = \"\";\r\n if (typeof displayDefaultMessage === 'undefined') displayDefaultMessage = true;\r\n if (displayDefaultMessage || messageText === \"\") {\r\n messageText = Rifton.Messages[\"General/Default Error Message\"] + messageText;\r\n }\r\n displayAlert(messageText);\r\n }\r\n\r\n function yesNoQuestion(messageText, yesCallback, noCallback, options) {\r\n setIcon(\"question\");\r\n setButtons(\"yes-no\", yesCallback, noCallback);\r\n setOptions(options, \"alert-yes-no\");\r\n displayAlert(messageText);\r\n }\r\n\r\n function custom(messageText, iconName, callback1, buttonText1, callback2, buttontext2, options) {\r\n setIcon(iconName);\r\n setButtons(\"custom\", callback1, callback2, buttonText1, buttontext2);\r\n setOptions(options, \"alert-custom\");\r\n displayAlert(messageText);\r\n }\r\n\r\n function spinner(messageText, iconName, options) {\r\n setIcon(iconName);\r\n $(alertSelector + \" .spinner\").removeClass(\"d-none\");\r\n setButtons(\"none\");\r\n setOptions(options, \"alert-spinner\");\r\n displayAlert(messageText);\r\n }\r\n\r\n function setIcon(iconName) {\r\n $(alertSelector + \" .spinner\").addClass(\"d-none\");\r\n $(alertSelector + \" .icons\").addClass(\"d-none\");\r\n $(alertSelector + \" i\").addClass(\"d-none\");\r\n if (iconName) {\r\n $(alertSelector + \" .icons\").removeClass(\"d-none\");\r\n $(alertSelector + \" i.\" + iconName).removeClass(\"d-none\");\r\n }\r\n }\r\n\r\n function setButtons(buttons, callback1, callback2, buttonText1, buttonText2) {\r\n $(allButtonsSelector).addClass(\"d-none\");\r\n $(buttonSelector.ok).off(\"click\");\r\n $(buttonSelector.yes).off(\"click\");\r\n $(buttonSelector.no).off(\"click\");\r\n $(buttonSelector.button1).off(\"click\");\r\n $(buttonSelector.button2).off(\"click\");\r\n if (buttons === \"yes-no\") {\r\n $(buttonSelector.yes).removeClass(\"d-none\");\r\n $(buttonSelector.no).removeClass(\"d-none\");\r\n $(buttonSelector.yes).on(\"click\", function () { hideAndCallback(callback1); });\r\n $(buttonSelector.no).on(\"click\", function () { hideAndCallback(callback2); });\r\n }\r\n else if (buttons === \"custom\") {\r\n if (callback1) {\r\n $(buttonSelector.button1).removeClass(\"d-none\");\r\n $(buttonSelector.button1).text(buttonText1);\r\n $(buttonSelector.button1).on(\"click\", function () { hideAndCallback(callback1); });\r\n }\r\n if (callback2) {\r\n $(buttonSelector.button2).removeClass(\"d-none\");\r\n $(buttonSelector.button2).text(buttonText2);\r\n $(buttonSelector.button2).on(\"click\", function () { hideAndCallback(callback2); });\r\n }\r\n }\r\n else if (buttons === \"none\") {\r\n\r\n }\r\n else {\r\n $(buttonSelector.ok).removeClass(\"d-none\");\r\n $(buttonSelector.ok).on(\"click\", function () { hideAndCallback(callback1); });\r\n }\r\n }\r\n\r\n var previousClasses;\r\n\r\n function setOptions(options, alertClass) {\r\n // setting position class\r\n var pos = (options && options.position) || defaultOptions.position;\r\n $(alertSelector + \" .modal-dialog\")\r\n .removeClass(positions.center).removeClass(positions.top)\r\n .addClass(positions[pos]);\r\n // setting CSS classes\r\n var cl = (alertClass ? alertClass : \"\") + \" \" +\r\n ((options && options.customClass) ? options.customClass : defaultOptions.customClass);\r\n if (previousClasses) $(alertSelector + \" .modal-content\").removeClass(previousClasses);\r\n if (cl) $(alertSelector + \" .modal-content\").addClass(cl)\r\n previousClasses = cl;\r\n }\r\n\r\n var alertMessageModal = null;\r\n var alertMessageIsInTransition = false;\r\n\r\n function getAlertModal() {\r\n if (!alertMessageModal) {\r\n // initializing alertModal\r\n var alertElement = document.querySelector(alertSelector);\r\n if (alertElement) {\r\n alertMessageModal = new bootstrap.Modal(alertElement, { backdrop: \"static\", keyboard: false });\r\n if (alertMessageModal) {\r\n $(alertElement).on(\"show.bs.modal\", () => { alertMessageIsInTransition = true; });\r\n $(alertElement).on(\"shown.bs.modal\", () => { alertMessageIsInTransition = false; });\r\n $(alertElement).on(\"hide.bs.modal\", () => { alertMessageIsInTransition = true; });\r\n $(alertElement).on(\"hidden.bs.modal\", () => { alertMessageIsInTransition = false; });\r\n }\r\n else console.log(\"Alert modal not initialized for \" + alertSelector);\r\n }\r\n else console.log(\"There's no alert modal with selector \" + alertSelector);\r\n }\r\n return alertMessageModal;\r\n }\r\n\r\n function displayAlert(messageText) {\r\n if (alertMessageIsInTransition) {\r\n // Alert is currently transitioning (it's being displayed or hidden). Come back a bit later to display it with new message.\r\n setTimeout(() => { displayAlert(messageText) }, 500);\r\n }\r\n else {\r\n $(alertSelector + \" .alert-text\").empty().html(messageText);\r\n var alertModal = getAlertModal();\r\n if (alertModal) {\r\n alertModal.show();\r\n }\r\n }\r\n }\r\n\r\n\r\n function hideAndCallback(callback) {\r\n if (callback) $(alertSelector).one(\"hidden.bs.modal\", callback);\r\n hide();\r\n }\r\n\r\n function hide() {\r\n if (alertMessageIsInTransition) {\r\n // Alert is currently transitioning (it's being displayed or hidden). Come back a bit later to hide it.\r\n setTimeout(() => { hide() }, 500);\r\n }\r\n else {\r\n // hide the modal\r\n var alertModal = getAlertModal();\r\n if (alertModal) {\r\n alertModal.hide();\r\n }\r\n }\r\n }\r\n\r\n return {\r\n show: show,\r\n info: info,\r\n warning: warning,\r\n error: error,\r\n yesNoQuestion: yesNoQuestion,\r\n custom: custom,\r\n spinner: spinner,\r\n hide: hide\r\n };\r\n });\r\n\n", "define('common/spinner',[\r\n],\r\n function () {\r\n\r\n var spinnerShownAt = {};\r\n\r\n function show(spinnerSelector) {\r\n if (!spinnerSelector) return;\r\n $(spinnerSelector).removeClass(\"d-none\");\r\n var image = $(spinnerSelector).find(\"img\");\r\n if (image.length) {\r\n var alt = $(image).attr(\"alt\");\r\n if (!alt)\r\n $(image).attr(\"alt\", \"Spinner\");\r\n }\r\n // mark the time when this spinner was displayed\r\n spinnerShownAt[spinnerSelector] = Date.now();\r\n }\r\n\r\n function hide(spinnerSelector, callbackWhenHidden) {\r\n if (!spinnerSelector) return;\r\n // This logic ensures that the spinner is displayed for at least 500ms.\r\n // Otherwise it just flickers and that doesn't look good for the user.\r\n var waitTime = 500 - (Date.now() - spinnerShownAt[spinnerSelector]);\r\n if (waitTime > 0) {\r\n setTimeout(function () {\r\n $(spinnerSelector).addClass(\"d-none\");\r\n if (callbackWhenHidden) callbackWhenHidden();\r\n }, waitTime);\r\n }\r\n else {\r\n $(spinnerSelector).addClass(\"d-none\");\r\n if (callbackWhenHidden) callbackWhenHidden();\r\n }\r\n }\r\n\r\n function getSpinnerHtml(spinnerId) {\r\n return '
';\r\n }\r\n\r\n return {\r\n show: show,\r\n hide: hide,\r\n getSpinnerHtml: getSpinnerHtml\r\n };\r\n });\r\n\n", "define('cart/cartOperations',[\r\n \"common/formUtils\",\r\n \"common/alertMessage\",\r\n \"common/spinner\"\r\n],\r\n function (formUtils, alertMessage, spinner) {\r\n function addItemToCart(itemCode, quantity, notes, details, okCallback, errorCallback) {\r\n var postData = buildCartItemPayload(itemCode, quantity, notes, details);\r\n $.ajax({\r\n type: \"POST\",\r\n url: \"/customapi/Cart/AddItemToCart\",\r\n dataType: \"json\",\r\n data: postData,\r\n success: function (data) {\r\n if (data.status === \"OK\") {\r\n okCallback();\r\n } else if (data.status === \"ERROR\") {\r\n alertMessage.error(data.message);\r\n if (errorCallback)\r\n errorCallback();\r\n }\r\n },\r\n error: function (jq, status, errorThrown) {\r\n alertMessage.error(status + \": \" + errorThrown);\r\n if (errorCallback)\r\n errorCallback();\r\n },\r\n complete: function () {\r\n\r\n }\r\n });\r\n }\r\n\r\n function updateCartItem(cartItemId, itemCode, quantity, details, okCallback, errorCallback) {\r\n var postData = buildCartItemPayload(itemCode, quantity, null, details);\r\n postData.cartItemId = cartItemId;\r\n $.ajax({\r\n type: \"POST\",\r\n url: \"/customapi/Cart/UpdateCartItem\",\r\n dataType: \"json\",\r\n data: postData,\r\n success: function (data) {\r\n if (data.status === \"OK\") {\r\n okCallback();\r\n } else if (data.status === \"ERROR\") {\r\n alertMessage.error(data.message);\r\n if (errorCallback)\r\n errorCallback();\r\n }\r\n },\r\n error: function (jq, status, errorThrown) {\r\n alertMessage.error(status + \": \" + errorThrown);\r\n if (errorCallback)\r\n errorCallback();\r\n },\r\n complete: function () {\r\n\r\n }\r\n });\r\n }\r\n\r\n function setCartItemQuantity(cartItemId, quantity, spinnerSelector, callback) {\r\n var postData = {\r\n cartItemId: cartItemId,\r\n quantity: quantity\r\n };\r\n formUtils.useToken(postData);\r\n spinner.show(spinnerSelector);\r\n $.ajax({\r\n type: \"POST\",\r\n url: \"/customapi/Cart/SetCartItemQuantity\",\r\n dataType: \"json\",\r\n data: postData,\r\n success: function (data) {\r\n if (data.status === \"ERROR\") {\r\n alertMessage.error(data.message);\r\n }\r\n callback(data.status, data.message, data);\r\n },\r\n error: function (jq, status, errorThrown) {\r\n var message = status + \": \" + errorThrown;\r\n alertMessage.error(message);\r\n callback(\"ERROR\", message, null);\r\n },\r\n complete: function () {\r\n spinner.hide(spinnerSelector);\r\n }\r\n });\r\n }\r\n\r\n function setCartItemNotes(cartItemId, notes, spinnerSelector, callback) {\r\n var postData = {\r\n cartItemId: cartItemId,\r\n notes: notes\r\n };\r\n formUtils.useToken(postData);\r\n spinner.show(spinnerSelector);\r\n $.ajax({\r\n type: \"POST\",\r\n url: \"/customapi/Cart/SetCartItemNotes\",\r\n dataType: \"json\",\r\n data: postData,\r\n success: function (data) {\r\n if (data.status === \"ERROR\") {\r\n alertMessage.error(data.message);\r\n }\r\n callback(data.status, data.message, data);\r\n },\r\n error: function (jq, status, errorThrown) {\r\n var message = status + \": \" + errorThrown;\r\n alertMessage.error(message);\r\n callback(\"ERROR\", message, null);\r\n },\r\n complete: function () {\r\n spinner.hide(spinnerSelector);\r\n }\r\n });\r\n }\r\n\r\n function removeItemFromCart(cartItemId, spinnerSelector, callback) {\r\n var postData = {\r\n cartItemId: cartItemId\r\n };\r\n formUtils.useToken(postData);\r\n spinner.show(spinnerSelector);\r\n $.ajax({\r\n type: \"POST\",\r\n url: \"/customapi/Cart/RemoveItemFromCart\",\r\n dataType: \"json\",\r\n data: postData,\r\n success: function (data) {\r\n if (data.status === \"ERROR\") {\r\n alertMessage.error(data.message);\r\n }\r\n callback(data.status, data.message, data);\r\n },\r\n error: function (jq, status, errorThrown) {\r\n var message = status + \": \" + errorThrown;\r\n alertMessage.error(message);\r\n callback(\"ERROR\", message, null);\r\n },\r\n complete: function () {\r\n spinner.hide(spinnerSelector);\r\n }\r\n });\r\n }\r\n\r\n function buildCartItemPayload(itemCode, quantity, notes, details) {\r\n var data = {\r\n input: {\r\n ItemCode: itemCode, // string\r\n Quantity: quantity, // int\r\n Notes: notes, // string\r\n Details: details // an array of DetailCode and Quantity pairs (e.g. [{DetailCode: \"ABC\", Quantity: 2},{DetailCode: \"XYZ\", Quantity: 1}])\r\n }\r\n };\r\n formUtils.useToken(data);\r\n return data;\r\n }\r\n\r\n return {\r\n addItemToCart: addItemToCart,\r\n updateCartItem: updateCartItem,\r\n setCartItemQuantity: setCartItemQuantity,\r\n setCartItemNotes: setCartItemNotes,\r\n removeItemFromCart: removeItemFromCart\r\n }\r\n }\r\n);\r\n\n", "require([\r\n \"cart/cartOperations\",\r\n \"common/alertMessage\",\r\n \"common/spinner\"\r\n],\r\n function (cartOperations, alertMessage, spinner) {\r\n configuratorCarousel = null;\r\n editConfigurationsCarousel = null;\r\n elements = \"\";\r\n STATUS_OK = \"OK\";\r\n selectedData = {}; \r\n tmpOptionElement = null;\r\n categoryHtml = \"\";\r\n executedOnce = false;\r\n firstElement = null;\r\n currencyFormatter = null;\r\n discountFormatter = null;\r\n PLACEHOLDER_SUBCATEGORY = \"{placeholderForSubcategory}\"; \r\n TABLE_TAGS = { TABLE_END: \"\", TR_END: \"\", TD_END: \"\" };\r\n optionsList = [];\r\n openedTab = false;\r\n clickOptionElements = [];\r\n initClickOptions = [];\r\n initiated = false;\r\n validQuoteData = false;\r\n thumbImages = [];\r\n substitutedCategories = [];\r\n newlyAddedCategory = \"\";\r\n SAVE_CONFIGURATION_SPINNER = \".save-configuration-spinner\";\r\n TOTAL_AMOUNT_SELECTOR = \".totalAmount\";\r\n SAVE_CONFIGURATION_BUTTON_SELECTOR = \".saveConfiguration\";\r\n \r\n function initConfigurator() {\r\n currencyFormatter = new Intl.NumberFormat(configurator.CurrencyInfo.CurrencyCulture, {\r\n style: 'currency',\r\n currency: configurator.CurrencyInfo.IsoCurrencyCode,\r\n });\r\n\r\n discountFormatter = new Intl.NumberFormat(configurator.CurrencyInfo.CurrencyCulture, {\r\n style: 'currency',\r\n currency: configurator.CurrencyInfo.IsoCurrencyCode,\r\n currencySign: 'accounting',\r\n signDisplay: 'always'\r\n });\r\n\r\n var frm = configurator.ConfigurationForms[0];\r\n setConfigurationForm(frm, true);\r\n updatePrices();\r\n triggerChangeEvents($('#accordionConfiguration'));\r\n $(\"#configurationSlide\").show();\r\n $(SAVE_CONFIGURATION_BUTTON_SELECTOR).off(\"click\").on(\"click\", saveConfiguration);\r\n initiated = true;\r\n initTooltips();\r\n }\r\n\r\n function getProductOptionByProductNumber(productNumber) {\r\n return productOptions.find((e) => e.PartNumber == productNumber);\r\n }\r\n \r\n function dispatchOptionChangedEvent() {\r\n var configuratorElement = $(\"#configuratorCarousel\");\r\n var selectedOptions = [];\r\n $('input[type=radio]:checked, input[type=checkbox]:checked', configuratorElement).each(function () {\r\n var selectedOption = $(this).data('productNumber');\r\n if (selectedOption) {\r\n var elementId = this.id.substring(3);\r\n var thumbUrlObj = thumbImages.find((x) => x.ImageId == elementId);\r\n var thumbUrl = \"\";\r\n var fullSizeImageUrl = \"\";\r\n if (thumbUrlObj) {\r\n thumbUrl = thumbUrlObj.Url;\r\n fullSizeImageUrl = thumbUrlObj.FullSizeUrl;\r\n }\r\n selectedOptions.push({ \"ProductCode\": selectedOption, \"Title\": $('label[for=\"' + this.id + '\"]').html(), \"Image\": thumbUrl, \"FullSizeImage\": fullSizeImageUrl });\r\n }\r\n });\r\n\r\n const productOptionChangedEvent = new CustomEvent(\"productOptionChanged\", {\r\n detail: { selected : selectedOptions },\r\n bubbles: true,\r\n cancelable: true,\r\n composed: false,\r\n });\r\n document.dispatchEvent(productOptionChangedEvent);\r\n }\r\n\r\n function triggerChangeEvents(element) {\r\n $(element).trigger(\"change\");\r\n $('input[type=radio]:checked', element).each(function () { clickOptionElements = []; triggerChangeEvents($(this)); });\r\n $('input[type=checkbox]:checked', element).each(function () { clickOptionElements = []; triggerChangeEvents($(this)); });\r\n }\r\n\r\n function getConfigurationForm() {\r\n if (selectedData.SelectedForm) return selectedData.SelectedForm;\r\n for (var i = 0; i < configurator.ConfigurationForms.length; i++) {\r\n var frm = configurator.ConfigurationForms[i];\r\n if (frm.SystemId == selectedData.SelectedSystem.Id && frm.ItemId == selectedData.SelectedProductItem.Id)\r\n return frm; \r\n }\r\n return null;\r\n }\r\n\r\n function createCategoryAccordionItem(category, openedTabs, openAllTabs) {\r\n categoryHtml = \"\";\r\n executedOnce = false;\r\n createCategoryOptions(category, category, 2, false);\r\n clearSubcategoryPlaceholder();\r\n addToElementsHtml(category, null);\r\n }\r\n\r\n function appendCategoryAccordionItem(accordionItemBeforeNewAccordionItem, category) {\r\n categoryHtml = \"\";\r\n executedOnce = false;\r\n createCategoryOptions(category, category, 2, true);\r\n clearSubcategoryPlaceholder();\r\n addToElementsHtml(category, accordionItemBeforeNewAccordionItem);\r\n }\r\n\r\n function clearSubcategoryPlaceholder() {\r\n if (categoryHtml.includes(PLACEHOLDER_SUBCATEGORY))\r\n categoryHtml = categoryHtml.replaceAll(PLACEHOLDER_SUBCATEGORY, \"\");\r\n }\r\n\r\n function addToElementsHtml(category, beforeElementToAdd) {\r\n openedTab = false;\r\n isOpenTab(category, 0);\r\n // this is for expanding all accordion items by default\r\n // comment this line if you don't want to expand all by default\r\n openedTab = true;\r\n var show = openedTab ? \"show\" : \"\";\r\n var collapsed = openedTab ? \"\" : \" collapsed\";\r\n var classname = \"\";\r\n var validationMessage = \"\";\r\n if (category.Message != null)\r\n validationMessage = 'data-validation-msg=\"' + category.Message + '\"';\r\n\r\n if (category.IsError)\r\n classname = ' error-category';\r\n\r\n var accordionItemHtml = '
' +\r\n '

' +\r\n '' +\r\n '

' +\r\n '
' +\r\n '
' +\r\n categoryHtml +\r\n '
' +\r\n '
' +\r\n '
';\r\n\r\n if (beforeElementToAdd == null)\r\n elements += accordionItemHtml;\r\n else\r\n $(beforeElementToAdd).after(accordionItemHtml);\r\n }\r\n\r\n function createCategoryOptions(parentElement, element, displayingLevel, skipElementLevelCheck) {\r\n var elementLevelCheck = true;\r\n if (skipElementLevelCheck) elementLevelCheck = false;\r\n if (!element) return;\r\n if (displayingLevel > 10) return;\r\n if (elementLevelCheck) {\r\n if (element.Level > displayingLevel) return;\r\n }\r\n if (parentElement == element && element.Options.length == 0) return;\r\n createCategoryTable(parentElement, element);\r\n //display only options (level one are handled already as categories or form options without category)\r\n if (parentElement != element) {\r\n if (element.Level > 1) {\r\n if (parentElement.ConfigurationElementType == \"Option\" && element.ConfigurationElementType == \"Category\") {\r\n categoryHtml = categoryHtml.replace(PLACEHOLDER_SUBCATEGORY, '' + element.Name + \"\");\r\n displayingLevel++;\r\n }\r\n else\r\n createHtmlOption(parentElement, element);\r\n }\r\n }\r\n\r\n if (element.ConfigurationElementType == \"Category\" && element.RequiresChild == false && element.AllowMultiple == false)\r\n createNoneOption(element);\r\n\r\n if (element.Options && element.Options.length > 0) {\r\n for (var i = 0; i < element.Options.length; i++)\r\n createCategoryOptions(element, element.Options[i], displayingLevel, skipElementLevelCheck);\r\n }\r\n\r\n if (firstElement == element) closeCategoryTableTag();\r\n }\r\n\r\n //check category elements, only on initialization\r\n function isOpenTab(element, level) {\r\n if (level > 1) return;\r\n if (level == 0) {\r\n if (element.RequiresChild) {\r\n openedTab = true;\r\n return;\r\n }\r\n }\r\n\r\n if (element.Options && element.Options.length > 0) {\r\n level++;\r\n if (element.Options.length > 0) {\r\n var selectedOption = element.Options.some(x => x.IsSelected);\r\n if (selectedOption) {\r\n openedTab = true;\r\n return;\r\n }\r\n for (var i = 0; i < element.Options.length; i++)\r\n isOpenTab(element.Options[i], level);\r\n }\r\n }\r\n }\r\n\r\n function createNoneOption(element) {\r\n var options = \"\";\r\n var optionType = \"radio\";\r\n var overridableMessage = element.Message == null ? \"\" : 'data-overridable-message=\"' + element.Message + '\"';\r\n var mainCategoryId = element.MainCategoryId;\r\n if (!mainCategoryId) mainCategoryId = element.HtmlId;\r\n var name = \"radio_\" + element.HtmlId + \"_\" + mainCategoryId;\r\n var id = generateElementId(element);\r\n options = '';\r\n var selected = 'checked=\"checked\"';\r\n options += '';\r\n var quantity = \" \";\r\n options += '' + quantity + '';\r\n var priceValue = \" \";\r\n var priceCell = '' + priceValue + \"\";\r\n options += priceCell;\r\n options += \"\";\r\n categoryHtml += options;\r\n }\r\n\r\n function createFormOptionsOnLevelOne(parentElement, element, displayingLevel) {\r\n if (!element) return;\r\n if (displayingLevel > 10) return;\r\n if (element.Level > displayingLevel) return;\r\n if (element.Level == 1) {\r\n var existingElement = getExistingHtmlElement(parentElement, element);\r\n if (existingElement.HtmlElement == null || (existingElement.HtmlElement != null && existingElement.SameLevel)) {\r\n if (parentElement.ConfigurationElementType == \"Option\" && element.ConfigurationElementType == \"Category\") {\r\n categoryHtml = categoryHtml.replace(PLACEHOLDER_SUBCATEGORY, '' + element.Name + \"\");\r\n displayingLevel++;\r\n }\r\n else\r\n createHtmlOption(parentElement, element);\r\n }\r\n\r\n if (existingElement.HtmlElement != null && existingElement.SameLevel == false) {\r\n categoryHtml += \"\";\r\n return;\r\n }\r\n }\r\n\r\n if (element.Options && element.Options.length > 0) {\r\n for (var i = 0; i < element.Options.length; i++)\r\n createCategoryOptions(element, element.Options[i], displayingLevel, skipElementLevelCheck);\r\n }\r\n }\r\n\r\n function closeCategoryTableTag() {\r\n if (categoryHtml.indexOf(\" -1)\r\n categoryHtml += TABLE_TAGS.TABLE_END;\r\n if (categoryHtml.includes(PLACEHOLDER_SUBCATEGORY))\r\n categoryHtml = categoryHtml.replace(PLACEHOLDER_SUBCATEGORY, \"\");\r\n }\r\n\r\n function createCategoryTable(parentElement, element) {\r\n if (!executedOnce) {\r\n categoryHtml += '';\r\n executedOnce = true;\r\n firstElement = element;\r\n }\r\n categoryHtml += PLACEHOLDER_SUBCATEGORY;\r\n }\r\n\r\n function createHtmlOption(parentElement, element) {\r\n var options = \"\";\r\n var elementType = \"\";\r\n if (parentElement.AllowMultiple)\r\n elementType = \"checkbox\";\r\n else if (parentElement.ConfigurationElementType == \"Category\")\r\n elementType = \"radio\";\r\n else\r\n elementType = \"checkbox\";\r\n options = createOption(element, elementType);\r\n categoryHtml += options;\r\n }\r\n\r\n function createOption(element, optionType) {\r\n var validationMessage = element.Message == null ? \"\" : 'data-validation-msg=\"' + element.Message + '\"';\r\n var options = \"\";\r\n var name = optionType == \"checkbox\" ? element.HtmlId : \"radio_\" + element.ParentHtmlId + \"_\" + element.MainCategoryId;\r\n options = '';\r\n var selected = element.IsSelected ? 'checked=\"checked\"' : \"\";\r\n var id = generateElementId(element);\r\n options += '';\r\n\r\n var productOption = getProductOptionByProductNumber(element.ProductNumber);\r\n\r\n if (productOption) {\r\n var tooltipImg = \"\";\r\n if (productOption.ListingImage) {\r\n tooltipImg = '
';\r\n thumbImages.push({ \"ImageId\": id, \"Url\": productOption.ListingImage, \"FullSizeUrl\": productOption.ListingImageFullSize });\r\n }\r\n var tooltipContent = '

' + productOption.PartName + '

' +\r\n '
' + tooltipImg + '
' + productOption.Description + '
';\r\n\r\n var htmlEncodeTooltip = escapeHtml(tooltipContent);\r\n var infoIcon = '';\r\n options += infoIcon;\r\n }\r\n var quantityValue = element.Quantity == 1 || element.Quantity == 0 ? \"\" : element.Quantity;\r\n if (element.IsSelected) {\r\n if (element.Quantity != 0)\r\n quantityValue = element.Quantity;\r\n }\r\n var quantity = element.FixedQuantity ? '' + quantityValue + '' : '';\r\n options += '';\r\n var priceValue = \" \";\r\n if (element.Price != 0) priceValue = currencyFormatter.format(element.Price);\r\n var priceCell = '';\r\n if (displayPrices == 'True')\r\n options += priceCell;\r\n options += \"\";\r\n\r\n var optionElement = { OptionId: \"opt\" + generateElementId(element), Level: element.Level, CategoryId: element.MainCategoryId, HtmlId: element.HtmlId, ParentId: element.ParentHtmlId, Element: element };\r\n optionsList.push(optionElement);\r\n var existingElement = clickOptionElements.find(x => x.OptionId == optionElement.OptionId);\r\n\r\n if (!existingElement)\r\n clickOptionElements.push(optionElement);\r\n\r\n return options;\r\n }\r\n\r\n function escapeHtml(unsafe) {\r\n return unsafe\r\n .replace(/&/g, \"&\")\r\n .replace(//g, \">\")\r\n .replace(/\"/g, \""\")\r\n .replace(/'/g, \"'\");\r\n }\r\n\r\n function generateElementId(element) {\r\n return element.ParentHtmlId + \"element\" + element.HtmlId + 'category' + element.MainCategoryId;\r\n }\r\n\r\n function getElementObjectFromHtml(htmlElement) {\r\n var optionId = $(htmlElement).attr('id');\r\n var parentId = $(htmlElement).data('parentId');\r\n var level = $(htmlElement).data('level');\r\n var categoryId = $(htmlElement).data('categoryId');\r\n var rowOptId = optionId.replace(new RegExp(categoryId + '$'), '');\r\n rowOptId = rowOptId.replace(\"opt\", \"\").replace(\"none\", \"\").replace(\"category\", \"\");\r\n optionId = optionId.replace(parentId, \"\").replace(\"opt\", \"\").replace(\"element\", \"\").replace(categoryId, \"\").replace(\"category\", \"\");\r\n var hierarchy = $(htmlElement).data('elementHierarchy');\r\n getFormElementByProductHtmlId(optionId, parentId, level, categoryId, hierarchy);\r\n return { \"OptionId\": optionId, \"ParentId\": parentId, \"CategoryId\": categoryId, \"RowOptId\": rowOptId }\r\n }\r\n\r\n clickOption = function (htmlElement) { \r\n enableOrDisableQuantityTextbox(htmlElement);\r\n var elementProperties = getElementObjectFromHtml(htmlElement);\r\n var currentOptionElement = tmpOptionElement;\r\n var parentElement = $(htmlElement).closest(\"tbody\").find('[data-element-hierarchy=\"' + $(htmlElement).data(\"elementHierarchy\") + '\"]');\r\n if (parentElement.length == 0)\r\n parentElement = $(htmlElement).closest(\"tbody\").find('input[id^=\"opt\"]'); \r\n removePreviousSelect(htmlElement, parentElement); \r\n handleOption(htmlElement, currentOptionElement, elementProperties.OptionId);\r\n updatePrices();\r\n dispatchOptionChangedEvent();\r\n initTooltips();\r\n }\r\n\r\n unselect = function (htmlElement) { \r\n enableOrDisableQuantityTextbox(htmlElement);\r\n var elementProperties = getElementObjectFromHtml(htmlElement);\r\n var currentOptionElement = tmpOptionElement;\r\n var parentElement = $(htmlElement).closest(\"tbody\").find('[data-element-hierarchy=\"' + $(htmlElement).data(\"elementHierarchy\") + '\"]');\r\n if (parentElement.length == 0)\r\n parentElement = $(htmlElement).closest(\"tbody\").find('input[id^=\"opt\"]'); \r\n handleOption(htmlElement, currentOptionElement, elementProperties.OptionId);\r\n updatePrices();\r\n dispatchOptionChangedEvent();\r\n initTooltips();\r\n }\r\n\r\n function removePreviousSelect(htmlElement, parentElement) { \r\n $(parentElement).each(function () {\r\n var parent = $(this);\r\n $(this).closest(\"table\").find('[data-element-hierarchy^=\"' + $(this).data(\"elementHierarchy\") + \"|\" + $(this).val().replaceAll(\"_\", \"-\") + '\"]').each(function () {\r\n if ($(htmlElement).attr(\"id\") != $(parent).attr(\"id\") && !$(parent).is(\":checked\")) {\r\n if ($(this).is(':checked')) {\r\n $(this).prop(\"checked\", false);\r\n unselect($(this));\r\n }\r\n }\r\n if (!parent.is(\":checked\"))\r\n $(this).closest(\"tr\").remove();\r\n });\r\n });\r\n\r\n if (initiated) {\r\n $(parentElement).each(function () {\r\n\r\n if ($(this).attr(\"id\") != $(htmlElement).attr(\"id\")) {\r\n if ($(this).is(\":checked\") == false) {\r\n $(this).prop(\"checked\", false);\r\n unselect($(this));\r\n }\r\n }\r\n });\r\n }\r\n }\r\n\r\n function initTooltips() {\r\n const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle=\"tooltip\"]')\r\n const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))\r\n }\r\n\r\n function enableOrDisableQuantityTextbox(htmlElement) {\r\n var trElement = $(htmlElement).closest(\"tr\");\r\n var quantityTxt = $(trElement).find('input[type=\"number\"][id^=\"qnt\"]');\r\n if (quantityTxt && quantityTxt.length) {\r\n if ($(htmlElement).is(':checked')) {\r\n $(quantityTxt).prop('disabled', false);\r\n } else {\r\n $(quantityTxt).prop('disabled', true);\r\n }\r\n }\r\n }\r\n\r\n function saveConfiguration(event) { \r\n validateForm();\r\n validateData(); \r\n var totalAmountPriceVal = 0;\r\n var totalAmountPriceElement = $(TOTAL_AMOUNT_SELECTOR).find(\".totalAmountPrice\");\r\n if (totalAmountPriceElement)\r\n totalAmountPriceVal = $(totalAmountPriceElement).data(\"totalPrice\"); \r\n if (totalAmountPriceVal == 0) {\r\n alertMessage.warning($(TOTAL_AMOUNT_SELECTOR).data(\"noComponentsSelectedText\"));\r\n return;\r\n }\r\n if (!validQuoteData) return;\r\n spinner.show(SAVE_CONFIGURATION_SPINNER);\r\n $(this).prop(\"disabled\", true);\r\n var cartItemId = $(event.target).data(\"cartItemId\");\r\n addOrUpdateCart(cartItemId); \r\n }\r\n\r\n function validateData() { \r\n validQuoteData = true;\r\n var configuratorElement = $(\"#configuratorCarousel\");\r\n $('input[type=radio]:checked:visible, input[type=checkbox]:checked:visible', configuratorElement).each(function () {\r\n if ($(this).attr(\"id\").indexOf(\"noneopt\") != -1) return;\r\n var htmlElement = $(this);\r\n getElementObjectFromHtml(htmlElement);\r\n var currentOptionElement = tmpOptionElement; \r\n validateSubOptions(htmlElement, currentOptionElement);\r\n });\r\n }\r\n\r\n function validateSubOptions(htmlElement, element) {\r\n if (!element) return;\r\n var validElement = false;\r\n if (element.Options && element.Options.length) {\r\n for (var i = 0; i < element.Options.length; i++) {\r\n var option = element.Options[i];\r\n var optionHtmlElement = $('input[id*=\"element' + option.HtmlId + '\"]:checked:visible');\r\n if (element.RequiresChild) {\r\n if (!validElement) { \r\n if (optionHtmlElement && optionHtmlElement.length) {\r\n validElement = true;\r\n }\r\n }\r\n }\r\n else\r\n validElement = true;\r\n // validate only suboptions if option is checked\r\n if (optionHtmlElement && optionHtmlElement.length)\r\n validateSubOptions(htmlElement, option);\r\n // validate if option has category as suboption\r\n if (element.Options.length == 1 && option.ConfigurationElementType == \"Category\")\r\n validateSubOptions(htmlElement, option);\r\n }\r\n }\r\n else\r\n validElement = true;\r\n\r\n if (!validElement) { \r\n validQuoteData = false;\r\n var accordionItem = $(htmlElement).closest(\".accordion-item\");\r\n var messageTxt = element.Message ? element.Message : \"Your configuration is missing \" + element.Name + \" Option(\" + $(htmlElement).data(\"productNumber\") + \")\";\r\n $(accordionItem).find(\".accordion-button\").css(\"background-color\", \"red\"); \r\n $(\"#errors\").append('

' + messageTxt + \"

\");\r\n var errors = $(\"#errors\").find(\"p\");\r\n errors.length ? $(\"#errors\").show() : $(\"#errors\").hide();\r\n errors.length ? $(SAVE_CONFIGURATION_BUTTON_SELECTOR).prop(\"disabled\", true) : $(SAVE_CONFIGURATION_BUTTON_SELECTOR).prop(\"disabled\", false); \r\n return;\r\n }\r\n }\r\n\r\n function addOrUpdateCart(cartItemId) {\r\n var confDetails = getConfigurationDetails();\r\n var productNumber = productItemInfo.ProductNumber;\r\n var confQuantity = $(\"#configurationQuantity\").val();\r\n if (cartItemId) {\r\n // updating an existing cart item\r\n cartOperations.updateCartItem(\r\n cartItemId,\r\n productNumber,\r\n confQuantity,\r\n confDetails,\r\n cartOperationCallback,\r\n cartOperationErrorCallback\r\n );\r\n }\r\n else\r\n {\r\n // adding a new item to the cart\r\n cartOperations.addItemToCart(\r\n productNumber,\r\n confQuantity,\r\n null, // Notes\r\n confDetails,\r\n cartOperationCallback,\r\n cartOperationErrorCallback\r\n );\r\n }\r\n }\r\n\r\n function getConfigurationDetails() {\r\n var quoteDetails = getQuoteDetails();\r\n return quoteDetails.map(({ ProductNumber, Quantity, CategoryId }) => ({ DetailCode: ProductNumber, Quantity: Quantity, CategoryId : CategoryId }));\r\n }\r\n\r\n function cartOperationCallback() {\r\n window.location = \"/cart\";\r\n }\r\n\r\n function cartOperationErrorCallback() {\r\n $(SAVE_CONFIGURATION_BUTTON_SELECTOR).prop(\"disabled\", false);\r\n spinner.hide(SAVE_CONFIGURATION_SPINNER);\r\n }\r\n\r\n function editQuoteDetails() {\r\n var quoteDetails = getQuoteDetails();\r\n var quoteDetailsInfo = { \"LynxItemId\": selectedData.SelectedProductItem.LynxItemId, \"QuoteDetails\": quoteDetails, \"ProductItemName\": selectedData.SelectedProductItem.Text, \"ProductItemId\": selectedData.SelectedProductItem.Id, \"ProductNumber\": selectedData.SelectedProductItem.ProductNumber, \"ConfigurationQuantity\": $(\"#configurationQuantity\").val() };\r\n var data = { \"QuoteId\": selectedData.QuoteId, \"ConfigurationNumber\": selectedData.SelectedConfigurationNumber, \"QuoteDetailsInfo\": quoteDetailsInfo, \"AddNewConfiguration\": selectedData.AddNewConfiguration };\r\n ajaxCall(\"/Configurator/EditQuoteConfiguration\", data, null, function (response) {\r\n if (response && response.status == STATUS_OK) {\r\n alert(\"Changes saved\");\r\n document.getElementById(\"configuratorCarousel\").style.display = \"none\";\r\n document.getElementById(\"editConfigurationsCarousel\").style.display = \"block\";\r\n if (selectedData.IsInEditingMode && selectedData.AddNewConfiguration)\r\n goToEditQuotes();\r\n else\r\n editConfigurationsCarousel.to(1);\r\n }\r\n else\r\n alert(\"Error occured. Data not saved.\");\r\n }, function (response) {\r\n alert(response.message);\r\n });\r\n }\r\n\r\n function createQuoteWithDetails() { \r\n var quoteDetails = getQuoteDetails();\r\n ajaxCall(\"/customapi/Configurator/CreateQuoteWithDetails\", { \"LynxItemId\": productItemInfo.LynxItemId, \"QuoteDetails\": quoteDetails, \"ProductItemName\": productItemInfo.Name, \"ProductItemId\": productItemInfo.ProductId, \"ProductNumber\": productItemInfo.ProductNumber, \"ConfigurationQuantity\": $(\"#configurationQuantity\").val() }, null, function (response) {\r\n if (response && response.Data && response.status == STATUS_OK) {\r\n alert(\"Configuration created.\");\r\n }\r\n else\r\n alert(\"Error occured. Data not saved.\");\r\n }, function (response) {\r\n alert(response.message);\r\n });\r\n }\r\n\r\n function getQuoteDetails() {\r\n var quoteDetails = [];\r\n $(\"#configurationPanel .accordion-item\").each(function () {\r\n var checkedOptions = $(this).find('[id^=\"opt\"]:checked');\r\n addQuoteDetails(quoteDetails, checkedOptions);\r\n });\r\n var checkedOptions = $('.formOptionsList').find('[id^=\"opt\"]:checked');\r\n addQuoteDetails(quoteDetails, checkedOptions);\r\n return quoteDetails;\r\n }\r\n\r\n function addQuoteDetails(quoteDetails, checkedOptions) {\r\n if (checkedOptions && checkedOptions.length) {\r\n for (var i = 0; i < checkedOptions.length; i++) {\r\n var checkedOption = checkedOptions[i];\r\n var id = $(checkedOption).attr(\"id\").replace(\"opt\", \"\");\r\n var trElement = $(checkedOption).closest(\"tr\");\r\n var quantityElement = $(trElement).find(\"#qnt\" + id);\r\n var quantity = 1;\r\n if (quantityElement.val() != \"\")\r\n quantity = parseFloat(quantityElement.val());\r\n var priceElement = $(trElement).find(\"#price\" + id);\r\n var price = 0;\r\n if (priceElement.val() != \"\")\r\n price = parseFloat(priceElement.val());\r\n quoteDetails.push({ \"QuoteId\": null, \"ProductId\": $(checkedOption).val(), \"ProductNumber\": $(checkedOption).data(\"productNumber\"), \"Quantity\": quantity, \"DefaultUnit\": $(checkedOption).data(\"defaultUnit\"), \"ParentProductId\": $(checkedOption).data(\"parentId\"), \"Price\": price, \"CategoryId\": $(checkedOption).data(\"categoryId\"), \"Hierarchy\": $(checkedOption).data(\"elementHierarchy\"), \"ProductName\": $('label[for=\"' + $(checkedOption).attr(\"id\") + '\"]').html() });\r\n }\r\n }\r\n }\r\n\r\n function validateForm() {\r\n $('[data-validation-msg]').each(function () {\r\n var accordionItem = $(this).closest(\".accordion-item\");\r\n if ($(accordionItem).css('display') == 'none') return;\r\n var accordionBody = $(accordionItem).find(\".accordion-collapse\");\r\n if (hasRequiredFields(this)) {\r\n $(accordionItem).find(\".accordion-button\").css(\"background-color\", \"\");\r\n $(accordionBody).find(\".validationMessage\").remove();\r\n $(\"#errors\").find('[id=\"error' + $(accordionItem).attr(\"id\") + '\"]').remove();\r\n }\r\n else {\r\n if (!$(accordionBody).find(\".validationMessage\").length) {\r\n $(accordionItem).find(\".accordion-button\").css(\"background-color\", \"red\");\r\n var validationText = $(this).data(\"validationMsg\");\r\n var messageElement = '
' + validationText + \"
\";\r\n $(accordionBody).prepend(messageElement);\r\n $(\"#errors\").append('

' + validationText + \"

\");\r\n }\r\n }\r\n });\r\n\r\n validateRequiredSubcategories();\r\n validateFieldsWithoutValidationMessage();\r\n var errors = $(\"#errors\").find(\"p\");\r\n errors.length ? $(\"#errors\").show() : $(\"#errors\").hide();\r\n errors.length ? $(SAVE_CONFIGURATION_BUTTON_SELECTOR).prop(\"disabled\", true) : $(SAVE_CONFIGURATION_BUTTON_SELECTOR).prop(\"disabled\", false);\r\n }\r\n\r\n function validateFieldsWithoutValidationMessage() {\r\n $('[data-requires-child=\"true\"]:not([data-linked-category=\"true\"])').each(function () {\r\n var accordionItem = $(this).closest(\".accordion-item\");\r\n if ($(accordionItem).css('display') == 'none') return;\r\n var categoryBackgroundColor = $(accordionItem).find(\".accordion-button\").css(\"background-color\");\r\n var checkedElements = $(this).find(\":input:checked\");\r\n if (checkedElements.length == 0) {\r\n if (categoryBackgroundColor != \"red\") {\r\n $(accordionItem).find(\".accordion-button\").css(\"background-color\", \"red\");\r\n var errorsContent = $(\"#errors\").html();\r\n if (errorsContent.indexOf(\"#\" + $(accordionItem).attr(\"id\")) == -1)\r\n $(\"#errors\").append('

Select one option (required)

');\r\n }\r\n }\r\n else {\r\n $(\"#errors\").find('[id=\"error' + $(accordionItem).attr(\"id\") + '\"]').remove();\r\n $(accordionItem).find(\".accordion-button\").css(\"background-color\", \"\");\r\n }\r\n });\r\n }\r\n\r\n function getSubcategoryOptions(element) {\r\n var subcategoryId = $(element).data(\"subcategoryId\");\r\n if (!subcategoryId) return null;\r\n var dataHierarchy = $(element).data(\"hierarchy\");\r\n var subcategoryRows = $('tr[data-hierarchy=\"' + dataHierarchy + \"|\" + subcategoryId.replaceAll(\"_\", \"-\") + '\"][data-row-parent-id=\"' + subcategoryId + '\"]');\r\n return subcategoryRows;\r\n }\r\n\r\n function validateRequiredSubcategories() {\r\n $('[data-validation-option=\"1\"]').remove();\r\n $('[data-linked-category=\"true\"][data-requires-child=\"true\"]').each(function () {\r\n var subcategoryRows = getSubcategoryOptions(this);\r\n if (subcategoryRows.length) {\r\n var checkedElements = $(subcategoryRows).find(\":input:checked\");\r\n if (checkedElements && checkedElements.length > 0) {\r\n }\r\n else {\r\n $(this).find(\"td\").append('
This option is required
');\r\n }\r\n }\r\n else\r\n $(this).hide();\r\n });\r\n }\r\n\r\n function hasRequiredFields(item) {\r\n if ($(item).hasClass(\"accordion-body\")) {\r\n var checkedElements = $(item).find(\":input:checked\");\r\n if (checkedElements && checkedElements.length > 0) return true;\r\n return false;\r\n }\r\n else {\r\n }\r\n }\r\n\r\n function handleOption(htmlElement, currentOptionElement, optionId) {\r\n clickOptionElements = [];\r\n if (currentOptionElement) {\r\n categoryHtml = \"\"; \r\n createCategoryOptions(currentOptionElement, currentOptionElement, currentOptionElement.Level + 1, false);\r\n\r\n var trElement = $(htmlElement).closest(\"tr\");\r\n $(\"#optionRow\" + optionId).remove();\r\n $('[data-validation-option=\"1\"]').remove();\r\n\r\n if ($(htmlElement).data(\"noneOption\") != true) {\r\n clearSubcategoryPlaceholder();\r\n if ($(htmlElement).is(\":checked\"))\r\n $(trElement).after(categoryHtml); \r\n }\r\n else\r\n handleNoneOptionClick(htmlElement);\r\n\r\n hideEverySubcategory();\r\n setQuantityOnClick(htmlElement);\r\n handleOtherOptionsBasedOnRules(htmlElement);\r\n hideEveryDuplicateOption(); \r\n hideOptionsWithoutAnySuboption();\r\n triggerSelectedOptions(htmlElement);\r\n $('table[id*=\"optTable\"][style*=\"display: none\"]').each(function () { $(this).closest(\".accordion-item\").hide(); });\r\n validateForm();\r\n }\r\n }\r\n\r\n function handleOtherOptionsBasedOnRules(htmlElement) { \r\n getElementObjectFromHtml(htmlElement);\r\n var elementOption = tmpOptionElement;\r\n var checked = $(htmlElement).is(':checked');\r\n if ($(htmlElement).attr(\"id\").indexOf(\"noneopt\") > -1)\r\n checked = false;\r\n\r\n newlyAddedCategory = \"\";\r\n for (var i = 0; i < elementOption.Options.length; i++) {\r\n iterateThroughOptionRules(elementOption, htmlElement, checked, elementOption.Options[i]);\r\n }\r\n }\r\n\r\n function iterateThroughOptionRules(elementOption, htmlElement, checked, option) { \r\n if (option.ConfigurationElementType == \"Category\") {\r\n var hasSelectedOption = false;\r\n var defaultOption = null;\r\n var createdCategory = false;\r\n \r\n for (var i = 0; i < option.Options.length; i++) {\r\n var suboption = option.Options[i];\r\n if (suboption.IsSelected == true)\r\n defaultOption = suboption;\r\n \r\n if (option.RequiresChild == true) {\r\n var suboptionHtml = $(\"#opt\" + generateElementId(suboption)); \r\n var suboptionsOnForm = $('input[value=\"' + suboption.ProductId + '\"]');\r\n $(suboptionsOnForm).each(function () {\r\n if ($(this).is(':checked')) \r\n hasSelectedOption = true; \r\n\r\n if (checked) {\r\n if ($(this).data(\"level\") == 2) { \r\n var category = getClosestTable($(this));\r\n if (category != null) {\r\n var accordionItem = $(category).closest(\".accordion-item\");\r\n if (checked) {\r\n setOptionLevels(option, 2);\r\n if (accordionItem.attr(\"id\") != \"accordionItem\" + option.HtmlId) {\r\n var originalCategoryId = accordionItem.attr(\"id\").replace(\"accordionItem\", \"\");\r\n appendCategoryAccordionItem(accordionItem, option);\r\n $(accordionItem).remove();\r\n var substitutedCategory = substitutedCategories.find(x => x.OriginalCategoryId == originalCategoryId);\r\n if (!substitutedCategory) {\r\n substitutedCategories.push({ \"OriginalCategoryId\": originalCategoryId, \"SubstitutedCategoryId\": option.HtmlId });\r\n }\r\n createdCategory = true;\r\n }\r\n }\r\n } \r\n }\r\n } \r\n });\r\n }\r\n\r\n if (!createdCategory) {\r\n if (checked)\r\n createCategoryOnHighestLevel(elementOption, htmlElement, option);\r\n }\r\n\r\n if (!checked) removeCategoryOnHighestLevel(elementOption, option);\r\n\r\n iterateThroughOptionRules(elementOption, htmlElement, checked, option.Options[i]);\r\n }\r\n\r\n if (option.RequiresChild == true) {\r\n if (!hasSelectedOption) {\r\n if (checked) {\r\n var suboptionHtml = $('input[value=\"' + defaultOption.ProductId + '\"]');\r\n $(suboptionHtml).prop('checked', true);\r\n }\r\n }\r\n }\r\n\r\n }\r\n //if it is option, don't go further, we are going recursevly only to options element type\r\n else if (option.ConfigurationElementType == \"Option\") {\r\n return;\r\n }\r\n }\r\n\r\n function removeCategoryOnHighestLevel(elementOption, option) {\r\n var substitutedCategory = substitutedCategories.find(x => x.SubstitutedCategoryId.indexOf(option.HtmlId) != -1);\r\n if (substitutedCategory) {\r\n substitutedCategory.SubstitutedCategoryId = substitutedCategory.SubstitutedCategoryId.replaceAll('|' + elementOption.HtmlId, '');\r\n if (substitutedCategory.SubstitutedCategoryId == option.HtmlId) {\r\n var categoryElement = getAnyCategoryElementById(substitutedCategory.OriginalCategoryId);\r\n if (categoryElement) {\r\n var substitutedAccordion = $(\"#accordionItem\" + substitutedCategory.SubstitutedCategoryId);\r\n if (substitutedCategory.OriginalCategoryId != substitutedCategory.SubstitutedCategoryId)\r\n appendCategoryAccordionItem(substitutedAccordion, categoryElement);\r\n $(substitutedAccordion).remove();\r\n\r\n substitutedCategories = substitutedCategories.filter(function (obj) {\r\n return obj.SubstitutedCategoryId !== option.HtmlId;\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n function createCategoryOnHighestLevel(elementOption, htmlElement, option) {\r\n var existingCategoryItem = $(\"#accordionItem\" + option.HtmlId);\r\n if (existingCategoryItem.length == 0) {\r\n setOptionLevels(option, 2);\r\n var table = getClosestTable($(htmlElement));\r\n if (table != null) {\r\n var accordionItem = $(table).closest(\".accordion-item\");\r\n if (newlyAddedCategory != \"\") {\r\n existingCategoryItem = $(\"#accordionItem\" + newlyAddedCategory);\r\n if (existingCategoryItem.length > 0)\r\n accordionItem = existingCategoryItem;\r\n }\r\n appendCategoryAccordionItem(accordionItem, option);\r\n newlyAddedCategory = option.HtmlId;\r\n var substitutedCategory = substitutedCategories.find(x => x.OriginalCategoryId == option.HtmlId);\r\n if (!substitutedCategory) {\r\n substitutedCategories.push({ \"OriginalCategoryId\": option.HtmlId, \"SubstitutedCategoryId\": option.HtmlId + '|' + elementOption.HtmlId });\r\n }\r\n\r\n checkIfNewlyAddedCategoryHasSubcategories(option.HtmlId);\r\n }\r\n }\r\n else {\r\n var substitutedCategory = substitutedCategories.find(x => x.OriginalCategoryId == option.HtmlId);\r\n if (substitutedCategory) {\r\n substitutedCategory.SubstitutedCategoryId += '|' + elementOption.HtmlId; \r\n }\r\n }\r\n firstElement = null;\r\n }\r\n\r\n function checkIfNewlyAddedCategoryHasSubcategories(htmlId) {\r\n var categoryItem = $(\"#accordionItem\" + htmlId);\r\n var subcategories = $(categoryItem).find('[data-linked-category=\"true\"]');\r\n if (subcategories.length > 0) {\r\n var checkedOptions = $(categoryItem).find(\"input:checked\").first();\r\n if (checkedOptions.length > 0)\r\n triggerChangeEvents(checkedOptions);\r\n }\r\n }\r\n\r\n function getAnyCategoryElementById(elementId) {\r\n var selectedForm = getConfigurationForm();\r\n var elementWithId = null;\r\n for (var i = 0; i < selectedForm.Elements.length; i++) {\r\n var element = selectedForm.Elements[i];\r\n iterateThroughElementOptions(element, function (el) {\r\n if (el.HtmlId == elementId)\r\n elementWithId = el;\r\n }); \r\n }\r\n\r\n return elementWithId;\r\n }\r\n\r\n function iterateThroughElementOptions(element, customFunction) {\r\n if (!element) return;\r\n customFunction(element);\r\n for (var i = 0; i < element.Options.length; i++) {\r\n var el = element.Options[i];\r\n customFunction(el);\r\n iterateThroughElementOptions(el, customFunction); \r\n }\r\n }\r\n\r\n function setOptionLevels(option, levelToSet) {\r\n option.Level = levelToSet;\r\n for (var i = 0; i < option.Options.length; i++) {\r\n setOptionLevels(option.Options[i], option.Level + 1);\r\n }\r\n }\r\n\r\n function getClosestTable(opt) {\r\n var table = $(opt).closest(\"table\");\r\n if (table.length == 0) return null;\r\n return table; \r\n }\r\n\r\n function triggerSelectedOptions(htmlElement) {\r\n if (!initiated) {\r\n var existingClick = initClickOptions.find(x => htmlElement.id);\r\n if (existingClick) return;\r\n initClickOptions.push(htmlElement);\r\n }\r\n else\r\n initClickOptions = [];\r\n for (var i = 0; i < clickOptionElements.length; i++) {\r\n var el = clickOptionElements[i].Element;\r\n if (el.IsSelected) {\r\n $(\"#\" + clickOptionElements[i].OptionId).each(function () { triggerChangeEvents($(this)); });\r\n } \r\n }\r\n }\r\n\r\n //we will display subcategories always as categories, so hide them\r\n function hideEverySubcategory() {\r\n $('[data-linked-category=\"true\"]').each(function () { \r\n var subcategoryOptions = getSubcategoryOptions(this);\r\n if (subcategoryOptions) {\r\n $(subcategoryOptions).remove(); \r\n }\r\n $('[data-none-option=\"true\"][data-parent-id=\"' + $(this).data(\"elementId\") + '\"]').closest(\"tr\").remove();\r\n $(this).remove();\r\n });\r\n }\r\n\r\n function hideOptionsWithoutAnySuboption() {\r\n $('[data-linked-category=\"true\"]').each(function () {\r\n var subcategoryOptions = getSubcategoryOptions(this);\r\n if (subcategoryOptions) {\r\n var inputs = $(subcategoryOptions).find(\":input:not([type=hidden]):visible\");\r\n if (inputs.length == 0) {\r\n $(this).remove();\r\n }\r\n }\r\n });\r\n \r\n $('[data-requires-child]:not([data-linked-category=\"true\"]):visible').each(function () {\r\n var subcategoryContent = getSubcategoryOptions(this);\r\n if (subcategoryContent) {\r\n var inputs = $(subcategoryContent).find(\":input:not([type=hidden]):visible\");\r\n if (inputs.length == 0) {\r\n $(subcategoryContent).hide();\r\n }\r\n }\r\n });\r\n\r\n //hide accordion items if they have no options\r\n $(\".accordion-item\").each(function () {\r\n var inputs = $(this).find('tr:not([style*=\"display: none\"])');\r\n if (!inputs.length) $(this).hide();\r\n });\r\n }\r\n\r\n function hideEveryDuplicateOption() {\r\n var duplicateOptions = [];\r\n var configuratorEl = $(\"#configuratorCarousel\");\r\n $('input[id^=\"opt\"]', configuratorEl).each(function () {\r\n duplicateOptions.push({ \"element\": $(this), \"elementId\": $(this).val(), \"level\": $(this).data(\"level\") });\r\n });\r\n\r\n $('input[id^=\"noneopt\"]', configuratorEl).each(function () {\r\n duplicateOptions.push({ \"element\": $(this), \"elementId\": $(this).val(), \"level\": $(this).data(\"level\") });\r\n });\r\n\r\n var groupById = groupBy(duplicateOptions, \"elementId\");\r\n for (var key in groupById) {\r\n var options = groupById[key];\r\n if (options && options.length > 1) {\r\n allHaveSameLevel = areAllDuplicateOptionsSameLevel(options);\r\n //Allow duplicate options on same level, if we don't want to allow duplicate options on same level, comment the line below this comment\r\n if (allHaveSameLevel) continue;\r\n options = options.sort((a, b) => a.level - b.level);\r\n for (var i = 1; i < options.length; i++) {\r\n var option = options[i];\r\n $(option.element).closest(\"tr\").remove();\r\n }\r\n }\r\n }\r\n }\r\n\r\n function areAllDuplicateOptionsSameLevel(options) {\r\n return options.every((element, index, arr) => element.level === arr[0].level);\r\n }\r\n\r\n function setQuantityOnClick(htmlElement) {\r\n var parent = $(htmlElement).closest(\"table\");\r\n if (parent && parent.length) {\r\n $(parent).find(\"input\").each(function () {\r\n setQuantityOnElement($(this));\r\n });\r\n }\r\n }\r\n\r\n function setQuantityOnElement(htmlElement) {\r\n var id = $(htmlElement).attr(\"id\").replace(\"opt\", \"\");\r\n var quantityElement = $(\"#qnt\" + id);\r\n var quantity = 1;\r\n if (quantityElement.val() != \"\")\r\n quantity = parseFloat(quantityElement.val());\r\n if (htmlElement.type === 'radio') {\r\n var parentElement = $(htmlElement).closest('table');\r\n if (parentElement && parentElement.length) {\r\n $(parentElement).find('input').each(function () {\r\n var id = $(this).attr(\"id\").replace(\"opt\", \"\");\r\n $(\"#qnt\" + id).text(\"\");\r\n });\r\n }\r\n }\r\n\r\n if ($(htmlElement).prop(\"checked\")) {\r\n if ($(quantityElement).is(\"span\"))\r\n $(quantityElement).text(quantity);\r\n else\r\n $(quantityElement).val(quantity);\r\n }\r\n else {\r\n if ($(quantityElement).is(\"span\"))\r\n $(quantityElement).text(\"\");\r\n else\r\n $(quantityElement).val(\"\");\r\n }\r\n }\r\n\r\n updatePrices = function () { \r\n $(\"#configuratorComponentsList\").empty();\r\n var quoteDetails = getQuoteDetails();\r\n var subtotalAmount = 0;\r\n for (var i = 0; i < quoteDetails.length; i++) {\r\n var quoteDetail = quoteDetails[i];\r\n subtotalAmount += quoteDetail.Quantity * quoteDetail.Price;\r\n if (quoteDetail.Quantity > 1) {\r\n if (displayPrices == 'True')\r\n $(\"#configuratorComponentsList\").append('
  • ' + quoteDetail.Quantity + ' X ' + quoteDetail.ProductName + '' + currencyFormatter.format(quoteDetail.Price) + '
  • ');\r\n else\r\n $(\"#configuratorComponentsList\").append('
  • ' + quoteDetail.Quantity + ' X ' + quoteDetail.ProductName + '
  • ');\r\n }\r\n else {\r\n if (displayPrices == 'True')\r\n $(\"#configuratorComponentsList\").append('
  • ' + quoteDetail.ProductName + '' + currencyFormatter.format(quoteDetail.Price) + '
  • ');\r\n else\r\n $(\"#configuratorComponentsList\").append('
  • ' + quoteDetail.ProductName + '
  • ');\r\n }\r\n }\r\n\r\n if (subtotalAmount == 0)\r\n $(\"#summaryAccordion\").find(\".accordion-item\").hide();\r\n else\r\n $(\"#summaryAccordion\").find(\".accordion-item\").show();\r\n\r\n setSubtotalAmount(subtotalAmount);\r\n calculatePrices(subtotalAmount);\r\n\r\n //if (configurator.IsDiscountLineItem)\r\n // $(\"#totalAmount\").html('' + currencyFormatter.format(subtotalAmount) + \"\");\r\n //else {\r\n // subtotalAmount = subtotalAmount - (subtotalAmount * configurator.DiscountPercentage / 100);\r\n // $(\"#totalAmount\").html('' + currencyFormatter.format(subtotalAmount) + \"\");\r\n //}\r\n }\r\n \r\n function setSubtotalAmount(subtotalAmount) {\r\n $(TOTAL_AMOUNT_SELECTOR + \" span\").remove();\r\n $(TOTAL_AMOUNT_SELECTOR).append('' + currencyFormatter.format(subtotalAmount) + \"\");\r\n }\r\n\r\n function calculatePrices(subtotalAmount) {\r\n if (displayPrices == 'False') return;\r\n ajaxCall(\"/customapi/Configurator/CalculateTotal\", { \"subTotal\": subtotalAmount }, null, function (response) { \r\n setSummaryPrices(response.Data, subtotalAmount);\r\n }, function (response) {\r\n subtotalAmount = 0;\r\n setSubtotalAmount(subtotalAmount);\r\n alertMessage.error(response.message);\r\n setSummaryPrices(response.Data, subtotalAmount); \r\n });\r\n }\r\n\r\n function setSummaryPrices(summaryPrices, subtotalAmount) { \r\n $(\".configurator-subtotal-val\").text(currencyFormatter.format(subtotalAmount));\r\n $(\".configurator-discount-val\").text(discountFormatter.format(-summaryPrices.PrimaryDiscount));\r\n $(\".configurator-sec-discount-val\").text(discountFormatter.format(-summaryPrices.SecondaryDiscount));\r\n $(\".configurator-total-val\").text(summaryPrices.Total);\r\n $(\".configurator-summary-subtotal\").show();\r\n $(\".configurator-summary-discount\").show();\r\n $(\".configurator-summary-sec-discount\").show();\r\n $(\".configurator-summary-total\").show();\r\n if (!summaryPrices.PrimaryDiscount && !summaryPrices.SecondaryDiscount) {\r\n $(\".configurator-summary-subtotal\").hide();\r\n $(\".configurator-summary-discount\").hide();\r\n $(\".configurator-summary-sec-discount\").hide(); \r\n }\r\n else if (!summaryPrices.SecondaryDiscount)\r\n $(\".configurator-summary-sec-discount\").hide();\r\n }\r\n\r\n function handleNoneOptionClick(htmlElement) { \r\n $(htmlElement).closest('table').find('input[type=checkbox]:checked, input[type=radio]:checked').each(function () {\r\n if ($(this).attr(\"id\") != $(htmlElement).attr(\"id\")) {\r\n $(this).prop(\"checked\", false);\r\n clickOption($(this));\r\n if ($(htmlElement).data(\"level\") < $(this).data(\"level\"))\r\n $(this).closest(\"tr\").remove();\r\n }\r\n }); \r\n }\r\n\r\n function groupBy(xs, key) {\r\n return xs.reduce(function (rv, x) {\r\n (rv[x[key]] = rv[x[key]] || []).push(x);\r\n return rv;\r\n }, {});\r\n }\r\n\r\n function getFormElementByProductHtmlId(productId, parentId, level, categoryId, hierarchy) {\r\n var selectedForm = getConfigurationForm();\r\n for (var i = 0; i < selectedForm.Elements.length; i++) {\r\n var mainCategory = selectedForm.Elements[i];\r\n if (productId == parentId && level == 2) {\r\n if (mainCategory.HtmlId == productId) {\r\n tmpOptionElement = mainCategory;\r\n break;\r\n }\r\n }\r\n getElementByProductHtmlId(mainCategory, productId, parentId, level, categoryId, hierarchy);\r\n }\r\n }\r\n\r\n function getElementByProductHtmlId(element, productId, parentId, level, categoryId, hierarchy) {\r\n if (!element) return;\r\n if (element.HtmlId == productId && element.ParentHtmlId == parentId && element.Level == level)\r\n if (element.HtmlId == productId && element.ParentHtmlId == parentId && element.Level == level && element.MainCategoryId == categoryId) {\r\n if (hierarchy) {\r\n if (element.Hierarchy == hierarchy) {\r\n tmpOptionElement = element;\r\n return;\r\n }\r\n }\r\n else {\r\n tmpOptionElement = element;\r\n return;\r\n }\r\n }\r\n\r\n if (element.Options && element.Options.length > 0) {\r\n for (var i = 0; i < element.Options.length; i++)\r\n getElementByProductHtmlId(element.Options[i], productId, parentId, level, categoryId, hierarchy);\r\n }\r\n }\r\n\r\n function getExistingHtmlElement(parentElement, element) {\r\n var existingElement = { HtmlElement: null, SameLevel: true };\r\n //check if element already exists\r\n //if it is category, check if category exists \r\n if (element.ConfigurationElementType == \"Category\") {\r\n existingElement = { HtmlElement: document.querySelector('[id^=\"optTable' + parentElement.HtmlId + '\"][data-element-type=\"Category\"]'), SameLevel: true };\r\n }\r\n else if (element.ConfigurationElementType == \"Option\") {\r\n existingElement = getExistingOptionItemElementOnHigherLevels(element);\r\n }\r\n\r\n return existingElement;\r\n }\r\n \r\n function getExistingOptionItemElementOnHigherLevels(element) {\r\n //check on higher levels if there is the same option \r\n var existingElement = { HtmlElement: null, SameLevel: true };\r\n var elements = document.querySelectorAll('input[id*=\"element' + element.HtmlId + '\"]');\r\n if (elements && elements.length) {\r\n if (elements.length == 1 && elements[0].getAttribute(\"data-level\") == element.Level) return { HtmlElement: elements[0], SameLevel: true };\r\n for (var i = 0; i < elements.length; i++) {\r\n var tmpElement = elements[i];\r\n var level = $(tmpElement).data('level');\r\n if (element.Level > level) {\r\n var checked = $(tmpElement).prop(\"checked\");\r\n if (checked) {\r\n var parentId = $(tmpElement).data(\"parentId\");\r\n var currentAccordion = $(tmpElement).closest(\".accordion-item\");\r\n var groupItems = currentAccordion.find('[data-parent-id=\"' + parentId + '\"]');\r\n var groupOptionItems = [];\r\n //groupitems and accordion maybe delete\r\n if (groupItems && groupItems.length) {\r\n for (var i = 0; i < groupItems.length; i++) {\r\n groupOptionItems.push({ Id: $(groupItems[i]).attr(\"id\"), Level: $(groupItems[i]).data(\"level\") });\r\n }\r\n }\r\n existingElement = { HtmlElement: tmpElement, SameLevel: false, GroupOptionItems: groupOptionItems, Accordion: currentAccordion };\r\n }\r\n }\r\n }\r\n }\r\n\r\n return existingElement;\r\n }\r\n\r\n function setConfigurationForm(configurationForm, openAllTabs) {\r\n selectedData.SelectedForm = configurationForm;\r\n elements = '
    ';\r\n var openedTabs = null;\r\n if (!openAllTabs)\r\n openedTabs = getOpenedConfigurationTabIds();\r\n\r\n var openedTableForOptionsWithoutCategory = false;\r\n $(\"#configurationQuantity\").val(configurationForm.Quantity);\r\n for (var i = 0; i < configurationForm.Elements.length; i++) {\r\n var element = configurationForm.Elements[i];\r\n if (element.ConfigurationElementType == \"Category\" && element.Options.length > 0) {\r\n closeFormOptionTableIfNeeded(openedTableForOptionsWithoutCategory);\r\n openedTableForOptionsWithoutCategory = false;\r\n createCategoryAccordionItem(element, openedTabs, openAllTabs);\r\n }\r\n else if (element.ConfigurationElementType == \"Option\") {\r\n if (!openedTableForOptionsWithoutCategory) {\r\n executedOnce = false;\r\n openedTableForOptionsWithoutCategory = true;\r\n categoryHtml = '
    ';\r\n }\r\n createFormOption(element);\r\n if (i == configurationForm.Elements.length - 1) {\r\n closeFormOptionTableIfNeeded(openedTableForOptionsWithoutCategory);\r\n }\r\n }\r\n }\r\n\r\n elements += '
    ';\r\n var configurationPanel = document.getElementById('configurationPanel');\r\n configurationPanel.innerHTML = elements;\r\n }\r\n\r\n function closeFormOptionTableIfNeeded(openedTableForOptionsWithoutCategory) {\r\n if (openedTableForOptionsWithoutCategory) {\r\n closeCategoryTableTag();\r\n clearSubcategoryPlaceholder();\r\n categoryHtml += '
    ';\r\n elements += categoryHtml;\r\n }\r\n }\r\n\r\n function createFormOption(formOption) {\r\n createCategoryTable(formOption, formOption);\r\n createFormOptionsOnLevelOne(formOption, formOption, 1);\r\n }\r\n\r\n function addVerificationToken(payload) {\r\n if (document.querySelector('input[name=\"__RequestVerificationToken\"]') !== null) {\r\n var token = document.querySelector('input[name=\"__RequestVerificationToken\"]').value;\r\n payload.__RequestVerificationToken = token;\r\n }\r\n }\r\n\r\n function ajaxCall(url, payload, selector, succesFunction, errorFunction) {\r\n if (payload)\r\n addVerificationToken(payload);\r\n if (!selector)\r\n selector = \".search-overlay\";\r\n showSpinner(selector);\r\n $.ajax({\r\n type: \"POST\",\r\n url: url,\r\n data: payload,\r\n dataType: \"json\",\r\n contentType: \"application/x-www-form-urlencoded; charset=utf-8\"\r\n }).done(function (response) {\r\n if (response.status === STATUS_OK) {\r\n succesFunction(response);\r\n }\r\n else {\r\n var message = response.Message;\r\n if (!message) message = response.message;\r\n console.log(\"ajax call: \" + url + \", message: \" + message);\r\n if (errorFunction != null) errorFunction(response);\r\n }\r\n\r\n }).fail(function (e) {\r\n console.log(\"ajax call: \" + url + \", status: \" + e.Status + \", message: \" + e.StatusText);\r\n alert(\"Error occured, url: \" + url + \", status: \" + e.Status + \", message: \" + e.StatusText);\r\n\r\n }).always(function () {\r\n hideSpinner(selector);\r\n });\r\n }\r\n\r\n function showSpinner(selector) {\r\n setSpinners(selector, \"block\");\r\n }\r\n\r\n function setSpinners(selector, display) {\r\n var spinners = document.querySelectorAll(selector);\r\n if (spinners && spinners.length > 0) {\r\n for (var i = 0; i < spinners.length; i++) {\r\n spinners[i].style.display = display;\r\n $(spinners[i]).find(\".loading-results-configurator\")[0].style.display = display;\r\n }\r\n }\r\n }\r\n\r\n function hideSpinner(selector) {\r\n setSpinners(selector, \"none\");\r\n }\r\n\r\n initConfigurator();\r\n });\ndefine(\"Configurator/main\", function(){});\n\n" ] }
    ' + '' + quantity + '' + priceValue + '