1require.config({"config": { 2 "jsbuild":{"Goyard_Catalog/js/customer_logged_status.js":"/**\n * Copyright Goyard Orkester\n * @author Orkester\n * @copyright Goyard\n */\ndefine([\n\t'Magento_Customer/js/customer-data'\n], function (customerData) {\n\t'use strict';\n\n\t/**\n\t * Synchronous read of customer data, may be empty not loaded yet\n\t */\n\tfunction getCustomer() {\n\t\treturn customerData.get('customer')();\n\t}\n\n\t/**\n\t * Wait for the customer data to be loaded\n\t */\n\tfunction getIsCustomerLoggedIn() {\n\t\treturn new Promise(function (resolve) {\n\t\t\tlet customer = customerData.get('customer');\n\n\t\t\tif (customer().firstname) {\n\t\t\t\tresolve(customer());\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet subscription = customer.subscribe(function () {\n\t\t\t\tsubscription.dispose();\n\t\t\t\tresolve(customer());\n\t\t\t});\n\n\t\t\tsetTimeout(function () {\n\t\t\t\tsubscription.dispose();\n\t\t\t\tresolve(customer());\n\t\t\t}, 1000);\n\t\t});\n\t}\n\n\treturn {\n\t\tgetCustomer: getCustomer,\n\t\tgetIsCustomerLoggedIn: getIsCustomerLoggedIn\n\t};\n});\n","Goyard_Catalog/js/swatch-renderer-mixin.js":"define(\n ['jquery',\n 'underscore',\n 'mage/template',\n 'mage/smart-keyboard-handler',\n 'mage/translate',\n 'priceUtils',\n 'Magento_Ui/js/modal/modal',\n 'mage/url',\n 'Goyard_Wishlist/js/front-injector',\n 'Goyard_Wishlist/js/check-customer-wishlist',\n 'Magento_Customer/js/customer-data',\n 'Goyard_Catalog/js/category/change-carousel',\n 'slick',\n 'jquery-ui-modules/widget',\n 'jquery/jquery.parsequery',\n 'mage/validation/validation',\n 'access_key',\n 'Goyard_Catalog/js/product_page/handler-swatchcolor',\n ],\n function (\n $,\n _,\n mageTemplate,\n keyboardHandler,\n $t,\n priceUtils,\n modal,\n urlBuilder,\n frontInjector,\n customerWishlist,\n customerData,\n changeCarousel\n ) {\n 'use strict';\n\n return function (SwatchRenderer) {\n $.widget('mage.SwatchRenderer', $['mage']['SwatchRenderer'], {\n\n _init: function () {\n //Reinit UrlBuilder BASE URL\n this.initUrls();\n\n // Don't render the same set of swatches twice\n if ($(this.element).attr('data-rendered')) {\n return;\n }\n\n $(this.element).attr('data-rendered', true);\n\n if (_.isEmpty(this.options.jsonConfig.images)) {\n this.options.useAjax = true;\n // creates debounced variant of _LoadProductMedia()\n // to use it in events handlers instead of _LoadProductMedia()\n this._debouncedLoadProductMedia = _.debounce(this._LoadProductMedia.bind(this), 500);\n }\n\n this.options.tierPriceTemplate = $(this.options.tierPriceTemplateSelector).html();\n\n if (this.options.jsonConfig !== '' && this.options.jsonSwatchConfig !== '') {\n // store unsorted attributes\n this.options.jsonConfig.mappedAttributes = _.clone(this.options.jsonConfig.attributes);\n this._sortAttributes();\n this._RenderControls();\n this._setPreSelectedGallery();\n $(this.element).trigger('swatch.initialized', { swatchThis: this });\n }\n },\n\n /**\n *\n * @param {*} event\n */\n setupFocus(event) {\n const $wrapper = $(event.currentTarget);\n const activeDescendantId = $wrapper.attr('aria-activedescendant');\n if (activeDescendantId) {\n $wrapper.find('.swatch-option').removeClass('borderBlue').removeAttr('tabindex');\n\n if (event.type === 'focus') {\n const selectedItem = $wrapper.find('.swatch-option#' + activeDescendantId);\n selectedItem.addClass('borderBlue');\n }\n else {\n $wrapper.find('.swatch-option').removeClass('borderBlue');\n }\n }\n },\n\n /**\n * Manage Product swatch option selection using left and right arrow\n * @param {*} event\n * @returns\n */\n throughSwatchOptions(event) {\n const $wrapper = $(event.currentTarget);\n const allOptions = $wrapper.find('[role=\"option\"]');\n const activeDescendantId = $wrapper.attr('aria-activedescendant');\n const currentItem = activeDescendantId ? $wrapper.find('#' + activeDescendantId) : allOptions.eq(0);\n const currentOptionIndex = allOptions.index(currentItem);\n let nextItem = currentItem;\n\n if (!currentItem.length) {\n return;\n }\n\n if (event.keyCode === 37) {\n if (currentOptionIndex > -1 && currentOptionIndex > 0) {\n nextItem = allOptions.eq(currentOptionIndex - 1);\n }\n nextItem.trigger('click');\n nextItem.toggleClass('borderBlue');\n\n }\n\n if (event.keyCode === 39) {\n if (currentOptionIndex > -1 && currentOptionIndex < allOptions.length - 1) {\n nextItem = allOptions.eq(currentOptionIndex + 1);\n }\n nextItem.trigger('click');\n nextItem.toggleClass('borderBlue');\n }\n },\n\n _RenderControls: function () {\n var $widget = this,\n container = this.element,\n classes = this.options.classes,\
2n chooseText = this.options.jsonConfig.chooseText,\n showTooltip = this.options.showTooltip;\n $widget.optionsMap = {};\n\n $.each(this.options.jsonConfig.attributes, function () {\n var item = this,\n controlLabelId = 'option-label-' + item.code + '-' + item.id,\n options = $widget._RenderSwatchOptions(item, controlLabelId),\n select = $widget._RenderSwatchSelect(item, chooseText),\n input = $widget._RenderFormInput(item),\n listLabel = '',\n label = '';\n\n // Show only swatch controls\n if ($widget.options.onlySwatches && !$widget.options.jsonSwatchConfig.hasOwnProperty(item.id)) {\n return;\n }\n\n if ($widget.options.enableControlLabel) {\n label +=\n '<p id=\"' + controlLabelId + '\" class=\"' + classes.attributeLabelClass + '\">' +\n $('<i></i>').text(item.label).html() +\n '<span class=\"' + classes.attributeSelectedOptionLabelClass + '\"></span>' +\n '</p>';\n\n }\n\n if ($widget.inProductList) {\n $widget.productForm.append(input);\n input = '';\n listLabel = 'aria-label=\"' + $('<i></i>').text(item.label).html() + '\"';\n } else {\n listLabel = 'aria-labelledby=\"' + controlLabelId + '\"';\n }\n\n // Create new control\n container.append(\n '<div class=\"' + classes.attributeClass + ' ' + item.code + '\" ' +\n 'data-attribute-code=\"' + item.code + '\" ' +\n 'data-attribute-id=\"' + item.id + '\">' +\n label +\n '<ul aria-activedescendant=\"\" ' +\n 'tabindex=\"0\" ' +\n 'aria-invalid=\"false\" ' +\n 'aria-required=\"true\" ' +\n 'aria-label=\"' + $t('See all colours') + '\" ' +\n 'role=\"listbox\" ' + listLabel +\n 'class=\"' + classes.attributeOptionsWrapper + ' clearfix\">' +\n options + select +\n '</ul>' + input +\n '</div>'\n );\n\n $widget.optionsMap[item.id] = {};\n\n // Aggregate options array to hash (key => value)\n $.each(item.options, function () {\n if (this.products.length > 0) {\n $widget.optionsMap[item.id][this.id] = {\n price: parseInt(\n $widget.options.jsonConfig.optionPrices[this.products[0]].finalPrice.amount,\n 10\n ),\n products: this.products\n };\n }\n });\n });\n\n if (showTooltip === 1) {\n // Connect Tooltip\n container\n .find('[data-option-type=\"1\"], [data-option-type=\"2\"],' +\n ' [data-option-type=\"0\"], [data-option-type=\"3\"]')\n .SwatchRendererTooltip();\n }\n\n // Hide all elements below more button\n $('.' + classes.moreButton).nextAll().hide();\n\n // Handle events like click or change\n $widget._EventListener();\n\n // Rewind options\n $widget._Rewind(container);\n\n //Emulate click on all swatches from Request\n $widget._EmulateSelected($.parseQuery());\n $widget._EmulateSelected($widget._getSelectedAttributes());\n },\n initUrls: function () {\n urlBuilder.setBaseUrl(window.BASE_URL);\n },\n\n _OnClick: function ($this, $widget) {\n // check if the element in swatch-color is already selected and return nothing\n if ($this[0].classList.contains('selected')) {\n return;\n }\n this._super($this, $widget);\n\n if (!$this.hasClass('selected')) {\n $this.attr('aria-selected', false);\n }\n\n if (this.isProductViewPage()) {\n const swatchOptionClicked = new CustomEvent('swatchOptionClickedOnProductPage', {\n detail: {\n element: $this\n }\n });\n document.dispatchEvent(swatchOptionClicked);\n }\n\n if (!this.isProductViewPage()) {\n const swatchOptionClickedOnListingPageOrResultPage = new CustomEvent('swatchOptionClickedOnListingPageOrResultPage', {\n detail: {\n element: $this\n }\n })\n document.dispatchEvent(swatchOptionClickedOnListingPageOrResultPage);\n }\n\n // Globale Fixed Prices\n /* check setting add_data_fp_attribute_automatically from module configuration */\n if (window.addD
2ataFpAutomayically !== undefined || window.addDataFpAutomayically === '1') {\n var priceBox = $widget.element.parents($widget.options.selectorProduct)\n var productId = $widget.getProduct();\n var baseSalePrice = $(priceBox).find('.product-fixed-price .price').first().text();\n var baseRegularPrice = $(priceBox).find('.product-fixed-price .price').last().text();\n if (baseSalePrice === baseRegularPrice) {\n baseRegularPrice = null;\n }\n $.get('/international-ge/ProductSwatch/product/?productId=' + productId).done(function (data) {\n if ($(priceBox).find('.product-fixed-price').length != 0) {\n $(priceBox).find('.product-fixed-price .price').first().html(baseSalePrice);\n if (baseRegularPrice) {\n $(priceBox).find('.product-fixed-price .price').last().html(baseRegularPrice);\n }\n if (data.finalFixedPrices !== undefined) {\n $(priceBox).find('.product-fixed-price').first().attr('data-fp', data.finalFixedPrices);\n }\n if (baseRegularPrice && data.regularFixedPrices !== undefined) {\n $(priceBox).find('.product-fixed-price').last().attr('data-fp', data.regularFixedPrices);\n }\n $(priceBox).find('.product-fixed-price').attr('product-vat', data.vat);\n }\n }).fail(function () { });\n }\n },\n\n _OnChange: function ($this, $widget) {\n this._super($this, $widget);\n\n if (this.isProductViewPage()) {\n $widget.element.find('li[data-option-id]').removeClass('disabled').prop('disabled', false);\n $widget._Rebuild();\n }\n },\n\n /**\n * Use aria-selected instead of aria-checked\n *\n * @param {Object} $this\n * @param {Object} $wrapper\n * @private\n */\n _toggleCheckedAttributes: function ($this, $wrapper) {\n $wrapper.attr('aria-activedescendant', $this.attr('id'))\n .find('.' + this.options.classes.optionClass).attr('aria-selected', false);\n $this.attr('aria-selected', true);\n },\n\n /**\n * Render swatch options by part of config\n *\n * @param {Object} config\n * @param {String} controlId\n * @returns {String}\n * @private\n */\n _RenderSwatchOptions: function (config, controlId) {\n var optionConfig = this.options.jsonSwatchConfig[config.id],\n optionJsonConfig = this.options.jsonConfig,\n optionClass = this.options.classes.optionClass,\n sizeConfig = this.options.jsonSwatchImageSizeConfig,\n moreLimit = parseInt(this.options.numberToShow, 10),\n moreClass = this.options.classes.moreButton,\n moreText = this.options.moreButtonText,\n colorFilterConfig = this.options.colorFilterConfig,\n countAttributes = 0,\n html = '';\n if (!this.options.jsonSwatchConfig.hasOwnProperty(config.id)) {\n return '';\n }\n\n // Get Json data in <ol></ol> from list.phtml\n let colorDigitalFilterIds = $('.product-items').data('json');\n\n $.each(config.options, function (index) {\n var id,\n type,\n value,\n thumb,\n label,\n width,\n height,\n attr,\n swatchImageWidth,\n swatchImageHeight;\n\n if (!optionConfig.hasOwnProperty(this.id)) {\n return '';\n }\n // Add more button\n if (moreLimit === countAttributes++) {\
2n html += '<a href=\"#\" class=\"' + moreClass + '\"><span>' + moreText + '</span></a>';\n }\n\n id = this.id;\n type = parseInt(optionConfig[id].type, 10);\n value = optionConfig[id].hasOwnProperty('value') ?\n $('<i></i>').text(optionConfig[id].value).html() : '';\n thumb = optionConfig[id].hasOwnProperty('thumb') ? optionConfig[id].thumb : '';\n width = _.has(sizeConfig, 'swatchThumb') ? sizeConfig.swatchThumb.width : 110;\n height = _.has(sizeConfig, 'swatchThumb') ? sizeConfig.swatchThumb.height : 90;\n label = this.label ? $('<i></i>').text(this.label).html() : '';\n\n // Get the att_color_digital_filter option ID corresponding with att_couleur LABEL\n let colorDigitalId = '';\n if (colorDigitalFilterIds) {\n colorDigitalId = colorFilterConfig[id];\n }\n\n let indexColors = optionJsonConfig.index;\n var targetValue = id;\n var targetKey = null;\n\n // Get Current SKU\n for (var key in indexColors) {\n if (indexColors.hasOwnProperty(key)) {\n if (indexColors[key][630] === targetValue) {\n targetKey = key;\n break;\n }\n }\n }\n\n attr =\n ' id=\"' + controlId + '-item-' + id + '\"' +\n ' index=\"' + index + '\"' +\n ' aria-selected=\"false\"' +\n ' aria-describedby=\"' + controlId + '\"' +\n ' data-option-type=\"' + type + '\"' +\n ' data-option-id=\"' + id + '\"' +\n ' data-option-filter-id=\"' + colorDigitalId + '\"' +\n ' data-option-sku=\"' + optionJsonConfig.sku[targetKey] + '\"' +\n ' title=\"' + label + '\"' +\n ' data-option-label=\"' + label + '\"' +\n ' aria-label=\"' + label + '\"' +\n ' role=\"option\"' +\n ' data-thumb-width=\"' + width + '\"' +\n ' data-thumb-height=\"' + height + '\"' +\n 'data-testid=\"product-color-option-' + optionJsonConfig.sku[targetKey] + '-li\"';\n\n attr += thumb !== '' ? ' data-option-tooltip-thumb=\"' + thumb + '\"' : '';\n attr += value !== '' ? ' data-option-tooltip-value=\"' + value + '\"' : '';\n\n swatchImageWidth = _.has(sizeConfig, 'swatchImage') ? sizeConfig.swatchImage.width : 30;\n swatchImageHeight = _.has(sizeConfig, 'swatchImage') ? sizeConfig.swatchImage.height : 20;\n\n if (!this.hasOwnProperty('products') || this.products.length <= 0) {\n attr += ' data-option-empty=\"true\"';\n }\n\n if (type === 0) {\n // Text\n html += '<div class=\"' + optionClass + ' text\" ' + attr + '>' + (value ? value : label) +\n '</div>';\n } else if (type === 1) {\n // Color\n html += '<div class=\"' + optionClass + ' color\" ' + attr +\n ' style=\"background: ' + value +\n ' no-repeat center; background-size: initial;\">' + '' +\n '</div>';\n } else if (type === 2) {\n // Image\n html += '<li class=\"' + optionClass + ' image\" ' + attr +\n ' style=\"background: url(' + value + ') no-repeat center; background-size: initial;width:' +\n swatchImageWidth + 'px; height:' + swatchImageHeight + 'px\">' + '' +\n '</li>';\n } else if (type === 3) {\n // Clear\n html += '<div class=\"' + optionClass + '\" ' + attr + '></div>';\n } else {\n // Default\n html += '<div class=\"' + optionClass + '\" ' + attr + '>' + label + '</div>';\n }\n });\n\n return html;\n }
2,\n\n /**\n * Render select by part of config\n *\n * @param {Object} config\n * @param {String} chooseText\n * @returns {String}\n * @private\n */\n _RenderSwatchSelect: function (config, chooseText) {\n var html;\n\n if (this.options.jsonSwatchConfig.hasOwnProperty(config.id)) {\n return '';\n }\n\n html = '<select class=\"' + this.options.classes.selectClass + ' ' + config.code + '\">';\n\n $.each(config.options, function () {\n var label = this.label,\n attr = ' value=\"' + this.id + '\" data-option-id=\"' + this.id + '\"';\n\n if (!this.hasOwnProperty('products') || this.products.length <= 0) {\n attr += ' data-option-empty=\"true\"';\n }\n\n html += '<option ' + attr + '>' + label + '</option>';\n });\n\n html += '</select>';\n\n return html;\n },\n\n /**\n * Check if we are on a Product Detail Page (PDP)\n * @returns {boolean}\n */\n isProductViewPage: function () {\n return $('body').hasClass('catalog-product-view');\n },\n\n /**\n * Update total price\n * Goyard TE\n */\n _UpdatePrice: function () {\n var $widget = this,\n $product = $widget.element.parents($widget.options.selectorProduct),\n $productPrice = $product.find(this.options.selectorProductPrice),\n result = $widget._getNewPrices(),\n tierPriceHtml,\n isShow;\n\n var customerDataSection = customerData.get('customer');\n\n // Goyard TE : Check if $productPrice exists to avoid $productPrice.priceBox is not a function\n if ($productPrice.length > 0 && customerDataSection().firstname) {\n $productPrice.trigger(\n 'updatePrice',\n {\n 'prices': $widget._getPrices(result, $productPrice.priceBox('option').prices)\n }\n );\n }\n\n if (!customerDataSection().firstname) {\n $('.price').empty();\n }\n\n isShow = typeof result != 'undefined' && result.oldPrice.amount !== result.finalPrice.amount;\n\n // TEOP\n // Hide the price container if price = 0\n if (result.finalPrice.amount > 0 && customerDataSection().firstname) {\n $(\".product-info-main .product-info-price\").show();\n\n let selected_option = $('.swatch-attribute-options .swatch-option.selected').data('optionSku');\n // check if simple sku allow price display\n if (!this.options.priceDisplay[selected_option]) {\n $(\".product-info-main .product-info-price\").hide();\n }\n } else {\n $(\".product-info-main .product-info-price\").hide();\n }\n // --------\n $productPrice.find('span:first').toggleClass('special-price', isShow);\n\n $product.find(this.options.slyOldPriceSelector)[isShow ? 'show' : 'hide']();\n\n if (typeof result != 'undefined' && result.tierPrices && result.tierPrices.length) {\n if (this.options.tierPriceTemplate) {\n tierPriceHtml = mageTemplate(\n this.options.tierPriceTemplate,\n {\n 'tierPrices': result.tierPrices,\
2n '$t': $t,\n 'currencyFormat': this.options.jsonConfig.currencyFormat,\n 'priceUtils': priceUtils\n }\n );\n $(this.options.tierPriceBlockSelector).html(tierPriceHtml).show();\n }\n } else {\n $(this.options.tierPriceBlockSelector).hide();\n }\n\n $(this.options.normalPriceLabelSelector).hide();\n\n _.each($('.' + this.options.classes.attributeOptionsWrapper), function (attribute) {\n if ($(attribute).find('.' + this.options.classes.optionClass + '.selected').length === 0) {\n if ($(attribute).find('.' + this.options.classes.selectClass).length > 0) {\n _.each($(attribute).find('.' + this.options.classes.selectClass), function (dropdown) {\n if ($(dropdown).val() === '0') {\n $(this.options.normalPriceLabelSelector).show();\n }\n }.bind(this));\n } else {\n $(this.options.normalPriceLabelSelector).show();\n }\n }\n }.bind(this));\n },\n });\n return $['mage']['SwatchRenderer'];\n };\n });","Goyard_Catalog/js/price-box-mixin.js":"define(\n\t'Goyard_Catalog/js/price-box-mixin', [\n\t'jquery',\n\t'Magento_Catalog/js/price-utils',\n\t'underscore',\n\t'mage/template',\n\t'jquery-ui-modules/widget'\n], function ($, utils, _, mageTemplate) {\n\t'use strict';\n\n\tvar globalOptions = {\n\t\tproductId: null,\n\t\tpriceConfig: null,\n\t\tprices: {},\n\t\tpriceTemplate: '<span style=\"display:none\" data-storefront-globale=\"data-ge-price\" class=\"price\"><%- data.formatted %></span>'\n\t};\n\tvar widgetMixin = {\n\t\toptions: globalOptions,\n\n\t\treloadPrice: function () {\n\t\t\tvar priceFormat = (this.options.priceConfig && this.options.priceConfig.priceFormat) || {},\n\t\t\t\tpriceTemplate = mageTemplate(this.options.priceTemplate);\n\n\t\t\t_.each(this.cache.displayPrices, function (price, priceCode) {\n\t\t\t\tprice.final = _.reduce(price.adjustments, function (memo, amount) {\n\t\t\t\t\treturn memo + amount;\n\t\t\t\t}, price.amount);\n\n\t\t\t\tprice.formatted = utils.formatPriceLocale(price.final, priceFormat);\n\n\t\t\t\t$('[data-price-type=\"' + priceCode + '\"]', this.element).html(priceTemplate({\n\t\t\t\t\tdata: price\n\t\t\t\t}));\n\n\t\t\t\t$('[data-price-type=\"' + priceCode + '\"]', this.element).find('.price').trigger('update-globale-element');\n\n\t\t\t}, this);\n\t\t}\n\t};\n\n\treturn function (targetWidget) {\n\t\t// Example how to extend a widget by mixin object\n\t\t$.widget('mage.priceBox', targetWidget, widgetMixin); // the widget alias should be like for the target widget\n\n\t\treturn $.mage.priceBox; // the widget by parent alias should be returned\n\t};\n});","Goyard_Catalog/js/infinite-scroll.js":"require([\n \"jquery\",\n \"ias\",\n \"Goyard_Catalog/js/columns-catalog\",\n 'Goyard_Catalog/js/category/custom-price-loader',\n 'Goyard_Catalog/js/video-playback'\n], function ($, InfiniteAjaxScroll, columnsCatalog, customPriceLoader, videoPlayback) {\n $(document).ready(function () {\n\n const customPriceListingPageEvent = new CustomEvent(\"plp-page:load\", {});\n document.dispatchEvent(customPriceListingPageEvent);\n\n if (!$('.products.list.items.product-items').length) {\n return;\n }\n\n let ias = new InfiniteAjaxScroll(\".products.list.items.product-items\", {\n item: \".item.product.product-item,.item.category-moodboard\",\n next: \".toolbar-bottom .pages .item.current + .item a\",\n pagination: \".toolbar-products.toolbar-bottom\",\n loadOnScroll: false,\n prefill: false,\n spinner: '.loader.goyard-loader',\n trigger: \".btn-more-products\"\n });\n let $lastProductItem;\n $(\".btn-more-products\").on(\"click\", function () {\n //Accces replace focus on last element in listing search (click / spacebar / enter)\n $lastProductItem = $('ol.products.list.items.product-items > li:last-child');\n $lastProductItem.find('.product-item-link').focus();\n // --\n $(\".loader.goyard-loader\").removeAttr(\"style\");\n $('.more-products-wrapper').removeAttr(\"style\");\n\n });\n\n ias.on(\"appended\", function () {\n $(\".products.list.items.product-items\").trigger(\"contentUpdated\");\n $(\".loader.goyard-loader\").attr(\"style\", \"display: none;\");\n $('.more-products-wrapper').attr(\"style\", \"margin-bottom: 40px\");\n\n pageWidth = document.documentElement.clientWidth;\n columnsCatalog.injectGridArea();\n\n if (pageWidth < 769) {\n $('.product-item-details').click(function () {\n $(\".product-items\").find(\".color-label\").css(\"display\", \"block\");\n $(\".product-items\").find(\".color-detail\").css(\"display\", \"none\");\n $(this).find(\".color-label\").css(\"display\", \"none\");\n $(this).find(\".color-detail\").css(\"display\", \"block\");\n });\n }\n\n // Force load & play on video if not disabled by accessibility mode\n $(\".products.list.items.product-items video\").each(function () {\n if (!$('body').hasClass('accessibility_mode_animation')) {\n if ($(this).hasClass('play-on')) {\n if ($(this).get(0).videoHeight >
2 0) {\n // Do nothing\n } else {\n // reload the video\n $(this).get(0).load();\n }\n\n }\n } else {\n videoPlayback.pause($(this)[0]);\n }\n });\n\n\n //Listen reductAnimation Event & stop video in carousel on Hover\n $(document).on(\"reductAnimation\", function (event) {\n $(\".product-list-video\").hover(function () {\n if (event.detail.animation === true) {\n videoPlayback.pause($(this).find(\"video\").get(0));\n } else {\n videoPlayback.play($(this).find(\"video\").get(0));\n }\n });\n });\n const $nextProduct = $lastProductItem.next();\n $nextProduct.find('.product-item-link').focus();\n\n // Dispatch Event for price in listing page\n document.dispatchEvent(customPriceListingPageEvent);\n })\n\n ias.on('last', () => {\n $('.more-products-wrapper').css(\"display\", \"none\");\n })\n });\n\n\n $(document).on(\"reload_pagination\", function () {\n if ($('.products.list.items.product-items').length > 0) {\n let ias = new InfiniteAjaxScroll(\".products.list.items.product-items\", {\n item: \".item.product.product-item,.item.category-moodboard\",\n next: \".toolbar-bottom .pages .item.current + .item a\",\n pagination: \".toolbar-products.toolbar-bottom\",\n loadOnScroll: false,\n prefill: false,\n spinner: '.loader.goyard-loader',\n trigger: \".btn-more-products\"\n });\n ias.on(\"appended\", function () {\n console.error('reload_pagination appended');\n $(\".products.list.items.product-items\").trigger(\"contentUpdated\");\n $(\".loader.goyard-loader\").attr(\"style\", \"display: none;\");\n $('.more-products-wrapper').attr(\"style\", \"margin-bottom: 40px\");\n })\n\n ias.on('last', () => {\n $('.more-products-wrapper').css(\"display\", \"none\");\n })\n }\n\n // Update moodboard\n columnsCatalog.injectGridArea();\n\n if ($(\".toolbar-bottom .pages .item.current + .item a\").length && !$('.more-products-wrapper').hasClass('no-product')) {\n $('.more-products-wrapper').css(\"display\", \"block\");\n $('.btn-more-products').css(\"opacity\", \"1\");\n }\n else {\n $('.more-products-wrapper').css(\"display\", \"none\");\n }\n });\n});\n","Goyard_Catalog/js/category/handler-swatchcolor.js":"/**\n * Copyright Goyard Orkester\n * @author Orkester\n * @copyright Goyard\n */\n\ndefine('Goyard_Catalog/js/category/handler-swatchcolor', [\n 'jquery',\n 'Goyard_Catalog/js/category/change-carousel',\n], function (\n $,\n changeCarousel\n) {\n 'use strict';\n\n const eventCatcherCategory = {\n init: function () {\n const event = new CustomEvent(\"plp-page:load\");\n document.dispatchEvent(event);\n\n $('body').on('swatch.initialized', function (event, data) {\n eventCatcherCategory.applyColorFilterFromUrlOnListing(data.swatchThis);\n });\n\n document.addEventListener(\"swatchOptionClickedOnListingPageOrResultPage\", function (event) {\n eventCatcherCategory.onSwatchOptionClick(event.detail.element);\n });\n },\n\n /**\n * Au click sur une couleur\n * Change le carousel, updates le Hash dans l'url et lance l'ajax pour mettre \u00e0 jour le prix\n */\n onSwatchOptionClick: function (element) {\n let color = element.attr('aria-label');\n let parent = element.closest('li.item.product.product-item.text-center');\n const name = parent.find('.product-item-link').text().trim();\n parent.attr('aria-label', name + ' - ' + color);\n\n changeCarousel.init(element);\n this.updateHashInUrl(element);\n\n const colorWrapper = element.closest('.product-item-info');\n const priceContainer = colorWrapper.find('.custom-price-container');\n const priceContainerSku = priceContainer.data('sku')\n\n const customPriceListingPageEvent = new CustomEvent(\"plp-swatchcolor:click\", {\n detail: {\n selector: \"#custom-price-plp-\" + priceContainerSku,\n sku: element.data('option-sku')\n }\n });\n window.dispatchEvent(customPriceListingPageEvent);\n\n },\n /**\n Update URl of product to add #SKU of the selected variation in any link\n in a product-item parent element.\n */\n updateHashInUrl: function (element) {\n const currentSku = element.data('option-sku');\n\n if (currentSku) {\n $(document).ready(function () {\n const listCarousel = element.closest('li.item.product.product-item.text-center');\n\n listCarousel.find('a').each(function () {\n const $link = $(this);\n const currentHref = $link.attr('href');\n\n if (!currentHref) return;\n\n if (currentHref.includes(\"/sku/\")) {\n const updatedUrl = currentHref.replace(/\\/sku\\/[^\\/]*/, '/sku/' + currentSku);\n $link.attr('href', updatedUrl);\n } else {\n const updatedUrl = currentHref.replace(/#.*/, '') + '#' + currentSku;\n $link.attr('href', updatedUrl);\n }\n });\n });\n }\n },\n\n applyColorFilterFromUrlOnListing: function (swatchThis) {\n try {\n if (!this.isListingPage()) return;\n\n const colorIds = this.extractColorFilterIdsFromUrl();\n\n if (colorIds.length > 0) {\n this.applyColorFilterToProducts(colorIds, swatchThis);\n } else {\n this.applyMainVariantColorFallback(swatchThis);\n }\n } catch (error) {\n console.error('Error in applyColorFilterFromUrlOnListing :', error);\n }\n },\n\n isListingPage: function () {\n return (\n $('.catalog-category-view').length >
2 0 ||\n $('.cms-index-index .product-carousel-widget-wrapper').length > 0 ||\n $('.cms-page-view .product-carousel-widget-wrapper').length > 0 ||\n $('.catalogsearch-result-index').length > 0 ||\n $('.search.results .products.wrapper.grid.products-grid .products.list.items.product-items').length > 0\n );\n },\n\n extractColorFilterIdsFromUrl: function () {\n const regex = /att_color_digital_filter%5B%5D=(\\d+)/g;\n const queryString = window.location.search;\n const matches = queryString.matchAll(regex);\n\n const colorIds = [];\n for (const match of matches) {\n colorIds.push(match[1]);\n }\n return colorIds;\n },\n\n applyColorFilterToProducts: function (colorIds, swatchThis) {\n const products = $('[data-item-position]');\n products.each((index, productElement) => {\n const colorIndex = index % colorIds.length;\n let colorId = colorIds[colorIndex];\n if ($(productElement).find($(swatchThis.element)).length > 0) {\n let swatchOption = $(productElement).find(`.swatch-option[data-option-filter-id*=\"${colorId}\"]`).first();\n if (swatchOption.length) {\n swatchOption.click();\n } else {\n this.tryFallbackColorOptions(productElement, colorIds, colorIndex);\n }\n }\n });\n },\n\n tryFallbackColorOptions: function (element, colorIds, startIndex) {\n const visited = [];\n\n for (let i = startIndex; i < colorIds.length; i++) {\n let colorId = colorIds[i];\n\n if (visited.includes(colorId)) {\n // All options tried \u2192 fallback to main variant\n const mainId = $(element).find(\".product-item-details\").attr('data-main-variant-option-id');\n $(element).find(`.swatch-option[data-option-id=\"${mainId}\"]`).click();\n return;\n }\n\n visited.push(colorId);\n let swatchOption = $(element).find(`.swatch-option[data-option-filter-id*=\"${colorId}\"]`);\n if (swatchOption.length) {\n swatchOption.click();\n return;\n }\n\n if (i === colorIds.length - 1) i = -1; // restart loop\n }\n },\n\n applyMainVariantColorFallback: function (swatchThis) {\n const $el = $(swatchThis.element);\n const mainVariantId = $el.parents('.product-item-details').attr('data-main-variant-option-id');\n const swatch = $el.find(`.swatch-option[data-option-id=\"${mainVariantId}\"]`);\n const color = swatch.attr('aria-label');\n const productEl = swatch.closest('li.item.product.product-item.text-center');\n const name = productEl.find('.product-item-link').text().trim();\n\n swatch.attr('aria-selected', 'true');\n productEl.attr('aria-label', name + ' - ' + color);\n }\n };\n\n return eventCatcherCategory;\n});\n\nrequire(['Goyard_Catalog/js/category/handler-swatchcolor'], function (eventCatcherCategory) {\n eventCatcherCategory.init();\n});\n","Goyard_Catalog/js/category/custom-price-loader.js":"define('Goyard_Catalog/js/category/custom-price-loader', [\n 'jquery',\n 'Magento_Customer/js/customer-data',\n 'mage/url'\n], function ($, customerData, urlBuilder) {\n 'use strict';\n\n const customPriceLoader = {\n\n displayPrice: function (item) {\n const selector = item.selector;\n\n if (selector === '.price') {\n if (item.label_parts) {\n $(selector).closest('.goyard-price-box-inner')\n .find('.price-label-before').text(item.label_parts.text_before);\n $(selector).text(item.label_parts.price);\n $(selector).closest('.goyard-price-box-inner')\n .find('.price-label-after').text(item.label_parts.text_after);\n } else {\n $(selector).text(item.price);\n }\n $(selector).show();\n } else {\n if (item.label_parts) {\n if (selector.indexOf('wishlist') !== -1) {\n $(selector).parent().find('.price-label-before').text(item.label_parts.text_before);\n $(selector).text(item.label_parts.price);\n $(selector).parent().find('.price-label-after').text(item.label_parts.text_after);\n } else {\n $(selector).find('.price-label-before').text(item.label_parts.text_before);\n $(selector).find('.price-plp-value').text(item.label_parts.price);\n $(selector).find('.price-label-after').text(item.label_parts.text_after);\n $(selector).show();\n }\n } else {\n if (selector.indexOf('wishlist') !== -1) {\n $(selector).text(item.price);\n } else {\n $(selector).find('.price-plp-value').text(item.price);\n $(selector).show();\n }\n }\n }\n },\n\n waitForCustomerData: function () {\n const dfd = $.Deferred();\n const customer = customerData.get('customer');\n\n if (customer().firstname) {\n dfd.resolve();\n } else {\n customer.subscribe(function () {\n if (customer().firstname) dfd.resolve();\n });\n }\n\n return dfd.promise();\n },\n\n getDatasOnCategoryPage: function () {\n const datas = {};\n if ($('body').hasClass('catalog-category-view') || $('body').hasClass('catalogsearch-result-index')) {\n datas['selector'] = \"#custom-price-plp-\";\n datas['sku'] = [];\n\n $('.custom-price-container').each($.proxy(function (i, container) {\n const $container = $(container);\n const divId = $container.attr('id');\n const sku = $container.data('sku');\n\n if (divId && sku && !sessionStorage.getItem('price_' + sku)) {\n datas['sku'].push(sku);\n }\n }, this));\n }\n if (datas['sku'] && datas['sku'].length) {\n datas['sku'] = datas['sku'].join(',');\n this.loadPrices(datas, 'plp');\n }\n },\n\n getDatasOnProductPage: function (sku) {\n if ($('body').hasClass('catalog-product-view') && !sessionStorage.getItem('price_' + sku)) {\n this.loadPrices([{ selector: '.price', sku: sku }], 'pdp');\n }\n },\n\n loadPrices: function (params, from) {\n const self = this;\n this.waitForCustomerData().done(function () {\n const query = $.param({ datas: params, from: from });\n const url = urlBuilder.build('goyard_catalog/ajax/marquageproductprice') + '?' + query;\n\n $.ajax({\n url: url,\n type: 'GET',\n dataType: 'json',\n cache: true,\n success: function (response) {\n if (!Array.isArray(response)) return console.error('R\u00e9ponse inattendue :', response);\n\n $.each(response, function (i, item) {\n if (!item.selector) return;\n\n if (item.status) {\n self.dis
2playPrice(item);\n } else {\n $(item.selector).find('span').text('');\n }\n });\n\n\n if (from === 'pdp') $(\".price\").show();\n },\n error: function () {\n console.error('Error when loading prices');\n }\n });\n });\n },\n\n init: function () {\n\n const self = this;\n $(document).on('plp-page:load', function () { self.getDatasOnCategoryPage(); });\n $(document).on('swatchOptionClicked', function (event) { self.getDatasOnProductPage(event.detail.optionSku); });\n $(window).on('plp-swatchcolor:click', function (event) { self.loadPrices([event.detail], 'plp'); });\n\n $(document).on('contentUpdated', '.products-grid', function () {\n self.getDatasOnCategoryPage();\n });\n }\n };\n\n return customPriceLoader;\n});\n\nrequire(['Goyard_Catalog/js/category/custom-price-loader'], function (customPriceLoader) {\n customPriceLoader.init();\n});\n","Goyard_Catalog/js/category/reassurance.js":"/**\n * Copyright Goyard Orkester\n * @author Orkester\n * @copyright Goyard\n */\n\ndefine([\n\t'jquery',\n\t'mage/url',\n\t'Magento_Customer/js/customer-data'\n], ($, urlBuilder, customerData) => {\n\t'use strict';\n\n\treturn function () {\n\t\t// Check if customer is logged and display reassurance block\n\t\tif (customerData.get('customer')().firstname) {\n\t\t\t$.ajax({\n\t\t\t\turl: urlBuilder.build('goyard_catalog/ajax/reassurance'),\n\t\t\t\ttype: 'GET',\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function (response) {\n\t\t\t\t\tlet html = response.html?.replaceAll(\"<\", '<').replaceAll(\">\", '>');\n\t\t\t\t\t$('.reassurance-block-container').append(html).show();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n});\n","Goyard_Catalog/js/category/change-carousel.js":"/**\n * Copyright Goyard Orkester\n * @author Orkester\n * @copyright Goyard\n */\n\ndefine('Goyard_Catalog/js/category/change-carousel', [\n 'jquery',\n], function ($) {\n 'use strict';\n const BaseUrl = window.BASE_URL;\n const urlForPersonalisationBrush = BaseUrl + 'goyard_catalog/ajax/personalisationBrush';\n const urlForProductCarousel = BaseUrl + 'goyard_catalog/ajax/productCarousel';\n\n const changeCarousel = {\n init: function ($this) {\n this.changeCarousel($this);\n },\n\n changeCarousel: function ($this) {\n const ajaxParam = $this.data('option-sku');\n let $product = $this.closest('.product-item');\n\n let productCarouselParam = this.prepareParamForProductCarousel(ajaxParam, $product);\n\n this.ajaxProductCarousel(productCarouselParam);\n\n // If the carousel is on the category page, we need to load the brush\n if ($('.catalog-category-view').length > 0 || $('.catalogsearch-result-index').length > 0) {\n let personalisationBrushParam = this.prepareParamForPersonalisationBrush(ajaxParam, $product);\n this.ajaxPersonalisationBrush(personalisationBrushParam);\n }\n },\n\n ajaxProductCarousel: function (productCarouselParam) {\n jQuery.ajax({\n url: urlForProductCarousel,\n type: 'GET',\n cache: true,\n timeout: 20000,\n data: productCarouselParam,\n dataType: 'json',\n success: function (response) {\n $(\".carousel-block-\" + response.parent).children().remove();\n $(\".carousel-block-\" + response.parent).html($(response.html));\n },\n error: function (xhr, status, error) {\n console.error(error);\n }\n });\n },\n\n prepareParamForProductCarousel: function (ajaxParam, $product) {\n let params = { 'sku': ajaxParam };\n\n let personalisation_allowed = Boolean($product.data('personalisationAllowed'));\n let first = Boolean($product.data('videoPosition'));\n let video_allowed = Boolean($product.data('videoAllowed'));\n let currentCategory = $product.data('category');\n\n let brushEnable = (typeof $('.products.wrapper').data('brush') !== 'undefined') ? 1 : 0;\n\n if (video_allowed) {\n params['video_allowed'] = 1;\n\n } else {\n params['video_allowed'] = 0;\n }\n if (personalisation_allowed) {\n params['personalisation_allowed'] = 1;\n } else {\n params['personalisation_allowed'] = 0;\n }\n if (first) {\n params['video_allowed'] = 1;\n if ($(window).width() < 768) {\n params['video_position'] = 2;\n } else {\n params['video_position'] = 1;\n }\n } else {\n params['video_position'] = 0;\n }\n if ($('.catalogsearch-result-index').length) {\n params['cache_search'] = 1;\n }\n if (currentCategory) {\n params['category_id'] = currentCategory;\n }\n params['brushEnable'] = brushEnable;\n\n return params;\n },\n\n ajaxPersonalisationBrush: function (personalisationBrushParam) {\n $.ajax({\n url: urlForPersonalisationBrush,\n type: 'GET',\n cache: true,\n timeout: 10000,\n data: personalisationBrushParam,\n dataType: 'json',\n success: function (response) {\n $(\"#brush_\" + response.parent).remove();\n $(response.html).insertBefore(\".carousel-block-\" + response.parent);\n },\n error: function (xhr, status, error) {\n console.error(error);\n }\n });\n },\n\n prepareParamForPersonalisationBrush: function (ajaxParam, $product) {\n let params = { 'sku': ajaxParam };\n let personalisation_allowed = Boolean($product.data('personalisationAllowed'));\n let brushEnable = (typeof $('.products.wrapper').data('brush') !== 'undefined') ? 1 : 0;\n\n if (personalisation_allowed) {\n params['personalisation_allowed'] = 1;\n } else {\n params['personalisation_allowed'] = 0;\n }\n params['brushEnable'] = brushEnable;\n\n return params;\n },\n }\n\n return changeCarousel;
2\n});","Goyard_Catalog/js/product_page/change_upsell.js":"define('Goyard_Catalog/js/product_page/change_upsell', [\n 'jquery',\n 'mage/url'\n], function ($, urlBuilder) {\n 'use strict';\n const urlForProductUpsell = urlBuilder.build('goyard_catalog/ajax/productUpsell');\n\n return {\n\n init: function () {\n document.addEventListener('swatchOptionClicked', (event) => {\n const productSku = event.detail.optionSku;\n this.changeUpsell(productSku);\n });\n },\n\n changeUpsell: function (productSku) {\n $('.product-upsell-container').addClass('ajax-refresh');\n this.ajaxProductUpsell(productSku);\n },\n\n ajaxProductUpsell: function (productSku) {\n $.ajax({\n url: urlForProductUpsell,\n type: 'GET',\n cache: true,\n timeout: 10000,\n data: {\n 'sku': productSku\n },\n dataType: 'json',\n success: function (response) {\n $('#product_upsell_section').replaceWith(response.html);\n $('.product-upsell-container').removeClass('ajax-refresh');\n if (!$('#product_upsell_section').children().length) {\n $('#product_upsell_section').addClass('d-none');\n }\n },\n error: function (xhr, status, error) {\n console.error(error);\n }\n });\n },\n\n };\n});\n\nrequire(['Goyard_Catalog/js/product_page/change_upsell'], function (changeUpsell) {\n changeUpsell.init();\n});\n","Goyard_Catalog/js/product_page/change_buttons.js":"/**\n * Copyright Goyard Orkester\n * @author Orkester\n * @copyright Goyard\n */\ndefine([\n\t'jquery',\n\t'mage/url',\n\t'Goyard_Catalog/js/customer_logged_status'\n], function ($, urlBuilder, customerLoggedStatus) {\n\t'use strict';\n\n\tdocument.addEventListener('swatchOptionClicked', (event) => {\n\t\tconst productSku = event.detail.optionSku;\n\t\t$('#product_addtocart_form').find('input[name=\"current_sku\"]').val(productSku);\n\t\tchangeAllButtons(productSku);\n\t});\n\n\t// Update product buttons section\n\tfunction changeAllButtons(productSku) {\n\t\tcustomerLoggedStatus.getIsCustomerLoggedIn().then(function (customer) {\n\t\t\tlet isLoggedIn = !!customer?.firstname;\n\t\t\tlet url = isLoggedIn ? urlBuilder.build('goyard_catalog/ajax/productAllButtons') : urlBuilder.build('goyard_catalog/ajax/productButtons');\n\t\t\t$('.product-buttons-container').addClass('disable');\n\n\t\t\tjQuery.ajax({\n\t\t\t\turl: url,\n\t\t\t\ttype: isLoggedIn ? 'POST' : 'GET',\n\t\t\t\tcache: true,\n\t\t\t\ttimeout: 10000,\n\t\t\t\tloader: true,\n\t\t\t\tdata: {\n\t\t\t\t\t'sku': productSku\n\t\t\t\t},\n\t\t\t\tdataType: 'json',\n\t\t\t\tsuccess: function (response) {\n\t\t\t\t\tlet featureContainer = $(response.html);\n\n\t\t\t\t\t$('.product-buttons-container').html(featureContainer);\n\n\t\t\t\t\t$('.product-buttons-container').removeClass('disable');\n\t\t\t\t},\n\t\t\t\terror: function (xhr, status, error) {\n\t\t\t\t\tconsole.error('changeAllButtonsThisProduct : ' + error);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n});\n","Goyard_Catalog/js/product_page/change_crosssell.js":"define('Goyard_Catalog/js/product_page/change_crosssell', [\n 'jquery',\n 'mage/url'\n], function ($, urlBuilder) {\n 'use strict';\n\n const urlChangeCrosssel = urlBuilder.build('goyard_catalog/ajax/productCrosssell');\n\n return {\n\n init: function () {\n document.addEventListener('swatchOptionClicked', (event) => {\n const productSku = event.detail.optionSku;\n this.changeCrosssell(productSku);\n });\n },\n\n changeCrosssell: function (productSku) {\n $('.product-crosssell-container').addClass('ajax-refresh');\n this.ajaxProductCrosssell(productSku);\n },\n\n ajaxProductCrosssell: function (productSku) {\n jQuery.ajax({\n url: urlChangeCrosssel,\n type: 'GET',\n cache: true,\n timeout: 10000,\n data: {\n 'sku': productSku\n },\n dataType: 'json',\n success: function (response) {\n $('#product_crosssell_section').replaceWith(response.html);\n $('.product-crosssell-container').removeClass('ajax-refresh');\n if (!$('#product_crosssell_section').children().length) {\n $('#product_crosssell_section').addClass('d-none');\n }\n },\n error: function (xhr, status, error) {\n console.error(error);\n }\n });\n }\n };\n});\n\nrequire(['Goyard_Catalog/js/product_page/change_crosssell'], function (changeCrosssell) {\n changeCrosssell.init(
2);\n});\n","Goyard_Catalog/js/product_page/handler-swatchcolor.js":"/**\n * Copyright Goyard Orkester\n * @author Orkester\n * @copyright Goyard\n */\n\ndefine('Goyard_Catalog/js/product_page/handler-swatchcolor', [\n 'jquery',\n 'Goyard_Wishlist/js/check-customer-wishlist',\n 'Goyard_Wishlist/js/front-injector',\n 'Goyard_Catalog/js/customer_logged_status',\n], function (\n $,\n customerWishlist,\n frontInjector,\n customerLoggedStatus,\n) {\n 'use strict';\n\n const eventCatcherProduct = {\n init: function () {\n let swatchInitCount = 0;\n const totalSwatches = $('.swatch-attribute').length;\n let jsonConfig = null;\n\n $('body').on('swatch.initialized', function (event, data) {\n swatchInitCount++;\n jsonConfig = data.swatchThis.options.jsonConfig;\n\n // D\u00e9clenche l'observateur taille & mati\u00e8re une seule fois\n if (swatchInitCount === 1) {\n eventCatcherProduct.watchAttSizeChange(jsonConfig);\n eventCatcherProduct.watchAttJewelryChange(jsonConfig);\n }\n\n // Quand TOUS les swatches sont pr\u00eats \u2192 on ex\u00e9cute selectVariantFromHash\n if (swatchInitCount >= totalSwatches) {\n eventCatcherProduct.handleInitialSwatchState(data.swatchThis);\n }\n });\n\n document.addEventListener(\"swatchOptionClickedOnProductPage\", function (event) {\n let sku = event.detail.element.data('option-sku');\n eventCatcherProduct.onSwatchOptionClick(sku, jsonConfig);\n });\n\n if ($('div.fotorama').length > 0) {\n $(document).trigger(\"swatch_reloaded\");\n }\n },\n\n /**\n * Observe les changements de s\u00e9lection sur l\u2019attribut \u201cjewelry\u201d\n * et d\u00e9clenche un event d\u00e8s que la s\u00e9lection change.\n * @param {Object} jsonConfig - Configuration produit Magento (jsonConfig)\n */\n watchAttJewelryChange: function (jsonConfig) {\n const $swatch = $('.swatch-attribute.att_jewelry');\n const skuMap = jsonConfig.sku;\n const indexMap = jsonConfig.index;\n\n if (!$swatch.length) return;\n\n // \ud83d\udd0d MutationObserver pour d\u00e9tecter le changement de data-option-selected\n const observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n if (mutation.type === 'attributes' && mutation.attributeName === 'data-option-selected') {\n const newSku = eventCatcherProduct.getSelectedJewelrySku(indexMap, skuMap, $swatch, \"567\");\n\n if (newSku) {\n eventCatcherProduct.updateUrlSku(newSku);\n eventCatcherProduct.createAndDispatchEvent(newSku);\n }\n }\n });\n });\n\n observer.observe($swatch[0], { attributes: true });\n },\n\n /**\n * R\u00e9cup\u00e8re le SKU correspondant \u00e0 la mati\u00e8re actuellement s\u00e9lectionn\u00e9e\n * @param {Object} indexMap - jsonConfig.index\n * @param {Object} skuMap - jsonConfig.sku\n * @param {jQuery} $swatch - \u00c9l\u00e9ment .swatch-attribute.att_jewelry\n * @param {String} jewelryAttrId - ID d\u2019attribut pour la bijouterie (ex: \"567\")\n * @returns {String|null} - SKU trouv\u00e9 ou null si aucun ou si pas configur\u00e9\n */\n getSelectedJewelrySku: function (indexMap, skuMap, $swatch, jewelryAttrId) {\n if (!indexMap || !skuMap) return null;\n if (!$swatch || !$swatch.length) return null;\n\n const selectedOption = $swatch.attr('data-option-selected');\n if (!selectedOption) return null;\n\n let foundKey = null;\n for (const [key, attrs] of Object.entries(indexMap)) {\n if (attrs[jewelryAttrId] && attrs[jewelryAttrId] === selectedOption) {\n foundKey = key;\n break;\n }\n }\n\n if (!foundKey) return null;\n\n const newSku = skuMap[foundKey] || null;\n return newSku;\n },\n\n /**\n * S\u00e9lectionne automatiquement la mati\u00e8re c
2orrespondant au SKU donn\u00e9.\n * @param {String} sku - SKU actuel\n * @param {Object} jsonConfig - Configuration produit (jsonConfig)\n */\n selectJewelryFromSku: function (sku, jsonConfig) {\n if (!sku || !jsonConfig || !jsonConfig.index) return;\n\n const indexMap = jsonConfig.index;\n const skuMap = jsonConfig.sku;\n const $jewelrySelect = $('.swatch-select.att_jewelry');\n\n if (!$jewelrySelect.length) return;\n\n const productId = Object.keys(skuMap).find(key => skuMap[key] === sku);\n if (!productId || !indexMap[productId]) return;\n\n const jewelryAttrId = Object.keys(indexMap[productId]).find(attrId => {\n return $('.swatch-select.att_jewelry[data-attribute-id=\"' + attrId + '\"]').length > 0\n || $('.swatch-attribute.att_jewelry[data-attribute-id=\"' + attrId + '\"]').length > 0;\n });\n\n if (jewelryAttrId === undefined) return;\n\n const jewelryOptionId = indexMap[productId][jewelryAttrId];\n if (!jewelryOptionId) return;\n\n const $targetOption = $jewelrySelect.find(`option[data-option-id=\"${jewelryOptionId}\"]`);\n if ($targetOption.length) {\n $jewelrySelect.val(jewelryOptionId);\n }\n },\n\n\n watchAttSizeChange: function (jsonConfig) {\n\n const $swatch = $('.swatch-attribute.att_size');\n const skuMap = jsonConfig.sku;\n const indexMap = jsonConfig.index;\n\n if (!$swatch.length) return;\n\n // MutationObserver pour d\u00e9tecter le changement de data-option-selected\n const observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n if (mutation.type === 'attributes' && mutation.attributeName === 'data-option-selected') {\n const newSku = eventCatcherProduct.getSelectedSizeSku(indexMap, skuMap, $swatch, \"602\");\n\n if (newSku) {\n eventCatcherProduct.updateUrlSku(newSku);\n eventCatcherProduct.createAndDispatchEvent(newSku);\n }\n }\n });\n });\n\n observer.observe($swatch[0], { attributes: true });\n },\n\n /**\n * R\u00e9cup\u00e8re le SKU correspondant \u00e0 la taille actuellement s\u00e9lectionn\u00e9e (si applicable)\n * @param {Object} indexMap - jsonConfig.index\n * @param {Object} skuMap - jsonConfig.sku\n * @param {jQuery} $swatch - \u00c9l\u00e9ment .swatch-attribute.att_size\n * @param {String} sizeAttrId - ID d'attribut de la taille (ex: \"602\")\n * @returns {String|null} - SKU trouv\u00e9 ou null si aucun ou si pas de taille configur\u00e9e\n */\n getSelectedSizeSku: function (indexMap, skuMap, $swatch, sizeAttrId) {\n // \ud83e\udde9 V\u00e9rifie si les structures de donn\u00e9es existent\n if (!indexMap || !skuMap) {\n return null;\n }\n\n // \ud83e\udde9 V\u00e9rifie si le swatch \"taille\" existe sur la page\n if (!$swatch || !$swatch.length) {\n return null;\n }\n\n const selectedOption = $swatch.attr('data-option-selected');\n if (!selectedOption) {\n return null;\n }\n\n let foundKey = null;\n for (const [key, attrs] of Object.entries(indexMap)) {\n if (attrs[sizeAttrId] && attrs[sizeAttrId] === selectedOption) {\n foundKey = key;\n break;\n }\n }\n\n if (!foundKey) {\n return null;\n }\n\n const newSku = skuMap[foundKey] || null;\n\n return newSku;\n },\n\n /**\n * S\u00e9lectionne automatiquement la taille correspondant au SKU donn\u00e9.\n * @param {String} sku - SKU actuel (ex: celui de la couleur s\u00e9lectionn\u00e9e)\n * @param {Object} jsonConfig - Configuration Magento (jsonConfig)\n */\n selectSizeFromSku: function (sku, jsonConfig) {\n if (!sku || !jsonConfig || !jsonConfig.index) return;\n\n const indexMap = jsonConfig.index;\n const skuMap = jsonConfig.sku;\n const $sizeSelect = $('.swatch-select.att_size');\n\n if (!$sizeSelect.length) {\n return;\n }\n\n const productId = Object.keys(skuMap).find(key => skuMap[key] === sku);\n if (!productId || !indexMap[productId]) return;\n\n const sizeAttrId = Object.keys(indexMap[productId]).find(attrId =>
2 {\n return $('.swatch-select.att_size[data-attribute-id=\"' + attrId + '\"]').length > 0\n || $('.swatch-attribute.att_size[data-attribute-id=\"' + attrId + '\"]').length > 0;\n });\n\n if (sizeAttrId === undefined) {\n return;\n }\n\n const sizeOptionId = indexMap[productId][sizeAttrId];\n if (!sizeOptionId) {\n return;\n }\n\n const $targetOption = $sizeSelect.find(`option[data-option-id=\"${sizeOptionId}\"]`);\n if ($targetOption.length) {\n\n $sizeSelect.val(sizeOptionId);\n }\n },\n\n createAndDispatchEvent: function (sku) {\n // Cr\u00e9er et diffuser un \u00e9v\u00e9nement personnalis\u00e9 avec les valeurs r\u00e9cup\u00e9r\u00e9es\n let swatchOptionClicked = new CustomEvent('swatchOptionClicked', {\n detail: {\n optionSku: sku\n }\n });\n\n document.dispatchEvent(swatchOptionClicked);\n },\n\n onSwatchOptionClick: function (sku, jsonConfig) {\n //update url hash in product page\n this.updateUrlSku(sku);\n\n this.createAndDispatchEvent(sku);\n\n $('.swatch-option.selected').data('option-sku', sku);\n\n if (jsonConfig) {\n this.selectSizeFromSku(sku, jsonConfig);\n }\n\n // Update Wishlist star\n this.updateWishlistStar(sku);\n },\n\n handleInitialSwatchState: function (swatchThis) {\n try {\n if (!this.isValidSwatchContext(swatchThis)) return;\n\n const $element = $(swatchThis.element);\n const config = swatchThis.options.jsonConfig;\n\n if (window.location.hash) {\n this.selectVariantFromHash($element, config);\n } else {\n this.selectDefaultVariant($element);\n }\n\n // Final UI/application tasks\n this.removeSpinner();\n this.setupAccessibilityEvents(swatchThis);\n this.updatePrice(swatchThis);\n\n } catch (error) {\n console.error('Error dans handleInitialSwatchState :', error);\n this.removeSpinner();\n }\n },\n\n isValidSwatchContext: function (swatchThis) {\n if (!swatchThis || !swatchThis.element || !swatchThis.options || !swatchThis.options.jsonConfig) {\n console.error('swatchThis is invalid or missing required properties');\n return false;\n }\n return true;\n },\n\n selectVariantFromHash: function ($element, config) {\n const variant = window.location.hash.slice(1).replace('/', '');\n const attributeCouleurId = $element.find('.swatch-attribute.couleur').attr('data-attribute-id');\n\n if (!attributeCouleurId) {\n console.error('swatch-attribute \"couleur\" not found');\n return;\n }\n\n const attributes = config.attributes || [];\n const attribute_couleur = attributes.find(attr => attr.id == attributeCouleurId);\n\n if (!attribute_couleur) {\n console.error('attribute \"' + attributeCouleurId + '\" not found');\n return;\n }\n\n for (const [productId, sku] of Object.entries(config.sku)) {\n if (variant === sku) {\n for (const attribute of attributes) {\n const option = attribute.options.find(opt => opt.products.includes(productId));\n if (!option) continue;\n\n const optionEl = $element.find(`.swatch-option[data-option-id=\"${option.id}\"]`);\n if (optionEl.length > 0) {\n optionEl.click();\n } else {\n $(`option[data-option-id=\"${option.id}\"]`).parent().val(option.id).trigger(\"change\");\n }\n }\n }\n }\n },\n\n selectDefaultVariant: function ($element) {\n const mainVariantId = $element.parents('.product-options-wrapper-container').attr('data-main-variant-option-id');\n if (mainVariantId) {\n const defaultOption = $element.find(`.swatch-option[data-option-id=\"${mainVariantId}\"]`);\n if (defaultOption.length) {\n defaultOption.click();\n }\n }\n },\n\n removeSpinner: function () {\n $(\"#spinner-product-view\").remove();\n },\n\n setupAccessibilityEvents: function (swatchThis) {\n // Accessibility focus and ke
2yboard navigation\n const $colorOptions = $(swatchThis.element).find('.couleur .swatch-attribute-options');\n\n $colorOptions.each(function () {\n const selectedOptionId = $(this).find('[aria-selected=\"true\"]')?.attr('id') ?? '';\n $(this).attr('aria-activedescendant', selectedOptionId)\n })\n $colorOptions.off('focus blur keydown');\n $colorOptions.on('focus blur', swatchThis.setupFocus.bind(swatchThis));\n $colorOptions.on('keydown', swatchThis.throughSwatchOptions.bind(swatchThis));\n\n // Add border for contrast accessibility\n $('.swatch-option').on('click', function () {\n $('.swatch-option').removeClass('borderBlue');\n if ($.mage.cookies.get('accessibility_mode_constrast') === \"true\") {\n $(this).addClass('borderBlue');\n }\n });\n\n // Remove border on click outside swatch\n $(document).on('click', function (event) {\n if (!$(event.target).closest('.swatch-option').length) {\n $(\".swatch-option\").removeClass('borderBlue');\n }\n });\n },\n\n updatePrice: function (swatchThis) {\n if ($('.catalog-product-view').length > 0) {\n customerLoggedStatus.getIsCustomerLoggedIn().then((customer) => {\n const price = swatchThis._getNewPrices?.();\n const selectedOptionSku = $('.swatch-attribute-options .swatch-option.selected').data('optionSku');\n\n if (\n price?.finalPrice?.amount > 0 &&\n customer?.firstname &&\n swatchThis.options.priceDisplay?.[selectedOptionSku]\n ) {\n $(\".product-info-main .product-info-price\").show();\n } else {\n $(\".product-info-main .product-info-price\").hide();\n }\n });\n }\n },\n\n /**\n Update URl sku after # in product page when changing color\n */\n updateUrlSku: function (newSku) {\n const baseUrl = window.location.href.split('#')[0];\n const updatedUrl = `${baseUrl}#${newSku}`;\n\n window.history.replaceState({}, document.title, updatedUrl);\n },\n\n /**\n Update Wishlist star\n */\n updateWishlistStar: function (sku) {\n if (customerLoggedStatus.getCustomer()?.firstname && $('#add-to-wishlist').length) {\n customerWishlist.checkIfAlreadyInWishlist(sku).then(function (data) {\
2n frontInjector.injectSvg(data.status);\n });\n } else {\n frontInjector.injectSvg(false);\n }\n },\n };\n\n return eventCatcherProduct;\n});\n\nrequire(['Goyard_Catalog/js/product_page/handler-swatchcolor'], function (eventCatcherProduct) {\n eventCatcherProduct.init();\n});","Goyard_Catalog/js/product_page/video_personalization.js":"define(['jquery', 'Goyard_Catalog/js/video-playback', 'mage/cookies'], function ($, videoPlayback) {\n var videoPersonalization = {\n init: function() {\n $(document).ready(function () {\n const playBtn = \"<button type='button' class='video-play-button play-on' aria-label='Pause'><div class='inner-button'></div></button>\";\n \n let personalization_video = $('.personalization-video-right .pagebuilder-video-container video');\n \n personalization_video.each(function () {\n $(this).removeAttr('controls');\n $(this).closest('.pagebuilder-video-wrapper').append(playBtn);\n \n if ($(window).width() >= 768) {\n $(this).prop('autoplay', true).prop('muted', true).prop('loop', true);\n videoPlayback.play(this);\n }\n });\n \n function loadVideo(video) {\n if (window.innerWidth < 768) {\n let source = $(video).parent().data('source-mobile');\n if (source) {\n video.src = source;\n video.load();\n }\n } else {\n let source = $(video).parent().data('source-desktop');\n if (source) {\n video.src = source;\n video.load();\n }\n }\n }\n \n function loadFallBackImage(video) {\n if (window.innerWidth < 768) {\n let source = $(video).parent().data('fallback-mobile');\n if (source) {\n video.poster = source;\n }\n } else {\n let source = $(video).parent().data('fallback-desktop');\n if (source) {\n video.poster = source;\n }\n }\n }\n \n function isStoppedAnimationInCookies() {\n let isAnimationMode = $.mage.cookies.get('accessibility_mode_animation') === \"true\";\n if (isAnimationMode) {\n personalization_video.each(function () {\n videoPlayback.pause(this);\n $(this).closest('.pagebuilder-video-wrapper').find('.video-play-button').attr('aria-label', 'Play');\n });\n }\n }\n \n function reduceAnimation() {\n document.addEventListener(\"reductAnimation\", (event) => {\n if (event.detail.animation === true) {\n personalization_video.each(function () {\n videoPlayback.pause(this);\n $(this).closest('.pagebuilder-video-wrapper').find('.video-play-button').attr('aria-label', 'Play');\n });\n } else {\n personalization_video.each(function () {\n videoPlayback.play(this);\n $(this).closest('.pagebuilder-video-wrapper').find('.video-play-button').attr('aria-label', 'Pause');\n });\n }\n });\n }\n \n let observer = new IntersectionObserver(function (entries, observer) {\n entr
2ies.forEach(function (entry) {\n if (entry.isIntersecting) {\n let video = entry.target.querySelector('video');\n loadFallBackImage(video);\n loadVideo(video);\n observer.unobserve(entry.target);\n }\n });\n });\n \n let videos = document.querySelectorAll('.pagebuilder-video-wrapper');\n videos.forEach(function (video) {\n observer.observe(video);\n });\n \n isStoppedAnimationInCookies();\n reduceAnimation();\n });\n }\n };\n return videoPersonalization;\n});\n","Goyard_Catalog/js/product_page/change_all_about.js":"/**\n * Copyright Goyard Orkester\n * @author Orkester\n * @copyright Goyard\n */\ndefine([\n\t'jquery',\n\t'mage/url',\n\t'Magento_Ui/js/modal/modal',\n\t'Goyard_Catalog/js/customer_logged_status'\n], function ($, urlBuilder, modal, customerLoggedStatus) {\n\t'use strict';\n\n\t$(document).on('click', '.accordion-trigger', function () {\n\t\tlet $content = $('.' + $(this).attr('aria-controls'));\n\t\tvar wasOpen = $(this).attr('aria-expanded') === 'true';\n\n\t\t$(this).attr('aria-expanded', !wasOpen);\n\t\tif (!wasOpen) {\n\t\t\t$content.addClass('show');\n\t\t} else {\n\t\t\t$content.removeClass('show');\n\t\t}\n\t});\n\n\t// \u00c9coute l'\u00e9v\u00e9nement personnalis\u00e9 \"swatchOptionClicked\"\n\tdocument.addEventListener('swatchOptionClicked', (event) => {\n\t\tconst productSku = event.detail.optionSku; // R\u00e9cup\u00e8re SKU depuis l'\u00e9v\u00e9nement\n\t\tchangeAllAbout(productSku); // Appelle la fonction changeAllAbout avec SKU\n\t});\n\n\tcheckIfUserIsLogged();\n\n\tlet options = {\n\t\tresponsive: true,\n\t\tinnerScroll: true,\n\t\tmodalClass: 'right-side-modal product-info-layer-modal',\n\t\toverlayClass: 'product-modal-overlay',\n\t\tbuttons: []\n\t};\n\t// Manage modals\n\tif (window.innerWidth >= 768) {\n\t\tlet modal_details = $('.product-info-details-layer');\n\t\tif (modal_details.length) {\n\t\t\tlet popup_details = modal(options, modal_details);\n\t\t\topenLayerModal(modal_details, '.product-info-details-layer-title')\n\t\t}\n\n\t\tlet modal_shipping = $('.product-info-shipping-layer');\n\t\tif (modal_shipping.length) {\n\t\t\tlet popup_shipping = modal(options, modal_shipping);\n\t\t\topenLayerModal(modal_shipping, '.product-info-shipping-layer-title')\n\t\t}\n\n\t\tlet modal_care = $('.product-info-care-layer');\n\t\tif (modal_care.length) {\n\t\t\tlet popup_care = modal(options, modal_care);\n\t\t\topenLayerModal(modal_care, '.product-info-care-layer-title')\n\t\t}\n\t}\n\n\tlet modal_size_guide = $('.product-size-guide');\n\tif (modal_size_guide.length) {\n\t\tlet popup_size_guide = modal(options, modal_size_guide);\n\t\topenLayerModal(modal_size_guide, '.product-size-guide-cta')\n\t}\n\n\t// Update product details section\n\tfunction changeAllAbout(productSku) {\n\t\tlet self = this;\n\t\tlet url = urlBuilder.build('goyard_catalog/ajax/productAllDetails');\n\t\tconst isMobile = window.innerWidth >= 768 ? false : true;\n\n\t\tif (isMobile) {\n\t\t\turl = urlBuilder.build('goyard_catalog/ajax/productAllDetailsLayers');\n\t\t}\n\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: 'GET',\n\t\t\tcache: true,\n\t\t\ttimeout: 10000,\n\t\t\tdata: {\n\t\t\t\t'sku': productSku,\n\t\t\t},\n\t\t\tdataType: 'json',\n\t\t\tsuccess: function (response) {\n\t\t\t\tlet featureContainer = $(response.html).filter('.product-feature-container').html();\n\n\t\t\t\t$('.product-feature-container').html(featureContainer);\n\t\t\t\t$('.product-feature-container').append(response.contact);\n\n\t\t\t\t// Update content of modals\n\t\t\t\tif (!isMobile) {\n\t\t\t\t\tlet detailsModalContent = $(response.html).filter('.product-info-details-layer').html();\n\t\t\t\t\tlet shippingModalContent = $(response.html).filter('.product-info-shipping-layer').html();\n\t\t\t\t\tlet careModalContent = $(response.html).filter('.product-info-care-layer').html();\n\n\t\t\t\t\t$('.modal-content >
2.product-info-details-layer').html(detailsModalContent);\n\t\t\t\t\t$('.modal-content >.product-info-shipping-layer').html(shippingModalContent);\n\t\t\t\t\t$('.modal-content >.product-info-care-layer').html(careModalContent);\n\t\t\t\t}\n\n\t\t\t\t// Remove layers if customer's not logged in\n\t\t\t\tif (!customerLoggedStatus.getCustomer().firstname) {\n\t\t\t\t\t$('.product-info-shipping-layer-title').remove();\n\t\t\t\t\t$('.product-info-shipping-layer').remove();\n\t\t\t\t}\n\n\t\t\t\t// Display contact button depending on add to cart button\n\t\t\t\tif ($('#add-to-cart-container').children().length) {\n\t\t\t\t\t$('.product-contact-container').addClass('d-none');\n\t\t\t\t} else {\n\t\t\t\t\t$('.product-contact-container').removeClass('d-none');\n\t\t\t\t}\n\n\t\t\t\t$('.product-feature-container').removeClass('disable');\n\t\t\t},\n\t\t\terror: function (xhr, status, error) {\n\t\t\t\tconsole.error('changeAllAboutThisProduct : ' + error);\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction checkIfUserIsLogged() {\n\t\tcustomerLoggedStatus.getIsCustomerLoggedIn().then(function (customer) {\n\t\t\tvar cacheStorage = JSON.parse(localStorage.getItem('mage-cache-storage') || 'null');\n\n\t\t\tif (customer?.firstname || cacheStorage?.customer?.firstname) {\n\t\t\t\t$('.product-info-shipping-layer-title').show();\n\t\t\t\t$('.product-info-shipping-layer-title').show();\n\n\t\t\t} else {\n\t\t\t\t$('.product-info-shipping-layer-title').hide();\n\t\t\t\t$('.product-info-shipping-layer-title').hide();\n\t\t\t}\n\t\t});\n\t}\n\n\t// Open product layer modal and set its height\n\tfunction openLayerModal(modal, title) {\n\t\t$(document).on('click', title, function () {\n\t\t\t$('html, body').animate({ scrollTop: 0 });\n\t\t\t$('.product-info-layer-modal').find('.modal-inner-wrap')?.css({ 'maxHeight': $('.product-info-top').innerHeight() + 'px' });\n\t\t\tmodal.modal('openModal');\n\t\t});\n\t}\n});\n","Goyard_Catalog/js/product_page/contact_modal.js":"require([\n\t'jquery',\n\t'Magento_Ui/js/modal/modal'\n], function ($, modal) {\n\tlet options = {\n\t\ttype: 'popup',\n\t\tresponsive: true,\n\t\tinnerScroll: true,\n\t\ttitle: '',\n\t\tmodalClass: 'right-side-modal product-info-layer-modal',\n\t\toverlayClass: 'product-modal-overlay',\n\t\tbuttons: []\n\t};\n\n\tlet modal_element = $('#product-info-contact-modal');\n\tif (modal_element.length) {\n\t\tlet popup_contact = modal(options, modal_element);\n\t}\n\n\tlet autocompleteAdded = false;\n\n\t// Open product layer modal and set its height\n\t$(document).on('click', '.product-info-contact-layer-title, #product-contact-cta', function (e) {\n\n\t\tif (!autocompleteAdded) {\n\t\t\t$('[id*=\"amform-form-\"]').find('[class*=\"ac-\"]').each(function () {\n\t\t\t\tvar autocompleteClass = $(this).attr('class').match(/(?:^|\\s)ac-((\\w|\\-)+)/)?.[1];\n\t\t\t\t$(this).attr('autocomplete', autocompleteClass);\n\t\t\t});\n\t\t\tautocompleteAdded = true;\n\t\t}\n\n\t\tif ($(window).width() > 768) {\n\t\t\t$('.product-info-layer-modal').find('.modal-inner-wrap')?.css({ 'maxHeight': $('.product-info-top').innerHeight() + 'px' });\n\t\t}\n\t\tif (!($(window).width() < 768 && $(e.currentTarget).hasClass('product-info-contact-layer-title'))) {\n\t\t\t$('html, body').animate({ scrollTop: 0 });\n\t\t\tmodal_element.modal('openModal');\n\t\t\tif (typeof mtcaptchaConfig !== 'undefined' && modal_element.find('.mtcaptcha').length) {\n\t\t\t\tmtcaptchaConfig.renderQueue.push(\"mtcaptcha\");\n\t\t\t}\n\t\t}\n\n\t\tif ($(\".swatch-option.selected\").length > 0) {\n\t\t\tlet sku_product = window.location.hash.substring(1);\n\t\t\t$('#product-info-contact-modal').find('input[name=\"product\"').attr(\"value\", sku_product);\n\t\t}\n\t});\n\n\tlet modalKeyboard = false;\n\t$(document).on('keydown', function (event) {\n\t\tif ((event.keyCode === 13 || event.code == \"Space\") && $('#product-contact-cta').is(':focus')) {\n\t\t\tmodalKeyboard = true;\n\t\t}\n\t});\n\n\t$('.modal-header .action-close').on('focus', function () {\n\t\tif (modalKeyboard) {\n\t\t\t$(this).addClass('close-focus');\n\t\t}\n\t});\n\n\t$('.modal-header .action-close').on('blur', function () {\n\t\t$(this).removeClass('close-focus');\n\t});\n\n\t$('#product-contact-cta').on('mousedown', function () {\n\t\tmodalKeyboard = false;\n\t});\n});","Goyard_Catalog/js/product_page/video_wearing.js":"define(['jquery', 'Goyard_Catalog/js/video-playback', 'slick', 'mage/cookies'], function ($, videoPlayback) {\n var videoWearing = {\n init: function(){\n $(document).ready(function () {\n const playBtn = \"<button type='button' class='video-play-button play-on' aria-label='Pause'><div class='inner-button'></div></button>\";\n\n // Ajoute le bouton play/pause \u00e0 chaque vid\u00e9o\n $('.video-wrapper').each(function () {\n $(this).append(playBtn);\n });\n\n // V\u00e9rifie si l'animation est r\u00e9duite dans les cookies\n function isAnimationReduced() {\n return $.mage.cookies.get('accessibility_mode_animation') === \"true\";\n }\n\n // Initialisation du slider Slick\n $('.video-section').slick({\n dots: true,\n autoplay: false,\n initialSlide: 0,\n slidesToShow: 1,\n infinite: true,\n responsive: [\n {\n breakpoint: 1600,\n settings: {\n slidesToShow: 1,\n }\n },\n {\n breakpoint: 768,\n settings: {\n dots: true,\n slidesToShow: 1\n }\n }\n ]\n });\n\n // Fonction pour charger la source de la vid\u00e9o (adapt\u00e9e avec v\u00e9rification)\n function loadVideoSource(video) {\n if (!video.src) {\n if (window.innerWidth < 768) {\n let source = $(video).parent().data('source-mobile');\n if (source) {\n video.src = source;\n video.load(); // Charger la vid\u00e9o avec la nouvelle source\n videoPlayback.pause(video);\n }\n } else {\n let source = $(video).parent().data('source-desktop');\n if (source) {\n video.src = source;\n video.load(); // Charger la vid\u00e9o avec la nouvelle source\n videoPlayback.pause(video);\n }\n }\n }\n }\n\n // Fonction pour g\u00e9rer l'\u00e9tat du bouton Play/Pause\n function togglePlayPauseButton(video) {\n let button = $(video).parent().find('.video-play-button');\n if (video.paused) {\n button.removeClass('play-on').addClass('play-off').attr('aria-label', 'Play');\n } else {\n button.removeClass('play-off').addClass('play-on').attr('aria-label', 'Pause');\n }\n }\n\n // Gestion du clic sur le bouton Play/Pause\n $(document).on('click', '.video-play-button', function () {\n let video = $(this).parent().find('video').get(0);\n loadVideoSource(video); // Charger la source si elle n'est pas encore d\u00e9finie\n\n if ($(this).hasClass('play-on')) {\n $(this).removeClass('play-on').addClass('play-off').attr('aria-label', 'Play');\n videoPlayback.pause(video);\n } else {\n $(this).removeClass('play-off').addClass('play-on').attr('aria-label', 'Pause');\n videoPlayback.play(video).then(function (isPlaying) {\n // Lecture bloqu\u
200e9e par le navigateur : on remet le bouton sur \"Play\"\n if (!isPlaying) {\n togglePlayPauseButton(video);\n }\n });\n }\n });\n\n // Fonction pour g\u00e9rer la visibilit\u00e9 de la vid\u00e9o et jouer/mettre en pause en fonction\n function handleVideoVisibilityWithObserver() {\n // S\u00e9lectionner toutes les vid\u00e9os dans la section \"how-to-wear\"\n $('#how-to-wear-section .slick-active .video-wrapper video').each(function () {\n let videoElement = $(this)[0];\n loadVideoSource(videoElement);\n\n // Cr\u00e9er un nouvel observer pour observer les vid\u00e9os\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {\n // Si la vid\u00e9o est visible \u00e0 au moins 50%, jouer la vid\u00e9o\n if (videoElement.paused && !$('body').hasClass('accessibility_mode_animation')) {\n loadVideoSource(videoElement); // Charger la source si n\u00e9cessaire\n videoPlayback.play(videoElement).then(function () {\n togglePlayPauseButton(videoElement); // Mettre \u00e0 jour le bouton\n });\n }\n } else {\n // Si la vid\u00e9o n'est pas assez visible, la mettre en pause\n if (!videoElement.paused) {\n videoPlayback.pause(videoElement).then(function () {\n togglePlayPauseButton(videoElement); // Mettre \u00e0 jour le bouton\n });\n }\n }\n });\n },\n {\n threshold: [0.5], // D\u00e9clencher quand 50% de la vid\u00e9o est visible\n root: null, // Utiliser la fen\u00eatre du navigateur comme racine\n rootMargin: '0px' // Pas de marge autour de la fen\u00eatre\n }\n );\n\n // D\u00e9marrer l'observation de la vid\u00e9o\n observer.observe(videoElement);\n });\n }\n\n // D\u00e9tecter le scroll et le redimensionnement pour v\u00e9rifier la visibilit\u00e9 des vid\u00e9os\n $(window).on('scroll resize', handleVideoVisibilityWithObserver);\n\n // Appel initial pour g\u00e9rer la visibilit\u00e9 des vid\u00e9os\n handleVideoVisibilityWithObserver();\n\n\n // Gestion des changements de slide dans le slider\n $('.video-section').on('beforeChange', function (event, slick, currentSlide, nextSlide) {\n // Pause la vid\u00e9o sur l'ancienne slide\n let currentVideo = $(slick.$slides[currentSlide]).find('video').get(0);\n if (currentVideo) {\n videoPlayback.pause(currentVideo).then(function () {\n togglePlayPauseButton(currentVideo);\n });\n }\n\n // Si l'animation est r\u00e9duite, ne pas jouer la vid\u00e9o sur le slide suivant\n if (isAnimationReduced()) {\n return; // Emp\u00eache de jouer la vid\u00e9o du slide suivant\n }\n\n // Charger et jouer la vid\u00e9o sur la nouvelle slide\n let nextVideo = $(slick.$slides[nextSlide]).find('video').get(0);\n if (nextVideo) {\n loadVideoSource(nextVideo);\n videoPlayback.play(nextVideo).then(function () {\n togglePlayPauseButton(nextVideo);\n });\n }\n });\n\n // Fonction pour g\u00e9rer l'arr\u00eat de l'animation en fonction des cookies (accessibility_mode_animation)\n function isStoppedAnimationInCookies() {\n let isAnimationMode = $.mage.cookies.get('accessibility_mode_animation') === \"true\";\n if (isAnimationMode) {\n $('.video-wrapper video').each(function () {\n videoPlayback.pause(this);\n $(this).closest('.pagebuilder-video-wrapper').find('.video-play-button')\n .removeClass('play-on')\n .addClass('play-off')\n .attr('aria-label', 'Play');\n });\n }\n }\n\n // Fonction pour r\u00e9duire l'animation (sur \u00e9v\u00e9nement custom)\n function reduceAnimation() {\
2n document.addEventListener(\"reductAnimation\", (event) => {\n if (event.detail.animation === true) {\n $('.video-wrapper video').each(function () {\n videoPlayback.pause(this);\n $(this).closest('.pagebuilder-video-wrapper').find('.video-play-button')\n .removeClass('play-on')\n .addClass('play-off')\n .attr('aria-label', 'Play');\n });\n } else {\n $('.video-wrapper video').each(function () {\n videoPlayback.play(this);\n $(this).closest('.pagebuilder-video-wrapper').find('.video-play-button')\n .removeClass('play-off')\n .addClass('play-on')\n .attr('aria-label', 'Pause');\n });\n }\n });\n }\n\n // Appel initial pour v\u00e9rifier le mode d'animation\n isStoppedAnimationInCookies();\n\n // \u00c9coute les \u00e9v\u00e9nements de r\u00e9duction d'animation\n reduceAnimation();\n\n // G\u00e9rer les \u00e9v\u00e9nements de progression de la vid\u00e9o\n $('.video-wrapper video').each(function () {\n var video = $(this)[0];\n // var progressBar = $(this).siblings('.progress-container').find('.progress-bar');\n\n // Met \u00e0 jour la barre de progression pendant la lecture\n // video.addEventListener('play', function () {\n // requestAnimationFrame(function () {\n // updateProgressBar(video, progressBar);\n // });\n // });\n\n // R\u00e9initialise la barre de progression au d\u00e9but de la vid\u00e9o\n // video.addEventListener('started', function () {\n // progressBar.css('width', '0%');\n // });\n\n // Met \u00e0 jour le bouton Play/Pause \u00e0 la fin de la vid\u00e9o\n video.addEventListener('ended', function () {\n $(video).parent().find('.video-play-button')\n .removeClass('play-on')\n .addClass('play-off')\n .attr('aria-label', 'Play');\n });\n });\n\n // Barre de progression pour les vid\u00e9os\n // function updateProgressBar(video, progressBar) {\n // if (video.duration) {\n // var percentage = (video.currentTime / video.duration) * 100;\n // progressBar.css('width', percentage + '%');\n // }\n\n // if (!video.paused && !video.ended) {\n // requestAnimationFrame(function () {\n // updateProgressBar(video, progressBar);\n // });\n // }\n // }\n });\n }\n }\n return videoWearing;\n});\n","Goyard_Catalog/js/product_page/change_art_of_marquage.js":"define('Goyard_Catalog/js/product_page/change_art_of_marquage', [\n 'jquery',\n 'mage/url'\n], function ($, urlBuilder) {\n 'use strict';\n\n const urlArtOfMarquage = urlBuilder.build('goyard_catalog/ajax/artOfMarquage');\n\n return {\n init: function () {\n document.addEventListener('swatchOptionClicked', (event) => {\n const productSku = event.detail.optionSku;\n this.changeArtOfMarquage(productSku);\n });\n },\n\n changeArtOfMarquage: function (productSku) {\n $('#product_artOfMarquage').addClass('ajax-refresh');\n this.ajaxArtOfMarquage(productSku);\n },\n\n ajaxArtOfMarquage: function (productSku) {\n $.ajax({\n url: urlArtOfMarquage,\n type: 'GET',\n cache: true,\n timeout: 10000,\n data: {\n 'sku': productSku\n },\n dataType: 'json',\n success: function (response) {\n $('#product_artOfMarquage').replaceWith(response.html);\n $('#product_artOfMarquage').removeClass('ajax-refresh');\n },\n error: function (xhr, status, error) {\n console.error(error);\n }\n });\n }\n };\n});\n\n// Appel de l'initialisation imm\u00e9diatement apr\u00e8s la d\u00e9finition du module\nrequire(['Goyard_Catalog/js/product_page/change_art_of_marquage'], function (changeArtOfMarquage) {\n changeArtOfMarquage.init(
2);\n});\n","Magento_ReCaptchaCheckout/js/webapiReCaptchaRegistry-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n return function (originalFunction) {\n /**\n * {@inheritDoc}\n */\n originalFunction.addListener = function (id , func) {\n this._listeners[id] = func;\n };\n\n return originalFunction;\n };\n\n});\n","Magento_ReCaptchaCheckout/js/reCaptchaCheckout.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(\n [\n 'Magento_ReCaptchaWebapiUi/js/webapiReCaptcha',\n 'jquery'\n ],\n function (Component, $) {\n 'use strict';\n\n var reCaptchaIds = new WeakMap(),\n uuid = 0;\n\n return Component.extend({\n defaults: {\n template: 'Magento_ReCaptchaCheckout/reCaptcha',\n skipPayments: [] // List of payment methods that do not require this reCaptcha\n },\n\n /**\n * Render reCAPTCHA for payment method\n *\n * @param {Object} method\n */\n renderReCaptchaFor: function (method) {\n var reCaptcha;\n\n if (this.isCheckoutReCaptchaRequiredFor(method)) {\n reCaptcha = $.extend(true, {}, this, {reCaptchaId: this.getReCaptchaIdFor(method)});\n reCaptcha.renderReCaptcha();\n }\n },\n\n /**\n * Get reCAPTCHA ID for payment method\n *\n * @param {Object} method\n * @returns {String}\n */\n getReCaptchaIdFor: function (method) {\n if (!reCaptchaIds.has(method)) {\n reCaptchaIds.set(method, this.getReCaptchaId() + '-' + uuid++);\n }\n return reCaptchaIds.get(method);\n },\n\n /**\n * Check whether checkout reCAPTCHA is required for payment method\n *\n * @param {Object} method\n * @returns {Boolean}\n */\n isCheckoutReCaptchaRequiredFor: function (method) {\n return !this.skipPayments || !this.skipPayments.hasOwnProperty(method.getCode());\n },\n\n /**\n * @inheritdoc\n */\n initCaptcha: function () {\n var $wrapper,\n $recaptchaResponseInput;\n\n this._super();\n // Since there will be multiple reCaptcha in the payment form,\n // they may override each other if the form data is serialized and submitted.\n // Instead, the reCaptcha response will be collected in the callback: reCaptchaCallback()\n // and sent in the request header X-ReCaptcha\n $wrapper = $('#' + this.getReCaptchaId() + '-wrapper');\n $recaptchaResponseInput = $wrapper.find('[name=g-recaptcha-response]');\n if ($recaptchaResponseInput.length) {\n $recaptchaResponseInput.prop('disabled', true);\n }\n }\n });\n }\n);\n","Magento_ReCaptchaCheckout/js/model/place-order-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable max-nested-callbacks */\n\ndefine([\n 'jquery',\n 'mage/utils/wrapper',\n 'Magento_ReCaptchaWebapiUi/js/webapiReCaptchaRegistry'\n], function ($, wrapper, recaptchaRegistry) {\n 'use strict';\n\n return function (placeOrder) {\n return wrapper.wrap(placeOrder, function (originalAction, serviceUrl, payload, messageContainer) {\n var recaptchaDeferred,\n reCaptchaId,\n $activeReCaptcha;\n\n $activeReCaptcha = $('.recaptcha-checkout-place-order:visible .g-recaptcha');\n\n if ($activeReCaptcha.length > 0) {\n reCaptchaId = $activeReCaptcha.last().attr('id');\n }\n\n if (reCaptchaId !== undefined && recaptchaRegistry.triggers.hasOwnProperty(reCaptchaId)) {\n //ReCaptcha is present for checkout\n recaptchaDeferred = $.Deferred();\n recaptchaRegistry.addListener(reCaptchaId, function (token) {\n //Add reCaptcha value to place-order request and resolve deferred with the API call results\n payload.xReCaptchaValue = token;\n originalAction(serviceUrl, payload, messageContainer).done(function () {\n recaptchaDeferred.resolve.apply(recaptchaDeferred, arguments);\n }).fail(function () {\n recaptchaDeferred.reject.apply(recaptchaDeferred, arguments);\n });\n });\n //Trigger ReCaptcha validation\n recaptchaRegistry.triggers[reCaptchaId]();\n\n if (\n !recaptchaRegistry._isInvisibleType.hasOwnProperty(reCaptchaId) ||\n recaptchaRegistry._isInvisibleType[reCaptchaId] === false\n ) {\n //remove listener so that place order action is only triggered by the 'Place Order' button\n recaptchaRegistry.removeListener(reCaptchaId);\n }\n\n return recaptchaDeferred;\n }\n\n //No ReCaptcha, just sending the request\n return originalAction(serviceUrl, payload, messageContainer);\n });\n };\n});\n","Dnd_Core/js/panel.js":"/**\n * @package Dnd\\Core\\view\n * @author Agence Dn'D <[email protected]>\n * @copyright 2004-present Agence Dn'D\n * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)\n * @link https://www.dnd.fr/\n */\n\ndefine([\n 'jquery',\n 'dnd/core/utils/dom-parser',\n 'jquery/ui',\n 'domReady!',\n], function($, DomParser) {\n 'use strict';\n\n $.widget('dnd.corePanel', {\n options: {\n closeAll: true,\n openFirst: true,\n onlyOneOpened: true,\n eventPanelTrigger: 'click',\n triggerSelector: '[data-role=dnd-panel-tr
2igger]',\n contentSelector: '[data-role=dnd-panel-content]',\n iconSelector: '[data-role=dnd-panel-icon]',\n iconPanelOpenedClass: 'icon-angle-up',\n iconPanelClosedClass: 'icon-angle-down',\n activeClass: 'open',\n stateDataKey: 'state',\n indexDataKey: 'panel-index',\n openedStateValue: 'opened',\n closedStateValue: 'closed',\n eventSelector: 'body',\n },\n privateOptions: {\n eventPanelOpen: 'dndCorePanel:open',\n eventPanelClose: 'dndCorePanel:close',\n },\n defaultIndex: 0,\n currentIndex: 0,\n /**\n * Plugin init function\n *\n * @private\n */\n _create: function() {\n this._applyStates();\n this._initializeEvents();\n\n if (this.options.closeAll) {\n this._closeAll();\n }\n if (this.options.openFirst) {\n this._openFirst();\n }\n\n },\n /**\n * Initialize all events\n *\n * @private\n */\n _initializeEvents: function() {\n $(this.options.eventSelector).\n on(this.options.eventPanelTrigger, this.options.triggerSelector,\n $.proxy(this._triggerPanel, this));\n $(this.options.eventSelector).\n on(this.privateOptions.eventPanelOpen,\n $.proxy(this._togglePanelOpenedClass, this));\n $(this.options.eventSelector).\n on(this.privateOptions.eventPanelClose,\n $.proxy(this._togglePanelClosedClass, this));\n $(this.options.eventSelector).\n on(this.privateOptions.eventPanelOpen,\n $.proxy(this._togglePanelOpenedIconClass, this));\n $(this.options.eventSelector).\n on(this.privateOptions.eventPanelClose,\n $.proxy(this._togglePanelClosedIconClass, this));\n $(this.options.eventSelector).\n on(this.privateOptions.eventPanelOpen,\n $.proxy(this._togglePanelOpenedState, this));\n $(this.options.eventSelector).\n on(this.privateOptions.eventPanelClose,\n $.proxy(this._togglePanelClosedState, this));\n $(this.options.eventSelector).\n on(this.privateOptions.eventPanelOpen,\n $.proxy(this._togglePanelOpenedState, this));\n },\n /**\n * @private\n */\n _applyStates: function() {\n var triggers = this._getTriggers();\n var self = this;\n var index = this.defaultIndex;\n\n triggers.map(function(index, trigger) {\n trigger = $(trigger);\n var content = self._getPanelContent(trigger);\n if (self._isContentVisible(content)) {\n self._applyOpenedState(trigger);\n self._applyOpenedState(content);\n } else {\n self._applyClosedState(trigger);\n self._applyClosedState(content);\n }\n\n self._applyIndex(trigger, index++);\n });\n },\n /**\n * @param element\n * @private\n */\n _applyIndex: function(element, index) {\n element.attr('data-' + this.options.indexDataKey, index);\n element.data(this.options.indexDataKey, index);\n },\n /**\n * @param element\n * @private\n */\n _setCurrentIndex: function(event) {\n var panelTrigger = $(event.currentTarget);\n var index = this._getElementIndex(panelTrigger);\n\n this.currentIndex = index;\n },\n /**\n * @returns {number}\n */\n getCurrentIndex: function() {\n return this.currentIndex;\n },\n /**\n * @param panelTrigger\n */\n getNextPanel: function(panelTrigger) {\n var index = this._getElementIndex(panelTrigger);\n var nextIndex = ++index;\n var nextPanel = DomParser.getNextElement(\n '[data-' + this.options.indexDataKey + '=' + nextIndex + ']',\n panelTrigger);\n\n return nextPanel;\n },\n /**\n * @param element\n * @private\n */\n _applyOpenedState: function(element) {\n element.attr('data-' + this.options.stateDataKey,\n this.options.openedStateValue);\n element.data(this.options.stateDataKey, this.options.openedStateValue);\n },\n /**\n * @param element\n * @private\n */\n _applyClosedState: function(element) {\n element.attr('data-' + this.options.stateDataKey,\n this.options.closedStateValue);\n element.data(this.options.stateDataKey, this.options.closedStateValue);\n },\n /**\n * @private\n */\n _openFirst: function() {\
2n var triggers = this._getTriggers();\n var trigger = triggers.first();\n\n this._closeAll();\n\n // Hack to requeue the openPanel at the end of the execution queue : https://stackoverflow.com/a/779785/3853370\n // Helps to trigger the event properly\n setTimeout(function() {\n this.openPanel(trigger);\n }.bind(this));\n },\n /**\n * @private\n */\n _closeAll: function() {\n var triggers = this._getTriggers();\n var self = this;\n\n triggers.map(function(index, trigger) {\n trigger = $(trigger);\n self.closePanel(trigger);\n });\n },\n /**\n * Trigger panel\n *\n * @param event\n * @private\n */\n _triggerPanel: function(event) {\n var panelTrigger = $(event.currentTarget);\n\n if (this._isStateOpened(panelTrigger)) {\n this.closePanel(panelTrigger);\n } else {\n this.openPanel(panelTrigger);\n }\n },\n /**\n * @param panelTrigger\n */\n openPanel: function(panelTrigger) {\n var panelContent = this._getPanelContent(panelTrigger);\n\n if (this.options.onlyOneOpened) {\n this._closeAll();\n }\n\n this._openContent(panelContent);\n this._dispatchOpenEvent(panelTrigger, panelContent);\n },\n /**\n * @param panelTrigger\n */\n closePanel: function(panelTrigger) {\n var panelContent = this._getPanelContent(panelTrigger);\n\n this._closeContent(panelContent);\n this._dispatchCloseEvent(panelTrigger, panelContent);\n },\n /**\n * @param panelContent\n * @private\n */\n _openContent: function(panelContent) {\n panelContent.show();\n },\n /**\n * @param panelContent\n * @private\n */\n _closeContent: function(panelContent) {\n panelContent.hide();\n },\n /**\n * Add class to trigger when panel is opened\n *\n * @param event\n * @private\n */\n _togglePanelOpenedClass: function(event) {\n var panelTrigger = $(event.currentTrigger);\n\n panelTrigger.addClass(this.options.activeClass);\n },\n /**\n * Remove class to trigger when panel is closed\n *\n * @param event\n * @private\n */\n _togglePanelClosedClass: function(event) {\n var panelTrigger = $(event.currentTrigger);\n\n panelTrigger.removeClass(this.options.activeClass);\n },\n /**\n * Apply opened state to trigger when panel is opened\n *\n * @param event\n * @private\n */\n _togglePanelOpenedState: function(event) {\n var panelTrigger = $(event.currentTrigger);\n var panelContent = this._getPanelContent(panelTrigger);\n\n this._applyOpenedState(panelTrigger);\n this._applyOpenedState(panelContent);\n },\n /**\n * Apply closed state to trigger when panel is closed\n *\n * @param event\n * @private\n */\n _togglePanelClosedState: function(event) {\n var panelTrigger = $(event.currentTrigger);\n var panelContent = this._getPanelContent(panelTrigger);\n\n this._applyClosedState(panelTrigger);\n this._applyClosedState(panelContent);\n },\n /**\n * Add class to icon when panel is opened\n *\n * @param event\n * @private\n */\n _togglePanelOpenedIconClass: function(event) {\n var panelTrigger = $(event.currentTrigger);\n var panelIcon = this._getPanelIcon(panelTrigger);\n\n panelIcon.addClass(this.options.iconPanelOpenedClass).\n removeClass(this.options.iconPanelClosedClass);\n },\n /**\n * Remove class to icon when panel is closed\n *\n * @param event\n * @private\n */\n _togglePanelClosedIconClass: function(event) {\n var panelTrigger = $(event.currentTrigger);\n var panelIcon = this._getPanelIcon(panelTrigger);\n\n panelIcon.addClass(this.options.iconPanelClosedClass).\n removeClass(this.options.iconPanelOpenedClass);\n },\n /**\n * Dispatch event when panel opened\n *\n * @param trigger\n * @param content\n * @private\n */\n _dispatchOpenEvent: function(trigger,
2content) {\n var eventName = this.privateOptions.eventPanelOpen;\n var isOpened = this._isStateOpened(trigger);\n var self = this;\n\n $(this.options.eventSelector).trigger({\n type: eventName,\n currentClass: self,\n currentTrigger: trigger,\n currentContent: content,\n isOpened: isOpened,\n });\n },\n /**\n * Dispatch event when panel closed\n *\n * @param trigger\n * @param content\n * @private\n */\n _dispatchCloseEvent: function(trigger, content) {\n var eventName = this.privateOptions.eventPanelClose;\n var isOpened = this._isStateOpened(trigger);\n var self = this;\n\n $(this.options.eventSelector).trigger({\n type: eventName,\n currentClass: self,\n currentTrigger: trigger,\n currentContent: content,\n isOpened: isOpened,\n });\n },\n /**\n * @param content\n * @private\n */\n _isContentVisible: function(content) {\n return content.is(':visible');\n },\n /**\n * @param element\n * @returns {boolean}\n * @private\n */\n _isStateOpened: function(element) {\n if (this._getElementState(element) == this.options.openedStateValue) {\n return true;\n }\n\n return false;\n },\n /**\n * @param element\n * @returns {*}\n * @private\n */\n _getElementState: function(element) {\n return element.data(this.options.stateDataKey);\n },\n /**\n * @param element\n * @returns {*}\n * @private\n */\n _getElementIndex: function(element) {\n return element.data(this.options.indexDataKey);\n },\n /**\n * @returns {*|jQuery|HTMLElement}\n * @private\n */\n _getTriggers: function() {\n return $(this.options.triggerSelector);\n },\n /**\n * @param panelTrigger\n * @private\n */\n _getPanelContent: function(panelTrigger) {\n return panelTrigger.next(this.options.contentSelector);\n },\n /**\n * @param panelTrigger\n * @private\n */\n _getPanelIcon: function(panelTrigger) {\n return panelTrigger.find(this.options.iconSelector);\n },\n });\n\n return $.dnd.corePanel;\n});\n","Dnd_Core/js/utils/dom-parser.js":"/**\n * @package Dnd\\Core\\view\n * @author Agence Dn'D <[email protected]>\n * @copyright 2004-present Agence Dn'D\n * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)\n * @link https://www.dnd.fr/\n */\n\ndefine([\n 'jquery',\n], function($) {\n 'use strict';\n\n return {\n /**\n * @param _selector\n * @param _subject\n * @returns {*}\n */\n getNextElement: function(_selector, _subject) {\n var next = this._next(_subject);\n while (next.length != 0) {\n var found = this._searchFor(_selector, next);\n if (found != null) {\n return found;\n }\n next = this._next(next);\n }\n\n return null;\n },\n /**\n * @param _subject\n * @returns {*}\n * @private\n */\n _next: function(_subject) {\n if (_subject.next().length > 0) {\n return _subject.next();\n }\n\n return this._next(_subject.parent());\n },\n /**\n * @param _selector\n * @param _subject\n * @returns {*}\n * @private\n */\n _searchFor: function(_selector, _subject) {\n if (_subject.is(_selector)) {\n return _subject;\n }\n\n var found = null;\n var self = this;\n _subject.children().each(function() {\n found = self._searchFor(_selector, $(this));\n if (found != null) {\n return false;\n }\n });\n\n return found;\n },\n };\n});\n","Dnd_Core/js/utils/main.js":"/**\n * @package Dnd\\Core\\view\n * @author Agence Dn'D <[email protected]>\n * @copyright 2004-present Agence Dn'D\n * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)\n * @link https://www.dnd.fr/\n */\n\ndefine(function(require) {\n 'use strict';\n\n var utils = {},\n _ = require('underscore');\n\n return _.extend(\n utils,\n require('./dom-parser'),\n );\n});\n","Amasty_InvisibleCaptcha/js/model/am-recaptcha.js":"/**\n * reCaptcha model\n */\n\ndefine([\n 'ko',\n 'underscore'\n], function (ko, _) {\n 'use strict';\n\n return {\n onLoadCallback: 'amInvisibleCaptchaOnloadCallback',\n isEnabledOnPayments: false,\n isScriptLoaded: false,\n tokenFields: [],\n url: 'https://www.google.com/recaptcha/api.js',\n isCaptchaAppended: false,\n checkoutRecaptchaValidateUrl: null,\n invisibleCaptchaCustomForm: false,\n isValidationPassed: ko.observable(false),\n recaptchaConfig: {\
2n lang: 'hl=en',\n size: 'invisible'\n },\n formToProtect: '',\n reCaptchaErrorMessage: 'Prove you are not a robot',\n recaptchaVersion: null,\n isInvisible: null,\n\n setConfig: function (config) {\n if (_.has(config, 'recaptchaConfig')) {\n this.setRecaptchaConfig(config.recaptchaConfig);\n }\n\n if (_.has(config, 'formsToProtect')) {\n this.setFormsList(config.formsToProtect);\n }\n\n this.checkoutRecaptchaValidateUrl = config.checkoutRecaptchaValidateUrl;\n this.invisibleCaptchaCustomForm = config.invisibleCaptchaCustomForm;\n this.isEnabledOnPayments = !!config.isEnabledOnPayments;\n this.reCaptchaErrorMessage = config.reCaptchaErrorMessage;\n this.recaptchaVersion = config.recaptchaVersion;\n },\n\n setRecaptchaConfig: function (config) {\n _.extend(this.recaptchaConfig, config);\n },\n\n getRecaptchaConfig: function () {\n return this.recaptchaConfig;\n },\n\n setFormsList: function (formsList) {\n this.formToProtect = formsList;\n },\n\n getFormsList: function () {\n return this.formToProtect;\n }\n };\n});\n","Amasty_InvisibleCaptcha/js/action/am-recaptcha-validate.js":"/**\n * Ajax actions\n * @api\n */\n\ndefine([\n 'jquery',\n 'underscore',\n 'Amasty_InvisibleCaptcha/js/model/am-recaptcha',\n], function ($, _, amReCaptchaModel) {\n 'use strict';\n\n return {\n options : {\n reCaptchaSelector: 'am-recaptcha-block',\n reCaptchaErrorSelector: 'recaptcha-error',\n reCaptchaErrorMessageSelector: '.recaptcha-error-message'\n },\n\n /**\n * Ajax call\n * @param {Element} tokenField\n * @param {String} token\n * @returns {Deferred}\n */\n validateCaptcha: function (tokenField, token) {\n this.showErrorMessage(false);\n return $.ajax({\n url: amReCaptchaModel.checkoutRecaptchaValidateUrl,\n data: {\n 'g-recaptcha-response': token\n },\n type: 'POST'\n });\n },\n\n showErrorMessage: function (show) {\n var amReCaptchaBlock = $('.payment-method._active').find('#' + this.options.reCaptchaSelector);\n\n if (show) {\n amReCaptchaBlock.addClass(this.options.reCaptchaErrorSelector);\n if (!amReCaptchaBlock.find(this.options.reCaptchaErrorMessageSelector).length > 0) {\n amReCaptchaBlock.append($('<div class=\"recaptcha-error-message\">').html(this.getErrorMessage()));\n }\n amReCaptchaBlock.find(this.options.reCaptchaErrorMessageSelector).show();\n } else {\n amReCaptchaBlock.removeClass(this.options.reCaptchaErrorSelector);\n amReCaptchaBlock.find(this.options.reCaptchaErrorMessageSelector).hide();\n }\n },\n\n getErrorMessage: function () {\n return amReCaptchaModel.reCaptchaErrorMessage;\n }\n };\n});\n","Amasty_InvisibleCaptcha/js/action/am-recaptcha-loader.js":"/**\n * reCaptcha API loader\n */\n\ndefine([\n 'Amasty_InvisibleCaptcha/js/model/am-recaptcha'\n], function (amReCaptchaModel) {\n 'use strict';\n\n return {\n /**\n * Add script tag.\n * @returns {void}\n */\n addReCaptchaScript: function () {\n var element,\n scriptTag;\n\n if (amReCaptchaModel.isScriptLoaded) {\n return;\n }\n\n scriptTag = document.getElementsByTagName('body')[0];\n element = document.createElement('script');\n element.async = true;\n element.src = this.getUrl();\n scriptTag.append(element);\n amReCaptchaModel.isScriptLoaded = true;\n },\n\n /**\n * Build url for captcha loading\n * @returns {string}\n */\n getUrl: function () {\n return amReCaptchaModel.url + '?onload=' + amReCaptchaModel.onLoadCallback\n + '&render=explicit' + this.getLang();\n },\n\n getLang: function () {\n return amReCaptchaModel.recaptchaConfig.lang ? '&' + amReCaptchaModel.recaptchaConfig.lang : '';\n }\n };\n});\n","Amasty_InvisibleCaptcha/js/action/am-recaptcha-configure.js":"define([\n 'Amasty_InvisibleCaptcha/js/model/am-recaptcha'\n], function (amReCaptchaModel) {\n 'use strict';\n\n return function (config) {\n amReCaptchaModel.setConfig(config);\n }\n});\n","Amasty_InvisibleCaptcha/js/view/am-recaptcha-payment.js":"define([\n 'jquery',\n 'underscore',\n 'mageUtils',\n 'Amasty_InvisibleCaptcha/js/view/am-recaptcha-abstract',\n 'Amasty_InvisibleCaptcha/js/model/am-recaptcha',\n 'Amasty_InvisibleCaptcha/js/action/am-recaptcha-validate',\n 'Magento_Ui/js/model/messageList',\n \"mage/translate\"\n], function (\n $,\n _,\n utils,\n Component,\n amReCaptchaModel,\n recaptchaValidate,\n messageList\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Amasty_InvisibleCaptcha/payment-recaptcha-container',\n isEnabledOnPayments: amReCaptchaModel.isEnabledOnPayments\n },\n\n renderReCaptcha: function (element) {\n if (window.grecaptcha && window.grecaptcha.render) {\n this.appendCaptcha();\n this.initCaptcha(element);\n } else {\n $(window).on('amcaptchaReady', function () {\n this.appendCaptcha();\n this.initCaptcha(element);\n }.bind(this));\n\n this.loadApi();\n }\n },\n\n getPaymentName: function (element) {\n var $element = $(element),\n // eslint-disable-next-line max-len\n paymentMethodField = $element.closest('.payment-method').find('.payment-method-title > input[type=\"radio\"]');\n\n return paymentMethodField.length ? paymentMethodField.val() : '';\n },\n\n /**\n * Init captcha on each payment method\n * @param {Element} element\n * @return {void}\n */\n initCaptcha: function (element) {\n var $element = $(element),\n widgetId,\n listeners,\n id = utils.uniqueid(),\n $button = $element.closest('.payment-method-content').find('button[type=\"submit\"]'),\n messagesContainer = $element.closest('.am-recaptcha-container').find('.messages-container'),\n paymentName = this.getPaymentName(element),\n $recaptchaBlock = $('<div>', {'id': recaptchaValidate.options.reCaptchaSelector})\n\n $(messagesContainer).attr('id', 'message-' + id);\n $element.attr('id', id);\n\n if (!$button.length) {\n $button = $('<button type=\"button\" class=\"hidden\" data-payment-name=\"' + paymentName + '\"></button>');\n\n $button.insertAfter($element);\n }\n\n $button.before($recaptchaBlock);\n widgetId = window.grecaptcha.render($recaptchaBlock[0], this.getParameters($element, $button));\n $recaptchaBlock.append(\n $('<div class=\"recaptcha-error-message\">').html(recaptchaValidate.getErrorMessage()).hide()\n );\n\n $button.click(function (event, data) {\n // Reset captcha in case of resubmitting the form\n if (this.needResetCaptcha(data)) {\n this.resetCaptcha();\n $element.val('');\n }\n\n if (!$element.val()) {\n event.preventDefault(event);\n event.stopImmediatePropagation();\n\n if (amReCaptchaModel.getRecaptchaConfig().isInvisible) {\n $(event.currentTarget).prop('disabled', true);\n window.grecaptcha.execute(widgetId);\n } else {\n recaptchaValidate.showErrorMessage(true);\n }\n } else {\n this.setIsCaptchaValidationPassed(true);\n }\n }.bind(this));\n\n listeners = $._data($button[0], 'events').click;\n listeners.unshift(listeners.pop());\n\n amReCaptchaModel.tokenFields.push($element);\n },\n\n /**\n * Need Reset Invisible Captcha\n * @param {Object} data\n * @return {Boolean}
2\n */\n needResetCaptcha: function (data) {\n return data?.disableCaptchaReset !== true\n && amReCaptchaModel.getRecaptchaConfig().isInvisible\n && amReCaptchaModel.getRecaptchaConfig().recaptchaVersion === 3;\n },\n\n /**\n * Get captcha parameters\n * @param {Element} tokenField\n * @param {Element} element\n * @return {Object}\n */\n getParameters: function (tokenField, element) {\n return _.extend(amReCaptchaModel.getRecaptchaConfig(), {\n 'callback': function (token) {\n recaptchaValidate.validateCaptcha(tokenField, token)\n .done(function (response) {\n var $element = $(element),\n isPlaceOrder = $element.prop('disabled');\n\n $element.prop('disabled', false);\n\n if (_.has(response, 'error') && response.error) {\n this.resetCaptcha();\n this.setIsCaptchaValidationPassed(false);\n this.handleTokenError($(tokenField).attr('id'), response.message);\n\n messageList.addErrorMessage({ message: response.message });\n } else {\n this.setIsCaptchaValidationPassed(true);\n recaptchaValidate.showErrorMessage(false);\n $(tokenField).val(token);\n\n if (!$(element).hasClass('hidden') && isPlaceOrder) {\n $element.trigger('click', [{ disableCaptchaReset: true }]);\n }\n }\n }.bind(this));\n }.bind(this),\n 'expired-callback': this.resetCaptcha\n });\n },\n\n handleTokenError: function (tokenFieldId, message) {\n var container = $('#message-' + tokenFieldId),\n messageBlock = container.find('.message');\n\n messageBlock.html(message);\n container.show(0).delay(5000).hide('fast', function () {\n messageBlock.html('');\n });\n }\n });\n});\n","Amasty_InvisibleCaptcha/js/view/am-recaptcha.js":"define([\n 'jquery',\n 'ko',\n 'underscore',\n 'mageUtils',\n 'Amasty_InvisibleCaptcha/js/view/am-recaptcha-abstract',\n 'Amasty_InvisibleCaptcha/js/model/am-recaptcha',\n 'mage/loader',\n 'domReady!'\n], function (\n $,\n ko,\n _,\n utils,\n Component,\n amReCaptchaModel\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n formsToProtect: '',\n captchaElementClass: 'am-recaptcha-block'\n },\n\n /**\n * @inheritDoc\n * @returns {Object}\n */\n initObservable: function () {\n this._super();\n\n this.formsToProtect = $(amReCaptchaModel.getFormsList());\n this.renderCaptcha();\n\n return this;\n },\n\n /**\n * @returns {void}\n */\n renderCaptcha: function () {\n $(window).on('amcaptchaReady', this.initFormHandler.bind(this));\n\n // eslint-disable-next-line consistent-return\n _.debounce(function () {\n this._addListeners();\n\n this.formsToProtect.on('submit', function (event) {\n const form = $(event.currentTarget);\n\n window.dispatchEvent(new CustomEvent('am-recaptcha-submit-event', {\n detail: {\n form: form\n }\n }));\n\n if (amReCaptchaModel.isScriptLoaded && !!event.target.dataset?.amCaptchaObserved) {\n form.off('submit:beforeSubmit');\n\n return;\n }\n\n event.preventDefault();\n event.stopImmediatePropagation();\n\n form.trigger('submit:beforeSubmit');\n });\n\n this._eventOrderChange();\n this._enableSubmitButtons();\n }.bind(this), 200)();\n },\n\n _enableSubmitButtons: function (forms) {\n if (typeof forms === 'undefined') {\n forms = this.formsToProtect;\n }\n\n forms.find('[am-captcha-protect=true]').removeAttr('disabled');\n },\n\n _addListeners: function () {\n this.formsToProtect.on('submit:beforeSubmit', function (event) {\n this.cachedForm = $(event.target);\n event.target.dataset.amCaptchaObserved = 1;\n\n if (amReCaptchaModel.isScriptLoaded) {\n $(window).trigger('amcaptchaReady');\n return;\n }\n\n this.loadApi();\n }.bind(this));\n },\n\n /**\n * @private\n * @returns {void}\n */\n _eventOrderChange: function () {\n _.each(this.formsToProtect, function (form) {\n var $form = $(form);\n\n $form.data('recaptchaFormId', utils.uniqueid());\n\n if (+amReCaptchaModel.invisibleCaptchaCustomForm) {\n this._swapSubmit($form);\n }\n }.bind(this));\n },\n\n /**\n * @param {Element} form\n * @private\n * @returns {void}\n */\n _swapSubmit: function (form) {\n var $form = $(form),\n listeners;\n\n listeners = $._data($form[0], 'events').submit;\n if (listeners) {\n listeners.unshift(listeners.pop());\n }\n },\n\n /**\n * @param {Element} form\n * @returns {Object}\n */\n getParameters: function (form) {\n var $form = $(form);\n\n return _.extend(amReCaptchaModel.getRecaptchaConfig(), {\n 'callback': function () {\n if (this.showLoaderOnCaptchaLoading) {\n $('body').trigger('processStop');\n }\n\n if ($form.valid()) {\n $form.submit();\n }\n }.bind(this),\n 'expired-callback': this.resetCaptcha\n });\n },\n\n /**\n * @returns {void}\n */\n initFormHandler: function () {\n var self = this;\n\n amReCaptchaModel.isScriptLoaded = true;\n this.appendCaptcha();\n _.each(self.formsToProtect, function (form) {\n if (self.cac
2hedForm && self.cachedForm[0] === form) {\n var $form = $(form),\n widgetId = self._initCaptchaOnForm(form);\n\n $form.on('ajaxFormLoaded', function () {\n self._formButtonClickEvent(form, widgetId);\n });\n\n $(document).on('am_form:ajax_complete', function (event, form) {\n self.renderCaptchaOnForm($(form));\n });\n }\n });\n },\n\n /**\n * Render captcha element on form\n *\n * @param {jQuery} $form\n * @param {jQuery|null} $captchaElement\n * @returns {Number}\n */\n renderCaptchaOnForm: function ($form, $captchaElement = null) {\n var $formCaptchaElement = $form.find('.' + this.captchaElementClass);\n\n if ($formCaptchaElement.length) {\n $formCaptchaElement.remove();\n }\n\n if (!$captchaElement) {\n $captchaElement = this.getCaptchaElement();\n }\n\n $form.append($captchaElement);\n\n var widgetId = window.grecaptcha.render($captchaElement[0], this.getParameters($form[0]));\n\n $captchaElement.data('id', widgetId);\n this._formButtonClickEvent($form[0], widgetId);\n\n this._enableSubmitButtons($form);\n\n return widgetId;\n },\n\n /**\n * Get captcha element\n *\n * @returns {jQuery}\n */\n getCaptchaElement: function () {\n return $('<div class=\"' + this.captchaElementClass + '\"></div>');\n },\n\n /**\n * Init captcha on form\n * @param {Element} form\n * @returns {String|Number}\n */\n _initCaptchaOnForm: function (form) {\n var $form = $(form),\n widgetId,\n $button = $form.find(\"[type='submit']\"),\n $captchaElement = this.getCaptchaElement();\n\n widgetId = this.renderCaptchaOnForm($form, $captchaElement);\n\n this._submitCachedForm($form, $button);\n\n amReCaptchaModel.tokenFields.push($captchaElement);\n\n return widgetId;\n },\n\n /**\n *\n * @param {Element} $form\n * @param {Element} $button\n * @private\n * @returns {void}\n */\n _submitCachedForm: function ($form, $button) {\n if ($button.length && this.cachedForm\n && this.cachedForm.data('recaptchaFormId') === $form.data('recaptchaFormId')) {\n if (this.showLoaderOnCaptchaLoading) {\n $('body').trigger('processStart');\n }\n\n $button.trigger('click');\n this.cachedForm = null;\n }\n },\n\n /**\n * Add Event to execute recaptcha widget on button click\n * @private\n * @param {Element} form\n * @param {Number} widgetId\n * @returns {void}\n */\n _formButtonClickEvent: function (form, widgetId) {\n var $form = $(form),\n $button = $form.find(\"[type='submit']\"),\n buttonClickListeners = null,\n buttonListeners = {};\n\n if ($button.length) {\n buttonListeners = $._data($button[0], 'events');\n }\n\n if (_.has(buttonListeners, 'click')) {\n buttonClickListeners = _.clone(buttonListeners.click);\n }\n\n $button.off('click').on('click', function (e) {\n e.preventDefault();\n\n if ($form.valid()) {\n $button.prop('disabled', true);\n window.grecaptcha.reset(widgetId);\n if (amReCaptchaModel.getRecaptchaConfig().isInvisible) {\n window.grecaptcha.execute(widgetId);\n }\n }\n\n if (buttonClickListeners) {\n $button.off('click');\n $.each(buttonClickListeners, function (index, event) {\n $button.bind(event.type, event.handler);\n });\n\n buttonClickListeners = null;\n }\n });\n\n this._enableSubmitButtons($form);\n }\n });\n});\n","Amasty_InvisibleCaptcha/js/view/am-recaptcha-abstract.js":"define([\n 'uiComponent',\n 'jquery',\n 'ko',\n 'underscore',\n 'mageUtils',\n 'Amasty_InvisibleCaptcha/js/model/am-recaptcha',\n 'Amasty_InvisibleCaptcha/js/action/am-recaptcha-loader',\n 'mage/loader',\n 'domReady!'\n], function (\n Component,\n $,\n ko,\n _,\n utils,\n amReCaptchaModel,\n amReCaptchaLoader\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n formsToProtect: '',\n showLoaderOnCaptchaLoading: false,\n reCaptchaId: 'am-recaptcha-place-order'\n },\n\n /**\n * Loads reCaptcha API\n * @returns {void}\n */\n loadApi: function () {\n if (!amReCaptchaModel.isScriptLoaded) {\n window[amReCaptchaModel.onLoadCallback] = function () {\n $(window).trigger('amcaptchaReady');\n };\n\n amReCaptchaLoader.addReCaptchaScript();\n }\n },\n\n /**\n * Add captcha\n * @returns {void}\n */\n appendCaptcha: function () {\n if (!amReCaptchaModel.isCaptchaAppended && amReCaptchaModel.getRecaptchaConfig().isInvisible) {\n this.add();\n\n window.grecaptcha.render(this.reCaptchaId, this.getParameters());\n\n amReCaptchaModel.isCaptchaAppended = true;\n }\n },\n\n /**\n * Initialize additional reCaptcha instance.\n * @returns {void}\n */\n add: function () {\n var rendererReCaptcha = $('<div>', {\n 'id': this.reCaptchaId,\n 'class': this.reCaptchaId\n });\n\n $('body').append(rendererReCaptcha);\n },\n\n setIsCaptchaValidationPassed: function (flag) {\n amReCaptchaModel.isValidationPassed(flag);\n amReCaptchaModel.isValidationPassed.valueHasMutated();\n },\n\n /**\n * Reset captcha\n * @returns {void}\n */\n resetCaptcha: function () {\n _.each(amReCaptchaModel.tokenFields, function (tokenBlock) {\n window.grecaptcha.reset(tokenBlock.data('id'));\n });\n\n this.setIsCaptchaValidationPassed(false);\n }\n });\n});\n","Amasty_InvisibleCaptcha/js/view/paypal/in-context/checkout-express-mixin.js":"/**\n * Mixin paypal express checkout\n */\ndefine([\n 'jquery',\n 'underscore',\n 'Amasty_InvisibleCaptcha/js/model/am-recaptcha',\n 'Magento_Checkout/js/model/payment/additional-validators'\n], function ($, _, amReCaptchaModel, additionalValidators) {\n 'use strict';\n\n var mixin = {\n defaults: {\n reCaptchaButton: fal
2se\n },\n isCaptchaValid: false,\n\n /** @inheritDoc */\n initListeners: function (context) {\n this._super(context);\n\n if (amReCaptchaModel.isEnabledOnPayments) {\n $.async('button[data-payment-name=\"' + this.index + '\"]', function (element) {\n this.reCaptchaButton = $(element);\n this.validate();\n }.bind(this));\n\n amReCaptchaModel.isValidationPassed.subscribe(function (data) {\n this.isCaptchaValid = data;\n }.bind(this));\n }\n\n return this;\n },\n\n /** @inheritDoc */\n validate: function (actions) {\n this.actions = actions || this.actions;\n\n if (this.actions) {\n if (amReCaptchaModel.isEnabledOnPayments && !this.isCaptchaValid) {\n this.actions.disable();\n } else {\n additionalValidators.validate(true)\n ? this.actions.enable()\n : this.actions.disable();\n\n }\n }\n },\n\n /**\n * Adding logic to be triggered onClick action for smart buttons component\n * @returns {void}\n */\n onClick: function () {\n var savedCallback = this._super;\n\n if (!this.isCaptchaValid && amReCaptchaModel.isEnabledOnPayments) {\n // eslint-disable-next-line one-var\n var subscribe = amReCaptchaModel.isValidationPassed.subscribe(function (data) {\
2n if (this.actions) {\n if (data) {\n this.actions.enable();\n\n savedCallback.apply(this);\n } else {\n this.actions.disable();\n }\n }\n\n subscribe.dispose();\n }.bind(this));\n\n this.validateCaptcha();\n } else {\n savedCallback.apply(this);\n }\n },\n\n /**\n * Trigger captcha's invisible button\n * @returns {void}\n */\n validateCaptcha: function () {\n if (this.reCaptchaButton.length) {\n this.reCaptchaButton.trigger('click');\n }\n }\n };\n\n return function (ExpressCheckout) {\n return ExpressCheckout.extend(mixin);\n };\n});\n","Goyard_Price/js/price-utils-mixin.js":"define([\n 'jquery',\n 'underscore'\n], function ($, _) {\n 'use strict';\n\n var globalPriceFormat = {\n requiredPrecision: 2,\n integerRequired: 1,\n decimalSymbol
2: ',',\n groupSymbol: ',',\n groupLength: ',',\n vatMention: ''\n }\n\n return function (target) {\n\n target.formatPriceLocale = function formatPriceLocale(amount, format, isShowSign) {\n var s = '',\n result = '',\n defaultThousandSeparator = '',\n precision, pattern, locale, r;\n\n format = _.extend(globalPriceFormat, format);\n if (Number.isInteger(amount)) {\n precision = 0;\n } else {\n precision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision;\n }\n \n if(precision > 0){\n defaultThousandSeparator = ',';\n }\n \n pattern = format.pattern || '%s';\n locale = window.LOCALE || 'en-US';\n if (isShowSign === undefined || isShowSign === true) {\n s = amount < 0 ? '-' : isShowSign ? '+' : '';\n } else if (isShowSign === false) {\n s = '';\n }\n pattern = pattern.indexOf('{sign}') < 0 ? s + pattern : pattern.replace('{sign}', s);\n amount = Number(Math.round(Math.abs(+amount || 0) + 'e+' + precision) + ('e-' + precision));\n r = amount.toLocaleString(locale, { minimumFractionDigits: precision });\n \n return pattern.replace('%s', r).replace(/^\\s\\s*/, '').replace(/\\s\\s*$/, '').replace(/[,.\u202f]/g, (format.thousandSeparator ?? defaultThousandSeparator)) + \" \" + format.vatMention;\n };\n\n return target;\n };\n});\n","Magento_Persistent/js/remember-me-config.js":"/**\n * Copyright 2024 Adobe\n * All Rights Reserved.\n */\n\ndefine(\n [\n 'ko',\n 'uiComponent'\n ],\n function (ko, Component) {\n 'use strict';\n\n return Component.extend({\n dataScope: 'global',\n config: {},\n\n /** @inheritdoc */\n initialize: function () {\n this._super();\n\n window.rememberMeConfig = this.config;\n }\n });\n }\n);\n","Magento_Persistent/js/view/customer-data-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'mage/utils/wrapper'\n], function ($, wrapper) {\n 'use strict';\n\n var mixin = {\n\n /**\n * Check if persistent section is expired due to lifetime.\n *\n * @param {Function} originFn - Original method.\n * @return {Array}\n */\n getExpiredSectionNames: function (originFn) {\n var expiredSections = originFn(),\n storage = $.initNamespaceStorage('mage-cache-storage').localStorage,\n currentTimestamp = Math.floor(Date.now() / 1000),\n persistentIndex = expiredSections.indexOf('persistent'),\n persistentLifeTime = 0,\n sectionData;\n\n if (window.persistent !== undefined && window.persistent.expirationLifetime !== undefined) {\n persistentLifeTime = window.persistent.expirationLifetime;\n }\n\n if (persistentIndex !== -1) {\n sectionData = storage.get('persistent');\n\n if (typeof sectionData === 'object' &&\n sectionData['data_id'] + persistentLifeTime >= currentTimestamp\n ) {\n expiredSections.splice(persistentIndex, 1);\n }\n }\n\n return expiredSections;\n },\n\n /**\n * @param {Object} settings\n * @constructor\n */\n 'Magento_Customer/js/customer-data': function (originFn) {\n let mageCacheTimeout = new Date($.localStorage.get('mage-cache-timeout')),\n mageCacheSessId = $.cookieStorage.isSet('mage-cache-sessid');\n\n originFn();\n if (window.persistent !== undefined && (mageCacheTimeout < new Date() || !mageCacheSessId)) {\n this.reload(['persistent','cart'],true);\n }\n }\n };\n\n /**\n * Override default customer-data.getExpiredSectionNames().\n */\n return function (target) {\n return wrapper.extend(target, mixin);\n };\n});\n","Magento_Persistent/js/view/remember-me-default.js":"/**\n * Copyright 2024 Adobe\n * All Rights Reserved.\n */\n\ndefine(\n [\n 'ko',\n 'uiComponent',\n 'Magento_Customer/js/customer-data'\n ],\n function (ko, Component, customerData) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Persistent/remember-me'\n },\n dataScope: 'global',\n isRememberMeCheckboxVisible: ko.observable(false),\n isRememberMeCheckboxChecked: ko.observable(false),\n\n /** @inheritdoc */\n initialize: function () {\n this._super();\n\n this.showElement();\n },\n\n /**\n * Show remember me checkbox on certain conditions\n */\n showElement: function () {\n let cart = customerData.get('cart'),\n persistenceConfig = window.rememberMeConfig.persistenceConfig;\n\n if (cart().isGuestCheckoutAllowed !== false) {\n persistenceConfig.isRememberMeCheckboxVisible = false;\n } else {\n cart.subscribe(function (cartData) {\n if (cartData.isGuestCheckoutAllowed !== false) {\n persistenceConfig.isRememberMeCheckboxVisible = false;\n }\n }, this);\n }\n\n this.isRememberMeCheckboxChecked = ko.observable(persistenceConfig.isRememberMeCheckboxChecked);\n this.isRememberMeCheckboxVisible = ko.observable(persistenceConfig.isRememberMeCheckboxVisible);\n }\n });\n }\n);\n","Magento_Persistent/js/view/additional-welcome.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/translate',\n 'Magento_Customer/js/customer-data'\n], function ($, $t, customerData) {\n 'use strict';\n\n return {\n /**\n * Init.\n */\n init: function () {\n var persistent = customerData.get('persistent');
2\n\n if (persistent().fullname === undefined) {\n customerData.get('persistent').subscribe(this.replacePersistentWelcome);\n } else {\n this.replacePersistentWelcome();\n }\n },\n\n /**\n * Replace welcome message for customer with persistent cookie.\n */\n replacePersistentWelcome: function () {\n var persistent = customerData.get('persistent'),\n welcomeElems;\n\n if (persistent().fullname !== undefined) {\n welcomeElems = $('li.greet.welcome > span.not-logged-in');\n\n if (welcomeElems.length) {\n $(welcomeElems).each(function () {\n var html = $t('Welcome, %1!').replace('%1', persistent().fullname);\n\n $(this).attr('data-bind', html);\n $(this).html(html);\n });\n $(welcomeElems).append(' <span><a ' + window.notYouLink + '>' + $t('Not you?') + '</a>');\n }\n }\n },\n\n /**\n * @constructor\n */\n 'Magento_Persistent/js/view/additional-welcome': function () {\n this.init();\n }\n };\n});\n","Magento_Persistent/js/view/remember-me.js":"/**\n * Copyright 2024 Adobe\n * All Rights Reserved.\n */\n\ndefine(\n [\n 'ko',\n 'uiComponent'\n ],\n function (ko, Component) {\n 'use strict';\n\n let persistenceConfig = window.checkoutConfig.persistenceConfig;\n\n return Component.extend({\n defaults: {\n template: 'Magento_Persistent/remember-me'\n },\n isRememberMeCheckboxVisible: ko.observable(persistenceConfig.isRememberMeCheckboxVisible),\n isRememberMeCheckboxChecked: ko.observable(persistenceConfig.isRememberMeCheckboxChecked)\n });\n }\n);\n","Magento_GiftRegistry/advanced-search.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget'\n], function ($) {\n 'use strict';\n\n $.widget('mage.advancedSearch', {\n options: {\n ajaxSpinnerSelector: '#gr-please-wait',\n ajaxResultSelector: '#gr-type-specific-options',\n ajaxResultContainerSelector: '#gr-type-specific-fieldset'\n },\n\n /**\n * bind handlers\n * @private\n */\n _create: function () {\n this.element.on('change', $.proxy(this._ajaxUpdate, this));\n this.options.selectedOption && this.element.val(this.options.selectedOption).trigger('change');\n },\n\n /**\n * ajax call for search option list\n * @private\n */\n _ajaxUpdate: function () {\n var typeId = this.element.val();\n\n $(this.options.ajaxSpinnerSelector).show();\n\n $.post(this.options.url, {\n 'type_id': typeId\n }
2, $.proxy(function (data) {\n $(this.options.ajaxSpinnerSelector).hide();\n $(this.options.ajaxResultSelector).html(data);\n $(this.options.ajaxResultContainerSelector).toggle(!!typeId);\n $('body').trigger('contentUpdated');\n }, this));\n }\n });\n\n return $.mage.advancedSearch;\n});\n","Magento_GiftRegistry/properties.js":"/**\r\n * Copyright \u00a9 Magento, Inc. All rights reserved.\r\n * See COPYING.txt for license details.\r\n */\r\n\r\ndefine(['jquery'], function ($) {\r\n 'use strict';\r\n\r\n return function (config, element) {\r\n $(element).prop(config);\r\n };\r\n});\r\n","Magento_GiftRegistry/address-option.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/template',\n 'Magento_Ui/js/modal/alert',\n 'jquery-ui-modules/widget',\n 'mage/translate'\n], function ($, mageTemplate, alert) {\n 'use strict';\n\n /**\n * Gift registry multi-ship address option\n */\n $.widget('mage.addressOption', {\n options: {\n addressOptionTmpl: '#address-option-tmpl' // 'Use gift registry shipping address' option.\n },\n\n /**\n * Add the gift registry shipping address option to every gift registry item on the multishipping page.\n * @private\n */\n _create: function () {\n this.addressOptionTmpl = mageTemplate(this.options.addressOptionTmpl);\n\n $.each(this.options.registryItems, $.proxy(this._addAddressOption, this));\n },\n\n /**\n * Add a 'Use gift registry shipping address' option to items on the multishipping page. Bind a change\n * handler on the quantity field of gift registry items to prevent changing the value.\n * @private\n * @param {Number} x - Index value from $.each() - Unused.\n * @param {Object} object - JSON Object - {\"item\": #, \"address\": #}\n */\n _addAddressOption: function (x, object) {\n var _this = this;\n\n this.element.find('select[id^=\"ship_\"]').each(function (y, element) {\n var arr = $(element).attr('id').split('_'),\n selectedIndices = _this.options.selectedAddressIndices,\n selectOption;\n\n if (arr[2] && parseInt(arr[2], 10) === object.item) {\n selectOption = _this.addressOptionTmpl({\n data: {\n _text_: $.mage.__('Use gift registry shipping address'),\n _value_: _this.options.addressItemPrefix + object.address\n }\n });\n\n selectOption = $(selectOption).appendTo(element);\n\n if (selectedIndices.length > 0) {\n _this._setSelected(selectOption, parseInt(arr[1], 10), selectedIndices);\n }\n\n $(element).closest('tr').find('input[type=\"text\"]').on('focus', function (event) {\n $(event.target).trigger('blur');\n alert({\n content: $.mage.__('The only place to change the number of gift registry items is on the Gift Registry Info page or directly in your cart.') //eslint-disable-line max-len\n });\n });\n }\n });\n },\n\n /**\n * Search for the target index and set the selected attribute when there is a match. This will mark\n * the 'Use gift registry shipping address' option as 'selected'.\n * @private\n * @param {Object} option - Select option object.\n * @param {Number} index - The target index value being searched for.\n * @param {Array} indices - An array of indices to iterate through looking for the target.\n */\n _setSelected: function (option, index, indices) {\n var i;\n\n for (i = 0; i < indices.length;
2 i++) {\n if (indices[i] === index) {\n option.prop('selected', true);\n break;\n }\n }\n }\n });\n\n return $.mage.addressOption;\n});\n","Magento_GiftRegistry/gift-registry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'Magento_Theme/js/row-builder',\n 'jquery-ui-modules/widget'\n], function ($, rowBuilder) {\n 'use strict';\n\n /**\n * Extending the rowBuilder widget and adding custom formProcessing for rendering recipients\n */\n $.widget('mage.giftRegistry', rowBuilder, {\n\n options: {\n rowIdPrefix: 'registrant:',\n rowCustomIdPrefix: 'registrant:custom:',\n addrTypeSelector: '#address_type_or_id',\n newShipAddrFormSelector: '#shipping-new-address-form',\n shipAddrDataSelector: 'div[data-shipping-address]',\n shipAddrDataAttr: 'shipping-address',\n newAddrTypeVal: 'new'\n },\n\n /**\n *\n * @private\n */\n _create: function () {\n this._super();\n\n if ($(this.options.shipAddrDataSelector).data(this.options.shipAddrDataAttr)) {\n $(this.options.addrTypeSelector).val(this.options.newAddrTypeVal);\n $(this.options.newShipAddrFormSelector).show();\n }\n this.element.on('change', this.options.addrTypeSelector, $.proxy(this._handleShipAddrChange, this));\n },\n\n /**\n * @override\n * Process and loop through all row data to create preselected values. This is used for any error on submit.\n * For complex implementations the inheriting widget can override this behavior\n * @public\n * @param {Object} formDataArr\n */\n processFormDataArr: function (formDataArr) {\n var formData = formDataArr.formData,\n i;\n\n for (i = this.options.rowIndex = 0; i < formData.length; this.options.rowIndex = i++) {\n this.addRow(i);\n this._processFormDataArrKey(i, formData[i], false);\n }\n\n },\n\n /**\n * Function to recursively process json encoded form data\n * This utility helps in processing formData values which are objects/json themselves\n * @private\n * @param {Number} index - index of the curr row\n * @param {Object}
2 formRow - row object containing field name and value\n * @param {Boolean} isCustom - if the registrant has custom fields\n *\n */\n _processFormDataArrKey: function (index, formRow, isCustom) {\n var idPrefix = isCustom ? this.options.rowCustomIdPrefix : this.options.rowIdPrefix,\n key;\n\n for (key in formRow) {\n if (formRow.hasOwnProperty(key)) {\n if (Object.prototype.toString.call(formRow[key]) === '[object Object]') { //eslint-disable-line\n this._processFormDataArrKey(index, formRow[key], true);\n } else {\n this.setFieldById(idPrefix + key + index, formRow[key]);\n }\n }\n }\n },\n\n /**\n * Function to handle shipping address change\n * @private\n * @param {Object} e - native event object\n */\n _handleShipAddrChange: function (e) {\n $(this.options.newShipAddrFormSelector).toggle(e.target.value === this.options.newAddrTypeVal);\n }\n });\n\n return $.mage.giftRegistry;\n});\n","Magento_GiftRegistry/js/search-by-changed.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['jquery'], function ($) {\n 'use strict';\n\n return function (config, element) {\n $(element).on('change', function (event) {\n event.preventDefault();\n $('form[id^=\"gr-quick-search-widget\"]').hide();\n $('#gr-quick-search-widget-' + this.value + '-form').show();\n });\n };\n});\n","Magento_GiftRegistry/js/model/checkout-data-resolver-ext.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'underscore',\n 'mage/utils/wrapper',\n 'Magento_Checkout/js/checkout-data'\n], function (\n $,\n _,\n wrapper,\n checkoutData\n) {\n 'use strict';\n\n return function (checkoutDataResolver) {\n function isGetShippingAddressDataEmpty() {\n return !checkoutData.getShippingAddressFromData() &&\n window.checkoutConfig.shippingAddressFromData;\n }\n\n function isGiftShippingAddressDataEmpty(giftRegistryShippingAddressData) {\n return !_.isEmpty(giftRegistryShippingAddressData) &&\n giftRegistryShippingAddressData.length !== 0;\n }\n\n checkoutDataResolver.resolveShippingAddress = wrapper.wrapSuper(\n checkoutDataResolver.resolveShippingAddress,\n function () {\n var giftRegistryShippingAddressData = $.extend(\n true,\n {},\n window.checkoutConfig.giftRegistry.giftRegistryShippingAddress\n ),\n addressData = [];\n\n if (!window.checkoutConfig.giftRegistry.available\n || !window.checkoutConfig.giftRegistry.id\n || !window.checkoutConfig.giftRegistry.giftRegistryShippingAddress\n ) {\n return this._super();\n }\n\n $.each(giftRegistryShippingAddressData, function (key, value) {\n if (giftRegistryShippingAddressData.hasOwnProperty(key)\n && !_.isEmpty(value)\n ) {\n if (key === 'street') {\n addressData[key] = Object.assign(\n {},\n value.split('\\n')\n );\n } else {\n addressData[key] = value;\n }\n }\n });\n\n if (isGetShippingAddressDataEmpty() ||\n isGiftShippingAddressDataEmpty(giftRegistryShippingAddressData)\n ) {\n checkoutData.setShippingAddressFromData(addressData);\n }\n this._super();\n });\n\n return checkoutDataResolver;\n };\n});\n","Magento_GiftRegistry/js/model/gift-registry-customer-addresses.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'ko',\n 'Magento_Customer/js/model/customer/address'\n], function ($, ko, Address) {\n 'use strict';\n\n var isLoggedIn = ko.observable(window.isCustomerLoggedIn);\n\n return {\n\n /**\n * Override gift registry addresses on default address list\n *\n * @return {Array}\n */\n getAddressItems: function () {\n var items = [],\n customerData = window.customerData;\n\n if (isLoggedIn()) {\n if (Object.keys(customerData).length) {\n $.each(customerData.addresses, function (key, item) {\n items.push(new Address(item));\n });\n }\n }\n\n return items;\n }\n };\n});\n","Magento_GiftRegistry/js/model/recipient-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n /**\n * @param {Number} registryId\n * @return {Object} new address object\n */\n return function (registryId) {\n return {\n giftRegistryId: registryId,\n\n /**\n * @return {Boolean}\n */\n isDefaultShipping: function () {\n return false;\n },\n\n /**\n * @return {Boolean}\n */\n isDefaultBilling: function () {\n return false;\n },\n\n /**\n * @return {String}\n */\n getType: function () {\n return 'gift-registry';
2\n },\n\n /**\n * @return {String}\n */\n getKey: function () {\n return this.getType() + this.giftRegistryId;\n },\n\n /**\n * @return {String}\n */\n getCacheKey: function () {\n return this.getKey();\n },\n\n /**\n * @return {Boolean}\n */\n isEditable: function () {\n return false;\n },\n\n /**\n * @return {Boolean}\n */\n canUseForBilling: function () {\n return false;\n }\n };\n };\n});\n","Magento_GiftRegistry/js/model/resource-url-manager.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'Magento_Checkout/js/model/resource-url-manager'\n], function ($, resourceUrlManager) {\n 'use strict';\n\n return $.extend(resourceUrlManager, {\n /**\n * @param {Object} quote\n * @return {*|String}\n */\n getUrlForEstimationShippingMethodsForGiftRegistry: function (quote) {\n var params = this.getCheckoutMethod() === 'guest' ? {\n quoteId: quote.getQuoteId()\n } : {},\n urls = {\n 'guest': '/guest-giftregistry/:quoteId/estimate-shipping-methods',\n 'customer': '/giftregistry/mine/estimate-shipping-methods'\n };\n\n return this.getUrl(urls, params);\n }\n });\n});\n","Magento_GiftRegistry/js/model/shipping-save-processor/gift-registry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/resource-url-manager',\n 'mage/storage',\n 'Magento_Checkout/js/model/payment-service',\n 'Magento_Checkout/js/model/error-processor',\n 'Magento_Checkout/js/model/payment/method-converter',\n 'Magento_Checkout/js/model/full-screen-loader'\n], function (quote, resourceUrlManager, storage, paymentService, errorProcessor, methodConverter, fullScreenLoader) {\n 'use strict';\n\n return {\n /**\n * Save shipping information.\n */\n saveShippingInformation: function () {\n var shippingAddress = {},\n payload;\n\n shippingAddress['extension_attributes'] = {\n 'gift_registry_id': quote.shippingAddress().giftRegistryId\n };\n\n payload = {\n addressInformation: {\n 'shipping_address': shippingAddress,\n 'shipping_method_code': quote.shippingMethod()['method_code'],\n 'shipping_carrier_code': quote.shippingMethod()['carrier_code']\n }\n };\n\n fullScreenLoader.startLoader();\n\n return storage.post(\n resourceUrlManager.getUrlForSetShippingInformation(quote),\n JSON.stringify(payload)\n ).done(function (response) {\n paymentService.setPaymentMethods(methodConverter(response['payment_methods']));\n quote.setTotals(response.totals);\n fullScreenLoader.stopLoader();\n }).fail(function (response) {\n errorProcessor.process(response);\n fullScreenLoader.stopLoader();\n });\n }\n };\n});\n","Magento_GiftRegistry/js/model/shipping-rate-processor/gift-registry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_GiftRegistry/js/model/resource-url-manager',\n 'Magento_Checkout/js/model/quote',\n 'mage/storage',\n 'Magento_Checkout/js/model/shipping-service',\n 'Magento_Checkout/js/model/shipping-rate-registry',\n 'Magento_Checkout/js/model/error-processor'\n], function (resourceUrlManager, quote, storage, shippingService, rateRegistry, errorProcessor) {\n 'use strict';\n\n return {\n /**\n * @param {Object} address\n */\n getRates: function (address) {\n var cache;\n\n shippingService.isLoading(true);\n cache = rateRegistry.get(address.getKey());\n\n if (cache) {\n shippingService.setShippingRates(cache);\n shippingService.isLoading(false);\n } else {\n storage.post(\n resourceUrlManager.getUrlForEstimationShippingMethodsForGiftRegistry(quote),\n JSON.stringify({\n registryId: address.giftRegistryId\n }),\n false\n ).done(function (result) {\n rateRegistry.set(address.getKey(), result);\n shippingService.setShippingRates(result);\n }).fail(function (response) {\n shippingService.setShippingRates([]);\n errorProcessor.process(response);\n }).always(function () {\n shippingService.isLoading(false);\n });\n }\n }\n };\n});\n","Magento_GiftRegistry/js/view/shipping-address/gift-registry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'uiComponent',\n 'Magento_GiftRegistry/js/model/recipient-address',\n 'Magento_Customer/js/model/address-list',\n 'Magento_Checkout/js/model/shipping-rate-service',\n 'Magento_GiftRegistry/js/model/shipping-rate-processor/gift-registry',\n 'Magento_Checkout/js/model/shipping-save-processor',\n 'Magento_GiftRegistry/js/model/shipping-save-processor/gift-registry'\n], function (\n Component,\n RecipientAddress,\n addressList,\n shippingRateService,\n shippingRateProcessor,\n shippingSaveProcessor,\n giftRegistryShippingSaveProcessor\n) {\n 'use strict';\n function checkExistingAddress() {\n let giftRegistry = window.checkoutConfig.giftRegistry;\n\n return giftRegistry.isLoggedIn && addressList().length !== 0 &&\n giftRegistry.id && giftRegistry.available;\n }\n\n //Register gift registry address provider\n if (checkExistingAddress()) {\n addressList.push(new RecipientAddress(window.checkoutConfig.giftRegistry.id));\n }\n\n //Register gift registry rate processor\n shippingRateService.registerProcessor('gift-registry', shippingRateProcessor);\n\n //Register gist registry save shipping address processor\n shippingSaveProcessor.registerProcessor('gift-registry', giftRegistryShippingSaveProcessor);\n\n /** Add view logic here if needed */\n return Component.extend({});\n});\n","Magento_GiftRegistry/js/view/shipping-address/address-renderer/gift-registry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'uiComponent',\n 'Magento_Checkout/js/action/select-shipping-address',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/checkout-data'\n], function (ko, Component, selectShippingAddressAction, quote, checkoutData) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_GiftRegistry/shipping-address/address-renderer/gift-registry'\n }
2,\n\n /** @inheritdoc */\n initObservable: function () {\n this._super();\n this.isSelected = ko.computed(function () {\n var isSelected = false,\n shippingAddress = quote.shippingAddress();\n\n if (shippingAddress) {\n isSelected = shippingAddress.getKey() == this.address().getKey(); //eslint-disable-line eqeqeq\n }\n\n return isSelected;\n }, this);\n\n return this;\n },\n\n /** Set selected customer shipping address */\n selectAddress: function () {\n selectShippingAddressAction(this.address());\n checkoutData.setSelectedShippingAddress(this.address().getKey());\n }\n });\n});\n","Magento_ProductVideo/js/fotorama-add-video-events.js":"/**\n * Copyright 2015 Adobe\n * All Rights Reserved.\n */\n\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget',\n 'catalogGallery',\n 'loadPlayer'\n], function ($) {\n 'use strict';\n\n /**\n * @private\n */\n var allowBase = true; //global var is needed because fotorama always fully reloads events in case of fullscreen\n\n /**\n * @private\n */\n function parseHref(href) {\n var a = document.createElement('a');\n\n a.href = href;\n\n return a;\n }\n\n /**\n * @private\n */\n function parseURL(href, forceVideo) {\n var id,\n type,\n ampersandPosition,\n vimeoRegex,\n useYoutubeNocookie = false;\n\n /**\n * Get youtube ID\n * @param {String} srcid\n * @returns {{}}\n */\n function _getYoutubeId(srcid) {\n if (srcid) {\n ampersandPosition = srcid.indexOf('&');\n\n if (ampersandPosition === -1) {\n return srcid;\n }\n\n srcid = srcid.substring(0, ampersandPosition);\n }\n\n return srcid;\n }\n\n if (typeof href !== 'string') {\n return href;\n }\n\n href = parseHref(href);\n\n if (href.host.match(/youtube\\.com/) && href.search) {\n id = href.search.split('v=')[1];\n\n if (id) {\n id = _getYoutubeId(id);\n type = 'youtube';\n }\n } else if (href.host.match(/youtube\\.com|youtu\\.be|youtube-nocookie.com/)) {\n id = href.pathname.replace(/^\\/(embed\\/|v\\/)?/, '').replace(/\\/.*/, '');\n type = 'youtube';\n\n if (href.host.match(/youtube-nocookie.com/)) {\n useYoutubeNocookie = true;\n }\n } else if (href.host.match(/vimeo\\.com/)) {\n type = 'vimeo';\n vimeoRegex = new RegExp(['https?:\\\\/\\\\/(?:www\\\\.|player\\\\.)?vimeo.com\\\\/(?:channels\\\\/(?:\\\\w+\\\\/)',\n '?|groups\\\\/([^\\\\/]*)\\\\/videos\\\\/|album\\\\/(\\\\d+)\\\\/video\\\\/|video\\\\/|)(\\\\d+)(?:$|\\\\/|\\\\?)'\n ].join(''));\n id = href.href.match(vimeoRegex)[3];\n }\n\n if ((!id || !type) && forceVideo) {\n id = href.href;\n type = 'custom';\n }\n\n return id ? {\n id: id, type: type, s: href.search.replace(/^\\?/, ''), useYoutubeNocookie: useYoutubeNocookie\n } : false;\n }\n\n //create AddFotoramaVideoEvents widget\n $.widget('mage.AddFotoramaVideoEvents', {\n options: {\n videoData: '',\n videoSettings: '',\n optionsVideoData: '',\n dataMergeStrategy: 'replace'\n },\n\n /**\n * @private\n */\n onVimeoJSFramework: function () {},\n defaultVideoData: [],\n PV: 'product-video', // [CONST]\n VU: 'video-unplayed',\n PVLOADED: 'fotorama__product-video--loaded', // [CONST]\n PVLOADING: 'fotorama__product-video--loading', // [CONST]\n VID: 'video', // [CONST]\n VI: 'vimeo', // [CONST]\n FTVC: 'fotorama__video-close',\n FTAR: 'fotorama__arr',\n fotoramaSpinner: 'fotorama__spinner',\n fotoramaSpinnerShow: 'fotorama__spinner--show',\n TI: 'video-thumb-icon',\n isFullscreen: false,\n FTCF: '[data-gallery-role=\"fotorama__fullscreen-icon\"]',\n Base: 0, //on check for video is base this setting become true if there is any video with base role\n MobileMaxWidth: 767,\n GP: 'gallery-placeholder', //gallery placeholder class is needed to find and erase <script> tag\n videoData: null,\n videoDataPlaceholder: [{\n id: '',\n isBase: true,\n mediaType: 'image',\n provider: ''\n }
2],\n\n /**\n * Creates widget\n * @private\n */\n _create: function () {\n if (!this.defaultVideoData.length) {\n this.defaultVideoData = this.options.videoData;\n }\n\n // If product does not have images, no video data generated,\n // but for configurable product we still need a video data, in case of 'prepend' gallery strategy.\n if (!this.defaultVideoData.length && !this.options.videoData.length) {\n this.defaultVideoData = this.options.videoData = this.videoDataPlaceholder;\n }\n this._initializeOnGalleryLoaded();\n },\n\n /**\n *\n * @private\n */\n _initialize: function () {\n this.clearEvents();\n\n if (this._checkForVideoExist()) {\n this._checkFullscreen();\n this._listenForFullscreen();\n this._isVideoBase();\n this._initFotoramaVideo();\n this._attachFotoramaEvents();\n }\n },\n\n /**\n * Initializes after gallery is loaded\n *\n * @private\n */\n _initializeOnGalleryLoaded: function () {\n $(this.element).data('gallery') ?\n this._onGalleryLoaded() :\n $(this.element).on('gallery:loaded', this._onGalleryLoaded.bind(this));\n },\n\n /**\n * Callback which fired after gallery gets initialized.\n */\n _onGalleryLoaded: function () {\n this.fotoramaItem = $(this.element).find('.fotorama-item');\n this._initialize();\n },\n\n /**\n * Clear gallery events to prevent duplicated calls.\n *\n * @private\n */\n clearEvents: function () {\n if (this.fotoramaItem !== undefined) {\n this.fotoramaItem.off(\n 'fotorama:show.' + this.PV +\n ' fotorama:showend.' + this.PV +\n ' fotorama:fullscreenenter.' + this.PV +\n ' fotorama:fullscreenexit.' + this.PV\n );\n }\n },\n\n /**\n *\n * @param {Object} options\n * @private\n */\n _setOptions: function (options) {\n if (options.videoData && options.videoData.length) {\n this.options.videoData = options.videoData;\n }\n\n this._loadVideoData(options);\n this._initializeOnGalleryLoaded();\n },\n\n /**\n * Set video data for configurable product.\n *\n * @param {Object} options\n * @private\n */\n _loadVideoData: function (options) {\n if (options.selectedOption) {\n if (options.dataMergeStrategy === 'prepend') {\n this.options.videoData = [].concat(\n this.options.optionsVideoData[options.selectedOption],\n this.defaultVideoData\n );\n } else {\n this.options.videoData = this.options.optionsVideoData[options.selectedOption];\n }\n } else {\n this.options.videoData = this.defaultVideoData;\n }\n },\n\n /**\n *\n * @private\n */\n _checkFullscreen: function () {\n if (this.fotoramaItem.data('fotorama').fullScreen || false) {\n this.isFullscreen = true;\n }\n },\n\n /**\n *\n * @private\n */\n _listenForFullscreen: function () {\n this.fotoramaItem.on('fotorama:fullscreenenter.' + this.PV, $.proxy(function () {\n this.isFullscreen = true;\n }, this));\n\n this.fotoramaItem.on('fotorama:fullscreenexit.' + this.PV, $.proxy(function () {\n this.isFullscreen = false;\n this._hideVideoArrows();\n }, this));\n },\n\n /**\n *\n * @param {Object} inputData\n * @param {bool} isJSON\n * @returns {{}}\n * @private\n */\n _createVideoData: function (inputData, isJSON) {\n var videoData = [],\n dataUrl,\n tmpVideoData,\n tmpInputData,\n i;\n\n if (isJSON) {\n inputData = JSON.parse(inputData);\n }\n\n for (i = 0; i < inputData.length;
2 i++) {\n tmpInputData = inputData[i];\n dataUrl = '';\n tmpVideoData = {\n mediaType: '',\n isBase: '',\n id: '',\n provider: ''\n };\n tmpVideoData.mediaType = this.VID;\n\n if (tmpInputData.mediaType !== 'external-video') {\n tmpVideoData.mediaType = tmpInputData.mediaType;\n }\n\n tmpVideoData.isBase = tmpInputData.isBase;\n\n if (tmpInputData.videoUrl && tmpInputData.videoUrl !== null) {\n dataUrl = tmpInputData.videoUrl;\n dataUrl = parseURL(dataUrl);\n tmpVideoData.id = dataUrl.id;\n tmpVideoData.provider = dataUrl.type;\n tmpVideoData.videoUrl = tmpInputData.videoUrl;\n tmpVideoData.useYoutubeNocookie = dataUrl.useYoutubeNocookie;\n }\n\n videoData.push(tmpVideoData);\n }\n\n return videoData;\n },\n\n /**\n *\n * @param {Object} fotorama\n * @param {bool} isBase\n * @private\n */\n _createCloseVideo: function (fotorama, isBase) {\n var closeVideo;\n\n this.fotoramaItem.find('.' + this.FTVC).remove();\n this.fotoramaItem.append('<div class=\"' + this.FTVC + '\"></div>');\n this.fotoramaItem.css('position', 'relative');\n closeVideo = this.fotoramaItem.find('.' + this.FTVC);\n this._closeVideoSetEvents(closeVideo, fotorama);\n\n if (\n isBase &&\n this.options.videoData[fotorama.activeIndex].isBase &&\n $(window).width() > this.MobileMaxWidth) {\n this._showCloseVideo();\n }\n },\n\n /**\n *\n * @private\n */\n _hideCloseVideo: function () {\n this.fotoramaItem\n .find('.' + this.FTVC)\n .removeClass('fotorama-show-control');\n },\n\n /**\n *\n * @private\n */\n _showCloseVideo: function () {\n this.fotoramaItem\n .find('.' + this.FTVC)\n .addClass('fotorama-show-control');\n },\n\n /**\n *\n * @param {jQuery} $closeVideo\n * @param {jQuery} fotorama\n * @private\n */\n _closeVideoSetEvents: function ($closeVideo, fotorama) {\n $closeVideo.on('click', $.proxy(function () {\n this._unloadVideoPlayer(fotorama.activeFrame.$stageFrame.parent(), fotorama, true);\n this._hideCloseVideo();\n }, this));\n },\n\n /**\n *\n * @returns {Boolean}\n * @private\n */\n _checkForVideoExist: function () {\n var key, result, checker, videoSettings;\n\n if (!this.options.videoData) {\n return false;\n }\n\n if (!this.options.videoSettings) {\n return false;\n }\n\n result = this._createVideoData(this.options.videoData, false);\n checker = false;\n videoSettings = this.options.videoSettings[0];\n videoSettings.playIfBase = parseInt(videoSettings.playIfBase, 10);\n videoSettings.showRelated = parseInt(videoSettings.showRelated, 10);\n videoSettings.videoAutoRestart = parseInt(videoSettings.videoAutoRestart, 10);\n\n for (key in result) {\n if (result[key].mediaType === this.VID) {\n checker = true;\n }\n }\n\n if (checker) {\n this.options.videoData = result;\n }\n\n return checker;\n },\n\n /**\n *\n * @private\n */\n _isVideoBase: function () {\n var allVideoData = this.options.videoData,\n videoItem,\n allVideoDataKeys,\n key,\n i;\n\n allVideoDataKeys = Object.keys(allVideoData);\n\n for (i = 0; i < allVideoDataKeys.length;
2 i++) {\n key = allVideoDataKeys[i];\n videoItem = allVideoData[key];\n\n if (\n videoItem.mediaType === this.VID && videoItem.isBase &&\n this.options.videoSettings[0].playIfBase && allowBase\n ) {\n this.Base = true;\n allowBase = false;\n }\n }\n\n if (!this.isFullscreen) {\n this._createCloseVideo(this.fotoramaItem.data('fotorama'), this.Base);\n }\n },\n\n /**\n *\n * @param {Event} e\n * @private\n */\n _initFotoramaVideo: function (e) {\n var fotorama = this.fotoramaItem.data('fotorama'),\n thumbsParent,\n thumbs,\n t;\n\n if (!fotorama.activeFrame.$navThumbFrame) {\n this.fotoramaItem.on('fotorama:showend.' + this.PV, $.proxy(function (evt, fotoramaData) {\n $(fotoramaData.activeFrame.$stageFrame).removeAttr('href');\n }, this));\n\n this._startPrepareForPlayer(e, fotorama);\n\n return null;\n }\n\n fotorama.data.map($.proxy(this._setItemType, this));\n thumbsParent = fotorama.activeFrame.$navThumbFrame.parent();\n thumbs = thumbsParent.find('.fotorama__nav__frame:visible');\n\n for (t = 0; t < thumbs.length; t++) {\n this._setThumbsIcon(thumbs.eq(t), t);\n this._checkForVideo(e, fotorama, t + 1);\n }\n\n this.fotoramaItem.on('fotorama:showend.' + this.PV, $.proxy(function (evt, fotoramaData) {\n $(fotoramaData.activeFrame.$stageFrame).removeAttr('href');\n }, this));\n },\n\n /**\n *\n * @param {Object} elem\n * @param {Number} i\n * @private\n */\n _setThumbsIcon: function (elem, i) {\n var fotorama = this.fotoramaItem.data('fotorama');\n\n if (fotorama.options.nav === 'dots' && elem.hasClass(this.TI)) {\n elem.removeClass(this.TI);\n }\n\n if (this.options.videoData[i] &&\n this.options.videoData[i].mediaType === this.VID &&\n fotorama.data[i].type === this.VID &&\n fotorama.options.nav === 'thumbs') {\n elem.addClass(this.TI);\n }\n },\n\n /**\n * Temporary solution with adding types for configurable product items\n *\n * @param {Object} item\n * @param {Number} i\n * @private\n */\n _setItemType: function (item, i) {\n !item.type && (item.type = this.options.videoData[i].mediaType);\n },\n\n /**\n * Attach\n *\n * @private\n */\n _attachFotoramaEvents: function () {\n this.fotoramaItem.on('fotorama:showend.' + this.PV, $.proxy(function (e, fotorama) {\n this._startPrepareForPlayer(e, fotorama);\n }, this));\n\n this.fotoramaItem.on('fotorama:show.' + this.PV, $.proxy(function (e, fotorama) {\n this._unloadVideoPlayer(fotorama.activeFrame.$stageFrame.parent(), fotorama, true);\n }, this));\n\n this.fotoramaItem.on('fotorama:fullscreenexit.' + this.PV, $.proxy(function (e, fotorama) {\n fotorama.activeFrame.$stageFrame.find('.' + this.PV).remove();\n this._startPrepareForPlayer(e, fotorama);\n }, this));\n },\n\n /**\n * Start prepare for player\n *\n * @param {Event} e\n * @param {jQuery} fotorama\n * @private\n */\n _startPrepareForPlayer: function (e, fotorama) {\n this._unloadVideoPlayer(fotorama.activeFrame.$stageFrame.parent(), fotorama, false);\n this._checkForVideo(e, fotorama, fotorama.activeFrame.i);\n this._checkForVideo(e, fotorama, fotorama.activeFrame.i - 1);\n this._checkForVideo(e, fotorama, fotorama.activeFrame.i + 1);\n },\n\n /**\n * Check for video\n *\n * @param {Event} e\n * @param {jQuery} fotorama\n * @param {Number} number\n * @private\n */\n _checkForVideo: function (e, fotorama, number) {\n var videoData = this.options.videoData[number - 1],\n $image = fotorama.data[number - 1];\n\n if ($image) {\n !$image.type && this._setItemType($image, number - 1);\n\n if ($image.type === 'image') {\n $image.$navThumbFrame && $image.$navThumbFrame.removeClass(this.TI);\n this._hideCloseVideo();\n\n return;\n } else if ($image.$navThumbFrame && $image.type === 'video') {\n !$image.$navThumbFrame.hasClass(this.TI) && $image.$navThumbFrame.addClass(this.TI);\n }\n\n $image = $image.$stageFrame;\n }\n\n if ($image && videoData && videoData.mediaType === this.VID) {\n $(fotorama.activeFrame.$stageFrame).removeAttr('href');\n this._prepareForVideoContainer($image, videoData, fotorama, number);\n }\n\n if (this.isFullscreen && this.fotoramaItem.data('fotorama').activeFrame.i === number) {\n this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.trigger('click');\n }\n },\n\n /**\n * Prepare for video container\n *\n * @param {jQuery} $image\n * @param {Object} videoData\n * @param {Object} fotorama\n * @param {Number} number\n * @private\n */\n _prepareForVideoContainer: function ($image, videoData, fotorama, number) {\n $image.addClass('fotorama-video-container').addClass(this.VU);\n this._createVideoContainer(videoData, $image);\n this._setVideoEvent($image, this.PV, fotorama, number);\n },\n\n /**\n * Create video container\n *\n * @param {Object} videoData\n * @param {jQuery} $image\n * @private\n */\n _createVideoContainer: function (videoData, $image) {\n var videoSettings;\n\n videoSettings = this.options.videoSettings[0];\n $image.find('.' + this.PV).remove();\n $image.append(\n '<div class=\"' +\n this.PV +\n '\" data-related=\"' +\n videoSettings.showRelated +\n '\" data-loop=\"' +\n videoSettings.videoAutoRestart +\n '\" data-type=\"' +\n videoData.provider +\n '\" data-code=\"' +\n videoData.id +\n '\" data-youtubenocookie=\"' +\n videoData.useYoutubeNocookie +\n '\" data-width=\"100%\" data-height=\"100%\"></div>'\n );\n },\n\n /**\n *\n * @param {Object} $image\n * @param {Object} PV\n * @param {Object} fotorama\n * @param {Number} number\n * @private\n */\n _setVideoEvent: function ($image, PV, fotorama, number) {\n $image.find('.magnify-lens').remove();\n $image\n .off('click tap', $.proxy(this._clickHandler, this))\n .on('click tap', $.proxy(this._clickHandler, this));\n this._handleBaseVideo(fotorama, number); //check for video is it base and handle it if it's base\n },\n\n /**\n * Hides preview arrows above video player.\n * @private\n */\n _hideVideoArrows: function () {\n var arrows = $('.' + this.FTAR);\n\n arrows.removeClass('fotorama__arr--shown');\n arrows.removeClass('fotorama__arr--hidden');\n },\n\n /**\n * @private\n */\n _showLoader: function () {\n var spinner = this.fotoramaItem.find('.' + this.fotoramaSpinner);\n\n spinner.addClass(this.fotoramaSpinnerShow);\n this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.addClass(this.PVLOADING);\n },\n\n /**\n * @private\n */\n _hideLoader: function () {\n var spinner = this.fotoramaItem.find('.' + this.fotoramaSpinner);\n\n spinner.removeClass(this.fotoramaSpinnerShow);\n this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.removeClass(this.PVLOADING);\n },\n\n /**\n * @param {Event} event\n * @private\n */\n _clickHandler: function (event) {\n var type;\n\n if ($(event.target).hasClass(this.VU) && $(event.target).find('iframe').length === 0) {\n $(event.target).removeClass(this.VU);\n type = $(event.target).find('.' + this.PV).data('type');\n\n if (type === this.VI) {\n $(event.target).find('.' + this.PV).productVideoLoader();\n } else if (type === this.VI) {\n this._showLoader();\n this.onVimeoJSFramework = function () {\n $(event.target).find('.' + this.PV).productVideoLoader();\n this._hideLoader();\n }.bind(this);\n } else {\n $(event.target).find('.' + this.PV).productVideoLoader();\n }\n\n $('.' + this.FTAR).addClass(this.isFullscreen ? 'fotorama__arr--shown' : 'fotorama__arr--hidden');\n $('.' + this.FTVC).addClass('fotorama-show-control');\n }\n },\n\n /**\n * Handle base video\n * @param {Object} fotorama\n * @param {Number} srcNumber\n * @private\n */\n _handleBaseVideo: function (fotorama, srcNumber) {\n var videoData = this.options.videoData,\n activeIndex = fotorama.activeIndex,\n number = parseInt(srcNumber, 10),\n activeIndexIsBase = videoData[activeIndex];\n\n if (!this.Base) {\n return;\n }\n\n if (activeIndexIsBase && number === 1 && $(window).width() > this.MobileMaxWidth) {\n setTimeout($.proxy(function () {\n fotorama.requestFullScreen();\n this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.trigger('click');\n this.Base = false;\n }, this), 50);\n }\n },\n\n /**\n * Destroy video player\n * @param {jQuery} $wrapper\n * @param {jQuery} current\n * @param {bool} close\n * @private\n */\n _unloadVideoPlayer: function ($wrapper, current, close) {\n var self = this;\n\n if (!$wrapper) {\n return;\n }\n\n $wrapper.find('.' + this.PVLOADED).removeClass(this.PVLOADED);\n this._hideLoader();\n\n $wrapper.find('.' + this.PV).each(function () {\n var $item = $(this).parent(),\n cloneVideoDiv,\n iframeElement = $(this).find('iframe'),\n currentIndex,\n itemIndex;\n\n if (iframeElement.length === 0) {\n return;\n }\n\n currentIndex = current.activeFrame.$stageFrame.index();\n itemIndex = $item.index();\n\n if (currentIndex === itemIndex && !close) {\n return;\n }\n\n if (currentIndex !== itemIndex && close) {\n return;\n }\n\n iframeElement.remove();\n cloneVideoDiv = $(this).clone();\n $(this).remove();\n $item.append(cloneVideoDiv);\n $item.addClass(self.VU);\n\n self._hideCloseVideo();\n self._hideVideoArrows();\n\n if (self.isFullscreen && !self.fotoramaItem.data('fotorama').options.fullscreen.arrows) {\n if ($('.' + self.FTAR + '--prev').is(':focus') || $('.' + self.FTAR + '--next').is(':focus')) {\
2n $(self.FTCF).trigger('focus');\n }\n }\n });\n }\n });\n\n return $.mage.AddFotoramaVideoEvents;\n});\n","Magento_ProductVideo/js/load-player.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n @version 0.0.1\n @requires jQuery & jQuery UI\n */\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget',\n 'vimeoWrapper'\n], function ($) {\n 'use strict';\n\n var videoRegister = {\n _register: {},\n\n /**\n * Checks, if api is already registered\n *\n * @param {String} api\n * @returns {bool}\n */\n isRegistered: function (api) {\n return this._register[api] !== undefined;\n },\n\n /**\n * Checks, if api is loaded\n *\n * @param {String} api\n * @returns {bool}\n */\n isLoaded: function (api) {\n return this._register[api] !== undefined && this._register[api] === true;\n },\n\n /**\n * Register new video api\n * @param {String} api\n * @param {bool} loaded\n */\n register: function (api, loaded) {\n loaded = loaded || false;\n this._register[api] = loaded;\n }\n };\n\n $.widget('mage.productVideoLoader', {\n\n /**\n * @private\n */\n _create: function () {\n switch (this.element.data('type')) {\n case 'youtube':\n this.element.videoYoutube();\n this._player = this.element.data('mageVideoYoutube');\n break;\n\n case 'vimeo':\n this.element.videoVimeo();\n this._player = this.element.data('mageVideoVimeo');\n break;\n default:\n throw {\n name: 'Video Error',\n message: 'Unknown video type',\n\n /**\n * join name with message\n */\n toString: function () {\n return this.name + ': ' + this.message;\n }\n };\n }\n },\n\n /**\n * Initializes variables\n * @private\n */\n _initialize: function () {\n this._params = this.element.data('params') || {};\n this._code = this.element.data('code');\n this._width = this.element.data('width');\n this._height = this.element.data('height');\n this._autoplay = !!this.element.data('autoplay');\n this._playing = this._autoplay || false;\n this._loop = this.element.data('loop');\n this._rel = this.element.data('related');\n this.useYoutubeNocookie = this.element.data('youtubenocookie') || false;\n\n this._responsive = this.element.data('responsive') !== false;\n\n if (this._responsive === true) {\n this.element.addClass('responsive');\n }\n\n this._calculateRatio();\n },\n\n /**\n * Abstract play command\n */\n play: function () {\n this._player.play();\n },\n\n /**\n * Abstract pause command\n */\n pause: function () {\n this._player.pause();\n },\n\n /**\n * Abstract stop command\n */\n stop: function () {\n this._player.stop();\n },\n\n /**\n * Abstract playing command\n */\n playing: function () {\n return this._player.playing();\n },\n\n /**\n * Calculates ratio for responsive videos\n * @private\n */\n _calculateRatio: function () {\n if (!this._responsive) {\n return;\n }\n this.element.css('paddingBottom', this._height / this._width * 100 + '%');\n }\n });\n\n $.widget('mage.videoYoutube', $.mage.productVideoLoader, {\n\n /**\n * Initialization of the Youtube widget\n * @private\n */\n _create: function () {\n var self = this;\n\n this._initialize();\n\n this.element.append('<div></div>');\n\n this._on(window, {\n\n /**\n * Handle event\n */\n 'youtubeapiready': function () {\n var host = 'https://www.youtube.com';\n\n if (self.useYoutubeNocookie) {\n host = 'https://www.youtube-nocookie.com';\n }\n\n if (self._player !== undefined) {\n return;\n }\n self._autoplay = true;\n\n if (self._autoplay) {\n self._params.autoplay = 1;\n }\n\n if (!self._rel) {\n self._params.rel = 0;\n }\n\n self._player = new window.YT.Player(self.element.children(':first')[0], {\n height: self._height,\n width: self._width,\n videoId: self._code,\n playerVars: self._params,\n host: host,\n events: {\n\n /**\n * Get duration\n */\n 'onReady': function onPlayerReady() {\
2n self._player.getDuration();\n self.element.closest('.fotorama__stage__frame')\n .addClass('fotorama__product-video--loaded');\n },\n\n /**\n * Event observer\n */\n onStateChange: function (data) {\n switch (window.parseInt(data.data, 10)) {\n case 1:\n self._playing = true;\n break;\n default:\n self._playing = false;\n break;\n }\n\n self._trigger('statechange', {}, data);\n\n if (data.data === window.YT.PlayerState.ENDED && self._loop) {\n self._player.playVideo();\n }\n }\n }\n\n });\n }\n });\n\n this._loadApi();\n },\n\n /**\n * Loads Youtube API and triggers event, when loaded\n * @private\n */\n _loadApi: function () {\n var element,\n scriptTag;\n\n if (videoRegister.isRegistered('youtube')) {\n if (videoRegister.isLoaded('youtube')) {\n $(window).trigger('youtubeapiready');\n }\n\n return;\n }\n\n // if script already loaded by other library\n if (window.YT) {\n videoRegister.register('youtube', true);\n $(window).trigger('youtubeapiready');\n\n return;\n }\n videoRegister.register('youtube');\n\n element = document.createElement('script');\n scriptTag = document.getElementsByTagName('script')[0];\n\n element.async = true;\n element.src = 'https://www.youtube.com/iframe_api';\n scriptTag.parentNode.insertBefore(element, scriptTag);\n\n /**\n * Event observe and handle\n */\n window.onYouTubeIframeAPIReady = function () {\n $(window).trigger('youtubeapiready');\n videoRegister.register('youtube', true);\n };\n },\n\n /**\n * Play command for Youtube\n */\n play: function () {\n this._player.playVideo();\n this._playing = true;\n },\n\n /**\n * Pause command for Youtube\n */\n pause: function () {\n this._player.pauseVideo();\n this._playing = false;\n },\n\n /**\n * Stop command for Youtube\n */\n stop: function () {\n this._player.stopVideo();\n this._playing = false;\n },\n\n /**\n * Playing command for Youtube\n */\n playing: function () {\n return this._playing;\n },\n\n /**\n * stops and unloads player\n * @private\n */\n _destroy: function () {\n this.stop();\n }\n });\n\n $.widget('mage.videoVimeo', $.mage.productVideoLoader, {\n\n /**\n * Initialize the Vimeo widget\n * @private\n */\n _create: function () {\n var timestamp,\n additionalParams = '',\n src,\n id;\n\n this._initialize();\n timestamp = new Date().getTime();\n this._autoplay = true;\n\n if (this._autoplay) {\n additionalParams += '&autoplay=1';\n }\n\n if (this._loop) {\n additionalParams += '&loop=1';\n }\n src = 'https://player.vimeo.com/video/' +\n this._code + '?api=1&player_id=vimeo' +\n this._code +\n timestamp +\n additionalParams;
2\n id = 'vimeo' + this._code + timestamp;\n this.element.append(\n $('<iframe></iframe>')\n .attr('frameborder', 0)\n .attr('id', id)\n .attr('width', this._width)\n .attr('height', this._height)\n .attr('src', src)\n .attr('webkitallowfullscreen', '')\n .attr('mozallowfullscreen', '')\n .attr('allowfullscreen', '')\n .attr('referrerPolicy', 'origin')\n .attr('allow', 'autoplay')\n );\n\n /* eslint-disable no-undef */\n this._player = new Vimeo.Player(this.element.children(':first')[0]);\n\n this._player.ready().then(function () {\n $('#' + id).closest('.fotorama__stage__frame').addClass('fotorama__product-video--loaded');\n });\n },\n\n /**\n * Play command for Vimeo\n */\n play: function () {\n this._player.play();\n this._playing = true;\n },\n\n /**\n * Pause command for Vimeo\n */\n pause: function () {\n this._player.pause();\n this._playing = false;\n },\n\n /**\n * Stop command for Vimeo\n */\n stop: function () {\n this._player.unload();\n this._playing = false;\n },\n\n /**\n * Playing command for Vimeo\n */\n playing: function () {\n return this._playing;\n }\n });\n});\n","Magento_Banner/js/model/banner.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'underscore',\n 'ko',\n 'jquery/jquery-storageapi'\n], function ($, _, ko) {\n 'use strict';\n\n var options = {\n cacheTtl: 0,\n sectionLoadUrl: ''\n },\n selectors = {\n productIdSelector: '#product_addtocart_form [name=\"product\"]'\n },\n storage = $.initNamespaceStorage('mage-banners-cache-storage').localStorage,\n productId = $(selectors.productIdSelector).val(),\n\n /**\n * Cache invalidation. Banner cache ttl is 30 sec by default.\n */\n invalidateCacheBySessionTimeOut = function () {\n var cacheEol = new Date($.localStorage.get('mage-banners-cache-timeout')),\n dateTo = new Date(Date.now() + options.cacheTtl),\n cartDataId = null,\n globalStoreId = $.cookieStorage.get('store') || 'default';\n\n if ($.localStorage.get('mage-banners-storeId') === null) {\n $.localStorage.set('mage-banners-storeId', globalStoreId);\n }\n\n if ($.localStorage.get('mage-cache-storage') !== null &&\n $.localStorage.get('mage-cache-storage').hasOwnProperty('cart')) {\n cartDataId = $.localStorage.get('mage-cache-storage').cart['data_id'];\n }\n\n if (cacheEol < new Date() ||\n $.localStorage.get('mage-banners-storeId') !== globalStoreId ||\n $.localStorage.get('mage-banners-cartDataId') !== cartDataId) {\n storage.removeAll();\n $.localStorage.set('mage-banners-cache-timeout', dateTo);\n $.localStorage.set('mage-banners-storeId', globalStoreId);\n\n if (cartDataId) {\n $.localStorage.set('mage-banners-cartDataId', cartDataId);\n }\n }\n },\n dataProvider = {\n\n /**\n * Request data from storage\n *\n * @param {Array} sectionNames\n * @returns {Object}\n */\n getFromStorage: function (sectionNames) {\n var result = {};\n\n _.each(sectionNames, function (sectionName) {\n result[sectionName] = storage.get(sectionName);\n });\n\n return result;\n },\n\n /**\n * Request data from server\n *\n * @param {Array} sectionNames\n * @returns {Object}\n */\n getFromServer: function (sectionNames) {\n var parameters = {\n 'requesting_page_url': window.location.href\n };\n\n if (productId) {\n parameters.data = {\n 'product_id': productId\n };\n }\n\n if (_.isArray(sectionNames)) {\n parameters.sections = sectionNames.join(',');\n }\n\n return $.getJSON(options.sectionLoadUrl, parameters).fail(function (jqXHR) {\n throw new Error(jqXHR);\n });\n }\n },\n buffer = {\n data: {},\n\n /**\n * Binding parameter\n *\n * @param {String} sectionName\n */\n bind: function (sectionName) {\n this.data[sectionName] = ko.observable({});\n },\n\n /**\n *\n * @param {String} sectionName\n * @returns {Object}\n */\n get: function (sectionName) {\n if (!this.data[sectionName]) {\n this.bind(sectionName);\n }\n\n return this.data[sectionName];\n },\n\n /**\n * Get keys\n *\n * @returns {Array}\n */\n keys: function () {\n return _.keys(this.data);\n },\n\n /**\n * Notify storage\n *\n * @param {String} sectionName\n * @param {Object} sectionData\n */\n notify: function (sectionName, sectionData) {\
2n if (!this.data[sectionName]) {\n this.bind(sectionName);\n }\n this.data[sectionName](sectionData);\n },\n\n /**\n * Update sections\n *\n * @param {Array} sections\n */\n update: function (sections) {\n _.each(sections, function (sectionData, sectionName) {\n storage.set(sectionName, sectionData);\n buffer.notify(sectionName, sectionData);\n });\n }\n },\n banner = {\n\n /**\n * Initialization\n */\n init: function () {\n var dataSectionName;\n\n dataSectionName = this.getSectionName('data');\n\n if (_.isEmpty(storage.keys()) || !storage.get(dataSectionName)) {\n this.reload([]);\n } else {\n _.each(dataProvider.getFromStorage(storage.keys()), function (sectionData, sectionName) {\n buffer.notify(sectionName, sectionData);\n });\n }\n },\n\n /**\n * Get data\n *\n * @param {String} sectionName\n * @returns {*|Object}\n */\n get: function (sectionName) {\n sectionName = this.getSectionName(sectionName);\n\n return buffer.get(sectionName);\n },\n\n /**\n * Set data\n *\n * @param {String} sectionName\n * @param {Object} sectionData\n */\n set: function (sectionName, sectionData) {\n var data = {};\n\n sectionName = this.getSectionName(sectionName);\n data[sectionName] = sectionData;\n buffer.update(data);\n },\n\n /**\n * Reloading from storage or server\n *\n * @param {Array} sectionNames\n * @returns {Object}\n */\n reload: function (sectionNames) {\n return dataProvider.getFromServer(sectionNames).done(function (sections) {\n _.each(sections, function (sectionData, sectionName) {\n this.set(sectionName, sectionData);\n }.bind(this));\n }.bind(this));\n },\n\n /**\n * Get section name\n *\n * @returns {String}\n */\n getSectionName: function (sectionName) {\n var result;\n\n result = productId && sectionName === 'data' ? 'data_product_' + productId : sectionName;\n\n return result;\n },\n\n /**\n * Init helper\n *\n * @param {Array} settings\n */\n 'Magento_Banner/js/model/banner': function (settings) {\n options = _.extend(options, settings);\n invalidateCacheBySessionTimeOut(settings);\n banner.init();\n }\n };\n\n //TODO: remove global change, in this case made for initNamespaceStorage\n $.cookieStorage.setConf({\n path: '/'\n });\n\n return banner;\n});\n","Magento_Banner/js/view/banner.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'uiComponent',\n 'Magento_Banner/js/model/banner',\n 'underscore',\n 'jquery',\n 'Magento_Ui/js/lib/core/storage/local'\n], function (Component, Banner, _, $, storage) {\n 'use strict';\n\n /**\n * Stores banners initialized in getItems() method\n *\n * Prevent series reinitialization on consecutive calls to getItems() method\n *\n * @type {Array}\n */\n var initializedItems = [];\n\n /**\n * Returns next banner in series\n *\n * @param {Array} applicableBanners\n * @param {String} rotationType\n * @param {String} bannerId\n * @returns {Object}\n */\n function getBannerFromSeries(applicableBanners, rotationType, bannerId) {\n var storageKey,\n series,\n itemToDisplay,\n storeId;\n\n storeId = Banner.get('data')()['store_id'];\n storageKey = rotationType + '_' + bannerId + '_' + storeId;\n series = storage.get(storageKey);\n\n if (!series || !series.length) {\n series = applicableBanners;\n }\n\n itemToDisplay = series.shift();\n\n if (!series.length) {\n series = applicableBanners;\n }\n\n storage.set(storageKey, series);\n\n return itemToDisplay;\n }\n\n /**\n *\n * @param {Array} applicableBanners\n * @param {String} rotationType\n * @param {String} bannerId\n * @returns {Array}\n */\n function applyRotation(applicableBanners, rotationType, bannerId) {\n\n var result = applicableBanners;\n\n switch (rotationType) {\n\n case 'random':\n result = [applicableBanners[_.random(applicableBanners.length - 1)]];\n break;\n\n case 'shuffle':\n result = _.shuffle(applicableBanners);\n result = [getBannerFromSeries(result, rotationType, bannerId)];\n break;\n\n case 'series':\n result = [getBannerFromSeries(applicableBanners, rotationType, bannerId)];\n break;\n }\n\n return result;\n }\n\n /**\n * @param {Object} bannerConfig\n */\n function getItems(bannerConfig) {\n var applicableBanners = [],\n displayMode = bannerConfig.data('display-mode'),\n allowedBannerTypes = bannerConfig.data('types'),\n assignedBannerIds = bannerConfig.data('ids') + '',\n rotationType = bannerConfig.data('rotate'),\n blockId = bannerConfig.data('banner-id');\n\n if (!initializedItems[blockId] && !_.isEmpty(Banner.get('data')().items)) {\n applicableBanners = _.toArray(Banner.get('data')().items[displayMode]);\n\n if (!_.isEmpty(assignedBannerIds)) {\n assignedBannerIds = assignedBannerIds ? assignedBannerIds.split(',') : null;\n applicableBanners = _.filter(applicableBanners, function (banner) {\n return !assignedBannerIds ? true : _.contains(assignedBannerIds, banner.id);\n });\n applicableBanners = _.sortBy(applicableBanners, function (banner) {\n return _.indexOf(assignedBannerIds, banner.id);\n });\n }\n\n if (_.isEmpty(assignedBannerIds) && displayMode === 'fixed') {\n applicableBanners = [];\n }\n\n /**\n * In case allowedBannerTypes is empty filtering by type must not be performed\n */\n if (!_.isEmpty(allowedBannerTypes) && !_.isEmpty(applicableBanners)) {\n allowedBannerTypes = allowedBannerTypes ? allowedBannerTypes.split(',') : null;\n applicableBanners = _.filter(applicableBanners, function (banner) {\n return !allowedBannerTypes || _.isEmpty(banner.types) ? true : !_.isEmpty(\n _.intersection(allowedBannerTypes, banner.types)\n );\n });\n }\n\n initializedItems[blockId] = [];\n\n if (!_.isEmpty(applicableBanners)) {\n applicableBanners = applyRotation(applicableBanners, rotationType, blockId);\n _.each(applicableBanners, function (banner) {\n initializedItems[blockId].push({\n html: banner.content,\n bannerId: banner.id\n });\n });\n }\n }\n\n return initializedItems[blockId];\n }\n\n return Component.extend({\n /** @inheritdoc */\n initialize: function () {\n this._super();\n this.banner = Banner.get('data');\n },\n\n /**\n * Register method after element render to have access to banner items.\n *\n * @param {HTMLElement} el\n */\n registerBanner: function (el) {\n var banner = $(el.parentElement);\n\n this['getItems' + banner.data('banner-id')] = getItems.bind(\n null,\n banner\n );\n }\n });\n});\n","Magento_CheckoutAddressSearch/js/modal-component.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Ui/js/modal/modal-component'\n], function (Modal) {\n 'use strict';\n\n return Modal.extend({\n\n /**\n * Wrap content in a modal of certain type\n *\n * @param {HTMLElement} element\n * @returns {Object} Chainable.\n */\n initModal: function (element) {\n this.modal = null;\n this._super(element);\n\n return this;\n }\n });\n});\n","Magento_CheckoutAddressSearch/js/view/billing-address.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'jquery',\n 'mage/translate',\n 'Magento_Checkout/js/view/billing-address',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/action/select-billing-address',\n 'Magento_Checkout/js/checkout-data',\n 'Magento_Ui/js/modal/modal',\n 'Magento_Checkout/js/action/create-billing-address',\n 'Magento_Customer/js/model/address-list',\n 'Magento_Ui/js/lib/view/utils/async'\n], function (_, $, $t, Component, quote, selectBillingAddress, checkoutData, modal, createBillingAddress, addressList) {\n 'use strict';\n\n var lastSelectedBillingAddress = null;\n\n return Component.extend({\n defaults: {\n template: 'Magento_CheckoutAddressSearch/billing-address',\n detailsTemplate: 'Magento_CheckoutAddressSearch/billing-address/details',\n selectBillingAddressProvider: '',\n isNewAddressAdded: false,\n newCustomerBillingAddress: null,\n popUpButtons: {\n save: {\n text: $t('Save Address'),\n class: 'action primary action-save-address'\n },\n cancel: {\n text: $t('Cancel'),\n class: 'action secondary action-hide-popup'\n }\n },\n popUpForm: {\n element: '.new-billing-address-form',\n options: {\n type: 'popup',\n responsive: true,\n innerScroll: true,\n title: $t('Billing Address')\n }\n },\n modules: {\n selectBillingAddress: '${ $.selectBillingAddressProvider }'\n },\n noAddressMessage: $t('No address selected')\n },\n\n /** @inheritdoc */\n initialize: function () {\n this._super();\n this.isNewAddressAdded(!!checkoutData.getNewCustomerBillingAddress());\n\n if (this.isNewAddressAdded()) {\n this.newCustomerBillingAddress(createBillingAddress(checkoutData.getNewCustomerBillingAddress()));\n }\n\n quote.billingAddress.subscribe(function (addressOption) {\n if (!addressOption) {\n _.each(addressList(), function (address) {\n if (address.isDefaultBilling && address.isDefaultBilling()) {\n selectBillingAddress(address);\n checkoutData.setSelectedBillingAddress(address.getKey());\n }\n }, this);\n }\n }, this);\n\n $.async({\n component: this,\n selector: this.popUpForm.element\n }, this.initPopup.bind(this));\n\n return this;\n }
2,\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe('isNewAddressAdded newCustomerBillingAddress');\n\n quote.billingAddress.subscribe(function () {\n this.isAddressFormVisible(false);\n }, this);\n\n return this;\n },\n\n /** @inheritdoc */\n useShippingAddress: function () {\n if (this.isAddressSameAsShipping()) {\n lastSelectedBillingAddress = quote.billingAddress();\n selectBillingAddress(quote.shippingAddress());\n checkoutData.setSelectedBillingAddress(quote.shippingAddress().getKey());\n this.updateAddresses();\n } else if (lastSelectedBillingAddress &&\n lastSelectedBillingAddress.getCacheKey() !== quote.billingAddress().getCacheKey()\n ) {\n selectBillingAddress(lastSelectedBillingAddress);\n checkoutData.setSelectedBillingAddress(lastSelectedBillingAddress.getKey());\n this.updateAddresses();\n }\n\n return true;\n },\n\n /**\n * Edit address action.\n */\n editAddress: function () {\n this.showFormPopUp();\n },\n\n /**\n * Cancel address edit action.\n */\n cancelAddressEdit: function () {\n checkoutData.setBillingAddressFromData($.extend(true, {}, this.temporaryAddress));\n this.closeFormPopUp();\n },\n\n /**\n * Init form for billing address.\n *\n * @param {HTMLElement} element\n */\n initPopup: function (element) {\n this.popUpForm.options.buttons = [\n {\n text: this.popUpButtons.save.text,\n class: this.popUpButtons.save.class,\n click: function () {\n this.updateAddress();\n\n if (!this.source.get('params.invalid')) {\n this.isNewAddressAdded(true);\n this.closeFormPopUp();\n }\n }.bind(this)\n },\n {\n text: this.popUpButtons.cancel.text,\n class: this.popUpButtons.cancel.class,\n click: this.cancelAddressEdit.bind(this)\n }\n ];\n\n this.popUpForm.options.modalCloseBtnHandler = this.cancelAddressEdit.bind(this);\n this.popUpForm.options.keyEventHandlers = {\n escapeKey: this.cancelAddressEdit.bind(this)\n };\n\n /** @inheritdoc */\n this.popUpForm.options.opened = function () {\n // Store temporary address for revert action in case when user click cancel action\n this.temporaryAddress = $.extend(true, {}, checkoutData.getBillingAddressFromData());\n }.bind(this);\n\n this.popUp = modal(this.popUpForm.options, $(element));\n },\n\n /**\n * Show from popUp.\n */\n showFormPopUp: function () {\n this.isAddressFormVisible(true);\n this.popUp.openModal();\n },\n\n /**\n * Close from popUp.\n */\n closeFormPopUp: function () {\n this.isAddressFormVisible(false);\n this.popUp.closeModal();\n },\n\n /**\n * Open address selection modal.\n */\n openAddressSelection: function () {\n this.selectBillingAddress().openModal();\n },\n\n /** @inheritdoc */\n updateAddress: function () {\n this._super();\n\n if (!this.selectedAddress() || this.isAddressFormVisible()) {\n this.newCustomerBillingAddress(createBillingAddress(checkoutData.getNewCustomerBillingAddress()));\n }\n },\n\n /**\n * Is address editable.\n *\n * @param {Object} address\n * @returns {Boolean}\n */\n isAddressEditable: function (address) {\n if (address) {\n return address.getType() === 'new-customer-billing-address';\n }\n }\n });\n});\n","Magento_CheckoutAddressSearch/js/view/billing-address/ui-select.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'Magento_Ui/js/form/element/ui-select',\n 'Magento_Checkout/js/action/select-billing-address',\n 'Magento_Checkout/js/checkout-data',\n 'Magento_Customer/js/model/customer/address',\n 'Magento_Customer/js/customer-data',\n 'Magento_Checkout/js/model/quote'\n], function (_, Select, selectBillingAddress, checkoutData, Address, customerData, quote) {\n 'use strict';\n\n var countryData = customerData.get('directory-data');\n\n return Select.extend({\n defaults: {\n addressTmpl: 'Magento_CheckoutAddressSearch/billing-address/address-renderer/item',\n modal: '${$.parentName}',\n quantityPlaceholder: 'addresses',\n value: {},\n billingAddressProvider: '',\n isNewAddressAdded: false,\n imports: {\n isNewAddressAdded: '${ $.billingAddressProvider }:isNewAddressAdded',\n newCustomerBillingAddress: '${ $.billingAddressProvider }:newCustomerBillingAddress'\n },\n listens: {\n newCustomerBillingAddress: 'onChangeNewCustomerBillingAddress'\n },\n modules: {\n modal: '${ $.modal }',\n billingAddress: '${ $.billingAddressProvider }'\n },\n newAddressInSearchResult: false\n },\n\n /** @inheritdoc */\n initialize: function () {\n this._super();\n\n this._setItemsQuantity(this.total);\n },\n\n /** @inheritdoc */\n initConfig: function () {\n var existingOptions = [];\n\n this._super();\n\n if (this.newCustomerBillingAddress) {\n existingOptions.push(this.newCustomerBillingAddress);\n }\n\n _.each(this.options, function (option) {\n existingOptions.push(new Address(option));\n });\n\n this.options = this.sortAddresses(existingOptions);\n\n return this;\n }
2,\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe('isNewAddressAdded');\n\n quote.billingAddress.subscribe(function (address) {\n if (address) {\n this.value(address);\n }\n }, this);\n\n return this;\n },\n\n /**\n * Set selected customer billing address.\n *\n * @param {Object} option\n */\n selectBillingAddress: function (option) {\n delete option.level;\n delete option.isVisited;\n delete option.path;\n\n this.value(option);\n this.modal().closeModal();\n selectBillingAddress(option);\n checkoutData.setSelectedBillingAddress(option.getKey());\n this.billingAddress().updateAddresses(true);\n },\n\n /**\n * Edit address\n */\n editAction: function () {\n this.modal().closeModal();\n this.billingAddress().editAddress();\n },\n\n /** @inheritdoc */\n success: function (response) {\n var existingOptions = this.options();\n\n _.each(response.options, function (opt) {\n var address = new Address(opt);\n\n // add options only if they were not added yet\n if (!_.findWhere(existingOptions, {\n customerAddressId: address.id\n })) {\n existingOptions.push(address);\n }\n });\n\n this.total = response.total;\n this.newAddressInSearchResult = false;\n\n if (this.newCustomerBillingAddress) {\n existingOptions.push(this.newCustomerBillingAddress);\n }\n\n this.options(this.sortAddresses(existingOptions));\n },\n\n /**\n * Sort addresses.\n *\n * Sort addresses in such way that new address and default one are displayed on the top of results\n * if one of them matches search criteria or search is empty.\n *\n * @param {Array} existingOptions\n * @return {Array}\n */\n sortAddresses: function (existingOptions) {\n var resultOptions = [],\n defaultAddress;\n\n if (!_.isEmpty(this.newCustomerBillingAddress) &&\n this.canShowNewAddress(this.newCustomerBillingAddress, this.currentSearchKey)\n ) {\n if (this.newAddressInSearchResult === false) {\n this._setItemsQuantity(++this.total);\n }\n this.newAddressInSearchResult = true;\n resultOptions.push(this.newCustomerBillingAddress);\n }\n\n defaultAddress = _.find(existingOptions, function (address) {\n return address.isDefaultShipping();\n });\n\n !_.isEmpty(defaultAddress) && resultOptions.push(defaultAddress);\n\n return resultOptions.concat(_.filter(existingOptions, function (address) {\n return address.getType() !== 'new-customer-billing-address' && !address.isDefaultShipping();\n }));\n },\n\n /**\n * Check if we can show address.\n *\n * @param {Object} address\n * @param {String} searchKey\n * @return {Boolean}\n */\n canShowNewAddress: function (address, searchKey) {\n var searchFields = ['city', 'postcode', 'region', ['street']],\n filteredResults = [],\n value = '';\n\n if (!searchKey) {\n return true;\n }\n\n filteredResults = searchFields.filter(function (elem) {\n value = address[elem];\n\n if (_.isArray(value)) {\n value = value.join(' ');\n }\n\n return value.toLowerCase().indexOf(searchKey.toLowerCase()) !== -1;\n });\n\n return !!filteredResults.length;\n },\n\n /**\n * Get country name.\n *\n * @param {String} countryId\n * @return {String}\n */\n getCountryName: function (countryId) {\n return countryData()[countryId] !== undefined ? countryData()[countryId].name : '';\n },\n\n /**\n * Is address selected.\n *\n * @param {Object} address\n * @returns {Boolean}\n */\n isAddressSelected: function (address) {\n return !_.isEmpty(this.value()) && this.value().getKey() === address.getKey();\n },\n\n /**\n * Is address editable.\n *\n * @param {Object} address\n * @returns {Boolean}\n */\n isAddressEditable: function (address) {\n return address.getType() === 'new-customer-billing-address';\n },\n\n /**\n * On new customer billing address change.\n *\n * @param {Object} address\n */\n onChangeNewCustomerBillingAddress: function (address) {\n var options = _.filter(this.options(), function (option) {\n return option.getType() !== 'new-customer-billing-address';\n });\n\n options.push(address);\n this.options(this.sortAddresses(options));\n },\n\n /**\n * Return formatted items placeholder.\n *\n * @param {Object} data - option data\n * @returns {String}
2\n */\n getItemsPlaceholder: function (data) {\n var prefix = '';\n\n if (this.lastSearchKey) {\n prefix = 'Found ';\n }\n\n return prefix + data + ' ' + this.quantityPlaceholder;\n },\n\n /** @inheritdoc */\n onScrollDown: function (data, event) {\n if (this.loading() || this.options().length >= this.total) {\n return;\n }\n\n this._super(data, event);\n }\n });\n});\n","Magento_CheckoutAddressSearch/js/view/shipping-address/selected.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'uiComponent',\n 'mage/translate',\n 'Magento_Customer/js/customer-data',\n 'Magento_Checkout/js/model/shipping-address/form-popup-state',\n 'Magento_Checkout/js/model/quote'\n], function (Component, $t, customerData, formPopUpState, quote) {\n 'use strict';\n\n var countryData = customerData.get('directory-data');\n\n return Component.extend({\n defaults: {\n template: 'Magento_CheckoutAddressSearch/shipping-address/selected',\n selectShippingAddressProvider: '',\n defaultAddress: quote.shippingAddress(),\n isChangeAddressVisible: true,\n modules: {\n selectionModal: '${ $.selectShippingAddressProvider }'\n },\n noAddressMessage: $t('No address selected')\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe('defaultAddress');\n quote.shippingAddress.subscribe(this.onShippingAddressUpdate, this);\n\n return this;\n },\n\n /**\n * Get country name.\n *\n * @param {String} countryId\n * @return {String}\n */\n getCountryName: function (countryId) {\n return countryData()[countryId] !== undefined ? countryData()[countryId].name : '';\n },\n\n /**\n * Edit address.\n */\n editAddress: function () {\n formPopUpState.isVisible(true);\n },\n\n /**\n * Open address selection modal.\n */\n openAddressSelection: function () {\n this.selectionModal().openModal();\n },\n\n /**\n * On shipping address update.\n *\n * @param {Object} address\n */\n onShippingAddressUpdate: function (address) {\n this.defaultAddress(address);\n }\n });\n});\n","Magento_CheckoutAddressSearch/js/view/shipping-address/ui-select.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'Magento_Ui/js/form/element/ui-select',\n 'Magento_Checkout/js/action/select-shipping-address',\n 'Magento_Checkout/js/checkout-data',\n 'Magento_Customer/js/model/customer/address',\n 'Magento_Customer/js/model/address-list',\n 'Magento_Customer/js/customer-data',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/shipping-address/form-popup-state'\n], function (\n _,\n Select,\n selectShippingAddressAction,\n checkoutData,\n Address,\n addressList,\n customerData,\n quote,\n formPopUpState\n) {\n 'use strict';\n\n var countryData = customerData.get('directory-data');\n\n return Select.extend({\n defaults: {\n addressTmpl: 'Magento_CheckoutAddressSearch/shipping-address/address-renderer/item',\n modalProvider: '${ $.parentName }',\n quantityPlaceholder: 'addresses',\n modules: {\n modal: '${ $.modalProvider }'\n },\n newAddressInSearchResult: false\n },\n\n /** @inheritdoc */\n initialize: function () {\n this._super();\n\n this._setItemsQuantity(this.total);\n },\n\n /** @inheritdoc */\n initConfig: function () {\n var existingOptions = [];\n\n this._super();\n\n _.each(this.options, function (option) {\n existingOptions.push(new Address(option));\n });\n\n this.options = this.sortAddresses(existingOptions);\n\n return this;\n }
2,\n\n /** @inheritdoc */\n initObservable: function () {\n this._super();\n\n this.onShippingAddressChange(quote.shippingAddress());\n quote.shippingAddress.subscribe(this.onShippingAddressChange, this);\n\n addressList.subscribe(function (changes) {\n _.each(changes, function (change) {\n\n if (change.status === 'added' && change.value.getType() === 'new-customer-address') {\n this.options().push(change.value);\n this.options(this.sortAddresses(this.options()));\n }\n }, this);\n }, this, 'arrayChange');\n\n return this;\n },\n\n /**\n * On shipping address change.\n *\n * @param {Object} address\n */\n onShippingAddressChange: function (address) {\n if (address) {\n this.options(this.sortAddresses(this.options()));\n }\n this.value(address);\n },\n\n /**\n * Set selected customer shipping address.\n *\n * @param {Object} option\n */\n selectShippingAddress: function (option) {\n delete option.level;\n delete option.isVisited;\n delete option.path;\n\n this.value(option);\n this.modal().closeModal();\n selectShippingAddressAction(option);\n checkoutData.setSelectedShippingAddress(option.getKey());\n },\n\n /**\n * Edit address.\n */\n editAction: function () {\n this.modal().closeModal();\n formPopUpState.isVisible(true);\n },\n\n /** @inheritdoc */\n success: function (response) {\n var existingOptions = this.options();\n\n // eliminate duplicates from ui-select search result\n _.each(response.options, function (opt) {\n if (!_.findWhere(existingOptions, {\n customerAddressId: opt.id\n })) {\n existingOptions.push(new Address(opt));\n }\n });\n\n this.total = response.total;\n this.newAddressInSearchResult = false;\n\n this.options(this.sortAddresses(existingOptions));\n },\n\n /**\n * Sort addresses.\n *\n * Sort addresses in such way that new address and default one are displayed on the top of results\n * if one of them matches search criteria or search is empty.\n *\n * @param {Array} existingOptions\n * @return {Array}\n */\n sortAddresses: function (existingOptions) {\n\n var resultOptions = [],\n defaultAddress, newAddress;\n\n newAddress = _.find(addressList(), function (address) {\n return address.getType() === 'new-customer-address';\n });\n\n if (!_.isEmpty(newAddress) && this.canShowNewAddress(newAddress, this.currentSearchKey)) {\n if (this.newAddressInSearchResult === false) {\n this._setItemsQuantity(++this.total);\n }\n this.newAddressInSearchResult = true;\n resultOptions.push(newAddress);\n }\n\n defaultAddress = _.find(existingOptions, function (address) {\n return address.isDefaultShipping();\n });\n\n !_.isEmpty(defaultAddress) && resultOptions.push(defaultAddress);\n\n return resultOptions.concat(_.filter(existingOptions, function (address) {\n return address.getType() !== 'new-customer-address' && !address.isDefaultShipping();\n }));\n },\n\n /**\n * Check if we can show address.\n *\n * @param {Object} address\n * @param {String} searchKey\n * @return {Boolean}\n */\n canShowNewAddress: function (address, searchKey) {\n var searchFields = ['city', 'postcode', 'region', ['street']],\n filteredResults = [],\n value = '';\n\n if (!searchKey) {\n return true;\n }\n\n filteredResults = searchFields.filter(function (elem) {\n value = address[elem];\n\n if (_.isArray(value)) {\n value = value.join(' ');\n }\n\n return value.toLowerCase().indexOf(searchKey.toLowerCase()) !== -1;\n });\n\n return !!filteredResults.length;\n },\n\n /**\n * Get country name.\n *\n * @param {String} countryId\n * @return {String}\n */\n getCountryName: function (countryId) {\n return countryData()[countryId] !== undefined ? countryData()[countryId].name : '';\n },\n\n /**\n * Is address selected.\n *\n * @param {Object} address\n * @returns {Boolean}\n */\n isAddressSelected: function (address) {\n return !_.isEmpty(this.value()) && this.value().getKey() === address.getKey();\n },\n\n /**\n * Return formatted items placeholder.\n *\n * @param {Object} data - option data\n * @returns {String}
2\n */\n getItemsPlaceholder: function (data) {\n var prefix = '';\n\n if (this.lastSearchKey) {\n prefix = 'Found ';\n }\n\n return prefix + data + ' ' + this.quantityPlaceholder;\n },\n\n /** @inheritdoc */\n onScrollDown: function (data, event) {\n if (this.loading() || this.options().length >= this.total) {\n return;\n }\n\n this._super(data, event);\n }\n });\n});\n","Magento_Reports/js/recently-viewed.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget'\n], function ($) {\n 'use strict';\n\n $.widget('mage.recentlyViewedProducts', {\n options: {\n localStorageKey: 'recently-viewed-products',\n productBlock: '#widget_viewed_item',\n viewedContainer: 'ol'\n },\n\n /**\n * Bind events to the appropriate handlers.\n * @private\n */\n _create: function () {\n var productHtml = $(this.options.productBlock).html(),\n productSku = $(this.options.productBlock).data('sku'),\n products = JSON.parse(window.localStorage.getItem(this.options.localStorageKey)),\n productsLength, maximum, showed, index;\n\n if (products) {\n productsLength = products.sku.length;\n maximum = $(this.element).data('count');\n showed = 0;\n\n for (index = 0; index <= productsLength; index++) {\n if (products.sku[index] == productSku || showed >= maximum) { //eslint-disable-line\n products.sku.splice(index, 1);\n products.html.splice(index, 1);\n } else {\n $(this.element).find(this.options.viewedContainer).append(products.html[index]);\n $(this.element).show();\n showed++;\n }\n }\n $(this.element).find(this.options.productBlock).show();\n } else {\n products = {};\n products.sku = [];\n products.html = [];\n }\n products.sku.unshift(productSku);\n products.html.unshift(productHtml);\n window.localStorage.setItem(this.options.localStorageKey, JSON.stringify(products));\n }\n });\n\n return $.mage.recentlyViewedProducts;\n});\n","Amasty_DatePicker/js/autoload-datepicker-extend.js":"define([], function() {\n 'use strict';\n\n return function(widget) {\n require(['Amasty_DatePicker/js/datepicker-extend']);\n\n return widget;\n };\n});\n","Amasty_DatePicker/js/datepicker-extend.js":"/**\n * Amasty DatePicker Extension\n *\n * This module overrides jQuery UI Datepicker's _showDatepicker method\n * to apply accessibility enhancements.\n */\ndefine([\n 'jquery',\n 'Amasty_DatePicker/js/datepicker-accessibility',\n 'domReady!'\n], function ($, DatePickerAccessibility) {\n 'use strict';\n\n if (!$.datepicker) {\n return;\n }\n\n const accessibility = new DatePickerAccessibility();\n\n const originalConnect = $.datepicker._connectDatepicker;\n\n $.datepicker._connectDatepicker = function(target, inst) {\n originalConnect.call(this, target, inst);\n\n if (!$(target).hasClass('am-datepicker-observed')) {\n return;\n }\n\n requestAnimationFrame(() => accessibility.updateInputLabel($(target)));\n };\n\n const originalSelectDate = $.datepicker._selectDate;\n\n $.datepicker._selectDate = function(id, dateStr) {\n const inputElement = typeof id === 'string' ? document.querySelector(id) : (id?.currentTarget || id);\n\n originalSelectDate.call(this, id, dateStr);\n\n if (!inputElement || !inputElement.closest || !inputElement.closest('.am-datepicker-observed')) {\n return;\n }\n\n requestAnimationFrame(() =>
2 {\n const $updatedCalendar = $(accessibility.calendarSelector);\n accessibility.makeCalendarAccessible($updatedCalendar, inputElement, true);\n });\n };\n\n const originalHide = $.datepicker._hideDatepicker;\n\n $.datepicker._hideDatepicker = function() {\n originalHide.apply(this, arguments);\n accessibility.markClosed();\n };\n\n const originalShow = $.datepicker._showDatepicker;\n\n /**\n * Override of jQuery UI Datepicker's _showDatepicker method\n * @param {HTMLElement|Event} datepickerInput - The input element or event object\n */\n $.datepicker._showDatepicker = function(datepickerInput) {\n const actualInput = datepickerInput?.currentTarget || datepickerInput;\n\n if (datepickerInput?.type === 'focus'\n && !!actualInput?.closest?.('.am-datepicker-observed')\n ) {\n return;\n }\n\n const skipInitialFocus = !!$.datepicker?._datepickerShowing;\n\n if (!skipInitialFocus) {\n accessibility.setOpenerElement(document.activeElement);\n }\n\n originalShow.call(this, datepickerInput);\n\n if (!actualInput || !actualInput.closest || !actualInput.closest('.am-datepicker-observed')) {\n return;\n }\n\n accessibility.makeCalendarAccessible($('#ui-datepicker-div'), actualInput, skipInitialFocus);\n\n $(actualInput).on('click', function () {\n $(this).datepicker('hide');\n });\n };\n\n $('.am-datepicker-observed').each(function() {\n let inst;\n\n try {\n inst = $.datepicker._getInst(this);\n } catch (e) {\n return;\n }\n\n if (inst?.trigger?.length) {\n accessibility.updateInputLabel($(this));\n }\n });\n\n return accessibility;\n});\n","Amasty_DatePicker/js/datepicker-accessibility.js":"/**\n * Amasty DatePicker Accessibility Class\n *\n * This module provides accessibility features for jQuery UI Datepicker\n * to comply with WCAG 2.1 standards and improve keyboard navigation.\n *\n * Features:\n * - ARIA attributes for screen reader support\n * - Full keyboard navigation (Arrow keys, Home, End, PageUp, PageDown)\n * - Focus trap within the calendar dialog\n * - Roving tabindex for grid navigation\n * - Custom OK/Cancel buttons\n * - Accessible labels and announcements\n *\n * Keyboard shortcuts:\n * - Arrow keys: Navigate between dates\n * - Home/End: Jump to first/last day of week\n * - PageUp/PageDown: Navigate to previous/next month\n * - Shift+PageUp/PageDown: Navigate to previous/next year\n * - Enter/Space: Select date or activate button\n * - Tab: Navigate between focusable elements\n * - Esc: Close calendar\n */\ndefine([\n 'jquery',\n 'Amasty_DatePicker/js/accessibility/aria-manager',\n 'Amasty_DatePicker/js/accessibility/focus-manager',\n 'Amasty_DatePicker/js/accessibility/keyboard-handler',\n 'Amasty_DatePicker/js/accessibility/ui-manager'\n], function ($, AriaManager, FocusManager, KeyboardHandler, UiManager) {\n 'use strict';\n\n /**\n * DatePicker Accessibility Class\n */\n class DatePickerAccessibility {\n /**\n * Constructor\n */\n constructor() {\n this.calendarSelector = '#ui-datepicker-div';\n this.rowLength = 7;\n\n this.ariaManager = new AriaManager();\n this.focusManager = new FocusManager();\n\n this.keyboardHandler = new KeyboardHandler({\n calendarSelector: this.calendarSelector,\n rowLength: this.rowLength,\n focusManager: this.focusManager,\n makeCalendarAccessible: this.makeCalendarAccessible.bind(this),\n focusOnDay: this.focusOnDay.bind(this),\n focusAfterClose: this.focusAfterClose.bind(this),\n handleCancelButton: () => this.uiManager.handleCancelButton(),\n });\n\n this.uiManager = new UiManager({\n calendarSelector: this.calendarSelector,\n replaceSelectsWithLabelCallback: this.replaceSelectsWithLabel.bind(this),\n updateInputLabelCallback: this.updateInputLabel.bind(this),\n makeCalendarAccessibleCallback: this.makeCalendarAccessible.bind(this)\n });\n }\n\n /**\n * Replaces month/year select dropdowns with a text label\n * @param {jQuery} $calendar - The calendar jQuery element\n */\n replaceSelectsWithLabel($calendar) {\n this.uiManager.replaceSelectsWithLabel($calendar);\n }\n\n /**\n * Updates the ARIA label of the input field with the selected date\n * @param {jQuery} $input - The input jQuery element\n */\n updateInputLabel($input) {\n this.ariaManager.updateInputLabel($input);\n }
2\n\n /**\n * Focuses on a specific day number in the calendar\n * @param {jQuery} $calendar - The calendar jQuery element\n * @param {number} targetDay - The day number to focus (1-31)\n */\n focusOnDay($calendar, targetDay) {\n this.focusManager.focusOnDay($calendar, targetDay);\n }\n\n focusAfterClose() {\n this.uiManager.focusAfterClose();\n }\n\n markClosed() {\n this.uiManager.markClosed();\n }\n\n setOpenerElement(el) {\n this.uiManager.setOpenerElement(el);\n }\n\n /**\n * Main function to make the calendar accessible with ARIA attributes and keyboard navigation\n * @param {jQuery} $calendar - The calendar jQuery element\n * @param {HTMLElement} inputElement - The input element associated with the calendar\n * @param {boolean} [skipInitialFocus=false] - Whether to skip setting initial focus\n */\n makeCalendarAccessible($calendar, inputElement, skipInitialFocus) {\n $calendar.addClass('amasty-custom-datepicker');\n this.uiManager.setInputElement(inputElement);\n this.ariaManager.setAriaAttributes($calendar);\n this.replaceSelectsWithLabel($calendar);\n\n const {$table, $title} = this.ariaManager.setupTableGrid($calendar);\n\n this.uiManager.setupNavigationButtons($calendar);\n this.ariaManager.setupTimeLabels($calendar);\n this.ariaManager.setupTableStructure($table);\n this.ariaManager.setupDateCells($table, $title);\n this.focusManager.removeTableFocus($table);\n this.ariaManager.updateInputLabel($(inputElement));\n\n this.keyboardHandler.setupKeyboardNavigation($calendar, $table, inputElement);\n this.focusManager.setupFocusTrap($calendar);\n\n if (!skipInitialFocus) {\n requestAnimationFrame(() => this.focusManager.setInitialFocus($calendar));\n }\n }\n }\n\n return DatePickerAccessibility;\n});\n\n","Amasty_DatePicker/js/accessibility/ui-manager.js":"/**\n * UI Elements Manager\n *\n * Manages UI elements (buttons, labels) for the datepicker calendar\n */\ndefine([\n 'jquery',\n 'mage/translate'\n], function ($, $t) {\n 'use strict';\n\n /**\n * UI Manager Class\n */\n class UiManager {\n /**\n * Constructor\n * @param {Object} config - Configuration object\n * @param {string} config.calendarSelector - Calendar selector\n * @param {Function} config.replaceSelectsWithLabelCallback - Callback to replace selects\n * @param {Function} config.updateInputLabelCallback - Callback to update input label\n * @param {Function} config.makeCalendarAccessibleCallback - Callback to fully reinitialize calendar accessibility\n */\n constructor(config) {\n this.calendarSelector = config.calendarSelector;\n this.replaceSelectsWithLabelCallback = config.replaceSelectsWithLabelCallback;\n this.updateInputLabelCallback = config.updateInputLabelCallback;\n this.makeCalendarAccessibleCallback = config.makeCalendarAccessibleCallback;\n this.inputElement = null;\n this.originalValue = null;\n this.isOpen = false;\n this.openerElement = null;\n }\n\n /**\n * Sets the current input element associated with the open calendar\n * @param {HTMLElement} inputElement\n */\n setInputElement(inputElement) {\n if (!this.isOpen) {\n this.originalValue = $(inputElement).val();\n this.isOpen = true;\n }\n this.inputElement = inputElement;\n }\n\n setOpenerElement(el) {\n this.openerElement = el;\n }\n\n resetOpenState() {\n this.isOpen = false;\n this.originalValue = null;\n }\n\n markClosed() {\n this.isOpen = false;\n }\n\n /**\n * Replaces month/year select dropdowns with a text label\n * @param {jQuery} $calendar - The calendar jQuery element\n */\n replaceSelectsWithLabel($calendar) {\n const $monthSelect = $calendar.find('.ui-datepicker-month');\n const $yearSelect = $calendar.find('.ui-datepicker-year');\n const $title = $calendar.find('.ui-datepicker-title');\n\n if (($monthSelect.length > 0 || $yearSelect.length > 0) && !$title.hasClass('label-replaced')) {\n const monthText = $monthSelect.length > 0 ? $monthSelect.find('option:selected').text() : '';\n const yearText = $yearSelect.length > 0 ? $yearSelect.find('option:selected').text() : '';\n const labelText = monthText && yearText ? `${monthText} ${yearText}` :\n monthText ? monthText : yearText;\n\n $monthSelect.remove();\n $yearSelect.remove();\n\n if (labelText) {\n const $label = $('<span>')\n .addClass('ui-datepicker-month-year-label')\n .text(labelText);\n\n $title.empty().append($label).addClass('label-replaced');\n }\n } else if ($title.length > 0 && !$title.hasClass('label-replaced')) {\n $title.addClass('label-replaced');\n }\n }\n\n /**\n * Sets up navigation buttons (prev/next) with ARIA attributes and event handlers\n * @param {jQuery} $calendar - The calendar jQuery element\n */\n setupNavigationButtons($calendar) {\n const $prevButton = $calendar.find('.ui-datepicker-prev');\n const $nextButton = $calendar.find('.ui-datepicker-next');\n\n $prevButton.attr({\n 'role': 'button',\n 'aria-label': $t('Previous Month'),\n 'tabindex': '0'\n }).removeAttr('title');\n\n $nextButton.attr({\n 'role': 'button',\n 'aria-label': $t('Next Month'),\n 'tabindex': '0'\n }).removeAttr('title');\n\n $calendar.find('.ui-datepicker-prev, .ui-datepicker-next')\n .off('click.update-label')\n .on('click.update-label', () => requestAnimationFrame(() =>
2 {\n this.makeCalendarAccessibleCallback($(this.calendarSelector), this.inputElement, false);\n }));\n\n this.createActionButtons($calendar);\n }\n\n /**\n * Creates and sets up custom OK/Cancel buttons for the calendar\n * @param {jQuery} $calendar - The calendar jQuery element\n */\n createActionButtons($calendar) {\n $calendar.find('.ui-datepicker-buttonpane').hide();\n\n if ($calendar.find('.custom-datepicker-buttonpane').length === 0) {\n const $buttonPane = $('<div>')\n .addClass('custom-datepicker-buttonpane');\n\n const $cancelButton = $('<button>')\n .addClass('custom-datepicker-cancel')\n .attr({\n 'type': 'button',\n 'role': 'button',\n 'aria-label': $t('Cancel'),\n 'tabindex': '0'\n })\n .text($t('Cancel'));\n\n const $okButton = $('<button>')\n .addClass('custom-datepicker-ok')\n .attr({\n 'type': 'button',\n 'role': 'button',\n 'aria-label': $t('OK'),\n 'tabindex': '0'\n })\n .text($t('OK'));\n\n $buttonPane.append($cancelButton, $okButton);\n $calendar.append($buttonPane);\n\n $cancelButton.on('click', (e) => {\n e.preventDefault();\n this.handleCancelButton();\n });\n\n $okButton.on('click', (e) => {\n e.preventDefault();\n this.handleOkButton();\n });\n\n $cancelButton.on('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.handleCancelButton();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n this.handleCancelButton();\n }\n });\n\n $okButton.on('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.handleOkButton();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n this.handleCancelButton();\n }\n });\n }\n }\n\n /**\n * Resolves the trigger button or input to return focus to after closing\n * @returns {jQuery} - The element to focus\n */\n resolveFocusTarget() {\n const $opener = this.openerElement ? $(this.openerElement) : null;\n\n if ($opener?.length && !$opener.is('body') && $opener.is(':visible') && !$opener.prop('disabled')) {\n return $opener;\n }\n\n const $input = this.inputElement\n ? $(this.inputElement)\n : $('input.hasDatepicker').first();\n\n if (!$input.length) {\n return $();\n }\n\n let inst;\n\n try {\n inst = $.datepicker._getInst($input[0]);\n } catch (e) {\n return $input;\n }\n\n const $trigger = inst?.trigger;\n\n if ($trigger?.length && $trigger.is(':visible')) {\n return $trigger;\n }\n\n return $input;\n }\n\n /**\n * Focuses the trigger element after the calendar is closed\n */\n focusAfterClose() {\n const [el] = this.resolveFocusTarget();\n\n if (!el) {\n return;\n }\n\n if (el.tagName === 'INPUT') {\n //prevent calendar reopen for showOn: 'both' or 'focus'\n $.datepicker._lastInput = el;\n }\n\n el?.focus();\n $.datepicker._lastInput = null;\n }\n\n /**\n * Handles cancel button click\n */\n handleCancelButton() {\n const originalValue = this.originalValue;\n const $input = this.inputElement ? $(this.inputElement) : $('input.hasDatepicker').first();\n\n this.resetOpenState();\n $.datepicker._hideDatepicker();\n\n if (originalValue !== null) {\n $input.val(originalValue);\n }\n\n this.focusAfterClose();\n }\n\n /**\n * Handles OK button click\n */\n handleOkButton() {\n const $input = this.inputElement ? $(this.inputElement) : $('input.hasDatepicker').first();\n const $selected = $(this.calendarSelector).find('td.ui-datepicker-current-day a').first();\n\n if ($selected.length) $selected.click();\n\n this.resetOpenState();\n $.datepicker._hideDatepicker();\n\n const [inputEl] = $input;\n\n if (inputEl) this.updateInputLabelCallback($input);\n\n this.focusAfterClose();\n }\n }\n\n return UiManager;\n});\n\n","Amasty_DatePicker/js/accessibility/aria-manager.js":"/**\n * ARIA Attributes Manager\n *\n * Manages ARIA attributes for the datepicker calendar\n */\ndefine([\n 'jquery',\n 'mage/translate',\n 'mage/utils/misc'\n], function ($, $t, utils) {\n 'use strict';\n\n /**\n * ARIA Manager Class\n */\n class AriaManager {\n /**\n * Sets ARIA attributes for the calendar dialog\n * @param {jQuery} $calendar - The calendar jQuery element\n */\n isDateTimePicker($calendar) {\n return $calendar && $calendar.find('.ui-timepicker-div').length > 0;\n }\n\n setAriaAttributes($calendar) {\n const label = this.isDateTimePicker($calendar) ? $t('Choose Date and Time') : $t('Choose Date');\n\n $calendar.attr({\n 'role': 'dialog',\n 'aria-modal'
2: 'true',\n 'aria-label': label,\n 'tabindex': '-1'\n });\n }\n\n /**\n * Sets up the calendar table grid with proper ARIA attributes\n * @param {jQuery} $calendar - The calendar jQuery element\n * @returns {{$table: jQuery, $title: jQuery}} Object containing table and title elements\n */\n setupTableGrid($calendar) {\n const $table = $calendar.find('.ui-datepicker-calendar');\n\n $table.attr({\n 'role': 'grid',\n 'aria-labelledby': 'ui-datepicker-title'\n });\n\n const $header = $calendar.find('.ui-datepicker-header');\n const $title = $header.find('.ui-datepicker-title');\n\n if (!$title.attr('id')) {\n $title.attr('id', 'ui-datepicker-title');\n }\n\n $title.attr('aria-live', 'polite');\n\n return {$table, $title};\n }\n\n /**\n * Sets up table structure with proper ARIA roles for rows and headers\n * @param {jQuery} $table - The table jQuery element\n */\n setupTableStructure($table) {\n $table.find('thead tr').attr('role', 'row');\n $table.find('tbody tr').attr('role', 'row');\n\n $table.find('thead th').each(function() {\n $(this).attr({\n 'role': 'columnheader',\n 'aria-label': $(this).text()\n });\n });\n }\n\n /**\n * Builds a human-readable aria-label for a date cell link\n * @param {string} day - Day number as text\n * @param {string} month - Month/year string from the calendar title\n * @param {boolean} isToday\n * @param {boolean} isSelected\n * @returns {string}\n */\n buildDateAriaLabel(day, month, isToday, isSelected) {\n let label = day + ' ' + month;\n\n if (isToday) label += ', ' + $t('today');\n if (isSelected) label += ', ' + $t('selected');\n\n return label;\n }\n\n /**\n * Formats a data-date attribute value (YYYY-MM-DD) from link data attributes.\n * Returns null when the required attributes are missing or invalid.\n * @param {jQuery} $link\n * @returns {string|null}\n */\n formatDataDate($link) {\n const dayNum = parseInt($link.text());\n\n if (isNaN(dayNum) || !$link.attr('data-month') || !$link.attr('data-year')) {\n return null;\n }\n\n const monthNum = parseInt($link.attr('data-month'));\n const yearNum = parseInt($link.attr('data-year'));\n const d = String(dayNum).padStart(2, '0');\n const m = String(monthNum + 1).padStart(2, '0');\n\n return yearNum + '-' + m + '-' + d;\n }\n\n /**\n * Sets up date cells with ARIA attributes and labels\n * @param {jQuery} $table - The table jQuery element\n * @param {jQuery} $title - The title jQuery element containing month/year\n */\n setupDateCells($table, $title) {\n const month
2= $title.text();\n\n $table.find('tbody td').each((_, el) => {\n const $cell = $(el);\n const $link = $cell.find('a');\n const $span = $cell.find('span');\n\n $cell.attr('role', 'gridcell');\n\n if ($link.length > 0) {\n const isToday = $cell.hasClass('ui-datepicker-today');\n const isSelected = $cell.hasClass('ui-datepicker-current-day');\n const dataDate = this.formatDataDate($link);\n\n if (dataDate) {\n $cell.attr('data-date', dataDate);\n }\n\n $link.attr({\n 'role': 'button',\n 'aria-label': this.buildDateAriaLabel($link.text(), month, isToday, isSelected),\n 'aria-current': isToday ? 'date' : null,\n 'tabindex': '-1'\n });\n\n if (isSelected) {\n $cell.attr('aria-selected', 'true');\n } else {\n $cell.removeAttr('aria-selected');\n }\n } else if ($span.length > 0) {\n $cell.attr('aria-disabled', 'true');\n $span.attr('aria-hidden', 'true');\n }\n });\n }\n\n /**\n * Builds a verbose \"Change Date, Monday 1 January, 2026\" label\n * from a datepicker instance. Returns null when data is unavailable.\n * @param {Object} inst - jQuery UI datepicker instance\n * @returns {string|null}\n */\n formatSelectedDateLabel(inst, isDateTime) {\n if (!inst || !inst.selectedYear || inst.selectedMonth === undefined || !inst.selectedDay) {\n return null;\n }\n\n const dayLabels = [\n $t('Sunday'), $t('Monday'), $t('Tuesday'), $t('Wednesday'),\n $t('Thursday'), $t('Friday'), $t('Saturday')\n ];\n const monthLabels = [\n $t('January'), $t('February'), $t('March'), $t('April'),\n $t('May'), $t('June'), $t('July'), $t('August'),\n $t('September'), $t('October'), $t('November'), $t('December')\n ];\n\n const date = new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay);\n const prefix = isDateTime ? $t('Change Date and Time') : $t('Change Date');\n\n return prefix\n + ', ' + dayLabels[date.getDay()]\n + ' ' + date.getDate()\n + ' ' + monthLabels[date.getMonth()]\n + ', ' + date.getFullYear();\n }\n\n /**\n * @param {jQuery} $calendar - The calendar jQuery element\n */\n setupTimeLabels($calendar) {\n const $timepickerDiv = $calendar.find('.ui-timepicker-div');\n\n if (!$timepickerDiv.length) {\n return;\n }\n\n const $timeInputs = $timepickerDiv.find('dd:not(.ui_tpicker_unit_hide) [data-unit]');\n\n $timeInputs.each((key, el) => {\n const $el = $(el);\n const unit = el.dataset.unit;\n const id = utils.uniqueid();\n const labelContainer = $timepickerDiv.find('.ui_tpicker_' + unit + '_label');\n const label = document.createElement('label');\n\n el.id = id;\n label.textContent = labelContainer.text();\n label.setAttribute('for', id);\n label.classList.add('label');\n labelContainer.html(label);\n\n $el.off('change.am-timepicker-focus').on('change.am-timepicker-focus', (e) => {\n this.retainTimeSelectFocus($calendar, e.target.dataset.unit);\n });\n })\n }\n\n /**\n * jQuery UI Timepicker Addon (controlType: 'select') discards and recreates\n * every unit <select> on each change to apply updated min/max/step constraints,\n * which drops focus from the option the user just picked. Restores ARIA labels\n * and refocuses the freshly created control for the same time unit once the\n * rebuild completes.\n * @param {jQuery} $calendar - The calendar jQuery element\n * @param {string} unit - The time unit of the changed control (e.g. 'hour', 'minute')\n */\n retainTimeSelectFocus($calendar, unit) {\n if (!unit) {\n return;\n }\n\n requestAnimationFrame(() =>
2 {\n this.setupTimeLabels($calendar);\n\n const [select] = $calendar.find(`.ui-timepicker-select[data-unit=\"${unit}\"]`);\n\n select?.focus();\n });\n }\n\n /**\n * Updates the ARIA label of the input field with the selected date\n * @param {jQuery} $input - The input jQuery element\n */\n updateInputLabel($input) {\n let label;\n const inst = $.datepicker._getInst($input[0]);\n const isDateTime = inst ? this.isDateTimePicker(inst.dpDiv) : false;\n const choosePlaceholder = isDateTime ? $t('Choose Date and Time') : $t('Choose Date');\n\n if (!$input.val()) {\n label = choosePlaceholder;\n } else {\n try {\n label = this.formatSelectedDateLabel(inst, isDateTime) || choosePlaceholder;\n } catch (e) {\n label = choosePlaceholder;\n }\n }\n\n $input.attr('aria-label', label);\n\n const $trigger = $input.next('.ui-datepicker-trigger');\n\n if ($trigger.length) {\n $trigger.attr('aria-label', label);\n }\n }\n }\n\n return AriaManager;\n});\n\n","Amasty_DatePicker/js/accessibility/keyboard-handler.js":"/**\n * Keyboard Navigation Handler\n *\n * Handles keyboard navigation for the datepicker calendar\n */\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n /**\n * Keyboard Handler Class\n */\n class KeyboardHandler {\n /**\n * Constructor\n * @param {Object} config - Configuration object\n * @param {string} config.calendarSelector - Calendar selector\n * @param {number} config.rowLength - Number of columns in grid\n * @param {FocusManager} config.focusManager - Focus manager instance\n * @param {Function} config.makeCalendarAccessible - Callback to reinitialize calendar\n * @param {Function} config.focusOnDay - Callback to focus on specific day\n * @param {Function} config.focusAfterClose - Callback to handle focus after calendar close\n */\n constructor(config) {\n this.calendarSelector = config.calendarSelector;\n this.rowLength = config.rowLength;\n this.focusManager = config.focusManager;\n this.makeCalendarAccessible = config.makeCalendarAccessible;\n this.focusOnDay = config.focusOnDay;\n this.focusAfterClose = config.focusAfterClose;\n this.handleCancelButton = config.handleCancelButton;\n }\n\n /**\n * Clicks a prev/next navigation button, restores focus to the same day,\n * then returns focus to the nav button.\n * @param {jQuery} $btn - The nav button element\n * @param {HTMLElement} inputElement\n */\n activateNavButton($btn, inputElement) {\n const isPrev = $btn.hasClass('ui-datepicker-prev');\n const $activeTd = this.focusManager.getSelectableCells($(this.calendarSelector))\n .filter((_, td) => $(td).attr('tabindex') === '0')\n .first();\n const currentDay = parseInt($activeTd.find('a').text()) || 1;\n\n this.navigateByMonthCount(inputElement, isPrev ? -1 : +1, currentDay, ($updated) => {\n const $activeCell = this.focusManager.getSelectableCells($updated)\n .filter((_, td) => $(td).attr('tabindex') === '0')\n .first();\n\n $activeCell.addClass('am-datepicker-cell-active');\n\n const [btnEl] = isPrev\n ? $updated.find('.ui-datepicker-prev')\n : $updated.find('.ui-datepicker-next');\n\n btnEl?.focus();\n\n $updated.one('focusin.cell-active', 'td', () => {\n $updated.find('.am-datepicker-cell-active').removeClass('am-datepicker-cell-active');\n });\n });\n }\n\n /**\n * Navigates to an adjacent month and focuses the boundary cell.\n * Used by ArrowLeft (prev month, last cell) and ArrowRight (next month, first cell).\n * @param {HTMLElement} inputElement\n * @param {number} offset - Month offset: -1 for previous, +1 for next\n * @param {'first'|'last'} edge - Which boundary cell to focus after navigation\n */\n navigateToMonth(inputElement, offset, edge) {\n $.datepicker._adjustDate($(inputElement), offset, 'M');\n\n requestAnimationFrame(() =>
2 {\n const $updatedCalendar = $(this.calendarSelector);\n\n this.makeCalendarAccessible($updatedCalendar, inputElement, true);\n\n const $cells = this.focusManager.getSelectableCells($updatedCalendar);\n\n if (!$cells.length) return;\n\n const newIndex = edge === 'first' ? 0 : $cells.length - 1;\n const [cellEl] = edge === 'first' ? $cells : [...$cells].reverse();\n\n this.focusManager.updateRovingTabindex($cells, newIndex);\n cellEl?.focus();\n });\n }\n\n /**\n * Navigates forward or backward by months/years and restores focus to the same day.\n * Used by PageUp (back) and PageDown (forward).\n * @param {HTMLElement} inputElement\n * @param {number} offset - Signed month count (negative = back, positive = forward)\n * @param {number} targetDay - Day number to restore focus to after navigation\n * @param {Function} [afterNavigate] - Optional callback run after focusOnDay\n */\n navigateByMonthCount(inputElement, offset, targetDay, afterNavigate) {\n $.datepicker._adjustDate($(inputElement), offset, 'M');\n\n requestAnimationFrame(() => {\n const $updated = $(this.calendarSelector);\n\n this.makeCalendarAccessible($updated, inputElement, true);\n this.focusOnDay($updated, targetDay);\n afterNavigate?.($updated);\n });\n }\n\n /**\n * Finds the nearest selectable <td> sibling in the given direction\n * by walking through all tbody cells in DOM order.\n * @param {jQuery} $calendar\n * @param {jQuery} $fromCell - Currently focused cell\n * @param {'left'|'right'} direction\n * @returns {jQuery|null}\n */\n findAdjacentCell($calendar, $fromCell, direction) {\n const $allTd = $calendar.find('tbody td');\n const domIndex = $allTd.index($fromCell);\n const step = direction === 'left' ? -1 : 1;\n const limit = direction === 'left' ? -1 : $allTd.length;\n\n for (let i = domIndex + step; i !== limit; i += step) {\n const $td = $allTd.eq(i);\n\n if (this.focusManager.isSelectableCell($td)) {\n return $td;\n }\n }\n\n return null;\n }\n\n /**\n * Moves focus to an adjacent cell in the same column, one row up or down.\n * @param {jQuery} $focused - Currently focused cell\n * @param {jQuery} $allCells - All selectable cells\n * @param {'prev'|'next'} rowDirection\n */\n navigateVertical($focused, $allCells, rowDirection) {\n const $currentRow = $focused.closest('tr');\n const colIndex = $currentRow.find('td').index($focused);\n const $target = $currentRow[rowDirection]('tr').find('td').eq(colIndex);\n const [targetEl] = $target;\n\n if (targetEl && this.focusManager.isSelectableCell($target)) {\n this.focusManager.updateRovingTabindex($allCells, $allCells.index($target));\n targetEl.focus();\n }\n }\n\n /**\n * Moves focus to the nearest selectable cell left or right,\n * crossing into the adjacent month when at the boundary.\n * @param {jQuery} $focused - Currently focused cell\n * @param {jQuery} $calendar\n * @param {jQuery} $allCells\n * @param {HTMLElement} inputElement\n * @param {'left'|'right'} direction\n */\n navigateHorizontal($focused, $calendar, $allCells, inputElement, direction) {\n const $target = this.findAdjacentCell($calendar, $focused, direction);\n\n if ($target) {\n this.focusManager.updateRovingTabindex($allCells, $allCells.index($target));\n $target.focus();\n } else {\n this.navigateToMonth(inputElement, direction === 'left' ? -1 : +1, direction === 'left' ? 'last' : 'first');\n }\n }\n\n /**\n * Handles arrow key navigation within the calendar grid\n * @param {KeyboardEvent} e - The keyboard event\n * @param {jQuery} $calendar - The calendar jQuery element\n * @param {HTMLElement} inputElement - The input element associated with the calendar\n * @param {jQuery} $allCells - Collection of all selectable <td> elements\n * @param {number} currentIndex - Current focused cell index\n * @returns {{handled: boolean}}\n */\n handleArrowNavigation(e, $calendar, inputElement, $allCells, currentIndex) {\n const $focused = $allCells.eq(currentIndex);\n\n switch (e.key) {\n case 'ArrowLeft':\n e.preventDefault();\n this.navigateHorizontal($focused, $calendar, $allCells, inputElement, 'left');\n return {handled: true};\n\n case 'ArrowRight':\n e.preventDefault();\n this.navigateHorizontal($focused, $calendar, $allCells, inputElement, 'right');\n return {handled: true};\n\n case 'ArrowUp':\n e.preventDefault();\n this.navigateVertical($focused, $allCells, 'prev');\n return {handled: true};\n\n case 'ArrowDown':\n e.preventDefault();\n this.navigateVertical($focused, $allCells, 'next');\n return {handled: true};\n\n default:\n return {handled: false};\n }\n }\n\n /**\n * Handles grid navigation keys (Home/End/PageUp/PageDown/Arrows) for a focused date cell.\n * @param {KeyboardEvent} e\n * @param {jQuery} $calendar\n * @param {HTMLElement} inputElement\n * @returns {false|undefined}\n */\n handleGridNavigation(e, $calendar, inputElement) {\n const $focused = $(document.activeElement);
2\n const $activeTd = $focused.is('td') ? $focused : $focused.closest('td');\n\n if (!$activeTd.length || !$.contains($calendar[0], $activeTd[0])) return;\n\n e.preventDefault();\n\n const $allCells = this.focusManager.getSelectableCells($calendar);\n\n if (!$allCells.length) return false;\n\n let currentIndex = $allCells.index($activeTd);\n\n if (currentIndex === -1) currentIndex = 0;\n\n switch (e.key) {\n case 'Home':\n case 'End': {\n const $rowCells = $activeTd.closest('tr').find('td').filter((_, td) => this.focusManager.isSelectableCell($(td)));\n const [$target] = e.key === 'Home' ? $rowCells : [...$rowCells].reverse();\n const newIndex = $allCells.index($target);\n\n if (newIndex >= 0) {\n this.focusManager.updateRovingTabindex($allCells, newIndex);\n $target?.focus();\n }\n\n return false;\n }\n\n case 'PageUp':\n case 'PageDown': {\n const currentDay = parseInt($activeTd.find('a').text());\n\n if (isNaN(currentDay)) return false;\n\n const sign = e.key === 'PageUp' ? -1 : +1;\n\n this.navigateByMonthCount(inputElement, sign * (e.shiftKey ? 12 : 1), currentDay);\n return false;\n }\n\n case 'ArrowLeft':\n case 'ArrowUp':\n case 'ArrowRight':\n case 'ArrowDown':\n this.handleArrowNavigation(e, $calendar, inputElement, $allCells, currentIndex);\n return false;\n }\n }\n\n /**\n * Sets up comprehensive keyboard navigation for the calendar\n * @param {jQuery} $calendar - The calendar jQuery element\n * @param {jQuery} $table - The table jQuery element\n * @param {HTMLElement} inputElement - The input element associated with the calendar\n */\n setupKeyboardNavigation($calendar, $table, inputElement) {\n $calendar.off('keydown.datepicker-navigation').off('keydown.focus-trap');\n\n $calendar.on('keydown.datepicker-navigation', (e) => {\n const $focused = $(document.activeElement);\n\n switch (e.key) {\n case 'Escape': {\n if ($focused.is('option')) {\n //time element option\n return true;\n }\n e.preventDefault();\n this.handleCancelButton();\n return false;\n }\n\n case 'Tab': {\n const $focusable = this.focusManager.getFocusableElements($calendar);\n\n if (!$focusable.length) return;\n\n const $target = e.shiftKey\n ? this.focusManager.resolveBackwardFocusTarget($calendar, $focused, $focusable.first(), $focusable.last())\n : this.focusManager.resolveForwardFocusTarget($calendar, $focused, $focusable.first(), $focusable.last());\n\n if (!$target) return;\n\n e.preventDefault();\n $target.focus();\n return false;\n }\n\n case 'Enter':\n case ' ': {\n if ($focused.is('select') || $focused.is('option')) {\n //time elements\n return true;\n }\n e.preventDefault();\n\n const isNavButton = $focused.hasClass('ui-datepicker-prev') || $focused.hasClass('ui-datepicker-next');\n\n if (isNavButton) {\n this.activateNavButton($focused, inputElement);\n return false;\n }\n\n if (!this.focusManager.isDateCell($focused) || $focused.hasClass('ui-datepicker-unselectable')) {\n return false;\n }\n\n if (e.key === 'Enter') {\n $focused.find('a').click();\n $.datepicker._hideDatepicker();\n requestAnimationFrame(() => this.focusAfterClose());\n } else {\n $table.find('td.ui-datepicker-current-day')\n .removeClass('ui-datepicker-current-day')\n .removeAttr('aria-selected');\n $focused.addClass('ui-datepicker-current-day').attr('aria-selected', 'true');\n }\n\n return false;\n }\n\n case 'Home':\n case 'End':\n case 'PageUp':\n case 'PageDown':\n case 'ArrowLeft':\n case 'ArrowUp':\n case 'ArrowRight':\n case 'ArrowDown':\n return this.handleGridNavigation(e, $calendar, inputElement);\n }\n });\n }\n }\n\n return KeyboardHandler;\n});\n\n","Amasty_DatePicker/js/accessibility/focus-manager.js":"/**\n * Focus Manager\n *\n * Manages focus behavior for the datepicker calendar\n */\ndefine([\n 'jquery',\n 'jquery/ui-modules/focusable',\n 'jquery/ui-modules/tabbable',\n], function ($) {\n 'use strict';\n\n /**\n * Focus Manager Class\n */\n class FocusManager {\n /**\n * Updates the roving tabindex for date navigation.\n * Tabindex is placed on <td> elements (not <a>) so screen readers\n * announce only the focused cell, not the entire dialog.\n * @param {jQuery} $allCells - Collection of all selectable <td> elements\n * @param {number} newIndex - Index of the element to receive tabindex=\"0\"\n */\n updateRovingTabindex($allCells, newIndex) {\n $allCells.attr('tabindex', '-1');\n\n if (newIndex >= 0 && newIndex < $allCells.length) {\n $allCells.eq(newIndex).attr('tabindex', '0');\n }\n }\n\n /**\n * Returns true when a <td> is selectable (not disabled and contains a date link)\n * @param {jQuery} $td\n * @returns {boolean}\n */\n isSelectableCell($td) {\n return !$td.hasClass('ui-datepicker-unselectable') && $td.find('a').length > 0;\n }\n\n /**\n * Returns all selectable date cells (<td>) in the calendar\n * @param {jQuery} $calendar\n * @returns {jQuery}\n */\n getSelectableCells($calendar) {\n return $calendar.find('td').filter((_, td) => this.isSelectableCell($(td)));\n }\n\n /**\n * Sets up focus handling for the calendar table\n * @param {jQuery} $table - The table jQuery element\n */\n removeTableFocus($table) {\n $table.removeAttr('tabindex').off('focus.table-focus');\n }\n\n /**\n * Returns focusable elements within the calendar (excluding decorative icons)\n * @param {jQuery} $calendar\n * @returns {jQuery}\n */\n getFocusableElements($calendar) {\n return $calendar\n .find(':tabbable');\n }\n\n /**\n * Returns true when the given element is a selectable date cell\n * @param {jQuery} $el\n * @returns {boolean}\n */\n isDateCell($el) {\n return $el.is('td') && $el.find('a').length > 0;\n }\n\n /**\n * Returns true when the given element is outside the calendar\n * @param {jQuery} $calendar\n * @param {jQuery} $el\n * @returns {boolean}\n */\n isOutsideCalendar($calendar, $el) {\n return !$.contains($calendar[0], $el[0]);\n }\n\n /**\n * Resolves the element that should receive focus on Shift+Tab traversal.\n * @param {jQuery} $calendar\n * @param {jQuery} $current - Currently focused element\n * @param {jQuery} $first - First focusable element\n * @param {jQuery} $last - Last focusable element\n * @returns {jQuery|null} Target element, or null when no redirect is needed\n */\n resolveBackwardFocusTarget($calendar, $current, $first, $last) {\n if (this.isOutsideCalendar($calendar, $current) || $current.is($first)) {\n return $last;\n }\n\n if (this.isDateCell($current)) {\n const $nextBtn = $calendar.find('.ui-datepicker-next');\n\n return $nextBtn.length ? $nextBtn : $first;\n }\n\n return null;\n }\n\n /**\n * Resolves the element that should receive focus on forward Tab traversal.\n * @param {jQuery} $calendar\n * @param {jQuery} $current - Currently focused element\n * @param {jQuery} $first - First focusable element\n * @param {jQuery} $last - Last focusable element\n * @returns {jQuery|null} Target element, or null when no redirect is needed\n */\n resolveForwardFocusTarget($calendar, $current, $first, $last) {\n if (this.isOutsideCalendar($calendar, $current) || $current.is($last)) {\n return $first;\n }\n\n if (this.isDateCell($current)) {\n const timePickerInput = $calendar.find('.ui-timepicker-select:visible');\n\n if (timePickerInput.length) {\n return timePickerInput.first();\n }\n\n const $cancelBtn = $calendar.find('.custom-datepicker-cancel');\n\n return $cancelBtn.length ? $cancelBtn : $last;\n }\n\n return null;\n }\n\n /**\n * Sets up a focus trap to keep keyboard focus within the calendar dialog\n * @param {jQuery} $calendar - The calendar jQuery element\n */\n setupFocusTrap($calendar) {\n $calendar.off('keydown.focus-trap').on('keydown.focus-trap', (e) => {\n if (e.key !== 'Tab') return;\n\n const $focusable = this.getFocusableElements($calendar);\n\n if ($focusable.length === 0) return;\n\n const $first = $focusable.first();\n const $last = $focusable.last();\n const $current = $(document.activeElement);\n\n const $target = e.shiftKey\n ? this.resolveBackwardFocusTarget($calendar, $current, $first, $last)\n : this.resolveForwardFocusTarget($calendar, $current, $first, $last);\n\n if (!$target) return;\n\n e.preventDefault();
2\n $target.focus();\n });\n }\n\n /**\n * Sets the initial focus to the appropriate date cell (<td>) when the calendar opens.\n * Focusing <td role=\"gridcell\"> instead of the inner <a> prevents screen readers\n * from reading the entire dialog content on open.\n * @param {jQuery} $calendar - The calendar jQuery element\n */\n setInitialFocus($calendar) {\n const [selectedCell] = $calendar.find('td.ui-datepicker-current-day');\n const [todayCell] = $calendar.find('td.ui-datepicker-today');\n const [firstCell] = this.getSelectableCells($calendar);\n const toFocus = selectedCell ?? todayCell ?? firstCell;\n\n toFocus && $(toFocus).attr('tabindex', '0').focus();\n }\n\n /**\n * Focuses on a specific day number in the calendar\n * @param {jQuery} $calendar - The calendar jQuery element\n * @param {number} targetDay - The day number to focus (1-31)\n */\n focusOnDay($calendar, targetDay) {\n const $selectableCells = this.getSelectableCells($calendar);\n\n if ($selectableCells.length === 0) return;\n\n const day = String(targetDay);\n const [matchedLink] = $selectableCells.find(`a:contains(${day})`).filter((_, a) => $(a).text().trim() === day);\n const $targetCell = matchedLink ? $(matchedLink).closest('td') : $selectableCells.last();\n const newIndex = $selectableCells.index($targetCell);\n\n if (newIndex >= 0) {\n this.updateRovingTabindex($selectableCells, newIndex);\n $targetCell.focus();\n }\n }\n }\n\n return FocusManager;\n});\n\n","Magento_GroupedProduct/js/product-ids-resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'Magento_Catalog/js/product/view/product-ids',\n 'Magento_Catalog/js/product/view/product-info'\n], function ($, productIds, productInfo) {\n 'use strict';\n\n /**\n * Returns id's of products in form.\n *\n * @param {Object} config\n * @param {HTMLElement} element\n * @return {Array}\n */\n return function (config, element) {\n $(element).find('div[data-product-id]').each(function () {\n productIds.push($(this).data('productId').toString());\n productInfo.push(\n {\n 'id': $(this).data('productId').toString()\n }\n );\n });\n\n return productIds();\n };\n});\n","Magento_GroupedProduct/js/grouped-product.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'underscore',\n 'jquery-ui-modules/widget',\n 'jquery/jquery.parsequery'\n], function ($) {\n 'use strict';\n\n $.widget('mage.groupedProduct', {\n options: {\n qtySelector: 'input.qty',\n qtyNameSelector: 'super_group'\n },\n\n /**\n * Creates widget\n * @private\n */\n _create: function () {\n // Override defaults with URL query parameters and/or inputs values\n this._overrideDefaults();\n },\n\n /**\n * Override default options values settings with either URL query parameters or\n * initialized inputs values.\n * @private\n */\n _overrideDefaults: function () {\n var hashIndex = window.location.href.indexOf('#');\n\n if (hashIndex !== -1) {\n this._parseQueryParams(window.location.href.substr(hashIndex + 1));\n }\n },\n\n /**\n * Parse query parameters from a query string and set options values based on the\n * key value pairs of the parameters.\n * @param {*} queryString - URL query string containing query parameters.\n * @private\n */\n _parseQueryParams: function (queryString) {\n var queryParams = $.parseQuery({\n query: queryString\n }),\n form = this.element,\n qtyNameSelector = this.options.qtyNameSelector,\n qtys = $(this.options.qtySelector, form);\n\n $.each(queryParams, $.proxy(function (key, value) {\n qtys.each(function (index, qty) {\n var nameSelector = qtyNameSelector.concat('[', key, ']');\n\n if (qty.name === nameSelector) {\n $(qty).val(value);\n }\n });\n }, this));\n }\n });\n\n return $.mage.groupedProduct;\n});\n","Goyard_Adyen/js/model/adyen-wallet-registry.js":"/**\n * @copyright Copyright (c) 2026 Goyard\n * @author Orkester https://orkester.fr/\n *\n * Shared registry holding Adyen wallet component instances (Google Pay, Apple Pay).\n * Allows payment.js to call submit() on the component without a direct dependency.\n */\ndefine([], function () {\n 'use strict';\n\n var components = {};\n\n return {\n set: function (methodCode, component) {\n components[methodCode] = component;\n },\n get: function (methodCode) {\n return components[methodCode] || null;\n }\n };\n});\n","Goyard_Adyen/js/model/adyen-checkout-mixin.js":"/**\n * @copyright Copyright (c) 2026 Goyard\n * @author Orkester https://orkester.fr/\n *\n * Mixin to override Adyen Web Components translations with Magento i18n\n */\n\ndefine([\n\t'jquery',\n\t'Adyen_Payment/js/model/adyen-configuration'\n], function ($, adyenConfiguration) {\n\t'use strict';\n\n\treturn function (originalAdyenCheckout) {\n\t\t// Build checkout with custom translations for validation messages\n\t\toriginalAdyenCheckout.buildCheckoutComponent = function (\n\t\t\tpaymentMethodsResponse,\n\t\t\tcountryCode,\n\t\t\thandleOnAdditionalDetails,\
2n\t\t\thandleOnSubmit,\n\t\t\thandleOnError\n\t\t) {\n\t\t\tif (!paymentMethodsResponse.paymentMethodsResponse) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar locale = adyenConfiguration.getLocale().replace('_', '-');\n\t\t\tvar translations = {};\n\t\t\t// Goyard custom translations\n\t\t\ttranslations[locale] = {\n\t\t\t\t'creditCard.cardNumber.label': $.mage.__('Card number'),\n\t\t\t\t'creditCard.expiryDate.label': $.mage.__('Expiration'),\n\t\t\t\t'creditCard.securityCode.label': $.mage.__('Security code'),\n\t\t\t\t'creditCard.securityCode.contextualText.3digits': $.mage.__('CVC'),\n\t\t\t\t'creditCard.holderName': $.mage.__('Name on the card'),\n\t\t\t\t'cc.num.900': $.mage.__('Enter a valid card number'),\n\t\t\t\t'cc.num.901': $.mage.__('Enter a valid card number'),\n\t\t\t\t'cc.num.902': $.mage.__('Enter a valid card number'),\n\t\t\t\t'cc.dat.910': $.mage.__('Enter a valid expiry date'),\n\t\t\t\t'cc.dat.911': $.mage.__('Enter a valid expiry date'),\n\t\t\t\t'cc.dat.912': $.mage.__('Enter a valid expiry date'),\n\t\t\t\t'cc.dat.913': $.mage.__('Enter a valid expiry date'),\n\t\t\t\t'cc.cvc.920': $.mage.__('Enter the security code'),\n\t\t\t\t'cc.cvc.921': $.mage.__('Enter the security code'),\n\t\t\t};\n\n\t\t\treturn window.AdyenWeb.AdyenCheckout({\n\t\t\t\tlocale: locale,\n\t\t\t\tcountryCode: countryCode,\n\t\t\t\tclientKey: adyenConfiguration.getClientKey(),\n\t\t\t\tenvironment: adyenConfiguration.getCheckoutEnvironment(),\n\t\t\t\tpaymentMethodsResponse: paymentMethodsResponse.paymentMethodsResponse,\n\t\t\t\ttranslations: translations,\n\t\t\t\tonAdditionalDetails: handleOnAdditionalDetails,\n\t\t\t\tonSubmit: handleOnSubmit,\n\t\t\t\tonError: handleOnError\n\t\t\t});\n\t\t};\n\n\t\tvar originalMount = originalAdyenCheckout.mountPaymentMethodComponent;\n\t\toriginalAdyenCheckout.mountPaymentMethodComponent = function (checkoutComponent, paymentMethodType, configuration, elementLabel, result) {\n\t\t\tif (paymentMethodType === 'card' && configuration) {\n\t\t\t\tconfiguration.placeholders = {\n\t\t\t\t\tcardNumber: $.mage.__('0000 0000 0000 0000'),\n\t\t\t\t\texpiryDate: $.mage.__('MM/YY'),\n\t\t\t\t\tsecurityCodeThreeDigits: $.mage.__('CVC'),\n\t\t\t\t\tholderName: $.mage.__('Mr. John Smith'),\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Call parent with new configuration\n\t\t\treturn originalMount.call(this, checkoutComponent, paymentMethodType, configuration, elementLabel, result);\n\t\t};\n\n\t\treturn originalAdyenCheckout;\n\t};\n});\n","Goyard_Adyen/js/view/payment/method-renderer/adyen-cc-method-mixin.js":"/**\n * @copyright Copyright (c) 2026 Goyard\n * @author Orkester https://orkester.fr/\n */\n\ndefine([\n\t'jquery',\n\t'mage/url',\n\t'Adyen_Payment/js/model/adyen-payment-modal',\n\t'Magento_Checkout/js/model/full-screen-loader',\n\t'Adyen_Payment/js/model/adyen-payment-service',\n], function (\n\t$,\n\turl,\n\tAdyenPaymentModal,\n\tfullScreenLoader,\n\tadyenPaymentService,\n) {\n\t'use strict';\n\n\t/**\n\t * Maps an XHR error response to the appropriate user-facing message.\n\t * 5xx (technical/server errors) \u2192 ER001, all others \u2192 CCAM9.\n\t * NOTE: We do NOT use parsed.message for non-5xx because AfterPaymentsDetailsPlugin\n\t * only intercepts /paymentsDetails (3DS flow). Direct refusals go through\n\t * savePaymentInformationAndPlaceOrder and return the raw Adyen message\n\t * (e.g. \"The payment is REFUSED.\") which must not be shown to the user.\n\t */\n\tfunction resolveAdyenErrorMessage(response) {\n\t\tif (response.status >= 500) {\n\t\t\treturn $.mage.__('[ER001] An error occured while placing order.');\n\t\t}\n\n\t\treturn $.mage.__('Unfortunately the order could not be processed. Please contact us or try again later.');\n\t}\n\n\treturn function (Component) {\n\t\treturn Component.extend({\n\n\t\t\tdefaults: {\n\t\t\t\ttemplate: 'Goyard_Adyen/payment/cc-form',\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the title for the component.\n\t\t\t * @returns {String} The title of the component.\n\t\t\t */\n\t\t\tgetTitle: function () {\n\t\t\t\treturn $.mage.__('Credit Cards');\n\t\t\t},\n\n\t\t\t// Removed in Adyen v10 but needed by Signifyd\n\t\t\tgetAllInstallments: function () {\n\t\t\t\treturn window.checkoutConfig.payment.adyenCc.installments;\n\t\t\t},\n\n\t\t\t// Removed in Adyen v10 but needed by Signifyd\n\t\t\tgetCcCodeByAltCode: function (altCode) {\n\t\t\t\tvar adyenCcTypes = window.checkoutConfig.payment.adyenCc.adyenCcTypes;\n\t\t\t\tif (adyenCcTypes && adyenCcTypes[altCode]) {\n\t\t\t\t\treturn adyenCcTypes[altCode].code;\n\t\t\t\t}\n\t\t\t\treturn '';\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Intercepts place-order failures (direct card refusal, no 3DS).\
2n\t\t\t * The parent sends the AJAX and rejects the deferred on failure.\n\t\t\t * We read the mapped PHP message from responseText and store it in\n\t\t\t * sessionStorage before redirecting \u2014 sessionStorage survives the navigation\n\t\t\t * and is immune to Magento's section reload (which would overwrite customerData).\n\t\t\t * filter-cart-messages.js reads the value on cart page load and injects it.\n\t\t\t */\n\t\t\tgetPlaceOrderDeferredObject: function () {\n\t\t\t\tvar deferred = $.Deferred();\n\n\t\t\t\tthis._super()\n\t\t\t\t\t.done(function () {\n\t\t\t\t\t\tdeferred.resolve.apply(deferred, arguments);\n\t\t\t\t\t})\n\t\t\t\t\t.fail(function (response) {\n\t\t\t\t\t\tvar msg = resolveAdyenErrorMessage(response);\n\t\t\t\t\t\twindow.sessionStorage.setItem('adyen_payment_error', msg);\n\t\t\t\t\t\twindow.location.replace(url.build('checkout/cart'));\n\t\t\t\t\t\tdeferred.reject.apply(deferred, arguments);\n\t\t\t\t\t});\n\n\t\t\t\treturn deferred.promise();\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * On payment error, AfterPaymentsDetailsPlugin maps the Adyen exception to\n\t\t\t * CCAM9 (\"Unfortunately the order could not be processed...\") and re-throws it.\n\t\t\t * The HTTP error response contains that message in responseText.message \u2014\n\t\t\t * we store it in sessionStorage (survives navigation) and redirect to the cart page.\n\t\t\t * filter-cart-messages.js reads the value on cart load and injects it via customerData.\n\t\t\t */\n\t\t\thandleOnAdditionalDetails: function (result) {\n\t\t\t\tvar self = this;\n\t\t\t\tvar request = result.data;\n\n\t\t\t\tAdyenPaymentModal.hideModalLabel(this.modalLabel);\n\t\t\t\tfullScreenLoader.startLoader();\n\t\t\t\tvar popupModal = self.showModal();\n\n\t\t\t\tadyenPaymentService.paymentDetails(request, self.orderId)\n\t\t\t\t\t.done(function (responseJSON) {\n\t\t\t\t\t\tself.handleAdyenResult(responseJSON, self.orderId);\n\t\t\t\t\t})\n\t\t\t\t\t.fail(function (response) {\n\t\t\t\t\t\tself.closeModal(popupModal);\n\t\t\t\t\t\tfullScreenLoader.stopLoader();\n\t\t\t\t\t\tself.isPlaceOrderActionAllowed(true);\n\n\t\t\t\t\t\twindow.sessionStorage.setItem('adyen_payment_error', resolveAdyenErrorMessage(response));\n\t\t\t\t\t\twindow.location.replace(url.build('checkout/cart'));\n\t\t\t\t\t});\n\t\t\t},\n\t\t});\n\t};\n});\n","Goyard_Adyen/js/view/payment/method-renderer/adyen-googlepay-method-mixin.js":"/**\n * @copyright Copyright (c) 2026 Goyard\n * @author Orkester https://orkester.fr/\n *\n * Hides the native Google Pay button so the generic \"Valider et Payer\" CTA\n * can be used instead. The component instance is stored in adyen-wallet-registry\n * so payment.js can call submit() on it programmatically.\n * On payment failure (refusal or 3DS error), stores the error in sessionStorage\n * and redirects to cart \u2014 matching the CC payment error behaviour.\n */\ndefine([\n 'jquery',\n 'mage/url',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Adyen_Payment/js/model/adyen-payment-service',\n 'Adyen_Payment/js/model/adyen-payment-modal',\n 'Goyard_Adyen/js/model/adyen-wallet-registry'\n], function (\n $,\n url,\n fullScreenLoader,\n adyenPaymentService,\n adyenPaymentModal,\n walletRegistry\n) {\n 'use strict';\n\n function resolveAdyenErrorMessage(response) {\n if (response && response.status >= 500) {\n return $.mage.__('[ER001] An error occured while placing order.');\n }\n return $.mage.__('Unfortunately the order could not be processed. Please contact us or try again later.');\n }\n\n /**\n * Result codes meaning the payment went through, as classified by\n * Adyen\\Payment\\Helper\\PaymentResponseHandler::formatPaymentResponse(). Refused and Error\n * are flagged isFinal there too, so isFinal alone cannot stand for \"paid\".\n */\n var SUCCESSFUL_RESULT_CODES = ['Authorised', 'Received', 'PresentToShopper'];\n\n return function (TargetComponent) {\n return TargetComponent.extend({\n defaults: {\n template: 'Goyard_Adyen/payment/googlepay-form',\n logoUrl: require.toUrl('images/payment_method/googlepay.svg'),\n paymentAuthorised: fal
2se\n },\n\n buildComponentConfiguration: function (paymentMethod, paymentMethodsExtraInfo) {\n var config = this._super(paymentMethod, paymentMethodsExtraInfo);\n config.showPayButton = false;\n return config;\n },\n\n selectPaymentMethod: function () {\n var result = this._super();\n this._markAsWallet();\n return result;\n },\n\n mountPaymentMethodComponent: function (paymentMethod, configuration, methodCode) {\n this._super(paymentMethod, configuration, methodCode);\n if (this.paymentComponent) {\n walletRegistry.set(this.getCode(), this.paymentComponent);\n }\n this._markAsWallet();\n },\n\n _markAsWallet: function () {\n var radioEl = document.getElementById(this.getCode());\n if (radioEl) {\n var wrapper = radioEl.closest('.payment-method');\n if (wrapper) {\n wrapper.classList.add('adyen-wallet-method');\n }\n }\n },\n\n /**\n * Latch the payment as paid, which handleOnFailure() needs to spot late failures.\n * The parent only tracks orderId on its non-final branch.\n */\n validateActionOrPlaceOrder: function (responseJSON, orderId, component) {\n var response = JSON.parse(responseJSON);\n\n if (response.isFinal && SUCCESSFUL_RESULT_CODES.indexOf(response.resultCode) !== -1) {\n this.paymentAuthorised = true;\n this.orderId = orderId;\n }\n\n return this._super(responseJSON, orderId, component);\n },\n\n /**\n * Called when placeRedirectOrder fails (payment refused, network error, etc.).\n * Also called via handleOnError for Adyen component-level errors.\n * Redirects to cart with a sanitised message instead of showing it inline\n * in the checkout \u2014 matches the behaviour of the CC mixin.\n *\n * Failures reported after the payment was authorised are ignored: the Google Pay\n * sheet is still open when the parent starts navigating to the success page, and its\n * teardown makes the Google Pay SDK reject with statusCode CANCELED. Redirecting on\n * that would replace the in-flight success navigation with the cart, dropping the\n * shopper on an empty cart with a paid order.\n */\n handleOnFailure: function (error, component) {\n if (this.paymentAuthorised) {\n // Keep the loader up: the browser is on its way to the success page.\n return;\n }\n\n fullScreenLoader.stopLoader();\n window.sessionStorage.setItem('adyen_payment_error', resolveAdyenErrorMessage(error));\n window.location.replace(url.build('checkout/cart'));\n },\n\n /**\n * Called after a 3DS challenge (edge case for wallet payments).\n * On success, redirects to the Adyen success page.\n * On failure, redirects to cart with a sanitised error message.\n */\n handleOnAdditionalDetails: function (state, component) {\n var self = this;\n adyenPaymentModal.hideModalLabel(this.modalLabel);\n fullScreenLoader.startLoader();\n\n var request = (state && state.data) ? state.data : {};\n\n adyenPaymentService.paymentDetails(request, self.orderId)\n .done(function () {\n $.mage.redirect(window.checkoutConfig.payment.adyen.successPage);\n })\n .fail(function (response) {\n if (self.popupModal) {\n self.closeModal(self.popupModal);\n }\n window.sessionStorage.setItem('adyen_payment_error', resolveAdyenErrorMessage(response));\n window.location.replace(url.build('checkout/cart'));\n });\n }\n });\n };\n});\n","Goyard_Adyen/js/view/payment/method-renderer/adyen-applepay-method-mixin.js":"/**\n * @copyright Copyright (c) 2026 Goyard\n * @author Orkester https://orkester.fr/\n *\n * Hides the native Apple Pay button so the generic \"Valider et Payer\" CTA\n * can be used instead. The component instance is stored in adyen-wallet-registry\n * so payment.js can call submit() on it programmatically.\n * On payment failure (refusal or 3DS error), stores the error in sessionStorage\n * and redirects to cart \u2014 matching the CC payment error behaviour.\n */\ndefine([\n 'jquery',\n 'mage/url',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Adyen_Payment/js/model/adyen-payment-service',\n 'Adyen_Payment/js/model/adyen-payment-modal',\n 'Goyard_Adyen/js/model/adyen-wallet-registry'\n], function (\n $,\n url,\n fullScreenLoader,\n adyenPaymentService,\n adyenPaymentModal,\n walletRegistry\n) {\n 'use strict';\n\n function resolveAdyenErrorMessage(response) {\n if (response && response.status >= 500) {\n return $.mage.__('[ER001] An error occured while placing order.');\n }
2\n return $.mage.__('Unfortunately the order could not be processed. Please contact us or try again later.');\n }\n\n return function (TargetComponent) {\n return TargetComponent.extend({\n defaults: {\n template: 'Goyard_Adyen/payment/applepay-form',\n logoUrl: require.toUrl('images/payment_method/applepay.svg')\n },\n\n buildComponentConfiguration: function (paymentMethod, paymentMethodsExtraInfo) {\n var config = this._super(paymentMethod, paymentMethodsExtraInfo);\n config.showPayButton = false;\n return config;\n },\n\n selectPaymentMethod: function () {\n var result = this._super();\n this._markAsWallet();\n return result;\n },\n\n mountPaymentMethodComponent: function (paymentMethod, configuration, methodCode) {\n this._super(paymentMethod, configuration, methodCode);\n if (this.paymentComponent) {\n walletRegistry.set(this.getCode(), this.paymentComponent);\n }\n this._markAsWallet();\n },\n\n _markAsWallet: function () {\n var radioEl = document.getElementById(this.getCode());\n if (radioEl) {\n var wrapper = radioEl.closest('.payment-method');\n if (wrapper) {\n wrapper.classList.add('adyen-wallet-method');\n }\n }\n },\n\n /**\n * Called when placeRedirectOrder fails (payment refused, network error, etc.).\n * Also called via handleOnError for Adyen component-level errors.\n * Redirects to cart with a sanitised message instead of showing it inline\n * in the checkout \u2014 matches the behaviour of the CC mixin.\n */\n handleOnFailure: function (error, component) {\n fullScreenLoader.stopLoader();\n window.sessionStorage.setItem('adyen_payment_error', resolveAdyenErrorMessage(error));\n window.location.replace(url.build('checkout/cart'));\n },\n\n /**\n * Called after a 3DS challenge (edge case for wallet payments).\n * On success, redirects to the Adyen success page.\n * On failure, redirects to cart with a sanitised error message.\n */\n handleOnAdditionalDetails: function (state, component) {\n var self = this;\n adyenPaymentModal.hideModalLabel(this.modalLabel);\n fullScreenLoader.startLoader();\n\n var request = (state && state.data) ? state.data : {};\n\n adyenPaymentService.paymentDetails(request, self.orderId)\n .done(function () {\n $.mage.redirect(window.checkoutConfig.payment.adyen.successPage);\n })\n .fail(function (response) {\n if (self.popupModal) {\n self.closeModal(self.popupModal);\n }\n window.sessionStorage.setItem('adyen_payment_error', resolveAdyenErrorMessage(response));\n window.location.replace(url.build('checkout/cart'));\n });\n }\n });\n };\n});\n","Magento_Tax/js/price/adjustment.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Ui/js/grid/columns/column',\n 'mage/translate'\n], function (Element, $t) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n bodyTmpl: 'Magento_Tax/price/adjustment',\n taxPriceType: 'final_price',\n taxPriceCssClass: 'price-including-tax',\n bothPrices: 3,\n inclTax: 2,\n exclTax: 1,\n modules: {\n price: '${ $.parentName }'\n },\n listens: {\n price: 'initializePriceAttributes'\n }\n },\n\n /**\n * {@inheritdoc}\n */\n initialize: function () {\n this._super()\n .initializePriceAttributes();\n\n return this;\n },\n\n /**\n * Update parent price.\n *\n * @returns {Object} Chainable.\n */\n initializePriceAttributes: function () {\n if (this.displayBothPrices && this.price()
2) {\n this.price().priceWrapperCssClasses = this.taxPriceCssClass;\n this.price().priceWrapperAttr = {\n 'data-label': $t('Incl. Tax')\n };\n }\n\n return this;\n },\n\n /**\n * Get price tax adjustment.\n *\n * @param {Object} row\n * @return {HTMLElement} tax html\n */\n getTax: function (row) {\n return row['price_info']['extension_attributes']['tax_adjustments']['formatted_prices'][this.taxPriceType];\n },\n\n /**\n * UnsanitizedHtml version of getTax.\n *\n * @param {Object} row\n * @return {HTMLElement} tax html\n */\n getTaxUnsanitizedHtml: function (row) {\n return this.getTax(row);\n },\n\n /**\n * Set price tax type.\n *\n * @param {String} priceType\n * @return {Object}\n */\n setPriceType: function (priceType) {\n this.taxPriceType = priceType;\n\n return this;\n },\n\n /**\n * Return whether display setting is to display\n * both price including tax and price excluding tax.\n *\n * @return {Boolean}\n */\n displayBothPrices: function () {\n return +this.source.data.displayTaxes === this.bothPrices;\n },\n\n /**\n * Return whether display setting is to display price including tax.\n *\n * @return {Boolean}\n */\n displayPriceIncludeTax: function () {\n return +this.source.data.displayTaxes === this.inclTax;\n },\n\n /**\n * Return whether display setting is to display price excluding tax.\n *\n * @return {Boolean}\n */\n displayPriceExclTax: function () {\n return +this.source.data.displayTaxes === this.exclTax;\n }\n });\n});\n","Magento_Tax/js/view/checkout/shipping_method/price.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'uiComponent',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Catalog/js/price-utils'\n], function (Component, quote, priceUtils) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Tax/checkout/shipping_method/price'\n },\n isDisplayShippingPriceExclTax: window.checkoutConfig.isDisplayShippingPriceExclTax,\n isDisplayShippingBothPrices: window.checkoutConfig.isDisplayShippingBothPrices,\n\n /**\n * @param {Object} item\n * @return {Boolean}\n */\n isPriceEqual: function (item) {\n return item['price_excl_tax'] != item['price_incl_tax']; //eslint-disable-line eqeqeq\n },\n\n /**\n * @param {*} price\n * @return {*|String}\n */\n getFormattedPrice: function (price) {\n //todo add format data\n return priceUtils.formatPriceLocale(price, quote.getPriceFormat());\n }\n });\n});\n","Magento_Tax/js/view/checkout/minicart/subtotal/totals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'ko',\n 'uiComponent',\n 'Magento_Customer/js/customer-data'\n], function (ko, Component, customerData) {\n 'use strict';\n\n return Component.extend({\n displaySubtotal: ko.observable(true),\n\n /**\n * @override\n */\n initialize: function () {\n this._super();\n this.cart = customerData.get('cart');\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/subtotal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Checkout/js/view/summary/abstract-total',\n 'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n 'use strict';\n\n var displaySubtotalMode = window.checkoutConfig.reviewTotalsDisplayMode;\n\n return Component.extend({\n defaults: {\n displaySubtotalMode: displaySubtotalMode,\n template: 'Magento_Tax/checkout/summary/subtotal'\n },\n totals: quote.getTotals(),\n\n /**\n * @return {*|String}\n */\n getValue: function () {\n var price = 0;\n\n if (this.totals()) {\n price = this.totals().subtotal;\n }\n\n return this.getFormattedPrice(price);\n },\n\n /**\n * @return {Boolean}\n */\n isBothPricesDisplayed: function () {\n return this.displaySubtotalMode == 'both'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {Boolean}\n */\n isIncludingTaxDisplayed: function () {\n return this.displaySubtotalMode == 'including'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {*|String}\n */\n getValueInclTax: function () {\n var price = 0;\n\n if (this.totals()) {\n price = this.totals()['subtotal_incl_tax'];\n }\n\n return this.getFormattedPrice(price);\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/grand-total.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Checkout/js/view/summary/abstract-total',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Catalog/js/price-utils',\n 'Magento_Checkout/js/model/totals'\n], function (Component, quote, priceUtils, totals) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n isFullTaxSummaryDisplayed: window.checkoutConfig.isFullTaxSummaryDisplayed || false,\n template: 'Magento_Tax/checkout/summary/grand-total'\n },\n totals: quote.getTotals(),\n isTaxDisplayedInGrandTotal: window.checkoutConfig.includeTaxInGrandTotal || false,\n\n /**\n * @return {*}\n */\n isDisplayed: function () {\n return this.isFullMode();\n },\n\n /**\n * @return {*|String}\n */\n getValue: function () {\n var price = 0;\n\n if (this.totals()) {\n price = totals.getSegment('grand_total').value;\n }\n\n return this.getFormattedPrice(price);\n },\n\n /**\n * @return {*|String}\n */\n getBaseValue: function () {\n var price = 0;\n\n if (this.totals()) {\n price = this.totals()['base_grand_total'];\n }
2\n\n return priceUtils.formatPriceLocale(price, quote.getBasePriceFormat());\n },\n\n /**\n * @return {*}\n */\n getGrandTotalExclTax: function () {\n var total = this.totals(),\n amount;\n\n if (!total) {\n return 0;\n }\n\n amount = total['grand_total'] - total['tax_amount'];\n\n if (amount < 0) {\n amount = 0;\n }\n\n return this.getFormattedPrice(amount);\n },\n\n /**\n * @return {Boolean}\n */\n isBaseGrandTotalDisplayNeeded: function () {\n var total = this.totals();\n\n if (!total) {\n return false;\n }\n\n return total['base_currency_code'] != total['quote_currency_code']; //eslint-disable-line eqeqeq\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/tax.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'ko',\n 'Magento_Checkout/js/view/summary/abstract-total',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/totals',\n 'mage/translate',\n 'underscore'\n], function (ko, Component, quote, totals, $t, _) {\n 'use strict';\n\n var isTaxDisplayedInGrandTotal = window.checkoutConfig.includeTaxInGrandTotal,\n isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed,\n isZeroTaxDisplayed = window.checkoutConfig.isZeroTaxDisplayed,\n taxAmount = 0,\n rates = 0;\n\n return Component.extend({\n defaults: {\n isTaxDisplayedInGrandTotal: isTaxDisplayedInGrandTotal,\n notCalculatedMessage: $t('Not yet calculated'),\n template: 'Magento_Tax/checkout/summary/tax'\n },\n totals: quote.getTotals(),\n isFullTaxSummaryDisplayed: isFullTaxSummaryDisplayed,\n\n /**\n * @return {Boolean}\n */\n ifShowValue: function () {\n if (this.isFullMode() && this.getPureValue() == 0) { //eslint-disable-line eqeqeq\n return isZeroTaxDisplayed;\n }\n\n return true;\n },\n\n /**\n * @return {Boolean}\n */\n ifShowDetails: function () {\n if (!this.isFullMode()) {\n return false;\n }\n\n return this.getPureValue() > 0 && isFullTaxSummaryDisplayed;\n },\n\n /**\n * @return {Number}\n */\n getPureValue: function () {\n var amount = 0,\n taxTotal;\n\n if (this.totals()) {\n taxTotal = totals.getSegment('tax');\n\n if (taxTotal) {\n amount = taxTotal.value;\n }\n }\n\n return amount;\n },\n\n /**\n * @return {*|Boolean}\n */\n isCalculated: function () {\n return this.totals() && this.isFullMode() && totals.getSegment('tax') != null;\n },\n\n /**\n * @return {*}\n */\n getValue: function () {\n var amount;\n\n if (!this.isCalculated()) {\n return this.notCalculatedMessage;\n }\n amount = totals.getSegment('tax').value;\n\n return this.getFormattedPrice(amount);\n },\n\n /**\n * @param {*} amount\n * @return {*|String}\n */\n formatPrice: function (amount) {\n return this.getFormattedPrice(amount);\n },\n\n /**\n * @param {*} parent\n * @param {*} percentage\n * @return {*|String}\n */\n getTaxAmount: function (parent, percentage) {\n var totalPercentage = 0;\n\n taxAmount = parent.amount;\n rates = parent.rates;\n _.each(rates, function (rate) {\n totalPercentage += parseFloat(rate.percent);\n });\n\n return this.getFormattedPrice(this.getPercentAmount(taxAmount, totalPercentage, percentage));\n },\n\n /**\n * @param {*} amount\n * @param {*} totalPercentage\n * @param {*} percentage\n * @return {*|String}\n */\n getPercentAmount: function (amount, totalPercentage, percentage) {\n return parseFloat(amount * percentage / totalPercentage);\n },\n\n /**\n * @return {Array}\n */\n getDetails: function () {\n var taxSegment = totals.getSegment('tax');\n\n if (taxSegment && taxSegment['extension_attributes']) {\n return taxSegment['extension_attributes']['tax_grandtotal_details'];\n }\n\n return [];\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/shipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'jquery',\n 'Magento_Checkout/js/view/summary/shipping',\n 'Magento_Checkout/js/model/quote'\n], function ($, Component, quote) {\n 'use strict';\n\n var displayMode = window.checkoutConfig.reviewShippingDisplayMode;\n\n return Component.extend({\n defaults: {\n displayMode: displayMode,\n template: 'Magento_Tax/checkout/summary/shipping'\n },\n\n /**\n * @return {Boolean}\n */\n isBothPricesDisplayed: function () {\n return this.displayMode == 'both'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {Boolean}\n */\n isIncludingDisplayed: function () {\n return this.displayMode == 'including'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {Boolean}\n */\n isExcludingDisplayed: function () {\n return this.displayMode == 'excluding'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {*|Boolean}\n */\n isCalculated: function () {\n return this.totals() && this.isFullMode() && quote.shippingMethod() != null;\n },\n\n /**\n * @return {*}\n */\n getIncludingValue: function () {\n var price;\n\n if (!this.isCalculated()) {\n return this.notCalculatedMessage;\n }\n price = this.totals()['shipping_incl_tax'];\n\n return this.getFormattedPrice(price);\n },\n\n /**\n * @return {*}\n */\n getExcludingValue: function () {\n var price;\n\n if (!this.isCalculated()) {\n return this.notCalculatedMessage;\n }\n price = this.totals()['shipping_amount'];\n\n return this.getFormattedPrice(price);\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/item/details/subtotal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Checkout/js/view/summary/item/details/subtotal'\n], function (subtotal) {\n 'use strict';\n\n var displayPriceMode = window.checkoutConfig.reviewItemPriceDisplayMode || 'including';\n\n return subtotal.extend({\n defaults: {\n displayPriceMode: displayPriceMode,\n template: 'Magento_Tax/checkout/summary/item/details/subtotal'\n },\n\n /**\n * @return {Boolean}\n */\n isPriceInclTaxDisplayed: function () {\n return dis
2playPriceMode == 'both' || displayPriceMode == 'including'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {Boolean}\n */\n isPriceExclTaxDisplayed: function () {\n return displayPriceMode == 'both' || displayPriceMode == 'excluding'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @param {Object} quoteItem\n * @return {*|String}\n */\n getValueInclTax: function (quoteItem) {\n return this.getFormattedPrice(quoteItem['row_total_incl_tax']);\n },\n\n /**\n * @param {Object} quoteItem\n * @return {*|String}\n */\n getValueExclTax: function (quoteItem) {\n return this.getFormattedPrice(quoteItem['row_total']);\n }\n\n });\n});\n","Magento_Tax/js/view/checkout/cart/totals/grand-total.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Tax/js/view/checkout/summary/grand-total'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n /**\n * @override\n */\n isDisplayed: function () {\n return true;\n }\n });\n});\n","Magento_Tax/js/view/checkout/cart/totals/tax.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Tax/js/view/checkout/summary/tax',\n 'Magento_Checkout/js/model/totals'\n], function (Component, totals) {\n 'use strict';\n\n var isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed,\n isZeroTaxDisplayed = window.checkoutConfig.isZeroTaxDisplayed;\n\n return Component.extend({\n /**\n * @override\n */\n ifShowValue: function () {\n if (this.isFullMode() && this.getPureValue() == 0) { //eslint-disable-line eqeqeq\n return isZeroTaxDisplayed;\n }\n\n return true;\n },\n\n /**\n * @override\n */\n ifShowDetails: function () {\n return this.getPureValue() > 0 && isFullTaxSummaryDisplayed;\n },\n\n /**\n * @override\n */\n isCalculated: function () {\n return this.totals() && totals.getSegment('tax') !== null;\n }\n });\n});\n","Magento_Tax/js/view/checkout/cart/totals/shipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Tax/js/view/checkout/summary/shipping',\n 'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n 'use strict';\n\n return Component.extend({\n /**\n * @override\n */\n isCalculated: function () {\n return !!quote.shippingMethod();\n },\n\n /**\n * @override\n */\n getShippingMethodTitle: function () {\n return '(' + this._super() + ')';\n }\n });\n});\n","js/address-popup.js":"/**\n * Copyright Goyard\n * Customer Addresses Page\n * Front Js to Open and Close Popup when user click on Delete\n */\n\nrequire([\n 'jquery',\n], function($) {\n $(document).ready(function() {\n\n //open popup with button \"delete\"\n $('.address-delete').off('click').on('click', function() {\n let addressBlock = $(this).closest('.block-content').find('.block-address');\n let popUp = $(this).closest('.block-content').find('.block-address-popup');\n\n popUp.show();\n\n if(addressBlock.hasClass('blur0')){\n addressBlock.removeClass('blur0').addClass('blur4');\n } else {\n addressBlock.addClass('blur4');\n }\n });\n\n\n //Close popup with Cross \"X\" or Button \"No\"\n $('.address-popup-close').off('click').on('click', function() {\n let addressBlock = $(this).closest('.block-content').find('.block-address');\n let popUp = $(this).closest('.block-content').find('.block-address-popup');\n\n popUp.hide();\n\n if(addressBlock.hasClass('blur4')){\n addressBlock.removeClass('blur4').addClass('blur0');\n } else {\n addressBlock.addClass('blur0');\n }\n });\n\n //Close popup when click outside popup\n $(document).on('click', function(event) { \n if (!$(event.target).closest('.block-address-popup').length && (!$(event.target).closest('.address-delete').length) ) {\n $('.block-address.blur4').parent().find('.block-address-popup').hide();\n $('.block-address.blur4').removeClass('blur4').addClass('blur0');\n };\n });
2\n\n //Construct URL to redirect on /customer/address/delete/id/ when user click on 'Yes'\n $('.action.delete').on('click', function(){\n window.location = $(this).data('address').toString() + '/form_key/' + $.mage.cookies.get('form_key')\n });\n });\n});","js/plp-focus-scroll.js":"/**\n * @copyright Copyright (c) 2026 Goyard\n * @author Orkester https://orkester.fr/\n *\n * GOYARDCOM-3875 - On the PLP, a tile focused via keyboard (Shift+Tab) can stay\n * hidden under the fixed header stack (page header, nav, category title, filters\n * bar) because Firefox does not scroll focused elements out from under fixed\n * overlays. Scroll the page so the whole tile is visible below the stack.\n */\ndefine([\n \"jquery\",\n \"access_key\"\n], function ($) {\n \"use strict\";\n\n var overlaySelectors = \".page-header, .sections.nav-sections, .page-title-wrapper.fixed-title, .block.filter.fixed-title\";\n var clearance = 10;\n var keyboardNavigation = false;\n\n function fixedOverlayBottom() {\n var bottom = 0;\n\n $(overlaySelectors).each(function () {\n var style = window.getComputedStyle(this),\n rect;\n\n if (style.position !== \"fixed\" && style.position !== \"sticky\") {\n return;\n }\n if (style.display === \"none\" || style.visibility === \"hidden\") {\n return;\n }\n rect = this.getBoundingClientRect();\n\n // ignore overlays that are collapsed or not pinned to the top of the viewport\n if (rect.height === 0 || rect.bottom <= 0 || rect.top > window.innerHeight / 2) {\n return;\n }\n bottom = Math.max(bottom, rect.bottom);\n });\n\n return bottom;\n }\n\n function clearFocusedTile(element) {\n var tile, tileTop, overlayBottom;\n\n if (document.activeElement !== element) {\n return;\n }\n tile = element.closest(\".product-item\") || element;\n tileTop = tile.getBoundingClientRect().top;\n overlayBottom = fixedOverlayBottom();\n\n if (tileTop < overlayBottom + clearance) {\n window.scrollBy(0, tileTop - overlayBottom - clearance);\n }\n }\n\n $(document).ready(function () {\n var $grid = $(\".catalog-category-view .products.wrapper\");\n\n if (!$grid.length) {\n return;\n }\n\n $(document).on(\"keydown\", function (event) {\n keyboardNavigation = eventTab(event);\n });\n $(document).on(\"mousedown\", function () {\n keyboardNavigation = false;\n });\n\n $grid.on(\"focusin\", function (event) {\n if (!keyboardNavigation) {\n return;\n }\n window.requestAnimationFrame(function () {\n clearFocusedTile(event.target);\n });\n\n // scrolling up makes the nav, title and filters bar reappear\n // (sticky-header.js / category-top-of-page.js), re-check once settled\n setTimeout(function () {\n clearFocusedTile(event.target);\n }, 250);\n });\n });\n});\n","js/skip-links.js":"/**\n * Copyright Goyard\n */\ndefine([\n \"jquery\",\n \"access_key\"\n], function ($) {\n \"use strict\";\n $(document).ready(function () {\n // Skip links are hidden off-screen and brought back into the flow on focus,\n // see web/css/source/header/_header.less -> .header-skip-links\n var $mainContent = $('#maincontent');\n\n // The main content area must be programmatically focusable\n if ($mainContent.length > 0) {\n $mainContent.attr('tabindex', '-1');\n }\n if($('li.header-skip-link-navbar a').length > 0) {\n \tdocument.querySelector('li.header-skip-link-navbar a').addEventListener('keyup', function(event) {\n\t if (event.type === 'keyup' && eventEnter(event)) {\n\t let navSectionElement = document.getElementById(\"store.menu\");\n\t if(navSectionElement){\n\t $(navSectionElement).find('a').first().focus();\n\t }\n\t }\n \t});\n }\n // Enter on a link natively fires a click event : a single click handler covers\n // keyboard, mouse and assistive technologies activation\n $('li.header-skip-link-body a').on('click', function (event) {\n if ($mainContent.length > 0) {\n event.preventDefault();\n $mainContent.trigger('focus');\n }\n });\n if($('li.header-skip-link-footer a').length > 0) {\n\t document.querySelector('li.header-skip-link-footer a').addEventListener('keydown', function(event) {\n\t if (event.type === 'keydown' && eventEnter(event)) {\n\t let newsletterInput = document.getElementById('newsletter');\n\t if (newsletterInput) {\n\t newsletterInput.focus();\n\t }\n\t }\n\t });\n }\n });\n});","js/ajax-link-modal.js":"/**\n * Copyright Goyard\n */\nrequire(\n ['jquery',\n 'Magento_Ui/js/modal/modal',\n 'mage/url',\n 'jquery/ui'],\n function($,modal,urlBuilder,ui){\n 'use strict';\n\n $(document).ready(function(){\n const element = $('[data-role=\"ajaxLinkModal\"]');\n const href = element.attr('href');\n const title = element.attr('data-modal-title');\n\n const linkModal = `<div id=\"link-modal\" class=\"link-modal\">\n <div class=\"link-modal goyard-loader\" style=\"display:none; display:flex; justify-content:center; align-items: center\">\n <img src=\"${require.toUrl('images/loader-white.gif')}\" alt=\"Loader\"/>\n </div>\n </div>`;\n\n $('body').append(linkModal).promise().done(function(){\n let options = {\n responsive: true,\n innerScroll: true,\n modalClass: title,\n clickableOverlay: true,\n buttons: []\n };\n let modal_element = $('#link-modal');\n let popup = modal(options, modal_element);\n let pageWrapper = $('.page-wrapper');\n let pageFooter = $('.page-footer');\n\n\n // Open modal & had blur around\n $('[data-role=\"ajaxLinkModal\"]').on('click', function(e){\n e.preventDefault();
2\n modal_element.modal('openModal');\n $('.link-modal.goyard-loader').show();\n \n pageWrapper.addClass('blur4');\n if(pageWrapper.hasClass('blur0')){\n pageWrapper.removeClass('blur0');\n }\n pageFooter.addClass('blur4');\n if(pageFooter.hasClass('blur0')){\n pageFooter.removeClass('blur0');\n }\n })\n // Close modal & delete blur around\n $('#link-modal').on('modalclosed', function() {\n $(\".page-wrapper\").removeClass('blur4').addClass('blur0');\n $(\".page-footer\").removeClass('blur4').addClass('blur0');\n });\n // On modal open\n modal_element.modal({\n opened: function() {\n $.ajax({\n url: href,\n type: 'GET',\n success: function (response) {\n const $reponseHtml = $(response);\n const content = $reponseHtml.find('#maincontent').html();\n $('#link-modal').empty();\n modal_element.append(content);\n modal_element.trigger('contentUpdated');\n $('.link-modal.goyard-loader').hide();\n },\n error: function(xhr, status, error) {\n console.error(error);\n }\n });\n }\n });\n });\n \n })\n});","js/globale-attributes.js":"define([\n\t'jquery',\n\t'Magento_Customer/js/customer-data'\n], function ($, customerData) {\n\t'use strict';\n\n\t$(document).ready(function () {\n\t\tfindGlobaleAttributes();\n\t});\n\n\t/**\n\t * Check user is logged\n\t */\n\tfunction getCustomerData() {\n\t\treturn new Promise(function (resolve, reject) {\n\t\t\tlet customer = customerData.get('customer');\n\t\t\tlet firstname = customer().firstname;\n\t\t\tif (firstname) {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\tcustomer.subscribe(function () {\n\t\t\t\t\tif (customer().firstname) {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Manage summary\n\t * @returns void\n\t */\n\tfunction observeSummary() {\n\t\tvar summaryNode = $('cart-totals').find('.table-wrapper');\n\t\tvar subtotal = $('.totals.sub').find('.price');\n\t\tvar total = $('.grand.totals').find('.price');\n\n\t\tif (summaryNode.hasClass('_block-content-loading') || !subtotal.length || !total.length) {\n\t\t\twindow.setTimeout(observeSummary, 500);\n\t\t\treturn;\n\t\t}\n\t\t// When item in totals exist, add globale attributes\n\t\t$('.totals.sub').find('.price').trigger('update-globale-element');\n\t\t$('.grand.totals').find('.price').trigger('update-globale-element');\n\t}\n\n\t// Check reload/insert of element\n\t$(document).on('update-globale-element', function (e, eventInfo) {\n\t\tgetCustomerData()\n\t\t\t.then(function () {\n\t\t\t\t// TODO - Check global-e is enable current storefront\n\t\t\t\t// if (window.globale_config) {\n\t\t\t\taddGlobaleAttributes($(e.target));\n\t\t\t\t// }\n\t\t\t})\n\t\t\t.catch(function (error) {\n\t\t\t\tconsole.error('Error while fetching data:', error);\n\t\t\t});\n\t});\n\n\t// Price attribute need to be add using js\n\tfunction findGlobaleAttributes() {\n\t\tgetCustomerData()\n\t\t\t.then(function () {\n\t\t\t\t// TODO - Check global-e is enable current storefront\n\t\t\t\t// if (window.globale_config) {\n\t\t\t\t// Add global-e attribute to element which should have it\n\t\t\t\t$('[data-storefront-globale]').each(function () {\n\t\t\t\t\taddGlobaleAttributes($(this));\n\t\t\t\t})\n\n\t\t\t\t// Check minicart\n\t\t\t\t// observeMinicart();\n\t\t\t\t// Price in product page\n\t\t\t\tif ($('.catalog-product-view').length > 0) {\n\t\t\t\t\t$('.product-info-main .product-info-price').find('.price').attr('data-ge-price', '');\n\t\t\t\t}\n\n\t\t\t\t// Price in cart\n\t\t\t\tif (window.basket_conversion_allowed && $('.checkout-cart-index').length > 0) {\n\t\t\t\t\tobserveSummary();\n\n\t\t\t\t\t$('#shopping-cart-table').find('.price').each(function () {\n\t\t\t\t\t\t$(this).attr('data-ge-basket-producttotalprice', '');\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\t// }\n\t\t\t})\n\t\t\t.catch(function (error) {\n\t\t\t\tconsole.error('Error while fetching data:', error);\n\t\t\t});\n\t}\n\n\t// Add global-e attribute to element\n\tfunction addGlobaleAttributes($element) {\n\t\tif ($element.length) {\n\t\t\tlet globaleAttribute = $element.data('storefront-globale')?.split('=')\n\t\t\t$element.attr(globaleAttribute?.[0], globaleAttribute?.[1] ?? '');\n\t\t}\n\t}\n});","js/horizontal-top.js":"/**\n * Copyright \u00a9 2017 Magento. All rights reserved.\n * See COPYING.txt for license details.\n */\n\nrequire([\n 'jquery',\n 'matchMedia',\n \"preheader\",\n 'domReady!'\n], function ($, mediaCheck) {\n 'use strict';\n\n function closeMenu() {\n $(\"html\").removeClass(\"nav-before-open nav-open\");\n $('.vertical-menu').removeClass(\"active\");\n $('.navigation').removeClass('active-level-1 active-level-2');\n $('.megamenu-item').removeClass('active show-child');\n $('.action.nav-toggle').removeClass(\"menu-open\");\n $('.action.nav-toggle').trigger('focus');\n }
2\n\n function isPreheaderReady() {\n return Boolean($('#preheader-wrapper').data('mage-preheader'));\n }\n\n function adjustBlockRightPosition() {\n let header = $('.sections.nav-sections').scrollTop(0);\n let preheaderHeight = $('.preheader-wrapper').length ? $('.preheader-wrapper').height() : 0;\n let pageHeaderHeight = $('.page-header').height();\n let navBarHeight = $('.nav-sections').height();\n let navigationMaxHeight = document.documentElement.clientHeight - (preheaderHeight + pageHeaderHeight + navBarHeight);\n\n if (!$(\".megamenu-item\").hasClass(\"active\")) {\n if (header == 0) {\n $(\"#block-right-broken\").remove();\n } else {\n $(\".block-right\").attr(\"style\", \"top:\" + (preheaderHeight + 120).toString() + \"px\");\n let block_right_broken = document.querySelector(\"#block-right-broken\");\n\n if (!block_right_broken) {\n block_right_broken = document.createElement(\"input\");\n block_right_broken.setAttribute(\"id\", \"block-right-broken\");\n block_right_broken.setAttribute(\"type\", \"hidden\");\n document.body.appendChild(block_right_broken);\n }\n }\n }\n\n // Update navigation menu position\n $('.megamenu-dropdown > .block-main > .megamenu-sub-items').css('max-height', navigationMaxHeight);\n $('.megamenu-item').children('.megamenu-dropdown').css('max-height', navigationMaxHeight);\n $('.block-right').css('max-height', navigationMaxHeight - 15);\n }\n\n function toggleMenuAction(element) {\n $('.megamenu-item').removeClass(\"active\");\n element.addClass(\"active\");\n $('.megamenu-item').find('.megamenu-item-link').first().attr('aria-expanded', 'false');\n element.find('.megamenu-item-link').first().attr(\"aria-expanded\", \"true\");\n\n if (element.hasClass('has-content')) {\n $('.magemenu-menu li.megamenu-item.close-button').addClass('active');\n }\n if (!$('.preheader-wrapper').length > 0 && $('.nav-sections').hasClass('opaque-nav-sections')) {\n let pageHeaderHeight = $('.page-header').height();\n let navBarHeight = $('.nav-sections').height();\n $('.magemenu-menu li.megamenu-item .megamenu-dropdown').css('top', (pageHeaderHeight + navBarHeight).toString() + 'px');\n }\n if ($('.preheader-wrapper').hasClass('initialized') && isPreheaderReady()) {\n $(\"#preheader-wrapper\").preheader(\"adjustToPreheader\");\n }\n }\n\n function closeAction() {\n let header = $(window).scrollTop();\n $('.megamenu-item').find('.megamenu-item-link').attr('aria-expanded', 'false');\n $('.page-main, #marquage-goyard, .page-footer').removeAttr(\"style\");\n $('.page-main').removeClass('blur-page');\n if ($('.magemenu-menu li.megamenu-item.close-button').hasClass('active')) {\n $('.magemenu-menu li.megamenu-item.close-button').removeClass('active');\n $('.nav-sections').removeAttr(\"style\");\n $('.magemenu-menu li.megamenu-item .megamenu-dropdown').removeAttr(\"style\");\n $('.nav-sections').removeClass(\"opaque-nav-sections\");\n $('.magemenu-menu').find('li.megamenu-item').removeClass(\"active\");\n if (header === 0) {\n let windowsize = $(window).width();\n if (windowsize > 768) {\n $('.page-header').addClass(\"anim-top\");\n $('.nav-sections').addClass(\"anim-top\");\n $('.page-header').removeAttr(\"style\");\n if ($('.preheader-wrapper').hasClass('initialized') && isPreheaderReady()) {\n $(\"#preheader-wrapper\").preheader(\"adjustToPreheader\");\n }\n }\n $('.nav-sections').removeClass(\"opaque-nav-sections\");\n $('.page-header').removeClass(\"opaque-header\");\n $('.page-header').removeClass(\"anim-top\");\n $('.nav-sections').removeClass(\"anim-top\");\n } else {\n let windowsize = $(window).width();\n if (windowsize > 768) {\n !$('.page-header').hasClass('opaque-header') ?? $('.page-header').addClass('opaque-header');\n }\n }\n }\n\n // Remove style\n $('.megamenu-dropdown > .block-main > .megamenu-sub-items').removeAttr('style');\n $('.megamenu-item').children('.megamenu-dropdown').removeAttr('style');\n $('.block-right').removeAttr('style');\n }
2\n\n function setBlurStyleOnMenuClick() {\n $('.page-main, #marquage-goyard, .page-footer').attr(\"style\", \"filter: blur(5px) !important\");\n }\n\n function handleSubMenuClick(element) {\n $('.magemenu-menu li.megamenu-sub-item').not($(element).parent()).removeClass('active');\n $(element).parent().toggleClass(\"active\");\n let currentExpandedStatus = element.attr(\"aria-expanded\") === \"true\";\n $('.megamenu-item').find('.megamenu-sub-item.has-child').find('.megamenu-item-link').attr('aria-expanded', 'false');\n element.attr(\"aria-expanded\", !currentExpandedStatus);\n }\n\n function handleMegamenuHover() {\n $(this).find('.tab-menu-content').css({ \"z-index\": \"6\", \"position\": \"absolute\" });\n }\n\n function handleMegamenuHoverOut() {\n $(this).find('.tab-menu-content').removeAttr('style');\n }\n\n function registerEventHandlers() {\n $('.magemenu-menu li.megamenu-item').on(\"click keydown\", function (e) {\n if (e.type === \"click\" || (e.type === \"keydown\" && (e.key === 'Enter' || e.key === ' '))) {\n e.preventDefault();\n toggleMenuAction($(this));\n }\n });\n\n $('.magemenu-menu li.megamenu-item.close-button').on(\"keydown click\", function (e) {\n if (e.type === \"click\" || (e.type === \"keydown\" && (e.key === 'Enter' || e.key === ' '))) {\n e.preventDefault();\n closeAction();\n }\n });\n $('body').on('click', function (event) {\n var container = $('.nav-sections');\n if ((!container.is(event.target) && !container.has(event.target).length)) {\n closeAction();\n }\n });\n $(document).on('keyup', function (e) {\n //ESCAPE KEY\n if (e.which === 27) {\n closeAction();\n $('body').removeClass('_keyfocus');\n }\n });\n //D\u00e9clenchement sur les liens des sous-sous-menus\n $('.megamenu-item-link').on({\n focus: function () {\n if ($('body').hasClass('_keyfocus') && $(this).parent().hasClass('has-child')) {\n let $customDiv = $('<div class=\"access-focus-menu-item\"></div>');\n $(this).append($customDiv);\n }\n },\n blur: function () {\n $(this).find('.access-focus-menu-item').remove();\n },\n keydown: function (e) {\n if (e.key === ' ') {\n e.preventDefault();\n if ($(e.target).is('[href]') && $(e.target).attr('href') !== '#') {\n window.location.href = $(e.target).attr('href');\n }\n } else if (e.key === 'Enter') {\n if ($(e.target).is('[href]') && $(e.target).attr('href') !== '#') {\n window.location.href = $(e.target).attr('href');\n }\n }\n },\n click: function (e) {\n\n if ($(e.target).is('[href]') && $(e.target).attr('href') !== '#') {\n $('.megamenu-item').find('.megamenu-sub-item.has-child').find('.megamenu-item-link').attr('aria-expanded', 'false');\n window.location.href = $(e.target).attr('href');\n }\n }\n });\n // D\u00e9clenchement sur la span des sous-sous-menus\n $('.megamenu-item-inner').on({\n click: function () {\n if ($(this).parent().is('[href]') && $(this).parent().attr('href') !== '#') {\n window.location.href = $(this).parent().attr('href');\n }\n }\n })\n\n $('.magemenu-menu li.megamenu-item.has-content').on(\"keydown click\", function (e) {\n if (e.type === \"click\" || (e.type === \"keydown\" && (e.key === 'Enter' || e.key === ' '))) {\n e.preventDefault();\n setBlurStyleOnMenuClick();\n }\n });\n\n $('.magemenu-menu li.megamenu-sub-item > a').on(\"keydown click\", function (e) {\n if (e.type === \"click\" || (e.type === \"keydown\" && (e.key === 'Enter' || e.key === ' '))) {\n e.preventDefault();\n\n handleSubMenuClick($(this));\n }\n });\n $(\".magemenu-menu.horizontal-menu .megamenu-items > li .megamenu-sub-items li .megamenu-sub-items .megamenu-sub-item\").hover(\n handleMegamenuHover,\n handleMegamenuHoverOut\n );\n }\n\n mediaCheck({\n media: '(min-width: 768px)',\n entry: function () {\n $('.magemenu-menu li.megamenu-item').click(adjustBlockRightPosition);\n registerEventHandlers();\n },\n exit: function () {\n $('.magemenu-menu li.megamenu-item').click(function () {\n $('.sections.nav-sections').scrollTop(0);\n });\n }\n });\n\n mediaCheck({\n media: '(max-width: 768px)',\n entry: function () {\n $(document).on('keydown', function (event) {\n if (event.key === 'Escape') {\n closeMenu();\n }\n });\n // Menu and SubMenu collapse toggles\n $('.magemenu-menu li.megamenu-item.has-content > .menu-collapse, .magemenu-menu li.megamenu-item.has-content .megamenu-dropdown li.megamenu-sub-item.has-child .menu-collapse').on(\"click keydown\", function (e) {\n if (e.type === \"click\" || (e.type === \"keydown\" && (e.key === 'Enter' || e.key === ' '))) {\n e.preventDefault();\n let $link = $(this).parent().find('.megamenu-item-link').first();\n $link.attr('aria-expanded', $link.attr(\"aria-expanded\") !== \"true\");\n }\n });\n }\n });\n});\n","js/sticky-header.js":"/**\n * Copyright Goyard\n */\ndefine([\n \"jquery\",\n \"preheader\"\n], function ($) {\n \"use strict\";\n let scrollPosition = 0;
2\n\n function isPreheaderReady() {\n return Boolean($('#preheader-wrapper').data('mage-preheader'));\n }\n $(window).scroll(function () {\n\n if ($(\".nav-sections\").length > 0) {\n var top_of_nav = $(\".nav-sections\").offset().top;\n var bottom_of_nav = $(\".nav-sections\").offset().top + $(\".nav-sections\").outerHeight();\n var bottom_of_screen = $(window).scrollTop() + $(window).innerHeight();\n var top_of_screen = $(window).scrollTop() + $(\".page-header\").innerHeight();\n\n if ((bottom_of_screen > top_of_nav) && (top_of_screen < bottom_of_nav) && (!$('.searchBar-root_open-hxZ').is(':visible'))) {\n var windowsize = $(window).width();\n if (windowsize > 768) {\n $('.page-header').addClass(\"full-header\");\n if (!$('.modal-inner-wrap').hasClass('scroll-up')) {\n $('.modal-inner-wrap').addClass('mini-scroll');\n };\n }\n } else {\n $('.page-header').addClass(\"opaque-header\");\n $('.modal-inner-wrap').addClass('scroll-down');\n $('.modal-inner-wrap').removeClass('mini-scroll');\n $('.page-header').removeClass(\"full-header\");\n // the element is not visible, do something else\n }\n }\n $(window).on('scroll', function () {\n let header = $(window).scrollTop();\n if (!$('.magemenu-menu li.megamenu-item').hasClass('active')) {\n if (header === 0 && (!$('.searchBar-root_open-hxZ').is(':visible'))) {\n //'header = 0 et search pas visible'\n var windowsize = $(window).width();\n $('.nav-sections').removeClass(\"opaque-nav-sections\");\n $('.page-header').removeClass(\"opaque-header\");\n $('.modal-inner-wrap').removeClass('scroll-down');\n $('.page-header').removeAttr(\"style\", \"position: fixed !important\");\n // pre-header\n if ($(window).width() > 768) {\n if ($('.preheader-wrapper').length > 0) {\n if (!$('.preheader-wrapper').hasClass('initialized')) {\n $('.preheader-wrapper').addClass('initialized');\n $('.preheader-wrapper').css('display', 'block');\n };\n if (isPreheaderReady()) {\n $(\"#preheader-wrapper\").preheader(\"adjustToPreheader\");\n }\n }\n }\n if ($(window).width() < 768) {\n if (!$(\"html\").hasClass(\"nav-before-open nav-open\")) {\n if ($('.preheader-wrapper').length > 0) {\n if (!$('.preheader-wrapper').hasClass('initialized')) {\n $('.preheader-wrapper').addClass('initialized');\n $('.preheader-wrapper').css('display', 'block');\n };\n if (isPreheaderReady()) {\n $(\"#preheader-wrapper\").preheader(\"adjustToPreheader\");\n }\n }\n }\n }\n scrollPosition = header;\n\n if (windowsize > 768) {\n $('.page-header').addClass('anim-back');\n $('.nav-sections').addClass('anim-back-nav');\n }\n } else {\n if ($(window).width() > 768) {\n if ($(window).scrollTop() > 0 && $(window).scrollTop() <= 100 && scrollPosition > header) {\n //entre 0 et 100 avec scroll up\n $('.page-header').removeAttr(\"style\");\n $('.page-header').addClass(\"opaque-header\");\n } else if ($(window).scrollTop() > 0 && $(window).scrollTop() <= 100) {\n //entre 0 et 100 sans scroll up\n scrollPosition = header;\n } else {\n //entre 0 et 100 avec scroll down\n scrollPosition = header;\n $('.page-header').removeAttr(\"style\");\n }\n }\n $('.page-header').removeClass(\"anim-back\");\n $('.nav-sections').removeClass(\"anim-back-nav\");\n if ($('.preheader-wrapper').hasClass('initialized') && isPreheaderReady()) {\n $(\"#preheader-wrapper\").preheader(\"unShowPreHeader\");\n }\n }\n }\n else {\n if (header >= 0 && header <= 100) {\n //header entre 0 et 100 et Menu OUVERT\n $('.nav-sections').attr(\"style\", \"position: fixed !important\");\n $('.page-header').attr(\"style\", \"position: fixed !important\");\n if ($('.preheader-wrapper').length > 0 && $(window).width() > 768) {\n if (!$('.preheader-wrapper').hasClass('initialized')) {\n $('.preheader-wrapper').addClass('initialized');\n $('.preheader-wrapper').css('display', 'block');\n };\n if (isPreheaderReady()) {\n $(\"#preheader-wrapper\").preheader(\"adjustToPreheader\");\n }\n }\n } else {\n //header en dessous de 100 et Menu OUVERT\n $('.nav-sections').attr(\"style\", \"position: fixed !important\");\n $('.page-header').attr(\"style\", \"position: fixed !important\");\n if ($('.preheader-wrapper').length > 0 && $(window).width() > 768 && isPreheaderReady()) {\n if ($('.preheader-wrapper').hasClass('initialized')) {\n $(\"#preheader-wrapper\").preheader(\"unShowPreHeader\");\n }\n $(\"#preheader-wrapper\").preheader(\"adjustToPreheader\");\n }\n }\n }\n });\n $(function () {\n var lastScrollTop = 0, delta = 5;\n $(window).scroll(function () {\n let header = $(window).scrollTop();\n var nowScrollTop = $(this).scrollTop();\n if (!$('.magemenu-menu li.megamenu-item').hasClass('active') && !$('.block-minicart').hasClass('active')) {\n if (Math.abs(lastScrollTop - nowScrollTop) >= delta && $(window).scrollTop() !== 0) {\n if (nowScrollTop > lastScrollTop && lastScrollTop !== 0) {\n // Scrolling down\n $('.nav-sections').removeClass('opaque-nav-sections');\n $('.modal-inner-wrap').removeClass('scroll-up');\n } else if (nowScrollTop < lastScrollTop && lastScrollTop !== 0 && header > 60) {\n // Scrolling up\n $('.nav-sections').addClass('opaque-nav-sections');\n $('.modal-inner-wrap').addClass('scroll-up');\n $('.modal-inner-wrap').removeClass('scroll-down');\n }\n lastScrollTop = nowScrollTop;\n }\n }\n });\n });\n });\n $(document).on('mouseenter', 'header.page-header.opaque-header', function () {\n var windowsize = $(window).width();\n if (windowsize > 768) {\n $('.sections.nav-sections').addClass('opaque-nav-sections');\n }\n });\n});\n","js/navigation-menu.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @deprecated\n * @see lib/web/mage/menu.js\n */\ndefine([\n 'jquery',\n 'matchMedia',\n 'mage/template',\n 'mage/dropdowns',\n 'mage/terms'\n], function ($, mediaCheck, mageTemplate) {\n 'use strict';\n\n $.widget('mage.navigationMenu', {\n options: {\n itemsContainer: '> ul',\n topLevel: 'li.level0',\n topLevelSubmenu: '> .submenu',\n topLevelHoverClass: 'hover',\n expandedTo
2pLevel: '.more',\n hoverInTimeout: 300,\n hoverOutTimeout: 500,\n submenuAnimationSpeed: 200,\n collapsable: true,\n collapsableDropdownTemplate:\n '<script type=\"text/x-magento-template\">' +\n '<li class=\"level0 level-top more parent\">' +\n '<div class=\"submenu\">' +\n '<ul><%= elems %></ul>' +\n '</div>' +\n '</li>' +\n '</script>'\n },\n\n /** @inheritdoc */\n _create: function () {\n this.itemsContainer = $(this.options.itemsContainer, this.element);\n this.topLevel = $(this.options.topLevel, this.element);\n this.topLevelSubmenu = $(this.options.topLevelSubmenu, this.topLevel);\n\n this._bind();\n },\n\n /**\n * @private\n */\n _init: function () {\n if (this.options.collapsable) {\n setTimeout($.proxy(function () {\n this._checkToCollapseOrExpand();\n }, this), 100);\n }\n },\n\n /**\n * @private\n */\n _bind: function () {\n this._on({\n /**\n * @param {jQuery.Event} e\n */\n 'mouseenter > ul > li.level0': function (e) {\n if (!this.entered) { // fix IE bug with 'mouseenter' event\n this.timeoutId && clearTimeout(this.timeoutId);\n this.timeoutId = setTimeout($.proxy(function () {\n this._openSubmenu(e);\n }, this), this.options.hoverInTimeout);\n this.entered = true;\n }\n },\n\n /**\n * @param {jQuery.Event} e\n */\n 'mouseleave > ul > li.level0': function (e) {\n this.entered = null;\n\n this.timeoutId && clearTimeout(this.timeoutId);\n this.timeoutId = setTimeout($.proxy(function () {\n this._closeSubmenu(e.currentTarget);\n }, this), this.options.hoverOutTimeout);\n },\n\n /**\n * @param {jQuert.Event} e\n */\n 'click': function (e) {\n e.stopPropagation();\n }\n });\n\n $(document)\n .on('click.hideMenu', $.proxy(function () {\n var isOpened = this.topLevel.filter(function () {\n return $(this).data('opened');\n });\n\n if (isOpened) {\n this._closeSubmenu(null, false);\n }\n }, this));\n\n $(window)\n .on('resize', $.proxy(function () {\n this.timeoutOnResize && clearTimeout(this.timeoutOnResize);\n this.timeoutOnResize = setTimeout($.proxy(function () {\n if (this.options.collapsable) {\n if ($(this.options.expandedTopLevel, this.element).length) {\n this._expandMenu();\n }\n this._checkToCollapseOrExpand();\n }\n }, this), 300);\n }, this));\n },\n\n /**\n * @param {jQuery.Event} e\n * @private\n */\n _openSubmenu: function (e) {\n var menuItem = e.currentTarget;\n\n if (!$(menuItem).data('opened')) {\n this._closeSubmenu(menuItem, true, true);\n\n $(this.options.topLevelSubmenu, menuItem)\n .slideDown(this.options.submenuAnimationSpeed, $.proxy(function () {\n $(menuItem).addClass(this.options.topLevelHoverClass);\n $(menuItem).data('opened', true);\n }, this));\n } else if ($(e.target).closest(this.options.topLevel)) {\n $(e.target)\n .addClass(this.options.topLevelHoverClass)\n .siblings(this.options.topLevel)\n .removeClass(this.options.topLevelHoverClass);\n }\n },\n\n /**\n * @param {*} menuItem\n * @param {*} excludeCurrent\n * @param {*} fast\n * @private\n */\n _closeSubmenu: function (menuItem, excludeCurrent, fast) {\n var topLevel = $(this.options.topLevel, this.element),\n activeSubmenu = $(this.options.topLevelSubmenu, menuItem || null);\n\n $(this.options.topLevelSubmenu, topLevel)\n .filter(function () {\n return excludeCurrent ? $(this).not(activeSubmenu) : true;\n })\n .slideUp(fast ? 0 : this.options.submenuAnimationSpeed);\n\n topLevel\n .removeClass(this.options.topLevelHoverClass)\n .data('opened', false);\n },\n\n /**\n * @private\n */\n _checkToCollapseOrExpand: function () {\n var navWidth, totalWidth, startCollapseIndex;\n\n if ($('html').hasClass('lt-640') || $('html').hasClass('w-640')) {\
2n return;\n }\n\n navWidth = this.itemsContainer.width();\n totalWidth = 0;\n startCollapseIndex = 0;\n\n $.each($(this.options.topLevel, this.element), function (index, item) {\n totalWidth += $(item).outerWidth(true);\n\n if (totalWidth > navWidth && !startCollapseIndex) {\n startCollapseIndex = index - 2;\n }\n });\n\n this[startCollapseIndex ? '_collapseMenu' : '_expandMenu'](startCollapseIndex);\n },\n\n /**\n * @param {*} startCollapseIndex\n * @private\n */\n _collapseMenu: function (startCollapseIndex) {\n this.elemsToCollapse = this.topLevel.filter(function (index) {\n return index > startCollapseIndex;\n });\n this.elemsToCollapseClone = $('<div></div>').append(this.elemsToCollapse.clone()).html();\n\n this.collapsableDropdown = $(\n mageTemplate(\n this.options.collapsableDropdownTemplate,\n {\n elems: this.elemsToCollapseClone\n }\n )\n );\n\n this.itemsContainer.append(this.collapsableDropdown);\n this.elemsToCollapse.detach();\n },\n\n /**\n * @private\n */\n _expandMenu: function () {\n this.elemsToCollapse && this.elemsToCollapse.appendTo(this.itemsContainer);\n this.collapsableDropdown && this.collapsableDropdown.remove();\n },\n\n /**\n * @private\n */\n _destroy: function () {\n this._expandMenu();\n }\n });\n\n /*\n * Provides \"Continium\" effect for submenu\n * */\n $.widget('mage.navigationMenu', $.mage.navigationMenu, {\n options: {\n parentLevel: '> ul > li.level0',\n submenuAnimationSpeed: 150,\n submenuContiniumEffect: false\n },\n\n /**\n * @private\n */\n _init: function () {\n this._super();\n this._applySubmenuStyles();\n },\n\n /**\n * @private\n */\n _applySubmenuStyles: function () {\n $(this.options.topLevelSubmenu, $(this.options.topLevel, this.element))\n .removeAttr('style');\n\n $(this.options.topLevelSubmenu, $(this.options.parentLevel, this.element))\n .css({\n display: 'block',\n height: 0,\n overflow: 'hidden'\n });\n },\n\n /**\n * @param {jQuery.Event} e\n * @private\n */\n _openSubmenu: function (e) {\n var menuItem = e.currentTarget,\n submenu = $(this.options.topLevelSubmenu, menuItem),\n openedItems = $(this.options.topLevel, this.element).filter(function () {\n return $(this).data('opened');\n });\n\n if (submenu.length) {\n this.heightToAnimate = $(this.options.itemsContainer, submenu).outerHeight(true);\n\n if (openedItems.length) {\n this._closeSubmenu(menuItem, true, this.heightToAnimate, $.proxy(function () {\n submenu.css({\n height: 'auto'\n });\n $(menuItem)\n .addClass(this.options.topLevelHoverClass);\n }, this), e);\n } else {\n submenu.animate({\n height: this.heightToAnimate\n }, this.options.submenuAnimationSpeed, $.proxy(function () {\n $(menuItem)\n .addClass(this.options.topLevelHoverClass);\n }, this));\n }\n\n $(menuItem)\n .data('opened', true);\n } else {\n this._closeSubmenu(menuItem);\n }\n },\n\n /**\n * @param {*} menuItem\n * @param {*} excludeCurrent\n * @param {*} heightToAnimate\n * @param {Function} callback\n * @private\n */\n _closeSubmenu: function (menuItem, excludeCurrent, heightToAnimate, callback) {\n var topLevel = $(this.options.topLevel, this.itemsContainer),\n prevOpenedItem, prevOpenedSubmenu;\n\n if (!excludeCurrent) {\n $(this.options.topLevelSubmenu, $(this.options.parentLevel, this.element))\n .animate({\n height: 0\n });\n\n topLevel\n .data('opened', false)\n .removeClass(this.options.topLevelHoverClass);\n } else {\n prevOpenedItem = topLevel.filter(function () {\n return $(this).data('opened');\n });\n prevOpenedSubmenu = $(this.options.topLevelSubmenu, prevOpenedItem);\n\n prevOpenedSubmenu.animate({\n height: heightToAnimate\n }, this.options.submenuAnimationSpeed, 'linear', function () {\n $(this).css({\n height: 0\n });\n callback && callback();\n });\n\n prevOpenedItem\n .data('opened', false)\n .removeClass(this.options.topLevelHoverClass);\n }\n },\n\n /**\n * @private\n */\n _collapseMenu: function () {\n this._superApply(arguments);\n this._applySubmenuStyles();\n }\n });\n\n // Responsive menu\n $.widget('mage.navigationMenu', $.mage.navigationMenu, {\n options: {\n responsive: false,\n origNavPlaceholder: '.page-header',\n mainContainer: 'body',\n pageWrapper: '.page-wrapper',\n openedMenuClass: 'o
2pened',\n toggleActionPlaceholder: '.block-search',\n itemWithSubmenu: 'li.parent',\n titleWithSubmenu: 'li.parent > a',\n submenu: 'li.parent > .submenu',\n toggleActionTemplate:\n '<script type=\"text/x-magento-template\">' +\n '<span data-action=\"toggle-nav\" class=\"action toggle nav\">Toggle Nav</span>' +\n '</script>',\n submenuActionsTemplate:\n '<script type=\"text/x-magento-template\">' +\n '<li class=\"action all\">' +\n '<a href=\"<%= categoryURL %>\"><span>All <%= category %></span></a>' +\n '</li>' +\n '</script>',\n navigationSectionsWrapperTemplate:\n '<script type=\"text/x-magento-template\">' +\n '<dl class=\"navigation-tabs\" data-sections=\"tabs\">' +\n '</dl>' +\n '</script>',\n navigationItemWrapperTemplate:\n '<script type=\"text/x-magento-template\">' +\n '<dt class=\"item title <% if (active) { %>active<% } %>\" data-section=\"title\">' +\n '<a class=\"switch\" data-toggle=\"switch\" href=\"#TODO\"><%= title %></a>' +\n '</dt>' +\n '<dd class=\"item content <% if (active) { %>active<%}%>\" data-section=\"content\">' +\n '</dd>' +\n '</script>'\n },\n\n /**\n * @private\n */\n _init: function () {\n this._super();\n\n this.mainContainer = $(this.options.mainContainer);\n this.pageWrapper = $(this.options.pageWrapper);\n this.toggleAction = $(mageTemplate(this.options.toggleActionTemplate, {}));\n\n if (this.options.responsive) {\n mediaCheck({\n media: '(min-width: 768px)',\n entry: $.proxy(function () {\n this._toggleDesktopMode();\n }, this),\n exit: $.proxy(function () {\n this._toggleMobileMode();\n }, this)\n });\n }\n },\n\n /**\n * @private\n */\n _bind: function () {\n this._super();\n this._bindDocumentEvents();\n },\n\n /**\n * @private\n */\n _bindDocumentEvents: function () {\n if (!this.eventsBound) {\n $(document)\n .on('click.toggleMenu', '.action.toggle.nav', $.proxy(function (e) {\n if ($(this.element).data('opened')) {\n this._hideMenu();\n } else {\n this._showMenu();\n }\n e.stopPropagation();\n this.mobileNav.scrollTop(0);\n this._fixedBackLink();\n }, this))\n .on('click.hideMenu', this.options.pageWrapper, $.proxy(function () {\n if ($(this.element).data('opened')) {\n this._hideMenu();\n this.mobileNav.scrollTop(0);\n this._fixedBackLink();\n }\n }, this))\n .on('click.showSubmenu', this.options.titleWithSubmenu, $.proxy(function (e) {\n this._showSubmenu(e);\n\n e.preventDefault();\n this.mobileNav.scrollTop(0);\n this._fixedBackLink();\n }, this))\n .on('click.hideSubmenu', '.action.back', $.proxy(function (e) {\n this._hideSubmenu(e);\n this.mobileNav.scrollTop(0);\n this._fixedBackLink();\n }, this));\n\n this.eventsBound = true;\n }\n },\n\n /**\n * @private\n */\n _showMenu: function () {\n $(this.element).data('opened', true);\n this.mainContainer.add('html').addClass(this.options.openedMenuClass);\n },\n\n /**\n * @private\n */\n _hideMenu: function () {\n $(this.element).data('opened', false);\n this.mainContainer.add('html').removeClass(this.options.openedMenuClass);\n },\n\n /**\n * @param {jQuery.Event} e\n * @private\n */\n _showSubmenu: function (e) {\n var submenu;\n\n $(e.currentTarget).addClass('action back');\n submenu = $(e.currentTarget).siblings('.submenu');\n\n submenu.addClass('opened');\n },\n\n /**\n * @param {jQuery.Event} e\n * @private\n */\n _hideSubmenu: function (e) {\n var submenuSelector = '.submenu',\n submenu = $(e.currentTarget).next(submenuSelector);\n\n $(e.currentTarget).removeClass('action back');\n submenu.removeClass('opened');\n },\n\n /**\n * @private\n */\n _renderSubmenuActions: function () {\n $.each(\n $(this.options.itemWithSubmenu),\n $.proxy(function (index, item) {\n var actions = $(mageTemplate(\n this.options.submenuActionsTemplate,\n {\n category: $('> a > span', item).text(),\n categoryURL: $('> a', item).attr('href')\n }\n )),\n submenu = $('> .submenu', item),\n items = $('> ul', submenu);\n\n items.prepend(actions);\n }, this)\n );\n },\n\n /**\n * @private\n */\n _toggleMobileMode: function () {\n this._expandMenu();\n\n $(this.options.topLevelSubmenu, $(this.options.topLevel, this.element))\n .removeAttr('style');\n\n this.toggleAction.insertBefore(this.options.toggleActionPlaceholder);\n this.mobileNav = $(this.element).detach().clone();\n this.mainContainer.prepend(this.mobileNav);\n this.mobileNav.find('> ul').addClass('nav');\n this._insertExtraItems();\n this._wrapItemsInSections();\n this.mobileNav.scroll($.proxy(function () {\n this._fixedBackLink();\n }, this));\n\n this._renderSubmenuActions();\n this._bindDocumentEvents();\n },\n\n /**\n * @private\n */\n _toggleDesktopMode: function () {\n this.mobileNav && this.mobileNav.remove();\n this.toggleAction.detach();\n $(this.element).insertAfter(this.options.origNavPlaceholder);\n\n $(document)\n .off('click.toggleMenu', '.action.toggle.nav')\n .off('click.hideMenu', this.options.pageWrapper)\n .off('click.showSubmenu', this.options.titleWithSubmenu)\n .off('click.hideSubmenu', '.action.back');\n\n this.eventsBound = false;\n\n this._applySubmenuStyles();\n },\n\n /**\n * @private\n */\n _insertExtraItems: function () {\n var settings, footerSettings, account;\n\n if ($('.header.panel .switcher').length) {\n settings = $('.header.panel .switcher')\n .clone()\n .addClass('settings');\n\n this.mobileNav.prepend(settings);\n }\n\n if ($('.footer .switcher').length) {\n footerSettings = $('.footer .switcher')\n .clone()\n .addClass('settings');\n\n this.mobileNav.prepend(footerSettings);\n }\n\n if ($('.header.panel .header.links li').length) {\n account = $('.header.panel > .header.links')\n .clone()\n .addClass('account');\n\n this.mobileNav.prepend(account);\n }\n },\n\n /**\n * @private\n */\n _wrapItemsInSections: function () {\n var account = $('> .account', this.mobileNav),\n settings = $('> .settings', this.mobileNav),\n nav = $('> .nav', this.mobileNav),\n navigationSectionsWrapper = $(mageTemplate(this.options.navigationSectionsWrapperTemplate, {})),\n navigationItemWrapper;\n\n this.mobileNav.append(navigationSectionsWrapper);\n\n if (nav.length) {\n navigationItemWrapper = $(mageTemplate(this.options.navigationItemWrapperTemplate, {\n title: 'Menu'\n }));\n navigationSectionsWrapper.append(navigationItemWrapper);\n navigationItemWrapper.eq(1).append(nav);\n }\n\n if (account.length) {\n navigationItemWrapper = $(mageTemplate(this.options.navigationItemWrapperTemplate, {\n title: 'Account'\n }));\n navigationSectionsWrapper.append(navigationItemWrapper);\n navigationItemWrapper.eq(1).append(account);\n }\n\n if (settings.length) {\n navigationItemWrapper = $(\n mageTemplate(this.options.navigationItemWrapperTemplate, {\n title: 'Settings'\n })\n );\n navigationSectionsWrapper.append(navigationItemWrapper);\n navigationItemWrapper.eq(1).append(settings);\n }\n\n navigationSectionsWrapper.addClass(\n 'navigation-tabs-' + navigationSectionsWrapper.find('[data-section=\"title\"]').length\n );\n navigationSectionsWrapper.terms();\n },\n\n /**\n * @private\n */\n _fixedBackLink: function () {\n var linksBack = this.mobileNav.find('.submenu .action.back'),\n linkBack = this.mobileNav.find('.submenu.opened > ul >
2 .action.back').last(),\n subMenu, navOffset, linkBackHeight;\n\n linksBack.removeClass('fixed');\n\n if (linkBack.length) {\n subMenu = linkBack.parent();\n navOffset = this.mobileNav.find('.nav').position().top;\n linkBackHeight = linkBack.height();\n\n if (navOffset <= 0) {\n linkBack.addClass('fixed');\n subMenu.css({\n paddingTop: linkBackHeight\n });\n } else {\n linkBack.removeClass('fixed');\n subMenu.css({\n paddingTop: 0\n });\n }\n }\n }\n });\n\n return $.mage.navigationMenu;\n});\n","js/accessibility-mode.js":"/**\n* Copyright Goyard\n*/\ndefine([\n \"jquery\",\n \"mage/cookies\",\n 'mage/translate'\n], function ($) {\n \"use strict\";\n\n const CLASS_ACCESSIBILITY_CONTRAST = 'accessibility_mode_constrast';\n const CLASS_ACCESSIBILITY_ANIMATION = 'accessibility_mode_animation';\n const EVENT_REDUCED_ANIMATION = new CustomEvent(\"reductAnimation\", { detail: { animation: true } });\n\n function init() {\n const isContrastMode = $.mage.cookies.get('accessibility_mode_constrast') === \"true\";\n const isAnimationMode = $.mage.cookies.get('accessibility_mode_animation') === \"true\";\n\n setContrastMode(isContrastMode);\n setAnimationMode(isAnimationMode);\n\n $('#upgradeConstrast').click(function () {\n toggleContrastMode();\n });\n\n $('#reductAnimation').click(function () {\n toggleAnimationMode();\n });\n }\n\n function setContrastMode(enabled) {\n $('body').toggleClass(CLASS_ACCESSIBILITY_CONTRAST, enabled);\n if (document.getElementById('upgradeConstrast')) {\n document.getElementById('upgradeConstrast').checked = enabled;\n }\n }\n\n function setAnimationMode(enabled) {\n $('body').toggleClass(CLASS_ACCESSIBILITY_ANIMATION, enabled);\n if (document.getElementById('reductAnimation')) {\n document.getElementById('reductAnimation').checked = enabled;\n document.dispatchEvent(enabled ? EVENT_REDUCED_ANIMATION : new CustomEvent(\"reductAnimation\", { detail: { animation: false } }));\n }\n }\n\n\n function toggleContrastMode() {\n setContrastMode(!$('body').hasClass(CLASS_ACCESSIBILITY_CONTRAST));\n $.mage.cookies.set('accessibility_mode_constrast', $('body').hasClass(CLASS_ACCESSIBILITY_CONTRAST), 24);\n }\n\n function toggleAnimationMode() {\n setAnimationMode(!$('body').hasClass(CLASS_ACCESSIBILITY_ANIMATION));\n $.mage.cookies.set('accessibility_mode_animation', $('body').hasClass(CLASS_ACCESSIBILITY_ANIMATION), 24);\n }\n\n $(document).ready(init);\n});","js/breadcrumb-navigation.js":"/**\n * Copyright Goyard Orkester\n *\n * Dynamic breadcrumb override based on navigation context.\n *\n * On category pages : persists the current breadcrumb path + page URL into\n * sessionStorage on every page load (no click dependency).\n * On product pages : reads sessionStorage and verifies via document.referrer\n * that the user actually came from the stored category before\n * replacing the server-rendered breadcrumb.\n *\n * The server-rendered canonical breadcrumb is never altered server-side,\n * so crawlers and direct URL access always see the canonical path (SEO safe).\n */\ndefine(['jquery'], function ($) {\n 'use strict';\n\n var STORAGE_KEY = 'goyard_nav_breadcrumb';\n\n /**\n * Reads all breadcrumb items from the current category page DOM.\n * The last item has no <a> tag (it is the current page), so we assign\n * window.location.href as its URL so it becomes a link on the product page.\n *\n * @returns {Array<{label: string, url: string, cssClass: string}>}\n */\n function readCategoryBreadcrumbs() {\n var crumbs = [];\n\n $('.breadcrumbs .items .item').each(function () {\n var $item = $(this);\n var $link = $item.find('a');\n var label, url;\n\n if ($link.length) {\n label = $.trim($link.text());\n url = $link.attr('href');\n } else {\n var $strong = $item.find('strong');\n label = $.trim($strong.length ? $strong.text() : $item.text());\n url = window.location.href;\n }\n\n crumbs.push({ label: label, url: url, cssClass: $item.attr('class') || '' });\n });\n\n return crumbs;\n }\n\n /**\n * Persists the current category breadcrumb path and page URL into sessionStorage.\n * Runs on every category page load \u2014 no click handler needed \u2014 so the stored\n * data always reflects the last visited category regardless of how the user\n * navigates within the page (image click, title click, keyboard, etc.).\n */\n function storeCategoryBreadcrumbs() {\n var crumbs = readCategoryBreadcrumbs();\n\n if (crumbs.length < 2) {\n return;\n }\n\n try {\n sessionStorage.setItem(STORAGE_KEY, JSON.stringify({\n crumbs: crumbs,\n categoryUrl: window.location.href\n }));\n } catch (e) {\n console.warn('[Goyard Breadcrumb] Could not write to sessionStorage:', e.message);\n }\n }\n\n /**\n * Overrides the server-rendered breadcrumb with the stored navigation path.\n * Guards against stale data by comparing document.referrer with the stored\n * categoryUrl \u2014 the override only applies when the user actually navigated\n * from that exact category page in this page load.\n */\n function overrideBreadcrumbsFromSession() {\n var raw;\n\n try {\n raw = sessionStorage.getItem(STORAGE_KEY);\n } catch (e) {\n console.warn('[Goyard Breadcrumb] Could not read from sessionStorage:', e.message);\n return;\n }\n\n if (!raw) {\n return;\n }\n\n var data;\n\n try {\n data = JSON.parse(raw);\n } catch (e) {\n return;\n }\n\n if (!data || !data.crumbs || !data.crumbs.length || !data.categoryUrl) {\n return;\n }\n\n // Verify the user actually navigated from the stored category.\n // W
2ithout this check, stale sessionStorage data from a previous category\n // would pollute direct URL access or navigation from unrelated pages.\n if (!document.referrer) {\n return;\n }\n\n var referrer = document.referrer.replace(/\\/$/, '');\n var categoryUrl = data.categoryUrl.replace(/\\/$/, '');\n\n if (referrer !== categoryUrl) {\n return;\n }\n\n $('.breadcrumbs .items').each(function () {\n var $list = $(this);\n $list.empty();\n\n $.each(data.crumbs, function (i, crumb) {\n var $li = $('<li>').addClass(crumb.cssClass);\n\n if (crumb.url) {\n $li.append($('<a>').attr({ href: crumb.url, title: '' }).text(crumb.label));\n } else {\n $li.append($('<strong>').text(crumb.label));\n }\n\n $list.append($li);\n });\n });\n }\n\n $(document).ready(function () {\n if (document.body.classList.contains('catalog-category-view')) {\
2n storeCategoryBreadcrumbs();\n } else if (document.body.classList.contains('catalog-product-view')) {\n overrideBreadcrumbsFromSession();\n }\n });\n});\n","js/category-top-of-page.js":"/**\n * Copyright Goyard\n */\nrequire([\n 'jquery'\n], function ($) {\n // Add page title to category description\n $(document).ready(function () {\n if ($('.pagebuilder-banner-wrapper').length > 0) {\n $('.page-title-wrapper').prependTo('.pagebuilder-banner-wrapper');\n }\n });\n\n let lastScroll = 0;\n let filterTop = $('.block.filter').offset()?.top ?? 0;\n let titleTop = $('.page-title-wrapper').offset()?.top ?? 0;\n let headerTop = ($('.page-header').height() ?? 0);\n let navHeight = $(window).width() > 768 ? $('.nav-sections').height() ?? 0 : 0;\n let banner = $('.pagebuilder-banner-wrapper').css('background-image');\n $(window).scroll(function () {\n let scrollPosition = $(this).scrollTop();\n let titleHeight = $('.page-title-wrapper').height() ?? 0;\n\n if (scrollPosition > lastScroll) { // Scroll down\n $('.block.filter').addClass('scroll-down');\n $('.block.filter').removeClass('scroll-up');\n $('.page-title-wrapper').addClass('scroll-down');\n $('.page-title-wrapper').removeClass('scroll-up');\n } else { // Scroll up\n $('.block.filter').removeClass('scroll-down');\n $('.block.filter').addClass('scroll-up');\n $('.page-title-wrapper').removeClass('scroll-down');\n $('.page-title-wrapper').addClass('scroll-up');\n }\n lastScroll = scrollPosition;\n\n // Manage filters\n if ((scrollPosition + headerTop + titleHeight + navHeight) > filterTop) {\n $('.block.filter').css('position', 'fixed');\n if ($('.block.filter').hasClass('scroll-down')) {\n $('.block.filter').css('top', headerTop + titleHeight + 'px');\n }\n else if ($('.block.filter').hasClass('scroll-up')) {\n $('.block.filter').css('top', headerTop + titleHeight + navHeight + 'px');\n }\n $('.block.filter').addClass('fixed-title');\n $('.pagebuilder-banner-wrapper').css('background-image', 'none');\n }\n else {\n $('.block.filter').css('position', 'static');\n $('.block.filter').removeClass('fixed-title');\n $('.pagebuilder-banner-wrapper').css('background-image', banner);\n }\n\n // Manage page title\n if ((scrollPosition + headerTop + navHeight) > titleTop) {\n $('.page-title-wrapper').css('position', 'fixed');\n if ($('.page-title-wrapper').hasClass('scroll-down')) {\n $('.page-title-wrapper').css('top', headerTop + 'px');\n }\n else if ($('.page-title-wrapper').hasClass('scroll-up')) {\n $('.page-title-wrapper').css('top', headerTop + navHeight + 'px');\n }\n $('.page-title-wrapper').addClass('fixed-title');\n $('.breadcrumbs').css('visibility', 'hidden');\n }\n else {\n $('.page-title-wrapper').css('position', 'static');\n $('.page-title-wrapper').removeClass('fixed-title');\n $('.breadcrumbs').css('visibility', 'visible');\n }\n\n // Reset positions\n if ($(this).scrollTop() < 1) {\n $('.block.filter').css('position', 'static');\n $('.block.filter').removeClass('fixed-title');\n $('.page-title-wrapper').css('position', 'static');\n $('.page-title-wrapper').removeClass('fixed-title');\n }\n });\n\n // Update position of title and filter when nav is visible\n $(document).on('mouseenter', 'header.page-header.opaque-header', function () {\n if ($('.page-title-wrapper').hasClass('fixed-title')) {\n let titleHeight = $('.page-title-wrapper').height() ?? 0;\n\n $('.page-title-wrapper').css('top', headerTop + navHeight + 'px');\n $('.block.filter').css('top', headerTop + titleHeight + navHeight + 'px');\n }\n });\n});\n","js/pagebuilder-video.js":"define([\n \"jquery\",\n \"Goyard_Catalog/js/video-playback\"\n], function ($, videoPlayback) {\n \"use strict\";\n $(document).ready(function () {\n $(\"video[autoplay]\", \".background-video-cover\").each(function (i,video) {\n\t\t\tvideo.playsinline=true;\n\t\t\tvideo.muted=true;\t\t\t\n video.controls=false;\n video.loop=true;\n $(video).attr('playsinline','');\n });\n \n $('[data-background-type=\"video\"], .background-video-cover').each(function () {\n\t\t\tconst buttonList = \"<ul class='video-button-list' aria-label='video controls'></ul>\";\n\t\t\t$(this).append(buttonList);\n\n\t\t\t// add test on CSS class to check if behavior apply to the video\n\t\t\t// CSS : no-play\n\t\t\tif(!$(this).hasClass('no-play')){\n\t\t\t\tcreatePlayButton(this);\n\t\t\t}\n\t\t\t\n\t\t\t// CSS : no-sound\n\t\t\tif(!$(this).hasClass('no-sound')){\n\t\t\t\tcreateSoundButton(this);\t\n\t\t\t}\n });\n \n document.addEventListener(\"reductAnimation\", (event) => {\n\t\t\tlet pageBuilderVideo = $('.pagebuilder-video-container').find('video');\n\n\t\t\t$(\"video[autoplay]\", \".background-video-cover\").each(function(i,video){\n event.detail.animation ? videoPlayback.pause(video) : videoPlayback.play(video);\n\t\t\t\t$(video).attr('aria-label',event.detail.animation ? 'Pause' : 'Play');\n })\n\t\t\t\n if (event.detail.animation === false) {\n \t$('.video-play-button.play-off').each(function(){\n\t\t\t\t\t$(this).removeClass('play-off').addClass('play-on');\n\t\t\t\t\t$(this).attr('aria-label','Pause');\n\t\t\t\t});\n\t\t\t\t$(pageBuilderVideo).each(function(){\n\t\t\t\t\tvideoPlayback.play(this);\n\t\t\t\t\t$(this).attr('aria-label','Pause');\n\t\t\t\t});\n }
2else{\n\t\t\t\t$('.video-play-button.play-on').each(function(){\n\t\t\t\t\t$(this).removeClass('play-on').addClass('play-off');\n\t\t\t\t\t$(this).attr('aria-label','Play');\n\t\t\t\t}); \n\t\t\t\t$(pageBuilderVideo).each(function(){\n\t\t\t\t\tvideoPlayback.pause(this);\n\t\t\t\t\t$(this).attr('aria-label','Play');\n\t\t\t\t});\n\t\t\t}\n });\n });\n \n /**\n *\n */\n function createSoundButton(videoWrapper){\t\t\n\t\t\n\t\tlet soundBtn = \"<li><button type='button' class='video-sound-button sound-off' tabindex='0' aria-label='Sound on'></button></li>\";\n\t\t$(videoWrapper).find('.video-button-list').append(soundBtn);\n\t\t\n\t\t$(videoWrapper).find('.video-sound-button').click(function(){\n\t\t\tif($(this).hasClass('sound-off')){\n\t\t\t\t$(this).closest('[data-background-type=\"video\"], .background-video-cover').find(\"video\").get(0).muted = false;\n\t\t\t\t$(this).removeClass('sound-off').addClass('sound-on');\n\t\t\t\t$(this).attr('aria-label','Sound off');\n\t\t\t}else{\n\t\t\t\t$(this).closest('[data-background-type=\"video\"], .background-video-cover').find(\"video\").get(0).muted = true;\n\t\t\t\t$(this).removeClass('sound-on').addClass('sound-off');\n\t\t\t\t$(this).attr('aria-label','Sound on');\n\t\t\t}\n\t\t});\n\t}\n\t\n\t/**\n\t*\n\t*/\n\tfunction createPlayButton(videoWrapper){\n\t\tlet playBtn = \"<li><button type='button' class='video-play-button play-on' tabindex='0' aria-label='Pause'></button></li>\";\n\t\t$(videoWrapper).find('.video-button-list').append(playBtn);\n\n\t\t$(videoWrapper).find('.video-play-button').click(function(){\n\t\t\tif($(this).hasClass('play-off')){\n\t\t\t\t$(this).removeClass('play-off').addClass('play-on');\n\t\t\t\tvideoPlayback.play($(this).closest('[data-background-type=\"video\"], .background-video-cover').find(\"video\").get(0));\n\t\t\t\t$(this).attr('aria-label','Pause');\n\n\t\t\t}else{\n\t\t\t\t$(this).removeClass('play-on').addClass('play-off');\n\t\t\t\tvideoPlayback.pause($(this).closest('[data-background-type=\"video\"], .background-video-cover').find(\"video\").get(0));\n\t\t\t\t$(this).attr('aria-label','Play');\n\t\t\t}\n\t\t});\n\n\t}\n\t\n\tfunction isVideoInViewport(element) {\n\t\tconst percentVisible = 2;\n\t const rect = element.getBoundingClientRect();\n\t const windowHeight = (window.innerHeight || document.documentElement.clientHeight);\n\t \t\n\t\treturn !(\n\t\t Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-rect.height) * 100)) < percentVisible ||\n\t\t Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible\n\t\t );\n\t}\n\t\n\t/**\n\t* Catch scroll event to pause/mute video when outside of the viewport windows\n\t*/\n\t$( window ).scroll(function() {\n\t\t// Sound\n\t\t$('.video-sound-button.sound-on').each(function(){\n\t\t\tif($(this).parent().find(\"video\").length > 0)\n\t\t\t{\n\t\t\t\tlet isVisible = isVideoInViewport($(this).parent().find(\"video\").get(0));\n\t\t\t\tif(!isVisible){\n\t\t\t\t\t$(this).parent().find(\"video\").get(0).muted = true;\n\t\t\t\t\t$(this).removeClass('sound-on').addClass('sound-off');\n\t\t\t\t\t$(this).attr('aria-label','Sound on');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\t// Play\n\t\t$('.video-play-button.play-on').each(function(){\n\t\t\tif($(this).parent().find(\"video\").length > 0)\n\t\t\t{\n\t\t\t\tlet video = $(this).parent().find(\"video\").get(0);\n\t\t\t\tlet isVisible = isVideoInViewport(video);\n\n\t\t\t\tif(!isVisible){\n\t\t\t\t\tvideoPlayback.pause(video);\n\t\t\t\t}else if(video.paused){\n\t\t\t\t\t// HTMLVideoElement n'expose pas de propriete \"playing\" : sans ce\n\t\t\t\t\t// test sur \"paused\", chaque evenement de scroll relance un play()\n\t\t\t\t\tvideoPlayback.play(video);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n})","js/gallery-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'fotorama/fotorama',\n 'underscore',\n 'matchMedia',\n 'mage/template',\n 'text!mage/gallery/gallery.html',\n 'uiClass',\n 'mage/translate'\n], function ($, fotorama, _, mediaCheck, template, galleryTpl, Class, $t) {\n 'use strict';\n return function (gallery) {\n return gallery.extend({\n\n /**\n * GOYARD - allow arrow on touch devices\n * \n * Checks if device has touch interface.\n * @return {Boolean} The result of searching touch events on device.\n */\n isTouchEnabled: (function () {\n return false;\n })(),\n\n initFullscreenSettings: function () {\n var settings = this.settings,\n self = this;\n\n settings.$gallery = this.settings.$element.find('[data-gallery-role=\"gallery\"]');\n settings.$fullscreenIcon = this.settings.$element.find('[data-gallery-role=\"fotorama__fullscreen-icon\"]');\n settings.focusableStart = this.settings.$element.find('[data-gallery-role=\"fotorama__focusable-start\"]');\n settings.focusableEnd = this.settings.$element.find('[data-gallery-role=\"fotorama__focusable-end\"]');\n settings.closeIcon = this.settings.$element.find('[data-gallery-role=\"fotorama__fullscreen-icon\"]');\n settings.fullscreenConfig.swipe = true;\n\n settings.$gallery.on('fotorama:fullscreenenter', function () {\n settings.closeIcon.show();\n settings.focusableStart.attr('tabindex', '0');\n settings.focusableEnd.attr('tabindex', '0');\n settings.focusableStart.on('focusin', self._focusSwitcher);\n settings.focusableEnd.on('focusin', self._focusSwitcher);\n settings.api.updateOptions(settings.defaultConfig.options, true);\n settings.api.updateOptions(settings.fullscreenConfig, true);\n\n if (!_.isEqual(settings.activeBreakpoint, {}) && settings.breakpoints) {\n settings.api.updateOptions(settings.activeBreakpoint.options, true);\n }\n settings.isFullscreen = true;\n $(\".logo\").toggleClass(\"pointer-events\");\n });\n\n settings.$gallery.on('fotorama:fullscreenexit', function () {\n settings.closeIcon.hide();\n settings.focusableStart.attr('tabindex', '-1');\n settings.focusableEnd.attr('tabindex', '-1');\n settings.api.updateOptions(settings.defaultConfig.options, true);\n settings.focusableStart.off('focusin', this._focusSwitcher);\n settings.focusableEnd.off('focusin', this._focusSwitcher);\n settings.closeIcon.hide();\n\n if (!_.isEqual(settings.activeBreakpoint, {}) && settings.breakpoints) {\n settings.api.updateOptions(settings.activeBreakpoint.options, true);\n }\n settings.isFullscreen = false;\n settings.$element.data('gallery').updateOptions({\n swipe: true\n });\n setTimeout(() =>
2 {\n $(\".logo\").toggleClass(\"pointer-events\");\n }\n , 200);\n });\n }\n });\n }\n});\n","js/category-filter-display.js":"/**\r\n * Copyright Goyard\r\n */\r\ndefine([\r\n \"jquery\"\r\n], function($){\r\n \"use strict\";\r\n\r\n \t$(document).ready(function(){\r\n\r\n \t\t$('.block-title.filter-title').click(function(){\r\n \t\t\tif(!$('.filter-top').first().hasClass(\"active\")){\r\n\t\t\t\t$('.filter-content').show();\r\n\t\t\t\t$(this).addClass('active');\r\n\t\t\t\t$('.filter-top').addClass('active');\r\n\t\t\t\t$('.page-main').addClass('filter-above');\r\n\t\t\t\t$('.page-main').addClass('filter-above');\r\n\t\t\t\t$('#back_top').hide();\r\n\t\t\t\t$('html').addClass('filter-opened');\r\n\r\n\t\t\t\t// Add test if block filter is bigger than the screen height\r\n const windowHeight = $(window).height() - $(\".nav-sections\").height() - $(\".page-header\").height();\r\n const filterHeight = $(\".block.filter\").height();\r\n if ($(window).width() > 1024 && filterHeight > windowHeight) {\r\n $('.block.filter').addClass('position-relative');\r\n }\r\n\t\t\t}else{\r\n $('.filter-content').hide();\r\n\t\t\t\t$(this).removeClass('active');\r\n\t\t\t\t$('.filter-top').removeClass('active');\r\n\t\t\t\t$('.page-main').removeClass('filter-above');\r\n $('#back_top').show();\r\n\t\t\t\t$('html').removeClass('filter-opened');\r\n if ($(window).width() > 1024) {\r\n $('.block.filter').removeClass('position-relative');\r\n }\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\t$('#filter-close').click(function(){\r\n\t\t\t$('.block-title.filter-title').removeClass('active');\r\n\t\t\t$('.filter-top').removeClass('active');\r\n $('.page-main').removeClass('filter-above');\r\n $('#back_top').show();\r\n\t\t\t$('.filter-content').hide();\r\n\t\t\t$('html').removeClass('filter-opened');\r\n\t\t});\r\n\r\n \t});\r\n\r\n});\r\n","js/validation-mixin.js":"/**\n * Copyright Goyard\n */\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n return function (target) {\n $.validator.addMethod(\n 'required-email',\n function (v) {\n return !(v == '' || (v == null) || (v.length == 0) || /^\\s+$/.test(v));\n },\n $.mage.__('The field e-mail address is required')\n );\n\n $.validator.addMethod(\n 'validate-name-goyard',\n function (v) {\n return $.mage.isEmptyNoTrim(v) || /^[\\p{L}\\p{M},\\-_.'\u2019`&\\s\\d]{1,255}$/u.test(v);\n },\n $.mage.__('Please enter a valid name.')\n );\n\n $.widget('mage.validation', $.mage.validation, {\n options: {\n errorElement: 'p',\n },\n\n /**\n * GOYARD - prevent scroll on validation for .no-scroll form\n *\n * Handle form validation. Focus on first invalid form field.\n *\n * @param {jQuery.Event} event\n * @param {Object} validation\n */\n listenFormValidateHandler: function (event, validation) {\n // Usual behaviour\n if (!$(validation?.currentForm)?.hasClass('no-scroll')) {\n return this._super(event, validation);\n }\n\n try {\n var successList = validation.successList;\n\n if (successList.length) {\n $.each(successList, function () {\n $(this)\n .removeAttr('aria-describedby')\n .removeAttr('aria-invalid');\n });\n }\n } catch (e) {\n // Don't do anything\n }\n\n return true;\n }\n });\n\n var showLabel = $.validator.prototype.showLabel;\n $.validator.prototype.showLabel = function (element, message) {\n var label, elem, ariaDescribedby = $(element).attr('aria-describedby');\n\n showLabel.call(this, element, message);\n\n // ARIA (adding aria-invalid & aria-describedby)\n label = this.errorsFor(element);\n elem = $(element);
2\n\n if (!label.attr('id')) {\n label.attr('id', this.idOrName(element) + '-error');\n }\n\n elem.attr('aria-invalid', 'true');\n // GOYARD accessibility changes to add error message id in aria-describedby instead of override it\n if (!(elem.attr('aria-describedby') || '').includes(label.attr('id')))\n elem.attr('aria-describedby', (elem.attr('aria-describedby') || '') + ' ' + label.attr('id'));\n ariaDescribedby = ariaDescribedby?.replaceAll(label.attr('id') + ' ', '');\n if (!(elem.attr('aria-describedby') || '').includes(ariaDescribedby))\n elem.attr('aria-describedby', (elem.attr('aria-describedby') || '') + ' ' + ariaDescribedby);\n };\n\n return target\n }\n\n});\n","js/smooth-scrolling.js":"/**\r\n * Copyright Goyard\r\n */\r\ndefine([\r\n \"jquery\"\r\n], function($){\r\n \"use strict\";\r\n\r\n \t$(document).ready(function(){\r\n\t\r\n \t\tdocument.querySelectorAll('a[href^=\"#\"]:not(.cancel-order)').forEach(anchor => {\r\n\t\t // Skip links move the focus themselves, see skip-links.js\r\n\t\t if (anchor.closest('.header-skip-links')) {\r\n\t\t return;\r\n\t\t }\r\n\r\n\t\t anchor.addEventListener('click', function (e) {\r\n\t\t e.preventDefault();\r\n\t\t\r\n\t\t var href = this.getAttribute('href');\r\n\t \tif(href !== \"#\" && /^#[a-zA-Z]/.test(href))\r\n\t \t{\r\n\t\t \tdocument.querySelector(href).scrollIntoView({\r\n\t\t behavior: 'smooth'\r\n\t\t \t});\r\n\t \t}\r\n\t\t });\r\n\t\t});\r\n \t\t\r\n \t}); \r\n \r\n});","js/header-menu-align-items.js":"/**\r\n * Copyright Goyard\r\n */\r\ndefine([\r\n \"jquery\"\r\n], function($){\r\n \"use strict\"; \r\n \r\n var left_submenu_margin = 5;\r\n \r\n $(document).ready(function(){\r\n\t\t\r\n\t\t// Align the submenu column with the horizontal top menu item\r\n \t/*$(\".magemenu-menu.horizontal-menu .megamenu-items > li\").hover(function(evt){ \t\t\r\n \t\tvar submenu_content = $(this).find('.megamenu-dropdown > .block-main > .megamenu-sub-items');\r\n \t\tif(submenu_content.length > 0){\r\n\t \t\tvar topmenu_left_offset = $(this).offset().left;\r\n\t \t\tvar submenu_left_offset = submenu_content.offset().left;\r\n\t \t\tvar submenu_content_left_padding = topmenu_left_offset - submenu_left_offset + left_submenu_margin;\r\n\t \t\tsubmenu_content.css(\"padding-left\",submenu_content_left_padding + \"px\");\r\n\t \t\tvar submenu_content_li = submenu_content.find('li').first();\r\n\t \t\tsubmenu_content.find('.tab-menu-content').css('left',(submenu_content_left_padding + submenu_content_li.width()) + \"px\");\r\n \t\t}\r\n \t});*/\r\n \t \t\r\n \t\r\n \t// Display backgound of the 3th level item over the 2nd level background display on hover\r\n \t$(\".magemenu-menu.horizontal-menu .megamenu-items > li .megamenu-sub-items li .megamenu-sub-items .megamenu-sub-item\").hover(\r\n\t\tfunction(evt){ \t\t\r\n\t\t\tvar bg_sub_item = $(this).find('.megamenu-dropdown-background');\r\n\t\t\tif(bg_sub_item.length > 0)\r\n\t\t\t{\r\n\t\t\t\tvar bg_sub_item_url = bg_sub_item.css('background-image');\t\t\t\t\r\n\t\t\t\tvar bg_sub_item_copy = \"<div id='megamenu_bg_sub_item_copy' style='background-image:\"+bg_sub_item_url+\"'></div>\";\r\n\t\t\t\t$(this).parents('.megamenu-sub-item').find('.megamenu-dropdown-background').first().append(bg_sub_item_copy);\r\n\t\t\t}\r\n\t\t\t \r\n \t},\r\n \tfunction(evt){ \t\t\r\n\t\t\t$('#megamenu_bg_sub_item_copy').remove();\r\n \t}\r\n \t);\r\n }); \r\n\t\r\n});","js/mute-migrate.js":"/**\r\n* Mute jQuery migrate log in console\r\n*/\r\nrequirejs(['jquery'], function ($) {\r\n $.migrateMute = true;\r\n $.migrateTrace = false;\r\n});","js/webcreate/infinite-ajax-scroll.3.0.1.min.js":"/**\n * Infinite Ajax Scroll v3.0.1\n * Turn your existing pagination into infinite scrolling pages with ease\n *\n * Commercial use requires one-time purchase of a commercial license\n * https://infiniteajaxscroll.com/docs/license.html\n *\n * Copyright 2014-2022 Webcreate (Jeroen Fiege)\n * https://infiniteajaxscroll.com\n */\n!function(t,e){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=e():\"function\"==typeof define&&define.amd?define(e):(t=\"undefined\"!=typeof globalThis?globalThis:t||self).InfiniteAjaxScroll=e()}(this,(function(){\"use strict\";function t(t){return\"object\"==typeof window.Node?t instanceof window.Node:null!==t&&\"object\"==typeof t&&\"number\"==typeof t.nodeType&&\"string\"
2==typeof t.nodeName}function e(e,n){if(void 0===n&&(n=document),e instanceof Array)return e.filter(t);if(t(e))return[e];if(o=Object.prototype.toString.call(i=e),\"object\"==typeof window.NodeList?i instanceof window.NodeList:null!==i&&\"object\"==typeof i&&\"number\"==typeof i.length&&/^\\[object (HTMLCollection|NodeList|Object)\\]$/.test(o)&&(0===i.length||t(i[0])))return Array.prototype.slice.call(e);var i,o;if(\"string\"==typeof e)try{var r=n.querySelectorAll(e);return Array.prototype.slice.call(r)}catch(t){return[]}return[]}var n=Object.prototype.hasOwnProperty,i=Object.prototype.toString,o=Object.defineProperty,r=Object.getOwnPropertyDescriptor,s=function(t){return\"function\"==typeof Array.isArray?Array.isArray(t):\"[object Array]\"===i.call(t)},l=function(t){if(!t||\"[object Object]\"!==i.call(t))return!1;var e,o=n.call(t,\"constructor\"),r=t.constructor&&t.constructor.prototype&&n.call(t.constructor.prototype,\"isPrototypeOf\");if(t.constructor&&!o&&!r)return!1;for(e in t);return void 0===e||n.call(t,e)},a=function(t,e){o&&\"__proto__\"===e.name?o(t,e.name,{enumerable:!0,configurable:!0,value:e.newValue,writable:!0}):t[e.name]=e.newValue},h=function(t,e){if(\"__proto__\"===e){if(!n.call(t,e))return;if(r)return r(t,e).value}return t[e]},c=function t(){var e,n,i,o,r,c,u=arguments,d=arguments[0],p=1,f=arguments.length,m=!1;for(\"boolean\"==typeof d&&(m=d,d=arguments[1]||{},p=2),(null==d||\"object\"!=typeof d&&\"function\"!=typeof d)&&(d={});f>p;++p)if(null!=(e=u[p]))for(n in e)i=h(d,n),d!==(o=h(e,n))&&(m&&o&&(l(o)||(r=s(o)))?(r?(r=!1,c=i&&s(i)?i:[]):c=i&&l(i)?i:{},a(d,{name:n,newValue:t(m,c,o)})):void 0!==o&&a(d,{name:n,newValue:o}));return d},u=\"undefined\"!=typeof globalThis?globalThis:\"undefined\"!=typeof window?window:\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:{},d=\"Expected a function\",p=/^\\s+|\\s+$/g,f=/^[-+]0x[0-9a-f]+$/i,m=/^0b[01]+$/i,y=/^0o[0-7]+$/i,g=parseInt,v=\"object\"==typeof self&&self&&self.Object===Object&&self,b=\"object\"==typeof u&&u&&u.Object===Object&&u||v||Function(\"return this\")(),w=Object.prototype.toString,x=Math.max,O=Math.min,E=function(){return b.Date.now()};function S(t,e,n){var i,o,r,s,l,a,h=0,c=!1,u=!1,p=!0;if(\"function\"!=typeof t)throw new TypeError(d);function f(e){var n=i,r=o;return i=o=void 0,h=e,s=t.apply(r,n)}function m(t){return h=t,l=setTimeout(g,e),c?f(t):s}function y(t){var n=t-a;return void 0===a||n>=e||0>n||u&&t-h>=r}function g(){var t=E();if(y(t))return v(t);l=setTimeout(g,function(t){var n=e-(t-a);return u?O(n,r-(t-h)):n}(t))}function v(t){return l=void 0,p&&i?f(t):(i=o=void 0,s)}function b(){var t=E(),n=y(t);if(i=arguments,o=this,a=t,n){if(void 0===l)return m(a);if(u)return l=setTimeout(g,e),f(a)}return void 0===l&&(l=setTimeout(g,e)),s}return e=j(e)||0,T(n)&&(c=!!n.leading,r=(u=\"maxWait\"in n)?x(j(n.maxWait)||0,e):r,p=\"trailing\"in n?!!n.trailing:p),b.cancel=function(){void 0!==l&&clearTimeout(l),h=0,i=a=o=l=void 0},b.flush=function(){return void 0===l?s:v(E())},b}function T(t){var e=typeof t;return!!t&&(\"object\"==e||\"function\"==e)}function j(t){if(\"number\"==typeof t)return t;if(function(t){return\"symbol\"==typeof t||function(t){return!!t&&\"object\"==typeof t}(t)&&\"[object Symbol]\"==w.call(t)}(t))return NaN;if(T(t)){var e=\"function\"==typeof t.valueOf?t.valueOf():t;t=T(e)?e+\"\":e}if(\"string\"!=typeof t)return 0===t?t:+t;t=t.replace(p,\"\");var n=m.test(t);return n||y.test(t)?g(t.slice(2),n?2:8):f.test(t)?NaN:+t}var L=function(t,e,n){var i=!0,o=!0;if(\"function\"!=typeof t)throw new TypeError(d);return T(n)&&(i=\"leading\"in n?!!n.leading:i,o=\"trailing\"in n?!!n.trailing:o),S(t,e,{leading:i,maxWait:e,trailing:o})},I={item:void 0,next:void 0,pagination:void 0,responseType:\"document\",bind:!0,scrollContainer:window,spinner:!1,logger:!0,loadOnScroll:!0,negativeMargin:0,trigger:!1,prefill:!0},C=function(t,n){var i=e(t);if(i.length>1)throw Error('Expected single element for \"'+n+'\"');if(0===i.length)throw Error('Element \"'+t+'\" not found for \"'+n+'\"')},_=function(t,n){if(0===e(t).length)throw Error('Element \"'+t+'\" not found for \"'+n+'\"')},H=function(t){for(var e=[],n=arguments.length-1;n-- >0;)e[n]=arguments[n+1];try{t.apply(void 0,e)}catch(t){console&&console.warn&&console.warn(t.message)}};function N(t){if(t!==window)return{x:t.scrollLeft,y:t.scrollTop};var e=void 0!==window.pageXOffset,n=\"CSS1Compat\"===(document.compatMode||\"\");return{x:e?window.pageXOffset:n?document.documentElement.scrollLeft:document.body.scrollLeft,y:e?window.pageYOffset:n?document.documentElement.scrollTop:document.body.scrollTop}}function M(t){var e;if(t!==window)e=t.getBoundingClientRect();else{var n=document.documentElement,i=document.body;e={top:0,left:0,right:n.clientWidth||i.clientWidth,width:n.clientWidth||i.clientWidth,bottom:n.clientHeight||i.clientHeight,height:n.clientHeight||i.clientHeight}}return e}var P=\"append\",F=\"appended\",R=\"binded\",D=\"unbinded\",k=\"hit\",A=\"load\",B=\"loaded\",W=\"error\",z=\"last\",X=\"next\",q=\"nexted\",$=\"ready\",V=\"scrolled\",Y=\"resized\",G=\"page\",U=\"prefill\",J=\"prefilled\",K={y:0,x:0,deltaY:0,deltaX:0};function Q(t,e){var n=N(t);return n.deltaY=n.y-(e?e.y:n.y),n.deltaX=n.x-(e?e.x:n.x),n}
vendor: 2,884 bytes, line 2
2function Z(){var t=this,e=t._lastScroll=Q(t.scrollContainer,t._lastScroll||K);this.emitter.emit(V,{scroll:e})}function tt(){var t=this,e=t._lastScroll=Q(t.scrollContainer,t._lastScroll||K);this.emitter.emit(Y,{scroll:e})}function et(){}et.prototype={on:function(t,e,n){var i=this.e||(this.e={});return(i[t]||(i[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var i=this;function o(){i.off(t,o),e.apply(n,arguments)}return o._=e,this.on(t,o,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),i=0,o=n.length;o>i;i++)n[i].fn.apply(n[i].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),i=n[t],o=[];if(i&&e)for(var r=0,s=i.length;s>r;r++)i[r].fn!==e&&i[r].fn._!==e&&o.push(i[r]);return o.length?n[t]=o:delete n[t],this}};var nt=et;function it(t){var n=this,i=n._lastResponse||document,o=e(n.options.next,i)[0];if(o)return n.load(o.href).then((function(o){i=n._lastResponse=o.xhr.response;var r=e(n.options.next,i)[0];return n.append(o.items).then((function(){return!!r})).then((function(e){return!e&&1>=t&&console&&console.warn&&console.warn('Element \"'+n.options.next+'\" not found for \"options.next\" on \"'+o.url+'\"'),e}))}));H(C,n.options.next,\"options.next\")}nt.TinyEmitter=et;var ot={element:void 0,hide:!1};var rt=function(t,e){this.options=c({},ot,function(t){return\"string\"==typeof t||\"object\"==typeof t&&t.nodeType===Node.ELEMENT_NODE?t={element:t,hide:!0}:\"boolean\"==typeof t&&(t={element:void 0,hide:t}),t}(e)),this.originalDisplayStyles=new WeakMap,this.options.hide&&(H(_,this.options.element,\"pagination.element\"),t.on(R,this.hide.bind(this)),t.on(D,this.restore.bind(this)))};rt.prototype.hide=function(){var t=this;e(this.options.element).forEach((function(e){t.originalDisplayStyles.set(e,window.getComputedStyle(e).display),e.style.display=\"none\"}))},rt.prototype.restore=function(){var t=this;e(this.options.element).forEach((function(e){e.style.display=t.originalDisplayStyles.get(e)||\"block\"}))};var st={element:void 0,delay:600,show:function(t){t.style.opacity=\"1\"},hide:function(t){t.style.opacity=\"0\"}};var lt=function(t,n){!1!==n&&(this.ias=t,this.options=c({},st,function(t){return(\"string\"==typeof t||\"object\"==typeof t&&t.nodeType===Node.ELEMENT_NODE)&&(t={element:t}),t}(n)),void 0!==this.options.element&&C(this.options.element,\"spinner.element\"),this.element=e(this.options.element)[0],this.hideFn=this.options.hide,this.showFn=this.options.show,t.on(R,this.bind.bind(this)),t.on(R,this.hide.bind(this)))};lt.prototype.bind=function(){var t,e,n=this,i=this.ias;i.on(X,(function(){t=+new Date,n.show()})),i.on(z,(function(){n.hide()})),i.on(P,(function(i){e=Math.max(0,n.options.delay-(+new Date-t));var o=i.appendFn.bind({});i.appendFn=function(t,i,r){return new Promise((function(s){setTimeout((function(){n.hide().then((function(){o(t,i,r),s()}))}),e)}))}}))}
2,lt.prototype.show=function(){return Promise.resolve(this.showFn(this.element))},lt.prototype.hide=function(){return Promise.resolve(this.hideFn(this.element))};var at={hit:function(){console.log(\"Hit scroll threshold\")},binded:function(){console.log(\"Binded event handlers\")},unbinded:function(){console.log(\"Unbinded event handlers\")},next:function(t){console.log(\"Next page triggered [pageIndex=\"+t.pageIndex+\"]\")},nexted:function(t){console.log(\"Next page completed [pageIndex=\"+t.pageIndex+\"]\")},load:function(t){console.log(\"Start loading \"+t.url)},loaded:function(){console.log(\"Finished loading\")},append:function(){console.log(\"Start appending items\")},appended:function(t){console.log(\"Finished appending \"+t.items.length+\" item(s)\")},last:function(){console.log(\"No more pages left to load\")},page:function(t){console.log(\"Page changed [pageIndex=\"+t.pageIndex+\"]\")},prefill:function(t){console.log(\"Start prefilling\")},prefilled:function(t){console.log(\"Finished prefilling\")}};var ht=function(t,e){if(!1!==e){var n=function(t){return!0===t&&(t=at),t}(e);Object.keys(n).forEach((function(e){t.on(e,n[e])}))}};var ct=function(t){this.ias=t,this.pageBreaks=[],this.currentPageIndex=t.pageIndex,this.currentScrollTop=0,t.on(R,this.binded.bind(this)),t.on(X,this.next.bind(this)),t.on(V,this.scrolled.bind(this)),t.on(Y,this.scrolled.bind(this))};ct.prototype.binded=function(){this.ias.sentinel()&&this.pageBreaks.push({pageIndex:this.currentPageIndex,url:\"\"+document.location,title:document.title,sentinel:this.ias.sentinel()})},ct.prototype.next=function(){var t=this,e=\"\"+document.location,n=document.title,i=function(t){e=t.url,t.xhr.response&&(n=t.xhr.response.title)};this.ias.once(B,i),this.ias.once(q,(function(o){t.pageBreaks.push({pageIndex:o.pageIndex,url:e,title:n,sentinel:t.ias.sentinel()}),t.update(),t.ias.off(B,i)}))},ct.prototype.scrolled=function(t){this.update(t.scroll.y)},ct.prototype.update=function(t){this.currentScrollTop=t||this.currentScrollTop;var e=function(t,e,n){for(var i=e+M(n).height,o=t.length-1;o>=0;o--)if(i>t[o].sentinel.getBoundingClientRect().bottom+e)return t[Math.min(o+1,t.length-1)];return t[0]}(this.pageBreaks,this.currentScrollTop,this.ias.scrollContainer);e&&e.pageIndex!==this.currentPageIndex&&(this.ias.emitter.emit(G,e),this.currentPageIndex=e.pageIndex)};var ut={element:void 0,when:function(t){return!0},show:function(t){t.style.opacity=\"1\"},hide:function(t){t.style.opacity=\"0\"}};var dt=function(t,n){var i=this;!1!==n&&(this.ias=t,this.options=c({},ut,function(t){if((\"string\"==typeof t||\"function\"==typeof t||\"object\"==typeof t&&t.nodeType===Node.ELEMENT_NODE)&&(t={element:t}),\"function\"==typeof t.element&&(t.element=t.element()),t.when&&Array.isArray(t.when)){var e=t.when;t.when=function(t){return-1!==e.indexOf(t)}}return t}(n)),void 0!==this.options.element&&C(this.options.element,\"trigger.element\"),this.element=e(this.options.element)[0],this.hideFn=this.options.hide,this.showFn=this.options.show,this.voter=this.options.when,this.showing=void 0,this.enabled=void 0,t.on(R,this.bind.bind(this)),t.on(D,this.unbind.bind(this)),t.on(k,this.hit.bind(this)),t.on(X,(function(t){return i.ias.once(F,(function(){return i.update(t.pageIndex)}))})))};function pt(t,e,n){var i=n?n.nextSibling:null,o=document.createDocumentFragment();t.forEach((function(t){o.appendChild(t)})),e.insertBefore(o,i)}dt.prototype.bind=function(){this.hide(),this.update(this.ias.pageIndex),this.element.addEventListener(\"click\",this.clickHandler.bind(this))},dt.prototype.unbind=function(){this.element.removeEventListener(\"click\",this.clickHandler.bind(this))},dt.prototype.clickHandler=function(){this.hide().then(this.ias.next.bind(this.ias))},dt.prototype.update=function(t){this.enabled=this.voter(t),this.enabled?this.ias.disableLoadOnScroll():this.ias.enableLoadOnScroll()},dt.prototype.hit=function(){this.enabled&&this.show()},dt.prototype.show=function(){if(!this.showing)return this.showing=!0,Promise.resolve(this.show
2Fn(this.element))},dt.prototype.hide=function(){if(this.showing||void 0===this.showing)return this.showing=!1,Promise.resolve(this.hideFn(this.element))};var ft=window.ResizeObserver,mt=function(t,e){this.el=t,this.listener=e};mt.prototype.observe=function(){this.el.addEventListener(\"resize\",this.listener)},mt.prototype.unobserve=function(){this.el.removeEventListener(\"resize\",this.listener)};var yt=function(t,e){this.el=t,this.listener=e,this.ro=new ft(this.listener)};yt.prototype.observe=function(){this.ro.observe(this.el)},yt.prototype.unobserve=function(){this.ro.unobserve()};var gt=function(t,e){this.el=t,this.listener=e,this.interval=null,this.lastHeight=null};gt.prototype.pollHeight=function(){var t=Math.trunc(M(this.el).height);null!==this.lastHeight&&this.lastHeight!==t&&this.listener(),this.lastHeight=t},gt.prototype.observe=function(){this.interval=setInterval(this.pollHeight.bind(this),200)},gt.prototype.unobserve=function(){clearInterval(this.interval)};var vt=function(t,e){this.ias=t,this.enabled=e};vt.prototype.prefill=function(){var t=this;if(this.enabled&&0>=this.ias.distance())return this.ias.emitter.emit(U),this._prefill().then((function(){t.ias.emitter.emit(J),t.ias.measure()}))},vt.prototype._prefill=function(){var t=this;return this.ias.next().then((function(e){if(e)return 0>t.ias.distance()?t._prefill():void 0}))};var bt=function(t,n){var i,o,r,s=this;void 0===n&&(n={}),C(t,\"container\"),this.container=e(t)[0],this.options=c({},I,n),this.emitter=new nt,this.options.loadOnScroll?this.enableLoadOnScroll():this.disableLoadOnScroll(),this.negativeMargin=Math.abs(this.options.negativeMargin),this.scrollContainer=this.options.scrollContainer,this.options.scrollContainer!==window&&(C(this.options.scrollContainer,\"options.scrollContainer\"),this.scrollContainer=e(this.options.scrollContainer)[0]),this.nextHandler=it,!1===this.options.next?this.nextHandler=function(){}:\"function\"==typeof this.options.next&&(this.nextHandler=this.options.next),this.resizeObserver=(i=this,o=this.scrollContainer,r=L(tt,200).bind(i),o===window?new mt(o,r):ft?new yt(o,r):(console&&console.warn&&console.warn(\"ResizeObserver not supported. Falling back on polling.\"),new gt(o,r))),this._scrollListener=L(Z,200).bind(this),this.ready=!1,this.bindOnReady=!0,this.binded=!1,this.paused=!1,this.pageIndex=this.sentinel()?0:-1,this.on(k,(function(){s.loadOnScroll&&s.next()})),this.on(V,this.measure),this.on(Y,this.measure),this.pagination=new rt(this,this.options.pagination),this.spinner=new lt(this,this.options.spinner),this.logger=new ht(this,this.options.logger),this.paging=new ct(this),this.trigger=new dt(this,this.options.trigger),this.prefill=new vt(this,this.options.prefill),this.on(R,this.prefill.prefill.bind(this.prefill));var l=function(){s.ready||(s.ready=!0,s.emitter.emit($),s.bindOnReady&&s.options.bind&&s.bind())};\"complete\"===document.readyState||\"interactive\"===document.readyState?setTimeout(l,1):window.addEventListener(\"DOMContentLoaded\",l)};return bt.prototype.bind=function(){this.binded||(this.ready||(this.bindOnReady=!1),this.scrollContainer.addEventListener(\"scroll\",this._scrollListener),this.resizeObserver.observe(),this.binded=!0,this.emitter.emit(R))},bt.prototype.unbind=function(){this.binded?(this.resizeObserver.unobserve(),this.scrollContainer.removeEventListener(\"scroll\",this._scrollListener),this.binded=!1,this.emitter.emit(D)):this.ready||this.once(R,this.unbind)},bt.prototype.next=function(){var t=this;if(!this.binded)return this.ready?void 0:this.once(R,this.next);this.pause();var e=this.pageIndex+1;return this.emitter.emit(X,{pageIndex:this.pageIndex+1}),Promise.resolve(this.nextHandler(e)).then((function(n){if(t.pageIndex=e,n)return t.resume(),n;t.emitter.emit(z)})).then((function(e){return t.emitter.emit(q,{pageIndex:t.pageIndex}),e}))},bt.prototype.load=function(t){var n=this;return new Promise((function(i,o){var r=new XMLHttpRequest,s={url:t,xhr:r,method:\"GET\",body:null,nocache:!1,responseType:n.options.responseType,headers:{\"X-Requested-With\":\"XMLHttpRequest\"}};n.emitter.emit(A,s);var l=s.url,a=s.method,h=s.responseType,c=s.headers,u=s.body;for(var d in s.nocache||(l=l+(/\\?/.test(l)?\"&\":\"?\")+(new Date).getTime()),r.onreadystatechange=function(){if(r.readyState===4)if(0===r.
2status);else if(200===r.status){var t=r.response;\"document\"===h&&(t=e(n.options.item,r.response)),n.emitter.emit(B,{items:t,url:l,xhr:r}),i({items:t,url:l,xhr:r})}else n.emitter.emit(W,{url:l,method:a,xhr:r}),o(r)},r.onerror=function(){n.emitter.emit(W,{url:l,method:a,xhr:r}),o(r)},r.open(a,l,!0),r.responseType=h,c)r.setRequestHeader(d,c[d]);r.send(u)}))},bt.prototype.append=function(t,e){var n=this,i={items:t,parent:e=e||n.container,appendFn:pt};n.emitter.emit(P,i);return new Promise((function(o){window.requestAnimationFrame((function(){Promise.resolve(i.appendFn(i.items,i.parent,n.sentinel())).then((function(){o({items:t,parent:e})}))}))})).then((function(t){n.emitter.emit(F,t)}))},bt.prototype.sentinel=function(){var t=e(this.options.item,this.container);return t.length?t[t.length-1]:null},bt.prototype.pause=function(){this.paused=!0},bt.prototype.resume=function(){this.paused=!1},bt.prototype.enableLoadOnScroll=function(){this.loadOnScroll=!0},bt.prototype.disableLoadOnScroll=function(){this.loadOnScroll=!1},bt.prototype.distance=function(t,e){var n=t||M(this.scrollContainer),i=function(t,e,n){var i=n;if(!t)return-1*i.height;var o=e.y,r=t.getBoundingClientRect();return Math.trunc(o+r.bottom-i.top-(o+i.height))}(e||this.sentinel(),N(this.scrollContainer),n);return i-=this.negativeMargin,i},bt.prototype.measure=function(){if(!this.paused){var t=M(this.scrollContainer);if(0!==t.height){var e=this.sentinel(),n=this.distance(t,e);n>0||this.emitter.emit(k,{distance:n})}}},bt.prototype.on=function(t,e){this.emitter.on(t,e,this),t===R&&this.binded&&e.bind(this)()},bt.prototype.off=function(t,e){this.emitter.off(t,e,this)},bt.prototype.once=function(t,e){var n=this;return new Promise((function(i){n.emitter.once(t,(function(){Promise.resolve(e.apply(this,arguments)).then(i)}),n),t===R&&n.binded&&(e.bind(n)(),i())}))},bt}));\n","Magento_Csp/js/sri.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\nrequire.config({\n onNodeCreated: function (node, config, moduleName, url) {\n 'use strict';\n if ('sriHashes' in window && url in window.sriHashes) {\n node.setAttribute('integrity', window.sriHashes[url]);\n node.setAttribute('crossorigin', 'anonymous');\n }\n }\n});\n","Magento_Csp/js/nonce-injector.js":"/**\n * Copyright 2024 Adobe\n * All Rights Reserved.\n */\n\ndefine('Magento_Csp/js/nonce-injector', [], function () {\n 'use strict';\n\n return function (config) {\n window.cspNonce = config.nonce;\n };\n});\n","Goyard_Xsearch/js/wrapper.js":"define([\n 'jquery',\n 'ko',\n 'amsearch_helpers',\n 'Amasty_Xsearch/js/wrapper'\n], function ($, ko, helpers, wrapperComponent) {\n 'use strict';\n\n return wrapperComponent.extend({\n /**\n * init Input functionality\n *\n * @private\n * @returns {void}\n */\n _initInput: function () {\n this.readyForSearch = ko.computed(function () {\n return this.inputValue().length >= this.data.minChars;\n }.bind(this));\n\n this.inputValue\n .extend({\n rateLimit: {\n method: 'notifyWhenChangesStop',\n timeout: this.data.delay\n }\n })\n .subscribe(function (value) {\n var isSearch = value.length >= this.data.minChars,\n strippedValue = helpers.stripTags(value);\n\n if (isSearch && strippedValue) {\n this.inputValue.silentUpdate(strippedValue);\n\n return false;\n }\n\n this.message(false);\n\n if (isSearch) {\n this.searchProcess(value);\n } else {\n this.searchItems.removeAll();\n this.searchProducts(false);\n this.match(false);\n $('.searchbar-results .searchbar-news').css('visibility', 'visible');\n $('.searchbar-suggestions').removeAttr('inert');\n $('.searchbar-category-item:not(.searchbar-category-item-default)').remove();\n $('.searchbar-category-item-default').show();\n }\n }.bind(this));\n },\n /**\n * Parsing data from search request\n *\n * @private\n * @param {Object} data\n * @return {void}
2\n */\n _parseSearchData: function (data) {\n\n var searchItems = [];\n\n Object.keys(data).forEach(function (key) {\n if (data[key].type === 'product') {\n if (!$.parseHTML(data[key].html.trim()).length) {\n this.searchProducts(false);\n this.message(this.messages.emptyProductSearch.replace('%search_query%', this.inputValue()));\n $('.searchbar-results .searchbar-news').css('visibility', 'visible');\n $('.searchbar-suggestions').removeAttr('inert');\n } else {\n this.searchProducts(data[key].html);\n if ($(data[key].html).find('.product-item').length) {\n $('.searchbar-suggestions').attr('inert', '');\n } else {\n $('.searchbar-suggestions').removeAttr('inert');\n }\n $('.searchbar-results .searchbar-news').css('visibility', 'hidden');\n }\n\n return;\n }\n\n if (data[key].type === 'category') {\n $('.searchbar-category-item:not(.searchbar-category-item-default)').remove();\n $('.searchbar-category-item-default').hide();\n\n /*if (data[key].html.trim().length) {\n $('.searchbar-category-items').append(data[key].html)\n\n // Then remove duplicate line\n $('.searchbar-category-items .searchbar-category-item:visible').each(function(){\n let cat_id = $(this).data('categoryId');\n if($('.searchbar-category-items .searchbar-category-item[data-category-id=\"'+cat_id+'\"]:visible').length > 1)\n {\n $('.searchbar-category-items .searchbar-category-item[data-category-id=\"'+cat_id+'\"]:visible').not('.force-visible').remove();\n }\n });\n }*/\n }\n\n if (data[key].html === undefined || data[key].html.length <= 1) {\n return;\n }\n\n searchItems.push(data[key]);\n }.bind(this));\n\n this.searchItems(searchItems);\n }\n })\n})","Goyard_Xsearch/js/products-categories.js":"define([\n\t'jquery',\n\t'matchMedia',\n\t'domReady!'\n], function ($) {\n\treturn function (config) {\n\t\tvar categoryIds = config.categoryIds;\n\t\tvar query = config.query;\n\n\t\t// Filter category list with array of ids\n\t\tfunction entry() {\n\n\t\t\tlet categoryIdsArray = categoryIds.split(',');\n\n\t\t\t$('.searchbar-category-items .searchbar-category-item').each(function () {\n\t\t\t\tif (categoryIdsArray.length > 0) {\n\t\t\t\t\tif (categoryIdsArray.includes(\"\" + $(this).data('categoryId'))) {\n\t\t\t\t\t\tif (!$(this).is(\":visible\")) {\n\t\t\t\t\t\t\t$(this).addClass('force-visible').fadeIn();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ($(this).is(\":visible\")) {\n\t\t\t\t\t\t\t$(this).removeClass('force-visible').fadeOut();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (!$(this).is(\":visible\")) {\n\t\t\t\t\t\t$(this).removeClass('force-visible').fadeIn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tentry();\n\t}\n});\n","Magento_Variable/js/grid/columns/radioselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'mage/translate',\n 'Magento_Ui/js/grid/columns/column',\n 'jquery'\n], function (_, $t, Column, jQuery) {\n 'use strict';\n\n return Column.extend({\n defaults: {\n bodyTmpl: 'Magento_Variable/grid/cells/radioselect',\n draggable: false,\n sortable: false,\n selectedVariableCode: null,\n selectedVariableType: null\n },\n\n /**\n * Calls 'initObservable' of parent\n *\n * @returns {Object}
2 Chainable.\n */\n initObservable: function () {\n this._super().observe(['selectedVariableCode']);\n\n return this;\n },\n\n /**\n * Remove disable class from Insert Variable button after Variable has been chosen.\n *\n * @return {Boolean}\n */\n selectVariable: function () {\n if (jQuery('#insert_variable').hasClass('disabled')) {\n jQuery('#insert_variable').removeClass('disabled');\n }\n\n return true;\n }\n });\n});\n","Magento_PageCache/js/form-key-provider.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(function () {\n 'use strict';\n\n return function (settings) {\n var formKey,\n inputElements,\n inputSelector = 'input[name=\"form_key\"]';\n\n /**\n * Set form_key cookie\n * @private\n */\n function setFormKeyCookie(value) {\n var expires,\n secure,\n date = new Date(),\n cookiesConfig = window.cookiesConfig || {},\n isSecure = !!cookiesConfig.secure,\n samesite = cookiesConfig.samesite || 'lax';\n\n date.setTime(date.getTime() + 86400000);\n expires = '; expires=' + date.toUTCString();\n secure = isSecure ? '; secure' : '';\n samesite = '; samesite=' + samesite;\n\n document.cookie = 'form_key=' + (value || '') + expires + secure + '; path=/' + samesite;\n }\n\n /**\n * Retrieves form key from cookie\n * @private\n */\n function getFormKeyCookie() {\n var cookie,\n i,\n nameEQ = 'form_key=',\n cookieArr = document.cookie.split(';');\n\n for (i = 0; i < cookieArr.length; i++) {\n cookie = cookieArr[i];\n\n while (cookie.charAt(0) === ' ') {\n cookie = cookie.substring(1, cookie.length);\n }\n\n if (cookie.indexOf(nameEQ) === 0) {\n return cookie.substring(nameEQ.length, cookie.length);\n }\n }\n\n return null;\n }\n\n /**\n * Get form key from UI input hidden\n * @private\n */\n function getFormKeyFromUI() {\n return document.querySelector(inputSelector).value;\n }\n\n /**\n * Generate form key string\n * @private\n */\n function generateFormKeyString() {\n var result = '',\n length = 16,\n chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\n while (length--) {\n result += chars[Math.round(Math.random() * (chars.length - 1))];\n }\n\n return result;\n }\n\n /**\n * Init form_key inputs with value\n * @private\n */\n function initFormKey() {\n formKey = getFormKeyCookie();\n\n if (settings && settings.isPaginationCacheEnabled && !formKey) {\n formKey = getFormKeyFromUI();\n setFormKeyCookie(formKey);\n }\n\n if (!formKey) {\n formKey = generateFormKeyString();\n setFormKeyCookie(formKey);\n }\n inputElements = document.querySelectorAll(inputSelector);\n\n if (inputElements.length) {\n Array.prototype.forEach.call(inputElements, function (element) {\n element.setAttribute('value', formKey);\n });\n }\n }\n\n initFormKey();\n };\n});\n","Magento_PageCache/js/page-cache.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'domReady',\n 'consoleLogger',\n 'Magento_PageCache/js/form-key-provider',\n 'jquery-ui-modules/widget',\n 'mage/cookies'\n], function ($, domReady, consoleLogger, formKeyInit) {\n 'use strict';\n\n /**\n * Helper. Generate random string\n * TODO: Merge with mage/utils\n * @param {String} chars - list of symbols\n * @param {Number} length - length for need string\n * @returns {String}\n */\n function generateRandomString(chars, length) {\n var result = '';\n\n length = length > 0 ? length : 1;\n\n while (length--) {\n result += chars[Math.round(Math.random() * (chars.length - 1))];\n }\n\n return result;\n }\n\n /**\n * Nodes tree to flat list converter\n * @returns {Array}\n */\n $.fn.comments = function () {\n var elements = [],\n contents,\n elementContents;\n\n /**\n * @param {jQuery} element - Comment holder\n */\n (function lookup(element) {\n var iframeHostName;\n\n // prevent cross origin iframe content reading\n if ($(element).prop('tagName') === 'IFRAME') {\n iframeHostName = $('<a>').prop('href', $(element).prop('src'))\n .prop('hostname');\n\n if (window.location.hostname !== iframeHostName) {\n return [];\n }\n }\n\n /**\n * Rewrite jQuery contents().\n *\n * @param {jQuery} elem\n */\n contents = function (elem) {\n return $.map(elem, function (el) {\n try {\n return el.nodeName.toLowerCase() === 'iframe' ?\
2n el.contentDocument || (el.contentWindow ? el.contentWindow.document : []) :\n $.merge([], el.childNodes);\n } catch (e) {\n consoleLogger.error(e);\n\n return [];\n }\n });\n };\n\n elementContents = contents($(element));\n\n $.each(elementContents, function (index, el) {\n switch (el.nodeType) {\n case 1: // ELEMENT_NODE\n lookup(el);\n break;\n\n case 8: // COMMENT_NODE\n elements.push(el);\n break;\n\n case 9: // DOCUMENT_NODE\n lookup($(el).find('body'));\n break;\n }\n });\n })(this);\n\n return elements;\n };\n\n /**\n * FormKey Widget - this widget is generating from key, saves it to cookie and\n * @deprecated see Magento/PageCache/view/frontend/web/js/form-key-provider.js\n */\n $.widget('mage.formKey', {\n options: {\n inputSelector: 'input[name=\"form_key\"]',\n allowedCharacters: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',\n length: 16\n },\n\n /**\n * Creates widget 'mage.formKey'\n * @private\n */\n _create: function () {\n var formKey = $.mage.cookies.get('form_key'),\n options = {\n secure: window.cookiesConfig ? window.cookiesConfig.secure : false\n };\n\n if (!formKey) {\n formKey = generateRandomString(this.options.allowedCharacters, this.options.length);\n $.mage.cookies.set('form_key', formKey, options);\n }\n $(this.options.inputSelector).val(formKey);\n }\n });\n\n /**\n * PageCache Widget\n * Handles additional ajax request for rendering user private content.\n */\n $.widget('mage.pageCache', {\n options: {\n url: '/',\n patternPlaceholderOpen: /^ BLOCK (.+) $/,\n patternPlaceholderClose: /^ \\/BLOCK (.+) $/,\n versionCookieName: 'private_content_version',\n handles: []\n },\n\n /**\n * Creates widget 'mage.pageCache'\n * @private\n */\n _create: function () {\n var placeholders,\n version = $.mage.cookies.get(this.options.versionCookieName);\n\n if (!version) {\n return;\n }\n placeholders = this._searchPlaceholders(this.element.comments());\n\n if (placeholders && placeholders.length) {\n this._ajax(placeholders, version);\n }\n },\n\n /**\n * Parse page for placeholders.\n * @param {Array} elements\n * @returns {Array}\n * @private\n */\n _searchPlaceholders: function (elements) {\n var placeholders = [],\n tmp = {},\n ii,\n len,\n el, matches, name;\n\n if (!(elements && elements.length)) {\n return placeholders;\n }\n\n for (ii = 0, len = elements.length; ii < len; ii++) {\n el = elements[ii];\n matches = this.options.patternPlaceholderOpen.exec(el.nodeValue);\n name = null;\n\n if (matches) {\n name = matches[1];\n tmp[name] = {\n name: name,\n openElement: el\n };\n } else {\n matches = this.options.patternPlaceholderClose.exec(el.nodeValue);\n\n if (matches) { //eslint-disable-line max-depth\n name = matches[1];\n\n if (tmp[name]) { //eslint-disable-line max-depth\n tmp[name].closeElement = el;\n placeholders.push(tmp[name]);\n delete tmp[name];\n }\n }\n }\n }\n\n return placeholders;\n },\n\n /**\n * Parse for page and replace placeholders\n * @param {Object} placeholder\n * @param {Object} html\n * @protected\n */\n _replacePlaceholder: function (placeholder, html) {\n var startReplacing = false,\n prevSibling = null,\n parent, contents, yy, len, element;\n\n if (!placeholder || !html) {\n return;\n }\n\n parent = $(placeholder.openElement).parent();\n contents = parent.contents();\n\n for (yy = 0, len = contents.length; yy < len; yy++) {\n element = contents[yy];\n\n if (element == placeholder.openElement) { //eslint-disable-line eqeqeq\n startReplacing = true;\n }\n\n if (startReplacing) {\n $(element).remove();\n } else if (element.nodeType != 8) { //eslint-disable-line eqeqeq\n //due to comment tag doesn't have siblings we try to find it manually\n prevSibling = element;\n }\n\n if (element == placeholder.closeElement) { //eslint-disable-line eqeqeq\n break;\n }\n }\n\n if (prevSibling) {\n $(prevSibling).after(html);\n } else {\n $(parent).prepend(html);\n }\n\n // trigger event to use mage-data-init attribute\n $(parent).trigger('contentUpdated');\n },\n\n /**\n * AJAX helper\n * @param {Object} placeholders\n * @param {String} version\n * @private\n */\n _ajax: function (placeholders, version) {\n var ii,\n data = {\n blocks: [],\n handles: this.options.handles,\n originalRequest: this.options.originalRequest,\n version: version\n };\n\n for (ii = 0; ii < placeholders.length; ii++) {\n data.blocks.push(placeholders[ii].name);\n }\n data.blocks = JSON.stringify(data.blocks.sort());\n data.handles = JSON.stringify(data.handles);\n data.originalRequest = JSON.stringify(data.originalRequest);\n $.ajax({\n url: this.options.url,\n data: data,\n type: 'GET',\n cache: true,\n dataType: 'json',\n context: this,\n\n /**\n * Response handler\n * @param {Object} response\n */\n success: function (response) {\n var placeholder, i;\n\n for (i = 0; i < placeholders.length;
2 i++) {\n placeholder = placeholders[i];\n\n if (response.hasOwnProperty(placeholder.name)) {\n this._replacePlaceholder(placeholder, response[placeholder.name]);\n }\n }\n }\n });\n }\n });\n\n domReady(function () {\n formKeyInit();\n });\n\n return {\n 'pageCache': $.mage.pageCache,\n 'formKey': $.mage.formKey\n };\n});\n","Goyard_Cms/js/pre-header.js":"/**\n * Copyright Goyard TE\n * @author Technology-everywhere\n * @author Sebastien GILBERT <[email protected]>\n * @copyright Technology-Everywhere\n */\n\n// search : $('body').hasClass('pre-header-active') in the code to know where we use it\ndefine([\n \"jquery\",\n 'mage/template',\n 'jquery-ui-modules/widget',\n 'mage/translate'\n], function ($) {\n (\"use strict\");\n\n $.widget(\"mage.preheader\", {\n options: {\n },\n _create: function () {\n var self = this;\n // Initialize html element\n $(document).ready(function () {\n let preheader_closed = self.getPreheaderClosed();\n if (preheader_closed) {\n if (preheader_closed.closed) {\n $('.preheader-wrapper').remove();\n return;\n }\n }\n\n if ($('.preheader-wrapper').length > 0 && $(document).scrollTop() === 0) {\n // Init preheader display :\n $('.preheader-wrapper').addClass('initialized').css({\n 'position': 'fixed'\n });\n self.adjustToPreheader();\n }\n self.createAndPlaceCross(self);\n\n // Add data attribute to preheader for automatisation\n $('.preheader-wrapper .pre-header').attr('data-testid', 'preheader-div');\n\n $('.action.nav-toggle').on('click keydown', function (e) {\n if (e.type === 'click' || e.type === 'keydown' && ((e.which === 13 || e.keyCode === 13) || (e.which === 32 || e.keyCode === 32))) {\n e.preventDefault();\n if ($(window).width() < 768) {\n if ($(\"html\").hasClass(\"nav-before-open nav-open\")) {\n self.unShowPreHeader();\n } else {\n if (!$('.preheader-wrapper').hasClass('initialized')) {\n $('.preheader-wrapper').addClass('initialized');\n $('.preheader-wrapper').css('display', 'block');\n };\n self.adjustToPreheader();\n }\n }\n }\n });\n $('.toggle-search').on('click', function () {\n if ($(window).width() < 768) {\n if ($(\"body\").hasClass(\"search-form-opened\")) {\n self.unShowPreHeader();\n } else if ($(window).scrollTop() > 0) {\n self.unShowPreHeader();\n } else {\n if (!$('.preheader-wrapper').hasClass('initialized')) {\n $('.preheader-wrapper').addClass('initialized');\n $('.preheader-wrapper').css('display', 'block');\n };\n self.adjustToPreheader();\n }\n }\n });\n\n $(document).on(\"show-wishlist-popup\", function (event) {\n self.adjustToPreheader();\n });\n });\n\n //PUBLIC function for external use\n this._on(this.element, {\n 'adjustToPreheader': this.adjustToPreheader,\n 'unShowPreHeader': this.unShowPreHeader\n });\n },\n\n createAndPlaceCross: function (self) {\n // Cross to disable pre header + data attribute for automatisation\n const html = '<div id=\"no-pre-header\" aria-role=\"button\" aria-label=\"' + $.mage.__('Close pre-header') + '\" tabindex=\"0\" data-testid=\"preheader-close-div\">X</div>';\n const textElement = $('.preheader-wrapper').find('div[data-content-type=\"text\"]');\n // recovers the same color as the text for the cross\n const color = textElement.find('span').css('color');\n $(html).appendTo($('.preheader-wrapper'));\n\n // CSS for cross\n $('#no-pre-header').css({\n \"position\": \"absolute\",\n \"color\": color,\n \"right\": \"5px\",\n \"font-family\": \"'Goyard', sans-serif\",\n \"padding\": \"2px 5px\",\n \"top\": \"50%\",\n \"cursor\": \"pointer\",\n \"transform\": \"translateY(-50%)\"\n });
2\n\n function handleNoPreHeaderClick() {\n self.adjustToPreheader();\n self.unShowPreHeader();\n $('.preheader-wrapper').remove();\n self.savePreheaderClosed();\n }\n $('#no-pre-header').on('click', handleNoPreHeaderClick);\n\n $(\"#no-pre-header\").on('keydown', function (event) {\n if (event.key === 'Enter' || event.code === 'Enter' || event.which === 13) {\n handleNoPreHeaderClick();\n }\n });\n },\n\n // register in local storage\n savePreheaderClosed: function (name, value) {\n const now = new Date();\n const item = {\n value: value,\n closed: true,\n expiry: now.getTime() + (24 * 60 * 60 * 1000)\n };\n localStorage.setItem('goyard_preheader_closed', JSON.stringify(item));\n },\n\n // get info from local storage\n getPreheaderClosed: function (name) {\n const preHeadClosedItem = localStorage.getItem('goyard_preheader_closed');\n\n if (!preHeadClosedItem) {\n return null;\n }\n\n const itemParsed = JSON.parse(preHeadClosedItem);\n const now = new Date();\n if (now.getTime() > itemParsed.expiry) {\n localStorage.removeItem('goyard_preheader_closed');\n return null;\n }\n return itemParsed;\n },\n\n adjustToPreheader: function () {\n let preheader_closed = this.getPreheaderClosed();\n if (!preheader_closed || (preheader_closed && !preheader_closed.closed)) {\n let preheaderHeight = $('.preheader-wrapper').length ? $('.preheader-wrapper').height() : 0;\n let pageHeaderHeight = $('.page-header').height();\n let navBarHeight = $('.nav-sections').height();\n\n $('.page-header').css({\n 'top': preheaderHeight.toString() + 'px',\n 'transition': '0s'\n });\n $('.nav-sections').css({\n 'top': (preheaderHeight + pageHeaderHeight).toString() + 'px',\n 'transform': $('.nav-sections').hasClass('opaque-nav-sections') ? 'none' : 'none',\n });\n $('.megamenu-dropdown').css('top', (preheaderHeight + pageHeaderHeight + navBarHeight).toString() + 'px');\n $('.searchBar-root_open-hxZ').css('top', (preheaderHeight + pageHeaderHeight).toString() + 'px');\n $('.page-wrapper.page-main.column.main').css('padding-top', (preheaderHeight + pageHeaderHeight + navBarHeight).toString() + 'px');\n $('body.cms-index-index #maincontent .page.messages .messages .message').attr(\"margin-top\", (preheaderHeight) + \"px !important\");\n $('#wishlist-popup').css(\"padding-top\", (preheaderHeight).toString() + 'px');\n\n if (!$('body').hasClass('cms-index-index') && !$('body').hasClass('page-layout-1column-transparent-header')) {\n var dynamicPaddingPre = 0;\n dynamicPaddingPre = preheaderHeight;\n\n if ($('body[class^=\"customer-\"]').length > 0 || $('body[class^=\"accountmanager-\"]').length > 0 || $('body').hasClass('account')) {\n $('.breadcrumbs').addClass(\"padding-preheader-calculate\");\n } else {\n if ($(window).width() < 768) {\n dynamicPaddingPre = preheaderHeight + pageHeaderHeight;\n $('#maincontent').addClass(\"padding-preheader-calculate\");\n } else {\n dynamicPaddingPre = preheaderHeight + pageHeaderHeight + navBarHeight;\n $('#maincontent').addClass(\"padding-preheader-calculate\");\n }\n }\n\n document.documentElement.style.setProperty('--dynamic-padding-top', dynamicPaddingPre + \"px\");\n }\n\n $('.block-right').each(function (index, element) {\n $(element).css('top', (preheaderHeight + 140).toString() + 'px');\n })\n }\n },\n\n unShowPreHeader: function () {\n $('.preheader-wrapper').removeClass('initialized');\n $('.preheader-wrapper').css('display', 'none');\n $('div.page-wrapper .breadcrumbs').removeClass(\"padding-preheader-calculate\");\n $('#wishlist-popup').css(\"padding-top\", '0' + 'px');\n $('.page.messages .messages .message').removeClass(\"padding-preheader-calculate\")\n $('.page-main').removeClass(\"padding-preheader-calculate\");\n $('.nav-sections').removeAttr('style');\n $('.page-header').removeAttr('style');\n $('.megamenu-dropdown').removeAttr('style');\n $('.searchBar-root_open-hxZ').removeAttr('style');\n\n $('.block-right').each(function (element) {\n $(element).removeAttr('style');\n })\n }\n });\n return $.mage.preheader;\n});","Goyard_Cms/js/footer_links.js":"require([\n\t\"jquery\",\n\t'Magento_Customer/js/customer-data',\n], function ($, customerData) {\n\t$(document).ready(function () {\n\t\t//Accessibility for \"Co
2okies\" link - work with didomi code\n\t\tdocument.addEventListener('keydown', function (e) {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\tif (!$('body').hasClass('_keyfocus')) {\n\t\t\t\t\t$('body').addClass('_keyfocus');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t$(document).on('keydown', '.footer-button', function (event) {\n\t\t\tif (event.type === 'keydown' && event.keyCode === 32) {\n\t\t\t\t$(this)[0].click();\n\t\t\t}\n\t\t});\n\n\t\tdisplayEmptyCartMsg()\n\n\t\tfunction displayEmptyCartMsg() {\n\t\t\treturn new Promise(function (resolve, reject) {\n\t\t\t\tlet customer = customerData.get('customer');\n\t\t\t\tlet firstname = customer().firstname;\n\t\t\t\tif (firstname) {\n\t\t\t\t\tresolve();\n\t\t\t\t\t$('.footer-item.hidden').removeClass('hidden');\n\t\t\t\t} else {\n\t\t\t\t\tcustomer.subscribe(function () {\n\t\t\t\t\t\tif (customer().firstname) {\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t$('.footer-item.hidden').removeClass('hidden');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$('.footer-item.hidden').remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t})\n});","Goyard_Cms/js/content-type/slider/appearance/default/widget.js":"/**\r\n * Copyright \u00a9 Magento, Inc. All rights reserved.\r\n * See COPYING.txt for license details.\r\n */\r\n\r\ndefine([\r\n 'jquery',\r\n 'Magento_PageBuilder/js/events',\r\n 'slick',\r\n 'mage/translate'\r\n], function ($, events) {\r\n 'use strict';\r\n return function (config, sliderElement) {\r\n var $element = $(sliderElement);\r\n /**\r\n * Prevent each slick slider from being initialized more than once which could throw an error.\r\n */\r\n if ($element.hasClass('slick-initialized')) {\r\n $element.slick('unslick');\r\n }\r\n $element.slick({\r\n slidesToShow: $element.data('slide-to-show') || 1,\r\n centerMode: $element.data('center-mode') || false,\r\n centerPadding: '20%',\r\n autoplay: $element.data('autoplay'),\r\n autoplaySpeed: $element.data('autoplay-speed') || 0,\r\n fade: $element.data('fade'),\r\n infinite: $element.data('infinite-loop'),\r\n arrows: $element.data('show-arrows'),\r\n dots: $element.data('show-dots'),\r\n prevArrow: '<button type=\"button\" class=\"slick-prev\" aria-label=\"'+$.mage.__('See the previous boutique')+'\"></button>',\r\n nextArrow: '<button type=\"button\" class=\"slick-next\" aria-label=\"'+$.mage.__('See the next boutique')+'\"></button>',\r\n responsive: [\r\n {\r\n breakpoint: 1500,\r\n settings: {\r\n centerMode: $element.data('center-mode') || false,\r\n centerPadding: '19%'\r\n }\r\n },\r\n {\r\n breakpoint: 1280,\r\n settings: {\r\n centerMode: $element.data('center-mode') || false,\r\n centerPadding: '17%'\r\n }\r\n },\r\n {\r\n breakpoint: 1024,\r\n settings: {\r\n centerMode: $element.data('center-mode-mobile') || false,\r\n centerPadding: '50px',\r\n slidesToShow: $element.data('slide-to-show-mobile') || 1,\r\n dots: $element.data('show-dots-mobile'),\r\n arrows: $element.data('show-arrows-mobile')\r\n }\r\n }\r\n ]\r\n });\r\n\r\n // Redraw slide after content type gets redrawn\r\n events.on('contentType:redrawAfter', function (args) {\r\n if ($element.closest(args.element).length) {\r\n $element.slick('setPosition');\r\n }\r\n });\r\n // eslint-disable-next-line jquery-no-bind-unbind\r\n events.on('stage:viewportChangeAfter', $element.slick.bind($element, 'setPosition'));\r\n\r\n $('.color-wrapper').click(function(e) {\r\n e.stopPropagation();\r\n $(\".product-items\").find(\".color-label\").css(\"display\", \"block\");\r\n $(\".product-items\").find(\".color-detail\").css(\"display\", \"none\");\r\n $(this).find(\".color-label\").css(\"display\", \"none\");\r\n $(this).find(\".color-detail\").css(\"display\", \"block\");\r\n });\r\n };\r\n});\r\n","Goyard_Cms/js/widget/language_form.js":"/**\r\n * Copyright Goyard TE\r\n * @author Technology-everywhere\r\n */\r\nrequire([\r\n 'jquery',\r\n 'underscore',\r\n 'mage/translate',\r\n 'Magento_Ui/js/modal/modal'\r\n],\r\n function ($, _, $t, modal) {\r\n 'use strict';\r\n\r\n $(document).ready(function () {\r\n \r\n \tlet element = $('[data-content-type=\"language_form\"]');\r\n \t\r\n \t// Used for declari\r\n \tconst language_translation_array = [\r\n $.mage.__('Language name fr'),\r\n $.mage.__('Language name en'),\r\n $.mage.__('Language name jp'),\r\n $.mage.__('Language name kr'),\r\n $.mage.__('Language name ko'),\r\n $.mage.__('Language name zh')\r\n ];\r\n \t\r\n \tif(element.length > 0)\r\n \t\t{\r\n\t\t\t\tlet dropdown_label = '<label for=\"crm-language_form-select\" class=\"title\">'+ $.mage.__('Choose the language') +'</label>';\r\n \t\tlet dropdown = '<select id=\"crm-language_form-select\" class=\"language_form-select\">';
2 \r\n \t\t\r\n \t\t// Loop on allowed language\r\n \t\tlet default_language = element.data('default_language');\r\n \t\tlet allowed_language = element.data('allowed_language');\r\n \t\t\r\n \t\tlet json_url_config = element.data('url_configuration');\r\n \t\tlet allowed_language_array = allowed_language.split(',');\r\n \t\t\r\n \t\tfor (const allowed_lang of allowed_language_array) {\t\t\t\t\r\n\t\t\t\t\tif(default_language == allowed_lang)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdropdown = dropdown + '<option value=\"'+json_url_config[allowed_lang]+'\" selected=\"selected\">' + $.mage.__('Language name '+allowed_lang) + '</option>';\r\n\t\t\t\t\t}else{\r\n\t\t\t\t\t\tdropdown = dropdown + '<option value=\"'+json_url_config[allowed_lang]+'\">' + $.mage.__('Language name '+allowed_lang) + '</option>';\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\t \t\t\r\n \t\tdropdown = dropdown + '</select>'; \r\n \t\telement.append(dropdown_label); \t\t\r\n \t\telement.append(dropdown);\r\n \t\t\r\n\t let target_iframe = $('#' + element.data('targetIframe'));\t \r\n\t var target_lang = \"\";\t \r\n\t \r\n\t element.find('select').on('change',function(){\r\n\t \ttarget_lang = $(this).val();\r\n\t \t\r\n\t \tvar queryString = window.top.location.search; \t \t\r\n\t \tlet target_url = target_lang + queryString;\r\n\t \t\r\n\t \twindow.location.href = target_url;\r\n\t });\r\n\t \r\n \t}\r\n })\r\n }\r\n);","Magento_Cookie/js/notices.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget',\n 'mage/cookies'\n], function ($) {\n 'use strict';\n\n $.widget('mage.cookieNotices', {\n /** @inheritdoc */\n _create: function () {\n if ($.mage.cookies.get(this.options.cookieName)) {\n this.element.hide();\n } else {\n this.element.show();\n }\n $(this.options.cookieAllowButtonSelector).on('click', $.proxy(function () {\n var cookieExpires = new Date(new Date().getTime() + this.options.cookieLifetime * 1000);\n\n $.mage.cookies.set(this.options.cookieName, JSON.stringify(this.options.cookieValue), {\n expires: cookieExpires\n });\n\n if ($.mage.cookies.get(this.options.cookieName)) {\n this.element.hide();\n $(document).trigger('user:allowed:save:cookie');\n } else {\n window.location.href = this.options.noCookiesUrl;\n }\n }, this));\n }\n });\n\n return $.mage.cookieNotices;\n});\n","Magento_Cookie/js/require-cookie.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'Magento_Ui/js/modal/alert',\n 'jquery-ui-modules/widget',\n 'mage/mage',\n 'mage/translate'\n], function ($, alert) {\n 'use strict';\n\n $.widget('mage.requireCookie', {\n options: {\n event: 'click',\n noCookieUrl: 'enable-cookies',\n triggers: ['.action.login', '.action.submit'],\n isRedirectCmsPage: true\n },\n\n /**\n * Constructor\n * @private\n */\n _create: function () {\n this._bind();\n },\n\n /**\n * This method binds elements found in this widget.\n * @private\n */\n _bind: function () {\n var events = {};\n\n $.each(this.options.triggers, function (index, value) {\n events['click ' + value] = '_checkCookie';\n });\n this._on(events);\n },\n\n /**\n * This method set the url for the redirect.\n * @param {jQuery.Event} event\n * @private\n */\n _checkCookie: function (event) {\n if (navigator.cookieEnabled) {\n return;\n }\n\n event.preventDefault();\n\n if (this.options.isRedirectCmsPage) {\n window.location = this.options.noCookieUrl;\n } else {\n alert({\n content: $.mage.__('Cookies are disabled in your browser.')\n });\n }\n }\n });\n\n return $.mage.requireCookie;\n});\n","js-storage/js.storage.js":"/*\n * JS Storage Plugin\n *\n * Copyright (c) 2019 Julien Maurel\n *\n *
2Licensed under the MIT license:\n * http://www.opensource.org/licenses/mit-license.php\n *\n * Project home:\n * https://github.com/julien-maurel/js-storage\n *\n * Version: 1.1.0\n */\n(function (factory) {\n var registeredInModuleLoader = false;\n if (typeof define === 'function' && define.amd) {\n define(['jquery', 'jquery/jquery.cookie'], factory);\n registeredInModuleLoader = true;\n }\n if (typeof exports === 'object') {\n module.exports = factory();\n registeredInModuleLoader = true;\n }\n if (!registeredInModuleLoader) {\n var OldStorages = window.Storages;\n var api = window.Storages = factory();\n api.noConflict = function () {\n window.Storages = OldStorages;\n return api;\n };\n }\n}(function () {\n // Variables used by utilities functions (like isPlainObject...)\n var class2type = {};\n var toString = class2type.toString;\n var hasOwn = class2type.hasOwnProperty;\n var fnToString = hasOwn.toString;\n var ObjectFunctionString = fnToString.call(Object);\n var getProto = Object.getPrototypeOf;\n var apis = {};\n\n // Prefix to use with cookie fallback\n var cookie_local_prefix = \"ls_\";\n var cookie_session_prefix = \"ss_\";\n\n // Get items from a storage\n function _get() {\n var storage = this._type, l = arguments.length, s = window[storage], a = arguments, a0 = a[0], vi, ret, tmp, i, j;\n if (l < 1) {\n throw new Error('Minimum 1 argument must be given');\n } else if (Array.isArray(a0)) {\n // If second argument is an array, return an object with value of storage for each item in this array\n ret = {};\n for (i in a0) {\n if (a0.hasOwnProperty(i)) {\n vi = a0[i];\n try {\n ret[vi] = JSON.parse(s.getItem(vi));\n } catch (e) {\n ret[vi] = s.getItem(vi);\n }\n }\n }\n return ret;\n } else if (l == 1) {\n // If only 1 argument, return value directly\n try {\n return JSON.parse(s.getItem(a0));\n } catch (e) {\n return s.getItem(a0);\n }\n } else {\n // If more than 1 argument, parse storage to retrieve final value to return it\n // Get first level\n try {\n ret = JSON.parse(s.getItem(a0));\n if (!ret) {\n throw new ReferenceError(a0 + ' is not defined in this storage');\n }\n } catch (e) {\n throw new ReferenceError(a0 + ' is not defined in this storage');\n }\n // Parse next levels\n for (i = 1; i < l - 1; i++) {\n ret = ret[a[i]];\n if (ret === undefined) {\n throw new ReferenceError([].slice.call(a, 0, i + 1).join('.') + ' is not defined in this storage');\n }\n }\n // If last argument is an array, return an object with value for each item in this array\n // Else return value normally\n if (Array.isArray(a[i])) {\n tmp = ret;\n ret = {};\n for (j in a[i]) {\n if (a[i].hasOwnProperty(j)) {\n ret[a[i][j]] = tmp[a[i][j]];\n }\n }\n return ret;\n } else {\n return ret[a[i]];\n }\n }\n }\n\n // Set items of a storage\n function _set() {\n var storage = this._type, l = arguments.length, s = window[storage], a = arguments, a0 = a[0], a1 = a[1], vi, to_store = isNaN(a1) ? {} : [], type, tmp, i;\n if (l < 1 || !_isPlainObject(a0) && l < 2) {\n throw new Error('Minimum 2 arguments must be given or first parameter must be an object');\n } else if (_isPlainObject(a0)) {\n // If first argument is an object, set values of storage for each property of this object\n for (i in a0) {\n if (a0.hasOwnProperty(i)) {\n vi = a0[i];\n if (!_isPlainObject(vi) && !this.alwaysUseJson) {\n s.setItem(i, vi);\n } else {\n s.setItem(i, JSON.stringify(vi));\n }\n }\n }\n return a0;\n } else if (l == 2) {\n // If only 2 arguments, set value of storage directly\n if (typeof a1 === 'object' || this.alwaysUseJson) {\n s.setItem(a0, JSON.stringify(a1));\n } else {\n s.setItem(a0, a1);\n }\n return a1;\n } else {\n // If more than 3 arguments, parse storage to retrieve final node and set value\n // Get first level\n try {\n tmp = s.getItem(a0);\n if (tmp != null) {\n to_store = JSON.parse(tmp);\n }\n } catch (e) {\n }\n tmp = to_store;\n // Parse next levels and set value\n for (i = 1; i < l - 2;
2 i++) {\n vi = a[i];\n type = isNaN(a[i + 1]) ? \"object\" : \"array\";\n if (!tmp[vi] || type == \"object\" && !_isPlainObject(tmp[vi]) || type == \"array\" && !Array.isArray(tmp[vi])) {\n if (type == \"array\") tmp[vi] = [];\n else tmp[vi] = {};\n }\n tmp = tmp[vi];\n }\n tmp[a[i]] = a[i + 1];\n s.setItem(a0, JSON.stringify(to_store));\n return to_store;\n }\n }\n\n // Remove items from a storage\n function _remove() {\n var storage = this._type, l = arguments.length, s = window[storage], a = arguments, a0 = a[0], to_store, tmp, i, j;\n if (l < 1) {\n throw new Error('Minimum 1 argument must be given');\n } else if (Array.isArray(a0)) {\n // If first argument is an array, remove values from storage for each item of this array\n for (i in a0) {\n if (a0.hasOwnProperty(i)) {\n s.removeItem(a0[i]);\n }\n }\n return true;\n } else if (l == 1) {\n // If only 2 arguments, remove value from storage directly\n s.removeItem(a0);\n return true;\n } else {\n // If more than 2 arguments, parse storage to retrieve final node and remove value\n // Get first level\n try {\n to_store = tmp = JSON.parse(s.getItem(a0));\n } catch (e) {\n throw new ReferenceError(a0 + ' is not defined in this storage');\n }\n // Parse next levels and remove value\n for (i = 1; i < l - 1; i++) {\n tmp = tmp[a[i]];\n if (tmp === undefined) {\n throw new ReferenceError([].slice.call(a, 1, i).join('.') + ' is not defined in this storage');\n }\n }\n // If last argument is an array,remove value for each item in this array\n // Else remove value normally\n if (Array.isArray(a[i])) {\n for (j in a[i]) {\n if (a[i].hasOwnProperty(j)) {\n delete tmp[a[i][j]];\n }\n }\n } else {\n delete tmp[a[i]];\n }\n s.setItem(a0, JSON.stringify(to_store));\n return true;\n }\n }\n\n // Remove all items from a storage\n function _removeAll(reinit_ns) {\n var keys = _keys.call(this), i;\n for (i in keys) {\n if (keys.hasOwnProperty(i)) {\n _remove.call(this, keys[i]);\n }\n }\n // Reinitialize all namespace storages\n if (reinit_ns) {\n for (i in apis.namespaceStorages) {\n if (apis.namespaceStorages.hasOwnProperty(i)) {\n _createNamespace(i);\n }\n }\n }\n }\n\n // Check if items of a storage are empty\n function _isEmpty() {\n var l = arguments.length, a = arguments, a0 = a[0], i;\n if (l == 0) {\n // If no argument, test if storage is empty\n return (_keys.call(this).length == 0);\n } else if (Array.isArray(a0)) {\n // If first argument is an array, test each item of this array and return true only if all items are empty\n for (i = 0; i < a0.length; i++) {\n if (!_isEmpty.call(this, a0[i])) {\n return false;\n }\n }\n return true;\n } else {\n // If at least 1 argument, try to get value and test it\n try {\n var v = _get.apply(this, arguments);\n // Convert result to an object (if last argument is an array, _get return already an object) and test each item\n if (!Array.isArray(a[l - 1])) {\n v = {'totest': v};\n }\n for (i in v) {\n if (v.hasOwnProperty(i) && !(\n (_isPlainObject(v[i]) && _isEmptyObject(v[i])) ||\n (Array.isArray(v[i]) && !v[i].length) ||\n (typeof v[i] !== 'boolean' && !v[i])\n )) {\n return false;\n }\n }\n return true;\n } catch (e) {\n return true;\n }\n }\n }\n\n // Check if items of a storage exist\n function _isSet() {\n var l = arguments.length, a = arguments, a0 = a[0], i;\n if (l < 1) {\n throw new Error('Minimum 1 argument must be given');\n }\n if (Array.isArray(a0)) {\n // If first argument is an array, test each item of this array and return true only if all items exist\n for (i = 0; i < a0.length;
2 i++) {\n if (!_isSet.call(this, a0[i])) {\n return false;\n }\n }\n return true;\n } else {\n // For other case, try to get value and test it\n try {\n var v = _get.apply(this, arguments);\n // Convert result to an object (if last argument is an array, _get return already an object) and test each item\n if (!Array.isArray(a[l - 1])) {\n v = {'totest': v};\n }\n for (i in v) {\n if (v.hasOwnProperty(i) && !(v[i] !== undefined && v[i] !== null)) {\n return false;\n }\n }\n return true;\n } catch (e) {\n return false;\n }\n }\n }\n\n // Get keys of a storage or of an item of the storage\n function _keys() {\n var storage = this._type, l = arguments.length, s = window[storage], keys = [], o = {};\n // If at least 1 argument, get value from storage to retrieve keys\n // Else, use storage to retrieve keys\n if (l > 0) {\n o = _get.apply(this, arguments);\n } else {\n o = s;\n }\n if (o && o._cookie) {\n // If storage is a cookie, use js-cookie to retrieve keys\n var cookies = Cookies.get();\n for (var key in cookies) {\n if (cookies.hasOwnProperty(key) && key != '') {\n keys.push(key.replace(o._prefix, ''));\n }\n }\n } else {\n for (var i in o) {\n if (o.hasOwnProperty(i)) {\n keys.push(i);\n }\n }\n }\n return keys;\n }\n\n // Create new namespace storage\n function _createNamespace(name) {\n if (!name || typeof name != \"string\") {\n throw new Error('First parameter must be a string');\n }\n if (storage_available) {\n if (!window.localStorage.getItem(name)) {\n window.localStorage.setItem(name, '{}');\n }\n if (!window.sessionStorage.getItem(name)) {\n window.sessionStorage.setItem(name, '{}');\n }\n } else {\n if (!window.localCookieStorage.getItem(name)) {\n window.localCookieStorage.setItem(name, '{}');\n }\n if (!window.sessionCookieStorage.getItem(name)) {\n window.sessionCookieStorage.setItem(name, '{}');\n }\n }\n var ns = {\n localStorage: _extend({}, apis.localStorage, {_ns: name}),\n sessionStorage: _extend({}, apis.sessionStorage, {_ns: name})\n };\n if (cookies_available) {\n if (!window.cookieStorage.getItem(name)) {\n window.cookieStorage.setItem(name, '{}');\n }\n ns.cookieStorage = _extend({}, apis.cookieStorage, {_ns: name});\n }\n apis.namespaceStorages[name] = ns;\n return ns;\n }\n\n // Test if storage is natively available on browser\n function _testStorage(name) {\n var foo = 'jsapi';\n try {\n if (!window[name]) {\n return false;\n }\n window[name].setItem(foo, foo);\n window[name].removeItem(foo);\n return true;\n } catch (e) {\n return false;\n }\n }\n\n // Test if a variable is a plain object (from jQuery)\n function _isPlainObject(obj) {\n var proto, Ctor;\n\n // Detect obvious negatives\n // Use toString instead of jQuery.type to catch host objects\n if (!obj || toString.call(obj) !== \"[object Object]\") {\n return false;\n }\n\n proto = getProto(obj);\n\n // Objects with no prototype (e.g., `Object.create( null )`) are plain\n if (!proto) {\n return true;\n }\n\n // Objects with prototype are plain iff they were constructed by a global Object function\n Ctor = hasOwn.call(proto, \"constructor\") && proto.constructor;\n return typeof Ctor === \"function\" && fnToString.call(Ctor) === ObjectFunctionString;\n }\n\n // Test if a variable is an empty object (from jQuery)\n function _isEmptyObject(obj) {\n var name;\n\n for (name in obj) {\n return false;\n }\n return true;\n }\n\n // Merge objects\n function _extend() {\n var i = 1;\n var result = arguments[0];\n for (; i < arguments.length;
2 i++) {\n var attributes = arguments[i];\n for (var key in attributes) {\n if (attributes.hasOwnProperty(key)) {\n result[key] = attributes[key];\n }\n }\n }\n return result;\n }\n\n // Check if storages are natively available on browser and check is js-cookie is present\n var storage_available = _testStorage('localStorage');\n var cookies_available = typeof Cookies !== 'undefined';\n\n // Namespace object\n var storage = {\n _type: '',\n _ns: '',\n _callMethod: function (f, a) {\n a = Array.prototype.slice.call(a);\n var p = [], a0 = a[0];\n if (this._ns) {\n p.push(this._ns);\n }\n if (typeof a0 === 'string' && a0.indexOf('.') !== -1) {\n a.shift();\n [].unshift.apply(a, a0.split('.'));\n }\n [].push.apply(p, a);\n return f.apply(this, p);\n },\n // Define if plugin always use JSON to store values (even to store simple values like string, int...) or not\n alwaysUseJson: false,\n // Get items. If no parameters and storage have a namespace, return all namespace\n get: function () {\n if (!storage_available && !cookies_available){\n return null;\n }\n return this._callMethod(_get, arguments);\n },\n // Set items\n set: function () {\n var l = arguments.length, a = arguments, a0 = a[0];\n if (l < 1 || !_isPlainObject(a0) && l < 2) {\n throw new Error('Minimum 2 arguments must be given or first parameter must be an object');\n }\n if (!storage_available && !cookies_available){\n return null;\n }\n // If first argument is an object and storage is a namespace storage, set values individually\n if (_isPlainObject(a0) && this._ns) {\n for (var i in a0) {\n if (a0.hasOwnProperty(i)) {\n this._callMethod(_set, [i, a0[i]]);\n }\n }\n return a0;\n } else {\n var r = this._callMethod(_set, a);\n if (this._ns) {\n return r[a0.split('.')[0]];\n } else {\n return r;\n }\n }\n },\n // Delete items\n remove: function () {\n if (arguments.length < 1) {\n throw new Error('Minimum 1 argument must be given');\n }\n if (!storage_available && !cookies_available){\n return null;\n }\n return this._callMethod(_remove, arguments);\n },\n // Delete all items\n removeAll: function (reinit_ns) {\n if (!storage_available && !cookies_available){\n return null;\n }\n if (this._ns) {\n this._callMethod(_set, [{}]);\n return true;\n } else {\n return this._callMethod(_removeAll, [reinit_ns]);\n }\n },\n // Items empty\n isEmpty: function () {\n if (!storage_available && !cookies_available){\n return null;\n }\n return this._callMethod(_isEmpty, arguments);\n },\n // Items exists\n isSet: function () {\n if (arguments.length < 1) {\n throw new Error('Minimum 1 argument must be given');\n }\n if (!storage_available && !cookies_available){\n return null;\n }\n return this._callMethod(_isSet, arguments);\n },\n // Get keys of items\n keys: function () {\n if (!storage_available && !cookies_available){\n return null;\n }\n return this._callMethod(_keys, arguments);\n }\n };\n\n // Use js-cookie for compatibility with old browsers and give access to cookieStorage\n if (cookie
2s_available) {\n // sessionStorage is valid for one window/tab. To simulate that with cookie, we set a name for the window and use it for the name of the cookie\n if (!window.name) {\n window.name = Math.floor(Math.random() * 100000000);\n }\n var cookie_storage = {\n _cookie: true,\n _prefix: '',\n _expires: null,\n _path: null,\n _domain: null,\n _secure: false,\n setItem: function (n, v) {\n Cookies.set(this._prefix + n, v, {expires: this._expires, path: this._path, domain: this._domain, secure: this._secure});\n },\n getItem: function (n) {\n return Cookies.get(this._prefix + n);\n },\n removeItem: function (n) {\n return Cookies.remove(this._prefix + n, {path: this._path});\n },\n clear: function () {\n var cookies = Cookies.get();\n for (var key in cookies) {\n if (cookies.hasOwnProperty(key) && key != '') {\n if (!this._prefix && key.indexOf(cookie_local_prefix) === -1 && key.indexOf(cookie_session_prefix) === -1 || this._prefix && key.indexOf(this._prefix) === 0) {\n Cookies.remove(key);\n }\n }\n }\n },\n setExpires: function (e) {\n this._expires = e;\n return this;\n },\n setPath: function (p) {\n this._path = p;\n return this;\n },\n setDomain: function (d) {\n this._domain = d;\n return this;\n },\n setSecure: function (s) {\n this._secure = s;\n return this;\n },\n setConf: function (c) {\n if (c.path) {\n this._path = c.path;\n }\n if (c.domain) {\n this._domain = c.domain;\n }\n if (c.secure) {\n this._secure = c.secure;\n }\n if (c.expires) {\n this._expires = c.expires;\n }\n return this;\n },\n setDefaultConf: function () {\n this._path = this._domain = this._expires = null;\n this._secure = false;\n }\n };\n if (!storage_available) {\n window.localCookieStorage = _extend({}, cookie_storage, {\n _prefix: cookie_local_prefix,\n _expires: 365 * 10,\n _secure: true\n });\n window.sessionCookieStorage = _extend({}, cookie_storage, {\n _prefix: cookie_session_prefix + window.name + '_',\n _secure: true\n });\n }\n window.cookieStorage = _extend({}, cookie_storage);\n // cookieStorage API\n apis.cookieStorage = _extend({}, storage, {\n _type: 'cookieStorage',\n setExpires: function (e) {\n window.cookieStorage.setExpires(e);\n return this;\n },\n setPath: function (p) {\n window.cookieStorage.setPath(p);\n return this;\n },\n setDomain: function (d) {\n window.cookieStorage.setDomain(d);\n return this;\n },\n setSecure: function (s) {\n window.cookieStorage.setSecure(s);\n return this;\n },\n setConf: function (c) {\n window.cookieStorage.setConf(c);\n return this;\n },\n setDefaultConf: function () {\n window.cookieStorage.setDefaultConf();\n return this;\n }\n });\n }\n\n // Get a new API on a namespace\n apis.initNamespaceStorage = function (ns) {\n return _createNamespace(ns);\n };\n if (storage_available) {\n // localStorage API\n apis.localStorage = _extend({}, storage, {_type: 'localStorage'});\n // sessionStorage API\n apis.sessionStorage = _extend({}, storage, {_type: 'sessionStorage'});\n } else {\n // localStorage API\n apis.localStorage = _extend({}, storage, {_type: 'localCookieStorage'});\n // sessionStorage API\n apis.sessionStorage = _extend({}, storage, {_type: 'sessionCookieStorage'});\n }\n // List of all namespace storage\n apis.namespaceStorages = {};\n // Remove all items in all storages\n apis.removeAllStorages = function (reinit_ns) {\n apis.localStorage.removeAll(reinit_ns);\n apis.sessionStorage.removeAll(reinit_ns);\n if (apis.cookieStorage) {\n apis.cookieStorage.removeAll(reinit_ns);\n }\n if (!reinit_ns) {\n apis.namespaceStorages = {};\n }\n };\n // About alwaysUseJson\n // By default, all values are string on html storages and the plugin don't use json to store simple values (strings, int, float...)\n // So by default, if you do storage.setItem('test',2), value in storage will be \"2\", not 2\n // If you set this property to true, all values set with the plugin will be stored as json to have typed values in any cases\n apis.alwaysUseJsonInStorage = function (value) {\n storage.alwaysUseJson = value;\n apis.localStorage.alwaysUseJson = value;\n apis.sessionStorage.alwaysUseJson = value;\n if (apis.cookieStorage) {\n apis.cookieStorage.alwaysUseJson = value;\n }\n };\n\n return apis;\n}));\n","js-storage/storage-wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'js-storage/js.storage'\n], function ($, storage) {\n 'use strict';\n\n if (window.cookieStorage) {\n var cookiesConfig = window.cookiesConfig || {};\n\n $.extend(window.cookieStorage, {\n _secure: !!cookiesConfig.secure,\n _samesite: cookiesConfig.samesite ? cookiesConfig.samesite : 'lax',\n\n /**\n * Set value under name\n * @param {String} name\n * @param {String}
2 value\n * @param {Object} [options]\n */\n setItem: function (name, value, options) {\n var _default = {\n expires: this._expires,\n path: this._path,\n domain: this._domain,\n secure: this._secure,\n samesite: this._samesite\n };\n\n $.cookie(this._prefix + name, value, $.extend(_default, options || {}));\n },\n\n /**\n * Set default options\n * @param {Object} c\n * @returns {storage}\n */\n setConf: function (c) {\n if (c.path) {\n this._path = c.path;\n }\n\n if (c.domain) {\n this._domain = c.domain;\n }\n\n if (c.expires) {\n this._expires = c.expires;\n }\n\n if (typeof c.secure !== 'undefined') {\n this._secure = c.secure;\n }\n\n if (typeof c.samesite !== 'undefined') {\n this._samesite = c.samesite;\n }\n\n return this;\n }\n });\n }\n\n $.alwaysUseJsonInStorage = $.alwaysUseJsonInStorage || storage.alwaysUseJsonInStorage;\n $.cookieStorage = $.cookieStorage || storage.cookieStorage;\n $.initNamespaceStorage = $.initNamespaceStorage || storage.initNamespaceStorage;\n $.localStorage = $.localStorage || storage.localStorage;\n $.namespaceStorages = $.namespaceStorages || storage.namespaceStorages;\n $.removeAllStorages = $.removeAllStorages || storage.removeAllStorages;\n $.sessionStorage = $.sessionStorage || storage.sessionStorage;\n});\n","Magento_Fedex/js/model/shipping-rates-validation-rules.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n return {\n /**\n * @return {Object}\n */\n getRules: function () {\n return {\n 'postcode': {\n 'required': true\n },\n 'country_id': {\n 'required': true\n },\n 'city': {\n 'required': true\n }\n };\n }\n };\n});\n","Magento_Fedex/js/model/shipping-rates-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mageUtils',\n 'Magento_Fedex/js/model/shipping-rates-validation-rules',\n 'mage/translate'\n], function ($, utils, validationRules, $t) {\n 'use strict';\n\n return {\n validationErrors: [],\n\n /**\n * @param {Object} address\n * @return {Boolean}\n */\n validate: function (address) {\n var self = this;\n\n this.validationErrors = [];\n $.each(validationRules.getRules(), function (field, rule) {\n var message;\n\n if (rule.required && utils.isEmpty(address[field])) {\n message = $t('Field ') + field + $t(' is required.');\n\n self.validationErrors.push(message);\n }\n });\n\n return !this.validationErrors.length;\n }\n };\n});\n","Magento_Fedex/js/view/shipping-rates-validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'uiComponent',\n 'Magento_Checkout/js/model/shipping-rates-validator',\n 'Magento_Checkout/js/model/shipping-rates-validation-rules',\n 'Magento_Fedex/js/model/shipping-rates-validator',\n 'Magento_Fedex/js/model/shipping-rates-validation-rules'\n], function (\n Component,\n defaultShippingRatesValidator,\n defaultShippingRatesValidationRules,\n fedexShippingRatesValidator,\n fedexShippingRatesValidationRules\n) {\n 'use strict';\n\n defaultShippingRatesValidator.registerValidator('fedex', fedexShippingRatesValidator);\n defaultShippingRatesValidationRules.registerRules('fedex', fedexShippingRatesValidationRules);\n\n return Component;\n});\n","Goyard_Store/js/modal-store-redirect-location.js":"define([\r\n\t'jquery',\r\n\t'Magento_Ui/js/modal/modal',\r\n\t'mage/url',\r\n\t'mage/cookies'\r\n], function ($, modal, urlBuilder) {\r\n\t'use strict';\r\n\r\n\treturn function (config) {\r\n\t\tlet options = {\r\n\t\t\ttype: 'popup',\r\n\t\t\tresponsive: true,\r\n\t\t\tmodalClass: 'redirection-store-modal',\r\n\t\t\tinnerScroll: true,\r\n\t\t\tbuttons: []\r\n\t\t};\r\n\r\n\t\t$(document).ready(function () {\r\n\t\t\tlet currentUrl = window.location.href;\r\n\t\t\tlet pageType = config.pageType;\r\n\t\t\tlet cmsPageId = config.cmsPageId;\r\n\t\t\tlet closedDurationCookie = parseInt(config.closedDurationCookie);\r\n\t\t\tlet excludedCountryGE = config.excludedCountryGE;\r\n\t\t\tlet preferredLocaleCookieLifetime = parseInt(config.preferredLocaleCookieLifetime);\r\n\t\t\tlet isPreferredLocaleCookieEnabled = Boolean(config.isPreferredLocaleCookieEnabled);\r\n\t\t\tconst now = new Date();\r\n\t\t\tconst expirationDate = new Date(now.getTime() + closedDurationCookie);\r\n\t\t\tconst preferredLocaleExpirationDate = new Date(now.getTime() + preferredLocaleCookieLifetime * 24 * 60 * 60 * 1000);\r\n\t\t\tconst forcingPopupNoCookieGlobalE = config.forcingPopupNoCookieGlobalE;\r\n\t\t\tconst mappedCountries = config.mappedCountries;\r\n\r\n\t\t\tlet hasClosedCookie = $.mage.cookies.get('closed_redirection_popup') !== null;\r\n\t\t\tlet hasGlobalECookie = $.mage.cookies.get('GlobalE_Data') !== null;\r\n\t\t\tlet hasFromStore = currentUrl.includes('from_store=');\r\n\t\t\tlet shouldForcePopup = forcingPopupNoCookieGlobalE === true || forcingPopupNoCookieGlobalE === 1 || forcingPopupNoCookieGlobalE === \"1\";\r\n\t\t\tlet global_e_enabled = window.globale_config;\r\n\r\n\t\t\tlet showModal = false;
2\r\n\r\n\t\t\t// CASE 1 : NO GLOBAL-E\r\n\t\t\tif (!global_e_enabled) {\r\n\t\t\t\tif (!hasClosedCookie) {\r\n\t\t\t\t\tshowModal = true;\r\n\t\t\t\t}\r\n\t\t\t\t// CASE 2 : GOLBAL-E Activated : Check if GEcookie is set\r\n\t\t\t} else {\r\n\t\t\t\tif (!hasGlobalECookie && !hasFromStore) {\r\n\t\t\t\t\tshowModal = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// if Cookie match with excluded Country , show the switch popin\r\n\t\t\t\tlet globalECookieData = JSON.parse($.mage.cookies.get('GlobalE_Data'));\r\n\t\t\t\tlet currentCookieCountry = globalECookieData ? globalECookieData.countryISO : '';\r\n\t\t\t\tif (excludedCountryGE.includes(currentCookieCountry)) {\r\n\t\t\t\t\tshowModal = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tlet $modalStoreRedirectLocationContent = $('#modal-store-redirect-location-content');\r\n\r\n\t\t\t// Keyboard event helper functions\r\n\t\t\tconst eventSpaceBar = (event) => event.which === 32 || event.keyCode === 32;\r\n\t\t\tconst eventEnter = (event) => event.which === 13 || event.keyCode === 13;\r\n\t\t\tconst eventArrowLeft = (event) => event.which === 37 || event.keyCode === 37;\r\n\t\t\tconst eventArrowRight = (event) => event.which === 39 || event.keyCode === 39;\r\n\t\t\tconst eventHome = (event) => event.key === 'Home' || event.keyCode === 36;\r\n\t\t\tconst eventEnd = (event) => event.key === 'End' || event.keyCode === 35;\r\n\r\n\t\t\t// Focus only on focusable tab element, Magento_Ui/js/modal/modal \":focusable\" selector does not exclude tabindex=\"-1\" bug\r\n\t\t\t$modalStoreRedirectLocationContent.on('focusin', '.sr-accordion-trigger[tabindex=\"-1\"]', function () {\r\n\t\t\t\t$modalStoreRedirectLocationContent.find('.regions-header [role=\"tab\"][tabindex=\"0\"]').trigger('focus');\r\n\t\t\t});\r\n\r\n\t\t\t// Tabs pattern\r\n\t\t\tfunction activateTab($tab) {\r\n\t\t\t\tlet $tabs = $modalStoreRedirectLocationContent.find('.regions-header [role=\"tab\"]');\r\n\r\n\t\t\t\t$tabs.attr({ 'aria-selected': 'false', tabindex: '-1' });\r\n\t\t\t\t$modalStoreRedirectLocationContent.find('.sr-accordion-panel').removeClass('show').attr('hidden', true);\r\n\r\n\t\t\t\t$tab.attr({ 'aria-selected': 'true', tabindex: '0' });\r\n\t\t\t\t$('#' + $tab.attr('aria-controls')).addClass('show').removeAttr('hidden');\r\n\t\t\t\t$tab.trigger('focus');\r\n\t\t\t}\r\n\r\n\t\t\tfunction moveFocusToTab($tab) {\r\n\t\t\t\t$modalStoreRedirectLocationContent.find('.regions-header [role=\"tab\"]').attr('tabindex', '-1');\r\n\t\t\t\t$tab.attr('tabindex', '0');\r\n\t\t\t\t$tab.trigger('focus');\r\n\t\t\t}\r\n\r\n\t\t\t$(document).on('click', '.sr-accordion-trigger', function () {\r\n\t\t\t\tactivateTab($(this));\r\n\t\t\t});\r\n\r\n\t\t\t$(document).on('keydown', '.sr-accordion-trigger', function (event) {\r\n\t\t\t\tlet $tabs = $modalStoreRedirectLocationContent.find('.regions-header [role=\"tab\"]');\r\n\t\t\t\tlet currentIndex = $tabs.index(this);\r\n\r\n\t\t\t\tif (eventArrowRight(event)) {\r\n\t\t\t\t\tevent.preventDefault();\r\n\t\t\t\t\tmoveFocusToTab($tabs.eq((currentIndex + 1) % $tabs.length));\r\n\t\t\t\t} else if (eventArrowLeft(event)) {\r\n\t\t\t\t\tevent.preventDefault();\r\n\t\t\t\t\tmoveFocusToTab($tabs.eq((currentIndex - 1 + $tabs.length) % $tabs.length));\r\n\t\t\t\t} else if (eventHome(event)) {\r\n\t\t\t\t\tevent.preventDefault();\r\n\t\t\t\t\tmoveFocusToTab($tabs.first());\r\n\t\t\t\t} else if (eventEnd(event)) {\r\n\t\t\t\t\tevent.preventDefault();\r\n\t\t\t\t\tmoveFocusToTab($tabs.last());\r\n\t\t\t\t} else if (eventEnter(event) || eventSpaceBar(event)) {\r\n\t\t\t\t\tevent.preventDefault();\r\n\t\t\t\t\tactivateTab($(this));\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\t// Close tabs and reset tabindex on close modal\r\n\t\t\t$modalStoreRedirectLocationContent.on('modalclosed', function () {\r\n\t\t\t\tlet $tabs = $modalStoreRedirectLocationContent.find('.regions-header [role=\"tab\"]');\r\n\r\n\t\t\t\t$tabs.attr({ 'aria-selected': 'false', tabindex: '-1' });\r\n\t\t\t\t$tabs.first().attr('tabindex', '0');\r\n\t\t\t\t$modalStoreRedirectLocationContent.find('.sr-accordion-panel').removeClass('show').attr('hidden', true);\r\n\t\t\t});\r\n\r\n\t\t\t// If show modal mean that we have to call an ajax controller to get the data from the current visitor\r\n\t\t\tif (showModal) {\r\n\t\t\t\tconst queryString = window.location.search;
2\r\n\t\t\t\tconst urlParams = new URLSearchParams(queryString);\r\n\t\t\t\tconst fastlyCountryCode = urlParams.get('fastly-country-code');\r\n\r\n\t\t\t\tconst url = urlBuilder.build('goyard_store/ajax/data');\r\n\t\t\t\tjQuery.ajax({\r\n\t\t\t\t\turl: url,\r\n\t\t\t\t\ttype: 'POST',\r\n\t\t\t\t\tdataType: 'JSON',\r\n\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t'current': currentUrl,\r\n\t\t\t\t\t\t'page_type': pageType,\r\n\t\t\t\t\t\t'cms_page_id': cmsPageId,\r\n\t\t\t\t\t\t'fastly_country_code': fastlyCountryCode\r\n\t\t\t\t\t},\r\n\t\t\t\t\tsuccess: function (response) {\r\n\r\n\t\t\t\t\t\tif (response.display_popup) {\r\n\t\t\t\t\t\t\t$('#popin_redirect_visiting_from').text(response.visiting_from || '');\r\n\t\t\t\t\t\t\tif (response.detected_country_label && response.detected_country_url) {\r\n\t\t\t\t\t\t\t\t$('#cta-detected-country')\r\n\t\t\t\t\t\t\t\t\t.attr('href', response.detected_country_url)\r\n\t\t\t\t\t\t\t\t\t.attr('data-url', response.detected_country_url)\r\n\t\t\t\t\t\t\t\t\t.attr('data-global', response.detected_country_global_e)\r\n\t\t\t\t\t\t\t\t\t.attr('data-store-code', response.detected_country_store_code)\r\n\t\t\t\t\t\t\t\t\t.text(response.detected_country_label);\r\n\t\t\t\t\t\t\t\t$('#popin_redirect_visiting_switch_to').show();\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tmodal(options, $modalStoreRedirectLocationContent);\r\n\t\t\t\t\t\t\t$modalStoreRedirectLocationContent.modal('openModal');\r\n\r\n\t\t\t\t\t\t\t$('a[id^=\"modal-continue-to\"]').on('click keydown', function (e) {\r\n\t\t\t\t\t\t\t\tif (e.type === 'click' || (e.type === 'keydown' && (e.which === 13 || e.keyCode === 13))) {\r\n\t\t\t\t\t\t\t\t\t$modalStoreRedirectLocationContent.modal('closeModal');\r\n\t\t\t\t\t\t\t\t\t$.mage.cookies.set('closed_redirection_popup', true, { expires: expirationDate });\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t});\r\n\r\n\t\t\t\t\t\t\t$modalStoreRedirectLocationContent.find('a').on('click keydown', function (e) {\r\n\t\t\t\t\t\t\t\tif (e.type === 'click' || (e.type === 'keydown' && (e.which === 13 || e.keyCode === 13))) {\r\n\t\t\t\t\t\t\t\t\t$.mage.cookies.set('closed_redirection_popup', true, { expires: expirationDate });\r\n\t\t\t\t\t\t\t\t\tconst globalData = $(this).data('global');\r\n\t\t\t\t\t\t\t\t\tif (globalData) {\r\n\t\t\t\t\t\t\t\t\t\t$.mage.cookies.set('GlobalE_Data', JSON.stringify(globalData), { expires: expirationDate });\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tconst storeCode = $(this).data('store-code');\r\n\t\t\t\t\t\t\t\t\tif (storeCode && isPreferredLocaleCookieEnabled) {\r\n\t\t\t\t\t\t\t\t\t\t$.mage.cookies.set('goyard_preferred_locale', storeCode, { expires: preferredLocaleExpirationDate });\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tconst targetUrl = $(this).data('url');\r\n\t\t\t\t\t\t\t\t\tif (targetUrl) {\r\n\t\t\t\t\t\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\t\t\t\t\t\twindow.location.href = targetUrl;\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t},\r\n\t\t\t\t\terror: function (xhr, status, error) {\r\n\t\t\t\t\t\t//console.error(\"Error white retrieving visiting information : \" + error);\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t});\r\n\t};\r\n});\r\n"} 3}});
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.