{"version":3,"file":"js/splits/search.js","sources":["webpack:///./node_modules/call-bind/callBound.js","webpack:///./node_modules/call-bind/index.js","webpack:///./node_modules/function-bind/implementation.js","webpack:///./node_modules/function-bind/index.js","webpack:///./node_modules/has-proto/index.js","webpack:///./node_modules/has-symbols/index.js","webpack:///./node_modules/has-symbols/shams.js","webpack:///./node_modules/has/src/index.js","webpack:///./org_colony/cartridge/js/compare-widget.js","webpack:///./org_colony/cartridge/js/pages/product/availability.js","webpack:///./org_colony/cartridge/js/pages/product/index.js","webpack:///./org_colony/cartridge/js/pages/product/productNav.js","webpack:///./org_colony/cartridge/js/pages/product/productSet.js","webpack:///./org_colony/cartridge/js/pages/product/variant.js","webpack:///./org_colony/cartridge/js/pages/search.js","webpack:///./org_colony/cartridge/js/product-tile.js","webpack:///./org_colony/cartridge/js/quickview.js","webpack:///./org_colony/cartridge/js/storeinventory/index.js","webpack:///./org_colony/cartridge/js/storeinventory/product.js","webpack:///./util.inspect (ignored)"],"sourcesContent":["'use strict';\n\nvar GetIntrinsic = require('get-intrinsic');\n\nvar callBind = require('./');\n\nvar $indexOf = callBind(GetIntrinsic('String.prototype.indexOf'));\n\nmodule.exports = function callBoundIntrinsic(name, allowMissing) {\n\tvar intrinsic = GetIntrinsic(name, !!allowMissing);\n\tif (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {\n\t\treturn callBind(intrinsic);\n\t}\n\treturn intrinsic;\n};\n","'use strict';\n\nvar bind = require('function-bind');\nvar GetIntrinsic = require('get-intrinsic');\n\nvar $apply = GetIntrinsic('%Function.prototype.apply%');\nvar $call = GetIntrinsic('%Function.prototype.call%');\nvar $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply);\n\nvar $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true);\nvar $defineProperty = GetIntrinsic('%Object.defineProperty%', true);\nvar $max = GetIntrinsic('%Math.max%');\n\nif ($defineProperty) {\n\ttry {\n\t\t$defineProperty({}, 'a', { value: 1 });\n\t} catch (e) {\n\t\t// IE 8 has a broken defineProperty\n\t\t$defineProperty = null;\n\t}\n}\n\nmodule.exports = function callBind(originalFunction) {\n\tvar func = $reflectApply(bind, $call, arguments);\n\tif ($gOPD && $defineProperty) {\n\t\tvar desc = $gOPD(func, 'length');\n\t\tif (desc.configurable) {\n\t\t\t// original length, plus the receiver, minus any additional arguments (after the receiver)\n\t\t\t$defineProperty(\n\t\t\t\tfunc,\n\t\t\t\t'length',\n\t\t\t\t{ value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) }\n\t\t\t);\n\t\t}\n\t}\n\treturn func;\n};\n\nvar applyBind = function applyBind() {\n\treturn $reflectApply(bind, $apply, arguments);\n};\n\nif ($defineProperty) {\n\t$defineProperty(module.exports, 'apply', { value: applyBind });\n} else {\n\tmodule.exports.apply = applyBind;\n}\n","'use strict';\n\n/* eslint no-invalid-this: 1 */\n\nvar ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';\nvar slice = Array.prototype.slice;\nvar toStr = Object.prototype.toString;\nvar funcType = '[object Function]';\n\nmodule.exports = function bind(that) {\n var target = this;\n if (typeof target !== 'function' || toStr.call(target) !== funcType) {\n throw new TypeError(ERROR_MESSAGE + target);\n }\n var args = slice.call(arguments, 1);\n\n var bound;\n var binder = function () {\n if (this instanceof bound) {\n var result = target.apply(\n this,\n args.concat(slice.call(arguments))\n );\n if (Object(result) === result) {\n return result;\n }\n return this;\n } else {\n return target.apply(\n that,\n args.concat(slice.call(arguments))\n );\n }\n };\n\n var boundLength = Math.max(0, target.length - args.length);\n var boundArgs = [];\n for (var i = 0; i < boundLength; i++) {\n boundArgs.push('$' + i);\n }\n\n bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);\n\n if (target.prototype) {\n var Empty = function Empty() {};\n Empty.prototype = target.prototype;\n bound.prototype = new Empty();\n Empty.prototype = null;\n }\n\n return bound;\n};\n","'use strict';\n\nvar implementation = require('./implementation');\n\nmodule.exports = Function.prototype.bind || implementation;\n","'use strict';\n\nvar test = {\n\tfoo: {}\n};\n\nvar $Object = Object;\n\nmodule.exports = function hasProto() {\n\treturn { __proto__: test }.foo === test.foo && !({ __proto__: null } instanceof $Object);\n};\n","'use strict';\n\nvar origSymbol = typeof Symbol !== 'undefined' && Symbol;\nvar hasSymbolSham = require('./shams');\n\nmodule.exports = function hasNativeSymbols() {\n\tif (typeof origSymbol !== 'function') { return false; }\n\tif (typeof Symbol !== 'function') { return false; }\n\tif (typeof origSymbol('foo') !== 'symbol') { return false; }\n\tif (typeof Symbol('bar') !== 'symbol') { return false; }\n\n\treturn hasSymbolSham();\n};\n","'use strict';\n\n/* eslint complexity: [2, 18], max-statements: [2, 33] */\nmodule.exports = function hasSymbols() {\n\tif (typeof Symbol !== 'function' || typeof Object.getOwnPropertySymbols !== 'function') { return false; }\n\tif (typeof Symbol.iterator === 'symbol') { return true; }\n\n\tvar obj = {};\n\tvar sym = Symbol('test');\n\tvar symObj = Object(sym);\n\tif (typeof sym === 'string') { return false; }\n\n\tif (Object.prototype.toString.call(sym) !== '[object Symbol]') { return false; }\n\tif (Object.prototype.toString.call(symObj) !== '[object Symbol]') { return false; }\n\n\t// temp disabled per https://github.com/ljharb/object.assign/issues/17\n\t// if (sym instanceof Symbol) { return false; }\n\t// temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4\n\t// if (!(symObj instanceof Symbol)) { return false; }\n\n\t// if (typeof Symbol.prototype.toString !== 'function') { return false; }\n\t// if (String(sym) !== Symbol.prototype.toString.call(sym)) { return false; }\n\n\tvar symVal = 42;\n\tobj[sym] = symVal;\n\tfor (sym in obj) { return false; } // eslint-disable-line no-restricted-syntax, no-unreachable-loop\n\tif (typeof Object.keys === 'function' && Object.keys(obj).length !== 0) { return false; }\n\n\tif (typeof Object.getOwnPropertyNames === 'function' && Object.getOwnPropertyNames(obj).length !== 0) { return false; }\n\n\tvar syms = Object.getOwnPropertySymbols(obj);\n\tif (syms.length !== 1 || syms[0] !== sym) { return false; }\n\n\tif (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { return false; }\n\n\tif (typeof Object.getOwnPropertyDescriptor === 'function') {\n\t\tvar descriptor = Object.getOwnPropertyDescriptor(obj, sym);\n\t\tif (descriptor.value !== symVal || descriptor.enumerable !== true) { return false; }\n\t}\n\n\treturn true;\n};\n","'use strict';\n\nvar hasOwnProperty = {}.hasOwnProperty;\nvar call = Function.prototype.call;\n\nmodule.exports = call.bind ? call.bind(hasOwnProperty) : function (O, P) {\n return call.call(hasOwnProperty, O, P);\n};\n","const TPromise = require('promise');\nconst page = require('./page');\nconst util = require('./util');\nconst dialog = require('./dialog');\n\nlet currentCategory = '';\nconst MAX_ACTIVE = 3;\n\n/**\n * @private\n * @function\n * @description Verifies the number of elements in the compare container and updates it with sequential classes for ui targeting\n */\nfunction refreshContainer() {\n const $compareContainer = $('.compare-items');\n const $compareItems = $compareContainer.find('.compare-item');\n const numActive = $compareItems.filter('.active').length;\n\n if (numActive < 2) {\n $('#compare-items-button').attr('disabled', 'disabled');\n } else {\n $('#compare-items-button').removeAttr('disabled');\n }\n\n $compareContainer.toggle(numActive > 0);\n}\n/**\n * @private\n * @function\n * @description Adds an item to the compare container and refreshes it\n */\nfunction addToList(data) {\n // get the first compare-item not currently active\n const $item = $('.compare-items .compare-item').not('.active').first();\n const $productTile = $(`#${data.uuid}`);\n\n if ($item.length === 0) {\n if ($productTile.length > 0) {\n $productTile.find('.compare-check')[0].checked = false;\n }\n dialog.open({\n html: Resources.COMPARE_ADD_FAIL,\n options: {\n width: 530,\n buttons: [],\n },\n });\n return;\n }\n\n // if already added somehow, return\n if ($(`[data-uuid=\"${data.uuid}\"]`).length > 0) {\n return;\n }\n // set as active item\n $item.addClass('active')\n .attr('data-uuid', data.uuid)\n .attr('data-itemid', data.itemid)\n .attr('data-colorval', data.colorval)\n .data('uuid', data.uuid)\n .data('itemid', data.itemid)\n .data('colorval', data.colorval)\n .append($(data.img).clone().addClass('compare-item-image'));\n}\n/**\n * @private\n * @function\n * description Removes an item from the compare container and refreshes it\n */\nfunction removeFromList($item) {\n if ($item.length === 0) { return; }\n // remove class, data and id from item\n $item.removeClass('active').removeAttr('data-uuid').removeAttr('data-itemid').data('uuid', '').data('itemid', '').find('.compare-item-image').remove();\n}\n\nfunction addProductAjax(args) {\n const promise = new TPromise((resolve, reject) => {\n $.ajax({\n url: Urls.compareAdd,\n data: {\n pid: args.itemid,\n category: currentCategory,\n },\n dataType: 'json',\n }).done((response) => {\n if (!response || !response.success) {\n reject(new Error(Resources.COMPARE_ADD_FAIL));\n } else {\n resolve(response);\n }\n }).fail((jqxhr, status, err) => {\n reject(new Error(err));\n });\n });\n return promise;\n}\n\nfunction removeProductAjax(args) {\n const promise = new TPromise((resolve, reject) => {\n $.ajax({\n url: Urls.compareRemove,\n data: {\n pid: args.itemid,\n category: currentCategory,\n },\n dataType: 'json',\n }).done((response) => {\n if (!response || !response.success) {\n reject(new Error(Resources.COMPARE_REMOVE_FAIL));\n } else {\n resolve(response);\n }\n }).fail((jqxhr, status, err) => {\n reject(new Error(err));\n });\n });\n return promise;\n}\n\nfunction shiftImages() {\n return new TPromise((resolve) => {\n const $items = $('.compare-items .compare-item');\n $items.each((i, item) => {\n const $item = $(item);\n // last item\n if (i === $items.length - 1) {\n removeFromList($item);\n return;\n }\n const $next = $items.eq(i + 1);\n if ($next.hasClass('active')) {\n // remove its own image\n $next.find('.compare-item-image').detach().appendTo($item);\n $item.addClass('active')\n .attr('data-uuid', $next.data('uuid'))\n .attr('data-itemid', $next.data('itemid'))\n .data('uuid', $next.data('uuid'))\n .data('itemid', $next.data('itemid'));\n }\n });\n resolve();\n });\n}\n\n/**\n * @function\n * @description Removes product from the compare table\n * @param {object} args - the arguments object should have the following properties: itemid, uuid and cb (checkbox)\n */\nfunction removeProduct(args) {\n const $cb = args.cb ? $(args.cb) : null;\n return removeProductAjax(args).then(() => {\n const $item = $(`[data-uuid=\"${args.uuid}\"]`);\n removeFromList($item);\n if ($cb && $cb.length > 0) { $cb[0].checked = false; }\n refreshContainer();\n }, () => {\n if ($cb && $cb.length > 0) { $cb[0].checked = true; }\n });\n}\n\nfunction removeItem($item) {\n const uuid = $item.data('uuid');\n const $productTile = $(`#${uuid}`);\n return removeProduct({\n itemid: $item.data('itemid'),\n uuid,\n cb: ($productTile.length === 0) ? null : $productTile.find('.compare-check'),\n });\n}\n\n/**\n * @function\n * @description Adds product to the compare table\n */\n// eslint-disable-next-line\nfunction addProduct(args) {\n let promise;\n const $items = $('.compare-items .compare-item');\n const $cb = $(args.cb);\n const numActive = $items.filter('.active').length;\n if (numActive === MAX_ACTIVE) {\n let dontRemoveEl = true;\n dialog.open({\n html: Resources.COMPARE_CONFIRMATION,\n options: {\n width: 530,\n buttons: [{\n text: Resources.REMOVE,\n class: 'button primary',\n click() {\n // remove product using id\n dontRemoveEl = false;\n const $firstItem = $items.first();\n promise = removeItem($firstItem).then(() => shiftImages());\n $(this).dialog('close');\n return promise.then(() => addProductAjax(args).then(() => {\n addToList(args);\n if ($cb && $cb.length > 0) { $cb[0].checked = true; }\n refreshContainer();\n })).then(null, () => {\n if ($cb && $cb.length > 0) { $cb[0].checked = false; }\n });\n },\n }, {\n text: Resources.NO_THANKS,\n class: 'button tertiary',\n click() {\n $(this).dialog('close');\n },\n }],\n close() {\n if (dontRemoveEl) {\n $cb[0].checked = false;\n }\n },\n },\n });\n } else {\n promise = TPromise.resolve(0);\n return promise.then(() => addProductAjax(args).then(() => {\n addToList(args);\n if ($cb && $cb.length > 0) { $cb[0].checked = true; }\n refreshContainer();\n })).then(null, () => {\n if ($cb && $cb.length > 0) { $cb[0].checked = false; }\n });\n }\n}\n\n/**\n * @private\n * @function\n * @description Initializes the DOM-Object of the compare container\n */\nfunction initializeDom() {\n const $compareContainer = $('.compare-items');\n currentCategory = $compareContainer.data('category') || '';\n const $active = $compareContainer.find('.compare-item').filter('.active');\n $active.each((index, element) => {\n const $productTile = $(`#${$(element).data('uuid')}`);\n if ($productTile.length === 0) { return; }\n $productTile.find('.compare-check')[0].checked = true;\n });\n // set container state\n refreshContainer();\n}\n\n/**\n * @private\n * @function\n * @description Initializes the events on the compare container\n */\nfunction initializeEvents() {\n // add event to buttons to remove products\n $('.compare-item').on('click', '.compare-item-remove', (e) => {\n removeItem($(e.currentTarget).closest('.compare-item'));\n });\n\n // Button to go to compare page\n $('#compare-items-button').on('click', () => {\n const additionalPar = {category: currentCategory};\n $('.compare-items-panel .compare-item.active').each((index, element) => {\n additionalPar[`_itemid_${$(this).data('itemid')}`] = $(element).data('colorval');\n });\n page.redirect(util.appendParamsToUrl(Urls.compareShow, additionalPar));\n });\n\n // Button to clear all compared items\n // rely on refreshContainer to take care of hiding the container\n $('#clear-compared-items').on('click', () => {\n $('.compare-items .active').each((index, element) => {\n removeItem($(element));\n });\n });\n}\n\nexports.init = function init() {\n initializeDom();\n initializeEvents();\n};\n\nexports.addProduct = addProduct;\nexports.removeProduct = removeProduct;\n","const ajax = require('../../ajax');\nconst util = require('../../util');\n\nfunction updateContainer(data) {\n const $availabilityMsg = $('#pdpMain .availability .availability-msg');\n let message; // this should be lexically scoped, when `let` is supported (ES6)\n if (!data) {\n $availabilityMsg.html(Resources.ITEM_STATUS_NOTAVAILABLE);\n return;\n }\n $availabilityMsg.empty();\n // Look through levels ... if msg is not empty, then create span el\n if (data.levels.IN_STOCK > 0) {\n if (data.levels.PREORDER === 0 && data.levels.BACKORDER === 0 && data.levels.NOT_AVAILABLE === 0) {\n // Just in stock\n message = Resources.IN_STOCK;\n } else {\n // In stock with conditions ...\n message = data.inStockMsg;\n }\n $availabilityMsg.append(`
${message}
`);\n }\n if (data.levels.PREORDER > 0) {\n if (data.levels.IN_STOCK === 0 && data.levels.BACKORDER === 0 && data.levels.NOT_AVAILABLE === 0) {\n message = Resources.PREORDER;\n } else {\n message = data.preOrderMsg;\n }\n $availabilityMsg.append(`${message}
`);\n }\n if (data.levels.BACKORDER > 0) {\n if (data.levels.IN_STOCK === 0 && data.levels.PREORDER === 0 && data.levels.NOT_AVAILABLE === 0) {\n message = Resources.BACKORDER;\n } else {\n message = data.backOrderMsg;\n }\n $availabilityMsg.append(`${message}
`);\n }\n if (data.inStockDate !== '') {\n $availabilityMsg.append(`${String.format(Resources.IN_STOCK_DATE, data.inStockDate)}
`);\n }\n if (data.levels.NOT_AVAILABLE > 0) {\n if (data.levels.PREORDER === 0 && data.levels.BACKORDER === 0 && data.levels.IN_STOCK === 0) {\n message = Resources.NOT_AVAILABLE;\n } else {\n message = Resources.REMAIN_NOT_AVAILABLE;\n }\n $availabilityMsg.append(`${message}
`);\n }\n}\n\nfunction getAvailability() {\n ajax.getJson({\n url: util.appendParamsToUrl(Urls.getAvailability, {\n pid: $('#pid').val(),\n Quantity: $(this).val(),\n }),\n callback: updateContainer,\n });\n}\n\nmodule.exports = function availability() {\n $('body').on('change', '.pdpForm input[name=\"Quantity\"], .pdpForm select[name=\"Quantity\"]', getAvailability);\n};\n","const dialog = require('../../dialog');\nconst tooltip = require('../../tooltip');\nconst util = require('../../util');\nconst addToCart = require('./addToCart');\nconst availability = require('./availability');\nconst image = require('./image');\nconst productNav = require('./productNav');\nconst productSet = require('./productSet');\nconst variant = require('./variant');\n\n/**\n * @description Initialize product detail page with reviews, recommendation and product navigation.\n */\nfunction initializeDom() {\n productNav();\n tooltip.init();\n $('.recommendations-container .tiles-container').slick({\n speed: 300,\n dots: false,\n arrows: true,\n slide: '.grid-tile',\n slidesToShow: 4,\n slidesToScroll: 1,\n responsive: [\n {\n breakpoint: util.getViewports('md'),\n settings: {\n slidesToShow: 2,\n },\n },\n {\n breakpoint: 690,\n settings: {\n slidesToShow: 1,\n },\n },\n ],\n });\n}\n\n/**\n * @description Initialize event handlers on product detail page\n */\nfunction initializeEvents() {\n const $pdpMain = $('#pdpMain');\n\n addToCart();\n availability();\n variant();\n image();\n productSet();\n util.initDynamicCarousel('[id^=\"cq_recomm_slot\"]', '.recommendations-container .tiles-container', 0);\n util.initDynamicCarousel('[id^=\"cq_recomm_slot\"]', '.recommendations-container .tiles-container', 1);\n\n // Add to Wishlist and Add to Gift Registry links behaviors\n $pdpMain.on('click', '[data-action=\"wishlist\"], [data-action=\"gift-registry\"]', (e) => {\n const data = util.getQueryStringParams($('.pdpForm').serialize());\n if (data.cartAction) {\n delete data.cartAction;\n }\n const url = util.appendParamsToUrl(e.currentTarget.href, data);\n e.currentTarget.setAttribute('href', url);\n });\n\n $pdpMain.on('click', '#ask-a-question-link', (event) => {\n const $askAQuestionLink = $(event.target);\n\n const $quickViewDialog = $askAQuestionLink.closest('#QuickViewDialog');\n const $fullPdpLinkWithHashParam = $('.pdp-linkto-questions');\n if ($quickViewDialog.length && $fullPdpLinkWithHashParam.length) {\n $fullPdpLinkWithHashParam[0].click();\n return;\n }\n\n const $prQuestionBtn = $('#pr-question-form-link');\n $('.tab.questions .tab-header').addClass('expanded');\n\n $prQuestionBtn.trigger('click');\n if ($prQuestionBtn.offset().top) {\n $('html, body').animate({\n scrollTop: ($prQuestionBtn.offset().top),\n }, 200);\n }\n });\n\n // product options\n $pdpMain.on('change', '.product-options select', (e) => {\n const salesPrice = $pdpMain.find('.product-add-to-cart .price-sales');\n const selectedItem = $(e.currentTarget).children().filter(':selected').first();\n salesPrice.text(selectedItem.data('combined'));\n });\n\n // prevent default behavior of thumbnail link and add this Button\n $pdpMain.on('click', '.thumbnail-link, .unselectable a', (e) => {\n e.preventDefault();\n });\n\n // convert personalization fields to all caps that require uppercase\n $pdpMain.on('blur', '.personalization-input.uppercase', (e) => {\n $(e.currentTarget).val($(e.currentTarget).val().toUpperCase());\n });\n\n // show hidden personalization fields when the 'Show More Options' link is clicked\n $pdpMain.on('click', '.show-more', (e) => {\n e.preventDefault();\n $('.personalization-option.visually-hidden').removeClass('visually-hidden');\n $(e.currentTarget).hide();\n });\n\n // show hidden optional personalization fields when the checkbox is checked\n $pdpMain.on('click', '#personalized-check', (e) => {\n if ($(e.currentTarget).is(':checked')) {\n $(e.currentTarget).closest('.personalization-box').find('.optional-personalization').css('display', 'block');\n $pdpMain.find('.swatchanchor').each((index, element) => {\n element.setAttribute('href', util.appendParamsToUrl(element.href, {personalizedChecked: 'true'}));\n });\n } else {\n $(e.currentTarget).closest('.personalization-box').find('.optional-personalization').css('display', 'none');\n $pdpMain.find('.swatchanchor').each((index, element) => {\n element.setAttribute('href', util.removeParamFromURL(element.href, 'personalizedChecked'));\n });\n }\n });\n\n // dynamic max quantity values for pick n choose products\n $pdpMain.on('change', 'input.pnc-qty', () => {\n const packCount = parseInt($('.pnc').data('packcount'), 10);\n let totalQty = 0;\n // calculate the total quantity of pick n choose items\n $('input.pnc-qty').each((index, element) => {\n totalQty += parseInt($(element).val(), 10);\n });\n // set the new max quantity based on quantity remaining in the selected pack\n const remainingQty = packCount - totalQty;\n $('input.pnc-qty:not(.disabled)').each((index, element) => {\n const maxAmount = parseInt($(element).val(), 10) + remainingQty;\n const maxAvailable = parseInt($(element).data('available'), 10);\n // make sure max is not more than the amount available\n $(element).prop('max', maxAmount > maxAvailable ? maxAvailable : maxAmount);\n });\n if (totalQty <= packCount && totalQty >= 0) {\n $pdpMain.find('.pnc-remain-count').text(totalQty);\n }\n });\n\n $('.size-chart-link a').on('click', (e) => {\n e.preventDefault();\n dialog.open({\n url: $(e.target).attr('href'),\n });\n });\n\n $pdpMain.on('click', '.tab-header', (e) => {\n $(e.currentTarget).toggleClass('expanded');\n }).on('click', '.open-dialog', (e) => {\n e.preventDefault();\n dialog.open({\n url: $(e.currentTarget).attr('href'),\n doClose: $('.pt_product-search-result').length === 0,\n options: {\n title: $(e.currentTarget).find('.visually-hidden').text() || $(e.currentTarget).attr('title'),\n },\n });\n }).on('click', '.restrictions-dialog', (e) => {\n e.preventDefault();\n dialog.open({\n url: $(e.target).attr('href'),\n doClose: $('.pt_product-search-result').length === 0,\n options: {\n width: 540,\n title: $(e.target).attr('title'),\n dialogClass: 'restrictions-dialog',\n },\n });\n });\n\n // Pick 'n Choose\n const pncAttribute = $('ul.colpackcount');\n if (pncAttribute.length > 0) {\n // Trigger Pick 'n Choose quantity inputs to reset max quantity\n $pdpMain.find('.pnc-qty').trigger('change');\n }\n}\n\nconst product = {\n initializeEvents,\n init() {\n initializeDom();\n initializeEvents();\n },\n};\n\nmodule.exports = product;\n","const ajax = require('../../ajax');\nconst util = require('../../util');\n\n/**\n * @description loads product's navigation\n * */\nmodule.exports = () => {\n const $pidInput = $('.pdpForm input[name=\"pid\"]').last();\n const $navContainer = $('#product-nav-container');\n // if no hash exists, or no pid exists, or nav container does not exist, return\n if (window.location.hash.length <= 1 || $pidInput.length === 0 || $navContainer.length === 0) {\n return;\n }\n\n const pid = $pidInput.val();\n const hash = window.location.hash.substr(1);\n const url = util.appendParamToURL(`${Urls.productNav}?${hash}`, 'pid', pid);\n\n ajax.load({\n url,\n target: $navContainer,\n });\n};\n","const ajax = require('../../ajax');\nconst tooltip = require('../../tooltip');\nconst util = require('../../util');\n\nmodule.exports = () => {\n const $addToCart = $('#add-to-cart');\n const $addAllToCart = $('#add-all-to-cart');\n const $productSetList = $('#product-set-list');\n\n const updateAddToCartButtons = () => {\n if ($productSetList.find('.add-to-cart-disabled').length > 0) {\n $addAllToCart.attr('disabled', 'disabled');\n // product set does not have an add-to-cart button, but product bundle does\n $addToCart.attr('disabled', 'disabled');\n } else {\n $addAllToCart.removeAttr('disabled');\n $addToCart.removeAttr('disabled');\n }\n };\n\n const updateAddAllToCartButton = () => {\n if ($productSetList.find('.product-set-item form').not('.suppressed').length === 0) {\n $addAllToCart.attr('disabled', 'disabled');\n } else if ($productSetList.find('.add-to-cart-disabled').length === 0) {\n $addAllToCart.removeAttr('disabled');\n }\n };\n\n const suppressForm = (el) => {\n const qtyVal = el.val();\n const parentForm = el.parents('form');\n if (qtyVal < 1 || qtyVal === '') {\n parentForm.addClass('suppressed');\n } else {\n parentForm.removeClass('suppressed');\n }\n updateAddAllToCartButton();\n };\n\n if ($productSetList.length > 0) {\n updateAddToCartButtons();\n }\n // click on swatch for product set\n $productSetList.on('click', '.product-set-item .swatchanchor', (e) => {\n e.preventDefault();\n if ($(e.currentTarget).parents('li').hasClass('unselectable')) { return; }\n const url = Urls.getSetItem + e.currentTarget.search;\n const $container = $(e.currentTarget).closest('.product-set-item');\n const qty = $container.find('form input[name=\"Quantity\"], form select[name=\"Quantity\"]').first().val();\n\n const ratingHtml = $container.find('.rating-wrapper').html();\n\n ajax.load({\n url: util.appendParamToURL(url, 'Quantity', Number.isNaN(qty) ? '1' : qty),\n target: $container,\n callback() {\n updateAddToCartButtons();\n tooltip.init();\n const newQtyField = $container.find('form input[name=\"Quantity\"], form select[name=\"Quantity\"]').first();\n suppressForm(newQtyField);\n if (ratingHtml) {\n $container.find('.rating-wrapper').html(ratingHtml);\n }\n },\n });\n // handle selects for product sets\n }).on('change', '.product-set-item .variation-select', (e) => {\n e.preventDefault();\n const selectedOptionURL = $(e.currentTarget).val();\n const selectedOptionURLtrim = selectedOptionURL.indexOf('?');\n const variationValue = selectedOptionURL.substring(selectedOptionURLtrim);\n const url = Urls.getSetItem + variationValue;\n const $container = $(e.currentTarget).closest('.product-set-item');\n const qty = $container.find('form input[name=\"Quantity\"], form select[name=\"Quantity\"]').first().val();\n\n ajax.load({\n url: util.appendParamToURL(url, 'Quantity', Number.isNaN(qty) ? '1' : qty),\n target: $container,\n callback() {\n updateAddToCartButtons();\n tooltip.init();\n const newQtyField = $container.find('form input[name=\"Quantity\"], form select[name=\"Quantity\"]').first();\n suppressForm(newQtyField);\n },\n });\n }).on('change', '.product-set-item input[name=\"Quantity\"]', (e) => {\n suppressForm($(e.currentTarget));\n }).on('click', '.add-to-cart', (e) => {\n const parentForm = $(e.currentTarget).parents('.product-add-to-cart');\n if (parentForm.hasClass('suppressed')) {\n parentForm.removeClass('suppressed');\n updateAddAllToCartButton();\n }\n });\n\n /* global pwr */\n if (SitePreferences.ENABLE_POWER_REVIEWS) {\n window.pwr = window.pwr || function initPwr(...args) {\n (pwr.q = pwr.q || []).push(args);\n };\n\n const snippets = $('.ps-review-snippet');\n\n if (snippets.length > 0) {\n const prArray = [];\n snippets.each((idx, snippet) => {\n const $snippet = $(snippet);\n prArray.push({\n ENABLE_CLIENT_SIDE_STRUCTURED_DATA: false,\n api_key: SitePreferences.PR_API_KEY,\n locale: SitePreferences.PR_LOCALE,\n merchant_group_id: SitePreferences.PR_MERCHANT_GROUP_ID,\n merchant_id: SitePreferences.PR_MERCHANT_ID,\n page_id: $snippet.data('page-id'),\n components: {\n CategorySnippet: snippet.id,\n },\n });\n });\n\n pwr('render', prArray);\n const targetNode = document.getElementById('product-set-list');\n\n const observer = new MutationObserver((mutationList) => {\n mutationList.forEach((mutation) => {\n if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {\n const $links = $(mutation.target).find('.pr-no-reviews').parents('.rating-wrapper').find('.links');\n if ($links.length > 0) {\n $($links.children()[0]).hide();\n $($links.children()[1]).html(Resources.WRITE_FIRST_REVIEW);\n }\n }\n });\n });\n\n observer.observe(targetNode, {childList: true, subtree: true});\n }\n }\n};\n","const ajax = require('../../ajax');\nconst image = require('./image');\nconst progress = require('../../progress');\nconst productStoreInventory = require('../../storeinventory/product');\nconst tooltip = require('../../tooltip');\nconst util = require('../../util');\nconst validator = require('../../validator');\n\n/**\n * @description restore form values when product content is updated (Personalization and Pick 'n Choose)\n * @param {Array} formdata - array with name/value objects\n * @param {String} eventType - the type of event to trigger on the updated field\n * */\nfunction restoreFormValues(formdata, eventType) {\n $.each(formdata, (i, val) => {\n if (val.value !== '' && $(`#${val.name}`).length > 0) {\n // Update value and trigger event for validation/update\n $(`#${val.name}`).val(val.value).trigger(eventType);\n }\n });\n}\n\n/**\n * @function\n * @desc Replaces the PDP header with the updated variation information\n */\nfunction replaceHeader() {\n const $newHeading = $('.update-product-content-header');\n const $targetHeading = $('.product-col-1');\n\n if ($newHeading.length && $targetHeading.length) {\n $targetHeading.html($newHeading.html());\n $newHeading.remove();\n }\n}\n\n/**\n * @description update product content with new variant from href, load new content to #product-content panel\n * @param {String} href - url of the new product variant\n * */\nfunction updateContent(href) {\n const $pdpForm = $('.pdpForm');\n const qty = $pdpForm.find('input[name=\"Quantity\"], select[name=\"Quantity\"]').first().val();\n const params = {\n Quantity: Number.isNaN(qty) ? '1' : qty,\n format: 'ajax',\n productlistid: $pdpForm.find('input[name=\"productlistid\"]').first().val(),\n };\n // Save personalized values before refreshing content\n const personalizationValues = $('.personalization-options input, .personalization-options select').serializeArray();\n const pncOldPackSize = $('.pnc').data('packcount');\n const pncValues = $('.pnc input').serializeArray();\n const showMore = $('a.show-more').is(':hidden');\n\n progress.show($('#pdpMain'));\n\n ajax.load({\n url: util.appendParamsToUrl(href, params),\n target: $('#product-content'),\n callback() {\n if (SitePreferences.STORE_PICKUP) {\n productStoreInventory.init();\n }\n\n // Replace the PDP images\n image.replaceImages();\n // Replace the PDP heading content (name, id, price)\n replaceHeader();\n // Re-init the tooltips\n tooltip.init();\n if ($('#product-content').length > 0) {\n image.heroCarousel();\n image.wistiaThumbmail();\n }\n if (personalizationValues.length > 0) {\n // Re-init the validator\n validator.init();\n // Restore personalization values\n restoreFormValues(personalizationValues, 'blur');\n // Show extra options if 'Show More Options' has already been clicked\n if (showMore) {\n $('a.show-more').click();\n }\n }\n // Restore Pick 'n Choose quantities\n if (pncValues.length > 0) {\n const pncNewPackSize = $('.pnc').data('packcount');\n // Only restore quantities if moving to a larger pack size\n if (parseInt(pncNewPackSize, 10) > parseInt(pncOldPackSize, 10)) {\n restoreFormValues(pncValues, 'change');\n // Trigger one more change because the 'X of X items selected' text doesn't consistently update\n $('input.pnc-qty').change();\n }\n }\n },\n });\n}\n\nmodule.exports = () => {\n const $pdpMain = $('#pdpMain');\n\n // click on swatch - should replace product content with new variant\n $pdpMain.on('click', '.product-detail .swatchanchor', (e) => {\n e.preventDefault();\n if ($(e.currentTarget).parents('li').hasClass('unselectable')) { return; }\n updateContent(e.currentTarget.href);\n });\n\n // change drop down variation attribute - should replace product content with new variant\n $pdpMain.on('change', '.variation-select', (e) => {\n const $productSetList = $('#product-set-list');\n if ($(e.currentTarget).val().length === 0) { return; }\n if ($productSetList.length === 0) {\n updateContent($(e.currentTarget).val());\n }\n });\n};\n","const compareWidget = require('../compare-widget');\nconst productTile = require('../product-tile');\nconst util = require('../util');\n\n/**\n * @function\n * @desc Loads a new search page based on the grid URL on the place holder\n * @param loadingPlaceHolder {jQuery} Selector used to find the unloaded infinite scroll placeholder\n * @returns\n */\nfunction loadSearchPage(loadingPlaceHolder) {\n // get url hidden in DOM\n const gridUrl = loadingPlaceHolder.attr('data-grid-url');\n\n // switch state to 'loading'\n // - switches state, so the above selector is only matching once\n // - shows loading indicator\n loadingPlaceHolder.attr('data-loading-state', 'loading');\n loadingPlaceHolder.addClass('infinite-scroll-loading');\n\n // named wrapper function, which can either be called, if cache is hit, or ajax repsonse is received\n const fillEndlessScrollChunk = (html) => {\n loadingPlaceHolder.removeClass('infinite-scroll-loading');\n loadingPlaceHolder.attr('data-loading-state', 'loaded');\n $('.search-result-content').append(html);\n };\n $.ajax({\n type: 'GET',\n dataType: 'html',\n url: gridUrl,\n success(response) {\n // update UI\n fillEndlessScrollChunk(response);\n productTile.init();\n },\n });\n}\n\n/**\n * @function\n * @desc Loads a new page of the infinite scroll if an unloaded placeholder is found\n * @returns\n */\nfunction infiniteScroll() {\n // getting the hidden div, which is the placeholder for the next page\n const loadingPlaceHolder = $('.infinite-scroll-placeholder[data-loading-state=\"unloaded\"]');\n\n if (loadingPlaceHolder.length === 1 && util.elementInViewport(loadingPlaceHolder.get(0), 250)) {\n loadSearchPage(loadingPlaceHolder);\n }\n}\n\n/**\n * @private\n * @function\n * @description Initializes events for the following elements:refinement blocks
\n *updating grid: refinements, pagination, breadcrumb
\n *item click
\n *sorting changes
\n */\nfunction initializeEvents() {\n const $main = $('#main');\n // compare checked\n $main.on('click', 'input[type=\"checkbox\"].compare-check', (event) => {\n event.preventDefault();\n const cb = $(event.currentTarget);\n const tile = cb.closest('.product-tile');\n const func = event.currentTarget.checked ? compareWidget.addProduct : compareWidget.removeProduct;\n const itemImg = tile.find('.product-image a img').first();\n func({\n itemid: tile.data('itemid'),\n uuid: tile[0].id,\n img: itemImg,\n cb,\n colorval: tile.find('.swatch.selected').data('colorval') || '',\n });\n });\n\n /**\n * Code to detect if the Enter key is pressed on Refinement headings, then toggle the expanded class and the aria-expanded attribute and trigger chane event on checkbox selection.\n */\n\n // Get all h3 elements where class is refinement-header\n const refinementHeaders = document.querySelectorAll('h3.refinement-header');\n\n // Add event listener for 'keydown' event on each h3 element using arrow function\n refinementHeaders.forEach((h3) => {\n h3.addEventListener('keydown', (e) => {\n // Check if Enter key was pressed\n if (e.key === 'Enter') {\n $(e.currentTarget).toggleClass('expanded').attr(\n 'aria-expanded',\n $(e.currentTarget).attr('aria-expanded') === 'false' ? 'true' : 'false',\n );\n }\n });\n });\n\n // Get all checkboxes\n const refinementCheckboxes = document.querySelectorAll('input[type=\"checkbox\"].refinement-checkbox');\n // Add event listeners for the Enter key\n refinementCheckboxes.forEach((checkbox) => {\n checkbox.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n const targetCheckbox = checkbox;\n targetCheckbox.checked = !targetCheckbox.checked;\n const changeEvent = new Event('change', {bubbles: true, cancelable: true});\n checkbox.dispatchEvent(changeEvent);\n }\n });\n });\n\n $main.on('click', '.refinement > a.toggle, .refinement > h3, .refinement > a', (e) => {\n e.preventDefault();\n\n if (!$('.search-refinements-section').length > 0) {\n $(e.currentTarget).toggleClass('expanded').attr(\n 'aria-expanded',\n $(e.currentTarget).attr('aria-expanded') === 'false' ? 'true' : 'false',\n );\n }\n }).on('click', '.refinement .clear', (e) => {\n e.stopPropagation();\n }).on('click', '.refinement .see-more', (e) => {\n e.preventDefault();\n $(e.currentTarget).parents('ul').find('li').removeClass('hidden');\n $(e.currentTarget).parents('.see-more-ref').addClass('hidden');\n });\n\n if ($(window).innerWidth() >= util.getViewports('lg')) {\n $('.refinement > h3').slice(0, 4).addClass('expanded')\n .attr('aria-expanded', 'true');\n }\n util.smartResize(() => {\n if ($(window).innerWidth() >= util.getViewports('lg')) {\n $('.refinement > h3').slice(0, 4).addClass('expanded')\n .attr('aria-expanded', 'true');\n } else {\n $('.refinement > h3').slice(1).removeClass('expanded')\n .attr('aria-expanded', 'false');\n }\n });\n\n // handle events for updating grid\n $main.on('click', '.refinements a:not(.see-more), .pagination a, .breadcrumb-refinement-value a, .selected-refinement-value a, .clear-all-refinements', (e) => {\n // don't intercept for category and folder refinements, as well as unselectable\n if ($(e.currentTarget).parents('.category-refinement').length > 0 || $(e.currentTarget).parents('.folder-refinement').length > 0 || $(e.currentTarget).parent().hasClass('unselectable')) {\n return;\n }\n e.preventDefault();\n if ($(e.currentTarget).hasClass('clear-all-refinements')) {\n const queryString = util.getQueryString(window.location.href);\n const params = util.getQueryStringParams(queryString);\n let newURL = window.location.href.split('?')[0];\n\n // Remove all refinements. Keep any other parameter (q, cgid, srule, etc)\n $.each(params, (key, value) => {\n if (key.indexOf('pref') === -1 && key.indexOf('pmax') === -1 && key.indexOf('pmin') === -1) {\n newURL = util.appendParamToURL(newURL, key, value);\n }\n });\n\n $(e.currentTarget).attr('href', newURL);\n }\n\n let focusElement = $(e.currentTarget).attr('id');\n\n if (focusElement) {\n focusElement = `#${focusElement}`;\n }\n\n if ($('#secondary').hasClass('open')) {\n $('#wrapper').addClass('open-refinements');\n } else {\n $('#wrapper').removeClass('open-refinements');\n }\n\n window.location.href = e.currentTarget.href;\n\n if ($(e.currentTarget).parents('.pagination')) {\n $('html,body').animate({\n scrollTop: 0,\n }, 700);\n }\n });\n\n // handle events item click. append params.\n $main.on('click', '.product-tile a:not(#quickviewbutton)', (e) => {\n const a = $(e.currentTarget);\n // get current page refinement values\n const wl = window.location;\n const qsParams = (wl.search.length > 1) ? util.getQueryStringParams(wl.search.substr(1)) : {};\n const hashParams = (wl.hash.length > 1) ? util.getQueryStringParams(wl.hash.substr(1)) : {};\n\n // merge hash params with querystring params\n const params = $.extend(hashParams, qsParams);\n if (!params.start) {\n params.start = 0;\n }\n // get the index of the selected item and save as start parameter\n const tile = a.closest('.product-tile');\n const idx = tile.data('idx') ? +tile.data('idx') : 0;\n\n // convert params.start to integer and add index\n params.start = (+params.start) + (idx + 1);\n // set the hash and allow normal action to continue\n a[0].hash = $.param(params);\n });\n\n // handle sorting change\n $main.on('change', '.sort-by select', (e) => {\n e.preventDefault();\n window.location.href = $(e.currentTarget).find('option:selected').val();\n }).on('change', '.items-per-page select', (e) => {\n const refineUrl = $(e.currentTarget).find('option:selected').val();\n if (refineUrl === 'INFINITE_SCROLL') {\n $('html').addClass('infinite-scroll').removeClass('disable-infinite-scroll');\n } else {\n $('html').addClass('disable-infinite-scroll').removeClass('infinite-scroll');\n window.location.href = refineUrl;\n }\n });\n\n // Close Refinements on tab out\n $('.clear-all-refinements').focusout(() => {\n if ($(window).innerWidth() < util.getViewports('lg')) {\n $('#secondary.refinements').hide();\n }\n });\n\n // Close Refinements on escape keyup\n $(document).keyup((e) => {\n if (e.keyCode === 27) {\n if ($(window).innerWidth() < util.getViewports('lg')) {\n $('#secondary.refinements').hide();\n $('#wrapper').removeClass('open-refinements');\n }\n }\n });\n\n /**\n * @listener\n * @desc Listen for the click event on the refinement section toggle\n */\n $('body').on('click', '.refinement-select, .refinements-btn-close', () => {\n $('.refinements').toggle('slide', {direction: 'down'}, 300)\n .toggleClass('open');\n $('#wrapper').toggleClass('open-refinements');\n });\n\n $('body').on('change', '.sr-only.refinement-checkbox', (e) => {\n const href = $(e.currentTarget).data('href');\n if (typeof href === 'string' && href.length > 0) {\n window.location = href;\n }\n });\n\n /**\n * @listener\n * @desc Listen for the click event on the infinite scroll loader link\n */\n $('body').on('click', '.infinite-scroll-loader', (e) => {\n loadSearchPage($(e.currentTarget));\n });\n\n if (SitePreferences.LISTING_INFINITE_SCROLL) {\n $(window).on('scroll', infiniteScroll);\n }\n $('.recommendations-container .tiles-container').slick({\n speed: 300,\n dots: false,\n arrows: true,\n slide: '.grid-tile',\n slidesToShow: 4,\n slidesToScroll: 1,\n responsive: [\n {\n breakpoint: util.getViewports('md'),\n settings: {\n slidesToShow: 2,\n },\n },\n {\n breakpoint: 690,\n settings: {\n slidesToShow: 1,\n },\n },\n ],\n });\n // In case the content is not ready on load helper function will set a mutation observer to reinit\n util.initDynamicCarousel('[id^=\"cq_recomm_slot\"]', '.recommendations-container .tiles-container', 0);\n}\n\n/**\n * Update the position of the bottom-cat-banner slot to outside the area that will be replaced by the refirment ajax call\n */\nfunction positionBVBottomSlot() {\n const $bottomcCatBanner = $('#bottom-cat-banner-container');\n if ($bottomcCatBanner.length > 0) {\n $bottomcCatBanner.insertAfter('#main');\n $bottomcCatBanner.show();\n }\n}\npositionBVBottomSlot();\n\nmodule.exports = {\n init() {\n compareWidget.init();\n productTile.init();\n initializeEvents();\n },\n};\n","const quickview = require('./quickview');\nconst util = require('./util');\n\nfunction initDataLayer() {\n /* global utag, utag_data */\n utag.view(utag_data);\n}\n\n/**\n * @function\n * @description Sets up the quick view button when called with the appropriate values\n * @param {jQuery} $link - Link that is used to define the quick view button\n * @param {boolean} focus - Mark this as true when the focus event is used\n */\nfunction initQuickView($link, focus) {\n let $qvButton = $('#quickviewbutton');\n\n if ($qvButton.length) {\n $qvButton.remove();\n }\n\n if ($link.parents('.product-tile').hasClass('disable-quickview')) {\n return;\n }\n\n $qvButton = $(`${Resources.QUICK_VIEW}${util.svg('qv-icon')}`);\n\n $qvButton.on('click', (e) => {\n e.preventDefault();\n quickview.show({\n url: $link.attr('href'),\n source: 'quickview',\n callback: initDataLayer,\n });\n });\n\n $qvButton.attr({\n href: $link.attr('href'),\n title: $link.attr('title'),\n });\n\n if (focus) {\n $qvButton.appendTo($link.parent('.product-image'));\n $qvButton.css('display', 'block');\n } else {\n $qvButton.appendTo($link.parent('.product-image'));\n }\n}\n\n/**\n * @function\n * @description Sets up the product tile so that when the mouse cursor enters the tile the quick view button appears\n */\nfunction initQuickViewButtons() {\n $('.tiles-container .product-image').on('mouseenter', (event) => {\n const $link = $(event.currentTarget).find('.thumb-link');\n initQuickView($link);\n });\n}\n\n/**\n * @function\n * @description Sets up the product tile so that when the tile is focused with the keyboard the quick view button appears\n */\nfunction initQuickViewButtonsFocus() {\n $('.tiles-container .product-image .thumb-link').on('focus', (event) => {\n const $link = $(event.currentTarget);\n initQuickView($link, true);\n });\n}\n\nfunction initRollover() {\n $('.tiles-container').on('mouseenter', '.product-image.rollover', (event) => {\n $(event.currentTarget).addClass('hover');\n }).on('mouseleave', '.product-image.rollover', (event) => {\n $(event.currentTarget).removeClass('hover');\n });\n}\nfunction syncTilesHeight() {\n const productTile = $('.tiles-container').find('.product-tile');\n let syncTiles = false;\n let inRow;\n if ($(window).innerWidth() >= util.getViewports('md')) {\n inRow = 3;\n syncTiles = true;\n } else if ($(window).innerWidth() >= util.getViewports('sm')) {\n inRow = 2;\n syncTiles = true;\n }\n\n productTile.find('.product-swatches, .product-promo, .product-pricing').removeAttr('style');\n if (syncTiles && productTile.length > 1) {\n for (let i = 0; i < productTile.length; i += inRow) {\n const swatchesArrayChunk = productTile.find('.product-swatches').slice(i, i + inRow);\n const promosArrayChunk = productTile.find('.product-promo').slice(i, i + inRow);\n const pricesArrayChunk = productTile.find('.product-pricing').slice(i, i + inRow);\n\n swatchesArrayChunk.syncHeight();\n promosArrayChunk.syncHeight();\n pricesArrayChunk.syncHeight();\n }\n }\n}\n\n/**\n * @private\n * @function\n * @description Initializes events on the product-tile for the following elements:\n * - swatches\n * - thumbnails\n */\nfunction initializeEvents() {\n initQuickViewButtons();\n initQuickViewButtonsFocus();\n initRollover();\n syncTilesHeight();\n\n /* global pwr */\n if (SitePreferences.ENABLE_POWER_REVIEWS) {\n window.pwr = window.pwr || function initPwr(...args) {\n (pwr.q = pwr.q || []).push(args);\n };\n\n const snippets = $('.pr-tile-review-snippet');\n\n if (snippets.length > 0) {\n const prArray = [];\n snippets.each((idx, snippet) => {\n const $snippet = $(snippet);\n prArray.push({\n ENABLE_CLIENT_SIDE_STRUCTURED_DATA: false,\n api_key: SitePreferences.PR_API_KEY,\n locale: SitePreferences.PR_LOCALE,\n merchant_group_id: SitePreferences.PR_MERCHANT_GROUP_ID,\n merchant_id: SitePreferences.PR_MERCHANT_ID,\n page_id: $snippet.data('page-id'),\n components: {\n CategorySnippet: snippet.id,\n },\n });\n\n const targetNode = snippet;\n\n /**\n * Funky code alert: PR will only add the review snippet to one element per\n * product ID, but for some searches including product sets, multiple results\n * use the same ID. This mutation observer watches for PR rendering the snippet\n * and copies this snippet to all elements with the same product ID.\n */\n const observer = new MutationObserver((mutationList) => {\n mutationList.forEach((mutation) => {\n if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {\n const $targetNode = $(targetNode);\n const pageId = $targetNode.attr('data-page-id');\n if ($targetNode.find('section').length > 0) {\n observer.disconnect();\n $(`[data-page-id=${pageId}]`).html($targetNode.html());\n }\n }\n });\n });\n\n observer.observe(targetNode, {childList: true, subtree: true});\n });\n\n pwr('render', prArray);\n }\n }\n\n util.smartResize(() => {\n syncTilesHeight();\n });\n\n $('.swatch-list').on('mouseleave', (event) => {\n // Restore current thumb image\n const $tile = $(event.currentTarget).closest('.product-tile');\n const $thumb = $tile.find('.product-image .thumb-link img').eq(0);\n const data = $thumb.data('current');\n if (data !== undefined) {\n $thumb.attr({\n src: data.src,\n alt: data.alt,\n title: data.title,\n });\n }\n });\n\n $('.swatch-list .swatch').on('click', (event) => {\n event.preventDefault();\n if ($(event.currentTarget).hasClass('selected')) { return; }\n\n const $tile = $(event.currentTarget).closest('.product-tile');\n $(event.currentTarget).closest('.swatch-list').find('.swatch.selected').removeClass('selected');\n $(event.currentTarget).addClass('selected');\n $tile.find('.thumb-link').attr('href', $(event.currentTarget).attr('href'));\n $tile.find('name-link').attr('href', $(event.currentTarget).attr('href'));\n const data = $(event.currentTarget).children('img').filter(':first').data('thumb');\n const altData = $(event.currentTarget).children('img').filter(':first').data('thumbalt');\n const $tileImg = $tile.find('.product-image');\n const $thumb = $tileImg.find('.thumb-link .thumb-front');\n const $thumbAlt = $tileImg.find('.thumb-link .thumb-back');\n const currentAttrs = {\n src: data.src,\n alt: data.alt,\n };\n $thumb.attr(currentAttrs);\n $thumb.data('current', currentAttrs);\n if ($thumbAlt.length > 0 && altData) {\n const currentBackAttrs = {\n src: altData.src,\n alt: altData.alt,\n };\n $thumbAlt.attr(currentBackAttrs);\n $tileImg.addClass('rollover');\n } else if (altData) {\n $(`',\n ` ${store.address1}
`,\n ` ${store.city}, ${store.stateCode} ${store.postalCode}`,\n '
${store.status}
`,\n ` ',\n '