{"version":3,"file":"default/js/productDetail.js","sources":["webpack:///webpack/bootstrap","webpack:///./cartridges/app_custom_jau_marketplace/cartridge/client/default/js/product/base.js","webpack:///./cartridges/app_custom_jau_marketplace/cartridge/client/default/js/product/detail.js","webpack:///./cartridges/app_custom_jau_marketplace/cartridge/client/default/js/productDetail.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/ajax.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/bonus-products-view.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/carousel.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/dialog.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/minicart.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/page.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/pages/favouritewidget.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/product-tile.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/progress.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/promos.js","webpack:///./cartridges/app_groceries/cartridge/client/default/js/util.js","webpack:///./cartridges/app_storefront_base/cartridge/client/default/js/components/focus.js","webpack:///./cartridges/app_storefront_base/cartridge/client/default/js/product/base.js","webpack:///./cartridges/app_storefront_base/cartridge/client/default/js/product/detail.js","webpack:///./cartridges/app_storefront_base/cartridge/client/default/js/util.js","webpack:///./node_modules/asap/browser-asap.js","webpack:///./node_modules/asap/browser-raw.js","webpack:///./node_modules/ev-emitter/ev-emitter.js","webpack:///./node_modules/imagesloaded/imagesloaded.js","webpack:///./node_modules/lodash/lodash.js","webpack:///./node_modules/promise/index.js","webpack:///./node_modules/promise/lib/core.js","webpack:///./node_modules/promise/lib/done.js","webpack:///./node_modules/promise/lib/es6-extensions.js","webpack:///./node_modules/promise/lib/finally.js","webpack:///./node_modules/promise/lib/index.js","webpack:///./node_modules/promise/lib/node-extensions.js","webpack:///./node_modules/promise/lib/synchronous.js","webpack:///(webpack)/buildin/global.js","webpack:///(webpack)/buildin/module.js"],"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./cartridges/app_custom_jau_marketplace/cartridge/client/default/js/productDetail.js\");\n","'use strict';\nvar base = require('base/product/base');\n\n/**\n * Retrieves the relevant pid value\n * @param {jquery} $el - DOM container for a given add to cart button\n * @return {string} - value to be used when adding product to cart\n */\nfunction getPidValue($el) {\n var pid;\n\n if ($('#quickViewModal').hasClass('show') && !$('.product-set').length) {\n pid = $($el).closest('.modal-content').find('.product-quickview').data('pid');\n } else if ($('.product-set-detail').length || $('.product-set').length) {\n pid = $($el).closest('.product-detail').find('.product-id').text();\n } else {\n pid = $('.product-detail:not(\".bundle-item\")').data('pid');\n }\n\n return pid;\n}\n\n/**\n * Retrieve contextual quantity selector\n * @param {jquery} $el - DOM container for the relevant quantity\n * @return {jquery} - quantity selector DOM container\n */\nfunction getQuantitySelector($el) {\n return $el && $('.set-items').length\n ? $($el).closest('.product-detail').find('.quantity-select')\n : $('.quantity-select');\n}\n\n/**\n * Retrieves the value associated with the Quantity pull-down menu\n * @param {jquery} $el - DOM container for the relevant quantity\n * @return {string} - value found in the quantity input\n */\nfunction getQuantitySelected($el) {\n return getQuantitySelector($el).val();\n}\n\n/**\n * Process the attribute values for an attribute that has image swatches\n *\n * @param {Object} attr - Attribute\n * @param {string} attr.id - Attribute ID\n * @param {Object[]} attr.values - Array of attribute value objects\n * @param {string} attr.values.value - Attribute coded value\n * @param {string} attr.values.url - URL to de/select an attribute value of the product\n * @param {boolean} attr.values.isSelectable - Flag as to whether an attribute value can be\n * selected. If there is no variant that corresponds to a specific combination of attribute\n * values, an attribute may be disabled in the Product Detail Page\n * @param {jQuery} $productContainer - DOM container for a given product\n * @param {Object} msgs - object containing resource messages\n */\nfunction processSwatchValues(attr, $productContainer, msgs) {\n attr.values.forEach(function (attrValue) {\n var $attrValue = $productContainer.find('[data-attr=\"' + attr.id + '\"] [data-attr-value=\"' +\n attrValue.value + '\"]');\n var $swatchButton = $attrValue.parent();\n\n if (attrValue.selected) {\n $attrValue.addClass('selected');\n $attrValue.siblings('.selected-assistive-text').text(msgs.assistiveSelectedText);\n } else {\n $attrValue.removeClass('selected');\n $attrValue.siblings('.selected-assistive-text').empty();\n }\n\n if (attrValue.url) {\n $swatchButton.attr('data-url', attrValue.url);\n } else {\n $swatchButton.removeAttr('data-url');\n }\n\n // Disable if not selectable\n $attrValue.removeClass('selectable unselectable');\n\n $attrValue.addClass(attrValue.selectable ? 'selectable' : 'unselectable');\n });\n}\n\n/**\n * Process attribute values associated with an attribute that does not have image swatches\n *\n * @param {Object} attr - Attribute\n * @param {string} attr.id - Attribute ID\n * @param {Object[]} attr.values - Array of attribute value objects\n * @param {string} attr.values.value - Attribute coded value\n * @param {string} attr.values.url - URL to de/select an attribute value of the product\n * @param {boolean} attr.values.isSelectable - Flag as to whether an attribute value can be\n * selected. If there is no variant that corresponds to a specific combination of attribute\n * values, an attribute may be disabled in the Product Detail Page\n * @param {jQuery} $productContainer - DOM container for a given product\n */\nfunction processNonSwatchValues(attr, $productContainer) {\n var $attr = '[data-attr=\"' + attr.id + '\"]';\n var $defaultOption = $productContainer.find($attr + ' .select-' + attr.id + ' option:first');\n $defaultOption.attr('value', attr.resetUrl);\n\n attr.values.forEach(function (attrValue) {\n var $attrValue = $productContainer\n .find($attr + ' [data-attr-value=\"' + attrValue.value + '\"]');\n $attrValue.attr('value', attrValue.url)\n .removeAttr('disabled');\n\n if (!attrValue.selectable) {\n $attrValue.attr('disabled', true);\n }\n });\n}\n\n/**\n * Routes the handling of attribute processing depending on whether the attribute has image\n * swatches or not\n *\n * @param {Object} attrs - Attribute\n * @param {string} attr.id - Attribute ID\n * @param {jQuery} $productContainer - DOM element for a given product\n * @param {Object} msgs - object containing resource messages\n */\nfunction updateAttrs(attrs, $productContainer, msgs) {\n // Currently, the only attribute type that has image swatches is Color.\n var attrsWithSwatches = ['color'];\n\n attrs.forEach(function (attr) {\n if (attrsWithSwatches.indexOf(attr.id) > -1) {\n processSwatchValues(attr, $productContainer, msgs);\n } else {\n processNonSwatchValues(attr, $productContainer);\n }\n });\n}\n\n/**\n * Updates the availability status in the Product Detail Page\n *\n * @param {Object} response - Ajax response object after an\n * attribute value has been [de]selected\n * @param {jQuery} $productContainer - DOM element for a given product\n */\nfunction updateAvailability(response, $productContainer) {\n var availabilityValue = '';\n var availabilityMessages = response.product.availability.messages;\n if (!response.product.readyToOrder) {\n availabilityValue = '
  • ' + response.resources.info_selectforstock + '
  • ';\n } else {\n availabilityMessages.forEach(function (message) {\n availabilityValue += '
  • ' + message + '
  • ';\n });\n }\n\n $($productContainer).trigger('product:updateAvailability', {\n product: response.product,\n $productContainer: $productContainer,\n message: availabilityValue,\n resources: response.resources\n });\n}\n\n/**\n * Generates html for product attributes section\n *\n * @param {array} attributes - list of attributes\n * @return {string} - Compiled HTML\n */\nfunction getAttributesHtml(attributes) {\n if (!attributes) {\n return '';\n }\n\n var html = '';\n\n attributes.forEach(function (attributeGroup) {\n if (attributeGroup.ID === 'mainAttributes') {\n attributeGroup.attributes.forEach(function (attribute) {\n html += '
    ' + attribute.label + ': '\n + attribute.value + '
    ';\n });\n }\n });\n\n return html;\n}\n\n/**\n * @typedef UpdatedOptionValue\n * @type Object\n * @property {string} id - Option value ID for look up\n * @property {string} url - Updated option value selection URL\n */\n\n/**\n * @typedef OptionSelectionResponse\n * @type Object\n * @property {string} priceHtml - Updated price HTML code\n * @property {Object} options - Updated Options\n * @property {string} options.id - Option ID\n * @property {UpdatedOptionValue[]} options.values - Option values\n */\n\n/**\n * Updates DOM using post-option selection Ajax response\n *\n * @param {OptionSelectionResponse} optionsHtml - Ajax response optionsHtml from selecting a product option\n * @param {jQuery} $productContainer - DOM element for current product\n */\nfunction updateOptions(optionsHtml, $productContainer) {\n\t// Update options\n $productContainer.find('.product-options').empty().html(optionsHtml);\n}\n\n/**\n * Dynamically creates Bootstrap carousel from response containing images\n * @param {Object[]} imgs - Array of large product images,along with related information\n * @param {jQuery} $productContainer - DOM element for a given product\n */\nfunction createCarousel(imgs, $productContainer) {\n var carousel = $productContainer.find('.carousel');\n $(carousel).carousel('dispose');\n var carouselId = $(carousel).attr('id');\n $(carousel).empty().append('
      ' + $(carousel).data('prev') + '' + $(carousel).data('next') + '');\n for (var i = 0; i < imgs.length; i++) {\n $('
      \"'
      ').appendTo($(carousel).find('.carousel-inner'));\n $('
    1. ').appendTo($(carousel).find('.carousel-indicators'));\n }\n $($(carousel).find('.carousel-item')).first().addClass('active');\n $($(carousel).find('.carousel-indicators > li')).first().addClass('active');\n if (imgs.length === 1) {\n $($(carousel).find('.carousel-indicators, a[class^=\"carousel-control-\"]')).detach();\n }\n $(carousel).carousel();\n $($(carousel).find('.carousel-indicators')).attr('aria-hidden', true);\n}\n\n/**\n * Parses JSON from Ajax call made whenever an attribute value is [de]selected\n * @param {Object} response - response from Ajax call\n * @param {Object} response.product - Product object\n * @param {string} response.product.id - Product ID\n * @param {Object[]} response.product.variationAttributes - Product attributes\n * @param {Object[]} response.product.images - Product images\n * @param {boolean} response.product.hasRequiredAttrsSelected - Flag as to whether all required\n * attributes have been selected. Used partially to\n * determine whether the Add to Cart button can be enabled\n * @param {jQuery} $productContainer - DOM element for a given product.\n */\nfunction handleVariantResponse(response, $productContainer) {\n var isChoiceOfBonusProducts =\n $productContainer.parents('.choose-bonus-product-dialog').length > 0;\n var isVaraint;\n if (response.product.variationAttributes) {\n updateAttrs(response.product.variationAttributes, $productContainer, response.resources);\n isVaraint = response.product.productType === 'variant';\n if (isChoiceOfBonusProducts && isVaraint) {\n $productContainer.parent('.bonus-product-item')\n .data('pid', response.product.id);\n\n $productContainer.parent('.bonus-product-item')\n .data('ready-to-order', response.product.readyToOrder);\n }\n }\n\n // Update primary images\n var primaryImageUrls = response.product.images.large;\n createCarousel(primaryImageUrls, $productContainer);\n\n // Update pricing\n if (!isChoiceOfBonusProducts) {\n var $priceSelector = $('.prices .price', $productContainer).length\n ? $('.prices .price', $productContainer)\n : $('.prices .price');\n $priceSelector.replaceWith(response.product.price.html);\n }\n\n // Update promotions\n $productContainer.find('.promotions').empty().html(response.product.promotionsHtml);\n\n updateAvailability(response, $productContainer);\n\n if (isChoiceOfBonusProducts) {\n var $selectButton = $productContainer.find('.select-bonus-product');\n $selectButton.trigger('bonusproduct:updateSelectButton', {\n product: response.product, $productContainer: $productContainer\n });\n } else {\n // Enable \"Add to Cart\" button if all required attributes have been selected\n $('button.add-to-cart, button.add-to-cart-global, button.update-cart-product-global').trigger('product:updateAddToCart', {\n product: response.product, $productContainer: $productContainer\n }).trigger('product:statusUpdate', response.product);\n }\n\n // Update attributes\n $productContainer.find('.main-attributes').empty()\n .html(getAttributesHtml(response.product.attributes));\n}\n\n/**\n * @typespec UpdatedQuantity\n * @type Object\n * @property {boolean} selected - Whether the quantity has been selected\n * @property {string} value - The number of products to purchase\n * @property {string} url - Compiled URL that specifies variation attributes, product ID, options,\n * etc.\n */\n\n/**\n * Updates the quantity DOM elements post Ajax call\n * @param {UpdatedQuantity[]} quantities -\n * @param {jQuery} $productContainer - DOM container for a given product\n */\nfunction updateQuantities(quantities, $productContainer) {\n if (!($productContainer.parent('.bonus-product-item').length > 0)) {\n var optionsHtml = quantities.map(function (quantity) {\n var selected = quantity.selected ? ' selected ' : '';\n return '';\n }).join('');\n getQuantitySelector($productContainer).empty().html(optionsHtml);\n }\n}\n\n/**\n * Retrieves url to use when adding a product to the cart\n *\n * @return {string} - The provided URL to use when adding a product to the cart\n */\nfunction getAddToCartUrl() {\n return $('.add-to-cart-url').val();\n}\n\n/**\n * Parses the html for a modal window\n * @param {string} html - representing the body and footer of the modal window\n *\n * @return {Object} - Object with properties body and footer.\n */\nfunction parseHtml(html) {\n var $html = $('
      ').append($.parseHTML(html));\n\n var body = $html.find('.choice-of-bonus-product');\n var footer = $html.find('.modal-footer').children();\n\n return { body: body, footer: footer };\n}\n\n/**\n * Retrieves url to use when adding a product to the cart\n *\n * @param {Object} data - data object used to fill in dynamic portions of the html\n */\nfunction chooseBonusProducts(data) {\n $('.modal-body').spinner().start();\n\n if ($('#chooseBonusProductModal').length !== 0) {\n $('#chooseBonusProductModal').remove();\n }\n var bonusUrl;\n if (data.bonusChoiceRuleBased) {\n bonusUrl = data.showProductsUrlRuleBased;\n } else {\n bonusUrl = data.showProductsUrlListBased;\n }\n\n var htmlString = ''\n + '
      '\n + ''\n + '
      '\n + ''\n + '
      '\n + '
      '\n + ' ' + data.labels.selectprods + ''\n + ' '\n + '
      '\n + '
      '\n + '
      '\n + '
      '\n + '
      '\n + '
      ';\n $('body').append(htmlString);\n $('.modal-body').spinner().start();\n\n $.ajax({\n url: bonusUrl,\n method: 'GET',\n dataType: 'json',\n success: function (response) {\n var parsedHtml = parseHtml(response.renderedTemplate);\n $('#chooseBonusProductModal .modal-body').empty();\n $('#chooseBonusProductModal .enter-message').text(response.enterDialogMessage);\n $('#chooseBonusProductModal .modal-header .close .sr-only').text(response.closeButtonText);\n $('#chooseBonusProductModal .modal-body').html(parsedHtml.body);\n $('#chooseBonusProductModal .modal-footer').html(parsedHtml.footer);\n $('#chooseBonusProductModal').modal('show');\n $.spinner().stop();\n },\n error: function () {\n $.spinner().stop();\n }\n });\n}\n\n/**\n * Updates the Mini-Cart quantity value after the customer has pressed the \"Add to Cart\" button\n * @param {string} response - ajax response from clicking the add to cart button\n */\nfunction handlePostCartAdd(response) {\n $('.minicart').trigger('count:update', response);\n var messageType = response.error ? 'alert-danger' : 'alert-success';\n // show add to cart toast\n if (response.newBonusDiscountLineItem\n && Object.keys(response.newBonusDiscountLineItem).length !== 0) {\n chooseBonusProducts(response.newBonusDiscountLineItem);\n } else {\n if ($('.add-to-cart-messages').length === 0) {\n $('body').append(\n '
      '\n );\n }\n\n $('.add-to-cart-messages').append(\n '
      '\n + response.message\n + '
      '\n );\n\n setTimeout(function () {\n $('.add-to-basket-alert').remove();\n }, 5000);\n }\n}\n\n/**\n * Retrieves the bundle product item ID's for the Controller to replace bundle master product\n * items with their selected variants\n *\n * @return {string[]} - List of selected bundle product item ID's\n */\nfunction getChildProducts() {\n var childProducts = [];\n $('.bundle-item').each(function () {\n childProducts.push({\n pid: $(this).find('.product-id').text(),\n quantity: parseInt($(this).find('label.quantity').data('quantity'), 10)\n });\n });\n\n return childProducts.length ? JSON.stringify(childProducts) : [];\n}\n\n/**\n * Retrieve product options\n *\n * @param {jQuery} $productContainer - DOM element for current product\n * @return {string} - Product options and their selected values\n */\nfunction getOptions($productContainer) {\n var options = $productContainer\n .find('.product-option')\n .map(function () {\n var $elOption = $(this).find('.options-select');\n var urlValue = $elOption.val();\n var selectedValueId = $elOption.find('option[value=\"' + urlValue + '\"]')\n .data('value-id');\n return {\n optionId: $(this).data('option-id'),\n selectedValueId: selectedValueId\n };\n }).toArray();\n\n return JSON.stringify(options);\n}\n\n/**\n * Makes a call to the server to report the event of adding an item to the cart\n *\n * @param {string | boolean} url - a string representing the end point to hit so that the event can be recorded, or false\n */\nfunction miniCartReportingUrl(url) {\n if (url) {\n $.ajax({\n url: url,\n method: 'GET',\n success: function () {\n // reporting urls hit on the server\n },\n error: function () {\n // no reporting urls hit on the server\n }\n });\n }\n}\n\nfunction attributeSelect(selectedValueUrl, $productContainer, option) {\n var redirect = $(option).data('isbuyboxredirect');\n\n var qtyBuybox = Number($('#qtyBuyBox').val());\n\n if(qtyBuybox){\n selectedValueUrl = selectedValueUrl + '&qtyBuybox='+qtyBuybox;\n }\n\n if (redirect === true) {\n window.location.href = selectedValueUrl;\n } else {\n if (selectedValueUrl) {\n $('body').trigger('product:beforeAttributeSelect',\n { url: selectedValueUrl, container: $productContainer });\n\n $.ajax({\n url: selectedValueUrl,\n method: 'GET',\n success: function (data) {\n handleVariantResponse(data, $productContainer);\n updateOptions(data.product.optionsHtml, $productContainer);\n updateQuantities(data.product.quantities, $productContainer);\n $('body').trigger('product:afterAttributeSelect',\n { data: data, container: $productContainer });\n $.spinner().stop();\n },\n error: function () {\n $.spinner().stop();\n }\n });\n }\n }\n}\n\nmodule.exports = {\n selectAttribute: function () {\n $(document).off('change', 'select[class*=\"select-\"], .options-select').on('change', 'select[class*=\"select-\"], .options-select', function (e) {\n e.preventDefault();\n\n var $productContainer = $(this).closest('.set-item');\n if (!$productContainer.length) {\n $productContainer = $(this).closest('.product-detail');\n }\n\n var option = $(e.currentTarget).find(':selected');\n\n attributeSelect(e.currentTarget.value, $productContainer, option);\n });\n }\n}","'use strict';\n\n//var buyBox = require('plugin_buybox/product/detail');\nvar base = require('base/product/base');\nvar baseProductDetail = require('base/product/detail'),\n Promise = require('promise'),\n _ = require('lodash'),\n util = require('grocery/util'),\n page = require('grocery/page'),\n dialog = require('grocery/dialog'),\n minicart = require('grocery/minicart'),\n progress = require('grocery/progress'),\n carousel = require('grocery/carousel'),\n ajax = require('grocery/ajax'),\n //productStoreInventory = require('../../storeinventory/product'),\n //tooltip = require('../../tooltip'),\n //availability = require('./availability'),\n //image = require('./image'),\n //productNav = require('./productNav'),\n //productSet = require('./productSet'),\n //variant = require('./variant'),\n favouritewidget = require('grocery/pages/favouritewidget'),\n promos = require('grocery/promos');\n\n\nfunction getCookie(name) {\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${name}=`);\n if (parts.length === 2) return parts.pop().split(';').shift();\n}\n\n/**\n * @description Make the AJAX request to add an item to cart\n * @param {Element} form The form element that contains the item quantity and ID data\n * @returns {Promise}\n */\nfunction addItemToCart(form) {\n var $form = $(form),\n $qty = $form.find('input[name=\"quantity\"], select[name=\"quantity\"]');\n\n if ($qty.length === 0 || isNaN($qty.val()) || parseInt($qty.val(), 10) === 0 || Number($qty.val()) < 0) {\n $qty.val('1');\n }\n\n return Promise.resolve($.ajax({\n type: 'POST',\n url: util.ajaxUrl(Urls.addProduct),\n data: $form.serialize()\n })).then(function (response) {\n // handle error in the response\n if (response.error) {\n throw new Error(response.error);\n } else {\n return response;\n }\n });\n}\n\n/**\n * @description Handler to handle the add to cart event\n */\nfunction addToCart (e) {\n e.preventDefault();\n if (!getCookie('dw_shippostalcode')) {\n $('#popUpCep').slideDown();\n $('#popUpCep').modal('show'); //MOSTRA O MODAL DE CEP\n } else {\n var $form = $(this).closest('form');\n var pid = $(this).data('pid');\n var qty = 1; // quantity selection is not editable by the user until after 1 product is added, so start with 1.\n var productURL = util.ajaxUrl(Urls.getProductUrl + '?pid=' + pid);\n\n const jqXHR = $.ajax({\n type: 'POST',\n url: util.ajaxUrl(Urls.addProduct),\n data: $form.serialize()\n });\n\n jqXHR.done(function () {\n var $uuid = $form.find('input[name=\"uuid\"]');\n if ($uuid.length > 0 && $uuid.val().length > 0) {\n page.refresh();\n } else {\n // do not close quickview if adding individual item that is part of product set\n // @TODO should notify the user some other way that the add action has completed successfully\n if (!$(this).hasClass('sub-product-item')) {\n dialog.close();\n }\n // Update pdpAddToCartForm\n $.ajax({\n url: productURL,\n type: 'GET',\n dataType: 'html',\n success: function(data) {\n var newPdpAddToCartForm = $(data).children('#pdpMain').find('#pdpAddToCartForm');\n $('#pdpAddToCartForm').html(newPdpAddToCartForm.html());\n }\n });\n // Update the miniCart\n $.ajax({\n url: Urls.miniCart,\n type: 'GET',\n dataType: 'html',\n success: function(data) {\n minicart.show(data, !$('.mini-cart-empty').length);\n }\n });\n $(document).trigger({\n type: 'add-to-cart-pdp',\n pid: pid,\n quantity: qty,\n source: 'pdp',\n uuid: $uuid.val()\n });\n $(document).trigger('toastNotify', 'added');\n }\n });\n }\n}\n\n\nfunction addAllToCart(e) {\n e.preventDefault();\n var $productForms = $('#product-set-list').find('form').toArray();\n // We're popping the last array item (product) off so we can re-call addItemToCart() later with this alone\n // so that we're sure to have all the products in the last call\n var lastProduct = $productForms.pop();\n Promise\n .all(_.map($productForms, addItemToCart))\n .then(function () {\n dialog.close();\n\n // We have to call addItemToCart again with the last product so that we get a response with all the products in it\n addItemToCart(lastProduct).then(function (responses) {\n minicart.show(responses, !$('.mini-cart-empty').length);\n });\n });\n}\n\nfunction openAccordian() {\n if ($('.pdp-howto').length === 0 && $('.pdp-awards').length === 0) {\n $('.list-group .list-group-item:not(.d-md-none):first h4').toggleClass('collapsed').attr('aria-expanded', 'true');\n $('.list-group .list-group-item:not(.d-md-none):first .collapse').toggleClass('show');\n }\n}\n\n/**\n * @description Initialize event handlers on product detail page\n */\nfunction initializeEvents () {\n var $pdpMain = $('#pdpMain');\n\n // Add to Wishlist and Add to Gift Registry links behaviors\n $pdpMain.on('click', '[data-action=\"gift-registry\"]', function () {\n var data = util.getQueryStringParams($('.pdpForm').serialize());\n if (data.cartAction) {\n delete data.cartAction;\n }\n var url = util.appendParamsToUrl(this.href, data);\n this.setAttribute('href', url);\n });\n\n // product options\n $pdpMain.on('change', '.product-options select', function () {\n var salesPrice = $pdpMain.find('.product-add-to-cart .price-sales');\n var selectedItem = $(this).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', function (e) {\n e.preventDefault();\n });\n\n $('.tiles-carousel').slick({\n config: carousel.landing\n });\n\n // Add to Cart click handlers\n $(document).off('click', 'button.add-to-cart, button.add-to-cart-global');\n $(document).on('click', '.product-detail .add-to-cart', addToCart);\n $('#add-all-to-cart').on('click', addAllToCart);\n\n\n if (SitePreferences.STORE_PICKUP) {\n //productStoreInventory.init();\n }\n\n /**\n * Listen for the add-to-cart-pdp event and update minicart & PDP with the needed PLI data\n * @returns\n */\n $(document).on('add-to-cart-pdp', function (e) {\n\n const productLineItems = window.ProductLineItems;\n var suppressMinicart = false;\n\n for (var i in productLineItems) {\n const productLineItem = productLineItems[i];\n const promos = productLineItem.promoInfo;\n\n for (var j in promos) {\n const $productOffer = $('.product-offer[data-promo=\"' + promos[j].ID + '\"]');\n\n if ($productOffer.length) {\n $('.product-offers').attr('data-item-uuid', productLineItem.UUID);\n }\n }\n }\n\n promos.addPromoMessages();\n\n // TODO: Re-initialize the product ratings when implemented\n\n if (!suppressMinicart) {\n $(document).trigger({\n type: 'basketupdate',\n pid: e.pid,\n quantity: e.quantity,\n source: 'pdp',\n uuid: e.uuid\n });\n }\n });\n\n $(document).on('basketupdate.pdp', function (e) {\n var $content = $('#pdpAddToCartForm');\n if (window.location.href.indexOf('?pid=' + e.pid) >= 0) {\n if (isNaN(e.quantity) || e.quantity === 0 || (e.quantity === 1 && !$content.find('.quantity-container').length)) {\n progress.show($content);\n var params = {\n Quantity: isNaN(e.quantity) ? '1' : e.quantity,\n pid: e.pid,\n format: 'ajax'\n };\n if (e.quantity === 0) {\n // If going back to 0 just reset the whole PDP\n $.ajax({\n url: util.ajaxUrl(Urls.getProductUrl + '?pid=' + e.pid),\n type: 'GET',\n dataType: 'html',\n success: function(data) {\n var newPdp = $(data).children('#pdpMain');\n $('#pdpMain').html(newPdp.html());\n }\n });\n } else {\n const jqXHR = ajax.load({\n url: util.appendParamsToUrl(window.Urls.pdpRefreshAddToBagQuantity, params),\n target: $content\n });\n\n jqXHR.always(function () {\n promos.addPromoMessages();\n progress.hide();\n });\n }\n }\n }\n });\n \n $('body').on('change', '.substituion-option', function (e) {\n e.preventDefault();\n var substituionOption = $('[id$=substitution-option] option:selected').val();\n $('input[name$=substitution]').val(substituionOption);\n });\n\n $(document).on('toastNotify', function(event, type){\n console.log(type);\n \n if(type === 'removed'){\n $('.toastMessageContainer i').removeClass('fa-check-circle').addClass('fa-times-circle');\n $('.toastMessage-text').text($('.toastMessage').data('messageRemoved'));\n } else if (type === 'added'){\n $('.toastMessageContainer i').removeClass('fa-times-circle').addClass('fa-check-circle');\n $('.toastMessage-text').text($('.toastMessage').data('messageAdded'));\n }\n \n $('.toastMessage').addClass('toastVisible');\n setTimeout(function(){\n $('.toastMessage').removeClass('toastVisible');\n }, 2000);\n });\n}\n\n\nfunction miniCartReportingUrl(url) {\n if (url) {\n $.ajax({\n url: url,\n method: 'GET',\n success: function () {\n // reporting urls hit on the server\n },\n error: function () {\n // no reporting urls hit on the server\n }\n });\n }\n}\n\n// TO DO put this function in a util to be used by other scripts\nfunction getQueryParams(qs) {\n qs = qs.split('+').join(' ');\n\n var params = {},\n tokens,\n re = /[?&]?([^=]+)=([^&]*)/g;\n\n while (tokens = re.exec(qs)) {\n params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);\n }\n\n return params;\n}\n\nmodule.exports = $.extend({}, baseProductDetail, {\n init: function () {\n openAccordian();\n favouritewidget.initAddToFavourite();\n promos.addPromoMessages();\n initializeEvents();\n },\n availability: baseProductDetail.availability,\n // addToCartmarketplace: buyBox.addToCartmarketplace,\n // updateAttributesAndDetails: buyBox.updateAttributesAndDetails,\n // showSpinner: buyBox.showSpinner,\n updateAttribute: function () {\n $('body').off('product:afterAttributeSelect').on('product:afterAttributeSelect', function (e, response) {\n if ($('.product-detail>.bundle-items').length) {\n response.container.data('pid', response.data.product.id);\n response.container.find('.product-id').text(response.data.product.id);\n } else if ($('.product-set-detail').eq(0)) {\n response.container.attr('data-pid', response.data.product.id);\n response.container.find(\"[data-pid]\").attr('data-pid', response.data.product.id);\n response.container.find(\"#pid\").attr('value', response.data.product.id);\n response.container.find(\"#add-to-cart\").attr('data-pid', response.data.product.id);\n response.container.find('.product-id').text(response.data.product.id);\n } else {\n $('.product-id').text(response.data.product.id);\n $('.product-detail:not(\".bundle-item\")').data('pid', response.data.product.id);\n }\n response.container.find('.sellers').empty().html(response.data.product.marketplaceHtml);\n response.container.find('.soldBy').empty().html(response.data.product.soldByHtml);\n });\n },\n // updateAddToCart: buyBox.updateAddToCart,\n // updateAvailability: buyBox.updateAvailability,\n // sizeChart: buyBox.sizeChart,\n // copyProductLink: buyBox.copyProductLink,\n // preSelectVariant: buyBox.preSelectVariant,\n focusChooseBonusProductModal: base.focusChooseBonusProductModal(),\n // viewShippingCosts: buyBox.viewShippingCosts,\n // changeSortOrder: buyBox.changeSortOrder,\n // scrollToBuyBox: buyBox.scrollToBuyBox\n});\n","'use strict';\n\nvar processInclude = require('base/util');\n\n$(document).ready(function () {\n processInclude(require('./product/base'));\n processInclude(require('./product/detail'));\n});\n","'use strict';\n\nvar progress = require('./progress'),\n util = require('./util');\n\nvar currentRequests = [];\n\n/**\n * @function\n * @description Ajax request to get json response\n * @param {Boolean} async Asynchronous or not\n * @param {String} url URI for the request\n * @param {Object} data Name/Value pair data request\n * @param {Function} callback Callback function to be called\n */\nvar getJson = function (options) {\n options.url = util.toAbsoluteUrl(options.url);\n // return if no url exists or url matches a current request\n if (!options.url || currentRequests[options.url]) {\n return;\n }\n\n currentRequests[options.url] = true;\n\n // make the server call\n return $.ajax({\n dataType: 'json',\n url: options.url,\n async: (typeof options.async === 'undefined' || options.async === null) ? true : options.async,\n data: options.data || {}\n })\n // success\n .done(function (response) {\n if (options.callback) {\n options.callback(response);\n }\n })\n // failed\n .fail(function (xhr, textStatus) {\n if (textStatus === 'parsererror') {\n window.alert(Resources.BAD_RESPONSE);\n }\n if (typeof options.callback === 'function') {\n options.callback(null);\n }\n })\n // executed on success or fail\n .always(function () {\n // remove current request from hash\n if (currentRequests[options.url]) {\n delete currentRequests[options.url];\n }\n });\n};\n/**\n * @function\n * @description ajax request to load html response in a given container\n * @param {String} url URI for the request\n * @param {Object} data Name/Value pair data request\n * @param {Function} callback Callback function to be called\n * @param {Object} target Selector or element that will receive content\n */\nvar load = function (options) {\n options.url = util.toAbsoluteUrl(options.url);\n // return if no url exists or url matches a current request\n if (!options.url || currentRequests[options.url]) {\n return;\n }\n\n currentRequests[options.url] = true;\n\n // make the server call\n return $.ajax({\n dataType: 'html',\n url: util.appendParamToURL(options.url, 'format', 'ajax'),\n data: options.data,\n xhrFields: {\n withCredentials: true\n }\n })\n .done(function (response) {\n // success\n if (options.target) {\n $(options.target).empty().html(response);\n }\n if (typeof options.callback === 'function') {\n options.callback(response);\n }\n })\n .fail(function (xhr, textStatus) {\n // failed\n if (textStatus === 'parsererror') {\n window.alert(Resources.BAD_RESPONSE);\n }\n if (typeof options.callback === 'function') {\n options.callback(null, textStatus);\n }\n })\n .always(function () {\n progress.hide();\n // remove current request from hash\n if (currentRequests[options.url]) {\n delete currentRequests[options.url];\n }\n });\n};\n\nexports.getJson = getJson;\nexports.load = load;\n","'use strict';\n\nvar dialog = null, // require('./dialog'),\n page = require('./page'),\n util = require('./util'),\n favouritewidget = require('./pages/favouritewidget');\n\nvar selectedList = [];\nvar selectedListState = [];\nvar maxItems = 1;\nvar bliUUID = '';\n\n/**\n * @private\n * @function\n * description Gets a list of bonus products related to a promoted product\n */\nfunction getBonusProducts() {\n var bonusproducts = [];\n\n var i, len;\n for (i = 0, len = selectedList.length; i < len; i++) {\n var p = {\n pid: selectedList[i].pid,\n qty: selectedList[i].qty,\n options: {}\n };\n var a, alen, bp = selectedList[i];\n if (bp.options) {\n for (a = 0, alen = bp.options.length; a < alen; a++) {\n var opt = bp.options[a];\n p.options = {optionName:opt.name, optionValue:opt.value};\n }\n }\n bonusproducts.push({product:p});\n }\n return {bonusproducts: bonusproducts};\n}\n\nvar selectedItemTemplate = function (data) {\n var attributes = '';\n for (var attrID in data.attributes) {\n var attr = data.attributes[attrID];\n attributes += '
    2. \\n';\n attributes += '' + attr.displayName + ': ';\n attributes += '' + attr.displayValue + '\\n';\n attributes += '
    3. ';\n }\n attributes += '
    4. \\n';\n attributes += '' + data.qty + '';\n return [\n '
    5. ',\n '',\n '
      ' + data.name + '
      ',\n '