1/* Minification failed. Returning unminified contents. 2(6534,16-17): run-time error JS1195: Expected expression: . 3(6534,21-22): run-time error JS1003: Expected ':': ) 4(6539,9-11): run-time error JS1010: Expected identifier: if 5(6539,13-14): run-time error JS1010: Expected identifier: ! 6(6539,13-14): run-time error JS1326: Expected binding syntax: ! 7(6539,13-14): run-time error JS1193: Expected ',' or ')': ! 8(6539,13-14): run-time error JS1006: Expected ')': ! 9(6539,13-14): run-time error JS1008: Expected '{': ! 10(6539,38): run-time error JS1004: Expected ';' 11(6539,38-39): run-time error JS1195: Expected expression: ) 12(6566,5-12): run-time error JS1009: Expected '}': console 13(6566,5-12): run-time error JS1006: Expected ')': console 14(6539,9,6564,6): run-time error JS1314: Implicit property name must be identifier: if (!dataObject.tealium_event) { 15 console.error("No tealium_event defined for the link call. Please define a tealium_event key-value pair."); 16 return; 17 } 18 19 //Force everything to be strings 20 var objString = Object.fromEntries( 21 Object.entries(dataObject).map(([key, value]) => { 22 if (typeof value === 'object' && value !== null) { 23 if (Array.isArray(value)) { 24 var newValue = []; 25 for (var i = 0; i < value.length; i++) { 26 newValue[i] = String(value[i]); 27 } 28 return [key, newValue]; 29 } 30 console.log('Tealium link() calls do not accept any objects outside of arrays and strings, ommitting object from data set.'); 31 return [key, '']; 32 } 33 return [key, String(value)]; 34 }) 35 ); 36 37 window.utag.link(objString); 38 return; 39 } 40 */ 41!function ($) { 42 43 $.validator.addMethod("postalCode", function (value, element) { 44 return this.optional(element) || /^[a-zA-Z][0-9][a-zA-Z] *[0-9][a-zA-Z][0-9]$/.test(value); 45 }, "Please enter a valid postal code."); 46 47 /** 48 * Default Validation Settings 49 */ 50 $.validator.setDefaults({ 51 invalidHandler: function (form, validator) { 52 var errors = validator.numberOfInvalids(); 53 if (errors) { 54 setTimeout(function () { 55 validator.errorList[0].element.focus(); 56 }, 100); 57 } 58 }, 59 errorPlacement: function (error, element) { 60 var $parent = element.parent(); 61 if ($parent.hasClass("style-radio")) { 62 error.prependTo($parent.parents(".form-list")); 63 } else if ($parent.hasClass("style-checkbox")) { 64 error.appendTo($parent.parent().siblings("label[class='label-jqv-error']")); 65 } else { 66 error.appendTo(element.parent()); 67 } 68 }, 69 highlight: function (element, errorClass, validClass) { 70 if (element.type === "radio") { 71 this.findByName(element.name).addClass(errorClass).removeClass(validClass); 72 } else { 73 $(element).addClass(errorClass).removeClass(validClass); 74 $(element.form).find("label[for=" + element.id + "]").addClass('label-' + errorClass); 75 if (($select = $(element).parent('.select-wrap')).length) { 76 $select.addClass(errorClass).removeClass(validClass) 77 } 78 } 79 }, 80 unhighlight: function (element, errorClass, validClass) { 81 if (element.type === "radio") { 82 this.findByName(element.name).removeClass(errorClass).addClass(validClass); 83 } else { 84 $(element).removeClass(errorClass).addClass(validClass); 85 $(element.form).find("label[for=" + element.id + "]").removeClass('label-' + errorClass); 86 if (($select = $(element).parent('.select-wrap')).length) { 87 $select.removeClass(errorClass).addClass(validClass) 88 } 89 } 90 }, 91 ignoreTitle: true, 92 onkeyup: false, 93 errorElement: "p", 94 errorClass: "jqv-error" 95 }); 96 97 98 $('#product-form').validate(); 99 100 // generic form validation 101 $('.validate-form').each(function (i, v) {
102 $(this).validate(); 103 }); 104 105 // ads instant credit form validation 106 $('.validate-ads-form').each(function (i, v) { 107 $(this).validate({ 108 groups: { 109 SSN: "SS1 SS2 SS3", 110 DateOfBirth: "DOBYear DOBMonth DOBDay", 111 PhoneNumber: "PhoneNum1 PhoneNum2 PhoneNum3", 112 AlternatePhoneNumber: "AltNum1 AltNum2 AltNum3" 113 }, 114 errorPlacement: function (error, element) { 115 if (element.attr("name") == "SS1" || element.attr("name") == "SS2" || element.attr("name") == "SS3") { 116 error.insertAfter("#SSN"); 117 } 118 else if (element.attr("name") == "PhoneNum1" || element.attr("name") == "PhoneNum2" || element.attr("name") == "PhoneNum3") { 119 error.insertAfter("#PhoneNumber"); 120 } 121 else if (element.attr("name") == "AltNum1" || element.attr("name") == "AltNum2" || element.attr("name") == "AltNum3") { 122 error.insertAfter("#AlternateNumber"); 123 } 124 else if (element.attr("name") == "DOBYear" || element.attr("name") == "DOBMonth" || element.attr("name") == "DOBDay") { 125 error.insertAfter("#DOB"); 126 } 127 else if (element.attr("name") == "UserAgreementAcceptance") { 128 //only turn the text red... dont display any extra messages 129 } 130 else { 131 error.insertAfter(element); 132 } 133 }, 134 focusInvalid: false, 135 invalidHandler: function(form, validator) { 136 if (!validator.numberOfInvalids()) 137 return; 138 139 $('html, body').animate({ 140 scrollTop: $(validator.errorList[0].element).offset().top 141 }, 1); 142 } 143 }) 144 }); 145 146 147 /** 148 * handling country changes - need to change validation requirements 149 * based on country selected. 150 * - set state as optional/required and hide/show 151 * - 152 */ 153 $(document).on('change.country', 'select.country-select', function (e) { 154 var $this = $(this), 155 $form = $this.parents('form'), 156 validator = $form.data('validator'), 157 $stateField = $this.parents('.form-list').find('select.state'), 158 $zipField = $this.parents('.form-list').find('input.zip'), 159 $phoneField = $this.parents('.form-list').find('input.phone'), 160 option = $this.val(); 161 162 if (option == "") { 163 return; 164 } 165 166 if (option == "US" || option == "CA") { 167 168 $stateField.addClass('required').parents('li').show(); 169 $zipField.addClass('required'); 170 $phoneField.removeClass('phoneNonUS').addClass('phoneUS'); 171 172 // Logic for state/province swap 173 var previousValue = $stateField.val(); 174 $stateField.find('option').eq(0).siblings().remove(); 175 176 if (option == "CA") 177 $zipField.removeClass('zipUS').addClass('zipCA'); 178 else if (option == "US") 179 $zipField.removeClass('zipCA').addClass('zipUS'); 180 181 return AjaxJsonPostWrapper.ajaxRouteNonAsync('Product', 'GetStateList', { country: option }, 182 function (result) { 183 $(result).each(function () { 184 $('<option/>', { 185 value: this.Value, 186 text: this.Text 187 }).appendTo($stateField); 188 }); 189 }, 190 null, 191 function () { 192 // Reset state field value 193 $stateField.find('option').each(function () { 194 if ($(this).val() === previousValue) { 195 $(this).prop('selected', true); 196 } 197 }) 198 $stateField.customSelect('updateText'); 199 } 200 ); 201 202 } else { 203 $stateField.empty(); 204 $stateField.removeClass('required').parents('li').hide(); 205 $zipField.removeClass('zipCA').removeClass('zipUS'); 206 $phoneField.removeClass('phoneUS').addClass('phoneNonUS'); 207 } 208 });
209 /** 210 * Update day select opts based on selected month 211 */ 212 $(document).on('change.month', 'select.month-select', function (e) { 213 var $this = $(this),//month select 214 $form = $this.parents('form'), //parent form 215 $day = $form.find('.day-select'), //date select 216 today = new Date(), //get todays date 217 month = parseInt($this.val()),//get month 218 year = $form.find('.year-select').val() == "" ? today.getFullYear() : parseInt($form.find('.year-select').val()),//get year, if no year is set use current year 219 daysInMonth = new Date(year, month, 0).getDate(), //get the last day of the month by setting the day to zero 220 lastDay = $day.children('option').length - 1; //get the current last day in the select 221 222 223 //remove days 224 for (var i = lastDay; i >= 0; i--) { 225 if (i > daysInMonth) { 226 $day.children('option').eq(i).remove(); 227 } 228 } 229 230 //add days 231 for (i = lastDay + 1; i <= daysInMonth; i++) { 232 $day.append('<option value="' + i + '">' + i + '</option>'); 233 } 234 235 $day.customSelect('updateText'); //update select display 236 237 }); 238 239 $(document).on('change.year', 'select.year-select', function (e) { 240 var $this = $(this);//year select 241 var $form = $this.parents('form'); //parent form 242 var $month = $form.find('.month-select'); 243 if ($month.val() != "") { 244 var $day = $form.find('.day-select'), //date select 245 month = parseInt($month.val()),//get month 246 year = $this.val() == "" ? today.getFullYear() : parseInt($this.val()),//get year, if no year is set use current year 247 daysInMonth = new Date(year, month, 0).getDate(), //get the last day of the month by setting the day to zero 248 lastDay = $day.children('option').length - 1; //get the current last day in the select 249 250 251 //remove days 252 for (var i = lastDay; i >= 0; i--) { 253 if (i > daysInMonth) { 254 $day.children('option').eq(i).remove(); 255 } 256 } 257 258 //add days 259 for (i = lastDay + 1; i <= daysInMonth; i++) { 260 $day.append('<option value="' + i + '">' + i + '</option>'); 261 } 262 263 $day.customSelect('updateText'); //update select display 264 } 265 }); 266 267}(window.jQuery);;;; 268/** 269 * Ajax add to cart functionality 270 * 271 * Usage using the data api add to the trigger element data-ajax="true" or $('myElement').AjaxCart(options); 272 * 273 * SEARCHING FOR THESE? #btnAddItemToCart .btn-cart 274 */ 275!function ($) { 276 var _root = this, 277 _namespace = 'AjaxCart'; 278 279 var AjaxCart = this.AjaxCart = function (element, options) { 280 this.$element = $(element); 281 this.$element.data(this.namespace, this); 282 this.options = $.extend({}, this.defaults, options); 283 this.prepare(); 284 }; 285 286 AjaxCart.prototype = { 287 namespace: _namespace, 288 289 defaults: { 290 miniCartContainer: '#cartSummary', 291 onBeforeSubmitCallback: null, 292 onSuccessCallback: null, 293 onFailureCallback: null 294 }, 295 296 prepare: function () { 297 var url = '', 298 data = null, 299 instance = this; 300 301 if (($form = this.$element.parents('form')).length) { 302 //check if form valdiation is initalized and validated 303 var options = $form.find(".product-options").length; 304 var ColorCode = $form.find("#ColorCode").val(); 305 var SizeCode = $form.find("#SizeCode").val(); 306 307 if ($form.data('validator')) { 308 if ($form.valid()) { 309 310 if (options > 0) { 311 if (ColorCode == 000) { 312 $form.data('validator').focusInvalid(); 313 return false; 314 } 315 if (SizeCode == 000) { 316 $form.data('validator').focusInvalid(); 317 return false; 318 } 319 } 320 321 if ($form.find("#hdnFreightZip").length && $form.find("#hdnFreightAmount").length) { 322 if (!this.validateFreightFields($form)) { 323 return false;
324 } 325 } 326 327 //todo validate the options are interacted with if there are any in ProductOptionsController.js 328 329 url = $form.prop('action'); 330 data = $form.serialize(); 331 this.setButtonState(false); 332 333 if ($form.find('#companion-products').length) { 334 var scope = angular.element($form.find('#companion-products')).scope(); 335 let companions = []; 336 scope.vm.forEach(function (product) { 337 if (product.addToCart) { 338 let companion = {}; 339 product.Quantity = $form.find("#quantity").val(); 340 if (!product.ColorCode) product.ColorCode = '000'; 341 if (!product.SizeCode) product.SizeCode = '000'; 342 companion.AdId = product.AdId; 343 companion.ID = product.ID; 344 companion.PromoCode = product.PromoCode; 345 companion.SizeCode = product.SizeCode; 346 companion.ColorCode = product.ColorCode; 347 companion.Quantity = parseInt(product.Quantity); 348 companions.push(companion); 349 } 350 }); 351 if (companions.length) data += '&Companions=' + JSON.stringify(companions); 352 } 353 354 this.submit(url, data); 355 356 if (typeof this.options.onBeforeSubmitCallback === 'function') { 357 this.options.onBeforeSubmitCallback(this); 358 } 359 } else { 360 $form.data('validator').focusInvalid(); 361 } 362 } 363 } 364 }, 365 366 //freight fields are required in cart post for truck items, but they are hidden 367 validateFreightFields: function($form) { 368 var zip = $form.find("#hdnFreightZip").val(); 369 var amount = $form.find("#hdnFreightAmount").val(); 370 var status = $form.find("#hdnFreightStatus").val(); 371 var validator = $form.validate(); 372 if (zip == null || zip === "" || amount == null || amount === "" || amount === 0) { 373 validator.showErrors({ 374 "freightZipInput": "You must have a freight rate set to purchase this item." 375 }); 376 $form.data('validator').focusInvalid(); 377 return false; 378 } 379 380 if (status !== "200") { 381 return false; 382 } 383 384 return true; 385 }, 386 387 setButtonState: function (state) { 388 state ? this.$element.prop('disabled', false).removeClass('disabled') : this.$element.prop('disabled', true).addClass('disabled') 389 }, 390 391 submit: function (url, data) { 392 var that = this; 393 394 Gorilla.util.messages.clearMessages(); 395 396 $.ajax({
397 type: 'POST', 398 url: url.toLowerCase(), 399 data: data, 400 dataType: 'json' 401 }) 402 .done(function (data) { 403 that.handleSuccess(data); 404 }) 405 .fail(function (xhr, ajaxOptions, thrownError) { 406 that.handleFailure(thrownError); 407 }).always(function () { 408 that.setButtonState(true); 409 }) 410 }, 411 412 handleSuccess: function (response) { 413 if (response.success) { 414 if (response.message != null && response.message != '') { 415 Gorilla.util.messages.addMessages(response.messages, 'success'); 416 } 417 418 populateTealiumAjaxScript(response.tealium); 419 if (response.certona) { 420 var certonaDiv = $('#certonaAjax'); 421 if (typeof certonaDiv !== 'undefined') { 422 certonaDiv.empty(); 423 certonaDiv.append(response.certona); 424 } 425 } 426 427 if (window.location.href.indexOf('cart/viewcart')) { 428 var scope = angular.element(document.getElementById('ViewCartController')).scope(); 429 if (scope != undefined) scope.getCart(); 430 } 431 } else { 432 //set messages 433 if (response.messages) { 434 Gorilla.util.messages.addMessages(response.messages, 'error'); 435 } 436 } 437 438 if (typeof this.options.onSuccessCallback === 'function') { 439 this.options.onSuccessCallback(this, response); 440 } 441 442 var scope = angular.element(document.getElementById('CartWishListHomepageController')).scope(); 443 if (scope != undefined) scope.addedToCart(); 444 }, 445 446 handleFailure: function (thrownError) { 447 alert('An error occurred while processing your request. Please try again shortly.'); 448 449 if (typeof this.options.onFailureCallback === 'function') { 450 this.options.onFailureCallback(this, thrownError); 451 } 452 }, 453 454 /** 455 * Resets the plugin state back to init state 456 */ 457 reset: function () { 458 459 }, 460 461 /** 462 * Unsets all events and settings back to init state 463 */ 464 unset: function () { 465 $(document).off('click.ajaxCart'); 466 } 467 468 469 }; 470 471 $.fn[_namespace] = function (options) { 472 var args = arguments; 473 if (options === undefined) { 474 options = {}; 475 } 476 477 if (typeof options === "object") { 478 return this.each(function () { 479 new AjaxCart(this, options); 480 }); 481 } else { 482 if (typeof options === 'string' && AjaxCart.prototype[options]) { 483 var obj = $(this).data(_namespace); 484 obj[options].apply(obj, Array.prototype.slice.call(args, 1)); 485 } else { 486 console.error('Method ' + options + ' does not exist in ' + _namespace); 487 } 488 } 489 }; 490 491 $(document).on('click.ajaxCart', '[data-ajax="true"]', function (e) { 492 e.preventDefault(); 493 $(this).AjaxCart(); 494 }); 495 496 497 /** 498 * Ajax AddCart - Handles successful responses 499 * @param obj 500 * @param response 501 */ 502 AjaxCart.prototype.defaults.onSuccessCallback = function (obj, response) { 503 if (response.cartMax == true) 504 $("#cart-limit-modal-trigger").moby({ 505 'modalClass': 'cart-limit-modal gradient-gray', 506 'ariaLabelText': 'Full Cart', 507 'onCompleteCallback': function () { 508 $(".moby-close").on('click', function (event) { 509 event.preventDefault(); 510 $("#cart-limit-modal-trigger").moby('hide'); 511 }); 512 } 513 }).moby('show', '#cart-limit-modal'); 514 else { 515 516 if (response.miniCartHtml && response.miniCartHtml !== "") { 517 //update mini cart html
518 var prevItemCount = $("#cart-mmenu .products-grid li").length; 519 setCartQuantityText(); 520 var showCart = response.freeGiftHtml == "" && 521 response.personalizeHtml == ""; 522 523 if (Gorilla.util.getCookie("ab-cart") === "Experiment" && showCart) { 524 //this is bad practice, but a necessary evil until we are fully angular on the rest of the site 525 var scope = angular.element(document.getElementById('ItemAddedDialogController')).scope(); 526 scope.showDialog(); 527 } else { 528 updateShowMiniCart(response.miniCartHtml, true); 529 //$(obj.options.miniCartContainer).html(response.miniCartHtml); 530 if ($("#cart-mmenu .products-grid li").length > prevItemCount) 531 popFadeProduct("cart-mmenu"); 532 } 533 } 534 535 } 536 537 //determine if we are in a modal and close it, dont close if there are errors 538 if (response.success) { 539 if (obj.$element && ($moby = obj.$element.parents('.moby-container')).length) { 540 $moby.find('.moby-close').trigger('click').off('click'); //close the actual window that triggered this....normal path 541 } 542 } 543 else { 544 Gorilla.util.messages.addMessages(response.messages, 'error'); 545 } 546 547 //this has to go after the modal close above otherwise the page data is changed and the modal will not close. 548 if (response.cartHtml) { 549 $('#cartContainer').html(response.cartHtml); 550 $('#cartContainer').find($("img.lazy")).lazy(); 551 } 552 } 553 554 555}(jQuery); 556 557 558function populateTealiumAjaxScript(script) { 559 var div = $('#tealiumAjax'); 560 if (typeof div !== 'undefined') { 561 div.empty(); 562 div.append(script); 563 } 564} 565 566function addItemToCartFamilyGroup(itemId, promoCode, color, size, qty, fgItem, fgPromo, fgOfferID, fromTable) { 567 var cartItem = { ID: itemId, PromoCode: promoCode, ColorCode: color, SizeCode: size, Quantity: qty, FreeGiftItemId: fgItem, FreeGiftPromoCode: fgPromo, FreeGiftOfferID: fgOfferID, FromTable: fromTable }; 568 return AjaxJsonPostWrapper.ajaxRoute('cart', 'addtocart', { data: cartItem }, function (result) { 569 if (result.cartMax == true) { 570 $("#cart-limit-modal-trigger").moby({ 571 'modalClass': 'cart-limit-modal gradient-gray', 572 'ariaLabelText': 'Full Cart', 573 'onCompleteCallback': function () { 574 $(".moby-close").on('click', function (event) { 575 event.preventDefault(); 576 $("#cart-limit-modal-trigger").moby('hide'); 577 }); 578 } 579 }).moby('show', '#cart-limit-modal'); 580 } 581 else { 582 updateShowMiniCart(result.miniCartHtml, true); 583 populateTealiumAjaxScript(result.tealium); 584 if (result.freeGiftHtml) { 585 if (($giftTrigger = $('#freegift-trigger')).length && ($giftModal = $('#freegift-modal')).length) { 586 //init the modal and set the Html from the response, since Moby requires an anchor we're triggering a click on the hidden anchor 587 $giftModal.html(result.freeGiftHtml); 588 $giftTrigger.moby({ 589 'modalClass': 'free-gift', 590 'ariaLabelText': 'Free Gift', 591 'bodyClose': false, 592 'keyActions': false, 593 'onCompleteCallback': function () { 594 Gorilla.util.initForms(); 595 $(".moby-close").hide(); 596 $('#free-gift').validate(); 597 } 598 }).moby('show', '#freegift-modal'); 599 } 600 } 601 } 602 603 }); 604} 605; 606var AjaxJsonPostWrapper = (function () { 607 608 var my = {}; 609 610 my.async = true; 611 612 my.getBaseUrl = function () { 613 var pathArray = window.location.pathname.split('/'); 614 return window.location.protocol + "//" + window.location.host; 615 }; 616 617 my.getUrl = function (controller, action) { 618 return my.getBaseUrl() + '/' + controller + '/' + action; 619 }; 620 621 my.getFormData = function (form) { 622 // there is an improved version of this function in the admin tool... 623 var data = $(form).serializeArray(); 624 var formData = {}; 625 for (var i = 0; i < data.length; i++) { 626 formData[data[i].name] = data[i].value; 627 } 628 return formData; 629 }; 630 631 my.ajaxUrl = function (url, data, success, error, complete, type) { 632 var ajaxType = 'POST'; 633 634 if (type != undefined) { 635 ajaxType = type; 636 } 637 return $.ajax({
638 type: ajaxType, 639 url: url.toLowerCase(), 640 async: my.async, 641 data: JSON.stringify(data), 642 contentType: 'application/json', 643 traditional: true, 644 beforeSend: function () { 645 }, 646 success: function (result) { 647 if (success != undefined) { 648 success(result); 649 } 650 }, 651 complete: function () { 652 if (complete != undefined) { 653 complete(); 654 } 655 }, 656 error: function (XMLHttpRequest, textStatus, errorThrown) { 657 var errId = XMLHttpRequest.getResponseHeader("System-Error-ID"); 658 var errIdMsg = ""; 659 if (errId != null) { 660 // var newUrl = AjaxJsonPostWrapper.getBaseUrl() + '/error/error?errId=' + errId; 661 // window.location.replace(newUrl); 662 errIdMsg = " [" + errId + "]" 663 } 664 console.log("An error occurred during ajax operation" + errIdMsg + ".") // mimics what has been "good enough" since redesign, circa 2014. we don't really know what to do but probably don't want to interrupt the user 665 666 if (error != undefined) { 667 error(errorThrown); 668 } 669 else 670 { 671 Gorilla.util.messages.addMessage('Sorry, there was an error with your request. Please try again shortly.', 'error'); 672 } 673 } 674 }) 675 .done(function (data) { 676 if (data.errors) { 677 onDataError(data); 678 } 679 }); 680 }; 681 682 my.ajaxRoute = function (controller, action, data, success, error, complete, type) { 683 my.async = true; 684 var url = my.getUrl(controller.toLowerCase(), action.toLowerCase()); 685 return my.ajaxUrl(url, data, success, error, complete, type); 686 }; 687 688 my.ajaxRouteNonAsync = function (controller, action, data, success, error, complete, type) { 689 my.async = false; 690 var url = my.getUrl(controller.toLowerCase(), action.toLowerCase()); 691 return my.ajaxUrl(url, data, success, error, complete, type); 692 }; 693 694 return my; 695}());; 696var moveToWishlistIndex = 0; 697 698!function ($) { 699 700 // Readied 701 $(function () { 702 //test for csscalc support 703 Modernizr.addTest('csscalc', function () { 704 var prop = 'width:'; 705 var value = 'calc(10px);'; 706 var el = document.createElement('div'); 707 708 el.style.cssText = prop + Modernizr._prefixes.join(value + prop); 709 710 return !!el.style.length; 711 }); 712 if (!Modernizr.csscalc) { 713 $("html").addClass("no-csscalc"); 714 } 715 716 //fix for keyboard open and position fixed elements with iOS 717 if (Modernizr.touch) { 718 var $body = $('body'); 719 720 $(document).on('focus', 'input:not(#searchMobile), textarea, select, md-select-menu', function () { 721 $body.addClass('ios-kb-fix'); 722 }).on('blur', 'input, textarea, select, md-select-menu', function () { 723 $body.removeClass('ios-kb-fix'); 724 }); 725 } 726 727 var fnSkipToContent = function () { 728 focusOnFirstEl($("#main[role='main']")); 729 } 730 731 $("#skipToContent > a").on("click", fnSkipToContent); 732 $("#skipToContent > a").on('keypress', function (e) { 733 if (e.which == 13) { fnSkipToContent(); } 734 }); 735 736 //init custom form elements 737 Gorilla.util.initForms(); 738 739 if (($modalTrigger = $('.trigger-modal')).length) { 740 $modalTrigger.moby({ 741 'modalClass': 'generic' 742 }); 743 } 744 745 initToolTips(); 746 747 //restrictions accordion in quickview 748 $(document).on("click", ".moby-container .restrictions-note legend", function () { 749 var restrictionsText = $(this).parent().find("#restrictions-text"); 750 751 if (restrictionsText.is(":visible")) { 752 $(this).find("#plus-minus").text("+"); 753 restrictionsText.fadeOut('fast'); 754 } else { 755 $(this).find("#plus-minus").text("-"); 756 restrictionsText.fadeIn('slow'); 757 } 758 }); 759 760 if (($lazyImg = $('.lazy')).length) { 761 $lazyImg.lazy(); 762 } 763 764 //Init default sliders, use data api to set items count and margins 765 if (($slider = $('.default-slider .products-grid')).length) { 766 if (!$slider.hasClass('slick-initialized')) { 767 $slider.slick({ 768 dots: false, 769 arrows: true, 770 slidesToShow: 4, 771 slidesToScroll: 4, 772 infinite: false, 773 lazyLoad: 'ondemand', 774 prevArrow: '<span class="sg-slick-prev" role="button" aria-label="Previous" tabindex="0"> ‹ </span>', 775 nextArrow: '<span class="sg-slick-next" role="button" aria-label="Next" tabindex="0"> › </span>', 776 responsive: [ 777 { 778 breakpoint: 1060, 779 settings: { 780 slidesToShow: 3, 781 slidesToScroll: 3, 782 arrows: true, 783 dots: true 784 } 785 }, 786 { 787 breakpoint: 768, 788 settings: { 789 slidesToShow: 2, 790 slidesToScroll: 2, 791 arrows: true, 792 dots: true 793 } 794 }, 795 { 796 breakpoint: 480, 797 settings: { 798 slidesToShow: 1, 799 slidesToScroll: 1, 800 arrows: true, 801 dots: true 802 } 803 } 804 ] 805 }); 806 numSlickProductSliders += $('.default-slider .products-grid').length; 807 $slider.on("breakpoint", function (event, slick, breakpoint) { 808 event.preventDefault(); 809 processSlickProductSliders(); 810 }); 811 } 812 } 813 814 //brands carousel slider 815 if (($brandslider = $('.slick-brands-carousel')).length) { 816 if (!$brandslider.hasClass('slick-initialized')) { 817 $brandslider.slick({ 818 dots: false, 819 infinite: true, 820 respondTo: 'slider', 821 slidesToShow: 8, 822 slidesToScroll: 8, 823 prevArrow: '<span class="sg-slick-prev" role="button" aria-label="Previous" tabindex="0"> ‹ </span>',/*Needs styles*/ 824 nextArrow: '<span class="sg-slick-next" role="button" aria-label="Next" tabindex="0"> › </span>', 825 responsive: [ 826 { 827 breakpoint: 1400, 828 settings: { 829 slidesToShow: 7, 830 slidesToScroll: 7 831 } 832 }, 833 { 834 breakpoint: 1200, 835 settings: { 836 slidesToShow: 6, 837 slidesToScroll: 6 838 } 839 }, 840 { 841 breakpoint: 1060, 842 settings: { 843 slidesToShow: 5, 844 slidesToScroll: 5 845 } 846 }, 847 { 848 breakpoint: 960, 849 settings: { 850 slidesToShow: 4, 851 slidesToScroll: 4 852 } 853 }, 854 { 855 breakpoint: 680, 856 settings: { 857 slidesToShow: 3, 858 slidesToScroll: 3 859 } 860 }, 861 { 862 breakpoint: 480, 863 settings: { 864 slidesToShow: 2, 865 slidesToScroll: 2 866 } 867 }, 868 { 869 breakpoint: 320, 870 settings: { 871 slidesToShow: 1, 872 slidesToScroll: 1, 873 variableWidth: true, 874 centerMode: true,
875 arrows: false 876 } 877 } 878 ] 879 }); 880 $brandslider.find('img').show(); 881 } 882 } 883 884 //callout slider 885 if (($calloutSlider = $('.techDetailsCarousel-container .slick-slider')).length) { 886 if (!$calloutSlider.hasClass('slick-initialized')) { 887 $calloutSlider.slick({ 888 dots: false, 889 arrows: true, 890 slidesToShow: 1, 891 slidesToScroll: 1, 892 lazyLoad: 'ondemand', 893 fade: true, 894 cssEase: 'linear' 895 }); 896 897 $calloutSlider.on('beforeChange', function (event, slick, currentSlide, nextSlide) { 898 $(".techDetailsCarousel-container ul.callout-thumbs li").removeClass("selected"); 899 $(".techDetailsCarousel-container ul.callout-thumbs").find("li:eq(" + nextSlide + ")").addClass("selected"); 900 }); 901 902 $("ul.callout-thumbs li").on("click", function () { 903 $calloutSlider.slick('slickGoTo', $(this).index()); 904 }); 905 } 906 } 907 908 if (($navslider = $('.navigation-carousel .bcwp-widgets-wrapper')).length) { 909 if (!$navslider.hasClass('slick-initialized')) { 910 $navslider.slick({ 911 dots: false, 912 infinite: true, 913 respondTo: 'slider', 914 slidesToShow: 6, 915 slidesToScroll: 6, 916 prevArrow: '<span class="sg-slick-prev-gray" role="button" aria-label="Previous" tabindex="0"></span>',/*Needs styles*/ 917 nextArrow: '<span class="sg-slick-next-gray" role="button" aria-label="Next" tabindex="0"></span>', 918 responsive: [ 919 { 920 breakpoint: 1400, 921 settings: { 922 slidesToShow: 6, 923 slidesToScroll: 6 924 } 925 }, 926 { 927 breakpoint: 1060, 928 settings: { 929 slidesToShow: 5, 930 slidesToScroll: 5 931 } 932 }, 933 { 934 breakpoint: 960, 935 settings: { 936 slidesToShow: 4, 937 slidesToScroll: 4 938 } 939 }, 940 { 941 breakpoint: 680, 942 settings: { 943 slidesToShow: 3, 944 slidesToScroll: 3 945 } 946 } 947 ] 948 }); 949 } 950 } 951 952 /** 953 * Ajax AddCart - Handles successful responses 954 * @param obj 955 * @param response 956 */ 957 AjaxCart.prototype.defaults.onSuccessCallback = function (obj, response) { 958 if (response.cartMax == true) 959 $("#cart-limit-modal-trigger").moby({ 960 'modalClass': 'cart-limit-modal gradient-gray', 961 'ariaLabelText': 'Full Cart', 962 'onCompleteCallback': function () { 963 $(".moby-close").on('click', function (event) { 964 event.preventDefault(); 965 $("#cart-limit-modal-trigger").moby('hide'); 966 }); 967 } 968 }).moby('show', '#cart-limit-modal'); 969 else { 970 971 if (response.miniCartHtml && response.miniCartHtml !== "") { 972 //update mini cart html
973 var prevItemCount = $("#cart-mmenu .products-grid li").length; 974 setCartQuantityText(); 975 var showCart = response.freeGiftHtml == "" && 976 response.personalizeHtml == ""; 977 978 if (Gorilla.util.getCookie("ab-cart") === "Experiment" && showCart) { 979 //this is bad practice, but a necessary evil until we are fully angular on the rest of the site 980 var scope = angular.element(document.getElementById('ItemAddedDialogController')).scope(); 981 scope.showDialog(); 982 } else { 983 updateShowMiniCart(response.miniCartHtml, showCart); 984 $(obj.options.miniCartContainer).html(response.miniCartHtml); 985 986 if ($("#cart-mmenu .products-grid li").length > prevItemCount) 987 popFadeProduct("cart-mmenu"); 988 } 989 } 990 991 //handle freegift modal 992 if (response.freeGiftHtml) { 993 if (($giftTrigger = $('#freegift-trigger')).length && ($giftModal = $('#freegift-modal')).length) { 994 //init the modal and set the Html from the response, since Moby requires an anchor we're triggering a click on the hidden anchor 995 $giftModal.html(response.freeGiftHtml); 996 $giftTrigger.moby({ 997 'modalClass': 'free-gift', 998 'ariaLabelText': 'Free Gift', 999 'bodyClose': false, 1000 'keyActions': false, 1001 'onCompleteCallback': function () { 1002 1003 if (($selects = $("#free-gift select")).length) { 1004 $selects.first().prop("selectedIndex", 0).customSelect("updateText"); 1005 } 1006 1007 Gorilla.util.initForms(); 1008 $(".moby-close").hide(); 1009 $('#free-gift').validate(); 1010 } 1011 }).moby('show', '#freegift-modal'); 1012 } 1013 } 1014 1015 } 1016 //determine if we are in a modal and close it, dont close if there are errors 1017 if (response.success) { 1018 if (obj.$element && ($moby = obj.$element.parents('.moby-container')).length) { 1019 $moby.find('.moby-close').trigger('click').off('click'); //close the actual window that triggered this....normal path 1020 } 1021 } 1022 else { 1023 Gorilla.util.messages.addMessages(response.messages, 'error'); 1024 } 1025 1026 //this has to go after the modal close above otherwise the page data is changed and the modal will not close. 1027 if (response.cartHtml) { 1028 $('#cartContainer').html(response.cartHtml); 1029 $('#cartContainer').find($("img.lazy")).lazy(); 1030 } 1031 } 1032
1033 //Canada/International Shopping Modal 1034 $(document).on("click", "a.international", function () { 1035 var $intlMoby = $(this).moby({ 1036 'modalClass': 'generic intl-shopping-modal', 1037 'ariaLabelText': 'International options', 1038 'onCompleteCallback': function () { 1039 Gorilla.util.initForms(); 1040 $('#intl-shopping-form').validate(); 1041 $("#intl-shopping").find(".close-link").on("click", function (e) { 1042 e.preventDefault(); 1043 $intlMoby.off('click.moby'); 1044 $intlMoby.moby('remove'); 1045 }); 1046 $(".intl-shopping-modal .moby-close").on("click", function() { 1047 $(this).parent().find('.close-link').click(); 1048 }); 1049 } 1050 }).moby('show', '#intl-shopping'); 1051 }); 1052 1053 //Tracking Infomration Modal 1054 var $trackingInfoModal = $(".tracking-info-trigger").moby({ 1055 'modalClass': 'tracking-info-modal', 1056 'ariaLabelText': 'Tracking information', 1057 'onCompleteCallback': function () { 1058 Gorilla.util.initForms(); 1059 1060 // not going to have this Close link in _OrderTrackng.cshtml for the time-being 1061 // it may (or may not) have been causing infrequent "immediate close" when opening... 1062 //$("#tracking-info").find(".close-link").click(function (e) { 1063 // e.preventDefault(); 1064 // $trackingInfoModal.moby('hide'); 1065 //}); 1066 } 1067 }); 1068 1069 //Audio modal 1070 var $divAudioTrigger = $("#div-audio-trigger").moby({ 1071 'modalClass': 'audio-modal', 1072 'ariaLabelText': 'Audio sample', 1073 'onCompleteCallback': function () { 1074 Gorilla.util.initForms(); 1075 }, 1076 'onCloseCallback': function () { 1077 $("#audioPlayer")[0].pause(); 1078 } 1079 }); 1080 1081 //Share Wish List Link Modal 1082 if (($sharewishlist = $(".sharewishlist-trigger")).length) { 1083 $(document).on("click", ".sharewishlist-trigger", function (e) { 1084 e.preventDefault(); 1085 $(".sharewishlist-trigger").moby({ 1086 'modalClass': 'generic sharewishlist-modal', 1087 'ariaLabelText': 'Share Wish List', 1088 'onBeforeCloseCallback': function () { 1089 $("#email-wishlist-form").trigger("reset"); // reset the form... 1090 var validator = $("#email-wishlist-form").validate(); 1091 validator.resetForm(); 1092 $("#email-wishlist-form label").removeClass("label-error"); 1093 $('#message-block').fadeOut("slow"); 1094 $('#message-block').html(""); 1095 }, 1096 'onCompleteCallback': function () { 1097 Gorilla.util.initForms(); 1098 1099 $("#sharewishlist-modal").find(".close-link, .moby-close").click(function (e) { 1100 e.preventDefault(); 1101 $(".sharewishlist-trigger").moby('hide'); 1102 }); 1103 } 1104 }).moby('show', '#sharewishlist-modal'); 1105 }); 1106 } 1107 1108 // Message (Move to Wish List from Cart) Modal 1109 var $messageModal = $("#wishlistmessage-trigger").moby({ 1110 'modalClass': 'generic wishlistmessage-modal', 1111 'ariaLabelText': 'Wishlist Success', 1112 'onCloseCallback': function () { 1113 //ADA return focus to cart table after modal is closed 1114 setTimeout(function () { 1115 var $trs = $("#cartContainer tbody tr:not(.restrictions-row)"); 1116 if (moveToWishlistIndex > $trs.length) { 1117 $trs.last().find('.product-name a').focus(); 1118 } else { 1119 $("#cartContainer tbody tr:not(.restrictions-row):nth-child(" + moveToWishlistIndex + ")").find('.product-name a').focus(); 1120 } 1121 }, 250); 1122 } 1123 }); 1124 1125 //Edit Exp (cc) Link Modal done in checkout.js 1126 1127 //Cancel Club Modal 1128 $(document).on("click", "#cancel-membership", function () { 1129 $("#cancel-membership-trigger").moby({ 1130 'modalClass': 'club-accept-modal', 1131 'ariaLabelText': 'Cancel club', 1132 'onCompleteCallback': function () { 1133 Gorilla.util.initForms();
1134 $('#cancel-membership-form').validate(); 1135 } 1136 }).moby('show', '#cancel-membership-modal'); 1137 }); 1138 1139 //cancel club confirmation 1140 $(document).on("submit", "#cancel-membership-form", function () { 1141 var postedData = AjaxJsonPostWrapper.getFormData(this); 1142 var firstLast = $(".customer-firstlast").text(); 1143 return AjaxJsonPostWrapper.ajaxRoute('club', 'cancelmembership', 1144 { customerNumber: postedData.CustomerNumber, cancelReason: postedData.CancelReason, name: firstLast }, 1145 function(result) { 1146 if (result.Success === true) { 1147 $("#cancel-membership-modal").html(result.Message); 1148 $(".club-dashboard > .spiff-container").replaceWith(result.DashboardSpiffHtml); 1149 $(".club-dashboard > .spiff-container").find($("img.lazy")).lazy(); 1150 } else { 1151 Gorilla.util.messages.addMessage('Sorry, an error has occurred. Please try again shortly.', 1152 'error'); 1153 } 1154 }); 1155 }); 1156 1157 //selection groups will refresh the lightbox on quickview 1158 $(document).on("click", ".quickview-form ul.selection-group li a.selection-link", function (event) { 1159 event.preventDefault(); 1160 var adId = getParameterByName("a", $(this).attr('href')); 1161 var data = { "AdId": adId }; 1162 return AjaxJsonPostWrapper.ajaxRoute("product", "getproductcartdata", data, function (result) { 1163 $(".moby-container.quickview .quickview-form").replaceWith(result); 1164 validateAndInitQuickViewForm($(".moby-container.quickview .quickview-form")); 1165 }); 1166 }); 1167 1168 //Gift Card Balance Form 1169 var $giftCardBalanceForm = $("#card-balance-form"); 1170 if ($giftCardBalanceForm.length) { 1171 var $balanceMessageHolder = $("#balance-message"); 1172 1173 $giftCardBalanceForm.validate({ 1174 submitHandler: function (form) { 1175 var $loader = $(form).find(".ajax-loader"); 1176 var url = $(form).prop("action"); 1177 1178 $balanceMessageHolder.text(''); 1179 $loader.show(); 1180 1181 $.post(url, $(form).serialize(), function (response) { 1182 $balanceMessageHolder.text(response.message) 1183 if (response.success) { 1184 $balanceMessageHolder.addClass("success"); 1185 } else { 1186 $balanceMessageHolder.addClass("error"); 1187 } 1188 1189 $loader.hide(); 1190 }); 1191 } 1192 }); 1193 } 1194 1195 //gift card lookup on my account/shopping resources 1196 if ($(".gift-card-balance").length) { 1197 $(document).on("click", "#gc-balance-btn", function () { 1198 if ($("#ReferenceNumber").val().trim() == "" || 1199 !$('#card-balance-form').valid()) { 1200 return; 1201 } 1202 1203 var data = AjaxJsonPostWrapper.getFormData($('#card-balance-form')); 1204 AjaxJsonPostWrapper.ajaxRoute("giftcard", "giftcardlookup", { giftCard: data }, 1205 function (result) { 1206 $("#gift-card-lookup-tables").html(result.giftCardLookupHtml); 1207 }); 1208 }); 1209 } 1210 1211 /** 1212 * keep body from scrolling when nav menu is open in iOS 1213 */ 1214 $(document).on('touchmove', function (e) { 1215 if ($('body').hasClass('nav-showing')) { 1216 var $target = $(e.target); 1217 if ($target.is('#nav-wrapper') || $target.parents('#nav-wrapper')) { 1218 e.stopPropagation(); 1219 } 1220 } 1221 }); 1222 1223 //dimension accordion init 1224 if (($accordion = $('#dimensions').find('.dim-accordion')).length) { 1225 $accordion.gorillaAccordion({ 1226 trigger: 'a.trigger', 1227 container: '.content', 1228 containerInner: '> ul' 1229 }); 1230 } 1231 1232 // a simple pair of classes was addded to truncate top and bottom abstracts with "..." on mobile 1233 // this allows user to expand and read the whole section if desired. 1234 $(document).on("click", ".single-line-ellipsis-trigger", function () { 1235 $(this).toggleClass("single-line-ellipsis"); 1236 }); 1237 1238 //Accordion spiff from web page images template 1239 if (($spiffAccordion = $('.spiff-accordion')).length) { 1240 $spiffAccordion.gorillaAccordion({ 1241 trigger: '.category-hero', 1242 container: '.accordion-content', 1243 containerInner: '> div' 1244 }); 1245 } 1246 1247 //peelback spiff from web page images template 1248 if (($peelBackSpiff = $(".peelback-container")).length) { 1249 $peelBackSpiff.on("mouseover", function () { 1250 $(this).find("div.before").css("width", 0); 1251 }); 1252 } 1253 1254 $(document).on("click", ".cfs-offerdetails-trigger", function (e) { // variation on the sg-accordion-header concept 1255 e.preventDefault(); 1256 $(this).next().slideToggle(250, function () { // the very next element had better be the content... 1257 }); 1258 }); 1259 1260 // deal with container padding: first, last, multiple containers of the same type are in a row 1261 if ((bcwpContainers = $("div.base-container")).length) { 1262 for (var i = 0; i < bcwpContainers.length; i++) { 1263 var $elem = $(bcwpContainers[i]); 1264 1265 // see if we're the first one of multiple of this type 1266 if (i == 0 || (i > 0 && $elem.data("containertype") != $(bcwpContainers[i - 1]).data("c
1266ontainertype")) && 1267 i < bcwpContainers.length - 1 && 1268 $elem.data("containertype") == $(bcwpContainers[i + 1]).data("containertype")) { 1269 1270 $elem.addClass("firstOfType"); 1271 } 1272 1273 // look back to see if the one before this was the same type 1274 if (i > 0 && $elem.data("containertype") === $(bcwpContainers[i - 1]).data("containertype")) { 1275 $elem.addClass("nthOfType"); 1276 1277 // see if we're also the last of our type... 1278 if (i === bcwpContainers.length - 1 || $elem.data("containertype") != $(bcwpContainers[i + 1]).data("containertype")) { 1279 $elem.addClass("lastOfType"); 1280 } 1281 } 1282 1283 // tag the very first base-container 1284 if (i === 0) { 1285 $elem.addClass("firstBaseContainer") 1286 } 1287 1288 // tag the very last base-container 1289 if (i === bcwpContainers.length - 1) { 1290 $elem.addClass("lastBaseContainer") 1291 } 1292 } 1293 } 1294 1295 $(document).on("click", "button.tool-tip", function (e) { 1296 if (e.target.tagName.toLowerCase() === 'a') // let nested links work 1297 return true; 1298 1299 e.preventDefault(); 1300 e.stopPropagation(); 1301 }); 1302 1303 $(document).on("keypress", ".pdp2019-quantityAdjustment #quantity", function (e) { 1304 var keyCode = e.which; 1305 if (keyCode == 13 && $(this).valid()) { 1306 $('#btnAddItemToCart').click(); 1307 return false; 1308 } 1309 return textInputDigitsOnly(keyCode); 1310 }); 1311 1312 $(document).on("blur", ".pdp2019-quantityAdjustment #quantity", function () { 1313 $this = $(this); 1314 var curVal = Number($.trim($this.val())); 1315 if (isNaN(curVal) || curVal <= 0 || !Number.isInteger(curVal)) { 1316 $this.val(1); 1317 } 1318 }); 1319 1320 }); // **** END Readied **** 1321 1322 // lots of trial club pages need a huge block of text, we wanted an "accordian" style flyout when the "link" is clicked 1323 $(".show-buyers-club-benefits").on("click", function () { 1324 $('#buyers-club-benefits').fadeIn('slow'); 1325 $(this).html(''); 1326 }); 1327 1328 //promo banner "tool tips" 1329 $(document).on("click", ".promo-trigger", function () { 1330 var message = $(this).next("hdncontent"); 1331 $("#site-promo-modal").html(message.text()); 1332 1333 $("#site-promo-modal-trigger").moby({ 1334 //'modalClass': 'cart-limit-modal gradient-gray', 1335 'ariaLabelText': 'Promotion', 1336 'onCompleteCallback': function () { 1337 $(".moby-close").on('click', function (event) { 1338 event.preventDefault(); 1339 $("#site-promo-modal-trigger").moby('hide'); 1340 }); 1341 } 1342 }).moby('show', '#site-promo-modal'); 1343 }); 1344 1345 //new product tiles.. since we cant put an anchor inside an anchor we have to show the quickview using javascript :( 1346 if ($(".product-tile").length) { 1347 $(document).on("mouseenter mouseleave", ".product-tile .product-image, .product-tile .btn-quickview", function (e) { 1348 if (e.type === "mouseenter") { 1349 $(this).closest(".product-tile").find(".btn-quickview").addClass("show"); 1350 } else { 1351 $(this).closest(".product-tile").find(".btn-quickview").removeClass("show"); 1352 } 1353 }); 1354 } 1355 1356 //animate labels to shrink and anchor to left corner to solve the placeholder texts always being visible ADA issue 1357 if (($anchorLabel = $(".input-wrapper .anchor-label")).length) { 1358 $anchorLabel.each(function() { 1359 var $input = $("#" + $(this).attr("for")); 1360 if ($input.length) { 1361 $input.on('focusin', function () { 1362 $(this).closest(".input-wrapper").addClass("anchored"); 1363 }).on('focusout', function () { 1364 if (!$(this).val()) { 1365 $(this).closest(".input-wrapper").removeClass("anchored"); 1366 } 1367 }); 1368 } 1369 }); 1370 } 1371 1372 $(document).on("click", "#auto-renew-container .auto-renew-link-no-si", function (e) { 1373 e.preventDefault(); 1374 1375 $link = $(this); 1376 $link.attr('disabled', 'disabled'); 1377 1378 var cust = $('#custnum').val();
1379 return AjaxJsonPostWrapper.ajaxRoute('account', 'toggleautorenewjsonnosi', { ar: $link.data("target"), cust: cust }, 1380 function (result) { // success (ajax, business logic could still indicate issues) 1381 $("#auto-renew-container").html(result.html); 1382 $(".auto-renew-link").focus(); 1383 }, 1384 function () { // error (ajax) 1385 // console.log("error"); 1386 }, 1387 function () { // complete (ajax) 1388 $link.removeAttr('disabled'); 1389 } 1390 ); 1391 }); 1392 1393 $(document).on("click", "#auto-renew-container .auto-renew-link", function (e) { 1394 e.preventDefault(); 1395 1396 $link = $(this); 1397 $link.attr('disabled', 'disabled'); 1398 1399 return AjaxJsonPostWrapper.ajaxRoute('account', 'toggleautorenewjson', { ar: $link.data("target") }, 1400 function (result) { // success (ajax, business logic could still indicate issues) 1401 $("#auto-renew-container").html(result.html); 1402 $(".auto-renew-link").focus(); 1403 }, 1404 function () { // error (ajax) 1405 // console.log("error"); 1406 }, 1407 function () { // complete (ajax) 1408 $link.removeAttr('disabled'); 1409 } 1410 ); 1411 }); 1412 1413 $(document).on("focus", ".styled-select", function (e) { 1414 $(this).closest(".select-wrap").find("span.customStyleSelectBox").first().addClass("psuedo-focus"); 1415 }); 1416 1417 $(document).on("blur", ".styled-select", function (e) { 1418 $(this).closest(".select-wrap").find("span.customStyleSelectBox").first().removeClass("psuedo-focus"); 1419 }); 1420 1421}(window.jQuery); 1422 1423//this function completely replaces tag names 1424(function ($) { 1425 $.fn.replaceTagName = function(replaceWith) { 1426 var tags =[], 1427 i = this.length; 1428 while (i--) { 1429 var newElement = document.createElement(replaceWith), 1430 thisi = this[i], 1431 thisia = thisi.attributes; 1432 for (var a = thisia.length -1; a >= 0; a--) { 1433 var attrib = thisia[a]; 1434 newElement.setAttribute(attrib.name, attrib.value); 1435 }; 1436 newElement.innerHTML = thisi.innerHTML; 1437 $(thisi).after(newElement).remove(); 1438 tags[i]= newElement; 1439 } 1440 return $(tags); 1441 }; 1442}) (window.jQuery); 1443 1444function updateNotifyMeEamil(address) { 1445 var boxes = []; 1446 $("input:checkbox[name=notifyMeBox]:checked").each(function () { 1447 boxes.push($(this).val()); 1448 }); 1449 1450 return AjaxJsonPostWrapper.ajaxRouteNonAsync('email', 'updatenotifymepreferences', { emailAddress: address, notifyMeBox: boxes }, function (result) { 1451 if(result != "") { 1452 $('#preferencesDiv').replaceWith(result.preferencesHtml); 1453 Gorilla.util.initForms(); 1454 $('#notifyme-emails-modal-trigger').moby({ 1455 'modalClass': 'email-preferences-modal', 1456 'ariaLabelText': 'Notify Me', 1457 'onCompleteCallback': function () { 1458 $(".moby-close, .button.close").on('click', function (event) { 1459 event.preventDefault(); 1460 $('#notifyme-emails-modal-trigger').moby('hide'); 1461 }); 1462 } 1463 }).moby('show', '#notifyme-emails-modal'); 1464 } 1465 }); 1466} 1467/****************************** Wish List *******************************************/ 1468function addToWishListFamily(id, promo, isSignedIn, colorCode, sizeCode) { 1469 // color code, size code, promo code, id, quantity 1470 var cartItem = { ID: id, PromoCode: promo, ColorCode: colorCode, SizeCode: sizeCode, Quantity: 1 }; 1471 1472 1473 if (!isSignedIn) { 1474 Gorilla.util.setCookie('_wishlist-product-data', btoa(JSON.stringify(cartItem))); 1475 // if not signed in, send them off to sign-in/create account with their wish list as the final landing page (wish list will add the item from the cookie and trigger personalization if needed) 1476 window.location = "/authenticate/accountlogin?returnUrl=/wishlist/index" 1477 } 1478 else { 1479 // send them to their wish list (wish list will add the item from the cookie and trigger personalization if needed) 1480 window.location = "/wishlist/index"; 1481 } 1482} 1483 1484function showClubBucksDialog(buck) { 1485 var scope = angular.element(document.getElementById('MyAccountClubBucksDialogController')).scope(); 1486 scope.showDialog(buck); 1487} 1488 1489function setWishlistQuantityText() { 1490 var cookieValue = "0"; 1491 var cookieData = 1492 decodeURIComponent(document.cookie 1493 .replace(new RegExp("(?:(?:^|.*;)\\s*" + 1494 encodeURIComponent("wlQty").replace(/[\-\.\+\*]/g, "\\$&") +
1495 "\\s*\\=\\s*([^;]*).*$)|^.*$"), 1496 "$1")) || null; 1497 1498 if (cookieData != null) 1499 cookieValue = cookieData; 1500 1501 $('#wishlistQtyText').text(cookieValue); 1502 if (cookieValue != null && cookieValue != "0") { 1503 $('#wishlistQtyText').show(); 1504 $('#wishlistQtyLbl').show(); 1505 } else { 1506 $('#wishlistQtyText').hide(); 1507 $('#wishlistQtyLbl').hide(); 1508 } 1509 1510} 1511 1512function editPersonalization(entryId, isPersonalized) { 1513 AjaxJsonPostWrapper.ajaxRoute('wishlist', 'editpersonalization', { entryId: entryId, isPersonalized: isPersonalized }, function (result) { 1514 //handle personalize modal 1515 if (result.personalizeHtml) { 1516 if (result.personalizeHtml.substr(0, 10) == "embroidery") { 1517 document.location.href = "/wishlist/" + result.personalizeHtml; 1518 } 1519 else if (($personalizeTrigger = $('#personalize-trigger')).length && 1520 ($personalizeModal = $('#personalize-modal')).length) { 1521 1522 $personalizeModal.html(result.personalizeHtml); 1523 $personalizeTrigger.moby({ 1524 'modalClass': 'personalize-mod', 1525 'ariaLabelText': 'Customize Item', 1526 'onCompleteCallback': function () { 1527 Gorilla.util.initForms(); 1528 $('#personalize-mod').validate(); 1529 } 1530 }).moby('show', '#personalize-modal'); 1531 } 1532 } 1533 }); 1534}; 1535 1536function checkQtyLimit($form) { 1537 var limit = $form.find("#hdnPurchaseQtyLimit").val(); 1538 if (limit === "0" || limit === "99") return false; 1539 setTimeout(function () { 1540 $form.find('#quantity').attr('type', 'number').attr('max', limit); 1541 }, 1000); 1542 if ($form.find("#ammoQtyLimit").length) { 1543 $form.find("#ammoQtyLimit").text(limit); 1544 } else { 1545 $form.find('.pdp-title-flex-container').first().after( 1546 '<div class="bold-text" style="color:#54565a;">* THIS ITEM HAS A LIMIT OF <span id="ammoQtyLimit">' + 1547 limit + '</span> PER ORDER.</div>'); 1548 } 1549} 1550 1551function CartMoveToWishListAfterLogin(cartEntryId, inCheckout) { 1552 1553 // save form data to cookie 1554 Gorilla.util.setCookie('_wishlist-ceid', btoa(JSON.stringify(cartEntryId))); 1555 1556 var returnUrl = inCheckout ? "/checkout" : "/cart/viewcart"; 1557 1558 // if not signed in, send them off to sign-in/create account with their wish list as the final landing page (wish list will move the item from their cart to their now-available wishlist) 1559 window.location = "/authenticate/accountlogin?returnUrl=" + returnUrl; 1560 1561} 1562 1563function CartMoveToWishListAsync(el, cartEntryId, inCheckout, inQuickOrder) { 1564 1565 var maxLimitReached = false; 1566 var success = false; 1567 moveToWishlistIndex = $(el).closest('tr:not(.restrictions-row)').prevAll().length + 1; 1568 1569 if (cartEntryId == null) 1570 return false; 1571 1572 $('.loading').show(); 1573 AjaxJsonPostWrapper.ajaxRouteNonAsync('wishlist', 'movetowishlist', { entryId: cartEntryId }, function (response) { 1574 $('.loading').hide(); 1575 // don't need to update main wish list display 1576 maxLimitReached = response.maxLimitReached; 1577 success = response.success; 1578 if (maxLimitReached) { 1579 $("#wish-limit-modal-trigger").moby({ 1580 'modalClass': 'wish-limit-modal gradient-gray', 1581 'ariaLabelText': 'Full Wish List', 1582 'onCompleteCallback': function () { 1583 $(".moby-close, .button.close").on('click', function (event) { 1584 event.preventDefault(); 1585 $("#wish-limit-modal-trigger").moby('hide'); 1586 }); 1587 } 1588 }).moby('show', '#wish-limit-modal'); 1589 } 1590 }); 1591 1592 if (!maxLimitReached && success) { 1593 // remove item from cart 1594 var action = inCheckout ? "updateqtyincheckout" : "updateqty"; 1595 $('.loading').show();
1596 AjaxJsonPostWrapper.ajaxRouteNonAsync('cart', action, { entryId: cartEntryId, qty: 0, cqo: inQuickOrder }, function (result) { 1597 $('.loading').hide(); 1598 if (inQuickOrder && result.cartQty < 1) { 1599 window.location.assign("/cart/catalogquickorder"); 1600 } 1601 //update the main cart display 1602 else if (result.cartQty > 0) { 1603 if (result.cartHtml && result.cartHtml != "") { 1604 $('#cartContainer').html(result.cartHtml); 1605 $('#cartContainer').find($("img.lazy")).lazy(); 1606 $('#cartModifiedBtn').click(); 1607 Gorilla.util.initForms(); 1608 1609 if (!inCheckout) { 1610 setCartQuantityText(); 1611 } 1612 1613 // show message in modal 1614 $("#wishlistmessage-modal").html("Item moved to Wish List"); 1615 $("#wishlistmessage-trigger").click(); 1616 1617 } 1618 } 1619 else 1620 window.location.replace("/cart/viewcart"); 1621 }); 1622 } 1623 else if(!success) { 1624 $("#wishlistmessage-modal").html("Email address error. Please sign out and sign back in."); 1625 $("#wishlistmessage-trigger").click(); 1626 } 1627} 1628 1629// the HandleCartMoveToWishListLogin needs to be called from "returnUrl" client-side script, 1630// thus far it is just the Cart and the Payment pages that use this 1631function HandleCartMoveToWishListAfterLogin(inCheckout) { 1632 var cookie = Gorilla.util.getCookie("_wishlist-ceid"); 1633 if (cookie != null) { 1634 $('.loading').show(); 1635 AjaxJsonPostWrapper.ajaxRouteNonAsync('authenticate', 'issignedin', {}, function (response) { 1636 $('.loading').hide(); 1637 //only move the item if they are signed in, if the didnt actually sign in and the come back to the cart page then just delete the cookie 1638 if (response.signedIn) { 1639 var decodedData = atob(cookie); 1640 var data = JSON.parse(decodedData); 1641 Gorilla.util.deleteCookie("_wishlist-ceid"); 1642 1643 CartMoveToWishListAsync(this, data, inCheckout, false); 1644 } else { 1645 Gorilla.util.deleteCookie("_wishlist-ceid"); 1646 } 1647 }); 1648 } 1649 1650} 1651 1652 1653//ALL cart refreshes before checkout need to use this!!! 1654function updateShowMiniCart(html, showSlide) { 1655 if (html && html !== "") { 1656 setCartQuantityText(); 1657 var $cartSummary = $("#cartSummary"); 1658 setTimeout(function () { 1659 $cartSummary.empty().append(html); 1660 $("#mini-totals").empty().append($cartSummary.find(".mini-totals-container").detach()); 1661 1662 var itemCount = $cartSummary.find(".items-in-cart").detach().text(); 1663 var cartTotal = $("#mini-cart-total-preview").html(); 1664 var cls = $("#mini-cart-total-preview").attr('class'); 1665 $("#cart-mmenu").removeClass("mm-nomap").removeClass("mm-map").removeClass("mm-unset").removeClass("mm-noSavings"); 1666 if (itemCount.length) { 1667 $("#cart-mmenu").addClass(cls); 1668 $("#mini-cart-total").html(cartTotal).show(); 1669 $("#mini-count").empty().append(itemCount); 1670 $("#mini-cart-actions").show(); 1671 $("#cart-mmenu .mm-navbars_top .mm-navbar").css("height", ""); 1672 $("#cart-mmenu.mm-menu_navbar_top-1 .mm-panels").css("top", ""); 1673 } else { 1674 $("#mini-cart-actions").hide(); 1675 $("#cart-mmenu").addClass("mm-unset"); 1676 $("#mini-count").text("0 items in your cart"); 1677 $("#mini-cart-total").hide(); 1678 } 1679 }, 500); 1680 1681 if (showSlide) { 1682 dropMiniCart(); 1683 } 1684 } 1685} 1686 1687//ALL updates to the view cart container need to use this!!! 1688function updateCartContainer(html) { 1689 $('#cartContainer').replaceWith(html); 1690 $('#cartContainer').find($("img.lazy")).lazy(); 1691 Gorilla.util.initForms();
1692 //need to refresh dynamic data on teh club spiff... 1693 //TODO since that no longer show/hides based on the cart or membership... this should be fixed to be static 1694 AjaxJsonPostWrapper.ajaxRoute('dynamicdata', 'getdata', { page: 'viewcart' }, function (result) { 1695 var $clubDd = $("club-dynamic-data"); 1696 if (result.clubDd && $clubDd.length) { 1697 $("club-dynamic-data").replaceWith(result.clubDd); 1698 } 1699 }); 1700} 1701 1702/****************************** Search SuggestAhead *******************************************/ 1703function getSuggestAheadTerms(request, response) { 1704 var term = $('<div/>').text(request.term).html(); 1705 $.ajax({ 1706 type: "POST", 1707 url: window.location.protocol + "//" +window.location.host + "/main/suggestaheadsearchterms", 1708 async: true, 1709 data : JSON.stringify({ term: term }), 1710 contentType: 'application/json', 1711 traditional: true, 1712 success: function (result) { 1713 var fullTerms = result.suggestions.split('|'); 1714 var uniqueKeys =[]; 1715 $.each(fullTerms, function (i, el) { 1716 var str = el.trim(); 1717 if ($.inArray(str, uniqueKeys) == -1) uniqueKeys.push(str); 1718 }); 1719 $('#searchProducts').html(result.html); 1720 $itemContainer = $('#product-listing-container'); 1721 $itemContainer.find("img.lazy").lazy({ delay: 0 }); 1722 response(uniqueKeys); 1723 }, 1724 error: function (XMLHttpRequest, textStatus, errorThrown) { 1725 var errId = XMLHttpRequest.getResponseHeader("System-Error-ID"); 1726 var errIdMsg = ""; 1727 if (errId != null) { 1728 errIdMsg = " [" + errId + "]" 1729 } 1730 console.log("An error occurred during ajax operation" + errIdMsg + ".") // mimics what has been "good enough" since redesign, circa 2014. we don't really know what to do but probably don't want to interrupt the user 1731 1732 //if (error != undefined) { 1733 // error(errorThrown); 1734 //} 1735 //else { 1736 // Gorilla.util.messages.addMessage('Sorry, there was an error with your request. Please try again shortly.', 'error'); 1737 //} 1738 } 1739 }) 1740 .done(function (data) { 1741 if (data.errors) { 1742 onDataError(data); 1743 } 1744 }); 1745} 1746 1747function getSuggestAheadTermsFocusCall(term) { 1748 var suggestions = term; 1749 $('#searchProducts').html(""); 1750 AjaxJsonPostWrapper.ajaxRoute('main', 'suggestaheadsearchterms', { term: term }, function (result) { 1751 $('#searchProducts').html(result.html); 1752 $itemContainer = $('#product-listing-container'); 1753 $itemContainer.find("img.lazy").lazy({ delay: 0 }); 1754 }); 1755 return suggestions; 1756} 1757 1758function myGetStackTrace() { 1759 var stackTrace = (function () { 1760 var ret = new Error("").stack; // doesn't seem to work in IE but faster in Chrome and FF 1761 if (ret == undefined || ret == "") // use the throw catch technique when needed 1762 try { 1763 throw new Error(""); 1764 } catch (ex) { 1765 ret = ex.stack; 1766 } 1767 return ret; 1768 })(); 1769 1770 var messages = stackTrace ? stackTrace.split("\n") : ""; 1771 messages.splice(0, messages[0] == 'Error' ? 3 : 2); // removed the first 3 or 2 lines (FF doesn't start w/ "Error" line) 1772 1773 return messages.join("\n"); 1774} 1775 1776// when an item in the suggested terms dropdown gets the focus/hover, call out and get products for that term 1777function getSuggestAheadTermsFocus(liID, label) { 1778 if ($("#" + liID).hasClass('ui-state-active')) { // used to be ui-state-focus in older version of jQuery 1779 getSuggestAheadTermsFocusCall(label); 1780 } 1781} 1782 1783// setup a custom override of the jquery-ui's _renderMenu function 1784$.widget("ui.autocomplete", $.ui.autocomplete, { 1785 options: { 1786 maxItems: 9999 // adds this maxItems property to the object and default to 9999, usually overridden during specific .autocomplete({ inits 1787 }, 1788 _renderMenu: function (ul, items) { // override jQuery-Ui's _renderMenu so we can make use of the maxItems as needed 1789 var that = this; 1790 $.each(items, function (index, item) { // google says this goes in order that they appear in the DOM 1791 if (index < that.options.maxItems) { 1792 that._renderItemData(ul, item); 1793 } 1794 }); 1795 } 1796}); 1797 1798function validateEU(input) { 1799 return !/(\.(ad|at|be|bg|hr|cy|cz|dk|ee|fi|fr|de|gr|gp|va|hu|ie|im|it|lv|lt|lu|mt|mq|mc|nl|pl|pt|ro|sk|si|es|bl|mf|se|gb|uk|eu))$/i.test(input); 1800} 1801 1802/****************************** Truncate ad copy*******************************************/ 1803 1804function truncateQuickViewAdCopy(quickViewForm) { 1805 var overflowMaxHeight = 400; 1806 var productDesc = quickViewForm.find('.product-description'), 1807 productMore = quickViewForm.find('#quickViewMoreDetails'); 1808 truncateElementTextToHeight(productDesc, overflowMaxHeight);
1809 productMore.detach().appendTo(productDesc.children().last()); 1810} 1811 1812function truncateElementTextToHeight(elem, overflowMaxHeight) { 1813 if (elem.height() > overflowMaxHeight) { 1814 do { 1815 var lastChild = elem.children().last(); 1816 if ((lastChild.is('ul')) && (lastChild.children().length > 0)) { 1817 lastChild.children().last().remove(); 1818 if (lastChild.children().length == 0) { 1819 lastChild.remove(); 1820 } 1821 } 1822 else { 1823 var text = elem.html(); 1824 text = text.slice(0, text.lastIndexOf(" ")); 1825 elem.html(text); 1826 } 1827 } while (elem.height() > overflowMaxHeight); 1828 } 1829} 1830 1831/****************************** Bloomreach Related Product Quick View Image Swap *******************************************/ 1832 1833function swapBRRelProdImage(anchor) { 1834 var $id = anchor.href.substr(anchor.href.lastIndexOf('#')+1); 1835 var $div = $("div[id=" + $id + "]"); 1836 var $img = $div.find('img.brRelProd'); 1837 if ($img.length) { 1838 $img.attr("src", $img.attr("data-br-src").replace("/m/", "/e/")); 1839 } 1840 $div.find("#alternate-images img").each(function () { 1841 $(this).attr("src", $(this).attr("data-br-src").replace("/m/", "/e/")); 1842 }); 1843} 1844 1845/* This function will report if an element is in the current viewport */ 1846function isElementInViewport(el) { 1847 if (typeof jQuery === "function" && el instanceof jQuery) { 1848 el = el[0]; 1849 } 1850 1851 var rect = el.getBoundingClientRect(); 1852 1853 return ( 1854 rect.top >= 0 && 1855 rect.left >= 0 && 1856 rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */ 1857 rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */ 1858 ); 1859} 1860 1861/* This function will find the largest height and width of a set of elements and resize them accordingly */ 1862function resizeElms(els) { 1863 var $els = $(els); 1864 if ($els.length) { 1865 var height = getMaxHeight($els); 1866 var width = getMaxWidth($els); 1867 $els.each(function () { 1868 $(this).height(height); 1869 $(this).width(width); 1870 }); 1871 } 1872} 1873function resizeSelectionGroup(els) { 1874 var $els = $(els); 1875 var height = getMaxHeight($els); 1876 var width = getMaxWidth($els); 1877 $els.each(function () { 1878 $(this).width(width); 1879 $(this).height(height); 1880 $(this).css('line-height', height + 'px'); 1881 }); 1882} 1883function getMaxWidth(els) { 1884 return Math.max.apply(Math, 1885 $(els).map(function () { 1886 return $(this).width(); 1887 }).get()); 1888} 1889function getMaxHeight(els) { 1890 return Math.max.apply(Math, 1891 $(els).map(function () { 1892 return $(this).height(); 1893 }).get()); 1894} 1895 1896//equivalent to IsNullOrWhiteSpace server side 1897function isNullOrWhiteSpace(input) { 1898 if (typeof input === 'undefined' || input == null) return true; 1899 return input.replace(/\s/g, '').length < 1; 1900} 1901 1902// get query string parameter by name 1903function getParameterByName(name, url) { 1904 if (!url) { 1905 url = window.location.href; 1906 } 1907 name = name.replace(/[\[\]]/g, "\\$&"); 1908 var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), 1909 results = regex.exec(url); 1910 if (!results) return null; 1911 if (!results[2]) return ''; 1912 return decodeURIComponent(results[2].replace(/\+/g, " ")); 1913} 1914 1915function dropMiniCart() { 1916 //close the quickview slideout if its open 1917 if ($("#quickview-mmenu").length && $("#quickview-mmenu").hasClass("mm-menu_opened")) { 1918 $("#quickview-mmenu").data("mmenu").close(); 1919 if (lastFocus) { 1920 lastFocus.focus(); 1921 } 1922 } 1923 1924 $quickorderAdd = $("#quickorder-add"); 1925 if (!$quickorderAdd.length) 1926 setTimeout(function() { 1927 $("#cart-mmenu").data("mmenu").open(); 1928 trapFocus($("#cart-mmenu")); 1929 $("#cart-mmenu").on("click", ".mm-navbars_top", function (e) {
1930 $("#cart-mmenu").data("mmenu").close(); 1931 }); 1932 }, 500); 1933} 1934 1935 1936 1937// validates social security number 1938// method looks for SS1, SS2 and SS3 1939// SSN cannot be all the same digit or 123456789 1940function adsICSSNValidation() { 1941 if ($('#SS1').val() && $('#SS2').val() && $('#SS3').val()) 1942 { 1943 var SSN = $('#SS1').val() + $('#SS2').val() + $('#SS3').val(); 1944 return /^(?!\b(\d)\1+\b)(?!123456789|012345678)\d{9}$/.test(SSN); 1945 1946 } 1947 return true; 1948} 1949 1950// validates age, must be at least 18 years of age 1951// method looks for DOBDay, DOBMonth and DOBYear 1952function adsICDOBValidation() { 1953 if ($('#DOBDay').val() && $('#DOBMonth').val() && $('#DOBYear').val()) { 1954 var day = $('#DOBDay').val(); 1955 var month = $('#DOBMonth').val(); 1956 var year = $('#DOBYear').val(); 1957 var requiredAge = 18; 1958 1959 var dob = new Date(year, month - 1, day); 1960 var today = new Date(); 1961 var mindob = new Date(today.getFullYear() - 18, today.getMonth(), today.getDate()); 1962 return mindob >= dob; 1963 } 1964 return true; 1965} 1966 1967// validates phone number, must be 10 digits long 1968// method looks for PhoneNumber1, PhoneNumber2, PhoneNumber3 1969// phone number cannot be all the same digit or incrementing numbers, and must be 10 digits 1970function adsICPhoneValidation() { 1971 if ($('#PhoneNum1').val() && $('#PhoneNum2').val() && $('#PhoneNum3').val()) { 1972 var phone = $('#PhoneNum1').val() + $('#PhoneNum2').val() + $('#PhoneNum3').val(); 1973 return /^(?!\b(\d)\1+\b)(?!1234567890|0123456789)\d{10}$/.test(phone); 1974 } 1975 return true; 1976} 1977function adsICPhoneAltValidation() { 1978 if ($('#AltNum1').val() || $('#AltNum2').val() || $('#AltNum3').val()) { 1979 var phone = $('#AltNum1').val() + $('#AltNum2').val() + $('#AltNum3').val(); 1980 return /^(?!\b(\d)\1+\b)(?!1234567890|0123456789)\d{10}$/.test(phone); 1981 } 1982 return true; 1983} 1984 1985// checkout payment - validate if a customer can use their new ADS credit card 1986// or are they over their credit limit? 1987function adsCanUseCard(creditlimit) { 1988 if ($('#CCType').val() == "L" && creditlimit != 0 && $('#GrandTotal').val() != 0 && (Number(creditlimit) < Number($('#GrandTotal').val()))) 1989 { 1990 return false; 1991 } 1992 return true; 1993} 1994 1995function populateTealiumAjaxScript(script) { 1996 var div = $('#tealiumAjax'); 1997 div.empty(); 1998 div.append(script); 1999} 2000 2001function addItemToCartFamilyGroup(itemId, promoCode, color, size, qty, fgItem, fgPromo, fgOfferID, fromTable) { 2002 var cartItem = { ID: itemId, PromoCode: promoCode, ColorCode: color, SizeCode: size, Quantity: qty, FreeGiftItemId: fgItem, FreeGiftPromoCode: fgPromo, FreeGiftOfferID: fgOfferID, FromTable: fromTable }; 2003 return AjaxJsonPostWrapper.ajaxRoute('cart', 'addtocart', { data: cartItem }, function (result) { 2004 if (result.cartMax == true) { 2005 $("#cart-limit-modal-trigger").moby({ 2006 'modalClass': 'cart-limit-modal gradient-gray', 2007 'ariaLabelText': 'Full Cart', 2008 'onCompleteCallback': function () { 2009 $(".moby-close").on('click', function (event) { 2010 event.preventDefault(); 2011 $("#cart-limit-modal-trigger").moby('hide'); 2012 }); 2013 } 2014 }).moby('show', '#cart-limit-modal'); 2015 } 2016 else { 2017 updateShowMiniCart(result.miniCartHtml, true); 2018 populateTealiumAjaxScript(result.tealium); 2019 if (result.freeGiftHtml) { 2020 if (($giftTrigger = $('#freegift-trigger')).length && ($giftModal = $('#freegift-modal')).length) { 2021 //init the modal and set the Html from the response, since Moby requires an anchor we're triggering a click on the hidden anchor 2022 $giftModal.html(result.freeGiftHtml); 2023 $giftTrigger.moby({ 2024 'modalClass': 'free-gift', 2025 'ariaLabelText': 'Free Gift', 2026 'bodyClose': false, 2027 'keyActions': false, 2028 'onCompleteCallback': function () { 2029 Gorilla.util.initForms();
2030 $(".moby-close").hide(); 2031 $('#free-gift').validate(); 2032 } 2033 }).moby('show', '#freegift-modal'); 2034 } 2035 } 2036 } 2037 2038 }); 2039} 2040 2041//4 payplan consent modal... called from AccountFourPayList.. no longer used in checkout 2042function showPayplanConsent() { 2043 var $trigger = $('#payplan-consent-modal-trigger'); 2044 if ($trigger != null) 2045 { 2046 var $ppForm = $('#payplan-consent'); 2047 2048 $trigger.moby({ 2049 'modalClass': 'payplan-consent-modal', 2050 'ariaLabelText': '4-Pay', 2051 'onCompleteCallback': function () { 2052 Gorilla.util.initForms(); 2053 $ppForm.validate(); 2054 2055 $('.button.yes').on('click', function (event) { 2056 event.preventDefault(); 2057 if ($ppForm.valid()) { 2058 var orderNumber = $("#ConsentOrderNumber").val(); 2059 var phoneNumber = $("#ConsentPhone").val(); 2060 AjaxJsonPostWrapper.ajaxRouteNonAsync('account', 'editorderconsentphone', { order : orderNumber, phone : phoneNumber }, 2061 function (formattedPhone) { 2062 $('li[data-order="' + orderNumber + '"] div span').text(formattedPhone); 2063 } 2064 ); 2065 2066 $trigger.moby('hide'); 2067 } 2068 }); 2069 2070 $('a.close').on('click', function (event) { 2071 event.preventDefault(); 2072 $ppForm.resetForm(); 2073 $trigger.moby('hide'); 2074 }); 2075 } 2076 }).moby('show', '#payplan-consent-modal'); 2077 } 2078} 2079 2080function initQtyButtons(containerName) 2081{ 2082 if (($container = $(containerName)).length) 2083 { 2084 setTimeout(function () { 2085 $(".qty-adjust", $container).click(function (e) { 2086 e.preventDefault(); 2087 2088 var $this = $(this); 2089 var $form = $this.closest("form"); 2090 var $qty = $("#quantity", $form); 2091 var qty = $qty.val(); 2092 2093 // manage new version (button w/ enhanced ADA) vs old version (div no ADA) 2094 if ($this.prop("tagName").toLowerCase() === "button") { // new approach 2095 if ($this.data("direction") == "plus" && qty < 99) { 2096 qty++; 2097 } else if ($this.data("direction") == "minus" && qty > 1) { 2098 qty--; 2099 } 2100 } else { // old approach, should go away after PDP A/B test is complete and everything is rolled over to new version 2101 if ($this.text() == "+" && qty < 99) { 2102 qty++; 2103 } else if ($this.text() == "-" && qty > 1) { 2104 qty--; 2105 } 2106 } 2107 2108 // safety / default 2109 if (!$.isNumeric(qty) || qty < 1) { 2110 qty = 1; 2111 } 2112 2113 $qty.val(qty); 2114 $form.validate().element($qty); 2115 }); 2116 }, 1000); 2117 } 2118} 2119 2120function initFitRating(containerName, currentValue) 2121{ 2122 if (($container = $(containerName)).length) { 2123 if (($fitRating = $("#BVFitRating", $container)).length) { 2124 $fitRating.slider({ 2125 range: "max", 2126 min: 1, 2127 max: 5, 2128 step: 0.01, 2129 value: currentValue, 2130 disabled: true, 2131 create: function (event, ui) { 2132 setSliderTicks(event.target); 2133 } 2134 }); 2135 } 2136 } 2137} 2138 2139function initWidthRating(containerName, currentValue) 2140{ 2141 if (($container = $(containerName)).length) { 2142 if (($widthRating = $("#BVWidthRating", $container)).length) { 2143 $widthRating.slider({ 2144 range: "max", 2145 min: 1, 2146 max: 3, 2147 step: 0.1, 2148 value: currentValue, 2149 disabled: true, 2150 create: function (event, ui) { 2151 setSliderTicks(event.target); 2152 } 2153 }); 2154 } 2155 } 2156} 2157 2158//auto selects the only option in the size/color dropdowns 2159//function initAutoSelect(form) { 2160// var $form = $(form); 2161// processSelectedProductOption($form.find('.auto-select')); 2162//} 2163 2164function searchFaq(searchTerm) 2165{ 2166 // *** this function depends on the structure of the markup, if that changes this may stop working 2167 // most accordions are nested, some are not... 2168 // search the questions and answers together so we don't accidentally hide just one of the pair 2169 2170 $("#faqSearchCounts:visible").hide(); 2171 2172 $(".sg-accordion-header").fadeIn(); // show them all 2173 $(".sg-accordion-header").removeClass("active"); 2174 $(".sg-accordion-content").slideUp(); 2175 2176 searchTerm = $.trim(searchTerm); 2177 if (searchTerm === "") { 2178 return; // bail out 2179 } 2180 2181 searchTerm = searchTerm.replace(/[']/ig, ""); 2182 safeSearchTerm = jQuery.ui.autocomplete.escapeRegex(searchTerm); // escape any special characters that could affect regex; unofficial, per http://stackoverflow.com/questions/5306095/simple-jquery-javascript-method-to-escape-special-characters-in-string-for-reg 2183 var regexSearchTerm = new RegExp(safeSearchTerm, "i"); 2184 2185 $("h2.sg-accordion-header").each(function () { // process each category 2186 var $thisHeader = $(this); 2187 var $thisContent = $thisHeader.next(".sg-accordion-content"); 2188 2189 2190 if (searchQuestionAndAnswer(regexSearchTerm, $thisHeader, $())) { // check the category text first and skip children if found, assume they all apply 2191 $thisHeader.removeClass("hidden-header").fadeIn(); 2192 $(".sg-accordion-header", $thisContent).removeClass("hidden-header").fadeIn(); // show all children 2193 } else { 2194 var foundText = false; 2195 if (($children = $thisContent.find(".sg-accordion-header")).length) { 2196 // nested ones, at this time they only contain one or more accordions, not a mix of accordions and content, not further nested accordions 2197 var childrenShowing = 0; 2198 $children.each(function () { // process each question 2199 var $childHeader = $(this); 2200 var $childContent = $childHeader.next(".sg-accordion-content"); 2201 2202 foundText = searchQuestionAndAnswer(regexSearchTerm, $childHeader, $childContent); 2203 showOrHide(foundText, $childHeader, $childContent); 2204 2205 if (foundText) 2206 childrenShowing++; 2207 }); 2208 2209 showOrHide(childrenShowing > 0, $thisHeader, $thisContent); // hide parent if all children are hidden 2210 2211 } else { 2212 // does not contain a nested accordion 2213 // just check the content, we already checked the category text and didn't find it 2214 foundText = searchQuestionAndAnswer(regexSearchTerm, $(), $thisContent) 2215 showOrHide(foundText, $thisHeader, $thisContent); 2216 } 2217 } 2218 });
2219 2220 var categoryCount = 0; 2221 var questionCount = 0; 2222 2223 // animation messes with the native :visible, i put my own "hidden-header" class on the elements to get around that 2224 if ((categoryCount = $("h2.sg-accordion-header:not(.hidden-header)").length) === 0) { // if none are not .hidden-header, then no data found 2225 $("#faqSearchCounts").html("No results found").show(); 2226 } else { 2227 questionCount = $(".sg-accordion-content h3.sg-accordion-header:not(.hidden-header)").length 2228 $("#faqSearchCounts").html(questionCount + " FAQs found in " +categoryCount + " categories").show(); 2229 } 2230 2231 // record a couple of things to provide direction when FAQ content is revisted 2232 var data = { 2233 faqSearchInput: searchTerm, 2234 foundCategoryCount: categoryCount, 2235 foundQuestionCount: questionCount 2236 }; 2237 AjaxJsonPostWrapper.ajaxRoute('customerservice', 'searchfaqs', data, function (response) { }); // don't need to do anything with any returned information 2238 2239} 2240 2241function searchQuestionAndAnswer(regexSearchTerm, $header, $content) { 2242 return ($header.text().search(regexSearchTerm) >= 0) || ($content.text().search(regexSearchTerm) >= 0); 2243} 2244 2245function showOrHide(shouldShow, $header, $content) { 2246 if (shouldShow) { 2247 $header.removeClass("hidden-header"); 2248 $header.fadeIn(); 2249 // $content.fadeIn(); // this expands the accordion and kinda messes up their state 2250 } else { 2251 $header.addClass("hidden-header"); 2252 $header.hide(); 2253 $content.hide(); 2254 } 2255} 2256 2257function initToolTips() { //lazy-load tool tips on demand.. but not the fake ones (ffl lookup) 2258 $(document).on("click mouseover", "button.tool-tip:not(.not-really)", function (e) { 2259 e.preventDefault(); 2260 var $tip = $(this); 2261 if (!$tip.data('isSet')) { 2262 $tip.tipsy({ 2263 bounds: $('body'), 2264 //show method not publicly exposed... re-fire the event to show the tip after its wired up 2265 afterInitCallback: function() { 2266 if ($(window).width() > 960) { $tip.trigger('click'); } 2267 } 2268 }); 2269 } 2270 }); 2271} 2272 2273 2274// if they click / tap on a slider in mobile this should be used to take 2275// care of any underlying link / anchor 2276// used during click: function, sister function to swipe: function 2277function sliderTap(event, target) { 2278 switch ($(target).get(0).tagName.toLowerCase()) { 2279 case "a": 2280 document.location.href = target; 2281 break; 2282 case "img": 2283 // this only goes up one level, obviously... 2284 var p = $(target).parent(); 2285 if (p.get(0).tagName.toLowerCase() == "a") { 2286 document.location.href = p.attr("href"); 2287 } 2288 break; 2289 } 2290} 2291 2292function hookUpQuickViews(el) { 2293 if (matchMedia('(min-width: 961px)').matches) { 2294 $(el).find(".btn-quickview > button:not(.bound961)").each(function () { 2295 $(this).removeClass("bound"); 2296 $(this).parent().removeClass("hide-quick-view"); 2297 $(this).off("click"); 2298 $(this).addClass("bound961"); 2299 2300 hookupQuickviewAda($(this)); 2301 2302 //Bloomreach Related Products 2303 $(this).find("[href$='#brqv']").on("click", function () { 2304 swapBRRelProdImage($(this)); 2305 }); 2306 2307 $(this).moby({ 2308 'modalClass': 'quickview', 2309 'ariaLabelText': 'Quick View', 2310 'onCompleteCallback': function (e) { 2311 2312 var $form = $(e).find('form'); 2313 if ($form.length === 0) { // fix latent bug - seems like related products quickview's e is "window" and .find from there doesn't pick up the QV form... 2314 $form = $(".moby-container.quickview.show").find('form'); 2315 } 2316 2317 validateAndInitQuickViewForm($form); 2318 autoselectAttributeIfSingle($(".attribute-select", $form).first()); 2319 } 2320 }); 2321 }); 2322 2323 $(el).find(".btn-quickview > button:not(.bound961)").each(function () { 2324 $(this).removeClass("bound"); 2325 $(this).parent().removeClass("hide-quick-view"); 2326 $(this).off("click"); 2327 $(this).addClass("bound961"); 2328 2329 hookupQuickviewAda($(this)); 2330 2331 //Bloomreach Related Products 2332 $(this).find("[href$='#brqv']").on("click", function () { 2333 swapBRRelProdImage($(this)); 2334 }); 2335 2336 $(this).moby({ 2337 'modalClass': 'quickview', 2338 'ariaLabelText': 'Quick View', 2339 'onCompleteCallback': function (e) { 2340 2341 var $form = $(e).find('form'); 2342 if ($form.length === 0) { // fix latent bug - seems like related products quickview's e is "window" and .find from there doesn't pick up the QV form... 2343 $form = $(".moby-container.quickview.show").find('form'); 2344 } 2345 2346 validateAndInitQuickViewForm($form); 2347 autoselectAttributeIfSingle($(".attribute-select", $form).first()); 2348 } 2349 }); 2350 }); 2351 2352 $(el).find(".add-on-quickview:not(.bound961)").each(function () { 2353 $(this).removeClass("bound"); 2354 $(this).off("click"); 2355 $(this).addClass("bound961"); 2356 $(this).moby({ 2357 'modalClass': 'quickview', 2358 'ariaLabelText': 'Quick View', 2359 'onCompleteCallback': function (e) { 2360 2361 var $form = $(e).find('form'); 2362 if ($form.length === 0) { // fix latent bug - seems like related products quickview's e is "window" and .find from there doesn't pick up the QV form... 2363 $form = $(".moby-container.quickview.show").find('form'); 2364 } 2365 2366 validateAndInitQuickViewForm($form); 2367 autoselectAttributeIfSingle($(".attribute-select", $form).first()); 2368 } 2369 }); 2370 }); 2371 } 2372 else { 2373 $(el).find(".btn-quickview > button:not(.bound)").each(function () { 2374 $(this).removeClass("bound961"); 2375 $(this).off("click"); 2376 $(this).parent().removeClass("hide-quick-view"); 2377 $(this).addClass("bound"); 2378 2379 hookupQuickviewAda($(this)); 2380 2381 if ($(this).attr("href").indexOf("#brqv") >= 0) { //Bloomreach Related Products 2382 $(this).on("click", function (e) { 2383 e.preventDefault(); 2384 var $divId = $(this).attr("href").substr($(this).attr("href").lastIndexOf('#') + 1); 2385 var $brQVDiv = $("div[id=" + $divId + "]"); 2386 var $brQVImg = $brQVDiv.find('img.brRelProd'); 2387 if ($brQVImg.length) { 2388 $brQVImg.attr('src', $brQVImg.attr('src').replace("/m/", "/e/")); 2389 } 2390 $("#quickview-mmenu .quickview").html($brQVDiv.html()); 2391 $("#quickview-mmenu").data("mmenu").open(); 2392 trapFocus($("#quickview-mmenu")); 2393 validateAndInitQuickViewForm($("#quickview-mmenu").find('form'));
2394 return false; 2395 }); 2396 } 2397 else { 2398 $(this).on("click", function (e) { 2399 e.preventDefault(); 2400 $.ajax({ 2401 url: $(this).attr('href'), 2402 type: 'GET', 2403 datatype: "html", 2404 success: function (result) { 2405 $("#quickview-mmenu .quickview").html(result); 2406 $("#quickview-mmenu").data("mmenu").open(); 2407 validateAndInitQuickViewForm($("#quickview-mmenu").find('form')); 2408 } 2409 }); 2410 return false; 2411 }); 2412 } 2413 }); 2414 2415 $(el).find(".btn-quickview > button:not(.bound)").each(function () { 2416 $(this).removeClass("bound961"); 2417 $(this).off("click"); 2418 $(this).parent().removeClass("hide-quick-view"); 2419 $(this).addClass("bound"); 2420 2421 hookupQuickviewAda($(this)); 2422 2423 if ($(this).attr("href").indexOf("#brqv") >= 0) { //Bloomreach Related Products 2424 $(this).on("click", function (e) { 2425 e.preventDefault(); 2426 var $divId = $(this).attr("href").substr($(this).attr("href").lastIndexOf('#') + 1); 2427 var $brQVDiv = $("div[id=" + $divId + "]"); 2428 var $brQVImg = $brQVDiv.find('img.brRelProd'); 2429 if ($brQVImg.length) { 2430 $brQVImg.attr('src', $brQVImg.attr('src').replace("/m/", "/e/")); 2431 } 2432 $("#quickview-mmenu .quickview").html($brQVDiv.html()); 2433 $("#quickview-mmenu").data("mmenu").open(); 2434 trapFocus($("#quickview-mmenu")); 2435 validateAndInitQuickViewForm($("#quickview-mmenu").find('form')); 2436 return false; 2437 }); 2438 } 2439 else { 2440 $(this).on("click", function (e) { 2441 e.preventDefault(); 2442 $.ajax({
2443 url: $(this).attr('href'), 2444 type: 'GET', 2445 datatype: "html", 2446 success: function (result) { 2447 $("#quickview-mmenu .quickview").html(result); 2448 $("#quickview-mmenu").data("mmenu").open(); 2449 validateAndInitQuickViewForm($("#quickview-mmenu").find('form')); 2450 } 2451 }); 2452 return false; 2453 }); 2454 } 2455 }); 2456 2457 $(el).find(".add-on-quickview:not(.bound)").each(function () { 2458 $(this).removeClass("bound961"); 2459 $(this).off("click"); 2460 $(this).addClass("bound"); 2461 $(this).on("click", function (e) { 2462 e.preventDefault(); 2463 $.ajax({ 2464 url: $(this).attr('href'), 2465 type: 'GET', 2466 datatype: "html", 2467 success: function (result) { 2468 $("#quickview-mmenu .quickview").html(result); 2469 $("#quickview-mmenu").data("mmenu").open(); 2470 validateAndInitQuickViewForm($("#quickview-mmenu").find('form')); 2471 } 2472 }); 2473 return false; 2474 }); 2475 }); 2476 } 2477} 2478 2479function hookupQuickviewAda(el) { 2480 var $this = $(el); 2481 2482 //ada compliance...if the quickview has focus make it visible 2483 $this.on('focusin', function () { 2484 $(this).parent().addClass("show"); 2485 }).on('focusout', function () { 2486 $(this).parent().removeClass("show"); 2487 }); 2488 2489 //ada compliance... hide all tab focused quick views when mousing over the parent anchor 2490 //this helps prevent a sticky quick view button 2491 $this.closest(".product-image").on("mouseover", function () { 2492 $("body").find(".products-grid .btn-quickview > button:visible").trigger("blur"); 2493 }); 2494 2495} 2496 2497function validateAndInitQuickViewForm(quickViewForm) { 2498 truncateQuickViewAdCopy(quickViewForm); 2499 quickViewForm.validate(); 2500 2501 //register Notify Me Modal trigger in case quick view is of a product on notify 2502 quickViewForm.find('.notifyBtn').find("a").moby({ 2503 'modalClass': 'giveaway-modal', 2504 'ariaLabelText': 'Notify Me', 2505 'onCompleteCallback': function () { 2506 } 2507 }); 2508 Gorilla.util.initForms(); 2509} 2510 2511//this function will de-parameterize a multi-value cookie to easily be able to retrieve a specific value 2512function deparamCookie(params) { 2513 var o = {}; 2514 if (!params) return o; 2515 var a = params.split('&'); 2516 for (var i = 0; i < a.length; i++) { 2517 var pair = a[i].split('='); 2518 o[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); 2519 } 2520 return o; 2521} 2522 2523//this function retrives a query string parameter value 2524function getQueryStringParam(name) { 2525 var url = window.location.href; 2526 name = name.replace(/[\[\]]/g, "\\$&"); 2527 var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), 2528 results = regex.exec(url); 2529 if (!results) return null; 2530 if (!results[2]) return ''; 2531 return decodeURIComponent(results[2].replace(/\+/g, " ")); 2532} 2533 2534//javascript format currency 2535function formatCurrency(value, locale, currency) { 2536 var formatter = new Intl.NumberFormat(locale, 2537 { 2538 style: 'currency', 2539 currency: currency, 2540 minimumFractionDigits: 2 2541 }); 2542 2543 return formatter.format(value); 2544} 2545 2546function padLeft(num, size) { //mimics c#'s string.PadLeft 2547 var s = num + ""; 2548 while (s.length < size) s = "0" + s; 2549 return s; 2550} 2551 2552function trapFocus(element) { 2553 var focusableEls = 2554 element.find( 2555 'a[href], button:not(.magic-thumbs-button-disabled,[tabindex="-1"],.i18n), textarea, input[type="button"], input[type="text"], input[type="radio"], input[type="checkbox"], select, [tabindex]:not([tabindex="-1"])'), 2556 firstFocusableEl = focusableEls.first()[0], 2557 lastFocusableEl = focusableEls.last()[0], 2558 TABKEYCODE = 9, 2559 ARROWLEFTCODE = 37, 2560 ARROWUPCODE = 38, 2561 ARROWRIGHTCODE = 39, 2562 ARROWDOWNCODE = 40; 2563
2564 if (firstFocusableEl != null) { firstFocusableEl.focus(); } 2565 2566 $(element).off('keydown').on('keydown', function (e) { 2567 // tab (no shift) or the right/down keys 2568 var next = e.key === 'ArrowRight' || e.keyCode === ARROWRIGHTCODE || e.key === 'ArrowDown' || e.keyCode === ARROWDOWNCODE || ((e.key === 'Tab' || e.keyCode === TABKEYCODE) && !e.shiftKey); 2569 // tab (with shift) or the left/up keys 2570 var prev = e.key === 'ArrowLeft' || e.keyCode === ARROWLEFTCODE || e.keyCode === 'ArrowUp' || e.keyCode === ARROWUPCODE || ((e.key === 'Tab' || e.keyCode === TABKEYCODE) && e.shiftKey); 2571 2572 if (!next && !prev) { 2573 return; 2574 } 2575 2576 if (next && document.activeElement === lastFocusableEl) { 2577 firstFocusableEl.focus(); 2578 e.preventDefault(); 2579 } 2580 if (prev && document.activeElement === firstFocusableEl) { 2581 lastFocusableEl.focus(); 2582 e.preventDefault(); 2583 } 2584 }); 2585} 2586 2587function initSGAccordian(openByDefault) { 2588 // wire up events 2589 $(document).on("click", ".sg-accordion-header", function () { 2590 $this = $(this); 2591 $this.toggleClass("active"); 2592 $this.next().slideToggle(250); // the very next element had better be the content... 2593 2594 if (($button = $(".sg-accordion-header-button", $this)).length > 0) { 2595 $button.attr("aria-expanded", $this.hasClass("active")); // A360/ADA -- set aria-expanded as appropriate 2596 } 2597 }); 2598 2599 $(document).on("click", "#accordion-controls-container #expand-all", function () { 2600 $(".sg-accordion-header").each(function (i, v) { // TODO: this selector is probably not specific enough, maybe pass the parent container in? :/ 2601 $this = $(this); 2602 $this.addClass("active"); 2603 2604 if (($button = $(".sg-accordion-header-button", $this)).length > 0) { 2605 $button.attr("aria-expanded", true); 2606 } 2607 }); 2608 2609 $(".sg-accordion-content").slideDown(); 2610 }); 2611 2612 $(document).on("click", "#accordion-controls-container #collapse-all", function () { 2613 $(".sg-accordion-header").each(function (i, v) { // TODO: this selector is probably not specific enough, maybe pass the parent container in? :/ 2614 $this = $(this); 2615 $this.removeClass("active"); 2616 2617 if (($button = $(".sg-accordion-header-button", $this)).length > 0) { 2618 $button.attr("aria-expanded", false); 2619 } 2620 }); 2621 $(".sg-accordion-content").slideUp(); 2622 }); 2623 2624 if (openByDefault) { 2625 // have all panels open by default 2626 $(".sg-accordion-header").addClass("active"); // TODO: this selector is probably not specific enough, maybe pass the parent container in? :/ 2627 $(".sg-accordion-content").show(); // need it fast! // TODO: this selector is probably not specific enough, maybe pass the parent container in? :/ 2628 } 2629 2630 // deal with some FAQ's specific A360/ADA things... Seems like this could be applied to all instances of our .sg-accordion-header, but limiting to the FAQs for now 2631 $("#faqsV3 .sg-accordion-header").each(function (i, v) { 2632 var $this = $(this); 2633 var $next = $this.next(); // the very next element had better be the content... 2634 2635 // generate and assign an id to the associated content block, if needed 2636 var nextId = $next.attr("id"); 2637 if (nextId == undefined) { 2638 nextId = "sgac-" + i; 2639 $next.attr("id", nextId); 2640 } 2641 2642 // add the aria- stuff to $this 2643 if (($button = $(".sg-accordion-header-button", $this)).length > 0) { 2644 $button.attr("aria-expanded", $this.hasClass("active")); 2645 $button.attr("aria-controls", nextId); 2646 } 2647 }); 2648} 2649 2650function processSlickProductSliders() { 2651 workSlickProductSliders++; 2652 if (workSlickProductSliders == numSlickProductSliders) { 2653 $(document).find(".btn-quickview > button").each(function () { 2654 $(this).removeClass("bound"); 2655 $(this).removeClass("bound961"); 2656 }); 2657 initResponsive(); 2658 workSlickProductSliders = 0; 2659 } 2660} 2661 2662//Gift card functions on shopping resources and my account 2663function addAccountGiftCard(cardNum) {
2664 AjaxJsonPostWrapper.ajaxRoute("giftcard", "GiftCardAddToAccount", { cardNum: cardNum }, 2665 function (result) { 2666 $("#gift-card-lookup-tables").html(result.giftCardLookupHtml); 2667 }); 2668} 2669function removeAccountGiftCard(cardNum) { 2670 AjaxJsonPostWrapper.ajaxRoute("giftcard", "giftcardremovefromaccount", { cardNum: cardNum }, 2671 function (result) { 2672 $("#gift-card-lookup-tables").html(result.giftCardLookupHtml); 2673 }); 2674} 2675 2676function textInputDigitsOnly(keyCode) { // call from within a keypress (not key down) event, maxlength not enforced here, use html attribute 2677 2678 if (keyCode == 8 || keyCode == 127) { // backspace, delete, probably don't make it here but let them work if they do 2679 return true; 2680 } 2681 2682 if (keyCode >= 48 && keyCode <= 57) { // numbers 2683 return true; 2684 } 2685 2686 return false; // don't allow keystroke to register 2687 2688} 2689 2690function enableTabIndicators(e) { 2691 if (e.keyCode === 9) { // keyboard tabber detected! 2692 document.body.classList.add('user-tab-detected'); 2693 window.removeEventListener('keydown', enableTabIndicators); 2694 } 2695} 2696 2697window.addEventListener('keydown', enableTabIndicators); 2698 2699function setLeftNavActiveLinkProps() { 2700 $("#left-navigation li.active a").each(function (i, v) { // had better be one and only one. if not, last one wins 2701 var $activeAnchor = $(this); 2702 $activeAnchor.attr("aria-current", "page"); 2703 $activeAnchor.closest("aside#left-navigation").attr("aria-label", $activeAnchor.text() + " navigation"); // I asked / double-checked that this should be "page name" vs. "layout name" and A360 was pretty adamant 2704 }); 2705} 2706 2707function hide2ndImageOnPDP() { 2708 $("#main-image.MagicZoom figure div.mz-lens img").addClass("display-none"); 2709} 2710 2711//focus on first focusable element in the main page container 2712function focusOnFirstEl(container) { 2713 $(container).find(":focusable").first().focus(); 2714} 2715 2716function autoselectAttributeIfSingle($ddl) { 2717 2718 if ($ddl.length === 0 || $ddl.hasClass("auto-select")) 2719 return; 2720 2721 var $opts = $("option", $ddl); 2722 if ($opts.length === 2) { // "Select an Option" + 1 value 2723 $opts.prop("selected", false); // unset them all 2724 $($opts[1]).prop("selected", "selected"); // make the first one selected 2725 $ddl.change(); // trigger the change event 2726 } 2727} 2728 2729//this sends the user straight through to the address page if called on or before bridge page 2730function initPayPalCheckout() { 2731 2732 var pp = new PayPal(); 2733 pp.onPayPalSet = function (pp) { 2734 if (pp.payload.details.countryCode !== "US" || pp.payload.details.shippingAddress.countryCode !== "US") { 2735 $("#paypal-messages").html("PayPal is not currently available for customers outside the US."); 2736 return false; 2737 } 2738 2739 var ppData = { 2740 Email: pp.payload.details.email, 2741 PayerId: undefined, //let backend look it up 2742 Nonce: pp.payload.nonce, 2743 DeviceData: pp.deviceData 2744 } 2745 2746 var address = { 2747 FirstName: pp.payload.details.firstName, 2748 LastName: pp.payload.details.lastName, 2749 EmailAddress: pp.payload.details.email, 2750 Address1: pp.payload.details.shippingAddress.line1, 2751 Address2: pp.payload.details.shippingAddress.line2, 2752 City: pp.payload.details.shippingAddress.city, 2753 State: pp.payload.details.shippingAddress.state, 2754 Zip: pp.payload.details.shippingAddress.postalCode, 2755 Country: pp.payload.details.shippingAddress.countryCode, 2756 DayPhone: pp.payload.details.phone 2757 } 2758 2759 if (address.State && address.State.length > 2) { 2760 var self = this; 2761 self.logError("PayPal Value Error - State too Large - Email: " + address.EmailAddress + " - State: " + address.State + " - City: " + address.City); 2762 address.State = ""; 2763 } 2764 2765 return AjaxJsonPostWrapper.ajaxRoute("authenticate", "paypalcheckoutlogin", { PayPal: ppData, Address: address}, function(result) { 2766 if (result.success) { 2767 //todo just go to /checkout after a/b test is done 2768 return window.location.replace("/checkout"); 2769 } else { 2770 $("#paypal-messages").html("We are unable to accept PayPal at this time. Please try again or use one of our other checkout methods."); 2771 return false; 2772 } 2773 }); 2774 }; 2775 2776} 2777 2778function initializeSlider(id) { // used to be in DynamicDataScript.cshmlt but we want to use it in angularized ViewCart as well 2779 //Init default sliders, use data api to set items count and margins 2780 if (($slider = $(id + ' .products-grid')).length) { 2781 if (!$slider.hasClass('slick-initialized')) { 2782 $slider.slick({ 2783 accessibility: true, 2784 dots: false, 2785 arrows: true, 2786 slidesToShow: 4, 2787 slidesToScroll: 4, 2788 infinite: false, 2789 lazyLoad: 'ondemand', 2790 prevArrow: '<span class="sg-slick-prev" role="button" aria-label="Previous" tabindex="0">
2790 <img class="sg-carousel" src="/images/product/icon-image-left.svg"> </span>', 2791 nextArrow: '<span class="sg-slick-next" role="button" aria-label="Next" tabindex="0"> <img class="sg-carousel" src="/images/product/icon-image-right.svg"> </span>', 2792 responsive: [ 2793 { 2794 breakpoint: 1060, 2795 settings: { 2796 slidesToShow: 3, 2797 slidesToScroll: 3, 2798 arrows: true, 2799 dots: true 2800 } 2801 }, 2802 { 2803 breakpoint: 768, 2804 settings: { 2805 slidesToShow: 2, 2806 slidesToScroll: 2, 2807 arrows: true, 2808 dots: true 2809 } 2810 }, 2811 { 2812 breakpoint: 480, 2813 settings: { 2814 slidesToShow: 1, 2815 slidesToScroll: 1, 2816 arrows: true, 2817 dots: true 2818 } 2819 } 2820 ] 2821 }); 2822 numSlickProductSliders++; 2823 $slider.on("breakpoint", function (event, slick, breakpoint) { 2824 event.preventDefault(); 2825 processSlickProductSliders(); 2826 }); 2827 } 2828 } 2829} 2830 2831function submitArticleRating(stars, id) { 2832 return AjaxJsonPostWrapper.ajaxRoute('blogapi', 'ratearticle', { starRating: stars, webPageId: id }, function (result) { 2833 $(".article-ratings-input").hide(); 2834 $(".article-ratings-title").html("<span>Thank you for rating this article.</span>"); 2835 }); 2836}; 2837var altImagesSlider; 2838var $altImagesChangeSlider = false; 2839var $initClubAccordions = true; 2840var $initFooterLinksAccordion = true; 2841var promoCarouselTimeout; 2842var numSlickProductSliders = 0; 2843var workSlickProductSliders = 0; 2844var initMyAccountBackLink = true; 2845var lastFocus; 2846 2847domReady(function() { 2848 // Readied 2849 var w = $(window).width(); 2850 initResponsive(); 2851 2852 var resizeHandler = function () { 2853 $(window).on("resize", function () { 2854 if (w != $(window).width()) { 2855 initResponsive(); 2856 w = $(window).width(); 2857 delete w; 2858 } 2859 }); 2860 } 2861 //we were losing the resize event listener using $(window).resize due to an mmenu collision 2862 $(function () { 2863 window.addEventListener('resize', resizeHandler, false); 2864 }); 2865}); 2866 2867function initResponsive() { 2868 2869 //fix for back button issue with mobile menu in IE... IE doesnt support the library's use of window.history.back() 2870 //this is unbound then bound as the menu can be created/destroyed based on breakpoint shifts 2871 var closeEvent = function () { 2872 if (($currentMenu = $('.mm-menu.mm-current.mm-menu_opened')).length) { 2873 $currentMenu.data("mmenu").close(); 2874 lastFocus.focus(); 2875 } 2876 } 2877 $(document).off("click", "a.mm-btn, a.mm-title", closeEvent).on("click", "a.mm-btn, a.mm-title", closeEvent); 2878 2879 if (matchMedia('(min-width:961px)').matches) { 2880 //Large screens, full menu 2881 $('.shop').find('.fly-out').html("<h4><span>Loading...</span></h4>"); 2882 $('.shop').find('.fly-out').addClass('auto-height'); 2883 } 2884 2885 if (matchMedia('(min-width: 961px)').matches) { 2886 //site wide promo message banner 2887 if ($('#site-wide-promos').length) { 2888 destroySiteWidePromoSlickSlider(); 2889 } 2890 } else { 2891 //site wide promo message carousel 2892 if ($('#site-wide-promos').length) { 2893 createSiteWidePromoSlickSlider(); 2894 } 2895 } 2896 2897 if (matchMedia('(min-width: 961px)').matches) { 2898 //reset the nav cover, may have been manipulated if they went down to mobile and then back up to desktop 2899 $(".nav-cover-x").toggleClass("nav-cover nav-cover-x"); 2900 2901 if ($("#mm-nav").length) { //destroy mobile controls if orientation changed 2902 $("#mm-nav").gorillaAccordion('unset'); 2903 $("#mm-nav").find('.drop-down').gorillaAccordion('unset'); 2904 destroyMmenu(); 2905 } 2906 2907 if (($nav = $('#nav')).length) { 2908 //init main nav 2909 if (!$nav.attr("data-dropit")) { 2910 $nav.DropIt({ 2911 'triggerSelector': 'li.level-top', 2912 'menuSelector': '.drop-down', 2913 'speed': 0, 2914 'delay': 0, 2915 'showCover': true 2916 }); 2917 } 2918 2919 if (!$nav.find('.shop ul.level0').attr('data-dropit')) { 2920 $nav.find('.shop ul.level0').DropIt({ 2921 'triggerSelector': '> li', 2922 'menuSelector': '.fly-out', 2923 'speed': 0, 2924 'delay': 200, 2925 'onHover': function (elm) { 2926 var $this = $(elm), 2927 busy = false; 2928 2929 if (busy || $this.data('loaded')) { 2930 return; 2931 } 2932 2933 $.ajax({
2934 url: $this.data('menu'), 2935 type: 'post', 2936 dataType: 'html', 2937 beforeSend: function () { 2938 busy = true 2939 } 2940 }) 2941 .done(function (html) { 2942 $this.find('> a').after(html).end().data('loaded', true); 2943 $nav.find('ul.level0').DropIt('showMenu', $this.find('.fly-out')); 2944 }) 2945 .always(function () { 2946 busy = false; 2947 }) 2948 } 2949 }); 2950 } 2951 } 2952 //Quick View 2953 2954 hookUpQuickViews(document); 2955 2956 //footer accordion unset 2957 if (($accordion = $('#footer').find('.accordion')).length) { 2958 $accordion.gorillaAccordion('unset'); 2959 } 2960 $initFooterLinksAccordion = true; 2961 2962 $('body').removeClass('mobileVideo'); 2963 2964 } else { 2965 2966 //mobile navigation init 2967 if (($nav = $('#nav')).length) { 2968 $nav.DropIt('unset'); 2969 $nav.find('ul.level0').DropIt('unset'); 2970 } 2971 2972 //remove the nav cover if they ever hit this breakpoint, it can cause an issue with a tablet in landscape mode 2973 $(".nav-cover").hide().toggleClass("nav-cover nav-cover-x"); 2974 2975 //mobile splash nav menu (for gift guide template) 2976 if (($splashNav = $("#splashNav")).length) { 2977 $("#splashNav-toggle").on("click", function (e) { 2978 e.preventDefault(); 2979 lastFocus = document.activeElement; 2980 $splashNav.data("mmenu").open(); 2981 }); 2982 $splashNav.mmenu({ 2983 extensions: ["pagedim-black", "position-right", "position-front", "theme-white"], 2984 backButton: { close: false }, 2985 navbar: { title: "" }, //needed to hide the default title menu 2986 navbars: [{ position: "top", content: "<a class='mm-title' href='#' onclick='event.preventDefault();'>Menu</a><a class='mm-btn' href='#' onclick='event.preventDefault();' role='button'><span class='mmenu-close'></span><span class='sr-only'>close menu</span></a>" }], 2987 onClick: { close: false, setSelected: false }, 2988 slidingSubmenus: false 2989 },{ 2990 //configuration 2991 offCanvas: { 2992 pageSelector: "#sg-page-wrapper" 2993 } 2994 }); 2995 $("#splashNav-toggle").on("click", ".mm-navbars_top", function (e) { 2996 $("#splashNav-toggle").data("mmenu").close(); 2997 lastFocus.focus(); 2998 }); 2999 } 3000 3001 //filter nav dropdown init 3002 if ($("#mm-filters-menu").length === 0) { 3003 if (($filters = $('aside.filters:not(.noMobileDisplay)')).length) { 3004 $("#filter-toggle").on("click", function (e) { 3005 e.preventDefault(); 3006 lastFocus = document.activeElement; 3007 $("#mm-filters-menu").data("mmenu").open(); 3008 }); 3009 $filters.mmenu({ 3010 extensions: ["pagedim-black", "position-right", "position-front", "theme-white"], 3011 backButton: { close: false }, 3012 navbar: { title: "" }, //needed to hide the default title menu 3013 navbars: [ 3014 { 3015 position: "top", 3016 content: "<a class='mm-title' href='#' onclick='event.preventDefault();'>Filter</a><a class='mm-btn' href='#' onclick='event.preventDefault();' role='button'><span class='mmenu-close'></span><span class='sr-only'>close menu</span></a>" 3017 } 3018 ], 3019 onClick: { close: false, setSelected: false }, 3020 slidingSubmenus: false 3021 }, 3022 { 3023 //configuration 3024 clone: true, 3025 offCanvas: { 3026 pageSelector: "#sg-page-wrapper" 3027 } 3028 3029 }).on("init", function () { 3030 //we dont want nested elements to be submenus in this particular panel 3031 $("#mm-filters-menu").find('ol.mm-listview').removeClass('mm-listview'); 3032 $("#mm-filters-menu").find('ul.mm-listview').removeClass('mm-listview'); 3033
3034 // the menu gets cloned with new mm- id's for the filter checkboxes, we need to manually adjust the (invisible, used by screen readers/WAVE extension) labels 3035 $("#mm-filters-menu label[for^=dimSelected]").attr("for", function (i, val) { return "mm-" + val; }); 3036 3037 }).trigger("init"); 3038 $("#mm-filters-menu").on("click", ".mm-navbars_top", function (e) { 3039 $("#mm-filters-menu").data("mmenu").close(); 3040 lastFocus.focus(); 3041 }); 3042 3043 if (($accordion = $('#mm-filters-menu').find('.dim-accordion')).length) { 3044 $accordion.gorillaAccordion({ 3045 trigger: 'a.trigger', 3046 container: '.content', 3047 containerInner: '> ul' 3048 }); 3049 } 3050 3051 //same idea as in ProductList.cshtml onReady: ensure the auto opened facet accordions are properly init'd 3052 $("#mm-filters-menu .dim-accordion a.open").each(function () { 3053 var $this = $(this); 3054 $this.closest(".dim-accordion").gorillaAccordion('open', $this); 3055 }); 3056 } 3057 } 3058 3059 //footer accordion init 3060 if (($accordion = $('#footer').find('.accordion')).length) { 3061 if ($initFooterLinksAccordion) { 3062 $accordion.gorillaAccordion({ 3063 trigger: 'h2', 3064 container: '.content', 3065 containerInner: '> ul' 3066 }); 3067 $initFooterLinksAccordion = false; 3068 } 3069 } 3070 3071 //filter nav dropdown init 3072 if ($("#mm-left-navigation").length === 0) { 3073 if (($leftMenu = $('#left-navigation')).length) { 3074 $("#col-left-menu-toggle").on("click", function (e) { 3075 e.preventDefault(); 3076 lastFocus = document.activeElement; 3077 $("#mm-left-navigation").data("mmenu").open(); 3078 trapFocus($("#mm-left-navigation")); 3079 }); 3080 $leftMenu.mmenu({ 3081 extensions: ["pagedim-black", "position-right", "position-front", "theme-white"], 3082 backButton: { close: false }, 3083 navbar: { title: "" }, //needed to hide the default title menu 3084 navbars: [{ position: "top", content: "<a class='mm-title' href='#' onclick='event.preventDefault();'>Menu</a><a class='mm-btn' href='#' onclick='event.preventDefault();' role='button'><span class='mmenu-close'></span><span class='sr-only'>close menu</span></a>" }], 3085 onClick: { close: false, setSelected: false }, 3086 slidingSubmenus: false 3087 }, { 3088 //configuration 3089 clone: true, 3090 offCanvas: { 3091 pageSelector: "#sg-page-wrapper" 3092 } 3093 }); 3094 $("#mm-left-navigation").on("click", ".mm-navbars_top", function (e) { 3095 $("#mm-left-navigation").data("mmenu").close(); 3096 lastFocus.focus(); 3097 }); 3098 } 3099 } 3100 3101 $(".btn-quickview").find("button").each(function () { 3102 $(this).parent().removeClass("hide-quick-view"); 3103 if ($(this).moby.length) { 3104 $(this).moby('reset'); 3105 } 3106 }); 3107 3108 //rebind quickview to mmenu slideout 3109 if (($quickviewSlideout = $("#quickview-mmenu")).length) { 3110 hookUpQuickViews(document); 3111 3112 $quickviewSlideout.mmenu({ 3113 extensions: ["pagedim-black", "position-right", "position-front", "theme-white"], 3114 backButton: { close: false }, 3115 navbar: { title: "" }, //needed to hide the default title menu 3116 navbars: [{ position: "top", content: "<a class='mm-title' href='#' onclick='event.preventDefault();'>Close</a><a class='mm-btn' href='#' onclick='event.preventDefault();' role='button'><span class='mmenu-close'></span><span class='sr-only'>
3116close menu</span></a>" }], 3117 onClick: { close: false, setSelected: false }, 3118 slidingSubmenus: false 3119 }, { 3120 //configuration 3121 offCanvas: { 3122 pageSelector: "#sg-page-wrapper" 3123 } 3124 }); 3125 $("#quickview-mmenu").on("click", ".mm-navbars_top", function (e) { 3126 $("#quickview-mmenu").data("mmenu").close(); 3127 lastFocus.focus(); 3128 }); 3129 } 3130 3131 $('body').addClass('mobileVideo'); 3132 3133 // init new sticky back link in My Account area 3134 if (($myAccountBackLink = $('.my-account-back-to')).length && initMyAccountBackLink) { 3135 initBackToMyAccount($myAccountBackLink); 3136 } 3137 } 3138 3139 if (matchMedia('(min-width: 731px) and (max-width: 960px)').matches) { 3140 3141 } 3142 if (matchMedia('(min-width: 480px) and (max-width: 730px)').matches) { 3143 $('body').removeClass('mobile'); 3144 } 3145 3146 if (matchMedia('(min-width: 480px) and (max-width: 560px)').matches) { 3147 $('body').removeClass('mobile'); 3148 } 3149 3150 if (matchMedia('(min-width: 300px) and (max-width: 479px)').matches) { 3151 $('body').addClass('mobile'); 3152 } 3153 3154 if (matchMedia('(max-width: 680px)').matches) { 3155 3156 bindMobileSearch(); 3157 //we may have an issue with events being bound multiple times with the dynamic data stuff calling initResponsive again 3158 $(document).off("click", "#search-trigger").on("click", "#search-trigger", function (e) { 3159 e.preventDefault(); 3160 var $searchDiv = $(".site-search.mobile-search"); 3161 var $searchIcon = $(".mobile-trigger.search .search-icon"); 3162 var $searchInput = $(".site-search.mobile-search .input-text") 3163 if ($searchDiv.hasClass("closed")) { 3164 $searchDiv.slideToggle("fast").removeClass("closed").addClass("open"); 3165 $searchIcon.addClass("open"); 3166 $searchInput.focus(); 3167 } else if ($searchDiv.hasClass("open")) { 3168 $searchDiv.slideToggle("fast").removeClass("open").addClass("closed"); 3169 $searchIcon.removeClass("open"); 3170 $searchInput.blur(); 3171 } 3172 }); 3173 3174 $(".site-header .nav-container div.secondary").removeClass("header-flex-parent"); 3175 3176 $('#main').find('.cms-main [data-respond], .my-account-main [data-respond]').each(function() { 3177 var $_el = $(this); 3178 switch ($_el.data('respond')) { 3179 case 'accordion': 3180 $_el.addClass('accordion').gorillaAccordion({ 3181 trigger: '.trigger', 3182 container: '.content', 3183 containerInner: '> .inner' 3184 }); 3185 break; 3186 } 3187 }); 3188 3189 $('#in-stock-mobile').each(function () { 3190 this.style.setProperty('display', 'inline', 'important'); 3191 this.style.setProperty('font-size', '18px'); 3192 }); 3193 3194 $("#tabs").exploder({ 3195 container: "#Details", 3196 elements: ".inner-wrap", 3197 buttonIndex: 0, 3198 buttonText: "Read More" 3199 }); 3200 3201 $('#main').find('.family-group').each(function () { 3202 var $_mfh = $(this).find('.mobileFgHeader'); 3203 $(this).find('.colorswatches').insertAfter($_mfh); 3204 }); 3205 3206 } else { 3207 $(".site-header .nav-container div.secondary").addClass("header-flex-parent"); 3208 3209 $('#main').find('.cms-main [data-respond], .my-account-main [data-respond]').each(function () { 3210 var $_el = $(this); 3211 switch ($_el.data('respond')) { 3212 case 'accordion': 3213 $_el.removeClass('accordion').gorillaAccordion('unset'); 3214 break; 3215 } 3216 }); 3217 3218 $("#tabs").exploder('unset'); 3219 3220 $('#main').find('.family-group').each(function () { 3221 var $_fgi = $(this).find('.family-group-image'); 3222 $(this).find('.colorswatches').appendTo($_fgi); 3223 }); 3224 } 3225 3226 if (matchMedia('(min-width: 681px)').matches) { 3227 //mobile search to default state for shifting breakpoints 3228 $(".site-search.mobile-search").removeClass("open").addClass("closed").attr("style", ""); 3229 $(".mobile-trigger.search .search-icon").removeClass("open"); 3230 } 3231 3232 if (matchMedia('(max-width: 960px)').matches) { 3233 if ($("#main-scroll-images").length && $("#main-scroll-horizontal .slick-slide").length == 0) { 3234 if (!$altImagesChangeSlider) { 3235 $altImagesChangeSlider = true; 3236 createHorizontalProductImages(); 3237 scrollToSelectedProductImage(); 3238 setTimeout(function () { 3239 $altImagesChangeSlider = false; 3240 }, 10); 3241 } 3242 } 3243 } 3244 3245 if (matchMedia('(min-width: 681px) and (max-width: 960px)').matches) { 3246 bindTabletSearch(); 3247 } 3248 3249 if (matchMedia('(min-width:961px)').matches) { 3250 3251 bindDesktopSearch(); 3252 3253 if ($("#main-scroll-images").length && $("#main-scroll-vertical .slick-slide").length == 0) { 3254 if (!$altImagesChangeSlider) { 3255 $altImagesChangeSlider = true; 3256 createVerticalProductImages(); 3257 scrollToSelectedProductImage(); 3258 setTimeout(function () { 3259 $altImagesChangeSlider = false; 3260 }, 10); 3261 } 3262 } 3263 } 3264 3265 if ($(".product-list .products-grid").length) setEqualHeightPlp(); 3266 3267} 3268 3269function setEqualHeightPlp() { 3270 const items = Array.from(document.querySelectorAll(".product-list .products-grid > .product-tile"));
3271 const baseOffset = items[0].offsetTop; 3272 const breakIndex = items.findIndex(function (item) { return item.offsetTop > baseOffset; }); 3273 const chunk = (breakIndex === -1 ? items.length : breakIndex); 3274 3275 if (chunk === 1) { 3276 $(items).find('.product-name, .price-box, .rating-box, .starting-at').css({ 'min-height': '0' }); 3277 return false; 3278 } 3279 3280 const subsets = []; 3281 for (var i = 0; i < items.length; i += chunk) { 3282 subsets.push(items.slice(i, i + chunk)); 3283 } 3284 3285 return subsets.forEach(function (subset) { 3286 const $subset = $(subset); 3287 const newHeight = Math.max.apply(null, $subset.find(".new").map(function () { return $(this).height(); }).get()); 3288 const nameHeight = Math.max.apply(null, $subset.find(".product-name").map(function () { return $(this).height(); }).get()); 3289 const priceHeight = Math.max.apply(null, $subset.find(".price-box").map(function () { return $(this).height(); }).get()); 3290 const startingAt = Math.max.apply(null, $subset.find(".starting-at").map(function () { return $(this).height(); }).get()); 3291 3292 $subset.find(".new").css({ "min-height": newHeight }); 3293 $subset.find(".product-name").css({ "min-height": nameHeight }); 3294 $subset.find(".price-box").css({ "min-height": priceHeight }); 3295 $subset.find(".starting-at").css({ "min-height": startingAt }); 3296 }); 3297} 3298 3299function getUniqueKeys(request, response) 3300{ 3301 var escapeTerm = $('<div/>').text(request.term).html(); 3302 var fullSuggestAhead = getSuggestAheadTerms(escapeTerm); 3303 var fullTerms = fullSuggestAhead.split('|'); 3304 var uniqueKeys = []; 3305 $.each(fullTerms, function (i, el) { 3306 var str = el.trim(); 3307 if ($.inArray(str, uniqueKeys) == -1) uniqueKeys.push(str); 3308 }); 3309 return uniqueKeys; 3310} 3311 3312function highlightSearchedTerm($elem) 3313{ 3314 var acData = $elem.data('ui-autocomplete'); 3315 acData.menu.element.find('li').each(function () { 3316 var container = $("div", $(this)); // ui-autocomplete now has a div inside the li wrapping the words 3317 var keywords = acData.term.split(' ').join('|'); 3318 container.html(container.html().replace(new RegExp("(" + keywords + ")", "gi"), '<span class="highlight">$1</span>')); 3319 }); 3320} 3321 3322function destroySlider() { 3323 if (altImagesSlider != undefined && altImagesSlider != null) { 3324 altImagesSlider.destroySlider(); 3325 } 3326} 3327 3328function destroyMmenu() { 3329 $("div#mm-nav").remove(); 3330 $("aside#mm-filters-menu").remove(); 3331 $("div#mm-left-navigation").remove(); 3332 3333 $("#filter-toggle").off("click"); 3334 $("#col-left-menu-toggle").off("click"); 3335} 3336 3337function createSiteWidePromoSlickSlider() { 3338 var $ss = $("#site-wide-promos"); 3339 if (!$ss.hasClass('slick-initialized') && !$ss.hasClass("checkout-promo")) { 3340 $ss.slick({ 3341 slidesToShow: 1, 3342 slidesToScroll: 1, 3343 dots: true, 3344 appendDots: $('#promoBannerDots'), 3345 arrows: false, 3346 infinite: true, 3347 autoplay: true, 3348 autoplaySpeed: 5000 3349 }); 3350 } 3351} 3352 3353function destroySiteWidePromoSlickSlider() { 3354 var $ss = $("#site-wide-promos"); 3355 if ($ss.hasClass('slick-initialized')) { 3356 $ss.slick('unslick'); 3357 } 3358} 3359 3360function bindMobileSearch() { 3361 var $searchMobile = $("#searchMobile"); 3362 if ($searchMobile.data("ui-autocomplete") != undefined) { 3363 $searchMobile.autocomplete("destroy"); 3364 } 3365 3366 $searchMobile.autocomplete({ 3367 appendTo: "#searchSuggestionsMobile", 3368 source: function (request, response) { 3369 getSuggestAheadTerms(request, response); 3370 }, 3371 minLength: 3, 3372 delay: 200, 3373 maxItems: 5, 3374 3375 select: function (event, ui) { 3376 $searchMobile.val(ui.item.label); 3377 $("#mobilekform").submit(); 3378 }, 3379 3380 open: function (event, ui) { 3381 highlightSearchedTerm($(this)); 3382 } 3383 }); 3384} 3385 3386function bindTabletSearch() { 3387 if ($("#k").data("ui-autocomplete") != undefined) { 3388 $("#k").autocomplete("destroy"); 3389 } 3390 3391 $("#k").autocomplete({ 3392 appendTo: "#searchSuggestions", 3393 source: function (request, response) { 3394 getSuggestAheadTerms(request, response); 3395 }, 3396 minLength: 3, 3397 delay: 200, 3398 maxItems: 10, 3399 3400 select: function (event, ui) { 3401 $("#k").val(ui.item.label); 3402 $("#kform").submit(); 3403 }, 3404 3405 open: function (event, ui) { 3406 highlightSearchedTerm($(this)); 3407 }, 3408 });
3409} 3410 3411function bindDesktopSearch() { 3412 if ($("#k").data("ui-autocomplete") != undefined) { 3413 $("#k").autocomplete("destroy"); 3414 } 3415 3416 $("#k").autocomplete({ 3417 appendTo: "#searchSuggestions", 3418 source: function (request, response) { 3419 getSuggestAheadTerms(request, response); 3420 }, 3421 minLength: 3, 3422 delay: 200, 3423 maxItems: 10, 3424 3425 response: function (event, ui) { 3426 $("#searchProducts").css({ display: 'block' }); 3427 }, 3428 3429 select: function (event, ui) { 3430 $("#k").val(ui.item.label); 3431 3432 $("#kform").submit(); 3433 }, 3434 3435 close: function (event, ui) { 3436 event.preventDefault(); 3437 }, 3438 3439 focus: function (event, ui) { 3440 3441 }, 3442 3443 open: function (event, ui) { 3444 highlightSearchedTerm($(this)); 3445 } 3446 }); 3447 3448} 3449 3450function showHideSuggestAhead() { 3451 setTimeout(function () { 3452 if ($("#searchProducts :focus").length === 0) { 3453 $("#searchProducts").css({ display: 'none' }); 3454 } 3455 }, 200); 3456} 3457 3458function initBackToMyAccount($myAccountBackLink) { 3459 // calc the scrollPoint amount in case link is at different spots on various pages 3460 // my location - 90px ("within 14px" of the header, per spec -- happens to be exactly where the words end up, so it feels "locked in") 3461 var spXY = $myAccountBackLink.offset(); 3462 var sp = spXY.top - 90; 3463 $myAccountBackLink.headtacular({ scrollPoint: sp }) 3464 // MIGHT NEED TO ENHANCE THE headtacular PLUGIN TO ALLOW UNSET-ING, 3465 // if we care about that it's left enabled after they go from a small window to a large window 3466 // per Steve, at this time we don't 3467 3468 initMyAccountBackLink = false; // only want to hook up to the scroll event one time 3469}; 3470//Notify Me Modal 3471//$('.notifyBtn').find("a").moby({ 3472// //'modalClass': 'giveaway-modal notifyMeModal', 3473// 'ariaLabelText': 'Notify Me', 3474// 'bodyClose': true, 3475// 'keyActions': true, 3476// 'onCompleteCallback': function () { 3477// setTimeout(function () { 3478// trapFocus($(".notifyMeModal")); 3479// }, 500); 3480// }, 3481// 'onBeforeCloseCallback': function () { 3482// //$('.moby-container.notifyMeModal').removeClass('notifyMeModalSubmit'); 3483// //$('.moby-container.notifyMeModal .moby-close img').remove(); 3484// } 3485//}); 3486 3487//****************************product functions*********************************** 3488 3489//get's all forms from within an element that has the class sent in the wrapperClass param 3490//then serializes each form into a ProductBase and builds up an array of all of them and submits 3491function addItemsToCart(wrapperClass) { 3492 var myArray = []; 3493 $('.' + wrapperClass).find('form').each(function () { 3494 var myData = AjaxJsonPostWrapper.getFormData(this); 3495 myArray.push(myData); 3496 }); 3497 return AjaxJsonPostWrapper.ajaxRoute('cart', 'addtocart', { data: myArray }, function (result) { 3498 var itemsAdded = false; 3499 3500 for (var i = result.inventoryInfo.length - 1; i > -1; i--) { 3501 var item = result.inventoryInfo[i]; 3502 if (item.SellAction != 'X' && item.SellAction != 'N') 3503 { 3504 //remove the div associated with this item as it was added to the cart. 3505 $('#quickOrderItems').find('form')[i].remove(); 3506 itemsAdded = true; 3507 } 3508 } 3509 if (itemsAdded == true) //then display cart drop down 3510 { 3511 updateCartSummary(); 3512 var div = $('#tealiumAjax'); 3513 if (typeof div !== 'undefined') { 3514 div.empty(); 3515 div.append(result.tealium); 3516 } 3517 } 3518 if (result.alertMsg != "") 3519 alert(result.alertMsg); 3520 }); 3521} 3522 3523function addItemToCart(btn) { 3524 var myArray = []; //create an array, although we are only going to pass one item in it 3525 var myData = AjaxJsonPostWrapper.getFormData($(btn).closest('form')); 3526 myArray.push(myData); 3527 doAddToCartSingleItem(myArray);
3528} 3529 3530function addItemToCartCustom(itemId, promoCode, color, size, qty, personalize, description) { 3531 //TODO: Figure out how to serialize this data into a Json object of list<productbase> so we can send it in through the existing code 3532 var cartItem = { ID: itemId, PromoCode: promoCode, ColorCode: color, SizeCode: size, Quantity: qty, IsPersonalized: personalize }; 3533 var myArray = []; //create an array, although we are only going to pass one item in it 3534 myArray.push(cartItem); 3535 doAddToCartSingleItem(myArray); 3536} 3537 3538function doAddToCartSingleItem(data) { 3539 return AjaxJsonPostWrapper.ajaxRoute('cart', 'addtocart', { data: data }, function (result) { 3540 if (result.inventoryInfo[0].SellAction == "N") 3541 notifyMe(data.ID, data.PromoCode, data.Name); 3542 else if (result.inventoryInfo[0].SellAction == "X") 3543 alert(result.inventoryInfo[0].Message); 3544 else { 3545 if (result.inventoryInfo[0].Message != "In Stock") 3546 alert(result.inventoryInfo[0].Message); 3547 $(window).scrollTop(0); 3548 updateCartSummary(); 3549 var div = $('#tealiumAjax'); 3550 if (typeof div !== 'undefined') { 3551 div.empty(); 3552 div.append(result.tealium); 3553 } 3554 } 3555 }); 3556} 3557 3558function getNextProductOption(dd, updateField, clearWaist, clearSize, clearColor) { 3559 var $form = $(dd).closest('form'); 3560 //clear out any of the other drop downs below it 3561 if (clearWaist) { 3562 $form.find('#WaistCode').val(""); 3563 $form.find('#WaistCode').prop('disabled', true); 3564 $form.find('#WaistCode').customSelect('updateText'); 3565 } 3566 if (clearSize) { 3567 $form.find('#SizeCode').val(""); 3568 $form.find('#SizeCode').prop('disabled', true); 3569 $form.find('#SizeCode').customSelect('updateText'); 3570 } 3571 if (clearColor) { 3572 $form.find('#ColorCode').val(""); 3573 $form.find('#ColorCode').prop('disabled', true); 3574 $form.find('#ColorCode').customSelect('updateText'); 3575 } 3576 //reset buttons in case they had been modified 3577 $form.find('.addToCartButtonDiv').show(); 3578 $form.find('.notifyMeButtonDiv').hide(); 3579 3580 if ($form.hasClass("quickview-form")) { 3581 $form.find('.stock-note').text(" "); 3582 } else { 3583 $('.stock-note').text(" "); 3584 } 3585 3586 var itemId = $form.find('input[id=ID]').val(); 3587 3588 var prodDefData = getProductDefaultData(itemId); 3589 3590 checkCompanionProducts($(dd), $form); 3591 3592 if (dd.value != "") { 3593 var data = AjaxJsonPostWrapper.getFormData($form); 3594 3595 return AjaxJsonPostWrapper.ajaxRoute('product', 'getproductoption', { option: data, prodDefault: prodDefData }, 3596 function (result) { 3597 updatePriceBlockHtml($form, result.main, result.sticky); 3598 toggleCustomizationBox($form, "YES", 0); 3599 toggleDropShipMessage($form, prodDefData.IsDropShip, prodDefData.IsDropShip); 3600 //set the js variables that hold the arrays of values for the selected value (these will only really contain data when it is returnign the last drop down selection list) 3601 prices[itemId] = result.product.Prices; 3602 clubPrices[itemId] = result.product.ClubPrices; 3603 expectDates[itemId] = result.product.ExpectDates; 3604 sellActions[itemId] = result.product.SellActions; 3605 clubDiscounts[itemId] = result.product.ClubDiscounts; 3606 comparePrices[itemId] = result.product.ComparePrices; 3607 wasPrices[itemId] = result.product.WasPrices; 3608 embroideryFlags[itemId] = result.product.EmbroideryFlags; 3609 engravePrompts[itemId] = result.product.EngravePrompts; 3610 engraveCharges[itemId] = result.product.EngraveCharges; 3611 clubPriceFlags[itemId] = result.product.ClubPriceFlags; 3612 dropShipFlags[itemId] = result.product.DropShipFlags; 3613 vendorExpectedShipDates[itemId] = result.product.VendorExpectedShipDates; 3614 3615 if (!$form.hasClass("quickview-form") && window.invMsg) { 3616 window.invMsg.qtyOnHand = result.product.QtyOnHand; 3617 window.invMsg.salesBySku = result.product.SalesBySku; 3618 } 3619 3620 var ddl = $form.find('#' + updateField); 3621 ddl.empty(); 3622 $('<option/>', { value: "", text: "Select an Option" }).appendTo(ddl); 3623 $(result.product.Values).each(function () { 3624 $('<option/>', { 3625 value: this.Code, 3626 text: this.Desc, 3627 selected: result.product.Type = data.SizeCode != null && $(result.product.Values).length == 1 //color is always selected after size. if size is populated, then the results are colors. if only one, just select it. 3628 }).appendTo(ddl); 3629 }); 3630 ddl.prop('disabled', false); 3631 ddl.customSelect('updateText'); 3632 if (data.SizeCode != null && $(result.product.Values).length == 1) { 3633 //processSelectedProductOption(ddl); // last one..., auto-select done via server code 3634 } else { 3635 autoselectAttributeIfSingle(ddl); 3636 } 3637 }); 3638 } else {
3639 return AjaxJsonPostWrapper.ajaxRoute('product', 'getproductdefaultpriceblock', prodDefData, function (result) { 3640 updatePriceBlockHtml($form, result.main, result.sticky); 3641 toggleCustomizationBox($form, "YES", 0); 3642 toggleDropShipMessage($form, prodDefData.IsDropShip, prodDefData.IsDropShip); 3643 }); 3644 } 3645} 3646 3647function arrayAllTheSameValues(array) { 3648 var first = array[0]; 3649 var allTheSame = true; 3650 $(array).each(function (index) { if (array[index] != first) allTheSame = false; }); 3651 return allTheSame; 3652} 3653 3654window.defaultThisImage = null; // used for defaulting image when image gallery is ready 3655 3656function processSelectedProductOption(dd) { 3657 var $dd = $(dd); 3658 3659 // $dd.closet('form') was returning 2(!) forms (and using the incorrect 3660 // one half the time) when there are two $(".auto-select") dropdowns 3661 // in the markup (pdp + quickview). we'd like to only process for the relevant 3662 // form but don't have that available at this time, just process each/both correctly 3663 $dd.each(function (idx) { 3664 $myDD = $(this); 3665 3666 var $form = $myDD.closest('form'); 3667 3668 //js variables contain a arrays of values that correspond to the values of the final drop down 3669 var addBtnDiv = $form.find('.addToCartButtonDiv'); 3670 var addBtn = $form.find('.addToCartButton'); 3671 var notifyBtnDiv = $form.find('.notifyMeButtonDiv'); 3672 var quantityDiv = $form.find("#quantityAdjustment"); 3673 var productOptionType = $form.find("#ProductOptionType").val(); 3674 var stockMsgDiv; //not in the form on PDP 3675 var isTruck = $("#freightLookup").length > 0 && !($form.attr("id").indexOf('quickview') === 0); // IE doesn't support startsWith 3676 3677 if ($myDD.attr('name') === 'ColorCode' && $form.attr('id') !== "free-gift") { 3678 var selectedColorCode = $myDD.val(); 3679 if (selectedColorCode !== "") { 3680 if ($form.hasClass("quickview-form")) { 3681 var $modal = $form.closest(".moby-container.quickview.show"); // the visible quickview... 3682 // needs to NOT affect other quickviews or the pdp that may be behind this 3683 var $i = $modal.find("#product-thumbs img[data-associatedcolorcode = '" + selectedColorCode + "']").first(); 3684 if ($i.length) { 3685 $modal.find("#main-image img").attr("src", $i.attr('src').replace("/s/", "/l/")); 3686 $modal.find('.mainImageCaption').text($i.attr('title')); 3687 } 3688 } else { 3689 var $mScroll = $("#product-thumbs"); 3690 //todo watch out for related products... it pre-renders the quickview with duplicate ids on the page... 3691 //we should re-work those and we wouldnt need this check to see if the scroll is in a slider 3692 if ($mScroll.closest(".slider-container").length === 0) { 3693 var $btn = $mScroll.find("button img[data-associatedcolorcode = '" + selectedColorCode + "']").first().parent(); 3694 if ($btn.length) { 3695 var scope = $("#ImageGalleryController").scope(); 3696 if (scope != undefined) 3697 scope.swapImage($btn, true); 3698 else 3699 window.defaultThisImage = selectedColorCode; 3700 } 3701 } 3702 } 3703 } 3704 } 3705 3706 var isQuickView = false; 3707 if ($form.hasClass("quickview-form")) { 3708 isQuickView = true; 3709 stockMsgDiv = $form.find('.stock-note'); 3710 } else { 3711 stockMsgDiv = $('.stock-note'); 3712 } 3713 3714 var index; 3715 if (productOptionType == "A") { 3716 index = $myDD.prop('selectedIndex'); 3717 } else { 3718 index = $myDD.prop('selectedIndex') - 1; 3719 } 3720 3721 var itemId = $form.find('input[id=ID]').val(); 3722 3723 checkCompanionProducts($myDD, $form); 3724 3725 if (index > -1) //they selected a value 3726 { 3727 var sellAction = sellActions[itemId][index]; 3728 var price = prices[itemId][index]; 3729 var clubPrice = clubPrices[itemId][index]; 3730 var name = names[itemId][index]; 3731 if (name != undefined && name != null) { //ammo kit 3732 if ($form.hasClass("quickview-form")) { 3733 $(".product-title > h1", $form).text(name); // needs to NOT affect other quickviews or the pdp that may be behind this 3734 $(".itemNumberText", $form).text($myDD.val()); // needs to NOT affect other quickviews or the pdp that may be behind this 3735 } else { 3736 var $productTitle = $(".product-title > h1", $form); 3737 $productTitle.text(name); // needs to NOT affect Related Products Quickview modals that are already in page 3738 $(".breadcrumbs.container > ul > li:last > span > strong").text(name); 3739 $(".itemNumberText").text($myDD.val()); 3740 } 3741 3742 $form.find("#Name").val(name); 3743 checkPurchaseQtyLimits($form, $myDD.val()); 3744 //this is an ammo kit selection, hide the was price on selection change 3745 $(".was-price").hide(); 3746 } 3747 3748 if (isTruck) { 3749 resetFreightLookup(); 3750 } 3751 3752 var comparePrice = comparePrices[itemId][index];
3753 var wasPrice = wasPrices[itemId][index]; 3754 var pricingType = clubDiscounts[itemId][index]; 3755 var clubPriceFlag = clubPriceFlags[itemId][index]; 3756 var embroideryFlag = embroideryFlags[itemId][index]; 3757 var engravePrompt = engravePrompts[itemId][index]; 3758 var dropShipFlag = (dropShipFlags[itemId].length > 0 ) ? (dropShipFlags[itemId][index] === "Y") : priceDefaults[itemId][11]; 3759 3760 var optData = { 3761 ID: itemId, 3762 MinPrice: price, 3763 MaxPrice: price, 3764 MinClubPrice: clubPrice, 3765 MaxClubPrice: clubPrice, 3766 ComparePrice: comparePrice, 3767 WasPrice: wasPrice, 3768 ClubPriceFlag: clubPriceFlag, 3769 PricingType: pricingType, 3770 IsGenericPage: priceDefaults[itemId][8], 3771 HasBullseyeSavings: priceDefaults[itemId][9], 3772 IsClubExclusive: priceDefaults[itemId][10], 3773 IsDropShip: dropShipFlag, 3774 IsQuickView: isQuickView 3775 }; 3776 3777 return AjaxJsonPostWrapper.ajaxRoute('product', 'getproductoptionpriceblock', optData, function (result) { 3778 updatePriceBlockHtml($form, result.main, result.sticky); 3779 toggleCustomizationBox($form, embroideryFlag, engravePrompt); 3780 toggleDropShipMessage($form, priceDefaults[itemId][11], dropShipFlag); 3781 //default stock message to out...we'll change to in if needed 3782 $(stockMsgDiv).addClass("out").removeClass("in"); 3783 var expectDate = expectDates[itemId][index]; 3784 if (sellAction == "S" || sellAction == "B") { 3785 $(notifyBtnDiv).hide(); 3786 $(addBtnDiv).show(); 3787 $(quantityDiv).show(); 3788 if (isTruck) { 3789 $("#freightLookup").show(); 3790 } 3791 if (sellAction == "B") //on backorder, show stock message on back order 3792 { 3793 if (!isQuickView) { 3794 $(".backordered-note").show(); 3795 } 3796 var message = "Item is on backorder. Estimated availability: " + expectDate; 3797 $(stockMsgDiv).text(message); 3798 } 3799 else { 3800 if (!isQuickView) { 3801 $(".backordered-note").hide(); 3802 } 3803 var isJIT = $form.find('input[id=hdnIsJIT]').val(); 3804 var isFireArm = $form.find('input[id=hdnIsFirearm]').val(); 3805 if (isJIT == "false" || isFireArm == "true") { 3806 if (isFireArm == "true") { 3807 $(stockMsgDiv).addClass("in").removeClass("out"); 3808 $(stockMsgDiv).text("In Stock"); 3809 } 3810 else if (!dropShipFlag) { 3811 $(stockMsgDiv).addClass("in").removeClass("out"); 3812 $(stockMsgDiv).text("In Stock"); 3813 } 3814 else if (dropShipFlag) { 3815 $(stockMsgDiv).addClass("in").removeClass("out"); 3816 $(stockMsgDiv).text(vendorExpectedShipDates[itemId][index]); 3817 } 3818 } 3819 } 3820 } 3821 else if (sellAction == "N") { 3822 $(stockMsgDiv).text("Item not currently available for sale."); 3823 $(notifyBtnDiv).show(); 3824 $(addBtnDiv).hide(); 3825 $(quantityDiv).hide(); 3826 } 3827 else if (sellAction == "X") { 3828 $(stockMsgDiv).text("SOLD OUT"); 3829 $(notifyBtnDiv).hide(); 3830 $(addBtnDiv).hide(); 3831 $(quantityDiv).hide(); 3832 } 3833 3834 var $warrantyPdp = $("#warranty-data-pdp"); 3835 if ($warrantyPdp.length) { 3836 var $prodData = { 3837 ID: $form.find('#ID').val(), 3838 PromoCode: $form.find('#PromoCode').val(), 3839 SizeParam: $form.find('#SizeCode').val(), 3840 ColorParam: $form.find('#ColorCode').val() 3841 }; 3842 var $warrantyScope = angular.element(".warranty-control").scope(); 3843 $warrantyScope.$broadcast('skuChanged', $prodData); 3844 } 3845 }); 3846 } 3847 else { //if -1, then they set back to default no value 3848 //reset buttons and display to remove any info that was previously populated
3849 $(notifyBtnDiv).hide(); 3850 $(addBtnDiv).show(); 3851 $(stockMsgDiv).text(" "); 3852 $(quantityDiv).show(); 3853 3854 var optionData = { 3855 Prices: prices[itemId], 3856 ClubPrices: clubPrices[itemId], 3857 ClubDiscounts: clubDiscounts[itemId], 3858 ComparePrices: comparePrices[itemId], 3859 WasPrices: wasPrices[itemId], 3860 ClubPriceFlags: clubPriceFlags[itemId], 3861 DropShipFlags: dropShipFlags[itemId] 3862 }; 3863 var prodDefData = getProductDefaultData(itemId); 3864 prodDefData.IsQuickView = isQuickView; 3865 return AjaxJsonPostWrapper.ajaxRoute('product', 'getproductoptiondefaultpriceblock', { prodDefault: prodDefData, option: optionData }, function (result) { 3866 updatePriceBlockHtml($form, result.main, result.sticky); 3867 toggleCustomizationBox($form, "YES", 0); 3868 toggleDropShipMessage($form, prodDefData.IsDropShip, prodDefData.IsDropShip); 3869 3870 if (isTruck) { 3871 resetFreightLookup(); 3872 } 3873 }); 3874 } 3875 }); 3876 3877 //var end = new Date().getTime(); 3878 //console.log('milliseconds taken:' + (end - start)); 3879 3880} 3881 3882function getProductDefaultData(itemId) { 3883 var data = { 3884 ID: itemId, 3885 MinPrice: priceDefaults[itemId][0], 3886 MaxPrice: priceDefaults[itemId][1], 3887 MinClubPrice: priceDefaults[itemId][2], 3888 MaxClubPrice: priceDefaults[itemId][3], 3889 ComparePrice: priceDefaults[itemId][4], 3890 WasPrice: priceDefaults[itemId][5], 3891 ClubPriceFlag: priceDefaults[itemId][6], 3892 PricingType: priceDefaults[itemId][7], 3893 IsGenericPage: priceDefaults[itemId][8], 3894 HasBullseyeSavings: priceDefaults[itemId][9], 3895 IsClubExclusive: priceDefaults[itemId][10], 3896 IsDropShip: priceDefaults[itemId][11] 3897 }; 3898 return data; 3899} 3900 3901function updatePriceBlockHtml(form, main, sticky) { 3902 if (main) { 3903 angular.element(document).injector().invoke(['$compile', '$rootScope', function ($compile, $rootScope) { 3904 form.find("#priceBlockPH").html($compile(main)($rootScope)); 3905 }]); 3906 } 3907 if (sticky) { 3908 if (!(form.attr("id").indexOf('quickview') === 0)) { // IE doesn't support startsWith 3909 if ($("#stickyAddToCart").length) { 3910 $("#stickyAddToCart").find("#stickyPricePH").html(sticky); 3911 } 3912 } 3913 } 3914 if (main) { 3915 Gorilla.util.initForms(); 3916 } 3917} 3918 3919function toggleCustomizationBox(form, embroideryFlag, engravePrompt) { 3920 var custBox = form.find("#customization-box"); 3921 if (custBox) { 3922 if ((embroideryFlag && embroideryFlag != "N") || engravePrompt > 0) { 3923 custBox.show(); 3924 } else { 3925 custBox.hide(); 3926 form.find("#Personalize").prop('checked', false); 3927 } 3928 } 3929} 3930 3931function toggleDropShipMessage(form, itemDropShipDefault, dropShipFlag) { 3932 if (itemDropShipDefault) { 3933 var restrictShipEle = form.find(".restrictShip"); 3934 if (restrictShipEle) { 3935 var restrictAddlShipDiv = restrictShipEle.find("#restrictAddlShipTip"); 3936 if (restrictAddlShipDiv) { 3937 var dropShipEle = restrictAddlShipDiv.find(".dropShip"); 3938 if (dropShipEle) { 3939 if (dropShipFlag) { 3940 dropShipEle.show(); 3941 restrictShipEle.show(); 3942 } else { 3943 dropShipEle.hide(); 3944 if (dropShipEle.parent().find("li").length === 1) { 3945 restrictShipEle.hide(); 3946 } 3947 } 3948 } 3949 } 3950 } 3951 } 3952} 3953 3954function loadCustomerCommentPage(page) { 3955 //return AjaxJsonPostWrapper.ajaxRoute('usefullinks', 'getcustomercommentspage', { page: page }, function (result) { 3956 // $('#productReviewsSummary').html(result.reviewPageSummary); 3957 // $('#productReviewContainer').html(result.reviews); 3958 // $(window).scrollTop(0); 3959 //}); 3960} 3961 3962function catalogQuickOrderChange() 3963{ 3964 var itemNum = $('#newItemNumber').val(); 3965 var id = 0; 3966 var promo = ""; 3967 if (itemNum.split('-').length == 2) { 3968 id = parseInt(itemNum.split('-')[1], 10); 3969 var regex = new RegExp("^[0-9a-zA-Z0-9]+$"); 3970 promo = itemNum.split('-')[0].toUpperCase(); 3971 if (!regex.test(promo)) 3972 promo = ""; 3973 } 3974 $('#quickorderbtn').attr("href", "/product/getproductcartdata?ID=" + id + "&PCode=" + promo); 3975} 3976 3977//function notifyMe(btn) { 3978// var data = AjaxJsonPostWrapper.getFormData($(btn).closest('form'));
3979// return AjaxJsonPostWrapper.ajaxRoute('product', 'notifymeform', data, function (result) { 3980// console.log('results', result) 3981// $('#notifyMe').html(result); 3982// $('#notifyMe').show(); 3983 3984// }); 3985//} 3986 3987function notifyMeFamilyGroup(promo, id, name, colorCode, sizeCode) { 3988 var data = { ID: id, PromoCode: promo, Name: name, ColorCode: colorCode, SizeCode: sizeCode }; 3989 return AjaxJsonPostWrapper.ajaxRoute('product', 'notifymeform', data, function (result) { 3990 $('#notifyMe').html(result); 3991 $('#notifyMe').show(); 3992 }); 3993} 3994 3995//****************************end product functions*********************************** 3996 3997// trying to get bundle to make a new number... 3998function testFuncAS() 3999{ 4000 return false; 4001} 4002 4003//****************************cart view functions*********************************** 4004function updateQty(ctrl, entryId, qty, cqo) { 4005 if ((qty === 0 || $(ctrl).valid()) && 4006 $.trim(qty) != "") {//remove links send in 0 but don't do validation 4007 return AjaxJsonPostWrapper.ajaxRoute('cart', 'updateqty', { entryId: entryId, qty: qty, cqo: cqo }, function (result) { 4008 //update the main cart display 4009 if (result.cartHtml && result.cartHtml != "") { 4010 //update the cart drop down display 4011 setCartQuantityText(); 4012 if (result.cartQty < 1) { 4013 $(".subheader .checkout-btn").attr("style", "display:none!important"); 4014 } 4015 $('#cartSummary').html(""); 4016 updateCartContainer(result.cartHtml); 4017 $("#UpdateLink_" + entryId).focus(); 4018 } 4019 4020 if (result.miniCartHtml && result.miniCartHtml != "") { 4021 updateShowMiniCart(result.miniCartHtml, false); 4022 } 4023 }); 4024 } 4025} 4026 4027function removeItems(entryIds, cqo) { 4028 return AjaxJsonPostWrapper.ajaxRoute('cart', 'removeitems', { entryIds: entryIds, cqo: cqo }, function (result) { 4029 //update the main cart display 4030 if (result.cartHtml && result.cartHtml != "") { 4031 //update the cart drop down display 4032 setCartQuantityText(); 4033 $('#cartSummary').html(""); 4034 updateCartContainer(result.cartHtml); 4035 } 4036 }); 4037} 4038 4039function updateCartSummary() { 4040 return AjaxJsonPostWrapper.ajaxRoute('cart', 'getcartpreview', {}, function (result) { 4041 updateShowMiniCart(result, true); 4042 }); 4043} 4044 4045function updateWishSummary(showFade) { 4046 return AjaxJsonPostWrapper.ajaxRoute('wishlist', 'getwishlistpreview', {}, function (result) { 4047 updateShowMiniWish(result, true, showFade); 4048 }) 4049} 4050 4051function applyGiftCard() 4052{ 4053 // there is jquery/javascript that attaches to the "update" CSS class on the links, which 4054 // binds this link click to form submission. bottom line, we don't need to do anything here 4055 return false; 4056} 4057 4058function resetFreightLookup() { 4059 $("#freightLookup .lookup").show(); 4060 $("#freightLookup .result").hide(); 4061 $("#freightLookup").hide(); 4062 $("#hdnFreightZip").val(""); 4063 $("#hdnFreightAmount").val(0); 4064} 4065 4066function addCommas(nStr) { 4067 nStr += ''; 4068 var x = nStr.split('.'); 4069 var x1 = x[0]; 4070 var x2 = x.length > 1 ? '.' + x[1] : ''; 4071 var rgx = /(\d+)(\d{3})/; 4072 while (rgx.test(x1)) { 4073 x1 = x1.replace(rgx, '$1' + ',' + '$2'); 4074 } 4075 return x1 + x2; 4076} 4077 4078 4079//****************************end cart view functions********************************** 4080 4081//************ Product quick view is needed on a lot of pages because of the recently viewed section. ************ 4082function productQuickView(adId, id, promo) { 4083 return AjaxJsonPostWrapper.ajaxRoute('product', 'getproductcartdata', { ID: id, PromoCode: promo, AdId: adId }, function (result) { 4084 $('#notifyMe').html("<div id='productCart' style='width:1100px; background-color:white; border:5px outset black;'>" + result + "</div>"); 4085 $('#notifyMe').show(); 4086 }); 4087} 4088 4089function enableOK(checkbox) { 4090 var val = checkbox.id; 4091 if ($('#' + val).prop('checked')) { 4092 $('#' +val + '-acknowledge').removeAttr('disabled'); 4093 } 4094 else { 4095 $('#' + val + '-acknowledge').attr('disabled', 'disabled'); 4096 } 4097} 4098 4099//This function animates for effect the recently added item to cart/wishlist drawers 4100function popFadeProduct(containerId) { 4101 setTimeout(function () { 4102 var $productsGrid = $("#" + containerId).find("ol.products-grid"); 4103 var $el = $productsGrid.find("li:first-child"); 4104 $el.remove(); 4105 $el.prependTo($productsGrid).hide().delay(500).fadeIn(2000); 4106 }, 500); 4107} 4108 4109//Sold Out products in cart 4110if (($soldOutTrigger = $('#sold-out-modal-trigger')).length) { 4111 $('#sold-out-modal-trigger').appendTo('body'); 4112 $('#sold-out-modal').appendTo('body'); 4113 setTimeout(function () { 4114 $soldOutTrigger.moby({ 4115 'modalClass': 'sold-out-modal', 4116 'bodyClose': false, 4117 'keyActions': false, 4118 'onCompleteCallback': function () { 4119 Gorilla.util.initForms();
4120 $("#soldOutRemoveItem").on("click", function() { 4121 $("#sold-out-modal-trigger").moby('hide'); 4122 }); 4123 } 4124 }).moby('show', '#sold-out-modal'); 4125 }, 0); 4126} 4127 4128//Return restriction messaging 4129$(document).ready(function () { 4130 if (($gasReturnRestrictionTrigger = $('#gas-return-restriction-modal-trigger')).length) { 4131 setTimeout(function () { 4132 $gasReturnRestrictionTrigger.moby({ 4133 'modalClass': 'sold-out-modal', 4134 'bodyClose': false, 4135 'keyActions': false, 4136 'onCompleteCallback': function () { 4137 $("#gas-modal-close, #check-gas-acknowledge").on('click', function (event) { 4138 event.preventDefault(); 4139 $("#gas-return-restriction-modal-trigger").moby('hide'); 4140 }); 4141 } 4142 }).moby('show', '#gas-return-restriction-modal'); 4143 }, 40); 4144 } 4145 4146 if (($unopenedReturnRestrictionTrigger = $('#unopened-return-restriction-modal-trigger')).length) { 4147 setTimeout(function () { 4148 $unopenedReturnRestrictionTrigger.moby({ 4149 'modalClass': 'sold-out-modal', 4150 'bodyClose': false, 4151 'keyActions': false, 4152 'onCompleteCallback': function () { 4153 $("#unopened-modal-close, #check-unopened-acknowledge").on('click', function (event) { 4154 event.preventDefault(); 4155 $("#unopened-return-restriction-modal-trigger").moby('hide'); 4156 }); 4157 } 4158 }).moby('show', '#unopened-return-restriction-modal'); 4159 }, 40); 4160 } 4161 4162 if (($origpackagingReturnRestrictionTrigger = $('#origpackaging-return-restriction-modal-trigger')).length) { 4163 setTimeout(function () { 4164 $origpackagingReturnRestrictionTrigger.moby({ 4165 'modalClass': 'sold-out-modal', 4166 'bodyClose': false, 4167 'keyActions': false, 4168 'onCompleteCallback': function () { 4169 $("#origpackaging-modal-close, #check-origpackaging-acknowledge").on('click', function (event) { 4170 event.preventDefault(); 4171 $("#origpackaging-return-restriction-modal-trigger").moby('hide'); 4172 }); 4173 } 4174 }).moby('show', '#origpackaging-return-restriction-modal'); 4175 }, 40); 4176 } 4177}); 4178 4179function liftgateChange(el) { 4180 var $this = $(el); 4181 $("#liftgate-modal").data('elid', $this.attr("id")); 4182 var onPdp = $('body').hasClass('product-view'); 4183 var onCheckout = $('body').hasClass("checkout"); 4184 4185 if (!$this.is(":checked")) { 4186 $("#liftgate-modal-trigger").moby({ 4187 'bodyClose': false, 4188 'keyActions': false, 4189 'modalClass': 'freightModal', 4190 'onCompleteCallback': function () { 4191 4192 if (onPdp) { 4193 $(".freightWeight").html($("#hdnFreightWeight").val() + " lbs."); 4194 } else { 4195 updateFreightWeight($("#" + $("#liftgate-modal").data("elid"))); 4196 } 4197 4198 if ($("#liftgateAckText").hasClass("ajax-loading")) { 4199 AjaxJsonPostWrapper.ajaxRoute('cart', 'getackmessages', {}, function (result) { 4200 $("#liftgateAckText").removeClass("ajax-loading").html(result.ackMessages.Liftgate.Message); 4201 }); 4202 } 4203 4204 $(document).off("click", "#keepLiftgate").on("click", "#keepLiftgate", function () { 4205 var $el = $("#" + $("#liftgate-modal").data("elid")); 4206 $el.prop("checked", true); 4207 Gorilla.util.customCheckbox.update($el); 4208 $("#liftgate-modal-trigger").moby('hide'); 4209 }); 4210 4211 $(document).off("click", "#removeLiftgate").on("click", "#removeLiftgate", function () { 4212 var $el = $("#" + $("#liftgate-modal").data("elid")); 4213
4214 AjaxJsonPostWrapper.ajaxRoute('cart', 'sendackmessage', { ackId: 17 }); 4215 4216 //uncheck front door if its checked, cant have it without liftgate 4217 var $frontDoorInput = $el.closest(".freightAddOns").find("input[name='FrontDoor']"); 4218 $frontDoorInput.prop("checked", false); 4219 Gorilla.util.customCheckbox.update($frontDoorInput); 4220 4221 if (onPdp) { 4222 updateFreightTotal(); 4223 } else { 4224 updateFreightDeliveryOpt($el); 4225 } 4226 4227 if (onCheckout) { //this is a hack used to trigger the payment postback 4228 $('#cartModifiedBtn').click(); 4229 } 4230 4231 $("#liftgate-modal-trigger").moby('hide'); 4232 }); 4233 } 4234 }).moby('show', '#liftgate-modal'); 4235 4236 return; 4237 } 4238 4239 if (onPdp) { 4240 updateFreightTotal(); 4241 } else { 4242 updateFreightDeliveryOpt($this); 4243 } 4244 4245 if (onCheckout) { //this is a hack used to trigger the payment postback 4246 $('#cartModifiedBtn').click(); 4247 } 4248} 4249 4250function frontDoorChange(el) { 4251 var $this = $(el); 4252 $("#frontDoor-modal").data('elid', $this.attr("id")); 4253 var onPdp = $('body').hasClass('product-view'); 4254 var onCheckout = $('body').hasClass("checkout"); 4255 4256 if (!$this.is(":checked")) { 4257 $("#frontDoor-modal-trigger").moby({ 4258 'bodyClose': false, 4259 'keyActions': false, 4260 'modalClass': 'freightModal', 4261 'onCompleteCallback': function () { 4262 4263 if (onPdp) { 4264 $(".freightWeight").html($("#hdnFreightWeight").val() + " lbs."); 4265 } else { 4266 updateFreightWeight($("#" + $("#frontDoor-modal").data("elid"))); 4267 } 4268 4269 $(document).off("click", "#keepFrontDoor").on("click", "#keepFrontDoor", function () { 4270 var $el = $("#" + $("#frontDoor-modal").data("elid")); 4271 $el.prop("checked", true); 4272 Gorilla.util.customCheckbox.update($el); 4273 $("#frontDoor-modal-trigger").moby('hide'); 4274 }); 4275 4276 $(document).off("click", "#removeFrontDoor").on("click", "#removeFrontDoor", function () { 4277 var $el = $("#" + $("#frontDoor-modal").data("elid")); 4278 4279 if (onPdp) { 4280 updateFreightTotal(); 4281 } else { 4282 updateFreightDeliveryOpt($el); 4283 } 4284 4285 if (onCheckout) { //this is a hack used to trigger the payment postback 4286 $('#cartModifiedBtn').click(); 4287 } 4288 4289 $("#frontDoor-modal-trigger").moby('hide'); 4290 }); 4291 } 4292 }).moby('show', '#frontDoor-modal'); 4293 4294 return; 4295 } 4296 4297 //liftgate is required for front door, make sure its checked 4298 var $liftgateInput = $this.closest(".freightAddOns").find("input[name='Liftgate']"); 4299 $liftgateInput.prop("checked", true); 4300 Gorilla.util.customCheckbox.update($liftgateInput); 4301 4302 if (onPdp) { 4303 updateFreightTotal(); 4304 } else { 4305 updateFreightDeliveryOpt($this); 4306 } 4307 4308 if (onCheckout) { //this is a hack used to trigger the payment postback 4309 $('#cartModifiedBtn').click(); 4310 } 4311} 4312 4313function updateFreightTotal() { 4314 var quote = parseFloat($(".quoteAmount").text().slice(1)); 4315 var frontDoorAmount = parseFloat($(".frontDoorAmount").text().slice(1)); 4316 var liftgateAmount = parseFloat($(".liftgateAmount").text().slice(1)); 4317 4318 var liftgate = $(".freightAddOns").find("input[name=Liftgate]:not([type=hidden])").is(":checked"); 4319 var frontDoor = $(".freightAddOns").find("input[name=FrontDoor]:not([type=hidden])").is(":checked"); 4320 4321 if (liftgate && frontDoor) { 4322 $(".freightTotal").text("$" + (quote + frontDoorAmount + liftgateAmount).toFixed(2)); 4323 } else if (liftgate) { 4324 $(".freightTotal").text("$" + (quote + liftgateAmount).toFixed(2)); 4325 } else { 4326 $(".freightTotal").text("$" + quote.toFixed(2)); 4327 } 4328} 4329 4330function updateFreightWeight(el) { 4331 var $this = $(el); 4332 4333 var request = { 4334 ItemId: $this.closest('tr.restrictions-row').data('itemid'), 4335 SizeCode: $this.closest('tr.restrictions-row').data('sizecode'), 4336 ColorCode: $this.closest('tr.restrictions-row').data('colorcode') 4337 } 4338
4339 AjaxJsonPostWrapper.ajaxRoute('cart', 'getfreightdata', { request: request }, function (result) { 4340 $(".freightWeight").html(result.data.Weight + " lbs."); 4341 }); 4342} 4343 4344function updateFreightDeliveryOpt(el) { 4345 var $this = $(el); 4346 4347 var liftgate = $this.closest(".freightAddOns").find("input[name=Liftgate]:not([type=hidden])").is(":checked"); 4348 var frontDoor = $this.closest(".freightAddOns").find("input[name=FrontDoor]:not([type=hidden])").is(":checked"); 4349 4350 var opt; 4351 if (liftgate && frontDoor) 4352 opt = "F"; 4353 else if (liftgate) 4354 opt = "L"; 4355 else 4356 opt = "D"; 4357 4358 var request = { 4359 EntryId: $this.closest('tr.restrictions-row').data('entryid'), 4360 Opt: opt 4361 }; 4362 4363 AjaxJsonPostWrapper.ajaxRouteNonAsync('cart', 'setfreightdeliveryopt', { request: request }); 4364} 4365 4366function addToWishList(link, id, promo, form) { 4367 // validate form 4368 if (!form) { 4369 var form = $(link).closest('form'); 4370 if (!form.valid()) 4371 return; 4372 } 4373 4374 // Personalize is a checkbox which MVC renders also as a hidden field, deal with that duplication/binding complexity: 4375 if ($("#Personalize").is(":checked")) { 4376 // removed "false" Personalize inputs when the Personalize checkbox (which has an ID) is checked 4377 $("[name='Personalize']").each(function (index) { 4378 if ($(this).val() == "false") { 4379 $(this).remove(); 4380 } 4381 }); 4382 } 4383 4384 var data = AjaxJsonPostWrapper.getFormData(form); 4385 if (id.length > 0) data.ID = id; 4386 4387 //check to see if they're signed in 4388 AjaxJsonPostWrapper.ajaxRoute('authenticate', 'issignedin', {}, function (response) { 4389 if (!response.signedIn) { 4390 // save form data to cookie 4391 Gorilla.util.setCookie('_wishlist-product-data', btoa(JSON.stringify(data))); 4392 // if not signed in, send them off to sign-in/create account with their wish list as the final landing page (wish list will add the item from the cookie and trigger personalization if needed) 4393 window.location = "/authenticate/accountlogin?returnUrl=/wishlist/index"; 4394 } 4395 else { 4396 // add item to wish list and pop wish list drawer 4397 AjaxJsonPostWrapper.ajaxRoute('wishlist', 'addtowishlist', { data: data }, function (result) { 4398 //this is bad practice, but a necessary evil until we are fully angular on the rest of the site 4399 if (Gorilla.util.getCookie("ab-cart") === "Experiment") { 4400 if (($moby = $('.moby-container.quickview')).length) { 4401 $moby.find('.moby-close').trigger('click').off('click'); //close the actual window that triggered this....normal path 4402 } 4403 //close the quickview slideout if its open 4404 if ($("#quickview-mmenu").length && $("#quickview-mmenu").hasClass("mm-menu_opened")) { 4405 $("#quickview-mmenu").data("mmenu").close(); 4406 if (lastFocus) { 4407 lastFocus.focus(); 4408 } 4409 } 4410 4411 var scope = angular.element(document.getElementById('ItemAddedDialogController')).scope(); 4412 return scope.showDialog("wishlist"); 4413 } 4414 updateWishSummary(true); 4415 if (result.personalizeHtml) { 4416 if (($personalizeTrigger = $('#personalize-trigger')).length && ($personalizeModal = $('#personalize-modal')).length) { 4417 //init the modal and set the Html from the response, since Moby requires an anchor we're triggering a click on the hidden anchor 4418 $personalizeModal.html(result.personalizeHtml); 4419 $personalizeTrigger.moby({ 4420 'modalClass': 'personalize-mod', 4421 'ariaLabelText': 'Customize Item', 4422 'onCompleteCallback': function () { 4423 Gorilla.util.initForms();
4424 $('#personalize-mod').validate(); 4425 } 4426 }).moby('show', '#personalize-modal'); 4427 } 4428 } 4429 4430 var scope = angular.element(document.getElementById('CartWishListHomepageController')).scope(); 4431 if (scope != undefined) scope.addedToCart(); 4432 }); 4433 } 4434 }); 4435} 4436 4437function updateShowMiniWish(html, showSlide, showFade) { 4438 if (html && html !== "") { 4439 var prevItemCount = $("#wishlistQtyText").text(); 4440 setWishlistQuantityText(); 4441 var $wishSummary = $("#wishSummary"); 4442 setTimeout(function () { 4443 $wishSummary.empty().append(html); 4444 $("#mini-totals-wish").empty().append($wishSummary.find(".mini-totals-container-wish").detach()); 4445 var itemCount = $wishSummary.find(".items-in-cart-wish").detach().text(); 4446 if (itemCount.length) { 4447 $("#mini-count-wish").empty().append(itemCount); 4448 } else { 4449 $("#cart-mmenu").addClass("mm-unset"); 4450 $("#mini-count-wish").text("0 items in your wish list"); 4451 } 4452 }, 500); 4453 4454 if (showSlide) { 4455 dropMiniWish(); 4456 } 4457 4458 if (showFade && ($("#wishlistQtyText").text() > prevItemCount)) { 4459 popFadeProduct("wish-mmenu"); 4460 } 4461 } 4462} 4463 4464function dropMiniWish() { 4465 if (($moby = $('.moby-container.quickview')).length) { 4466 $moby.find('.moby-close').trigger('click').off('click'); //close the actual window that triggered this....normal path 4467 } 4468 4469 //close the quickview slideout if its open 4470 if ($("#quickview-mmenu").length && $("#quickview-mmenu").hasClass("mm-menu_opened")) { 4471 $("#quickview-mmenu").data("mmenu").close(); 4472 } 4473 4474 $quickorderAdd = $("#quickorder-add"); 4475 if (!$quickorderAdd.length) 4476 setTimeout(function () { 4477 $("#wish-mmenu").data("mmenu").open(); 4478 trapFocus($("#wish-mmenu")); 4479 $("#wish-mmenu").on("click", ".mm-navbars_top", function (e) { 4480 $("#wish-mmenu").data("mmenu").close(); 4481 if (lastFocus) { 4482 lastFocus.focus(); 4483 } 4484 }); 4485 }, 500); 4486} 4487 4488function checkCompanionProducts($myDD, $form) { 4489 if ($("#companion-products").length && !$form.hasClass("quickview-form")) { 4490 if ($myDD.attr('name') === 'ColorCode' || $myDD.attr('name') === 'SizeCode') { 4491 var compScope = angular.element("#companion-products").scope(); 4492 4493 var retVal = false; 4494 if ($(".product-options").length) { 4495 $('.product-options select:visible').each(function () { 4496 retVal = $(this).val() ? false : true; 4497 }); 4498 } 4499 4500 compScope.parentOptionsEmpty = retVal; 4501 compScope.parentSkuChange($myDD.attr('name'), $myDD.val()); 4502 compScope.$apply(); 4503 } 4504 } 4505} 4506 4507function checkPurchaseQtyLimits($form, itemId) { 4508 return AjaxJsonPostWrapper.ajaxRoute('product', 'getpurchaseqtylimit', { itemId: itemId }, function(response) { 4509 $form.find("#hdnPurchaseQtyLimit").val(response.purchaseQtyLimit); 4510 return window.checkQtyLimit($form); 4511 }); 4512}; 4513// Readied 4514domReady(function() { 4515 4516 if (($techDetailsContainer = $(".techDetailsCarousel-container")).length) { 4517 $techDetailsContainer.each(function() { 4518 $(this).attr("role", "region"); 4519 var title = $(this).find(".container-title").text() + " CAROUSEL"; 4520 $(this).attr("aria-label", title); 4521 }); 4522 } 4523 4524 //text media containers 4525 if (($textMediaContainers = $(".textMediaWide-container, .textMediaNarrow-container")).length) { 4526 if (($lazyImg = $textMediaContainers.find('.lazy')).length) { 4527 $lazyImg.lazy({ 4528 afterLoad: function (element) { 4529 var container = $(element).closest(".base-container"); 4530 initTextMediaScroll(container); 4531 } 4532 }); 4533 } 4534 } 4535 4536 if (($countdownContainer = $(".countdown-container")).length) { 4537 $countdownContainer.each(function () { 4538 var $el = $(this).find(".countdown"); 4539 var endDate = $el.find("input[name='EndDate']").val(); 4540 if (endDate !== undefined && endDate !== "") { 4541 $el.ResponsiveCountdown({ 4542 target_date: endDate, 4543 time_zone: -5, 4544 target_future: true, 4545 set_id: 0, 4546 pan_id: 0, 4547 day_digits: 2, 4548 fillStyleSymbol1: "rgba(84, 86, 90, 1)", 4549 fillStyleSymbol2: "rgba(84, 86, 90, 1)", 4550 fillStylesPanel_g1_1: "rgba(237, 237, 237, 1)", 4551 fillStylesPanel_g1_2: "rgba(237, 237, 237, 1)", 4552 fillStylesPanel_g2_1: "rgba(237, 237, 237, 1)", 4553 fillStylesPanel_g2_2: "rgba(237, 237, 237, 1)", 4554 text_color: "#D54400", 4555 text_glow: "#FFFFFF", 4556 show_ss: true, show_mm: true, show_hh: true, show_dd: true, 4557 f_family: "Verdana", show_labels: true, 4558 type3d: "group", max_height: 100, 4559 days_long: "DAYS", days_short: "dd", hours_long: "HOURS", hours_short: "hh", mins_long: "MINUTES", mins_short: "mm", secs_long: "SECONDS", secs_short: "ss", 4560 min_f_size: 9, max_f_size: 30, 4561 spacer: "circles", groups_spacing: 3, 4562 text_blur: 2, f_weight: "bold", font_to_digit_ratio: 0.125 4563 }); 4564 } 4565 }); 4566 } 4567 4568 if (($imageGridWithTextContainer = $(".media-grid-container")).length) { 4569 $imageGridWithTextContainer.each(function () { 4570 var $el = $(this).find(".media-grid-media .media-grid-text .media-grid-view-area"); 4571 $($el).on('scroll', function () {
4572 if ($el.scrollTop() + $el.innerHeight() >= $el[0].scrollHeight - 32) { 4573 $el.parent().find('#text-teaser').hide(); 4574 } else { 4575 $el.parent().find('#text-teaser').show(); 4576 } 4577 }) 4578 4579 //Check to see if content is scrollable 4580 if (($el[0].scrollHeight > $el[0].clientHeight) && ($el[0].clientWidth < $el[0].offsetWidth)) { 4581 $el.parent().find('#text-teaser').show(); 4582 $el.parent().find('.blah-bar').show(); 4583 } else { 4584 $el.parent().find('#text-teaser').hide(); 4585 $el.parent().find('.blah-bar').hide(); 4586 } 4587 }); 4588 } 4589 4590 if (($responsiveImageX = $('[class*="responsiveImageX"]')).length) { 4591 $responsiveImageX.each(function (index, el) { 4592 el.classList.remove("extendfull"); 4593 $(el).find('.sub-base-container').removeClass('extendfull'); 4594 var $containerTitle = $(el).find('.container-title'); 4595 if ($containerTitle.length) { 4596 el.prepend($containerTitle[0]); 4597 } 4598 4599 //Needed to accomodate container spacing 4600 var buttonHeight = $(el).find('.button-div:first').height(); 4601 if (buttonHeight) { 4602 $(el).css('margin-bottom', buttonHeight / 2); 4603 } 4604 }); 4605 } 4606 4607 if ($('.coupon-offer-disclaimer').length) { 4608 $('.coupon-offer-disclaimer').each(function (index, el) { 4609 el.getElementsByClassName("sub-base-container")[0].classList.remove("extendfull"); 4610 var paragraphs = el.getElementsByClassName('normal-text'); 4611 4612 Array.prototype.forEach.call(paragraphs, function (paragraph, index) { 4613 if (paragraphs.length > 1 && index == 0) { 4614 paragraph.firstChild.style.setProperty("display", "block"); 4615 var newHeader = document.createElement("h3"); 4616 newHeader.innerHTML = paragraph.innerHTML; 4617 paragraph.parentNode.replaceChild(newHeader, paragraph); 4618 } 4619 paragraph.firstChild.setAttribute("id", el.id + "-coupon-" + index); 4620 }); 4621 4622 //Create View Details button 4623 var button = document.createElement("BUTTON"); 4624 button.appendChild(document.createTextNode("View Details")); 4625 el.getElementsByClassName('sub-base-container')[0].appendChild(button); 4626 4627 button.addEventListener("click", function () { 4628 if (paragraphs[paragraphs.length - 1].firstChild.style.display === "block") { 4629 paragraphs[paragraphs.length - 1].firstChild.style.display = "none"; 4630 button.textContent = "View Details"; 4631 } else { 4632 paragraphs[paragraphs.length - 1].firstChild.style.display = 'block'; 4633 button.textContent = "Hide Details"; 4634 } 4635 }); 4636 4637 //Replace second h2 with h3 for accessibility purposes 4638 var oldHeader = el.getElementsByTagName("h2")[1]; 4639 if (oldHeader != undefined) { 4640 var newHeader = document.createElement("h3"); 4641 newHeader.innerHTML = oldHeader.innerHTML; 4642 oldHeader.parentNode.replaceChild(newHeader, oldHeader); 4643 } 4644 }); 4645 } 4646 4647 if ($('.featuredProducts-container').length) { 4648 $('.featuredProducts-container').each(function (index, el) { 4649 el.getElementsByClassName("normal-text")[0].style.marginBottom = 0; 4650 }); 4651 } 4652 4653 if ($('.textMediaNarrow-container').length) { 4654 $('.textMediaNarrow-container').each(function (index, el) { 4655 $(el).find('.media-story').each(function (index, el) { 4656 if ($(el).find('.youtube-video-object').length > 0) { 4657 $(el).css("max-width", "1200px"); 4658 } 4659 }); 4660 }); 4661 } 4662});; 4663var readied = domReady(function() { 4664 // Readied 4665 $(function () { 4666 var w = 0; 4667 w = $(window).width(); 4668 bcwpInitResponsive(); 4669 $(window).resize(function() { 4670 if (w != $(window).width()) { 4671 bcwpInitResponsive(); 4672 w = $(window).width(); 4673 delete w; 4674 } 4675 }); 4676 });
4677}); 4678 4679function bcwpInitResponsive() { 4680 if (matchMedia('(min-width:961px)').matches) { 4681 //help the text center when absolutely positioned in a div in media grids 4682 if ($('.media-grid-container').length) { 4683 $('.media-inner-text').each(function() { 4684 if ($(this).prop('scrollHeight') > $(this).prop('clientHeight')) { 4685 $(this).find('div').removeClass('vcenter'); 4686 } else if ($(this).children().length == 1) { 4687 $(this).children().css('top', '50%'); 4688 $(this).children().css('transform', 'translateY(-45%)'); 4689 } 4690 }); 4691 } 4692 } 4693 4694 if (matchMedia('(max-width:960px)').matches) { 4695 mobilizeWysiwigFonts(); 4696 } 4697 4698 if (($textMediaContainers = $(".textMediaWide-container, .textMediaNarrow-container")).length) { 4699 initTextMediaScroll($textMediaContainers); 4700 } 4701 4702 if (matchMedia('(min-width: 961px)').matches) { 4703 //club exclusive product list 4704 if ($('.club-exclusives-ss').length) { 4705 destroyClubExclusiveSlickSlider(); 4706 } 4707 } else { 4708 //club exclusive slider 4709 if ($('.club-exclusives-ss').length) { 4710 createClubExclusiveSlickSlider(); 4711 } 4712 } 4713 4714 if (($('.buyersClubExclusive-container')).length) { 4715 setClubExclusivePriceDisplay(); 4716 } 4717 4718 if (($('.twoColumnImageText-container')).length) { 4719 setTwoColImageButtonsDisplay(); 4720 } 4721 4722 if (matchMedia('(max-width: 730px)').matches) { 4723 if (($responsiveImageX2Container = $(".responsiveImageX2-container")).length) { 4724 $responsiveImageX2Container.each(function (index, el) { 4725 if ($(el).hasClass('gutter')) { 4726 var $widgetOne = $(el).find('.responsiveImage-widget').eq(0); 4727 if ($($widgetOne).find('.button-div').length) { 4728 $($widgetOne).css('margin-bottom', '40px'); 4729 } 4730 } 4731 var $widgetTwo = $(el).find('.responsiveImage-widget').eq(1); 4732 if (!$($widgetTwo).find('.button-div').length) { 4733 $(el).css('margin-bottom', '0px'); 4734 } 4735 }); 4736 } 4737 4738 if (($responsiveImageX3Container = $(".responsiveImageX3-container")).length) { 4739 $responsiveImageX3Container.each(function (index, el) { 4740 if ($(el).hasClass('gutter')) { 4741 var $widgetOne = $(el).find('.responsiveImage-widget').eq(0); 4742 if ($($widgetOne).find('.button-div').length) { 4743 $($widgetOne).css('margin-bottom', '40px'); 4744 } 4745 var $widgetTwo = $(el).find('.responsiveImage-widget').eq(1); 4746 if ($($widgetTwo).find('.button-div').length) { 4747 $($widgetTwo).css('margin-bottom', '40px'); 4748 } 4749 } 4750 var $widgetThree = $(el).find('.responsiveImage-widget').eq(2); 4751 if (!$($widgetThree).find('.button-div').length) { 4752 $(el).css('margin-bottom', '0px'); 4753 } 4754 }); 4755 } 4756 4757 if (($responsiveImageX4Container = $(".responsiveImageX4-container")).length) { 4758 $responsiveImageX4Container.each(function (index, el) { 4759 if ($(el).hasClass('gutter')) { 4760 var $widgetOne = $(el).find('.responsiveImage-widget').eq(0); 4761 if ($($widgetOne).find('.button-div').length) { 4762 $($widgetOne).css('margin-bottom', '40px'); 4763 } 4764 var $widgetTwo = $(el).find('.responsiveImage-widget').eq(1); 4765 if ($($widgetTwo).find('.button-div').length) { 4766 $($widgetTwo).css('margin-bottom', '40px'); 4767 } 4768 var $widgetThree = $(el).find('.responsiveImage-widget').eq(2); 4769 if ($($widgetThree).find('.button-div').length) { 4770 $($widgetThree).css('margin-bottom', '40px'); 4771 } 4772 } 4773 4774 var $widgetThree = $(el).find('.responsiveImage-widget').eq(2); 4775 var $widgetFour = $(el).find('.responsiveImage-widget').eq(3); 4776 if (!$($widgetThree).find('.button-div').length && !$($widgetFour).find('.button-div').length) { 4777 $(el).css('margin-bottom', '0px'); 4778 } 4779 }); 4780 } 4781 } 4782} 4783 4784function setTwoColImageButtonsDisplay() { 4785 $('.twoColumnImageText-container .media-story .button-div').each(function () { 4786 var $left = $(this).find('a'); 4787 var $right = $left.next('a'); 4788 var diff = 0; 4789 if ($right.length && $left.length) 4790 diff = $right.offset().top - $left.offset().top; 4791 4792 if (!$right.hasClass('full-width-button') && diff > 0) { 4793 $right.addClass('full-width-button').addClass('full-width-button-right'); 4794 $left.addClass('full-width-button'); 4795 } else if ($right.hasClass('full-width-button') && diff === 0) { 4796 $right.removeClass('full-width-button').removeClass('full-width-button-right'); 4797 $left.removeClass('full-width-button'); 4798 $left.width('auto'); 4799 $right.width('auto'); 4800 } 4801 if ($right.hasClass('full-width-button')) { 4802 $left.width('auto'); 4803 $right.width('auto'); 4804 if ($right.width() > $left.width()) { 4805 $left.width($right.width()); 4806 $right.width('auto'); 4807 } else if ($left.width() > $right.width()) { 4808 $right.width($left.width()); 4809 $left.width('auto'); 4810 } 4811 } 4812 });
4813} 4814 4815 4816function setClubExclusivePriceDisplay() { 4817 $('.exclusive-product-item .club-price').each(function () { 4818 var $left = $(this).find('.left'); 4819 var $right = $(this).find('.price-right'); 4820 var diff = $right.offset().top - $left.offset().top; 4821 4822 if ($right.hasClass('right') && diff > 0) { 4823 $right.removeClass('right').addClass('left'); 4824 } 4825 else if ($right.hasClass('left') && diff === 0) { 4826 $right.removeClass('left').addClass('right'); 4827 } 4828 }); 4829 4830 $('.exclusive-product-item .sub-text').each(function () { 4831 var $left = $(this).find('.left'); 4832 var $right = $(this).find('.text-right'); 4833 var diff = $right.offset().top - $left.offset().top; 4834 4835 if ($right.hasClass('right') && diff > 0) { 4836 $right.removeClass('right').addClass('left'); 4837 } 4838 else if ($right.hasClass('left') && diff === 0) { 4839 $right.removeClass('left').addClass('right'); 4840 } 4841 }); 4842} 4843 4844//make the text media container's text have a scroll bar and its height set to its media sibling
4845function initTextMediaScroll(containers) { 4846 var $containers = $(containers); 4847 4848 //set max-height on the text block to the adjacent image so we overflow and get a scroll bar 4849 if (matchMedia('(min-width:961px)').matches) { 4850 $containers.find(".media-story").each(function () { 4851 var $this = $(this); 4852 var imgHeight = $this.children('.img').outerHeight(); 4853 $this.children('.text').css('max-height', imgHeight) 4854 4855 setTimeout(function () { 4856 var imgHeight2 = $this.children('.img').outerHeight(); // double-check it, seems to matter more on Safari 4857 if (imgHeight != imgHeight2) { 4858 $this.children('.text').css('max-height', imgHeight2) 4859 } 4860 }, 100); 4861 }); 4862 } else { 4863 $containers.find(".media-story > .text").css('max-height', ''); 4864 } 4865} 4866 4867function createClubExclusiveSlickSlider() { 4868 var $ss = $('.club-exclusives-ss .inner-wrap'); 4869 if (!$ss.hasClass('slick-initialized')) { 4870 $ss.slick({ 4871 arrows: true, 4872 infinite: true, 4873 dots: true, 4874 slidesToShow: 1, 4875 slidesToScroll: 1 4876 }); 4877 } 4878} 4879 4880function destroyClubExclusiveSlickSlider() { 4881 var $ss = $(".club-exclusives-ss .inner-wrap"); 4882 if ($ss.hasClass('slick-initialized')) { 4883 $ss.slick('unslick'); 4884 } 4885} 4886 4887function mobilizeWysiwigFonts() { 4888 $(".bcwp .base-container p span").each(function() { 4889 var fontSize = $(this).css("fontSize"); 4890 switch (fontSize) { 4891 case "60px": 4892 $(this).css("fontSize", "42px"); 4893 break; 4894 case "42px": 4895 $(this).css("fontSize", "36px"); 4896 break; 4897 case "30px": 4898 $(this).css("fontSize", "27px"); 4899 break; 4900 } 4901 }); 4902}; 4903var numSlickProductSliders = 0; 4904var workSlickProductSliders = 0; 4905var lastFocus; 4906var windowSize = 0; 4907 4908domReady(function () { 4909 //fire off resize handler for responsive js when window size changes 4910 //from now on to break up js, we will need to add an event listener to the resize event for individual controls 4911 windowSize = $(window).width(); 4912 var resizeHandler = function () { 4913 $(window).on("resize", function () { 4914 if (windowSize !== $(window).width()) { 4915 windowSize = $(window).width(); 4916 } 4917 }); 4918 } 4919 //we were losing the resize event listener using $(window).resize due to an mmenu collision 4920 $(function () { window.addEventListener('resize', resizeHandler, false); }); 4921 4922 //test for csscalc support 4923 Modernizr.addTest('csscalc', function () { 4924 var prop = 'width:'; 4925 var value = 'calc(10px);'; 4926 var el = document.createElement('div'); 4927 4928 el.style.cssText = prop + Modernizr._prefixes.join(value + prop); 4929 4930 return !!el.style.length; 4931 }); 4932 if (!Modernizr.csscalc) { 4933 $("html").addClass("no-csscalc"); 4934 } 4935 4936 //fix for keyboard open and position fixed elements with iOS 4937 if (Modernizr.touch) { 4938 var $body = $('body'); 4939 4940 $(document).on('focus', 'input:not(#searchMobile), textarea, select, md-select-menu', function () { 4941 $body.addClass('ios-kb-fix'); 4942 }).on('blur', 'input, textarea, select, md-select-menu', function () { 4943 $body.removeClass('ios-kb-fix'); 4944 }); 4945 } 4946 4947 //init custom form elements 4948 Gorilla.util.initForms(); 4949 4950 if (($modalTrigger = $('.trigger-modal')).length) { 4951 $modalTrigger.moby({ 4952 'modalClass': 'generic' 4953 }); 4954 } 4955 4956 initToolTips(); 4957 4958 if (($lazyImg = $('.lazy')).length) { 4959 $lazyImg.lazy(); 4960 } 4961 4962 //Init default sliders, use data api to set items count and margins 4963 if (($slider = $('.default-slider .products-grid')).length) { 4964 if (!$slider.hasClass('slick-initialized')) { 4965 $slider.slick({ 4966 dots: false, 4967 arrows: true, 4968 slidesToShow: 4, 4969 slidesToScroll: 4, 4970 infinite: false, 4971 lazyLoad: 'ondemand', 4972 prevArrow: '<span class="sg-slick-prev" role="button" aria-label="Previous" tabindex="0"> ‹ </span>', 4973 nextArrow: '<span class="sg-slick-next" role="button" aria-label="Next" tabindex="0"> › </span>', 4974 responsive: [ 4975 { 4976 breakpoint: 1060, 4977 settings: { 4978 slidesToShow: 3, 4979 slidesToScroll: 3, 4980 arrows: true, 4981 dots: true 4982 } 4983 }, 4984 { 4985 breakpoint: 768, 4986 settings: { 4987 slidesToShow: 2, 4988 slidesToScroll: 2, 4989 arrows: true, 4990 dots: true 4991 } 4992 }, 4993 { 4994 breakpoint: 480, 4995 settings: { 4996 slidesToShow: 1, 4997 slidesToScroll: 1, 4998 arrows: true, 4999 dots: true 5000 } 5001 } 5002 ] 5003 }); 5004 numSlickProductSliders += $('.default-slider .products-grid').length; 5005 $slider.on("breakpoint", function (event, slick, breakpoint) { 5006 event.preventDefault(); 5007 processSlickProductSliders(); 5008 }); 5009 } 5010 } 5011 5012 //brands carousel slider 5013 if (($brandslider = $('.slick-brands-carousel')).length) { 5014 if (!$brandslider.hasClass('slick-initialized')) { 5015 $brandslider.slick({ 5016 dots: false, 5017 infinite: true, 5018 respondTo: 'slider', 5019 slidesToShow: 8, 5020 slidesToScroll: 8, 5021 prevArrow: '<span class="sg-slick-prev" role="button" aria-label="Previous" tabindex="0"> ‹ </span>',/*Needs styles*/ 5022 nextArrow: '<span class="sg-slick-next" role="button" aria-label="Next" tabindex="0"> › </span>', 5023 responsive: [ 5024 { 5025 breakpoint: 1400, 5026 settings: { 5027 slidesToShow: 7, 5028 slidesToScroll: 7 5029 } 5030 }, 5031 { 5032 breakpoint: 1200, 5033 settings: { 5034 slidesToShow: 6, 5035 slidesToScroll: 6 5036 } 5037 }, 5038 { 5039 breakpoint: 1060, 5040 settings: { 5041 slidesToShow: 5, 5042 slidesToScroll: 5 5043 } 5044 }, 5045 { 5046 breakpoint: 960, 5047 settings: { 5048 slidesToShow: 4, 5049 slidesToScroll: 4 5050 } 5051 }, 5052 { 5053 breakpoint: 680, 5054 settings: { 5055 slidesToShow: 3, 5056 slidesToScroll: 3 5057 } 5058 }, 5059 { 5060 breakpoint: 480, 5061 settings: { 5062 slidesToShow: 2, 5063 slidesToScroll: 2 5064 } 5065 }, 5066 { 5067 breakpoint: 320, 5068 settings: { 5069 slidesToShow: 1, 5070 slidesToScroll: 1, 5071 variableWidth: true, 5072 centerMode: true,
5073 arrows: false 5074 } 5075 } 5076 ] 5077 }); 5078 $brandslider.find('img').show(); 5079 } 5080 } 5081 5082 if (($navslider = $('.navigation-carousel .bcwp-widgets-wrapper')).length) { 5083 if (!$navslider.hasClass('slick-initialized')) { 5084 $navslider.slick({ 5085 dots: false, 5086 infinite: true, 5087 respondTo: 'slider', 5088 slidesToShow: 6, 5089 slidesToScroll: 6, 5090 prevArrow: '<span class="sg-slick-prev-gray" role="button" aria-label="Previous" tabindex="0"></span>', 5091 nextArrow: '<span class="sg-slick-next-gray" role="button" aria-label="Next" tabindex="0"></span>', 5092 responsive: [ 5093 { 5094 breakpoint: 1400, 5095 settings: { 5096 slidesToShow: 6, 5097 slidesToScroll: 6 5098 } 5099 }, 5100 { 5101 breakpoint: 1060, 5102 settings: { 5103 slidesToShow: 5, 5104 slidesToScroll: 5 5105 } 5106 }, 5107 { 5108 breakpoint: 960, 5109 settings: { 5110 slidesToShow: 4, 5111 slidesToScroll: 4 5112 } 5113 }, 5114 { 5115 breakpoint: 680, 5116 settings: { 5117 slidesToShow: 3, 5118 slidesToScroll: 3 5119 } 5120 } 5121 ] 5122 }); 5123 } 5124 } 5125 5126 //lifestyle plus 5 slider 5127 if (($lsp5slider = $('.lifestylePlusFive-container .bcwp-widgets-wrapper')).length) { 5128 if (!$lsp5slider.hasClass('slick-initialized')) {
5129 $lsp5slider.slick({ 5130 dots: false, 5131 infinite: true, 5132 respondTo: 'slider', 5133 slidesToShow: 1, 5134 slidesToScroll: 1, 5135 prevArrow: '<span class="sg-slick-prev-gray" role="button" aria-label="Previous" tabindex="0"></span>', 5136 nextArrow: '<span class="sg-slick-next-gray" role="button" aria-label="Next" tabindex="0"></span>', 5137 autoplay: false, 5138 autoplaySpeed: 5000 5139 }); 5140 } 5141 } 5142 5143 //new product tiles.. since we cant put an anchor inside an anchor we have to show the quickview using javascript :( 5144 if ($(".product-tile").length) { 5145 $(document).on("mouseenter mouseleave", ".product-tile .product-image, .product-tile .btn-quickview", function (e) { 5146 if (e.type === "mouseenter") { 5147 $(this).closest(".product-tile").find(".btn-quickview").addClass("show"); 5148 } else { 5149 $(this).closest(".product-tile").find(".btn-quickview").removeClass("show"); 5150 } 5151 }); 5152 } 5153 5154 /** 5155 * keep body from scrolling when nav menu is open in iOS 5156 */ 5157 $(document).on('touchmove', function (e) { 5158 if ($('body').hasClass('nav-showing')) { 5159 var $target = $(e.target); 5160 if ($target.is('#nav-wrapper') || $target.parents('#nav-wrapper')) { 5161 e.stopPropagation(); 5162 } 5163 } 5164 }); 5165 5166 // a simple pair of classes was addded to truncate top and bottom abstracts with "..." on mobile 5167 // this allows user to expand and read the whole section if desired. 5168 $(document).on("click", ".single-line-ellipsis-trigger", function () { 5169 $(this).toggleClass("single-line-ellipsis"); 5170 }); 5171 5172 //handle nested links in a button for A360 5173 $(document).on("click", "button.tool-tip", function (e) { 5174 if (e.target.tagName.toLowerCase() === 'a') // let nested links work 5175 return true; 5176 5177 e.preventDefault(); 5178 e.stopPropagation(); 5179 }); 5180 5181 //animate labels to shrink and anchor to left corner to solve the placeholder texts always being visible ADA issue 5182 if (($anchorLabel = $(".input-wrapper .anchor-label")).length) { 5183 $anchorLabel.each(function () { 5184 var $input = $("#" + $(this).attr("for")); 5185 if ($input.length) { 5186 $input.on('focusin', function () { 5187 $(this).closest(".input-wrapper").addClass("anchored"); 5188 }).on('focusout', function () { 5189 if (!$(this).val()) { 5190 $(this).closest(".input-wrapper").removeClass("anchored"); 5191 } 5192 }); 5193 } 5194 }); 5195 } 5196 5197 //fire the resize handler after we are fully ready... THIS LINE SHOULD BE LAST 5198 toolsResizeHandler(); 5199}); //end dom ready 5200 5201 5202 5203//RESPONSIVE 5204var toolsResizeHandler = function () { 5205 //fix for back button issue with mobile menu in IE... IE doesnt support the library's use of window.history.back() 5206 //this is unbound then bound as the menu can be created/destroyed based on breakpoint shifts 5207 var closeEvent = function () { 5208 if (($currentMenu = $('.mm-menu.mm-current.mm-menu_opened')).length) { 5209 $currentMenu.data("mmenu").close(); 5210 lastFocus.focus(); 5211 } 5212 } 5213 $(document).off("click", "a.mm-btn, a.mm-title", closeEvent).on("click", "a.mm-btn, a.mm-title", closeEvent); 5214 5215 if (matchMedia('(min-width: 961px)').matches) { 5216 //reset the nav cover, may have been manipulated if they went down to mobile and then back up to desktop 5217 $(".nav-cover-x").toggleClass("nav-cover nav-cover-x"); 5218 5219 if ($("#mm-nav").length) { //destroy mobile controls if orientation changed 5220 $("#mm-nav").gorillaAccordion('unset'); 5221 $("#mm-nav").find('.drop-down').gorillaAccordion('unset'); 5222 destroyMmenu(); 5223 } 5224 5225 $('body').removeClass('mobileVideo'); 5226 } 5227 5228 if (matchMedia('(max-width: 960px)').matches) { 5229 //remove the nav cover if they ever hit this breakpoint, it can cause an issue with a tablet in landscape mode 5230 $(".nav-cover").hide().toggleClass("nav-cover nav-cover-x"); 5231 $('body').addClass('mobileVideo'); 5232 } 5233 5234 if (matchMedia('(min-width: 480px) and (max-width: 730px)').matches) { 5235 $('body').removeClass('mobile'); 5236 } 5237 5238 if (matchMedia('(min-width: 480px) and (max-width: 560px)').matches) { 5239 $('body').removeClass('mobile'); 5240 } 5241 5242 if (matchMedia('(min-width: 300px) and (max-width: 479px)').matches) { 5243 $('body').addClass('mobile'); 5244 } 5245} 5246window.addEventListener('resize', toolsResizeHandler); 5247 5248 5249 5250function initToolTips() { //lazy-load tool tips on demand.. but not the fake ones (ffl lookup) 5251 $(document).on("click mouseover", "button.tool-tip:not(.not-really)", function (e) { 5252 e.preventDefault(); 5253 var $tip = $(this); 5254 if (!$tip.data('isSet')) { 5255 $tip.tipsy({ 5256 bounds: $('body'), 5257 //show method not publicly exposed... re-fire the event to show the tip after its wired up 5258 afterInitCallback: function () { 5259 if ($(window).width() > 960) { $tip.trigger('click'); } 5260 } 5261 }); 5262 } 5263 });
5264} 5265 5266//this function will de-parameterize a multi-value cookie to easily be able to retrieve a specific value 5267function deparamCookie(params) { 5268 var o = {}; 5269 if (!params) return o; 5270 var a = params.split('&'); 5271 for (var i = 0; i < a.length; i++) { 5272 var pair = a[i].split('='); 5273 o[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); 5274 } 5275 return o; 5276} 5277 5278function trapFocus(element) { 5279 var focusableEls = 5280 element.find( 5281 'a[href], button:not(.magic-thumbs-button-disabled,[tabindex="-1"],.i18n), textarea, input[type="button"], input[type="text"], input[type="radio"], input[type="checkbox"], select, [tabindex]:not([tabindex="-1"])'), 5282 firstFocusableEl = focusableEls.first()[0], 5283 lastFocusableEl = focusableEls.last()[0], 5284 TABKEYCODE = 9, 5285 ARROWLEFTCODE = 37, 5286 ARROWUPCODE = 38, 5287 ARROWRIGHTCODE = 39, 5288 ARROWDOWNCODE = 40; 5289 5290 if (firstFocusableEl != null) { firstFocusableEl.focus(); } 5291 5292 $(element).off('keydown').on('keydown', function (e) { 5293 // tab (no shift) or the right/down keys 5294 var next = e.key === 'ArrowRight' || e.keyCode === ARROWRIGHTCODE || e.key === 'ArrowDown' || e.keyCode === ARROWDOWNCODE || ((e.key === 'Tab' || e.keyCode === TABKEYCODE) && !e.shiftKey); 5295 // tab (with shift) or the left/up keys 5296 var prev = e.key === 'ArrowLeft' || e.keyCode === ARROWLEFTCODE || e.keyCode === 'ArrowUp' || e.keyCode === ARROWUPCODE || ((e.key === 'Tab' || e.keyCode === TABKEYCODE) && e.shiftKey); 5297 5298 if (!next && !prev) { 5299 return; 5300 } 5301 5302 if (next && document.activeElement === lastFocusableEl) {
5303 firstFocusableEl.focus(); 5304 e.preventDefault(); 5305 } 5306 if (prev && document.activeElement === firstFocusableEl) { 5307 lastFocusableEl.focus(); 5308 e.preventDefault(); 5309 } 5310 }); 5311} 5312 5313function initSGAccordian(openByDefault) { 5314 // wire up events 5315 $(document).on("click", ".sg-accordion-header", function () { 5316 $this = $(this); 5317 $this.toggleClass("active"); 5318 $this.next().slideToggle(250); // the very next element had better be the content... 5319 5320 if (($button = $(".sg-accordion-header-button", $this)).length > 0) { 5321 $button.attr("aria-expanded", $this.hasClass("active")); // A360/ADA -- set aria-expanded as appropriate 5322 } 5323 }); 5324 5325 $(document).on("click", "#accordion-controls-container #expand-all", function () { 5326 $(".sg-accordion-header").each(function (i, v) { // TODO: this selector is probably not specific enough, maybe pass the parent container in? :/ 5327 $this = $(this); 5328 $this.addClass("active"); 5329 5330 if (($button = $(".sg-accordion-header-button", $this)).length > 0) { 5331 $button.attr("aria-expanded", true); 5332 } 5333 }); 5334 5335 $(".sg-accordion-content").slideDown(); 5336 }); 5337 5338 $(document).on("click", "#accordion-controls-container #collapse-all", function () { 5339 $(".sg-accordion-header").each(function (i, v) { // TODO: this selector is probably not specific enough, maybe pass the parent container in? :/ 5340 $this = $(this); 5341 $this.removeClass("active"); 5342 5343 if (($button = $(".sg-accordion-header-button", $this)).length > 0) { 5344 $button.attr("aria-expanded", false); 5345 } 5346 }); 5347 $(".sg-accordion-content").slideUp(); 5348 }); 5349 5350 if (openByDefault) { 5351 // have all panels open by default 5352 $(".sg-accordion-header").addClass("active"); // TODO: this selector is probably not specific enough, maybe pass the parent container in? :/ 5353 $(".sg-accordion-content").show(); // need it fast! // TODO: this selector is probably not specific enough, maybe pass the parent container in? :/ 5354 } 5355 5356 // deal with some FAQ's specific A360/ADA things... Seems like this could be applied to all instances of our .sg-accordion-header, but limiting to the FAQs for now 5357 $("#faqsV3 .sg-accordion-header").each(function (i, v) { 5358 var $this = $(this); 5359 var $next = $this.next(); // the very next element had better be the content... 5360 5361 // generate and assign an id to the associated content block, if needed 5362 var nextId = $next.attr("id"); 5363 if (nextId == undefined) { 5364 nextId = "sgac-" + i; 5365 $next.attr("id", nextId); 5366 } 5367 5368 // add the aria- stuff to $this 5369 if (($button = $(".sg-accordion-header-button", $this)).length > 0) { 5370 $button.attr("aria-expanded", $this.hasClass("active")); 5371 $button.attr("aria-controls", nextId); 5372 } 5373 }); 5374} 5375 5376function processSlickProductSliders() { 5377 workSlickProductSliders++; 5378 if (workSlickProductSliders == numSlickProductSliders) { 5379 $(document).find(".btn-quickview > button").each(function () { 5380 $(this).removeClass("bound"); 5381 $(this).removeClass("bound961"); 5382 }); 5383 initResponsive(); 5384 workSlickProductSliders = 0; 5385 } 5386} 5387 5388function enableTabIndicators(e) { 5389 if (e.keyCode === 9) { // keyboard tabber detected! 5390 document.body.classList.add('user-tab-detected'); 5391 window.removeEventListener('keydown', enableTabIndicators); 5392 } 5393} 5394window.addEventListener('keydown', enableTabIndicators); 5395 5396function setLeftNavActiveLinkProps() { 5397 $("#left-navigation li.active a").each(function (i, v) { // had better be one and only one. if not, last one wins 5398 var $activeAnchor = $(this); 5399 $activeAnchor.attr("aria-current", "page"); 5400 $activeAnchor.closest("aside#left-navigation").attr("aria-label", $activeAnchor.text() + " navigation"); // I asked / double-checked that this should be "page name" vs. "layout name" and A360 was pretty adamant 5401 });
5402} 5403 5404function destroyMmenu() { 5405 $("div#mm-nav").remove(); 5406 $("aside#mm-filters-menu").remove(); 5407 $("div#mm-left-navigation").remove(); 5408 5409 $("#filter-toggle").off("click"); 5410 $("#col-left-menu-toggle").off("click"); 5411} 5412 5413function initializeSlider(id) { // used to be in DynamicDataScript.cshmlt but we want to use it in angularized ViewCart as well 5414 //Init default sliders, use data api to set items count and margins 5415 if (($slider = $(id + ' .products-grid')).length) { 5416 if (!$slider.hasClass('slick-initialized')) { 5417 $slider.slick({ 5418 accessibility: true, 5419 dots: false, 5420 arrows: true, 5421 slidesToShow: 5, 5422 slidesToScroll: 5, 5423 infinite: false, 5424 lazyLoad: 'ondemand', 5425 prevArrow: '<span class="sg-slick-prev" role="button" aria-label="Previous" tabindex="0"> <img class="sg-carousel" src="/images/product/icon-image-left.svg"> </span>', 5426 nextArrow: '<span class="sg-slick-next" role="button" aria-label="Next" tabindex="0"> <img class="sg-carousel" src="/images/product/icon-image-right.svg"> </span>', 5427 responsive: [ 5428 { 5429 breakpoint: 1250, 5430 settings: { 5431 slidesToShow: 4, 5432 slidesToScroll: 4, 5433 arrows: true, 5434 dots: true 5435 } 5436 }, 5437 { 5438 breakpoint: 1060, 5439 settings: { 5440 slidesToShow: 3, 5441 slidesToScroll: 3, 5442 arrows: true, 5443 dots: true 5444 } 5445 }, 5446 { 5447 breakpoint: 768, 5448 settings: { 5449 slidesToShow: 2, 5450 slidesToScroll: 2, 5451 arrows: true, 5452 dots: true 5453 } 5454 }, 5455 { 5456 breakpoint: 480, 5457 settings: { 5458 slidesToShow: 1, 5459 slidesToScroll: 1, 5460 arrows: true, 5461 dots: true 5462 } 5463 } 5464 ] 5465 }); 5466 numSlickProductSliders++; 5467 $slider.on("breakpoint", function (event, slick, breakpoint) { 5468 event.preventDefault(); 5469 processSlickProductSliders(); 5470 }); 5471 } 5472 } 5473} 5474 5475 5476// if they click / tap on a slider in mobile this should be used to take 5477// care of any underlying link / anchor 5478// used during click: function, sister function to swipe: function 5479function sliderTap(event, target) { 5480 switch ($(target).get(0).tagName.toLowerCase()) { 5481 case "a": 5482 document.location.href = target; 5483 break; 5484 case "img": 5485 // this only goes up one level, obviously... 5486 var p = $(target).parent(); 5487 if (p.get(0).tagName.toLowerCase() == "a") { 5488 document.location.href = p.attr("href"); 5489 } 5490 break; 5491 } 5492} 5493 5494function initQtyButtons(containerName) { //qty adjust buttons 5495 if (($container = $(containerName)).length) { 5496 setTimeout(function() { 5497 $(".qty-adjust", $container).click(function (e) { 5498 e.preventDefault(); 5499 5500 var $this = $(this); 5501 var $form = $this.closest("form"); 5502 var $qty = $("#quantity", $form); 5503 var qty = $qty.val(); 5504 5505 // manage new version (button w/ enhanced ADA) vs old version (div no ADA) 5506 if ($this.prop("tagName").toLowerCase() === "button") { // new approach
5507 if ($this.data("direction") == "plus" && qty < 99) { 5508 qty++; 5509 $(".qty-minus").prop("disabled", false); 5510 } else if ($this.data("direction") == "minus" && qty > 1) { 5511 qty--; 5512 if (qty == 1) { 5513 $(".qty-minus").prop("disabled", true); 5514 } 5515 } 5516 } else { // old approach, should go away after PDP A/B test is complete and everything is rolled over to new version 5517 if ($this.text() == "+" && qty < 99) { 5518 qty++; 5519 } else if ($this.text() == "-" && qty > 1) { 5520 qty--; 5521 } 5522 } 5523 5524 // safety / default 5525 if (!$.isNumeric(qty) || qty < 1) { 5526 qty = 1; 5527 } 5528 5529 $qty.val(qty); 5530 $form.validate().element($qty); 5531 }); 5532 }, 1000); 5533 } 5534} 5535 5536function initFitRating(containerName, currentValue) { 5537 if (($container = $(containerName)).length) { 5538 if (($fitRating = $("#BVFitRating", $container)).length) { 5539 $fitRating.slider({ 5540 range: "max", 5541 min: 1, 5542 max: 5, 5543 step: 0.01, 5544 value: currentValue, 5545 disabled: true, 5546 create: function (event, ui) { 5547 setSliderTicks(event.target); 5548 } 5549 }); 5550 } 5551 } 5552} 5553 5554function initWidthRating(containerName, currentValue) { 5555 if (($container = $(containerName)).length) { 5556 if (($widthRating = $("#BVWidthRating", $container)).length) { 5557 $widthRating.slider({ 5558 range: "max", 5559 min: 1, 5560 max: 3, 5561 step: 0.1, 5562 value: currentValue, 5563 disabled: true, 5564 create: function (event, ui) { 5565 setSliderTicks(event.target); 5566 } 5567 }); 5568 } 5569 } 5570} 5571 5572 5573//auto selects the only option in the size/color dropdowns 5574//function initAutoSelect(form) { 5575// var $form = $(form); 5576// processSelectedProductOption($form.find('.auto-select')); 5577//} 5578 5579/****************************** Truncate ad copy*******************************************/ 5580 5581function truncateQuickViewAdCopy(quickViewForm) { 5582 var overflowMaxHeight = 400; 5583 var productDesc = quickViewForm.find('.product-description'), 5584 productMore = quickViewForm.find('#quickViewMoreDetails'); 5585 truncateElementTextToHeight(productDesc, overflowMaxHeight); 5586 productMore.detach().appendTo(productDesc.children().last()); 5587} 5588 5589function truncateElementTextToHeight(elem, overflowMaxHeight) { 5590 if (elem.height() > overflowMaxHeight) { 5591 do { 5592 var lastChild = elem.children().last(); 5593 if ((lastChild.is('ul')) && (lastChild.children().length > 0)) { 5594 lastChild.children().last().remove(); 5595 if (lastChild.children().length == 0) { 5596 lastChild.remove(); 5597 } 5598 } 5599 else { 5600 var text = elem.html(); 5601 text = text.slice(0, text.lastIndexOf(" ")); 5602 elem.html(text); 5603 } 5604 } while (elem.height() > overflowMaxHeight); 5605 } 5606} 5607 5608/****************************** Bloomreach Related Product Quick View Image Swap *******************************************/ 5609 5610function swapBRRelProdImage(anchor) { 5611 var $id = anchor.href.substr(anchor.href.lastIndexOf('#') + 1); 5612 var $div = $("div[id=" + $id + "]"); 5613 var $img = $div.find('img.brRelProd'); 5614 if ($img.length) { 5615 $img.attr("src", $img.attr("data-br-src").replace("/m/", "/e/")); 5616 } 5617 $div.find("#alternate-images img").each(function () { 5618 $(this).attr("src", $(this).attr("data-br-src").replace("/m/", "/e/")); 5619 }); 5620} 5621 5622 5623function autoselectAttributeIfSingle($ddl) { 5624 5625 if ($ddl.length === 0 || $ddl.hasClass("auto-select")) 5626 return; 5627 5628 var $opts = $("option", $ddl); 5629 if ($opts.length === 2) { // "Select an Option" + 1 value 5630 $opts.prop("selected", false); // unset them all 5631 $($opts[1]).prop("selected", "selected"); // make the first one selected 5632 $ddl.change(); // trigger the change event 5633 } 5634} 5635 5636function checkQtyLimit($form) { 5637 var limit = $form.find("#hdnPurchaseQtyLimit").val(); 5638 if (limit === "0" || limit === "99") return false; 5639 setTimeout(function() { 5640 $form.find('#quantity').attr('type', 'number').attr('max', limit); 5641 }, 1000); 5642 if ($form.find("#ammoQtyLimit").length) { 5643 $form.find("#ammoQtyLimit").text(limit); 5644 } else { 5645 $form.find('.pdp-title-flex-container').first().after( 5646 '<div class="bold-text" style="color:#54565a;">* THIS ITEM HAS A LIMIT OF <span id="ammoQtyLimit">' + 5647 limit + '</span> PER ORDER.</div>'); 5648 } 5649}; 5650var $initFooterLinksAccordion = true; 5651var promoCarouselTimeout; 5652var mmenuCloseHookup = true; 5653domReady(function() { 5654 5655 //promo banner "tool tips" 5656 $(document).on("click", ".promo-trigger", function () { 5657 var message = $(this).next("hdncontent"); 5658 $("#site-promo-modal").html(message.text()); 5659 5660 $("#site-promo-modal-trigger").moby({ 5661 //'modalClass': 'cart-limit-modal gradient-gray', 5662 'ariaLabelText': 'Promotion', 5663 'onCompleteCallback': function () { 5664 $(".moby-close").on('click', function (event) { 5665 event.preventDefault(); 5666 $("#site-promo-modal-trigger").moby('hide'); 5667 }); 5668 } 5669 }).moby('show', '#site-promo-modal'); 5670 });
5671 5672 //PDP lightbox "tool tips" 5673 $(document).on("click", ".tooltip-button", function () { 5674 var message = $(this).next(".tooltip-content"); 5675 5676 /* console.log(message[0].innerHTML);*/ 5677 $("#site-modal").html(message[0].innerHTML); 5678 5679 $("#site-modal-trigger").moby({ 5680 'modalClass': 'tooltip-modal', 5681 'ariaLabelText': 'tooltip', 5682 'onCompleteCallback': function () { 5683 $(".moby-close").on('click', function (event) { 5684 event.preventDefault(); 5685 $("#site-modal-trigger").moby('hide'); 5686 }); 5687 } 5688 }).moby('show', '#site-modal'); 5689 }); 5690 5691 // setup a custom override of the jquery-ui's _renderMenu function 5692 $.widget("ui.autocomplete", $.ui.autocomplete, { 5693 options: { 5694 maxItems: 9999 // adds this maxItems property to the object and default to 9999, usually overridden during specific .autocomplete({ inits 5695 }, 5696 _renderMenu: function (ul, items) { // override jQuery-Ui's _renderMenu so we can make use of the maxItems as needed 5697 var that = this; 5698 $.each(items, function (index, item) { // google says this goes in order that they appear in the DOM 5699 if (index < that.options.maxItems) { 5700 that._renderItemData(ul, item); 5701 } 5702 }); 5703 } 5704 }); 5705 5706 //Canada/International Shopping Modal 5707 $(document).on("click", "a.international", function () { 5708 var $intlMoby = $(this).moby({ 5709 'modalClass': 'generic intl-shopping-modal', 5710 'ariaLabelText': 'International options', 5711 'onCompleteCallback': function () { 5712 Gorilla.util.initForms(); 5713 $('#intl-shopping-form').validate(); 5714 $("#intl-shopping").find(".close-link").on("click", function (e) { 5715 e.preventDefault(); 5716 $intlMoby.off('click.moby'); 5717 $intlMoby.moby('remove'); 5718 }); 5719 $(".intl-shopping-modal .moby-close").on("click", function () { 5720 $(this).parent().find('.close-link').click(); 5721 }); 5722 } 5723 }).moby('show', '#intl-shopping'); 5724 }); 5725 5726 var fnSkipToContent = function () { 5727 focusOnFirstEl($("#main[role='main']")); 5728 } 5729 5730 $("#skipToContent > a").on("click", fnSkipToContent); 5731 $("#skipToContent > a").on('keypress', function (e) { 5732 if (e.which === 13) { fnSkipToContent(); } 5733 }); 5734 5735 //allow the space bar to work on mock button elements 5736 $(document).on("keypress", "span[role=button]", function(e) { 5737 e.preventDefault(); 5738 if (e.which === 32) $(this).click(); 5739 }); 5740 5741 //fire the resize handler after we are fully ready... THIS LINE SHOULD BE LAST 5742 layoutResizeHandler(); 5743}); 5744 5745 5746 5747//RESPONSIVE 5748var layoutResizeHandler = function () { 5749 if (matchMedia('(min-width:961px)').matches) { 5750 //Large screens, full menu 5751 $('.shop').find('.fly-out').html("<h4><span>Loading...</span></h4>"); 5752 $('.shop').find('.fly-out').addClass('auto-height'); 5753 5754 if (($nav = $('#nav')).length) { 5755 //init main nav 5756 if (!$nav.attr("data-dropit")) { 5757 $nav.DropIt({ 5758 'triggerSelector': 'li.level-top', 5759 'menuSelector': '.drop-down', 5760 'speed': 0, 5761 'delay': 0, 5762 'showCover': true 5763 }); 5764 } 5765 5766 if (!$nav.find('.shop ul.level0').attr('data-dropit')) { 5767 $nav.find('.shop ul.level0').DropIt({ 5768 'triggerSelector': '> li', 5769 'menuSelector': '.fly-out', 5770 'speed': 0, 5771 'delay': 200, 5772 'onHover': function (elm) { 5773 var $this = $(elm), 5774 busy = false; 5775 5776 if (busy || $this.data('loaded')) { 5777 return; 5778 } 5779 5780 $.ajax({
5781 url: $this.data('menu'), 5782 type: 'post', 5783 dataType: 'html', 5784 beforeSend: function () { 5785 busy = true 5786 } 5787 }) 5788 .done(function (html) { 5789 $this.find('> a').after(html).end().data('loaded', true); 5790 $nav.find('ul.level0').DropIt('showMenu', $this.find('.fly-out')); 5791 }) 5792 .always(function () { 5793 busy = false; 5794 }) 5795 } 5796 }); 5797 } 5798 } 5799 5800 bindDesktopSearch(); 5801 hookUpQuickViews(document); 5802 5803 //footer accordion unset 5804 if (($accordion = $('#footer').find('.accordion')).length) { 5805 $accordion.gorillaAccordion('unset'); 5806 } 5807 $initFooterLinksAccordion = true; 5808 5809 } 5810 5811 if (matchMedia('(min-width: 961px)').matches) { 5812 //site wide promo message banner 5813 if ($('#site-wide-promos').length) { 5814 destroySiteWidePromoSlickSlider(); 5815 } 5816 } else { 5817 //site wide promo message carousel 5818 if ($('#site-wide-promos').length) { 5819 createSiteWidePromoSlickSlider(); 5820 } 5821 } 5822 5823 if (matchMedia('(max-width: 960px)').matches) { 5824 //mobile navigation init 5825 if (($nav = $('#nav')).length) { 5826 if ($nav.DropIt) { 5827 $nav.DropIt('unset'); 5828 $nav.find('ul.level0').DropIt('unset'); 5829 } 5830 } 5831 5832 //footer accordion init 5833 if (($accordion = $('#footer').find('.accordion')).length) { 5834 if ($initFooterLinksAccordion) { 5835 $accordion.gorillaAccordion({ 5836 trigger: 'h2', 5837 container: '.content', 5838 containerInner: '> ul' 5839 }); 5840 $initFooterLinksAccordion = false; 5841 } 5842 } 5843 5844 if (($quickviewSlideout = $("#quickview-mmenu")).length) { 5845 hookUpQuickViews(document); 5846 5847 $quickviewSlideout.mmenu({ 5848 extensions: ["pagedim-black", "position-right", "position-front", "theme-white"], 5849 backButton: { close: false }, 5850 navbar: { title: "" }, //needed to hide the default title menu 5851 navbars: [{ position: "top", content: "<a class='mm-title' href='#' onclick='event.preventDefault();'>Close</a><a class='mm-btn' href='#' onclick='event.preventDefault();' role='button'><span class='mmenu-close'></span><span class='sr-only'>close menu</span></a>" }], 5852 onClick: { close: false, setSelected: false }, 5853 slidingSubmenus: false 5854 }, { 5855 //configuration 5856 offCanvas: { 5857 pageSelector: "#sg-page-wrapper" 5858 } 5859 }); 5860 $("#quickview-mmenu").on("click", ".mm-navbars_top", function (e) { 5861 $("#quickview-mmenu").data("mmenu").close(); 5862 lastFocus.focus(); 5863 }); 5864 } 5865 } 5866 5867 if (matchMedia('(min-width: 681px) and (max-width: 960px)').matches) { 5868 bindTabletSearch(); 5869 } 5870 5871 if (matchMedia('(min-width: 681px)').matches) { 5872 //mobile search to default state for shifting breakpoints 5873 $(".site-search.mobile-search").removeClass("open").addClass("closed").attr("style", ""); 5874 $(".mobile-trigger.search .search-icon").removeClass("open"); 5875 } 5876 5877 if (matchMedia('(max-width: 680px)').matches) { 5878 bindMobileSearch(); 5879 $(document).off("click", "#search-trigger").on("click", 5880 "#search-trigger", 5881 function(e) { 5882 e.preventDefault(); 5883 var $searchDiv = $(".site-search.mobile-search"); 5884 var $searchIcon = $(".mobile-trigger.search .search-icon"); 5885 var $searchInput = $(".site-search.mobile-search .input-text") 5886 if ($searchDiv.hasClass("closed")) { 5887 $searchDiv.slideToggle("fast").removeClass("closed").addClass("open"); 5888 $searchIcon.addClass("open"); 5889 $searchInput.focus(); 5890 } else if ($searchDiv.hasClass("open")) { 5891 $searchDiv.slideToggle("fast").removeClass("open").addClass("closed"); 5892 $searchIcon.removeClass("open"); 5893 $searchInput.blur(); 5894 } 5895 }); 5896 } 5897 5898}
5899window.addEventListener('resize', layoutResizeHandler); 5900 5901 5902 5903 5904function setWishlistQuantityText() { 5905 var cookieValue = "0"; 5906 var cookieData = 5907 decodeURIComponent(document.cookie 5908 .replace(new RegExp("(?:(?:^|.*;)\\s*" + 5909 encodeURIComponent("wlQty").replace(/[\-\.\+\*]/g, "\\$&") + 5910 "\\s*\\=\\s*([^;]*).*$)|^.*$"), 5911 "$1")) || null; 5912 5913 if (cookieData != null) 5914 cookieValue = cookieData; 5915 5916 $('#wishlistQtyText').text(cookieValue); 5917 if (cookieValue != null && cookieValue != "0") { 5918 $('#wishlistQtyText').show(); 5919 $('#wishlistQtyLbl').show(); 5920 } else { 5921 $('#wishlistQtyText').hide(); 5922 $('#wishlistQtyLbl').hide(); 5923 } 5924 5925} 5926 5927//ALL updates to the view cart container need to use this!!! 5928function updateCartContainer(html) { 5929 $('#cartContainer').replaceWith(html); 5930 $('#cartContainer').find($("img.lazy")).lazy(); 5931 Gorilla.util.initForms(); 5932 //need to refresh dynamic data on teh club spiff... 5933 //TODO since that no longer show/hides based on the cart or membership... this should be fixed to be static 5934 AjaxJsonPostWrapper.ajaxRoute('dynamicdata', 'getdata', { page: 'viewcart' }, function (result) { 5935 var $clubDd = $("club-dynamic-data"); 5936 if (result.clubDd && $clubDd.length) { 5937 $("club-dynamic-data").replaceWith(result.clubDd); 5938 } 5939 }); 5940} 5941 5942/****************************** Search SuggestAhead *******************************************/ 5943function getSuggestAheadTerms(request, response) { 5944 var term = $('<div/>').text(request.term).html(); 5945 $.ajax({
5946 type: "POST", 5947 url: window.location.protocol + "//" + window.location.host + "/main/suggestaheadsearchterms", 5948 async: true, 5949 data: JSON.stringify({ term: term }), 5950 contentType: 'application/json', 5951 traditional: true, 5952 success: function (result) { 5953 //dont post old data, the newest response should be used 5954 if ($('#k').val() != result.term) { 5955 //console.log($('#k').val() + " :bad: " + result.term); 5956 return false; 5957 } 5958 //else 5959 //console.log($('#k').val() + " :good: " + result.term); 5960 var fullTerms = result.suggestions.split('|'); 5961 var uniqueKeys = []; 5962 $.each(fullTerms, function (i, el) { 5963 var str = el.trim(); 5964 if ($.inArray(str, uniqueKeys) == -1) uniqueKeys.push(str); 5965 }); 5966 $('#searchProducts').html(result.html); 5967 $itemContainer = $('#product-listing-container'); 5968 $itemContainer.find("img.lazy").lazy({ delay: 0 }); 5969 response(uniqueKeys); 5970 }, 5971 error: function (XMLHttpRequest, textStatus, errorThrown) { 5972 var errId = XMLHttpRequest.getResponseHeader("System-Error-ID"); 5973 var errIdMsg = ""; 5974 if (errId != null) { 5975 errIdMsg = " [" + errId + "]" 5976 } 5977 console.log("An error occurred during ajax operation" + errIdMsg + ".") // mimics what has been "good enough" since redesign, circa 2014. we don't really know what to do but probably don't want to interrupt the user 5978 5979 //if (error != undefined) { 5980 // error(errorThrown); 5981 //} 5982 //else { 5983 // Gorilla.util.messages.addMessage('Sorry, there was an error with your request. Please try again shortly.', 'error'); 5984 //} 5985 } 5986 }) 5987 .done(function (data) { 5988 if (data.errors) { 5989 onDataError(data); 5990 } 5991 5992 // tablet and desktop search, hook up keyboard functionality 5993 if (matchMedia('(min-width: 681px)').matches) { 5994 // add tab indexes to the suggest ahead terms and remove the tab index from the parent list 5995 5996 $("#searchSuggestions li:first").addClass('ac-first'); 5997 $("#searchSuggestions li:last").addClass('ac-last'); 5998 $("#searchSuggestionsQuantity").text($('#searchSuggestions li').length + " autocorrect results"); 5999 $("#searchProductsQuantity").text($('#searchProducts li').length + " product results"); 6000 6001 // triggers off search box 6002 $('#k').off('keydown').on('keydown', function (e) { 6003 if (e.key === 'ArrowDown' || e.keyCode === 40 || ((e.key === 'Tab' || e.keyCode === 9) && !e.shiftKey)) { 6004 //if suggest ahead list is showing and has values 6005 if ($('#searchSuggestions ul li').length > 0) { 6006 e.preventDefault(); 6007 $('#searchSuggestions ul.ui-menu').show(); 6008 $('#searchSuggestions li:first div').focus(); 6009 $('#searchProducts').attr("style", "display:block"); 6010 } 6011 } 6012 else if (e.key === 'ArrowUp' || e.keyCode === 38) { 6013 //if suggest ahead list is showing and has values 6014 if ($('#searchSuggestions ul li').length > 0) { 6015 e.preventDefault(); 6016 $('#searchSuggestions ul.ui-menu').show(); 6017 $('#searchSuggestions li:last div').focus(); 6018 } 6019 } 6020 else if (e.shiftKey && (e.key === 'Tab' || e.keyCode === 9)) { 6021 // leaving search box 6022 $('#searchSuggestions ul.ui-menu').hide(); 6023 $('#searchProducts').hide(); 6024 } 6025 }); 6026 6027 // redefine mouse hover effects 6028 $('#searchSuggestions li').hover(function (event, ui) { 6029 //console.log($(this).text() + " :: " + $(this).index()); 6030 var i = 0; 6031 for (i = 0; i < 11; i++) { 6032 $('#suggestindex-' + i).hide(); 6033 } 6034 $('#suggestindex-' + $(this).index()).show(); 6035 }); 6036 6037 // redefine off hover effects, 6038 // hide if focus leaves all of the three elements (search box, suggest head, suggest products) 6039 $('#kform').focusout(function (e) { 6040 var $elem = $(this); 6041 setTimeout(function () { 6042 var hasFocus = !!($elem.find(':focus').length > 0); 6043 if (!hasFocus) { 6044 $('#searchSuggestions ul.ui-menu').hide(); 6045 $('#searchProducts').hide(); 6046 } 6047 }, 10); 6048 }); 6049 6050 // define focus 6051 $('#searchSuggestions li div').focus(function (event, ui) { 6052 event.preventDefault(); 6053 var i = 0; 6054 for (i = 0; i < 11; i++) { 6055 $('#suggestindex-' + i).hide(); 6056 } 6057 $('#suggestindex-' + $(this).index()).show(); 6058 }); 6059 6060 // define arrow key movement 6061 //left and right moves through products 6062 //up and down (and shift+tab/tab) moves through suggest ahead 6063 $('#searchSuggestions li').on('keydown', function (e) { 6064 if (e.key === 'Enter' || e.keyCode === 13) { 6065 e.preventDefault(); 6066 $("#k").val($(this).text()); 6067 $("#kform").submit(); 6068 } 6069 else if ((e.key === 'Tab' || e.keyCokde === 9) && !e.shiftKey) { 6070 if ($('#searchProducts .category-products ol li').length > 0) { 6071 e.preventDefault(); 6072 $('#searchProducts .category-products ol a:first').focus(); 6073 } 6074 } 6075 }); 6076 6077 // if tabbing past everything then make sure to close auto correct boxes 6078 $('.site-search .icon-wrapper button.button').focus(function () { 6079 $('#searchSuggestions ul.ui-menu').hide(); 6080 $('#searchProducts').hide(); 6081 }); 6082 6083 6084 } else { 6085 // add tab indexes to the suggest ahead terms and remove the tab index from the parent list 6086 6087 6088 $('#searchMobile').off('keydown').on('keydown', function (e) { 6089 if (e.key === 'ArrowDown' || e.keyCode === 40 || ((e.key === 'Tab' || e.keyCode === 9) && !e.shiftKey)) { 6090 //if suggest ahead list is showing and has values 6091 if ($('#searchSuggestionsMobile ul li').length > 0) { 6092 e.preventDefault(); 6093 $('#searchSuggestionsMobile ul.ui-menu').show(); 6094 $('#searchSuggestionsMobile li:first div').focus(); 6095 } 6096 } 6097 else if (e.key === 'ArrowUp' || e.keyCode === 38) { 6098 //if suggest ahead list is showing and has values 6099 if ($('#searchSuggestionsMobile ul li').length > 0) { 6100 e.preventDefault(); 6101 $('#searchSuggestionsMobile ul.ui-menu').show(); 6102 $('#searchSuggestionsMobile li:last div').focus(); 6103 } 6104 } 6105 else if (e.shiftKey && (e.key === 'Tab' || e.keyCode === 9)) { 6106 $('#search-trigger').trigger('click').off('click'); 6107 } 6108 }); 6109 6110 // define arrow key movement 6111 //up and down (and shift+tab/tab) moves through suggest ahead 6112 $('#searchSuggestionsMobile li').on('keydown', function (e) { 6113 if (e.key === 'Enter' || e.keyCode === 13) { 6114 e.preventDefault(); 6115 $("#searchMobile").val($(this).text()); 6116 $("#mobilekform").submit(); 6117 } 6118 else if ((e.key === 'Tab' || e.keyCode === 9) && !e.shiftKey) { 6119 if ($(this).is(':last-child')) { 6120 e.preventDefault(); 6121 $('#search-trigger').trigger('click').off('click'); 6122 $('#menu-trigger').focus(); 6123 } 6124 6125 } 6126 6127 }); 6128 } 6129 }); 6130} 6131 6132// when an item in the suggested terms dropdown gets the focus/hover, call out and get products for that term 6133function getSuggestAheadTermsFocus(liID, label) { 6134 if ($("#" + liID).hasClass('ui-state-active')) { // used to be ui-state-focus in older version of jQuery 6135 getSuggestAheadTermsFocusCall(label); 6136 } 6137} 6138 6139function highlightSearchedTerm($elem) { 6140 var acData = $elem.data('ui-autocomplete'); 6141 acData.menu.element.find('li').each(function () { 6142 var container = $("div", $(this)); // ui-autocomplete now has a div inside the li wrapping the words 6143 var keywords = acData.term.split(' ').join('|'); 6144 container.html(container.html().replace(new RegExp("(" + keywords + ")", "gi"), '<span class="highlight">$1</span>')); 6145 });
6146} 6147 6148 6149function hookUpQuickViews(el) { 6150 if (matchMedia('(min-width: 961px)').matches) { 6151 $(el).find(".btn-quickview > button:not(.bound961)").each(function () { 6152 $(this).removeClass("bound"); 6153 $(this).parent().removeClass("hide-quick-view"); 6154 $(this).off("click"); 6155 $(this).addClass("bound961"); 6156 6157 hookupQuickviewAda($(this)); 6158 6159 //Bloomreach Related Products 6160 $(this).find("[href$='#brqv']").on("click", function () { 6161 swapBRRelProdImage($(this)); 6162 }); 6163 6164 $(this).moby({ 6165 'modalClass': 'quickview', 6166 'ariaLabelText': 'Quick View', 6167 'onCompleteCallback': function (e) { 6168 6169 var $form = $(e).find('form'); 6170 if ($form.length === 0) { // fix latent bug - seems like related products quickview's e is "window" and .find from there doesn't pick up the QV form... 6171 $form = $(".moby-container.quickview.show").find('form'); 6172 } 6173 6174 validateAndInitQuickViewForm($form); 6175 autoselectAttributeIfSingle($(".attribute-select", $form).first()); 6176 }, 6177 'onCloseCallback': function (e) { 6178 callMonetateScripts(); 6179 } 6180 }); 6181 }); 6182 $(el).find(".add-on-quickview:not(.bound961)").each(function () { 6183 $(this).removeClass("bound"); 6184 $(this).off("click"); 6185 $(this).addClass("bound961"); 6186 $(this).moby({ 6187 'modalClass': 'quickview', 6188 'ariaLabelText': 'Quick View', 6189 'onCompleteCallback': function (e) { 6190 6191 var $form = $(e).find('form'); 6192 if ($form.length === 0) { // fix latent bug - seems like related products quickview's e is "window" and .find from there doesn't pick up the QV form... 6193 $form = $(".moby-container.quickview.show").find('form'); 6194 } 6195 6196 validateAndInitQuickViewForm($form); 6197 autoselectAttributeIfSingle($(".attribute-select", $form).first()); 6198 }, 6199 'onCloseCallback': function (e) { 6200 callMonetateScripts(); 6201 } 6202 }); 6203 }); 6204 } 6205 else { 6206 $(el).find(".btn-quickview > button:not(.bound)").each(function () { 6207 $(this).removeClass("bound961"); 6208 $(this).off("click"); 6209 $(this).parent().removeClass("hide-quick-view"); 6210 $(this).addClass("bound"); 6211 6212 hookupQuickviewAda($(this)); 6213 6214 if ($(this).attr("href").indexOf("#brqv") >= 0) { //Bloomreach Related Products 6215 $(this).on("click", function (e) { 6216 e.preventDefault(); 6217 var $divId = $(this).attr("href").substr($(this).attr("href").lastIndexOf('#') + 1); 6218 var $brQVDiv = $("div[id=" + $divId + "]"); 6219 var $brQVImg = $brQVDiv.find('img.brRelProd'); 6220 if ($brQVImg.length) { 6221 $brQVImg.attr('src', $brQVImg.attr('src').replace("/m/", "/e/")); 6222 } 6223 $("#quickview-mmenu .quickview").html($brQVDiv.html()); 6224 $("#quickview-mmenu").data("mmenu").open(); 6225 trapFocus($("#quickview-mmenu")); 6226 validateAndInitQuickViewForm($("#quickview-mmenu").find('form')); 6227 return false; 6228 }); 6229 } 6230 else { 6231 $(this).on("click", function (e) { 6232 e.preventDefault(); 6233 $.ajax({
6234 url: $(this).attr('href'), 6235 type: 'GET', 6236 datatype: "html", 6237 success: function (result) { 6238 $("#quickview-mmenu .quickview").html(result); 6239 $("#quickview-mmenu").data("mmenu").open(); 6240 validateAndInitQuickViewForm($("#quickview-mmenu").find('form')); 6241 } 6242 }); 6243 return false; 6244 }); 6245 } 6246 }); 6247 6248 $(el).find(".add-on-quickview:not(.bound)").each(function () { 6249 $(this).removeClass("bound961"); 6250 $(this).off("click"); 6251 $(this).addClass("bound"); 6252 $(this).on("click", function (e) { 6253 e.preventDefault(); 6254 $.ajax({ 6255 url: $(this).attr('href'), 6256 type: 'GET', 6257 datatype: "html", 6258 success: function (result) { 6259 $("#quickview-mmenu .quickview").html(result); 6260 $("#quickview-mmenu").data("mmenu").open(); 6261 validateAndInitQuickViewForm($("#quickview-mmenu").find('form')); 6262 } 6263 }); 6264 return false; 6265 }); 6266 }); 6267 } 6268} 6269 6270function hookupQuickviewAda(el) { 6271 var $this = $(el); 6272 6273 //ada compliance...if the quickview has focus make it visible 6274 $this.on('focusin', function () { 6275 $(this).parent().addClass("show"); 6276 }).on('focusout', function () { 6277 $(this).parent().removeClass("show"); 6278 }); 6279 6280 //ada compliance... hide all tab focused quick views when mousing over the parent anchor 6281 //this helps prevent a sticky quick view button 6282 $this.closest(".product-image").on("mouseover", function () { 6283 $("body").find(".products-grid .btn-quickview > button:visible").trigger("blur"); 6284 }); 6285 6286} 6287 6288function validateAndInitQuickViewForm(quickViewForm) { 6289 truncateQuickViewAdCopy(quickViewForm); 6290 quickViewForm.validate(); 6291 6292 //register Notify Me Modal trigger in case quick view is of a product on notify 6293 quickViewForm.find('.notifyBtn').find("a").moby({ 6294 'modalClass': 'giveaway-modal', 6295 'ariaLabelText': 'Notify Me', 6296 'onCompleteCallback': function () { 6297 } 6298 }); 6299 Gorilla.util.initForms(); 6300} 6301 6302function createSiteWidePromoSlickSlider() { 6303 var $ss = $("#site-wide-promos"); 6304 $(window).on('load', function () { 6305 if (!$ss.hasClass('slick-initialized') && !$ss.hasClass("checkout-promo")) { 6306 $ss.slick({ 6307 slidesToShow: 1, 6308 slidesToScroll: 1, 6309 dots: true, 6310 appendDots: $('#promoBannerDots'), 6311 arrows: false, 6312 infinite: true, 6313 autoplay: true, 6314 autoplaySpeed: 5000 6315 }); 6316 } 6317 }); 6318} 6319 6320function destroySiteWidePromoSlickSlider() { 6321 var $ss = $("#site-wide-promos"); 6322 if ($ss.hasClass('slick-initialized')) { 6323 $ss.slick('unslick'); 6324 } 6325} 6326 6327function bindMobileSearch() { 6328 var $searchMobile = $("#searchMobile"); 6329 if ($searchMobile.data("ui-autocomplete") != undefined) { 6330 $searchMobile.autocomplete("destroy"); 6331 } 6332 6333 $searchMobile.autocomplete({ 6334 appendTo: "#searchSuggestionsMobile", 6335 source: function (request, response) { 6336 getSuggestAheadTerms(request, response); 6337 }, 6338 minLength: 3, 6339 delay: 200, 6340 maxItems: 5, 6341 6342 select: function (event, ui) { 6343 $searchMobile.val(ui.item.label); 6344 $("#mobilekform").submit(); 6345 }, 6346 6347 open: function (event, ui) { 6348 highlightSearchedTerm($(this)); 6349 } 6350 }); 6351} 6352 6353function bindTabletSearch() { 6354 if ($("#k").data("ui-autocomplete") != undefined) { 6355 $("#k").autocomplete("destroy"); 6356 } 6357 6358 $("#k").autocomplete({ 6359 appendTo: "#searchSuggestions", 6360 source: function (request, response) { 6361 getSuggestAheadTerms(request, response); 6362 }, 6363 minLength: 3, 6364 delay: 200, 6365 maxItems: 10, 6366 6367 select: function (event, ui) { 6368 $("#k").val(ui.item.label); 6369 $("#kform").submit(); 6370 }, 6371 6372 open: function (event, ui) { 6373 highlightSearchedTerm($(this)); 6374 } 6375 });
6376} 6377 6378function bindDesktopSearch() { 6379 if ($("#k").data("ui-autocomplete") != undefined) { 6380 $("#k").autocomplete("destroy"); 6381 } 6382 6383 $("#k").autocomplete({ 6384 appendTo: "#searchSuggestions", 6385 source: function (request, response) { 6386 getSuggestAheadTerms(request, response); 6387 }, 6388 minLength: 3, 6389 delay: 200, 6390 maxItems: 10, 6391 6392 response: function (event, ui) { 6393 $("#searchProducts").css({ display: 'block' }); 6394 }, 6395 6396 select: function (event, ui) { 6397 $("#k").val(ui.item.label); 6398 6399 $("#kform").submit(); 6400 }, 6401 6402 close: function (event, ui) { 6403 event.preventDefault(); 6404 }, 6405 6406 focus: function (event, ui) { 6407 }, 6408 6409 open: function (event, ui) { 6410 highlightSearchedTerm($(this)); 6411 } 6412 }); 6413 6414} 6415 6416function showHideSuggestAhead() { 6417 setTimeout(function () { 6418 if ($("#searchProducts :focus").length === 0) { 6419 $("#searchProducts").css({ display: 'none' }); 6420 } 6421 }, 200); 6422} 6423 6424function updateShowMiniCart(html, showSlide) { 6425 if (html && html !== "") { 6426 setCartQuantityText(); 6427 var $cartSummary = $("#cartSummary"); 6428 setTimeout(function () { 6429 $cartSummary.empty().append(html); 6430 $("#mini-totals").empty().append($cartSummary.find(".mini-totals-container").detach()); 6431 6432 var itemCount = $cartSummary.find(".items-in-cart").detach().text(); 6433 var cartTotal = $("#mini-cart-total-preview").html(); 6434 var fsThreshold = $("#mini-cart-fs-threshold").html(); 6435 var cls = $("#mini-cart-total-preview").attr('class'); 6436 var division = $("#cart-mmenu").data("division"); 6437 $("#cart-mmenu").removeClass("mm-nomap").removeClass("mm-map").removeClass("mm-unset").removeClass("mm-noSavings"); 6438 if (itemCount.length) { 6439 $("#cart-mmenu").addClass(cls); 6440 $("#mini-cart-total").html(cartTotal).show(); 6441 $("#mini-cart-fs-threshold-ds").html(fsThreshold).show(); 6442 $("#mini-count").empty().append(itemCount); 6443 $("#mini-cart-actions").show(); 6444 /*$("#cart-mmenu .mm-navbars_top .mm-navbar").css("height", ""); */ 6445 if (division == 32) { 6446 $("#cart-mmenu .mm-navbars_top .mm-navbar").css("height", ""); 6447 $("#cart-mmenu .mm-navbars_top .mm-navbar").addClass("softball-style"); 6448 } 6449 else if (division == 31) 6450 { 6451 $("#cart-mmenu .mm-navbars_top .mm-navbar").css("height", ""); 6452 } 6453 $("#cart-mmenu.mm-menu_navbar_top-1 .mm-panels").css("top", ""); 6454 } else { 6455 $("#mini-cart-actions").hide(); 6456 $("#cart-mmenu").addClass("mm-unset"); 6457 $("#mini-count").text("0 items in your cart"); 6458 $("#mini-cart-total").hide(); 6459 } 6460 }, 500); 6461 6462 if (showSlide) { 6463 dropMiniCart(); 6464 } 6465 } 6466} 6467 6468function dropMiniCart() { 6469 //close the quickview slideout if its open 6470 if ($("#quickview-mmenu").length && $("#quickview-mmenu").hasClass("mm-menu_opened")) { 6471 $("#quickview-mmenu").data("mmenu").close(); 6472 if (lastFocus) { 6473 lastFocus.focus(); 6474 } 6475 } 6476 6477 $quickorderAdd = $("#quickorder-add"); 6478 if (!$quickorderAdd.length) 6479 setTimeout(function () { 6480 var mmenuHookup = $("#cart-mmenu").data("mmenu").open(); 6481 if (mmenuCloseHookup) { 6482 mmenuCloseHookup = false; 6483 mmenuHookup.bind("close:after", function () { 6484 callMonetateScripts(); 6485 }); 6486 } 6487 trapFocus($("#cart-mmenu")); 6488 $("#cart-mmenu").on("click", ".mm-navbars_top", function (e) { 6489 $("#cart-mmenu").data("mmenu").close(); 6490 }); 6491 }, 500); 6492} 6493 6494function focusOnFirstEl(container) {
6495 var $focusableEl = $(container).find(":focusable").first(); 6496 $focusableEl.focus(); 6497 $([document.documentElement, document.body]).animate({ scrollTop: $focusableEl.offset().top }, 500); 6498} 6499 6500function removeQueryParameter(key, sourceURL) { 6501 var rtn = sourceURL.split("?")[0], 6502 param, 6503 params_arr = [], 6504 queryString = (sourceURL.indexOf("?") !== -1) ? sourceURL.split("?")[1] : ""; 6505 if (queryString !== "") { 6506 params_arr = queryString.split("&"); 6507 for (var i = params_arr.length - 1; i >= 0; i -= 1) { 6508 param = params_arr[i].split("=")[0]; 6509 if (param === key) { 6510 params_arr.splice(i, 1); 6511 } 6512 } 6513 if (params_arr.length) rtn = rtn + "?" + params_arr.join("&"); 6514 } 6515 return rtn; 6516} 6517 6518function monetateClick(recToken) { 6519 if (recToken) { 6520 AjaxJsonPostWrapper.ajaxRoute('monetate', 'monetateclickevent', { recToken: recToken }, function () { }); 6521 } 6522 return false; 6523} 6524 6525function algoliaClick(pid, pos, queryid, name) { 6526 var pids = [pid]; 6527 var poss = [pos]; 6528 AjaxJsonPostWrapper.ajaxRoute('algolia', 'algoliaclickevent', { eventObject: { queryId: queryid, eventName: name, positions: poss, objectIDs: pids } }); 6529 return false; 6530} 6531 6532function buildDDLink(type, typeValue, keepNonInternalQuery) { 6533 AjaxJsonPostWrapper.ajaxRoute('main', 'buildplponchangelink', { basePath: document.location.href, type: type, typeValue: typeValue, keepNonInternalQuery: keepNonInternalQuery }, function (result) { 6534 if(result.newUrl) 6535 document.location.href = result.newUrl; 6536 }); 6537} 6538 6539function callMonetateScripts() { 6540 var fullMonetateScript = ""; 6541 6542 if (window.monetatePageScript && window.monetatePageScript.length) { 6543 fullMonetateScript = window.monetatePageScript; 6544 } 6545 6546 if (window.monetateBreadCrumbScript && window.monetateBreadCrumbScript.length) { 6547 fullMonetateScript = fullMonetateScript + window.monetateBreadCrumbScript; 6548 } 6549 6550 if (window.monetateCartScript && window.monetateCartScript.length) { 6551 fullMonetateScript = fullMonetateScript + window.monetateCartScript; 6552 } 6553 6554 if (window.monetateProductScript && window.monetateProductScript.length) { 6555 fullMonetateScript = fullMonetateScript + window.monetateProductScript; 6556 } 6557 6558 if (window.monetateProductListScript && window.monetateProductListScript.length) { 6559 fullMonetateScript = fullMonetateScript + window.monetateProductListScript; 6560 } 6561 6562 if (fullMonetateScript && fullMonetateScript.length) { 6563 fullMonetateScript = fullMonetateScript + "<script id=\"monetateTrackData\" type=\"text/javascript\"> window.monetateQ.push([\"trackData\"]);<\/script>"; 6564 var monetateDiv = $('#monetateAjax'); 6565 monetateDiv.empty(); 6566 if (monetateDiv && monetateDiv.length) { 6567 monetateDiv.append(fullMonetateScript); 6568 } 6569 } 6570 return false; 6571} 6572 6573function tealiumLinkCall(dataObject) { 6574 if (window?.utag) { //Make sure Tealium is initialized, otherwise will cause JS errors. 6575 //All data in data object should be a string or an array of strings. 6576 //All link calls should include a "tealium_event" key-value pair. 6577 6578 //Checking if "tealium_event" key is defined. 6579 if (!dataObject.tealium_event) { 6580 console.error("No tealium_event defined for the link call. Please define a tealium_event key-value pair."); 6581 return; 6582 } 6583 6584 //Force everything to be strings 6585 var objString = Object.fromEntries( 6586 Object.entries(dataObject).map(([key, value]) => { 6587 if (typeof value === 'object' && value !== null) { 6588 if (Array.isArray(value)) { 6589 var newValue = []; 6590 for (var i = 0; i < value.length; i++) { 6591 newValue[i] = String(value[i]); 6592 } 6593 return [key, newValue]; 6594 } 6595 console.log('Tealium link() calls do not accept any objects outside of arrays and strings, ommitting object from data set.'); 6596 return [key, '']; 6597 } 6598 return [key, String(value)]; 6599 }) 6600 ); 6601 6602 window.utag.link(objString); 6603 return; 6604 } 6605 6606 console.error("Tealium script was not initialized before link function was called. Please check the timing of the link call."); 6607 return; 6608};
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.