1if (!window.variantController) { 2 3 window.variantController = 4 { 5 registry: [], 6 customIdLookup: {}, 7 addToCartLinkLookup: {}, 8 addToCartButtonLookup: {}, 9 wishlistButtonLookup: {}, 10 addToQuoteButtonLookup: {}, 11 addToCartButtonIds: [], 12 massAddToCartButtonIds: [], 13 addToCartLinkIds: [], 14 employeeDDIdsLookup: [], 15 registerVariants: function (itemId, customId, priceId, priceDollarsId, priceCentsId, itemNrId, qtyDiscountsId, qtyDiscountPricesId, 16 productStatusId, productTimeFrameId, variantGTINId, qtyTextboxId, useVariantInventory, qtyDiscountsAcrossVariants, 17 addToCartButtonId, addToCartLinkId, selectedVariantsId, pkgVariantsId, childPriceId, bindQtyToParent, 18 bindQtyCheckboxId, personalizationIdsId, personalizationStringsId, checkThisOnlyOnButtonClick, rewardPointsId, 19 rewardPointsToPurchaseId, qtyInStockId, priceAreaId, salePriceId, salePriceAreaId, wasPriceId, wasPriceAreaId, 20 wishlistButtonId, massAddToCartButtonId, useQtyOf1IfNoQty, retailPriceId, retailPriceAreaId, youSaveId, groupAddToCartButtonId, 21 weightId, lengthId, widthId, heightId, availabilityId, subscriptionId, isDDLSwatchCombined, jsaonDDLMetaData, isFitmentEnabled, imageId, lazyLoad, productPhotoHandling, externalImageOverrideUrl, zoomOverrideUrl, employeeDDId, customFieldId, addToQuoteButtonId, variantAdditionalInfoId) { 22 this.registry.push(new VariantAjaxManager(itemId, customId, priceId, priceDollarsId, priceCentsId, itemNrId, qtyDiscountsId, qtyDiscountPricesId, productStatusId, productTimeFrameId, variantGTINId, qtyTextboxId, useVariantInventory, qtyDiscountsAcrossVariants, addToCartButtonId, addToCartLinkId, selectedVariantsId, pkgVariantsId, childPriceId, bindQtyToParent, bindQtyCheckboxId, personalizationIdsId, personalizationStringsId, rewardPointsId, rewardPointsToPurchaseId, qtyInStockId, priceAreaId, salePriceId, salePriceAreaId, wasPriceId, wasPriceAreaId, useQtyOf1IfNoQty, retailPriceId, retailPriceAreaId, youSaveId, weightId, lengthId, widthId, heightId, availabilityId, subscriptionId, isDDLSwatchCombined, jsaonDDLMetaData, isFitmentEnabled, imageId, lazyLoad, productPhotoHandling, externalImageOverrideUrl, zoomOverrideUrl, employeeDDId, customFieldId, addToQuoteButtonId, variantAdditionalInfoId)); 23 24 this.customIdLookup[customId] = this.registry[this.registry.length - 1]; 25 this.bindAddToCartButton(addToCartButtonId, checkThisOnlyOnButtonClick); 26 this.bindAddToCartLink(addToCartLinkId); 27 this.bindWishListButton(wishlistButtonId); 28 this.bindAddToQuoteButton(addToQuoteButtonId); 29 this.bindMassAddToCartButton(massAddToCartButtonId); 30 this.bindAddToCartButton(groupAddToCartButtonId, checkThisOnlyOnButtonClick); 31 this.bindEmployeeDD(employeeDDId, customFieldId); 32 33 if (addToCartLinkId != null && addToCartLinkId.length > 0) 34 this.addToCartLinkLookup[addToCartLinkId] = this.registry[this.registry.length - 1]; 35 36 if (checkThisOnlyOnButtonClick && addToCartButtonId != null && addToCartButtonId.length > 0) 37 this.addToCartButtonLookup[addToCartButtonId] = this.registry[this.registry.length - 1]; 38 39 if (wishlistButtonId != null && wishlistButtonId.length > 0) 40 this.wishlistButtonLookup[wishlistButtonId] = this.registry[this.registry.length - 1]; 41 42 if (addToQuoteButtonId != null && addToQuoteButtonId.length > 0) 43 this.addToQuoteButtonLookup[addToQuoteButtonId] = this.registry[this.registry.length - 1]; 44 45 if (checkThisOnlyOnButtonClick && groupAddToCartButtonId != null && groupAddToCartButtonId.length > 0) 46 this.addToCartButtonLookup[groupAddToCartButtonId] = this.registry[this.registry.length - 1]; 47 48 if (employeeDDId != null && employeeDDId.length > 0) 49 this.employeeDDIdsLookup[employeeDDId] = this.registry[this.registry.length - 1]; 50 }, 51 bindAddToCartButton: function (addToCartButtonId, checkThisOnlyOnButtonClick) { 52 53 if (addToCartButtonId != null && addToCartButtonId.length > 0) { 54 55 if ($.inArray(addToCartButtonId, this.addToCartButtonIds) != -1) 56 return; 57 58 this.addToCartButtonIds.push(addToCartButtonId); 59 60 $("#" + addToCartButtonId).click(function (event) { 61 62 var lastResult; 63 64 if (checkThisOnlyOnButtonClick) { 65 66 var controller = window.variantController.addToCartButtonLookup[addToCartButtonId]; 67 //need to have some sort of way to look up the class based on id here? 68 lastResult = controller.checkSelections(false, true, addToCartButtonId); 69 70 if (!lastResult.success) { 71 alert(lastResult.message); 72 event.preventDefault(); 73 return false; 74 } 75 76 controller.saveSelections(controller.getSelections(true).join("|")); 77 controller.savePersonalizations(controller.getPersonalizations().join("|")); 78 79 return true; 80 81 } 82 else { 83 84 for (var i = 0; i < window.variantController.registry.length; i++) { 85 86 lastResult = window.variantController.registry[i].checkSelections(true, false, addToCartButtonId); 87 88 if (!lastResult.success) { 89 alert(lastResult.message); 90 event.preventDefault(); 91 return false; 92 } 93 94 window.variantController.registry[i].saveSelections(window.variantController.registry[i].getSelections(true).join("|")); 95 window.variantController.registry[i].savePersonalizations(window.variantController.registry[i].getPersonalizations().join("|")); 96 } 97 } 98 99 return true; 100 }); 101 } 102 }, 103 bindMassAddToCartButton: function (massAddToCartButtonId) { 104 if (massAddToCartButtonId != null && massAddToCartButtonId.length > 0) { 105 106 if ($.inArray(massAddToCartButtonId, this.massAddToCartButtonIds) != -1) 107 return; 108 109 this.massAddToCartButtonIds.push(massAddToCartButtonId); 110 111 $("#" + massAddToCartButtonId).click(function (event) { 112 113 var lastResult; 114 115 for (var i = 0; i < window.variantController.registry.length; i++) { 116 117 lastResult = window.variantController.registry[i].checkSelections(true, false, massAddToCartButtonId); 118 119 if (!lastResult.success) { 120 alert(lastResult.message); 121 event.preventDefault(); 122 return false; 123 } 124 125 window.variantController.registry[i].saveSelections(window.variantController.registry[i].getSelections(true).join("|")); 126 window.variantController.registry[i].savePersonalizations(window.variantController.registry[i].getPersonalizations().join("|")); 127 } 128 129 return true; 130 }); 131 } 132 }, 133 bindWishListButton: function (wishlistButtonId) { 134 135 if (wishlistButtonId != null && wishlistButtonId.length > 0) { 136 137 $("#" + wishlistButtonId).click(function (event) { 138 // Try and enable this button's wishlist popover 139 $(this).popover('enable'); 140 var controller = window.variantController.wishlistButtonLookup[wishlistButtonId]; 141 var lastResult = controller.checkSelections(false, true, wishlistButtonId); 142 143 if (!lastResult.success) { 144 alert(lastResult.message); 145 event.preventDefault(); 146 // Disable wishlist popover 147 $(this).popover('disable'); 148 return false; 149 } 150 151 controller.saveSelections(controller.getSelections(true).join("|")); 152 controller.savePersonalizations(controller.getPersonalizations().join("|")); 153 154 return true; 155 }); 156 } 157 }, 158 bindAddToQuoteButton: function (addToQuoteButtonId) { 159 160 if (addToQuoteButtonId != null && addToQuoteButtonId.length > 0) { 161 162 $("#" + addToQuoteButtonId).click(function (event) { 163 // Try and enable this button's popover 164 $(this).popover('enable'); 165 var controller = window.variantController.addToQuoteButtonLookup[addToQuoteButtonId]; 166 var lastResult = controller.checkSelections(false, true, addToQuoteButtonId); 167 168 if (!lastResult.success) { 169 alert(lastResult.message); 170 event.preventDefault(); 171 // Disable popover 172 $(this).popover('disable'); 173 return false; 174 } 175 176 controller.saveSelections(controller.getSelections(true).join("|")); 177 controller.savePersonalizations(controller.getPersonalizations().join("|")); 178 179 return true; 180 }); 181 } 182 }, 183 bindAddToCartLink: function (addToCartLinkId) { 184 if (addToCartLinkId != null && addToCartLinkId.length > 0) { 185 186 if ($.inArray(addToCartLinkId, this.addToCartLinkIds) != -1) 187 return; 188 189 this.addToCartLinkIds.push(addToCartLinkId); 190 191 $("#" + addToCartLinkId).click(function (event) { 192 193 var lastResult; 194 var controller = window.variantController.addToCartLinkLookup[addToCartLinkId]; 195 196 //need to have some sort of way to look up the class based on id here? 197 lastResult = controller.checkSelections(false, true, addToCartLinkId); 198 199 if (!lastResult.success) { 200 alert(lastResult.message); 201 event.preventDefault(); 202 return false; 203 } 204 205 if (!controller.uploadPersonalizationFiles()) { 206 event.preventDefault(); 207 return false; 208 } 209 210 controller.setSelectionsOnLink($(this), controller.getSelections(false).join("|")); 211 controller.setPersonalizationsOnLink($(this), controller.getPersonalizations(false).join("|")); 212 return true; 213 }); 214 } 215 }, 216 bindEmployeeDD: function (employeeDDId, customFieldId) { 217 if (employeeDDId != null && employeeDDId.length > 0) { 218 $("#" + employeeDDId).change(function (event) { 219 var dropdownValue = $(this).val(); 220 var employeeName = $(this).find('option[value=' + dropdownValue + ']').text(); 221 var dv = document.getElementById(customFieldId); 222 if (dv) { 223 var customFields; 224 var controller = window.variantController.employeeDDIdsLookup[employeeDDId]; 225 $.ajax({
226 type: "POST", 227 contentType: "application/json; charset=utf-8", 228 url: "/Store/Controls/ScriptService.asmx/GetCustomFields", 229 dataType: "json", 230 data: JSON.stringify({ 'employeeID': dropdownValue }), 231 }).done(function (response) { 232 if (response) { 233 dv.innerHTML = ""; 234 customFields = response.d; 235 if (customFields.length > 0) { 236 customFields.forEach(function (field) { 237 label = document.createElement("span"); 238 label.textContent = field.label + ": "; 239 label.className = "custom-field-label"; 240 dv.appendChild(label); 241 242 value = document.createElement("span"); 243 value.textContent = field.value; 244 value.setAttribute("target", field.name); 245 value.className = "custom-field-value"; 246 dv.appendChild(value); 247 248 br = document.createElement("br"); 249 dv.appendChild(br); 250 }); 251 252 if (controller._useVariantInventory) { 253 controller.$varInvDDs.each(function (i, item) { 254 if ($(item).is("select") || (controller._isDDLSwatchCombined && $(item).is("div.variants-combo-main-container"))) { 255 customFields.forEach(function (field) { 256 if (item.getAttribute("groupname") == field.name) { 257 let errorDv = $('.variant-custom-error[groupname=' + controller._customId + '_' + field.name + ']').html(''); 258 errorDv[0].setAttribute('data-auto-select', 'true') 259 errorDv[0].setAttribute('data-error', ''); 260 if (field.value) { 261 if (controller._isDDLSwatchCombined) { 262 let varOption = $('#' + item.id).find('.variants-combo-option[varname=' + field.value + ']'); 263 if (varOption && varOption.length > 0 && varOption[0].style.display != 'none') { 264 varOption.click(); 265 } 266 else { 267 errorDv.html('Profile option unavailable.'); 268 errorDv[0].setAttribute('data-error', 'option-unavailable'); 269 } 270 } 271 else { 272 let varOption = $('#' + item.id + ' option[varname=' + field.value + ']'); 273 if (varOption && varOption.length > 0) 274 $(item).val(varOption.val()).change(); 275 else { 276 errorDv.html('Profile option unavailable.'); 277 errorDv[0].setAttribute('data-error', 'option-unavailable'); 278 } 279 } 280 } 281 else { 282 errorDv.html(employeeName + ' has not selected a profile option for ' + field.label); 283 errorDv[0].setAttribute('data-error', 'no-profile-value'); 284 } 285 } 286 }) 287 } 288 }) 289 } 290 } 291 } 292 }); 293 } 294 return true; 295 }); 296 } 297 } 298 }; 299} 300 301 302var VariantAjaxManager = function (itemId, customId, priceId, priceDollarsId, priceCentsId, itemNrId, qtyDiscountsId, qtyDiscountPricesId, 303 productStatusId, productTimeFrameId, variantGTINId, qtyTextboxId, useVariantInventory, 304 qtyDiscountsAcrossVariants, addToCartButtonId, addToCartLinkId, selectedVariantsId, pkgVariants, 305 childPriceId, bindQtyToParent, bindQtyCheckboxId, personalizationIdsId, personalizationStringsId, 306 rewardPointsId, rewardPointsToPurchaseId, qtyInStockId, priceAreaId, salePriceId, salePriceAreaId, wasPriceId, wasPriceAreaId,
307 useQtyOf1IfNoQty, retailPriceId, retailPriceAreaId, youSaveId, weightId, widthId, lengthId, heightId, availabilityId, subscriptionId, isDDLSwatchCombined, 308 jsaonDDLMetaData, isFitmentEnabled, imageId, lazyLoad, productPhotoHandling, externalImageOverrideUrl, zoomOverrideUrl, employeeDDId, customFieldId, addToQuoteButtonId, variantAdditionalInfoId) { 309 this._itemId = itemId; 310 this._imageId = imageId; 311 this._priceId = priceId; 312 this._priceDollarsId = priceDollarsId; 313 this._priceCentsId = priceCentsId; 314 this._itemNrId = itemNrId; 315 this._qtyDiscountsId = qtyDiscountsId; 316 this._qtyDiscountPricesId = qtyDiscountPricesId; 317 this._productStatusId = productStatusId; 318 this._productTimeFrameId = productTimeFrameId; 319 this._variantGTINId = variantGTINId; 320 this._customId = customId; 321 this._qtyTextboxId = qtyTextboxId; 322 this._useVariantInventory = useVariantInventory; 323 this._qtyDiscountsAcrossVariants = qtyDiscountsAcrossVariants; 324 this._addToCartButtonId = addToCartButtonId; 325 this._addToCartLinkId = addToCartLinkId; 326 this._selectedVariantsId = selectedVariantsId; 327 this._pkgVariants = pkgVariants; 328 this._childPriceId = childPriceId; 329 this._bindQtyToParent = bindQtyToParent; 330 this._bindQtyCheckBoxId = bindQtyCheckboxId; 331 this._personalizationIdsId = personalizationIdsId; 332 this._personalizationStringsId = personalizationStringsId; 333 this._rewardPointsId = rewardPointsId; 334 this._rewardPointsToPurchaseId = rewardPointsToPurchaseId; 335 this._qtyInStockId = qtyInStockId; 336 this._priceAreaId = priceAreaId; 337 this._salePriceId = salePriceId; 338 this._salePriceAreaId = salePriceAreaId; 339 this._wasPriceId = wasPriceId; 340 this._wasPriceAreaId = wasPriceAreaId; 341 this._useQtyOf1IfNoQty = useQtyOf1IfNoQty; 342 this._retailPriceId = retailPriceId; 343 this._retailPriceAreaId = retailPriceAreaId; 344 this._youSaveId = youSaveId; 345 this._weightId = weightId; 346 this._lengthId = lengthId; 347 this._widthId = widthId; 348 this._heightId = heightId; 349 this._availability = availabilityId; 350 this._subscriptionId = subscriptionId; 351 this._isDDLSwatchCombined = isDDLSwatchCombined; 352 this._VariantsDDLCollection = jsaonDDLMetaData; 353 this._isFitmentEnabled = isFitmentEnabled; 354 this._lazyLoadEnabled = lazyLoad; 355 this._productPhotoHandling = productPhotoHandling; 356 this._externalImageOverrideUrl = externalImageOverrideUrl; 357 this._zoomOverrideUrl = zoomOverrideUrl; 358 this._employeeDDId = employeeDDId; 359 this._customFieldId = customFieldId; 360 this._addToQuoteButtonId = addToQuoteButtonId; 361 this._variantAdditionalInfoId = variantAdditionalInfoId; 362 this.indexes = {}; 363 this.combinedDDLCollection = []; 364 this.emailRegex = /^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\[(?:\d{1,3}\.){3}\d{1,3}\])$/; 365 this.selectedVariant = ""; 366 this.selectedVariantGroup = ""; 367 this.selectedControlID = ""; 368 var self = this; 369 //---------------- Helpers Related To Combined DDL with Swatch Object based --------//// 370 self.combinedSelect = function (containerElement, options) { 371 // element refs 372 if (containerElement == undefined) 373 return; 374 this.el = containerElement; 375 this.comboEl = containerElement.querySelector('[role=combobox]'); 376 this.listboxEl = containerElement.querySelector('[role=listbox]'); 377 // data 378 this.idBase = this.comboEl.id; 379 this.options = options; // only all options related to this ddl objects 380 // state 381 this.disabled = false; 382 this.activeIndex = 0; 383 this.open = false; 384 }; 385 self.combinedSelect.prototype.init = function () { 386 if (this.options == undefined) 387 return; 388 var self = this; 389 var defaultSelectedOption = this.options.find(function (obj, indx, ar) { 390 if (obj.IsDefaultSelected) { 391 this.activeIndex = indx; 392 return obj; 393 } // if system somehow set the default selection 394 }); 395 396 if (!defaultSelectedOption || defaultSelectedOption == null) { 397 defaultSelectedOption = this.options[0]; // otherwise show first item selected 398 } 399 this.comboEl.innerHTML = this.buildInnerHtml(defaultSelectedOption); // first element selected by default 400 401 this.comboEl.addEventListener('click', () => this.updateMenuState(true)); 402 this.comboEl.addEventListener('blur', this.onComboBlur.bind(this)); 403 VariantButtons.UpdateButtons(defaultSelectedOption.GroupId, defaultSelectedOption.VarintId.toString()); 404 this.options.map((option, index) => { 405 const optionEl = document.createElement('div'); 406 optionEl.setAttribute('role', 'option'); 407 optionEl.setAttribute('varname', option.VariantName); 408 optionEl.id = `${this.idBase}-${option.VarintId}`;//optionEl.id = `${this.idBase}-${index}`; 409 410 if (option.VarintId == defaultSelectedOption.VarintId) { 411 optionEl.className = 'variants-combo-option option-current'; 412 optionEl.setAttribute('aria-selected', 'true'); 413 } else { 414 optionEl.className = 'variants-combo-option'; 415 optionEl.setAttribute('aria-selected', 'false'); 416 } 417 optionEl.setAttribute('variantid', option.VarintId); 418 419 //optionEl.innerText = option; 420 optionEl.innerHTML = this.buildInnerHtml(option); 421 422 //on combo option click 423 $(optionEl).on('click', function (event, params) { 424 event.stopPropagation(); 425 self.onOptionClick(index, event, params); 426 }); 427 optionEl.addEventListener('mousedown', this.onOptionMouseDown.bind(this)); 428 429 this.listboxEl.appendChild(optionEl); 430 });
431 }; 432 self.combinedSelect.prototype.disableMe = function () { 433 this.disabled = true; 434 $(this.comboEl).removeClass("variants-combo-input-enabled").addClass("variants-combo-input-disabled"); 435 console.log('Select is disabled'); 436 }; 437 self.combinedSelect.prototype.enableMe = function () { 438 this.disabled = false; 439 $(this.comboEl).removeClass("variants-combo-input-disabled").addClass("variants-combo-input-enabled"); 440 }; 441 self.combinedSelect.prototype.buildInnerHtml = function (option) { 442 443 var photoImagePath = ""; 444 var bgColor = ""; 445 var displayText = ""; 446 var height = ""; 447 var width = ""; 448 449 if (option) { 450 451 displayText = option.DisplayText; 452 photoImagePath = option.PhotoImagePath; 453 bgColor = option.SwatchThumbColor; 454 height = option.SwatchImageHeight; 455 width = option.SwatchImageWidth; 456 if (option.HasPhotoImage) { 457 return '<div class="variants-combo-div-table">' + 458 '<div class="variants-combo-div-table-Row">' + 459 '<div class="variants-combo-div-table-cell CustomConvertPrice">' + displayText + '</div>' + 460 '<div class="variants-combo-div-table-cell-right">' + 461 '<img src="' + photoImagePath + '" height="' + height + '" width="' + width + '" class="variants-combo-img" ' + (self._lazyLoadEnabled ? 'loading="lazy"' : '') + ' />' + 462 '</div>' + 463 '</div>' + 464 '</div>'; 465 } else { 466 467 var styleTag = "background-color:" + bgColor; 468 if (!option.PhotoImagePath && !bgColor) { 469 styleTag = "display:none;"; 470 } 471 472 return '<div class="variants-combo-div-table">' + 473 '<div class="variants-combo-div-table-Row">' + 474 '<div class="variants-combo-div-table-cell CustomConvertPrice">' + displayText + '</div>' + 475 '<div class="variants-combo-div-table-cell-right">' + 476 '<img src="' + photoImagePath + '" class="variants-combo-img-backgroundColor" style="' + styleTag + '" ' + (self._lazyLoadEnabled ? 'loading="lazy"' : '') + ' />' + 477 '</div>' + 478 '</div>' + 479 '</div>'; 480 } 481 } 482 } 483 self.combinedSelect.prototype.onComboBlur = function () { 484 if (this.disabled) 485 return; 486 //console.log('Select.prototype.onComboBlur'); 487 if (this.ignoreBlur) { 488 this.ignoreBlur = false; 489 return; 490 } 491 492 if (this.open) { 493 this.updateMenuState(false, false); 494 } 495 }; 496 self.combinedSelect.prototype.onOptionChange = function (index) { 497 if (this.disabled) 498 return; 499 // debugger; 500 //console.log('Select.prototype.onOptionChange'); 501 this.activeIndex = index; 502 this.comboEl.setAttribute('aria-activedescendant', `${this.idBase}-${index}`); 503 504 // update active style 505 const options = this.el.querySelectorAll('[role=option]'); 506 [...options].forEach(optionEl => { 507 optionEl.classList.remove('option-current'); 508 }); 509 options[index].classList.add('option-current'); 510 511 if (isScrollable(this.listboxEl)) { 512 maintainScrollVisibility(options[index], this.listboxEl); 513 } 514 }; 515 self.combinedSelect.prototype.onOptionClick = function (index, evnt, eventParamsdata) { 516 if (this.disabled) 517 return; 518 //debugger; 519 //console.log('Select.prototype.onOptionClick'); 520 this.onOptionChange(index); 521 this.selectOption(index, eventParamsdata); 522 this.updateMenuState(false, false); 523 }; 524 self.combinedSelect.prototype.onOptionMouseDown = function () { 525 this.ignoreBlur = true; 526 }; 527 self.combinedSelect.prototype.selectOption = function (index, eventData) { 528 if (this.disabled) 529 return; 530 //console.log('Select.prototype.selectOption'); 531 //debugger; 532 const selected = this.options[index]; 533 this.comboEl.innerHTML = this.buildInnerHtml(selected); 534 this.activeIndex = index; 535 536 // update aria-selected 537 const options = this.el.querySelectorAll('[role=option]'); 538 [...options].forEach(optionEl => { 539 optionEl.setAttribute('aria-selected', 'false'); 540 });
541 var currentOptionElement = options[index]; 542 currentOptionElement.setAttribute('aria-selected', 'true'); 543 544 //To do: shall remove hidden field logic as hidden field is not working on server 545 //var hdnfld = $(this.comboEl.closest(".variants-combo-main-container")).children("[id$='_hdnComboSelectedValue']"); // sets selectedvalue on parent container as well. 546 //hdnfld.val(selected.VarintId); 547 var ddlchildCtrl = $(this.comboEl.closest(".variants-combo-main-container")).children("[id$='_ddlCombined']"); // sets selectedvalue on parent container as well. 548 ddlchildCtrl.val(selected.VarintId); // set selected value here 549 VariantButtons.UpdateButtons(selected.GroupId, selected.VarintId.toString()); 550 //eventdata contains if the nextdlls calls come in then if we do not control it individal drop down donot show their own thumbnail image on left 551 if (!eventData) { 552 //make main image change //like update the left main image 553 if (selected.ControlId && selected.ControlId != '' && selected.VarintId > 0) { 554 if (!self._useVariantInventory) { 555 try { 556 VariantSwatches.SelectVariant(selected.GroupId, selected.VarintId, false, self._imageId, eval('VariantSwatches_' + selected.ControlId)); 557 } catch (e) { 558 console.log('error selecting main photo image'); 559 } 560 } 561 } 562 self.updateVariantCustomFields(selected.GroupId, selected.VarintId); 563 self.selectedVariantGroup = selected.GroupId; 564 self.selectedVariant = selected.VarintId; 565 self.selectedControlID = selected.ControlId; 566 } 567 ///variant ajax manager; 568 self.onVariantChange($(this.comboEl.closest(".variants-combo-main-container"))); 569 570 }; 571 self.combinedSelect.prototype.updateMenuState = function (open, callFocus = true) { 572 if (this.disabled) 573 return; 574 575 this.open = open; 576 this.comboEl.setAttribute('aria-expanded', `${open}`); 577 open ? this.el.classList.add('open') : this.el.classList.remove('open'); 578 callFocus && this.comboEl.focus(); 579 }; 580 self.combinedSelect.prototype.setSelectedValue = function (variantId, isUnselectIfnotFound, isNextCall = false) { 581 582 var foundOption = this.options.find(function (obj, indx, ar) { 583 if (obj.VarintId == variantId) { 584 return obj; 585 } 586 }); 587 588 if (!foundOption) { 589 if (isUnselectIfnotFound) { 590 this.resetComboBoxSelection(); 591 //do i need to call here on variant chane, currently NO may be // to do check - currently there is another bug in current legacy implementation 592 } 593 } else { 594 //set selected value and every thing should be happen for the drop down like selectoption 595 var curroptEl = null; 596 const options = this.el.querySelectorAll('[role=option]'); 597 [...options].forEach(optionEl => { 598 if (optionEl.getAttribute("variantid") == variantId) { 599 curroptEl = optionEl; 600 } 601 }); 602 603 if (curroptEl) { 604 var params = []; 605 if (isNextCall) { 606 params.push({ VariantId: variantId, IsNextCall: isNextCall }); 607 } 608 $(curroptEl).trigger('click', params); // click on option to make it selected 609 } 610 } 611 612 }; 613 self.combinedSelect.prototype.getSelectedValue = function () { 614 //debugger; 615 var selectedValue = ''; 616 var comboMainContainerDivElement = this.comboEl.closest(".variants-combo-main-container"); 617 var ddlchildCtrl = $(comboMainContainerDivElement).children("[id$='_ddlCombined']"); // sets selectedvalue on parent container as well. 618 selectedValue = ddlchildCtrl.val(); 619 620 return selectedValue; 621 }; 622 self.combinedSelect.prototype.resetComboBoxSelection = function (keepDefaultItemDisplaySelection) { 623 //default 624 var keepDefaultItemdisplay = false; 625 if (keepDefaultItemDisplaySelection) { 626 keepDefaultItemdisplay = keepDefaultItemDisplaySelection; 627 } 628 var comboMainContainerDivElement = this.comboEl.closest(".variants-combo-main-container"); 629 var ddlCombinedSelection = $(comboMainContainerDivElement).children("[id$='_ddlCombined']"); 630 //hdnfld.val(''); 631 //$(this.comboEl).children("div.variants-combo-div-table").html(''); 632 var hdnSelectedVal = ddlCombinedSelection.val(); 633 634 if (hdnSelectedVal != "-999" || (hdnSelectedVal == "-999" && !keepDefaultItemdisplay)) { 635 ddlCombinedSelection.val(''); // test it 636 $(this.comboEl).children("div.variants-combo-div-table").html(''); 637 } 638 // update aria-selected 639 const options = this.el.querySelectorAll('[role=option]');
640 [...options].forEach(optionEl => { 641 if (hdnSelectedVal != "-999" || (hdnSelectedVal == $(optionEl).attr("variantid") && !keepDefaultItemdisplay)) { 642 optionEl.setAttribute('aria-selected', 'false'); 643 $(optionEl).removeClass("option-current"); 644 } 645 }); 646 647 }; 648 self.combinedSelect.prototype.reconfigureComboOptions = function (variantsJson, variantStockStatuses, variantModifierTexts, variantNames) { 649 var mySelf = this; 650 var customID = self._customId; 651 var previousVal = this.getSelectedValue(); // get selectected value 652 var bPreviousFound = false; 653 var firstVariantID = "-999"; 654 655 //let's hide the combo options instead of removing 656 $(this.listboxEl).children("[role='option']").each(function () { 657 var $currOption = $(this); 658 if ($currOption.attr("variantid") != "-999") { 659 $currOption.css("display", "none"); 660 } 661 }); 662 this.resetComboBoxSelection(true); 663 664 var defaultGroupSelection = this.doIHaveDefaultGroupOption(); 665 666 var firstVariant = true; 667 $.each(variantsJson, function (key, value) { 668 //add applied variants in sort order. the leading space is to stop json resort variants by key value 669 var variantId = key.trim(); 670 var foundOption = $(mySelf.listboxEl).children("[role='option'][variantid='" + variantId + "']"); 671 if (foundOption) { 672 foundOption.css("display", "block"); 673 var currentVariant = foundOption[0]; 674 currentVariant.innerHTML = currentVariant.innerHTML.replace(currentVariant.innerText, value.trim()); 675 mySelf.options.find(x => x.VarintId == variantId).DisplayText = value.trim(); 676 if (!defaultGroupSelection && firstVariant) { 677 firstVariant = false; // this is to make dropdown a first selection only first time 678 firstVariantID = variantId; 679 } 680 } 681 }); 682 683 if (previousVal != "") { 684 685 //keep previous selection selected if it is still available 686 $.each(variantsJson, function (key, value) { 687 //add applied variants in sort order. the leading space is to stop json resort variants by key value 688 var variantId = key.trim(); 689 //only set the selected value to previous one if upcoming in variantjson contains the variant id of previous variantid 690 if (variantId != "-999" && variantId == previousVal && !bPreviousFound && (variantStockStatuses === null || variantStockStatuses[key] != 0)) { 691 bPreviousFound = true; 692 mySelf.setSelectedValue(previousVal, true, true); 693 } 694 else if (variantId != "-999" && variantId == previousVal && (variantStockStatuses != null && variantStockStatuses[key] == 0)) { 695 let errorDv = $('.variant-custom-error[groupname=' + customID + '_' + mySelf.el.getAttribute("groupname") + ']'); 696 if (errorDv && errorDv.length > 0 && errorDv[0].hasAttribute('data-auto-select')) { 697 errorDv.html('Profile option is unavailable.'); 698 errorDv[0].setAttribute('data-error', 'status-unavailable'); 699 } 700 if (!firstVariant) 701 mySelf.setSelectedValue(firstVariantID, true, true); 702 } 703 var button = $("div[id^='varbutton_" + mySelf.options.find(x => x.VarintId == variantId).GroupId + "_" + variantId + "']"); 704 if (button.length > 0 && variantNames !== null && variantModifierTexts !== null) 705 button.html("<span class='desc-text'>" + variantNames[key] + "</span><span class='modifier-text'>" + variantModifierTexts[key] + "</span>"); 706 }); 707 } 708 else { 709 if (!firstVariant) 710 mySelf.setSelectedValue(firstVariantID, true, true); 711 } 712 VariantButtons.HideButtons(mySelf.options[0].GroupId, variantsJson); 713 }; 714 self.combinedSelect.prototype.doIHaveDefaultGroupOption = function () { 715 716 var result = false; 717 var defaultGroupSelection = this.options.find(function (obj, indx, ar) { 718 if (obj.VarintId == "-999") { 719 return obj; 720 } // if system somehow set the default selection 721 }); 722 723 724 if (defaultGroupSelection) { 725 result = true; 726 } 727 return result; 728 729 } 730 self.locateCombinedDDLObject = function (elementId) { 731 var currentCombinedDDL = this.combinedDDLCollection.find(function (obj, index, array) { 732 if (obj.el.id == elementId) { 733 return obj;
734 } 735 }); 736 return currentCombinedDDL; 737 }; 738 739 $(function () { 740 self.init(); 741 }); 742}; 743 744VariantAjaxManager.prototype = { 745 746 init: function () { 747 var self = this; 748 //debugger; 749 750 var groupNameSelector = "variantGroupID_" + this._customId; 751 752 var ddlSelector = ".variantDropDown" + this._customId + ", .variantRadioButtonList" + this._customId + ", .variantCheckBox" + this._customId; 753 754 if (this._isDDLSwatchCombined) { 755 ddlSelector = ".variantRadioButtonList" + this._customId + ", .variantCheckBox" + this._customId; // for avoid binding change ddl event on combined ddl which is of type div not type select 756 this._VariantsDDLCollection.map((groupItem, index) => { 757 758 var combinedSelect = new self.combinedSelect($('#' + groupItem.SelectDDLClientId).get(0), groupItem.DropDownDataCol); 759 combinedSelect.init(); 760 this.combinedDDLCollection.push(combinedSelect); // maintain all ddl collection object 761 }); 762 } 763 var $dd = $(ddlSelector); 764 this.$dd = $dd; 765 766 //20220309 AG Shared for each functions 767 function getCurrentCombinedDDL(elementId) { 768 return self._isDDLSwatchCombined ? self.locateCombinedDDLObject(elementId) : null; 769 } 770 function disableVariant(element, currentCombinedDDL) { 771 if ($(element).is("select")) { 772 $(element).prop("disabled", "disabled"); 773 } 774 else if (this._isDDLSwatchCombined && $(element).is("div.variants-combo-main-container")) { 775 // ?? this is combined drop down what to do with it? 776 currentCombinedDDL.disableMe(); 777 } 778 else { 779 $(element).find("input").attr("disabled", "disabled").first().prop("checked", "checked"); 780 } 781 } 782 783 //20220308 AG Hide variants on initial load. Variant options will be loaded after fitment is selected 784 if (this._isFitmentEnabled) { 785 $dd.each(function (index, element) { 786 var currentCombinedDDL = getCurrentCombinedDDL($(this).prop("id")); 787 self.indexes[this.id] = index; 788 789 // Disable all variants to ensure they wont be used 790 disableVariant(this, currentCombinedDDL); 791 }); 792 } 793 794 if (this._useVariantInventory) { 795 796 if (this._isDDLSwatchCombined) { 797 this.$varInvDDs = $(".variantDropDown-Combined" + this._customId + ", " + ddlSelector).not("[id*=NonInventoryVariantGroup" + this._customId + "]"); 798 } else { 799 this.$varInvDDs = $dd.not("[id*=NonInventoryVariantGroup" + this._customId + "]"); 800 } 801 802 803 if ($("#" + this._selectedVariantsId).val() !== undefined) { 804 var ids = $("#" + this._selectedVariantsId).val().split("|"); 805 806 var lastVal; 807 this.$varInvDDs.each(function (i) { 808 self.indexes[this.id] = i; 809 var currentCombinedDDL = getCurrentCombinedDDL($(this).prop("id")); 810 811 //if (i < ids.length) { 812 //if ($(this).is("select")) { 813 //$(this).val(ids[i]); // seems like setting up a selected 814 815 //} else if (self._isDDLSwatchCombined && $(this).is("div.variants-combo-main-container")) { 816 // // ?? this is combined drop down what to do with it? 817 //var currentCombinedDDL = locateCombinedDDLObject($(this)); 818 //currentCombinedDDL.setSelectedValue(ids[i], true); // should unselect for inventory variant case? 819 //} 820 //} 821 822 if (self._useVariantInventory && i > 0 && lastVal === "-999") { 823 disableVariant(this, currentCombinedDDL); 824 } 825 826 if ($(this).is("select")) { 827 lastVal = $(this).val(); 828 } else if (self._isDDLSwatchCombined && $(this).is("div.variants-combo-main-container")) { 829 lastVal = currentCombinedDDL.getSelectedValue(); // should unselect for inventory variant case? 830 } 831 else { 832 if ($(this).find("input:checked").length > 0) { 833 lastVal = $(this).find("input:checked").val(); 834 } 835 else { 836 lastVal = "-999"; 837 } 838 } 839 }); 840 } 841 else { 842 this.$varInvDDs.each(function (i) { 843 self.indexes[this.id] = i; 844 }); 845 } 846 } 847 848 $('.variant-repeater__variant').unbind('click').click(function () { 849 850 var variant = $(this); 851 852 if (variant.hasClass('selected')) 853 variant.removeClass('selected'); 854 else 855 variant.addClass("selected"); 856 857 self.updatePrice(); 858 }); 859 860 $(".variantCheckBox" + this._customId + " label").each(function () { 861 $(this).addClass("CustomConvertPrice"); 862 });
863 864 $(".variantRadioButtonList" + this._customId + " label").each(function () { 865 $(this).addClass("CustomConvertPrice"); 866 }); 867 868 $(".variantDropDown" + this._customId + " option").each(function () { 869 $(this).addClass("CustomConvertPrice"); 870 }); 871 872 $(".variant-repeater__variant .card-text").each(function () { 873 $(this).addClass("CustomConvertPrice"); 874 }); 875 876 $dd.change(function () { 877 if ($(this).is("select")) { 878 try { 879 self.selectedVariantGroup = $(this).parent().find("input[type = hidden]").val(); 880 self.selectedVariant = $(this).val(); 881 self.selectedControlID = "ProductVariations_variantGroup" + self._customId + "_" + self.selectedVariantGroup; 882 self.updateVariantCustomFields(self.selectedVariantGroup, self.selectedVariant); 883 } 884 catch { } 885 } 886 self.onVariantChange($(this)); 887 }); 888 889 $(".variantRadioButtonList" + this._customId + " input").change(function () { 890 try { 891 self.selectedVariantGroup = $(this).attr("name").split("_").pop(); 892 self.selectedVariant = $(this).val(); 893 self.selectedControlID = "ProductVariations_variantGroup" + self._customId + "_" + self.selectedVariantGroup; 894 self.updateVariantCustomFields(self.selectedVariantGroup, self.selectedVariant); 895 } 896 catch { } 897 self.onVariantChange($(this)); 898 }); 899 900 $(".variantCheckBox" + this._customId + " input").change(function () { 901 self.onVariantChange($(this)); 902 }); 903 904 $(".personalizationTextbox" + this._customId).change(function () { 905 self.onPersonalizationChange($(this)); 906 }); 907 908 $(".personalizationTextboxWithConfirm" + this._customId).change(function () { 909 self.onPersonalizationChange($(this)); 910 }); 911 912 $(".PersonalizationFileUpload" + this._customId).change(function () { 913 self.onPersonalizationChange($(this)); 914 }); 915 916 $(".PersonalizationEmailAddress" + this._customId).change(function () { 917 self.onPersonalizationChange($(this)); 918 }); 919 920 $(".PersonalizationPhoneNumber" + this._customId).change(function () { 921 self.onPersonalizationChange($(this)); 922 }); 923 924 $(".PersonalizationDatePicker" + this._customId).change(function () { 925 self.onPersonalizationChange($(this)); 926 self.enableSteps($(this), self._customId); 927 }); 928 929 $(".PersonalizationDropDown" + this._customId).change(function () { 930 self.onPersonalizationChange($(this)); 931 self.enableSteps($(this), self._customId); 932 }); 933 934 $('input[class*="NextStep' + this._customId + '"]').keyup(function (e) { 935 self.enableSteps($(this), self._customId); 936 }); 937 938 $('select[class*="NextStep' + this._customId + '"]').keyup(function (e) { 939 self.enableSteps($(this), self._customId); 940 }); 941 942 $('textarea[class*="NextStep' + this._customId + '"]').keyup(function (e) { 943 self.enableSteps($(this), self._customId); 944 }); 945 946 if (this._subscriptionId != "") { 947 948 $("#" + this._subscriptionId).change(function () { 949 self.updatePrice(); 950 }); 951 } 952 953 try { 954 if (typeof this.$varInvDDs != 'undefined' && this.$varInvDDs) { 955 var firstInvVariantddl = this.$varInvDDs.first(); 956 if (!this._isDDLSwatchCombined) { 957 firstInvVariantddl.change(); // ddl change event internally calls to this // but testing needs here do not know yet the purpose 958 } else { 959 960 if (firstInvVariantddl.is("div.variants-combo-main-container")) { 961 self.onVariantChange($(firstInvVariantddl)); // ddl change event internally calls to this // but testing needs here do not know yet the purpose 962 } else { 963 firstInvVariantddl.change(); 964 } 965 } 966 } 967 } 968 catch (err) { } 969 970 this.initVariantCustomFields(); 971 }, 972 973 ajaxCall: function (method, parameters, success) { 974 $.ajax({
975 type: "POST", 976 contentType: "application/json; charset=utf-8", 977 url: "/Store/Controls/ScriptService.asmx/" + method, 978 dataType: "json", 979 data: parameters 980 }).done(success); 981 }, 982 983 onPersonalizationChange: function ($element) { 984 $element.removeClass("needsSelection"); 985 this.updatePrice(); 986 }, 987 988 onVariantChange: function ($element) { 989 if (this._useVariantInventory) { 990 this.updateVariants($element); 991 } 992 else { 993 this.updatePrice(); 994 } 995 996 $element.removeClass("needsSelection"); 997 }, 998 999 updateVariantCustomFields: function (groupId, variantId) { 1000 var $group = $(".variant-custom-fields__group[data-group='" + groupId + "']"); 1001 if ($group.length === 0) return; 1002 $group.find(".variant-custom-fields__variant").hide(); 1003 $group.find(".variant-custom-fields__variant[data-value='" + variantId + "']").show(); 1004 }, 1005 1006 initVariantCustomFields: function () { 1007 var self = this; 1008 $(".variant-custom-fields__group").each(function () { 1009 var groupId = $(this).attr("data-group"); 1010 $(this).find(".variant-custom-fields__variant").hide(); 1011 1012 var variantId = null; 1013 1014 var $select = $("select[id*='variantGroup" + self._customId + "_" + groupId + "']"); 1015 if ($select.length) { 1016 variantId = $select.val(); 1017 } 1018 1019 if (!variantId || variantId === '-999') { 1020 var $checked = $(".variantRadioButtonList" + self._customId + " input[name$='_" + groupId + "']:checked"); 1021 if ($checked.length) { 1022 variantId = $checked.val(); 1023 } 1024 } 1025 1026 self.updateVariantCustomFields(groupId, variantId); 1027 }); 1028 }, 1029 1030 onFitmentChange: function (matchedChildrenIds) { 1031 this.getVariantsFromFitment(matchedChildrenIds); 1032 }, 1033 1034 enableSteps: function ($element, customId) { 1035 var arr = $element.prop('class').split(" "); 1036 1037 if (arr.length >= 3) { 1038 1039 //have to find step group, stepID and nextstep 1040 var stepGroupClass = ""; 1041 var stepIdClass = ""; 1042 var nextStepIdClass = ""; 1043 for (var i = 0; i < arr.length; i++) { 1044 if (arr[i].indexOf("StepGroup") != -1) 1045 stepGroupClass = arr[i]; 1046 else if (arr[i].indexOf("StepID") != -1) 1047 stepIdClass = arr[i]; 1048 else if (arr[i].indexOf("NextStep") != -1) 1049 nextStepIdClass = arr[i]; 1050 } 1051 1052 if (stepIdClass != "" && nextStepIdClass != "") { 1053 var stepIDs = stepIdClass.split("_"); 1054 var stepID = stepIDs[stepIDs.length - 1]; 1055 var nextStepIDs = nextStepIdClass.split("_"); 1056 var nextStepID = nextStepIDs[nextStepIDs.length - 1]; 1057 var c = ".StepID" + customId + "_" + nextStepID; 1058 if ($element.val() == "") { 1059 $(c).prop("disabled", true); 1060 $(c).val(""); 1061 $(c).trigger("keyup"); 1062 } 1063 else { 1064 $(c).prop("disabled", false); 1065 if ($(c).hasClass('iti__tel-input')) { 1066 var iti = intlTelInput.getInstance($(c)[0]); 1067 iti.setDisabled(false); 1068 } 1069 } 1070 } 1071 } 1072 }, 1073 1074 validateEmail: function ($element) { 1075 var val = $element.val().trim(); 1076 if (val.length > 0 && !this.emailRegex.test(val)) { 1077 return "Invalid email address."; 1078 } 1079 }, 1080 1081 setSelectionsOnLink: function (link, selections) { 1082 1083 if (selections == '') 1084 return; 1085 1086 var href = $(link).prop("href"); 1087 1088 //need to get selections from qty grid as well 1089 //needs to build a string to add multiple items to cart, one for each qty grid option that is specified, and the the options from the rest of the selections 1090 var qtyGrid = $(".VariantQuantityGrid" + this._customId); 1091 //if we have a qty grid, then for each that has qty, need to add that to the link 1092 //addtocart.aspx?itemid_1=blah&quantity_1=blah&variantid_1=1|2|3 need to get variant and qty of the individual qty grid column 1093 if (qtyGrid.length > 0) { 1094 //then we basically have to rebuild the link 1095 //get a list of all textboxes 1096 var $qtyTextboxes = qtyGrid.find(".VariantQuantityGridTextbox" + this._customId); 1097 1098 var qs = ""; 1099 1100 for (var i = 0; i < $qtyTextboxes.length; i++) { 1101 var iQty = parseInt($($qtyTextboxes[i]).find(".VariantQuantityBox").val()); 1102 var iVariantID = parseInt($($qtyTextboxes[i]).find("input[id$='hfVariantQuantityGridVariantID" + this._customId + "']").val()); 1103 1104 if (iQty > 0) { 1105 1106 var sVariants = iVariantID;
1107 if (selections.length > 0) 1108 sVariants += "|" + selections; 1109 1110 if (qs.length > 0) 1111 qs += "&"; 1112 qs += "itemID_" + i + "=" + this._itemId + "&quantity_" + i + "=" + iQty + "&variantID_" + i + "=" + sVariants; 1113 } 1114 } 1115 1116 href = "/store/AddToCart.aspx?" + qs; 1117 } 1118 else { 1119 href += "&variantID=" + selections; 1120 } 1121 1122 $(link).prop("href", href); 1123 }, 1124 1125 setPersonalizationsOnLink: function (link, selections) { 1126 1127 if (selections == '') 1128 return; 1129 1130 var href = $(link).prop("href"); 1131 href += "&personalization=" + selections; 1132 href += "&personalizationids=" + $("#" + this._personalizationIdsId).val(); 1133 1134 $(link).prop("href", href); 1135 }, 1136 1137 uploadPersonalizationFiles: function () { 1138 1139 var self = this; 1140 $(".PersonalizationFileUpload" + this._customId).each(function (index, element) { 1141 if ($(element).val() != '') { 1142 1143 var fileData = $(element).prop("files")[0]; 1144 var formData = new window.FormData(); 1145 formData.append("file", fileData); 1146 1147 var temp = $.ajax({ 1148 type: "POST", 1149 url: "/Store/UploadFile.ashx", 1150 data: formData, 1151 dataType: "text", 1152 cache: false, 1153 contentType: false, 1154 processData: false, 1155 async: false 1156 }).responseText; 1157 1158 if (temp) { 1159 result = JSON.parse(temp); 1160 1161 if (result) { 1162 1163 if (result.indexOf("Error") != -1) { 1164 alert(result); 1165 return false; 1166 } 1167 else { 1168 $(element).prop('data-url', result); 1169 return true; 1170 } 1171 1172 } 1173 else { 1174 alert("Failed to connect to server to upload file."); 1175 return false; 1176 } 1177 } 1178 else { 1179 alert("Failed to connect to server to upload file."); 1180 return false; 1181 } 1182 } 1183 }); 1184 1185 return true; 1186 }, 1187 1188 saveSelections: function (selections) { 1189 $("#" + this._selectedVariantsId).val(selections); 1190 }, 1191 1192 savePersonalizations: function (selections) { 1193 $("#" + this._personalizationStringsId).val(selections); 1194 }, 1195 1196 checkSelections: function (bForceValidQty, bLinkClicked, callerButtonId) { 1197 var selected = true; 1198 var self = this; 1199 //this part is also required some domain and data setup knowledge 1200 var result = { 1201 success: true, 1202 message: "" 1203 }; 1204 1205 //need to have ability to only check for ones that have a quantity 1206 var qtyGrid = $(".VariantQuantityGrid" + this._customId); 1207 1208 if (bForceValidQty && this.qtyIsEmpty() && qtyGrid.length == 0) { 1209 return result; 1210 } 1211 else if (qtyGrid.length > 0 && bLinkClicked) { 1212 //verify we have a valid quantity in the grid before we try to add 1213 //but only when adding via the link, b/c the button will just ignore if 0 qtys 1214 var $qtyTextboxes = qtyGrid.find(".VariantQuantityGridTextbox" + this._customId); 1215 var qtyGridHasQty = false; 1216 for (var i = 0; i < $qtyTextboxes.length; i++) { 1217 var iQty = parseInt($($qtyTextboxes[i]).find(".VariantQuantityBox").val()); 1218 1219 if (iQty > 0) { 1220 1221 qtyGridHasQty = true; 1222 } 1223 } 1224 selected = qtyGridHasQty; 1225 if (!selected) { 1226 result.message = "A quantity wasn't entered"; 1227 }; 1228 } 1229 1230 var sStoreTextVariantMessage = $("input[id$='hfAlertMsg_Variant']").val(); 1231 if (sStoreTextVariantMessage == undefined || sStoreTextVariantMessage.length <= 0) { 1232 sStoreTextVariantMessage = "Please select the product options for this item in the lists below, there is at least 1 selection missing.\n\n"; 1233 } 1234 1235 //both types of drop down can be handled here in one selector 1236 $(".variantDropDown" + this._customId + ", .variantDropDown-Combined" + this._customId).each(function (index, element) { 1237 var $dd = $(element); 1238 var isNonInventory = $dd.attr('id').indexOf('NonInventoryVariantGroup') != -1; 1239 var ddSelectedVal = ''; 1240 1241 var isValidationRequired = true; 1242 if (callerButtonId.indexOf('btnUpdateQuantities') > 0) { 1243 if ($dd.attr('id').indexOf('_rpCart_') > 0) { 1244 isValidationRequired = true; 1245 } 1246 else { 1247 isValidationRequired = false; 1248 } 1249 } 1250 1251 if (self._isDDLSwatchCombined) { 1252 var combinedDllObj = self.locateCombinedDDLObject($dd.attr('id')); 1253 if (combinedDllObj) {
1254 ddSelectedVal = combinedDllObj.getSelectedValue(); 1255 } 1256 } else { 1257 ddSelectedVal = $dd.val(); 1258 } 1259 1260 if (ddSelectedVal === "-999" && !isNonInventory && isValidationRequired) { 1261 $dd.addClass("needsSelection"); 1262 selected = false; 1263 1264 if (result.message.length <= 0) { 1265 result.message = sStoreTextVariantMessage.replace("##VARIANTGROUP##", element.getAttribute("groupname")).replace("##NUMBEROFSELECTION## ", ""); 1266 } 1267 } else { 1268 $dd.removeClass("needsSelection"); 1269 } 1270 }); 1271 1272 1273 $(".variantRadioButtonList" + this._customId).each(function (index, element) { 1274 var $radiolist = $(element); 1275 var $rb = element.querySelectorAll("input:checked"); 1276 var isNonInventory = $rb[0].id.indexOf('NonInventoryVariantGroup') != -1; 1277 if (($rb.length <= 0 || ($rb.length > 0 && ($rb[0].value === "-999" && !isNonInventory)))) { 1278 $radiolist.addClass("needsSelection"); 1279 selected = false; 1280 1281 if (result.message.length <= 0) { 1282 result.message = sStoreTextVariantMessage.replace("##VARIANTGROUP##", element.getAttribute("groupname")).replace("##NUMBEROFSELECTION## ", ""); 1283 } 1284 } else { 1285 $radiolist.removeClass("needsSelection"); 1286 } 1287 }); 1288 1289 $(".variantCheckBox" + this._customId).each(function (index, element) { 1290 var $chklist = $(element); 1291 var minSelection = parseInt(element.getAttribute("minselection")); 1292 var maxSelection = parseInt(element.getAttribute("maxselection")); 1293 var selectedTotal = element.querySelectorAll("input:checked").length; 1294 if ((minSelection > 0 && selectedTotal < minSelection) || (maxSelection > 0 && selectedTotal > maxSelection)) { 1295 $chklist.addClass("needsSelection"); 1296 selected = false; 1297 1298 if (result.message.length <= 0) { 1299 if (minSelection != maxSelection && maxSelection > 0) { 1300 result.message = sStoreTextVariantMessage.replace("##VARIANTGROUP##", element.getAttribute("groupname")).replace("##NUMBEROFSELECTION##", minSelection.toString() + "-" + maxSelection.toString()); 1301 } 1302 else { 1303 result.message = sStoreTextVariantMessage.replace("##VARIANTGROUP##", element.getAttribute("groupname")).replace("##NUMBEROFSELECTION##", minSelection.toString()); 1304 } 1305 } 1306 } else { 1307 $chklist.removeClass("needsSelection"); 1308 } 1309 }); 1310 1311 var personalizeMessage = $("input[id$='hfAlertMsg_Personalize']").val(); 1312 var hasPersonalizeError = false; 1313 1314 if (callerButtonId.indexOf('btnUpdateQuantities') <= 0) { //Personalization validation is not required if quantities are updated from Small Cart 1315 $(".personalizationTextbox" + this._customId + ".ProductPersonalizationRequired").each(function (index, element) { 1316 if ($(element).val() == '') { 1317 $(element).addClass("needsSelection"); 1318 selected = false; 1319 hasPersonalizeError = true; 1320 if (personalizeMessage.length <= 0) { 1321 personalizeMessage = "Please enter a personalization value for the required fields."; 1322 } 1323 } else { 1324 $(element).removeClass("needsSelection"); 1325 } 1326 }); 1327 1328 $(".personalizationTextboxWithConfirm" + this._customId + ".ProductPersonalizationRequired").each(function (index, element) { 1329 if ($(element).val() == '') { 1330 $(element).addClass("needsSelection"); 1331 selected = false; 1332 hasPersonalizeError = true; 1333 if (personalizeMessage.length <= 0) { 1334 personalizeMessage = "Please enter a personalization value for the required fields."; 1335 } 1336 } else { 1337 $(element).removeClass("needsSelection"); 1338 } 1339 }); 1340 1341 $(".PersonalizationEmailAddress" + this._customId).each(function (index, element) { 1342 var result = self.validateEmail($(element)); 1343 if (result && result.length > 0) { 1344 hasPersonalizeError = true; 1345 $(element).addClass("needsSelection"); 1346 selected = false; 1347 1348 if (personalizeMessage.length <= 0) { 1349 personalizeMessage = personalizeMessage + "\n\n" + result; 1350 } 1351 else { 1352 personalizeMessage += "\n\n" + result; 1353 } 1354 } else { 1355 $(element).removeClass("needsSelection"); 1356 } 1357 }); 1358 1359 $(".PersonalizationEmailAddress" + this._customId + ".ProductPersonalizationRequired").each(function (index, element) { 1360 if ($(element).val() == '') { 1361 $(element).addClass("needsSelection"); 1362 selected = false; 1363 hasPersonalizeError = true; 1364 if (personalizeMessage.length <= 0) { 1365 personalizeMessage = "Please enter a personalization value for the required fields."; 1366 } 1367 } else { 1368 $(element).removeClass("needsSelection"); 1369 } 1370 }); 1371 1372 $(".PersonalizationPhoneNumber" + this._customId + ".ProductPersonalizationRequired").each(function (index, element) { 1373 if ($(element).val() == '') { 1374 $(element).addClass("needsSelection"); 1375 selected = false; 1376 hasPersonalizeError = true; 1377 if (personalizeMessage.length <= 0) { 1378 personalizeMessage = "Please enter a personalization value for the required fields."; 1379 } 1380 } else { 1381 $(element).removeClass("needsSelection"); 1382 } 1383 }); 1384 1385 $(".PersonalizationDatePicker" + this._customId + ".ProductPersonalizationRequired").each(function (index, element) { 1386 if ($(element).val() == '') { 1387 $(element).addClass("needsSelection"); 1388 selected = false; 1389 hasPersonalizeError = true; 1390 if (personalizeMessage.length <= 0) { 1391 personalizeMessage = "Please enter a personalization value for the required fields."; 1392 } 1393 } else { 1394 $(element).removeClass("needsSelection"); 1395 } 1396 }); 1397 1398 $(".PersonalizationDropDown" + this._customId + ".ProductPersonalizationRequired").each(function (index, element) { 1399 if ($(element).val() == '') { 1400 $(element).addClass("needsSelection"); 1401 selected = false; 1402 hasPersonalizeError = true; 1403 if (personalizeMessage.length <= 0) { 1404 personalizeMessage = "Please enter a personalization value for the required fields."; 1405 } 1406 } else { 1407 $(element).removeClass("needsSelection"); 1408 } 1409 }); 1410 1411 $(".PersonalizationFileUpload" + this._customId + ".ProductPersonalizationRequired").each(function (index, element) { 1412 if ($(element).val() == '') { 1413 selected = false; 1414 hasPersonalizeError = true; 1415 $(element).addClass("needsSelection"); 1416 if (personalizeMessage.length <= 0) { 1417 personalizeMessage = "Please enter a personalization value for the required fields."; 1418 } 1419 } 1420 else { 1421 $(element).removeClass("needsSelection"); 1422 } 1423 }); 1424 1425 var customId = this._customId; 1426 1427 $(".personalizationTextboxWithConfirm" + this._customId).each(function (index, element) { 1428 var value = $(element).val(); 1429 var $confirmBox = $("[id$='" + $(element).attr("data-confirmid") + "']"); 1430 if (value != '' && $confirmBox.length > 0) { 1431 var confirmValue = $($confirmBox).val(); 1432 if (confirmValue != value) { 1433 selected = false; 1434 hasPersonalizeError = true; 1435 personalizeMessage = personalizeMessage + "\n\nThe personalization values entered do n
1435ot match. Please enter matching values."; 1436 $confirmBox.addClass("needsSelection"); 1437 } 1438 else { 1439 $confirmBox.removeClass("needsSelection"); 1440 } 1441 } 1442 }); 1443 } 1444 1445 if (!selected) { 1446 result.success = false; 1447 if (hasPersonalizeError) 1448 result.message = result.message + "\n\n" + personalizeMessage; 1449 } 1450 1451 return result; 1452 }, 1453 1454 getSelections: function (bForceValidQty) { 1455 var options = []; 1456 1457 //need to have ability to only check for ones that have a quantity 1458 if (bForceValidQty && this.qtyIsEmpty()) { 1459 return options; 1460 } 1461 // dropdowns 1462 if (this._isDDLSwatchCombined) { 1463 $(".variantDropDown-Combined" + this._customId).children("[id$='_ddlCombined']").each(function () { 1464 options.push($(this).val()); 1465 }); 1466 } else { 1467 $(".variantDropDown" + this._customId).each(function () { 1468 options.push($(this).val()); 1469 }); 1470 } 1471 1472 //variant repeater 1473 $(".variant-repeater__variant.selected").each(function () { 1474 options.push($(this).data('value')); 1475 }); 1476 1477 1478 // radio buttons 1479 $(".variantRadioButtonList" + this._customId + " input:radio:checked").each(function () { 1480 options.push($(this).val()); 1481 }); 1482 1483 // checkboxes 1484 $(".variantCheckBox" + this._customId + " input:checkbox:checked").each(function () { 1485 options.push($(this).parent().prop("id")); 1486 }); 1487 1488 return options.filter(option => option != null); 1489 }, 1490 1491 getPersonalizations: function () { 1492 1493 var options = []; 1494 1495 //order is important here, must get them in the same order they are on the page 1496 $(".personalization" + this._customId).each(function () { 1497 if (typeof $(this).prop('data-url') != 'undefined' && $(this).prop('data-url') != '') { 1498 options.push($(this).prop('data-url')); 1499 } 1500 else if ($(this).hasClass('iti__tel-input')) { 1501 var iti = intlTelInput.getInstance($(this)[0]); 1502 options.push(iti.getNumber(intlTelInput.utils.numberFormat.INTERNATIONAL)); 1503 } 1504 else { 1505 options.push($(this).val().replace(/\|/g, '%7C')); 1506 } 1507 }); 1508 return options; 1509 }, 1510 1511 qtyIsEmpty: function () { 1512 1513 if (this._bindQtyToParent) { 1514 if (this._bindQtyCheckBoxId.length > 0 && $("#" + this._bindQtyCheckBoxId + ":checked").length > 0) { 1515 return false; 1516 } 1517 else 1518 return true; 1519 } 1520 1521 var quantity = $("#" + this._qtyTextboxId).val(); 1522 1523 if (!quantity) { 1524 var combinedQty = 0; 1525 1526 if (this._qtyDiscountsAcrossVariants) { 1527 $(".VariantQuantityGridTextbox" + this._customId + " input").each(function () { 1528 var qty = parseInt($(this).val()); 1529 if (!isNaN(qty)) { 1530 combinedQty = combinedQty + qty; 1531 } 1532 }); 1533 } 1534 1535 quantity = combinedQty; 1536 } 1537 1538 if (quantity <= 0) { 1539 if (!this._useQtyOf1IfNoQty) 1540 return true; 1541 } 1542 1543 return false; 1544 1545 }, 1546 1547 getQuantity: function () { 1548 var quantity = $("#" + this._qtyTextboxId).val(); 1549 1550 if (!quantity) { 1551 var combinedQty = 0; 1552 1553 if (this._qtyDiscountsAcrossVariants) { 1554 $(".VariantQuantityGridTextbox" + this._customId + " input").each(function () { 1555 var qty = parseInt($(this).val()); 1556 if (!isNaN(qty)) { 1557 combinedQty = combinedQty + qty; 1558 } 1559 }); 1560 } 1561 1562 if ($("#hfQtyDiscountAcrossVariants").val() === "True") { 1563 $(".ProductDetailsVariantMatrixQuantityBox input").each(function () { 1564 var qty = parseInt($(this).val()); 1565 if (!isNaN(qty)) { 1566 combinedQty = combinedQty + qty; 1567 } 1568 }); 1569 } 1570 1571 quantity = combinedQty; 1572 } 1573 1574 if (quantity <= 0) { 1575 quantity = 1; 1576 } 1577 1578 return quantity; 1579 }, 1580 1581 htmlEscape: function (str) { 1582 return String(str) 1583 .replace(/&/g, '&') 1584 .replace(/"/g, '"') 1585 .replace(/'/g, ''') 1586 .replace(/</g, '<') 1587 .replace(/>/g, '>'); 1588 }, 1589 1590 getUpdatedImgUrl: function (url, newPath, productPhotoHandling, externalImageOverrideUrl) { 1591 if (productPhotoHandling == 'ExternalImaging') { 1592 var oldMainImageOptions = window.resizehelper.getExternalImageOptionsFromUrl(externalImageOverrideUrl, url); 1593 return window.resizehelper.getExternalImageUrl(externalImageOverrideUrl, newPath, oldMainImageOptions.width, oldMainImageOptions.height); 1594 } 1595 var oldUrl = url.split('?') 1596 var newUrl = newPath; 1597 if (newPath.startsWith("/") && oldUrl.length > 1) { 1598 newUrl = "/resize" + newPath; 1599 } 1600 if (oldUrl.length > 1) 1601 newUrl = newUrl + "?" + oldUrl[1]; 1602 return newUrl; 1603 }, 1604 1605 updatePrice: function () { 1606 var itemID = this._itemId; 1607 var quantity = this.getQuantity();
1608 1609 var options = this.getSelections(); 1610 this.saveSelections(options.join("|")); 1611 var sOptions = options.join(", "); 1612 1613 if (this._pkgVariants && this._pkgVariants.length > 0) { 1614 if (sOptions.length > 0) 1615 sOptions += ", "; 1616 sOptions += this._pkgVariants; 1617 } 1618 var personalizations = this.getPersonalizations(); 1619 this.savePersonalizations(personalizations.join("|")); 1620 var sPersonalizations = ''; 1621 $(personalizations).each(function (index, element) { 1622 if (sPersonalizations != '') 1623 sPersonalizations += ","; 1624 sPersonalizations += JSON.stringify(element); 1625 }); 1626 1627 var personalizationIds = $("#" + this._personalizationIdsId).val(); 1628 if (typeof personalizationIds != 'undefined' && personalizationIds.length > 0) 1629 personalizationIds = personalizationIds.replace(/\|/g, ', '); 1630 else 1631 personalizationIds = ''; 1632 1633 1634 var subscriptionId = "0"; 1635 if (this._subscriptionId != '') { 1636 subscriptionId = $("#" + this._subscriptionId).val(); 1637 let selectedOption = $("#" + this._subscriptionId + ' option:selected').text(); 1638 if (typeof subscriptionId == 'undefined' || selectedOption == "NoRenewal") 1639 subscriptionId = "0"; 1640 } 1641 1642 var params = '{"itemID": ' + itemID + ', "quantity": ' + quantity + ', "variantIDs": [' + sOptions + '], "personalizationIds": [' + personalizationIds + '], "personalizationStrings": [' + sPersonalizations + '], "subscription": ' + subscriptionId + '}'; 1643 1644 var self = this; 1645 1646 this.ajaxCall("GetPriceWithOptions", params, function (result) { 1647 1648 var resultPreSalePrice = Number(result.d.preSalePrice.replace(/[^0-9\.-]+/g, "")); 1649 var resultPrice = Number(result.d.price.replace(/[^0-9\.-]+/g, "")); 1650 1651 if (self._qtyDiscountPricesId) { 1652 $("#" + self._qtyDiscountPricesId).html(result.d.qtyBreakPrices); 1653 } 1654 else if (resultPreSalePrice > resultPrice && self._salePriceId && $('#' + self._salePriceId).length > 0) { 1655 1656 if (self._childPriceId) { 1657 $("#" + self._priceId).find("#" + self._childPriceId).html(''); 1658 $("#" + self._priceId).find("#" + self._childPriceId).hide(); 1659 $("#" + self._priceAreaId).hide(); 1660 } 1661 else if (self._priceId) { 1662 $("#" + self._priceId).html(''); 1663 $("#" + self._priceAreaId).hide(); 1664 } 1665 1666 if (self._wasPriceId && $('#' + self._wasPriceId).length > 0) { 1667 $('#' + self._wasPriceId).html(result.d.preSalePrice); 1668 $('#' + self._wasPriceAreaId).show(); 1669 } 1670 1671 if (self._salePriceId && $('#' + self._salePriceId).length > 0) { 1672 $('#' + self._salePriceId).html(result.d.price); 1673 $('#' + self._salePriceAreaId).show(); 1674 } 1675 } 1676 else { 1677 1678 if (self._wasPriceId && $('#' + self._wasPriceId).length > 0) { 1679 $('#' + self._wasPriceId).html(''); 1680 $('#' + self._wasPriceAreaId).hide(); 1681 } 1682 if (self._salePriceId && $('#' + self._salePriceId).length > 0) { 1683 $('#' + self._salePriceId).html(''); 1684 $('#' + self._salePriceAreaId).hide(); 1685 } 1686 1687 if (self._priceAreaId) { 1688 $("#" + self._priceAreaId).show(); 1689 } 1690 1691 if (self._childPriceId) { 1692 $("#" + self._priceId).find("#" + self._childPriceId).html(result.d.price); 1693 } 1694 else if (self._priceAreaId) { 1695 $("#" + self._priceId).html(result.d.price); 1696 } 1697 } 1698 1699 1700 if (self._itemNrId) { 1701 $("#" + self._itemNrId).html(self.htmlEscape(result.d.itemNr)); 1702 } 1703 if (self._qtyDiscountsId) { 1704 $("#" + self._qtyDiscountsId).html(result.d.qtyPricing); 1705 } 1706 if (self._productStatusId) { 1707 $("#" + self._productStatusId).html(result.d.status); 1708 } 1709 if (self._productTimeFrameId) { 1710 $("#" + self._productTimeFrameId).html(result.d.timeFrame); 1711 } 1712 if (self._variantGTINId) { 1713 $("#" + self._variantGTINId).html(result.d.gtin); 1714 } 1715 if (self._variantAdditionalInfoId) { 1716 $("#" + self._variantAdditionalInfoId).html(result.d.additionalInfo); 1717 } 1718 if (self._qtyInStockId) { 1719 $("#" + self._qtyInStockId).html(result.d.inStockQty); 1720 } 1721 if (self._rewardPointsId) { 1722 $("#" + self._rewardPointsId).html(result.d.rewardPointsEarned);
1723 } 1724 if (self._rewardPointsToPurchaseId) { 1725 $("#" + self._rewardPointsToPurchaseId).html(result.d.rewardPointsToPurchase); 1726 } 1727 if (self._retailPriceId) { 1728 $('#' + self._retailPriceId).html(result.d.retailPrice); 1729 } 1730 if (self._priceDollarsId) { 1731 $('#' + self._priceDollarsId).html(result.d.priceDollars); 1732 } 1733 if (self._priceCentsId) { 1734 $('#' + self._priceCentsId).html(result.d.priceCents); 1735 } 1736 if (self._youSaveId) { 1737 $("#" + self._youSaveId).html(result.d.youSave); 1738 } 1739 if (self._weightId) { 1740 $("#" + self._weightId).html(result.d.weight); 1741 } 1742 if (self._availabilityId) { 1743 $("#" + self._availabilityId).html(result.d.availability); 1744 } 1745 if (self._lengthId) { 1746 $("#" + self._lengthId).html(result.d.itemLength); 1747 } 1748 if (self._widthId) { 1749 $("#" + self._widthId).html(result.d.itemWidth); 1750 } 1751 if (self._heightId) { 1752 $("#" + self._heightId).html(result.d.itemHeight); 1753 } 1754 1755 if (sOptions.length > 0) { 1756 var estimateLink = $("a.estimate-shipping"); 1757 if (estimateLink.length != 0) { 1758 var estimateUrl = estimateLink.prop("href").replace(/(\?|&)variantIds=[^&]*/, ""); 1759 estimateLink.prop("href", estimateUrl + ((estimateUrl.indexOf("?") >= 0) ? "&" : "?") + "variantIds=" + sOptions); 1760 } 1761 1762 var notifymelink = $("#lnkNotifyMe"); 1763 if (notifymelink != null && notifymelink.length > 0) { 1764 if (result.d.ShowNotifyMe == 'TRUE') { 1765 var notifyurl = notifymelink.attr("data-href").replace(/(\?|&)variantIds=[^&]*/, ""); 1766 if (notifyurl != "") 1767 notifymelink.attr("data-href", notifyurl + ((notifyurl.indexOf("?") >= 0) ? "&" : "?") + "variantIds=" + sOptions); //notifymelink.data("href", notifyurl + ((notifyurl.indexOf("?") >= 0) ? "&" : "?") + "variantIds=" + sOptions); //For Some reason, this was not working for foundation theme 1768 1769 notifymelink.show(); 1770 } 1771 else { 1772 notifymelink.hide(); 1773 } 1774 } 1775 1776 if (self._addToCartButtonId) { 1777 if (result.d.ShowAddToCart == 'TRUE') 1778 $("#" + self._addToCartButtonId).show(); 1779 else 1780 $("#" + self._addToCartButtonId).hide(); 1781 } 1782 if (self._addToQuoteButtonId) { //For the situation where add to Cart is not available, we shouldn't allow adding the item to quote as well. 1783 if (result.d.ShowAddToCart == 'TRUE') 1784 $("#" + self._addToQuoteButtonId).show(); 1785 else 1786 $("#" + self._addToQuoteButtonId).hide(); 1787 } 1788 if (result.d.variantInventoryImg != '') { 1789 var mainimg = document.getElementById(self._imageId); 1790 if (mainimg != null && mainimg.src != undefined && !mainimg.src.includes(result.d.variantInventoryImg)) { 1791 mainimg.src = self.getUpdatedImgUrl(mainimg.src, result.d.variantInventoryImg, self._productPhotoHandling, self._externalImageOverrideUrl); 1792 1793 var mainimgHref = document.getElementsByClassName("main-product-photo"); 1794 if (mainimgHref != null && mainimgHref[0].href != undefined) { 1795 mainimgHref[0].href = self.getUpdatedImgUrl(mainimgHref[0].href, result.d.variantInventoryImg, self._productPhotoHandling, self._zoomOverrideUrl); 1796 } 1797 var mainimgzoom = document.getElementsByClassName("zoomImg"); 1798 if (mainimgzoom != null && mainimgzoom.length > 0 && mainimgzoom[0].src != undefined) { 1799 mainimgzoom[0].src = self.getUpdatedImgUrl(mainimgzoom[0].src, result.d.variantInventoryImg, self._productPhotoHandling, self._zoomOverrideUrl); 1800 } 1801 } 1802 } 1803 else { 1804 if (self._useVariantInventory) { 1805 try { 1806 VariantSwatches.SelectVariant(self.selectedVariantGroup.toString(), self.selectedVariant.toString(), false, self._imageId, eval('VariantSwatches_' + self.selectedControlID)); 1807 } catch (e) { 1808 console.log('error selecting main photo image'); 1809 } 1810 } 1811 } 1812 1813 if (typeof affirm != 'undefined') { 1814 var affirmPromo = $(".affirm-as-low-as"); 1815 if (affirmPromo != null && affirmPromo.length > 0) { 1816 affirmPromo.attr('data-amount', Math.round(resultPrice * 100)); 1817 affirm.ui.refresh();
1818 } 1819 } 1820 if ($("div[data-pp-message]").length > 0) { 1821 $("div[data-pp-message]").attr('data-pp-amount', resultPrice); 1822 } 1823 } 1824 1825 if (localStorage.getItem('LatestCurrency')) { 1826 if (typeof triggerConvertPriceWithCurrencyCode === 'function') { 1827 triggerConvertPriceWithCurrencyCode(); 1828 } 1829 } 1830 }); 1831 }, 1832 1833 updateVariants: function ($element) { 1834 1835 var self = this; 1836 var options = []; 1837 var elementID = $element.get(0).id; 1838 1839 if (this.indexes[elementID] == null) { 1840 this.updatePrice(); 1841 return; 1842 } 1843 1844 var nextIndex = this.indexes[elementID] + 1; 1845 1846 var $sel = this.$varInvDDs.slice(0, nextIndex); 1847 1848 $sel.each(function () { 1849 if ($(this).is("select")) { 1850 options.push($(this).val()); 1851 1852 } else if (self._isDDLSwatchCombined && $(this).is("div.variants-combo-main-container")) { 1853 var combinedDll = self.locateCombinedDDLObject($(this).prop("id")); 1854 if (combinedDll) { 1855 options.push(combinedDll.getSelectedValue()); 1856 } 1857 } else { 1858 options.push($(this).find("input:checked").val()); 1859 } 1860 }); 1861 //debugger; 1862 //this is an input of type hidden - Generated in BuildLabel() method on server side in VariantGroupControlBuilder.cs class seems no issue for dropdown select 1863 var groupID = self.getGroupId(nextIndex); 1864 1865 if (typeof groupID === 'undefined') { 1866 this.updatePrice(); 1867 return; 1868 } 1869 var $next = $(this.$varInvDDs.get(nextIndex)); 1870 1871 if ($next.length == 0) { 1872 this.updatePrice(); 1873 return; 1874 } 1875 1876 1877 var currentElementVal = ""; 1878 var bFoundCombinedSelectElem = false; 1879 var ddlCombined = null; 1880 if (this._isDDLSwatchCombined && $element.is("div.variants-combo-main-container")) { 1881 //means its combined combo then first locate its object 1882 bFoundCombinedSelectElem = true; 1883 ddlCombined = this.locateCombinedDDLObject(elementID); 1884 if (ddlCombined) { 1885 currentElementVal = ddlCombined.getSelectedValue(); // gets its selected value 1886 } 1887 } else { 1888 currentElementVal = $element.val(); // otherwise take it as normal current element value 1889 } 1890 1891 //An elment can be a select or combined select or input type radio or input type checkbox 1892 if (currentElementVal === "-999" || (!$element.is("select") && !bFoundCombinedSelectElem && $element.find("input:checked").length == 0)) { 1893 this.setDefaults($element); 1894 this.updatePrice(); 1895 return; 1896 } 1897 1898 var qty = this.getQuantity(); 1899 1900 var itemID = this._itemId; 1901 1902 if (itemID == null || isNaN(itemID)) 1903 itemID = 0; 1904 1905 if ($next.is("select")) { 1906 $next.prop("disabled", false); 1907 } else if (this._isDDLSwatchCombined && $next.is("div.variants-combo-main-container")) { 1908 var ddlnext = this.locateCombinedDDLObject($next.prop("id")); 1909 if (ddlnext) { 1910 ddlnext.enableMe(); 1911 } 1912 } 1913 1914 var vids = options.join(', '); 1915 if (vids.length == 0) 1916 return; 1917 1918 var params = '{"variantIDs": [' + vids + '], "groupID": ' + groupID + ', "qty": ' + qty + ', "itemID":' + itemID + '}'; 1919 1920 this.ajaxCall("GetApplicableVariants", params, function (result) { 1921 var results = JSON.parse(result.d); 1922 var variants = results.variants; 1923 var variantStockStatuses = results.variantStockStatuses; 1924 var variantModifierTexts = results.variantModifierTexts; 1925 var variantNames = results.variantNames; 1926 1927 var $selected; 1928 var ddlNextCombo = null; 1929 1930 if ($next.is("select") && !self._isDDLSwatchCombined) { 1931 self.handleNonCombinedSelect($next, groupID, variants, false, variantStockStatuses, variantModifierTexts, variantNames); 1932 $selected = $next; 1933 } else if (self._isDDLSwatchCombined && $next.is("div.variants-combo-main-container")) { 1934 ddlNextCombo = self.handleCombinedSelect($next, groupID, variants, variantStockStatuses, variantModifierTexts, variantNames); 1935 $selected = $next; 1936 } else { 1937 $selected = $next.find("input:checked"); 1938 self.handleVariantControl($next, groupID, variants, variantStockStatuses); 1939 } 1940 1941 self.setDefaults($next); 1942 if (self._isDDLSwatchCombined && $selected.is("div.variants-combo-main-container")) { 1943 var selectedVal = ddlNextCombo.getSelectedValue(); 1944 if (selectedVal === "-999") { 1945 self.updatePrice(); 1946 } 1947 } 1948 else { 1949 var selectedVal = $selected.val(); 1950 1951 if (selectedVal !== "-999") { 1952 //upate next available variant if pre selected a value 1953 self.updateVariants($next) 1954 } 1955 else { 1956 self.updatePrice(true); 1957 } 1958 } 1959 });
1960 }, 1961 1962 getVariantsFromFitment: function (childIds) { 1963 var self = this; 1964 1965 this.ajaxCall("GetParentVariantsFromChildIds", '{ "childProducts": ' + JSON.stringify(childIds) + ', "quantity": ' + this.getQuantity() + ' }', function (result) { 1966 var variantOptions = JSON.parse(result.d); 1967 1968 self.$dd.each(function (index, selector) { 1969 var element = $(selector); 1970 var groupID = self.getGroupId(element); 1971 var options = variantOptions[groupID]; 1972 var ddlNextCombo; 1973 1974 if (options == null) 1975 self.toggleGroup(groupID, false); 1976 else { 1977 if (element.is("select") && !self._isDDLSwatchCombined) { 1978 self.handleNonCombinedSelect(element, groupID, options, true); 1979 } 1980 else if (self._isDDLSwatchCombined && element.is("div.variants-combo-main-container")) { 1981 ddlNextCombo = self.handleCombinedSelect(element, groupID, options); 1982 } 1983 else { 1984 self.handleVariantControl(element, groupID, options); 1985 } 1986 1987 self.setDefaults(element); 1988 1989 self.toggleGroup(groupID, true); 1990 } 1991 }); 1992 }); 1993 }, 1994 1995 setDefaults: function ($startElement) { 1996 var self = this; 1997 var selectedVal; 1998 1999 if (!this._isDDLSwatchCombined && $startElement.is("select")) { 2000 selectedVal = $startElement.val(); // regular ddl or select 2001 2002 } else if (this._isDDLSwatchCombined && $startElement.is("div.variants-combo-main-container")) { 2003 //means its combined combo then first locate its object 2004 var ddlCombined = this.locateCombinedDDLObject($startElement.get(0).id); 2005 if (ddlCombined) { 2006 selectedVal = ddlCombined.getSelectedValue(); // gets its selected value 2007 } 2008 } 2009 else { 2010 var $checked = $startElement.find("input:checked"); 2011 2012 if ($checked.length > 0) { 2013 selectedVal = $checked.val(); 2014 } 2015 else { 2016 selectedVal = "-999"; 2017 } 2018 } 2019 2020 if (selectedVal === "-999") { 2021 var $nextElements = this.$varInvDDs ? this.$varInvDDs.slice(this.indexes[$startElement.get(0).id] + 1) : this.$dd.slice(this.indexes[$startElement.get(0).id] + 1); 2022 $nextElements.each(function () { 2023 if (!self._isDDLSwatchCombined && $(this).is("select")) { 2024 $(this).val("-999").prop("disabled", "disabled"); 2025 var groupID = self.getGroupId($(this)); 2026 self.updateVariantCustomFields(groupID, -999); 2027 2028 } else if (self._isDDLSwatchCombined && $(this).is("div.variants-combo-main-container")) { 2029 var combinedddl = self.locateCombinedDDLObject($(this).prop("id")); 2030 if (combinedddl) { 2031 combinedddl.setSelectedValue("-999", true); 2032 combinedddl.disableMe(); //just like prop disabled 2033 } 2034 } 2035 else { 2036 $(this).find("input").each(function () { 2037 $(this).prop("checked", false); 2038 if (this.value === "-999") { 2039 $(this).prop("checked", "checked"); 2040 } 2041 else { 2042 $(this).prop("disabled", "disabled"); 2043 } 2044 var groupID = self.getGroupId($(this)); 2045 self.updateVariantCustomFields(groupID, this.value); 2046 }); 2047 } 2048 }); 2049 } 2050 }, 2051 2052 handleNonCombinedSelect: function (element, groupID, variants, dontDisplaySwatches = false, variantStockStatuses = null, variantModifierTexts = null, variantNames = null) { 2053 var previousVal = element.val(); 2054 var customID = this._customId; 2055 element.children("option[value!='-999']").each(function () { 2056 // ZB 1-28-2015: Disable swatches for variants that aren't compatible with the currently selected parent variant 2057 var variantId = $(this).prop('value'); 2058 var $swatches = $("img[id^='varswatch_" + groupID + "_" + variantId + "_']"); 2059 if (dontDisplaySwatches) 2060 $swatches.parent().hide(); 2061 else 2062 $swatches.addClass("SwatchNotApplicable"); 2063 $(this).remove(); 2064 }); 2065 2066 $.each(variants, function (key, value) { 2067 //add applied variants in sort order. the leading space is to stop json resort variants by key value 2068 var variantId = key.trim(); 2069 var $swatches = $("img[id^='varswatch_" + groupID + "_" + variantId + "']"); 2070 var button = $("div[id^='varbutton_" + groupID + "_" + variantId + "']"); 2071 var variantName = value; 2072 if (button.length > 0 && variantNames !== null && variantModifierTexts !== null) { 2073 button.html("<span class='desc-text'>" + variantNames[key] + "</span><span class='modifier-text'>" + variantModifierTexts[key] + "</span>"); 2074 variantName = variantNames[key]; 2075 } 2076 element.append($("<option>", { value: variantId, varname: variantName }).text(value)); 2077 if (dontDisplaySwatches) 2078 $swatches.parent().show(); 2079 else 2080 $swatches.removeClass("SwatchNotApplicable"); 2081 if (previousVal == variantId && variantStockStatuses !== null) 2082 if (variantStockStatuses[key] == "0") { 2083 previousVal = ""; 2084 let errorDv = $('.variant-custom-error[groupname=' + customID + '_' + element[0].getAttribute("groupname") + ']'); 2085 if (errorDv && errorDv.length > 0 && errorDv[0].hasAttribute('data-auto-select')) { 2086 errorDv.html('Profile option is unavailable.'); 2087 errorDv[0].setAttribute('data-error', 'status-unavailable'); 2088 } 2089 } 2090 });
2091 2092 //keep previous selection selected if it is still available 2093 element.children("option[value!='-999']").each(function () { 2094 if (previousVal == $(this).prop('value')) 2095 $(this).prop('selected', true); 2096 }); 2097 VariantButtons.UpdateButtons(groupID, element.val()); 2098 VariantButtons.HideButtons(groupID, variants); 2099 VariantSwatches.HideSwatches(groupID); 2100 }, 2101 handleCombinedSelect: function (element, groupID, variants, variantStockStatuses = null, variantModifierTexts = null, variantNames = null) { 2102 var ddlNextCombo = this.locateCombinedDDLObject(element.prop("id")); 2103 if (ddlNextCombo) { 2104 ddlNextCombo.reconfigureComboOptions(variants, variantStockStatuses, variantModifierTexts, variantNames); 2105 } 2106 return ddlNextCombo; 2107 }, 2108 handleVariantControl: function (element, groupID, variants) { 2109 var lookup = {}; 2110 2111 $.each(variants, function (key, value) { 2112 lookup[key.trim()] = value; 2113 }); 2114 2115 element.find("input").each(function () { 2116 if (this.value !== "-999" && !lookup[this.value]) { 2117 $(this).prop("checked", false); 2118 $(this).prop("disabled", "disabled"); 2119 } 2120 else { 2121 $(this).removeAttr("disabled"); 2122 var variantLabel = lookup[this.value]; 2123 if (variantLabel) { 2124 $("label[for='" + this.id + "']").text(variantLabel); 2125 } 2126 } 2127 }); 2128 }, 2129 2130 ///Get group id of the variant 2131 getGroupId: function (index) { 2132 if (index instanceof Element || index instanceof HTMLDocument) 2133 index = index.id; 2134 else if (index instanceof jQuery) 2135 index = index.attr("id"); 2136 2137 //20220311 AG If index is a string, its an element id 2138 if (typeof index === "string") { 2139 return index.split("_").pop(); 2140 } 2141 2142 return $("#variantGroupID" + this._customId + "_" + (index)).val(); 2143 }, 2144 2145 ///Toggle groupname, input, and swatches 2146 toggleGroup: function (groupID, toggle) { 2147 var variantControl = $("[id$='variantGroup" + this._customId + "_" + groupID + "']"); 2148 var checkBoxVariantControl = $("[id$='VariantGroup" + this._customId + "_" + groupID + "']"); 2149 2150 //toggle group name 2151 $("[id^='variantGroupID" + this._customId + "'][value='" + groupID + "']").parent().toggle(toggle); 2152 //toggle variant control 2153 variantControl.toggle(toggle); 2154 checkBoxVariantControl.toggle(toggle); 2155 //toggle swatches 2156 $("[id^='varswatch_" + groupID + "']").closest(".ProductDetailsSwatches").toggle(toggle); 2157 2158 if (toggle) 2159 variantControl.removeAttr('disabled'); 2160 } 2161}; 2162 2163//----------------------------- // Helpers Related To Combined DDL with Swatch, Mainly ship with --------//// 2164function isScrollable(element) { 2165 return element && element.clientHeight < element.scrollHeight; 2166} 2167 2168 2169// ensure given child element is within the parent's visible scroll area 2170function maintainScrollVisibility(activeElement, scrollParent) { 2171 const { offsetHeight, offsetTop } = activeElement; 2172 const { offsetHeight: parentOffsetHeight, scrollTop } = scrollParent; 2173 2174 const isAbove = offsetTop < scrollTop; 2175 const isBelow = offsetTop + offsetHeight > scrollTop + parentOffsetHeight; 2176 2177 if (isAbove) { 2178 scrollParent.scrollTo(0, offsetTop); 2179 } else if (isBelow) { 2180 scrollParent.scrollTo(0, offsetTop - parentOffsetHeight + offsetHeight); 2181 } 2182} 2183 2184VariantSwatches = { 2185 SetResizedImageLinks: function (img, zoom, swatchUrl, variantSwatch) { 2186 var newMainImageUrl = img.attr("src"); 2187 var newScaledUpImageUrl = ""; 2188 var zoomWidth = variantSwatch.ZoomWidth; 2189 var zoomHeight = variantSwatch.ZoomHeight; 2190 var ImagingMode = variantSwatch.ImagingMode; 2191 var ProductPhotoOverride = variantSwatch.ProductPhotoOverride; 2192 var ZoomPhotoOverride = variantSwatch.ZoomPhotoOverride; 2193 if (ImagingMode == "ExternalImaging") { 2194 var oldMainImageOptions = window.resizehelper.getExternalImageOptionsFromUrl(ProductPhotoOverride, img.attr("src")); 2195 newMainImageUrl = window.resizehelper.getExternalImageUrl(ProductPhotoOverride, swatchUrl, oldMainImageOptions.width, oldMainImageOptions.height); 2196 newScaledUpImageUrl = window.resizehelper.getExternalImageUrl(ZoomPhotoOverride, swatchUrl, zoomWidth, zoomHe
2196ight); 2197 } else { 2198 var baseResizerPath = window.resizehelper.getBaseResizerPath(swatchUrl); 2199 var oldParams = ""; 2200 if (baseResizerPath.indexOf('?') > -1) { 2201 oldParams = newMainImageUrl.substring(newMainImageUrl.indexOf('?') + 1); 2202 var poStartIndex = oldParams.indexOf("po="); 2203 if (poStartIndex < 0) 2204 poStartIndex = oldParams.indexOf("path="); 2205 if (poStartIndex > -1) { 2206 var ampAfterIndex = oldParams.substring(poStartIndex).indexOf("&"); 2207 if (ampAfterIndex > -1) 2208 oldParams = oldParams.substring(poStartIndex + ampAfterIndex + 1); 2209 } 2210 } 2211 newMainImageUrl = img.attr("src").replace(/\/resize\/.+(\?.*)/, baseResizerPath + oldParams); 2212 newScaledUpImageUrl = baseResizerPath + "bw=" + zoomWidth + "&w=" + zoomWidth + "&bh=" + zoomHeight + "&h=" + zoomHeight 2213 } 2214 img.attr("src", newMainImageUrl); 2215 img.siblings("img").attr("src", newScaledUpImageUrl); 2216 if (img.attr("id").indexOf("lvCategory") == -1) { 2217 zoom.attr("href", newScaledUpImageUrl); 2218 } 2219 }, 2220 2221 SelectVariant: function (groupID, variantID, setDropDown, imageId, variantSwatch) { 2222 var mainPhotoPresent = false; 2223 if (imageId !== "") { 2224 var $img = $("#" + imageId); 2225 if ($img.length > 0) 2226 mainPhotoPresent = true; 2227 } 2228 $(".varpicmax_img[id^='varswatch_" + groupID + "_" + "']").removeClass("ProductDetailsSelectedVariant"); 2229 var o = variantSwatch.SwatchArray[variantID]; 2230 if (o) { 2231 if (mainPhotoPresent) { 2232 $zoomlink = $img.parent(); 2233 if (o.SwatchURL != "") { 2234 if (variantSwatch.ImagingMode == "ExternalImaging") { 2235 this.SetResizedImageLinks($img, $zoomlink, o.SwatchURL, variantSwatch); 2236 } else { 2237 if ($img.attr("src").indexOf("path=") != -1) { 2238 if ($img.attr("src").indexOf("&") != -1) { 2239 $img.attr("src", $img.attr("src").replace(new RegExp("path=.+?&"), "path=" + o.SwatchURL + "&")).attr("alt", "").attr("title", ""); 2240 $img.siblings("img").attr("src", o.SwatchURL); 2241 if ($img.attr("id").indexOf("lvCategory") == -1) { 2242 $zoomlink 2243 .attr("href", $zoomlink.attr("href").replace(new RegExp("path=.+?&"), "path=" + o.SwatchURL + "&")); 2244 } 2245 } else { 2246 $img.attr("src", $img.attr("src").replace(new RegExp("path=.+"), "path=" + o.SwatchURL)).attr("alt", "").attr("title", ""); 2247 if ($img.attr("id").indexOf("lvCategory") == -1) { 2248 $zoomlink 2249 .attr("href", $zoomlink.attr("href").replace(new RegExp("path=.+"), "path=" + o.SwatchURL)); 2250 } 2251 } 2252 } else if ($img.attr("src").indexOf("/resize/") != -1) { 2253 this.SetResizedImageLinks($img, $zoomlink, o.SwatchURL, variantSwatch); 2254 } else { 2255 $img.attr("src", o.SwatchURL).attr("alt", "").attr("title", ""); 2256 $img.siblings("img").attr("src", o.SwatchURL); 2257 if ($img.attr("id").indexOf("lvCategory") == -1) { 2258 $zoomlink.attr("href", o.SwatchURL); 2259 } 2260 } 2261 } 2262 } else { 2263 var groupVars = []; 2264 var hasSwatch = false; 2265 $("#" + o.ControlPath).children().each(function () { 2266 var v = variantSwatch.SwatchArray[$(this).val()]; 2267 if (v && v.SwatchURL !== "") { 2268 hasSwatch = true; 2269 } 2270 }); 2271 if (typeof ResetImage == 'function' && hasSwatch) 2272 ResetImage(); 2273 } 2274 } else if (typeof ResetImage == 'function') 2275 ResetImage(); 2276 if (setDropDown) { 2277 //for radio options only 2278 var count = $("[id$='" + o.ControlPath + "']").find("tr").length; 2279 for (let i = 0; i < count; i++) { 2280 if ($("[id$='" + o.ControlPath + "_" + i + "']").val() == variantID) { 2281 $("[id$='" + o.ControlPath + "_" + i + "']").prop("checked", true); 2282 } 2283 else { 2284 $("[id$='" + o.ControlPath + "_" + i + "']").prop("checked", false); 2285 } 2286 } 2287 //end of radio options only 2288 $("[id$='" + o.ControlPath + "']").val(variantID).change(); 2289 } 2290 } 2291 $(".varpicmax_img[id^='varswatch_" + groupID + "_" + variantID + "_" + "']").addClass("ProductDetailsSelectedVariant"); 2292 }, 2293 2294 HideSwatches: function (groupID) { 2295 var swatches = $("[id^='varswatch_" + groupID + "']"); 2296 for (var i = 0; i < swatches.length; i++) { 2297 if (swatches[i].classList.contains("SwatchNotApplicable")) { 2298 swatches[i].style.display = "none"; 2299 } 2300 else { 2301 swatches[i].style.display = null; 2302 } 2303 } 2304 } 2305} 2306 2307VariantButtons = { 2308 SelectVariant: function (groupID, variantID, setDropDown, variantButtons, isCombined) { 2309 var o = variantButtons.ButtonArray[variantID]; 2310 VariantButtons.UpdateButtons(groupID, variantID); 2311 if (o) { 2312 if (setDropDown) { 2313 if (isCombined) { 2314 $("[id$='combo-option-Id-" + variantID + "']").click() 2315 } 2316 else 2317 $("[id$='" + o.ControlPath + "']").val(variantID).change(); 2318 } 2319 } 2320 }, 2321 2322 UpdateButtons: function (groupID, variantID) { 2323 var buttons = $('.var-button[groupID=' + groupID + ']'); 2324 for (var i = 0; i < buttons.length; i++) { 2325 if (buttons[i].getAttribute("variantID") !== variantID) 2326 buttons[i].classList.remove('var-selected'); 2327 else 2328 buttons[i].classList.add('var-selected'); 2329 } 2330 }, 2331 2332 HideButtons: function (groupID, variants) { 2333 var buttons = $('.var-button[groupID=' + groupID + ']'); 2334 for (var i = 0; i < buttons.length; i++) { 2335 var isVisible = variants[" " + buttons[i].getAttribute("variantID")]; 2336 if (!isVisible) { 2337 buttons[i].style.display = "none"; 2338 buttons[i].classList.add('var-unavailable'); 2339 } 2340 else { 2341 buttons[i].style.display = null; 2342 buttons[i].classList.remove('var-unavailable'); 2343 } 2344 } 2345 } 2346}
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.