![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/cartforge.co/pub/static/frontend/Magento/blank/en_US/js/bundle/ |
require.config({"config": { "jsbuild":{"Magento_Ui/js/lib/knockout/bindings/optgroup.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'mageUtils'\n ], function (ko, utils) {\n 'use strict';\n\n var captionPlaceholder = {},\n optgroupTmpl = '<optgroup label=\"${ $.label }\"></optgroup>',\n nbspRe = / /g,\n optionsText,\n optionsValue,\n optionTitle;\n\n ko.bindingHandlers.optgroup = {\n /**\n * @param {*} element\n */\n init: function (element) {\n if (ko.utils.tagNameLower(element) !== 'select') {\n throw new Error('options binding applies only to SELECT elements');\n }\n\n // Remove all existing <option>s.\n while (element.length > 0) {\n element.remove(0);\n }\n },\n\n /**\n * @param {*} element\n * @param {*} valueAccessor\n * @param {*} allBindings\n */\n update: function (element, valueAccessor, allBindings) {\n var selectWasPreviouslyEmpty = element.length === 0,\n previousScrollTop = !selectWasPreviouslyEmpty && element.multiple ? element.scrollTop : null,\n includeDestroyed = allBindings.get('optionsIncludeDestroyed'),\n arrayToDomNodeChildrenOptions = {},\n captionValue,\n unwrappedArray = ko.utils.unwrapObservable(valueAccessor()),\n filteredArray,\n previousSelectedValues,\n itemUpdate = false,\n callback = setSelectionCallback,//eslint-disable-line no-use-before-define\n nestedOptionsLevel = -1;\n\n optionsText = ko.utils.unwrapObservable(allBindings.get('optionsText')) || 'text';\n optionsValue = ko.utils.unwrapObservable(allBindings.get('optionsValue')) || 'value';\n optionTitle = optionsText + 'title';\n\n if (element.multiple) {\n previousSelectedValues = ko.utils.arrayMap(\n selectedOptions(),//eslint-disable-line no-use-before-define\n ko.selectExtensions.readValue\n );\n } else {\n previousSelectedValues = element.selectedIndex >= 0 ?\n [ko.selectExtensions.readValue(element.options[element.selectedIndex])] :\n [];\n }\n\n if (unwrappedArray) {\n if (typeof unwrappedArray.length === 'undefined') { // Coerce single value into array\n unwrappedArray = [unwrappedArray];\n }\n\n // Filter out any entries marked as destroyed\n filteredArray = ko.utils.arrayFilter(unwrappedArray, function (item) {\n if (item && !item.label) {\n return false;\n }\n\n return includeDestroyed ||\n item === undefined ||\n item === null ||\n !ko.utils.unwrapObservable(item._destroy);\n });\n filteredArray.map(recursivePathBuilder, null);//eslint-disable-line no-use-before-define\n }\n\n /**\n * @param {*} option\n */\n arrayToDomNodeChildrenOptions.beforeRemove = function (option) {\n element.removeChild(option);\n };\n\n if (allBindings.has('optionsAfterRender')) {\n\n /**\n * @param {*} arrayEntry\n * @param {*} newOptions\n */\n callback = function (arrayEntry, newOptions) {\n setSelectionCallback(arrayEntry, newOptions);//eslint-disable-line no-use-before-define\n ko.dependencyDetection.ignore(\n allBindings.get('optionsAfterRender'),\n null,\n [newOptions[0],\n arrayEntry !== captionPlaceholder ? arrayEntry : undefined]\n );\n };\n }\n\n filteredArray = formatOptions(filteredArray);//eslint-disable-line no-use-before-define\n ko.utils.setDomNodeChildrenFromArrayMapping(\n element,\n filteredArray,\n optionNodeFromArray,//eslint-disable-line no-use-before-define\n arrayToDomNodeChildrenOptions,\n callback\n );\n\n ko.dependencyDetection.ignore(function () {\n var selectionChanged;\n\n if (allBindings.get('valueAllowUnset') && allBindings.has('value')) {\n // The model value is authoritative, so make sure its value is the one selected\n ko.selectExtensions.writeValue(\n element,\n ko.utils.unwrapObservable(allBindings.get('value')),\n true /* allowUnset */\n );\n } else {\n // Determine if the selection has changed as a result of updating the options list\n if (element.multiple) {\n // For a multiple-select box, compare the new selection count to the previous one\n // But if nothing was selected before, the selection can't have changed\n selectionChanged = previousSelectedValues.length &&\n selectedOptions().length < //eslint-disable-line no-use-before-define\n previousSelectedValues.length;\n } else {\n // For a single-select box, compare the current value to the previous value\n // But if nothing was selected before or nothing is selected now,\n // just look for a change in selection\n selectionChanged = previousSelectedValues.length && element.selectedIndex >= 0 ?\n ko.selectExtensions.readValue(element.options[element.selectedIndex]) !==\n previousSelectedValues[0] : previousSelectedValues.length || element.selectedIndex >= 0;\n }\n\n // Ensure consistency between model value and selected option.\n // If the dropdown was changed so that selection is no longer the same,\n // notify the value or selectedOptions binding.\n if (selectionChanged) {\n ko.utils.triggerEvent(element, 'change');\n }\n }\n });\n\n /*eslint-enable max-len, no-use-before-define*/\n\n if (previousScrollTop && Math.abs(previousScrollTop - element.scrollTop) > 20) {\n element.scrollTop = previousScrollTop;\n }\n\n /**\n * @returns {*}\n */\n function selectedOptions() {\n return ko.utils.arrayFilter(element.options, function (node) {\n return node.selected;\n });\n }\n\n /**\n * @param {*} object\n * @param {*} predicate\n * @param {*} defaultValue\n * @returns {*}\n */\n function applyToObject(object, predicate, defaultValue) {\n var predicateType = typeof predicate;\n\n if (predicateType === 'function') { // run it against the data value\n return predicate(object);\n } else if (predicateType === 'string') { // treat it as a property name on the data value\n return object[predicate];\n }\n\n return defaultValue;\n }\n\n /**\n * @param {*} obj\n */\n function recursivePathBuilder(obj) {\n\n obj[optionTitle] = (this && this[optionTitle] ? this[optionTitle] + '/' : '') + obj[optionsText].trim();\n\n if (Array.isArray(obj[optionsValue])) {\n obj[optionsValue].map(recursivePathBuilder, obj);\n }\n }\n\n /**\n * @param {Array} arrayEntry\n * @param {*} oldOptions\n * @returns {*[]}\n */\n function optionNodeFromArray(arrayEntry, oldOptions) {\n var option;\n\n if (oldOptions.length) {\n previousSelectedValues = oldOptions[0].selected ?\n [ko.selectExtensions.readValue(oldOptions[0])] : [];\n itemUpdate = true;\n }\n\n if (arrayEntry === captionPlaceholder) { // empty value, label === caption\n option = element.ownerDocument.createElement('option');\n ko.utils.setTextContent(option, allBindings.get('optionsCaption'));\n ko.selectExtensions.writeValue(option, undefined);\n } else if (typeof arrayEntry[optionsValue] === 'undefined') { // empty value === optgroup\n if (arrayEntry.__disableTmpl) {\n option = '<optgroup label=\"' + arrayEntry[optionsText] + '\"></optgroup>';\n } else {\n option = utils.template(optgroupTmpl, {\n label: arrayEntry[optionsText],\n title: arrayEntry[optionsText + 'title']\n });\n }\n option = ko.utils.parseHtmlFragment(option)[0];\n\n } else {\n option = element.ownerDocument.createElement('option');\n option.setAttribute('data-title', arrayEntry[optionsText + 'title']);\n ko.selectExtensions.writeValue(option, arrayEntry[optionsValue]);\n ko.utils.setTextContent(option, arrayEntry[optionsText]);\n }\n\n return [option];\n }\n\n /**\n * @param {*} newOptions\n */\n function setSelectionCallback(newOptions) {\n var isSelected;\n\n // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.\n // That's why we first added them without selection. Now it's time to set the selection.\n if (previousSelectedValues.length && newOptions.value) {\n isSelected = ko.utils.arrayIndexOf(\n previousSelectedValues,\n ko.selectExtensions.readValue(newOptions.value)\n ) >= 0;\n\n ko.utils.setOptionNodeSelectionState(newOptions.value, isSelected);\n\n // If this option was changed from being selected during a single-item update, notify the change\n if (itemUpdate && !isSelected) {\n ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, 'change']);\n }\n }\n }\n\n /**\n * @param {*} string\n * @param {Number} times\n * @returns {Array}\n */\n function strPad(string, times) {\n return new Array(times + 1).join(string);\n }\n\n /**\n * @param {*} options\n * @returns {Array}\n */\n function formatOptions(options) {\n var res = [];\n\n nestedOptionsLevel++;\n\n if (!nestedOptionsLevel) { // zero level\n // If caption is included, add it to the array\n if (allBindings.has('optionsCaption')) {\n captionValue = ko.utils.unwrapObservable(allBindings.get('optionsCaption'));\n // If caption value is null or undefined, don't show a caption\n if (//eslint-disable-line max-depth\n captionValue !== null &&\n captionValue !== undefined &&\n captionValue !== false\n ) {\n res.push(captionPlaceholder);\n }\n }\n }\n\n ko.utils.arrayForEach(options, function (option) {\n var value = applyToObject(option, optionsValue, option),\n label = applyToObject(option, optionsText, value) || '',\n disabled = applyToObject(option, 'disabled', false) || false,\n obj = {},\n space = '\\u2007\\u2007\\u2007';\n\n obj[optionTitle] = applyToObject(option, optionsText + 'title', value);\n\n if (disabled) {\n obj.disabled = disabled;\n }\n\n if (option.hasOwnProperty('__disableTmpl')) {\n obj.__disableTmpl = option.__disableTmpl;\n }\n\n label = label.replace(nbspRe, '').trim();\n\n if (Array.isArray(value)) {\n obj[optionsText] = strPad(' ', nestedOptionsLevel * 4) + label;\n res.push(obj);\n res = res.concat(formatOptions(value));\n } else {\n obj[optionsText] = strPad(space, nestedOptionsLevel * 2) + label;\n obj[optionsValue] = value;\n res.push(obj);\n }\n });\n nestedOptionsLevel--;\n\n return res;\n }\n }\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/collapsible.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n 'underscore',\n '../template/renderer'\n], function (ko, $, _, renderer) {\n 'use strict';\n\n var collapsible,\n defaults;\n\n defaults = {\n closeOnOuter: true,\n onTarget: false,\n openClass: '_active',\n as: '$collapsible'\n };\n\n collapsible = {\n\n /**\n * Sets 'opened' property to true.\n */\n open: function () {\n this.opened(true);\n },\n\n /**\n * Sets 'opened' property to false.\n */\n close: function () {\n this.opened(false);\n },\n\n /**\n * Toggles value of the 'opened' property.\n */\n toggle: function () {\n this.opened(!this.opened());\n }\n };\n\n /**\n * Document click handler which in case if event target is not\n * a descendant of provided container element, closes collapsible model.\n *\n * @param {HTMLElement} container\n * @param {Object} model\n * @param {EventObject} e\n */\n function onOuterClick(container, model, e) {\n var target = e.target;\n\n if (target !== container && !container.contains(target)) {\n model.close();\n }\n }\n\n /**\n * Creates 'css' binding which toggles\n * class specified in 'name' parameter.\n *\n * @param {Object} model\n * @param {String} name\n * @returns {Object}\n */\n function getClassBinding(model, name) {\n var binding = {};\n\n binding[name] = model.opened;\n\n return {\n css: binding\n };\n }\n\n /**\n * Prepares configuration for the binding based\n * on a default properties and provided options.\n *\n * @param {Object} [options={}]\n * @returns {Object} Complete instance configuration.\n */\n function buildConfig(options) {\n if (typeof options !== 'object') {\n options = {};\n }\n\n return _.extend({}, defaults, options);\n }\n\n ko.bindingHandlers.collapsible = {\n\n /**\n * Initializes 'collapsible' binding.\n */\n init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n var $collapsible = Object.create(collapsible),\n config = buildConfig(valueAccessor()),\n outerClick,\n bindings;\n\n _.bindAll($collapsible, 'open', 'close', 'toggle');\n\n $collapsible.opened = ko.observable(!!config.opened);\n\n bindingCtx[config.as] = $collapsible;\n\n if (config.closeOnOuter) {\n outerClick = onOuterClick.bind(null, element, $collapsible);\n\n $(document).on('click', outerClick);\n\n ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n $(document).off('click', outerClick);\n });\n }\n\n if (config.openClass) {\n bindings = getClassBinding($collapsible, config.openClass);\n\n ko.applyBindingsToNode(element, bindings, bindingCtx);\n }\n\n if (config.onTarget) {\n $(element).on('click', $collapsible.toggle);\n }\n\n if (viewModel && _.isFunction(viewModel.on)) {\n viewModel.on({\n close: $collapsible.close,\n open: $collapsible.open,\n toggleOpened: $collapsible.toggle\n });\n }\n }\n };\n\n ko.bindingHandlers.closeCollapsible = {\n\n /**\n * Creates listener for the click event on provided DOM element,\n * which closes associated with it collapsible model.\n */\n init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n var name = valueAccessor() || defaults.as,\n $collapsible = bindingCtx[name];\n\n if ($collapsible) {\n $(element).on('click', $collapsible.close);\n }\n }\n };\n\n ko.bindingHandlers.openCollapsible = {\n\n /**\n * Creates listener for the click event on provided DOM element,\n * which opens associated with it collapsible model.\n */\n init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n var name = valueAccessor() || defaults.as,\n $collapsible = bindingCtx[name];\n\n if ($collapsible) {\n $(element).on('click', $collapsible.open);\n }\n }\n };\n\n ko.bindingHandlers.toggleCollapsible = {\n\n /**\n * Creates listener for the click event on provided DOM element,\n * which toggles associated with it collapsible model.\n */\n init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n var name = valueAccessor() || defaults.as,\n $collapsible = bindingCtx[name];\n\n if ($collapsible) {\n $(element).on('click', $collapsible.toggle);\n }\n }\n };\n\n renderer\n .addAttribute('collapsible')\n .addAttribute('openCollapsible')\n .addAttribute('closeCollapsible')\n .addAttribute('toggleCollapsible');\n});\n","Magento_Ui/js/lib/knockout/bindings/i18n.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko',\n 'module',\n '../template/renderer',\n 'mage/translate'\n], function ($, ko, module, renderer) {\n 'use strict';\n\n var locations = {\n 'legend': 'Caption for the fieldset element',\n 'label': 'Label for an input element.',\n 'button': 'Push button',\n 'a': 'Link label',\n 'b': 'Bold text',\n 'strong': 'Strong emphasized text',\n 'i': 'Italic text',\n 'em': 'Emphasized text',\n 'u': 'Underlined text',\n 'sup': 'Superscript text',\n 'sub': 'Subscript text',\n 'span': 'Span element',\n 'small': 'Smaller text',\n 'big': 'Bigger text',\n 'address': 'Contact information',\n 'blockquote': 'Long quotation',\n 'q': 'Short quotation',\n 'cite': 'Citation',\n 'caption': 'Table caption',\n 'abbr': 'Abbreviated phrase',\n 'acronym': 'An acronym',\n 'var': 'Variable part of a text',\n 'dfn': 'Term',\n 'strike': 'Strikethrough text',\n 'del': 'Deleted text',\n 'ins': 'Inserted text',\n 'h1': 'Heading level 1',\n 'h2': 'Heading level 2',\n 'h3': 'Heading level 3',\n 'h4': 'Heading level 4',\n 'h5': 'Heading level 5',\n 'h6': 'Heading level 6',\n 'center': 'Centered text',\n 'select': 'List options',\n 'img': 'Image',\n 'input': 'Form element'\n },\n\n /**\n * Generates [data-translate] attribute's value\n * @param {Object} translationData\n * @param {String} location\n */\n composeTranslateAttr = function (translationData, location) {\n var obj = [{\n 'shown': translationData.shown,\n 'translated': translationData.translated,\n 'original': translationData.original,\n 'location': locations[location] || 'Text'\n }];\n\n return JSON.stringify(obj);\n },\n\n /**\n * Sets text for the element\n * @param {Object} el\n * @param {String} text\n */\n setText = function (el, text) {\n $(el).text(text);\n },\n\n /**\n * Sets [data-translate] attribute for the element\n * @param {Object} el - The element which is binded\n * @param {String} original - The original value of the element\n */\n setTranslateProp = function (el, original) {\n var location = $(el).prop('tagName').toLowerCase(),\n translated = $.mage.__(original),\n translationData = {\n shown: translated,\n translated: translated,\n original: original\n },\n translateAttr = composeTranslateAttr(translationData, location);\n\n $(el).attr('data-translate', translateAttr);\n\n setText(el, translationData.shown);\n },\n\n /**\n * Checks if node represents ko virtual node (nodeType === 8, nodeName === '#comment').\n *\n * @param {HTMLElement} node\n * @returns {Boolean}\n */\n isVirtualElement = function (node) {\n return node.nodeType === 8;\n },\n\n /**\n * Checks if it's real DOM element\n * in case of virtual element, returns span wrapper\n * @param {Object} el\n * @param {bool} isUpdate\n * @return {Object} el\n */\n getRealElement = function (el, isUpdate) {\n if (isVirtualElement(el)) {\n if (isUpdate) {\n return $(el).next('span');\n }\n\n return $('<span></span>').insertAfter(el);\n }\n\n return el;\n },\n\n /**\n * execute i18n binding\n * @param {Object} element\n * @param {Function} valueAccessor\n * @param {bool} isUpdate\n */\n execute = function (element, valueAccessor, isUpdate) {\n var original = ko.unwrap(valueAccessor() || ''),\n el = getRealElement(element, isUpdate),\n inlineTranslation = (module.config() || {}).inlineTranslation;\n\n if (inlineTranslation) {\n setTranslateProp(el, original);\n } else {\n setText(el, $.mage.__(original));\n }\n };\n\n /**\n * i18n binding\n * @property {Function} init\n * @property {Function} update\n */\n ko.bindingHandlers.i18n = {\n\n /**\n * init i18n binding\n * @param {Object} element\n * @param {Function} valueAccessor\n */\n init: function (element, valueAccessor) {\n execute(element, valueAccessor);\n },\n\n /**\n * update i18n binding\n * @param {Object} element\n * @param {Function} valueAccessor\n */\n update: function (element, valueAccessor) {\n execute(element, valueAccessor, true);\n }\n };\n\n ko.virtualElements.allowedBindings.i18n = true;\n\n renderer\n .addNode('translate', {\n binding: 'i18n'\n })\n .addAttribute('translate', {\n binding: 'i18n'\n });\n});\n","Magento_Ui/js/lib/knockout/bindings/resizable.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n 'Magento_Ui/js/lib/view/utils/async',\n 'uiRegistry',\n 'underscore',\n '../template/renderer'\n], function (ko, $, async, registry, _, renderer) {\n 'use strict';\n\n var sizeOptions = [\n 'minHeight',\n 'maxHeight',\n 'minWidth',\n 'maxWidth'\n ],\n\n handles = {\n height: '.ui-resizable-s, .ui-resizable-n',\n width: '.ui-resizable-w, .ui-resizable-e'\n };\n\n /**\n * Recalcs visibility of handles, width and height of resizable based on content\n * @param {HTMLElement} element\n */\n function adjustSize(element) {\n var maxHeight,\n maxWidth;\n\n element = $(element);\n maxHeight = element.resizable('option').maxHeight;\n maxWidth = element.resizable('option').maxWidth;\n\n if (maxHeight && element.height() > maxHeight) {\n element.height(maxHeight + 1);\n $(handles.height).hide();\n } else {\n $(handles.height).show();\n }\n\n if (maxWidth && element.width() > maxWidth) {\n element.width(maxWidth + 1);\n $(handles.width).hide();\n } else {\n $(handles.width).show();\n }\n }\n\n /**\n * Recalcs allowed min, max width and height based on configured selectors\n * @param {Object} sizeConstraints\n * @param {String} componentName\n * @param {HTMLElement} element\n * @param {Boolean} hasWidthUpdate\n */\n function recalcAllowedSize(sizeConstraints, componentName, element, hasWidthUpdate) {\n var size;\n\n element = $(element);\n\n if (!element.data('resizable')) {\n return;\n }\n\n if (!hasWidthUpdate) {\n element.css('width', 'auto');\n }\n\n _.each(sizeConstraints, function (selector, key) {\n async.async({\n component: componentName,\n selector: selector\n }, function (elem) {\n size = key.indexOf('Height') !== -1 ? $(elem).outerHeight(true) : $(elem).outerWidth(true);\n\n if (element.data('resizable')) {\n element.resizable('option', key, size + 1);\n }\n });\n }, this);\n\n adjustSize(element);\n }\n\n /**\n * Preprocess config to separate options,\n * which must be processed further before applying\n *\n * @param {Object} config\n * @param {Object} viewModel\n * @param {*} element\n * @return {Object} config\n */\n function processConfig(config, viewModel, element) {\n var sizeConstraint,\n sizeConstraints = {},\n recalc,\n hasWidthUpdate;\n\n if (_.isEmpty(config)) {\n return {};\n }\n _.each(sizeOptions, function (key) {\n sizeConstraint = config[key];\n\n if (sizeConstraint && !_.isNumber(sizeConstraint)) {\n sizeConstraints[key] = sizeConstraint;\n delete config[key];\n }\n });\n hasWidthUpdate = _.some(sizeConstraints, function (value, key) {\n return key.indexOf('Width') !== -1;\n });\n\n recalc = recalcAllowedSize.bind(null, sizeConstraints, viewModel.name, element, hasWidthUpdate);\n config.start = recalc;\n $(window).on('resize.resizable', recalc);\n registry.get(viewModel.provider).on('reloaded', recalc);\n\n return config;\n }\n\n ko.bindingHandlers.resizable = {\n\n /**\n * Binding init callback.\n *\n * @param {*} element\n * @param {Function} valueAccessor\n * @param {Function} allBindings\n * @param {Object} viewModel\n */\n init: function (element, valueAccessor, allBindings, viewModel) {\n var config = processConfig(valueAccessor(), viewModel, element);\n\n require(['jquery-ui-modules/resizable'], function () {\n if ($.fn.resizable) {\n $(element).resizable(config);\n }\n });\n }\n };\n\n renderer.addAttribute('resizable');\n});\n","Magento_Ui/js/lib/knockout/bindings/mage-init.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'underscore',\n 'mage/apply/main'\n], function (ko, _, mage) {\n 'use strict';\n\n ko.bindingHandlers.mageInit = {\n /**\n * Initializes components assigned to HTML elements.\n *\n * @param {HTMLElement} el\n * @param {Function} valueAccessor\n */\n init: function (el, valueAccessor) {\n var data = valueAccessor();\n\n _.each(data, function (config, component) {\n mage.applyFor(el, config, component);\n });\n }\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/staticChecked.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n '../template/renderer'\n], function (ko, renderer) {\n 'use strict';\n\n ko.bindingHandlers.staticChecked = {\n 'after': ['value', 'attr'],\n\n /**\n * Implements same functionality as a standard 'checked' binding,\n * but with a difference that it wont' change values array if\n * value of DOM element changes.\n */\n init: function (element, valueAccessor, allBindings) {\n var isCheckbox = element.type === 'checkbox',\n isRadio = element.type === 'radio',\n isValueArray,\n oldElemValue,\n useCheckedValue,\n checkedValue,\n updateModel,\n updateView;\n\n if (!isCheckbox && !isRadio) {\n return;\n }\n\n checkedValue = ko.pureComputed(function () {\n if (allBindings.has('checkedValue')) {\n return ko.utils.unwrapObservable(allBindings.get('checkedValue'));\n } else if (allBindings.has('value')) {\n return ko.utils.unwrapObservable(allBindings.get('value'));\n }\n\n return element.value;\n });\n\n isValueArray = isCheckbox && ko.utils.unwrapObservable(valueAccessor()) instanceof Array;\n oldElemValue = isValueArray ? checkedValue() : undefined;\n useCheckedValue = isRadio || isValueArray;\n\n /**\n * Updates values array if it's necessary.\n */\n updateModel = function () {\n var isChecked = element.checked,\n elemValue = useCheckedValue ? checkedValue() : isChecked,\n modelValue;\n\n if (ko.computedContext.isInitial()) {\n return;\n }\n\n if (isRadio && !isChecked) {\n return;\n }\n\n modelValue = ko.dependencyDetection.ignore(valueAccessor);\n\n if (isValueArray) {\n if (oldElemValue !== elemValue) {\n oldElemValue = elemValue;\n } else {\n ko.utils.addOrRemoveItem(modelValue, elemValue, isChecked);\n }\n } else {\n ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'checked', elemValue, true);\n }\n };\n\n /**\n * Updates checkbox state.\n */\n updateView = function () {\n var modelValue = ko.utils.unwrapObservable(valueAccessor());\n\n if (isValueArray) {\n element.checked = ko.utils.arrayIndexOf(modelValue, checkedValue()) >= 0;\n } else if (isCheckbox) {\n element.checked = modelValue;\n } else {\n element.checked = checkedValue() === modelValue;\n }\n };\n\n ko.computed(updateModel, null, {\n disposeWhenNodeIsRemoved: element\n });\n\n ko.utils.registerEventHandler(element, 'click', updateModel);\n\n ko.computed(updateView, null, {\n disposeWhenNodeIsRemoved: element\n });\n }\n };\n\n ko.expressionRewriting._twoWayBindings.staticChecked = true;\n\n renderer.addAttribute('staticChecked');\n});\n","Magento_Ui/js/lib/knockout/bindings/after-render.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n '../template/renderer'\n], function (ko, renderer) {\n 'use strict';\n\n ko.bindingHandlers.afterRender = {\n\n /**\n * Binding init callback.\n */\n init: function (element, valueAccessor, allBindings, viewModel) {\n var callback = valueAccessor();\n\n if (typeof callback === 'function') {\n callback.call(viewModel, element, viewModel);\n }\n }\n };\n\n renderer.addAttribute('afterRender');\n});\n","Magento_Ui/js/lib/knockout/bindings/fadeVisible.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko'\n], function ($, ko) {\n 'use strict';\n\n ko.bindingHandlers.fadeVisible = {\n /**\n * Initially set the element to be instantly visible/hidden depending on the value.\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n */\n init: function (element, valueAccessor) {\n var value = valueAccessor();\n\n // Use \"unwrapObservable\" so we can handle values that may or may not be observable\n $(element).toggle(ko.unwrap(value));\n },\n\n /**\n * Whenever the value subsequently changes, slowly fade the element in or out.\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n */\n update: function (element, valueAccessor) {\n var value = valueAccessor();\n\n ko.unwrap(value) ? $(element).fadeIn() : $(element).fadeOut();\n }\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/bootstrap.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(function (require) {\n 'use strict';\n\n var renderer = require('../template/renderer');\n\n renderer.addAttribute('repeat', renderer.handlers.wrapAttribute);\n\n renderer.addAttribute('outerfasteach', {\n binding: 'fastForEach',\n handler: renderer.handlers.wrapAttribute\n });\n\n renderer\n .addNode('repeat')\n .addNode('fastForEach');\n\n return {\n resizable: require('./resizable'),\n i18n: require('./i18n'),\n scope: require('./scope'),\n range: require('./range'),\n mageInit: require('./mage-init'),\n keyboard: require('./keyboard'),\n optgroup: require('./optgroup'),\n afterRender: require('./after-render'),\n autoselect: require('./autoselect'),\n datepicker: require('./datepicker'),\n outerClick: require('./outer_click'),\n fadeVisible: require('./fadeVisible'),\n collapsible: require('./collapsible'),\n staticChecked: require('./staticChecked'),\n simpleChecked: require('./simple-checked'),\n bindHtml: require('./bind-html'),\n tooltip: require('./tooltip'),\n repeat: require('knockoutjs/knockout-repeat'),\n fastForEach: require('knockoutjs/knockout-fast-foreach'),\n colorPicker: require('./color-picker')\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/outer_click.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Creates outerClick binding and registers in to ko.bindingHandlers object */\ndefine([\n 'ko',\n 'jquery',\n 'underscore',\n '../template/renderer'\n], function (ko, $, _, renderer) {\n 'use strict';\n\n var defaults = {\n onlyIfVisible: true\n };\n\n /**\n * Checks if element sis visible.\n *\n * @param {Element} el\n * @returns {Boolean}\n */\n function isVisible(el) {\n var style = window.getComputedStyle(el),\n visibility = {\n display: 'none',\n visibility: 'hidden',\n opacity: '0'\n },\n visible = true;\n\n _.each(visibility, function (val, key) {\n if (style[key] === val) {\n visible = false;\n }\n });\n\n return visible;\n }\n\n /**\n * Document click handler which in case if event target is not\n * a descendant of provided container element,\n * invokes specified in configuration callback.\n *\n * @param {HTMLElement} container\n * @param {Object} config\n * @param {EventObject} e\n */\n function onOuterClick(container, config, e) {\n var target = e.target,\n callback = config.callback;\n\n if (container === target || container.contains(target)) {\n return;\n }\n\n if (config.onlyIfVisible) {\n if (!_.isNull(container.offsetParent) && isVisible(container)) {\n callback();\n }\n } else {\n callback();\n }\n }\n\n /**\n * Prepares configuration for the binding based\n * on a default properties and provided options.\n *\n * @param {(Object|Function)} [options={}]\n * @returns {Object}\n */\n function buildConfig(options) {\n var config = {};\n\n if (_.isFunction(options)) {\n options = {\n callback: options\n };\n } else if (!_.isObject(options)) {\n options = {};\n }\n\n return _.extend(config, defaults, options);\n }\n\n ko.bindingHandlers.outerClick = {\n\n /**\n * Initializes outer click binding.\n */\n init: function (element, valueAccessor) {\n var config = buildConfig(valueAccessor()),\n outerClick = onOuterClick.bind(null, element, config),\n isTouchDevice = typeof document.ontouchstart !== 'undefined';\n\n if (isTouchDevice) {\n $(document).on('touchstart', outerClick);\n\n ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n $(document).off('touchstart', outerClick);\n });\n } else {\n $(document).on('click', outerClick);\n\n ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n $(document).off('click', outerClick);\n });\n }\n }\n };\n\n renderer.addAttribute('outerClick');\n});\n","Magento_Ui/js/lib/knockout/bindings/keyboard.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n '../template/renderer'\n], function (ko, renderer) {\n 'use strict';\n\n ko.bindingHandlers.keyboard = {\n\n /**\n * Attaches keypress handlers to element\n * @param {HTMLElement} el - Element, that binding is applied to\n * @param {Function} valueAccessor - Function that returns value, passed to binding\n * @param {Object} allBindings - all bindings object\n * @param {Object} viewModel - reference to viewmodel\n */\n init: function (el, valueAccessor, allBindings, viewModel) {\n var map = valueAccessor();\n\n ko.utils.registerEventHandler(el, 'keyup', function (e) {\n var callback = map[e.keyCode];\n\n if (callback) {\n return callback.call(viewModel, e);\n }\n });\n }\n };\n\n renderer.addAttribute('keyboard');\n});\n","Magento_Ui/js/lib/knockout/bindings/range.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'jquery',\n 'underscore',\n '../template/renderer'\n], function (ko, $, _, renderer) {\n 'use strict';\n\n var isTouchDevice = !_.isUndefined(document.ontouchstart),\n sliderFn = 'slider',\n sliderModule = 'jquery-ui-modules/slider';\n\n if (isTouchDevice) {\n sliderFn = 'touchSlider';\n sliderModule = 'mage/touch-slider';\n }\n\n ko.bindingHandlers.range = {\n\n /**\n * Initializes binding and a slider update.\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n */\n init: function (element, valueAccessor) {\n var config = valueAccessor(),\n value = config.value;\n\n _.extend(config, {\n value: value(),\n\n /**\n * Callback which is being called when sliders' value changes.\n *\n * @param {Event} event\n * @param {Object} ui\n */\n slide: function (event, ui) {\n value(ui.value);\n }\n });\n\n require([sliderModule], function () {\n $(element)[sliderFn](config);\n });\n },\n\n /**\n * Updates sliders' plugin configuration.\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n */\n update: function (element, valueAccessor) {\n var config = valueAccessor();\n\n config.value = ko.unwrap(config.value);\n\n require([sliderModule], function () {\n $(element)[sliderFn]('option', config);\n });\n }\n };\n\n renderer.addAttribute('range');\n});\n","Magento_Ui/js/lib/knockout/bindings/scope.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Creates scope binding and registers in to ko.bindingHandlers object */\ndefine([\n 'ko',\n 'uiRegistry',\n 'mage/translate',\n '../template/renderer',\n 'jquery',\n '../../logger/console-logger'\n], function (ko, registry, $t, renderer, $, consoleLogger) {\n 'use strict';\n\n /**\n * Creates child context with passed component param as $data. Extends context with $t helper.\n * Applies bindings to descendant nodes.\n * @param {HTMLElement} el - element to apply bindings to.\n * @param {ko.bindingContext} bindingContext - instance of ko.bindingContext, passed to binding initially.\n * @param {Promise} promise - instance of jQuery promise\n * @param {Object} component - component instance to attach to new context\n */\n function applyComponents(el, bindingContext, promise, component) {\n promise.resolve();\n component = bindingContext.createChildContext(component);\n\n ko.utils.extend(component, {\n $t: $t\n });\n\n ko.utils.arrayForEach(ko.virtualElements.childNodes(el), ko.cleanNode);\n\n ko.applyBindingsToDescendants(component, el);\n }\n\n ko.bindingHandlers.scope = {\n\n /**\n * Scope binding's init method.\n * @returns {Object} - Knockout declaration for it to let binding control descendants.\n */\n init: function () {\n return {\n controlsDescendantBindings: true\n };\n },\n\n /**\n * Reads params passed to binding, parses component declarations.\n * Fetches for those found and attaches them to the new context.\n * @param {HTMLElement} el - Element to apply bindings to.\n * @param {Function} valueAccessor - Function that returns value, passed to binding.\n * @param {Object} allBindings - Object, which represents all bindings applied to element.\n * @param {Object} viewModel - Object, which represents view model binded to el.\n * @param {ko.bindingContext} bindingContext - Instance of ko.bindingContext, passed to binding initially.\n */\n update: function (el, valueAccessor, allBindings, viewModel, bindingContext) {\n var component = valueAccessor(),\n promise = $.Deferred(),\n apply = applyComponents.bind(this, el, bindingContext, promise),\n loggerUtils = consoleLogger.utils;\n\n if (typeof component === 'string') {\n loggerUtils.asyncLog(\n promise,\n {\n data: {\n component: component\n },\n messages: loggerUtils.createMessages(\n 'requestingComponent',\n 'requestingComponentIsLoaded',\n 'requestingComponentIsFailed'\n )\n }\n );\n\n registry.get(component, apply);\n } else if (typeof component === 'function') {\n component(apply);\n }\n }\n };\n\n ko.virtualElements.allowedBindings.scope = true;\n\n renderer\n .addNode('scope')\n .addAttribute('scope', {\n name: 'ko-scope'\n });\n});\n","Magento_Ui/js/lib/knockout/bindings/datepicker.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Creates datepicker binding and registers in to ko.bindingHandlers object */\ndefine([\n 'ko',\n 'underscore',\n 'jquery',\n 'mage/translate'\n], function (ko, _, $, $t) {\n 'use strict';\n\n var defaults = {\n dateFormat: 'mm\\/dd\\/yyyy',\n showsTime: false,\n timeFormat: null,\n buttonImage: null,\n buttonImageOnly: null,\n buttonText: $t('Select Date')\n };\n\n ko.bindingHandlers.datepicker = {\n /**\n * Initializes calendar widget on element and stores it's value to observable property.\n * Datepicker binding takes either observable property or object\n * { storage: {ko.observable}, options: {Object} }.\n * For more info about options take a look at \"mage/calendar\" and jquery.ui.datepicker widget.\n * @param {HTMLElement} el - Element, that binding is applied to\n * @param {Function} valueAccessor - Function that returns value, passed to binding\n * @param {object} allBindings\n * @param {object} viewModel\n * @param {object} bindingContext\n */\n init: function (el, valueAccessor, allBindings, viewModel, bindingContext) {\n var config = valueAccessor(),\n observable,\n options = {};\n\n _.extend(options, defaults);\n\n if (typeof config === 'object') {\n observable = config.storage;\n _.extend(options, config.options);\n } else {\n observable = config;\n }\n\n require(['mage/calendar'], function () {\n $(el).calendar(options);\n\n ko.utils.registerEventHandler(el, 'change', function () {\n observable(this.value);\n });\n });\n\n if (bindingContext.$data) {\n bindingContext.$data.value.subscribe(function (newVal) {\n if (!newVal) {\n $(el).val('');\n }\n }, this);\n }\n\n\n },\n\n /**\n * Update calendar widget on element and stores it's value to observable property.\n * Datepicker binding takes either observable property or object\n * { storage: {ko.observable}, options: {Object} }.\n * @param {HTMLElement} element - Element, that binding is applied to\n * @param {Function} valueAccessor - Function that returns value, passed to binding\n */\n update: function (element, valueAccessor) {\n var config = valueAccessor(),\n $element = $(element),\n observable,\n options = {},\n newVal;\n\n _.extend(options, defaults);\n\n if (typeof config === 'object') {\n observable = config.storage;\n _.extend(options, config.options);\n } else {\n observable = config;\n }\n\n require(['moment', 'mage/utils/misc', 'mage/calendar'], function (moment, utils) {\n if (_.isEmpty(observable())) {\n newVal = null;\n } else {\n newVal = moment(\n observable(),\n utils.convertToMomentFormat(\n options.dateFormat + (options.showsTime ? ' ' + options.timeFormat : '')\n )\n ).toDate();\n }\n\n if (!options.timeOnly) {\n $element.datepicker('setDate', newVal);\n $element.trigger('blur');\n }\n });\n }\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/bind-html.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'underscore',\n 'mage/apply/main',\n '../template/renderer'\n], function (ko, _, mage, renderer) {\n 'use strict';\n\n /**\n * Set html to node element.\n *\n * @param {HTMLElement} el - Element to apply bindings to.\n * @param {Function} html - Observable html content.\n */\n function setHtml(el, html) {\n ko.utils.emptyDomNode(el);\n html = ko.utils.unwrapObservable(html);\n\n if (!_.isNull(html) && !_.isUndefined(html)) {\n if (!_.isString(html)) {\n html = html.toString();\n }\n\n el.innerHTML = html;\n }\n }\n\n /**\n * Apply bindings and call magento attributes parser.\n *\n * @param {HTMLElement} el - Element to apply bindings to.\n * @param {ko.bindingContext} ctx - Instance of ko.bindingContext, passed to binding initially.\n */\n function applyComponents(el, ctx) {\n ko.utils.arrayForEach(el.childNodes, ko.cleanNode);\n ko.applyBindingsToDescendants(ctx, el);\n mage.apply();\n }\n\n ko.bindingHandlers.bindHtml = {\n /**\n * Scope binding's init method.\n *\n * @returns {Object} - Knockout declaration for it to let binding control descendants.\n */\n init: function () {\n return {\n controlsDescendantBindings: true\n };\n },\n\n /**\n * Reads params passed to binding.\n * Set html to node element, apply bindings and call magento attributes parser.\n *\n * @param {HTMLElement} el - Element to apply bindings to.\n * @param {Function} valueAccessor - Function that returns value, passed to binding.\n * @param {Object} allBindings - Object, which represents all bindings applied to element.\n * @param {Object} viewModel - Object, which represents view model binded to el.\n * @param {ko.bindingContext} bindingContext - Instance of ko.bindingContext, passed to binding initially.\n */\n update: function (el, valueAccessor, allBindings, viewModel, bindingContext) {\n setHtml(el, valueAccessor());\n applyComponents(el, bindingContext);\n }\n };\n\n renderer.addAttribute('bindHtml');\n});\n","Magento_Ui/js/lib/knockout/bindings/color-picker.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n '../template/renderer',\n 'spectrum',\n 'tinycolor'\n], function (ko, $, renderer, spectrum, tinycolor) {\n 'use strict';\n\n /**\n * Change color picker status to be enabled or disabled\n *\n * @param {HTMLElement} element - Element to apply colorpicker enable/disable status to.\n * @param {Object} viewModel - Object, which represents view model binded to el.\n */\n function changeColorPickerStateBasedOnViewModel(element, viewModel) {\n $(element).spectrum(viewModel.disabled() ? 'disable' : 'enable');\n }\n\n ko.bindingHandlers.colorPicker = {\n /**\n * Binding init callback.\n *\n * @param {*} element\n * @param {Function} valueAccessor\n * @param {Function} allBindings\n * @param {Object} viewModel\n */\n init: function (element, valueAccessor, allBindings, viewModel) {\n var config = valueAccessor(),\n\n /** change value */\n changeValue = function (value) {\n if (value == null) {\n value = '';\n }\n config.value(value.toString());\n };\n\n config.change = changeValue;\n\n config.hide = changeValue;\n\n /** show value */\n config.show = function () {\n if (!viewModel.focused()) {\n viewModel.focused(true);\n }\n\n return true;\n };\n\n $(element).spectrum(config);\n\n changeColorPickerStateBasedOnViewModel(element, viewModel);\n },\n\n /**\n * Reads params passed to binding, parses component declarations.\n * Fetches for those found and attaches them to the new context.\n *\n * @param {HTMLElement} element - Element to apply bindings to.\n * @param {Function} valueAccessor - Function that returns value, passed to binding.\n * @param {Object} allBindings - Object, which represents all bindings applied to element.\n * @param {Object} viewModel - Object, which represents view model binded to element.\n */\n update: function (element, valueAccessor, allBindings, viewModel) {\n var config = valueAccessor();\n\n /** Initialise value as empty if it is undefined when color picker input is reset **/\n if (config.value() === undefined) {\n config.value('');\n }\n\n if (tinycolor(config.value()).isValid() || config.value() === '') {\n $(element).spectrum('set', config.value());\n\n if (config.value() !== '') {\n config.value($(element).spectrum('get').toString());\n }\n }\n\n changeColorPickerStateBasedOnViewModel(element, viewModel);\n }\n };\n\n renderer.addAttribute('colorPicker');\n});\n","Magento_Ui/js/lib/knockout/template/renderer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'underscore',\n './loader'\n], function ($, _, loader) {\n 'use strict';\n\n var colonReg = /\\\\:/g,\n renderedTemplatePromises = {},\n attributes = {},\n elements = {},\n globals = [],\n renderer,\n preset;\n\n renderer = {\n\n /**\n * Loads template by provided path and\n * than converts it's content to html.\n *\n * @param {String} tmplPath - Path to the template.\n * @returns {jQueryPromise}\n * @alias getRendered\n */\n render: function (tmplPath) {\n var cachedPromise = renderedTemplatePromises[tmplPath];\n\n if (!cachedPromise) {\n cachedPromise = renderedTemplatePromises[tmplPath] = loader\n .loadTemplate(tmplPath)\n .then(renderer.parseTemplate);\n }\n\n return cachedPromise;\n },\n\n /**\n * @ignore\n */\n getRendered: function (tmplPath) {\n return renderer.render(tmplPath);\n },\n\n /**\n * Parses provided string as html content\n * and returns an array of DOM elements.\n *\n * @param {String} html - String to be processed.\n * @returns {Array}\n */\n parseTemplate: function (html) {\n var fragment = document.createDocumentFragment();\n\n $(fragment).append(html);\n\n return renderer.normalize(fragment);\n },\n\n /**\n * Processes custom attributes and nodes of provided DOM element.\n *\n * @param {HTMLElement} content - Element to be processed.\n * @returns {Array} An array of content's child nodes.\n */\n normalize: function (content) {\n globals.forEach(function (handler) {\n handler(content);\n });\n\n return _.toArray(content.childNodes);\n },\n\n /**\n * Adds new global content handler.\n *\n * @param {Function} handler - Function which will be invoked for\n * an every content passed to 'normalize' method.\n * @returns {Renderer} Chainable.\n */\n addGlobal: function (handler) {\n if (!_.contains(globals, handler)) {\n globals.push(handler);\n }\n\n return this;\n },\n\n /**\n * Removes specified global content handler.\n *\n * @param {Function} handler - Handler to be removed.\n * @returns {Renderer} Chainable.\n */\n removeGlobal: function (handler) {\n var index = globals.indexOf(handler);\n\n if (~index) {\n globals.splice(index, 1);\n }\n\n return this;\n },\n\n /**\n * Adds new custom attribute handler.\n *\n * @param {String} id - Attribute identifier.\n * @param {(Object|Function)} [config={}]\n * @returns {Renderer} Chainable.\n */\n addAttribute: function (id, config) {\n var data = {\n name: id,\n binding: id,\n handler: renderer.handlers.attribute\n };\n\n if (_.isFunction(config)) {\n data.handler = config;\n } else if (_.isObject(config)) {\n _.extend(data, config);\n }\n\n data.id = id;\n attributes[id] = data;\n\n return this;\n },\n\n /**\n * Removes specified attribute handler.\n *\n * @param {String} id - Attribute identifier.\n * @returns {Renderer} Chainable.\n */\n removeAttribute: function (id) {\n delete attributes[id];\n\n return this;\n },\n\n /**\n * Adds new custom node handler.\n *\n * @param {String} id - Node identifier.\n * @param {(Object|Function)} [config={}]\n * @returns {Renderer} Chainable.\n */\n addNode: function (id, config) {\n var data = {\n name: id,\n binding: id,\n handler: renderer.handlers.node\n };\n\n if (_.isFunction(config)) {\n data.handler = config;\n } else if (_.isObject(config)) {\n _.extend(data, config);\n }\n\n data.id = id;\n elements[id] = data;\n\n return this;\n },\n\n /**\n * Removes specified custom node handler.\n *\n * @param {String} id - Node identifier.\n * @returns {Renderer} Chainable.\n */\n removeNode: function (id) {\n delete elements[id];\n\n return this;\n },\n\n /**\n * Checks if provided DOM element is a custom node.\n *\n * @param {HTMLElement} node - Node to be checked.\n * @returns {Boolean}\n */\n isCustomNode: function (node) {\n return _.some(elements, function (elem) {\n return elem.name.toUpperCase() === node.tagName;\n });\n },\n\n /**\n * Processes custom attributes of a content's child nodes.\n *\n * @param {HTMLElement} content - DOM element to be processed.\n */\n processAttributes: function (content) {\n var repeat;\n\n repeat = _.some(attributes, function (attr) {\n var attrName = attr.name,\n nodes = content.querySelectorAll('[' + attrName + ']'),\n handler = attr.handler;\n\n return _.toArray(nodes).some(function (node) {\n var data = node.getAttribute(attrName);\n\n return handler(node, data, attr) === true;\n });\n });\n\n if (repeat) {\n renderer.processAttributes(content);\n }\n },\n\n /**\n * Processes custom nodes of a provided content.\n *\n * @param {HTMLElement} content - DOM element to be processed.\n */\n processNodes: function (content) {\n var repeat;\n\n repeat = _.some(elements, function (element) {\n var nodes = content.querySelectorAll(element.name),\n handler = element.handler;\n\n return _.toArray(nodes).some(function (node) {\n var data = node.getAttribute('args');\n\n return handler(node, data, element) === true;\n });\n });\n\n if (repeat) {\n renderer.processNodes(content);\n }\n },\n\n /**\n * Wraps provided string in curly braces if it's necessary.\n *\n * @param {String} args - String to be wrapped.\n * @returns {String} Wrapped string.\n */\n wrapArgs: function (args) {\n if (~args.indexOf('\\\\:')) {\n args = args.replace(colonReg, ':');\n } else if (~args.indexOf(':') && !~args.indexOf('}')) {\n args = '{' + args + '}';\n }\n\n return args;\n },\n\n /**\n * Wraps child nodes of provided DOM element\n * with knockout's comment tag.\n *\n * @param {HTMLElement} node - Node whose children should be wrapped.\n * @param {String} binding - Name of the binding for the opener comment tag.\n * @param {String} data - Data associated with a binding.\n *\n * @example\n * <div id=\"example\"><span/></div>\n * wrapChildren(document.getElementById('example'), 'foreach', 'data');\n * =>\n * <div id=\"example\">\n * <!-- ko foreach: data -->\n * <span></span>\n * <!-- /ko -->\n * </div>\n */\n wrapChildren: function (node, binding, data) {\n var tag = this.createComment(binding, data),\n $node = $(node);\n\n $node.prepend(tag.open);\n $node.append(tag.close);\n },\n\n /**\n * Wraps specified node with knockout's comment tag.\n *\n * @param {HTMLElement} node - Node to be wrapped.\n * @param {String} binding - Name of the binding for the opener comment tag.\n * @param {String} data - Data associated with a binding.\n *\n * @example\n * <div id=\"example\"></div>\n * wrapNode(document.getElementById('example'), 'foreach', 'data');\n * =>\n * <!-- ko foreach: data -->\n * <div id=\"example\"></div>\n * <!-- /ko -->\n */\n wrapNode: function (node, binding, data) {\n var tag = this.createComment(binding, data),\n $node = $(node);\n\n $node.before(tag.open);\n $node.after(tag.close);\n },\n\n /**\n * Creates knockouts' comment tag for the provided binding.\n *\n * @param {String} binding - Name of the binding.\n * @param {String} data - Data associated with a binding.\n * @returns {Object} Object with an open and close comment elements.\n */\n createComment: function (binding, data) {\n return {\n open: document.createComment(' ko ' + binding + ': ' + data + ' '),\n close: document.createComment(' /ko ')\n };\n }\n };\n\n renderer.handlers = {\n\n /**\n * Basic node handler. Replaces custom nodes\n * with a corresponding knockout's comment tag.\n *\n * @param {HTMLElement} node - Node to be processed.\n * @param {String} data\n * @param {Object} element\n * @returns {Boolean} True\n *\n * @example Sample syntaxes conversions.\n * <with args=\"model\">\n * <span/>\n * </with>\n * =>\n * <!-- ko with: model-->\n * <span/>\n * <!-- /ko -->\n */\n node: function (node, data, element) {\n data = renderer.wrapArgs(data);\n\n renderer.wrapNode(node, element.binding, data);\n $(node).replaceWith(node.childNodes);\n\n return true;\n },\n\n /**\n * Base attribute handler. Replaces custom attributes with\n * a corresponding knockouts' data binding.\n *\n * @param {HTMLElement} node - Node to be processed.\n * @param {String} data - Data associated with a binding.\n * @param {Object} attr - Attribute definition.\n *\n * @example Sample syntaxes conversions.\n * <div text=\"label\"></div>\n * =>\n * <div data-bind=\"text: label\"></div>\n */\n attribute: function (node, data, attr) {\n data = renderer.wrapArgs(data);\n\n renderer.bindings.add(node, attr.binding, data);\n node.removeAttribute(attr.name);\n },\n\n /**\n * Wraps provided node with a knockouts' comment tag.\n *\n * @param {HTMLElement} node - Node that will be wrapped.\n * @param {String} data - Data associated with a binding.\n * @param {Object} attr - Attribute definition.\n *\n * @example\n * <div outereach=\"data\" class=\"test\"></div>\n * =>\n * <!-- ko foreach: data -->\n * <div class=\"test\"></div>\n * <!-- /ko -->\n */\n wrapAttribute: function (node, data, attr) {\n data = renderer.wrapArgs(data);\n\n renderer.wrapNode(node, attr.binding, data);\n node.removeAttribute(attr.name);\n }\n };\n\n renderer.bindings = {\n\n /**\n * Appends binding string to the current\n * 'data-bind' attribute of provided node.\n *\n * @param {HTMLElement} node - DOM element whose 'data-bind' attribute will be extended.\n * @param {String} name - Name of a binding.\n * @param {String} data - Data associated with the binding.\n */\n add: function (node, name, data) {\n var bindings = this.get(node);\n\n if (bindings) {\n bindings += ', ';\n }\n\n bindings += name;\n\n if (data) {\n bindings += ': ' + data;\n }\n\n this.set(node, bindings);\n },\n\n /**\n * Extracts value of a 'data-bind' attribute from provided node.\n *\n * @param {HTMLElement} node - Node whose attribute to be extracted.\n * @returns {String}\n */\n get: function (node) {\n return node.getAttribute('data-bind') || '';\n },\n\n /**\n * Sets 'data-bind' attribute of the specified node\n * to the provided value.\n *\n * @param {HTMLElement} node - Node whose attribute will be altered.\n * @param {String} bindings - New value of 'data-bind' attribute.\n */\n set: function (node, bindings) {\n node.setAttribute('data-bind', bindings);\n }\n };\n\n renderer\n .addGlobal(renderer.processAttributes)\n .addGlobal(renderer.processNodes);\n\n /**\n * Collection of default binding conversions.\n */\n preset = {\n nodes: _.object([\n 'if',\n 'text',\n 'with',\n 'scope',\n 'ifnot',\n 'foreach',\n 'component'\n ], Array.prototype),\n attributes: _.object([\n 'css',\n 'attr',\n 'html',\n 'with',\n 'text',\n 'click',\n 'event',\n 'submit',\n 'enable',\n 'disable',\n 'options',\n 'visible',\n 'template',\n 'hasFocus',\n 'textInput',\n 'component',\n 'uniqueName',\n 'optionsText',\n 'optionsValue',\n 'checkedValue',\n 'selectedOptions'\n ], Array.prototype)\n };\n\n _.extend(preset.attributes, {\n if: renderer.handlers.wrapAttribute,\n ifnot: renderer.handlers.wrapAttribute,\n innerif: {\n binding: 'if'\n },\n innerifnot: {\n binding: 'ifnot'\n },\n outereach: {\n binding: 'foreach',\n handler: renderer.handlers.wrapAttribute\n },\n foreach: {\n name: 'each'\n },\n value: {\n name: 'ko-value'\n },\n style: {\n name: 'ko-style'\n },\n checked: {\n name: 'ko-checked'\n },\n disabled: {\n name: 'ko-disabled',\n binding: 'disable'\n },\n focused: {\n name: 'ko-focused',\n binding: 'hasFocus'\n },\n\n /**\n * Custom 'render' attribute handler function. Wraps child elements\n * of a node with knockout's 'ko template:' comment tag.\n *\n * @param {HTMLElement} node - Element to be processed.\n * @param {String} data - Data specified in 'render' attribute of a node.\n */\n render: function (node, data) {\n data = data || 'getTemplate()';\n data = renderer.wrapArgs(data);\n\n renderer.wrapChildren(node, 'template', data);\n node.removeAttribute('render');\n }\n });\n\n _.extend(preset.nodes, {\n foreach: {\n name: 'each'\n },\n\n /**\n * Custom 'render' node handler function.\n * Replaces node with knockout's 'ko template:' comment tag.\n *\n * @param {HTMLElement} node - Element to be processed.\n * @param {String} data - Data specified in 'args' attribute of a node.\n */\n render: function (node, data) {\n data = data || 'getTemplate()';\n data = renderer.wrapArgs(data);\n\n renderer.wrapNode(node, 'template', data);\n $(node).replaceWith(node.childNodes);\n }\n });\n\n _.each(preset.attributes, function (data, id) {\n renderer.addAttribute(id, data);\n });\n\n _.each(preset.nodes, function (data, id) {\n renderer.addNode(id, data);\n });\n\n return renderer;\n});\n","Magento_Ui/js/lib/knockout/template/observable_source.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * Is being used by knockout template engine to store template to.\n */\ndefine([\n 'ko',\n 'uiClass'\n], function (ko, Class) {\n 'use strict';\n\n return Class.extend({\n\n /**\n * Initializes templateName, _data, nodes properties.\n *\n * @param {template} template - identifier of template\n */\n initialize: function (template) {\n this.templateName = template;\n this._data = {};\n this.nodes = ko.observable([]);\n },\n\n /**\n * Data setter. If only one arguments passed, returns corresponding value.\n * Else, writes into it.\n * @param {String} key - key to write to or to read from\n * @param {*} value\n * @return {*} - if 1 arg provided, Returns _data[key] property\n */\n data: function (key, value) {\n if (arguments.length === 1) {\n return this._data[key];\n }\n\n this._data[key] = value;\n }\n });\n});\n","Magento_Ui/js/lib/knockout/template/loader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n var licenseRegExp = /<!--[\\s\\S]*?-->/,\n defaultPlugin = 'text',\n defaultExt = 'html';\n\n /**\n * Checks of provided string contains a file extension.\n *\n * @param {String} str - String to be checked.\n * @returns {Boolean}\n */\n function hasFileExtension(str) {\n return !!~str.indexOf('.') && !!str.split('.').pop();\n }\n\n /**\n * Checks if provided string contains a requirejs's plugin reference.\n *\n * @param {String} str - String to be checked.\n * @returns {Boolean}\n */\n function hasPlugin(str) {\n return !!~str.indexOf('!');\n }\n\n /**\n * Checks if provided string is a full path to the file.\n *\n * @param {String} str - String to be checked.\n * @returns {Boolean}\n */\n function isFullPath(str) {\n return !!~str.indexOf('://');\n }\n\n /**\n * Removes license comment from the provided string.\n *\n * @param {String} content - String to be processed.\n * @returns {String}\n */\n function removeLicense(content) {\n return content.replace(licenseRegExp, function (match) {\n return ~match.indexOf('/**') ? '' : match;\n });\n }\n\n return {\n\n /**\n * Attempts to extract template by provided path from\n * a DOM element and falls back to a file loading if\n * none of the DOM nodes was found.\n *\n * @param {String} path - Path to the template or a DOM selector.\n * @returns {jQueryPromise}\n */\n loadTemplate: function (path) {\n var content = this.loadFromNode(path),\n defer;\n\n if (content) {\n defer = $.Deferred();\n\n defer.resolve(content);\n\n return defer.promise();\n }\n\n return this.loadFromFile(path);\n },\n\n /**\n * Loads template from external file by provided\n * path, which will be preliminary formatted.\n *\n * @param {String} path - Path to the template.\n * @returns {jQueryPromise}\n */\n loadFromFile: function (path) {\n var loading = $.Deferred();\n\n path = this.formatPath(path);\n\n require([path], function (template) {\n template = removeLicense(template);\n loading.resolve(template);\n }, function (err) {\n loading.reject(err);\n });\n\n return loading.promise();\n },\n\n /**\n * Attempts to extract content of a node found by provided selector.\n *\n * @param {String} selector - Node's selector (not necessary valid).\n * @returns {String|Boolean} If specified node doesn't exists\n * 'false' will be returned, otherwise returns node's content.\n */\n loadFromNode: function (selector) {\n var node;\n\n try {\n node =\n document.getElementById(selector) ||\n document.querySelector(selector);\n\n return node ? node.innerHTML : false;\n } catch (e) {\n return false;\n }\n },\n\n /**\n * Adds requirejs's plugin and file extension to\n * to the provided string if it's necessary.\n *\n * @param {String} path - Path to be processed.\n * @returns {String} Formatted path.\n */\n formatPath: function (path) {\n var result = path;\n\n if (!hasPlugin(path)) {\n result = defaultPlugin + '!' + result;\n }\n\n if (isFullPath(path)) {\n return result;\n }\n\n if (!hasFileExtension(path)) {\n result += '.' + defaultExt;\n }\n\n return result.replace(/^([^\\/]+)/g, '$1/template');\n }\n };\n});\n","Magento_Ui/js/lib/knockout/template/engine.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'ko',\n 'underscore',\n './observable_source',\n './renderer',\n '../../logger/console-logger'\n], function ($, ko, _, Source, renderer, consoleLogger) {\n 'use strict';\n\n var RemoteTemplateEngine,\n NativeTemplateEngine = ko.nativeTemplateEngine,\n sources = {};\n\n /**\n * Remote template engine class. Is used to be able to load remote templates via knockout template binding.\n */\n RemoteTemplateEngine = function () {\n // Instance reference for closure.\n var engine = this,\n // Decorate the builtin Knockout \"template\" binding to track synchronous template renders.\n origUpdate = ko.bindingHandlers.template.update;\n\n /**\n * Counter to track the number of currently running render tasks (both synchronous and asynchronous).\n * @type {Number}\n * @private\n */\n this._rendersOutstanding = 0;\n\n /**\n * Use a jQuery object as an event bus (but any event emitter with on/off/emit methods could work)\n * @type {jQuery}\n * @private\n */\n this._events = $(this);\n\n /**\n * Rendered templates\n * @type {Object}\n * @private\n */\n this._templatesRendered = {};\n\n /*eslint-disable no-unused-vars*/\n /**\n * Decorate update method\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n * @param {Object} allBindings\n * @param {Object} viewModel\n * @param {ko.bindingContext} bindingContext\n * @returns {*}\n */\n ko.bindingHandlers.template.update = function (element, valueAccessor, allBindings, viewModel, bindingContext) {\n /*eslint-enable no-unused-vars*/\n var options = ko.utils.peekObservable(valueAccessor()),\n templateName,\n isSync,\n updated;\n\n if (typeof options === 'object') {\n if (options.templateEngine && options.templateEngine !== engine) {\n return origUpdate.apply(this, arguments);\n }\n\n if (!options.name) {\n consoleLogger.error('Could not find template name', options);\n }\n templateName = options.name;\n } else if (typeof options === 'string') {\n templateName = options;\n } else {\n consoleLogger.error('Could not build a template binding', options);\n }\n engine._trackRender(templateName);\n isSync = engine._hasTemplateLoaded(templateName);\n updated = origUpdate.apply(this, arguments);\n\n if (isSync) {\n engine._releaseRender(templateName, 'sync');\n }\n\n return updated;\n };\n };\n\n /**\n * Creates unique template identifier based on template name and it's extenders (optional)\n * @param {String} templateName\n * @return {String} - unique template identifier\n */\n function createTemplateIdentifier(templateName) {\n return templateName;\n }\n\n RemoteTemplateEngine.prototype = new NativeTemplateEngine;\n RemoteTemplateEngine.prototype.constructor = RemoteTemplateEngine;\n\n /**\n * When an asynchronous render task begins, increment the internal counter for tracking when renders are complete.\n * @private\n */\n RemoteTemplateEngine.prototype._trackRender = function (templateName) {\n var rendersForTemplate = this._templatesRendered[templateName] !== undefined ?\n this._templatesRendered[templateName] : 0;\n\n this._rendersOutstanding++;\n this._templatesRendered[templateName] = rendersForTemplate + 1;\n this._resolveRenderWaits();\n };\n\n /**\n * When an asynchronous render task ends, decrement the internal counter for tracking when renders are complete.\n * @private\n */\n RemoteTemplateEngine.prototype._releaseRender = function (templateName) {\n var rendersForTemplate = this._templatesRendered[templateName];\n\n this._rendersOutstanding--;\n this._templatesRendered[templateName] = rendersForTemplate - 1;\n this._resolveRenderWaits();\n };\n\n /**\n * Check to see if renders are complete and trigger events for listeners.\n * @private\n */\n RemoteTemplateEngine.prototype._resolveRenderWaits = function () {\n if (this._rendersOutstanding === 0) {\n this._events.triggerHandler('finishrender');\n }\n };\n\n /**\n * Get a promise for the end of the current run of renders, both sync and async.\n * @return {jQueryPromise} - promise that resolves when render completes\n */\n RemoteTemplateEngine.prototype.waitForFinishRender = function () {\n var defer = $.Deferred();\n\n this._events.one('finishrender', defer.resolve);\n\n return defer.promise();\n };\n\n /**\n * Returns true if this template has already been asynchronously loaded and will be synchronously rendered.\n * @param {String} templateName\n * @returns {Boolean}\n * @private\n */\n RemoteTemplateEngine.prototype._hasTemplateLoaded = function (templateName) {\n // Sources object will have cached template once makeTemplateSource has run\n return sources.hasOwnProperty(templateName);\n };\n\n /**\n * Overrided method of native knockout template engine.\n * Caches template after it's unique name and renders in once.\n * If template name is not typeof string, delegates work to knockout.templateSources.anonymousTemplate.\n * @param {*} template\n * @param {HTMLElement} templateDocument - document\n * @param {Object} options - options, passed to template binding\n * @param {ko.bindingContext} bindingContext\n * @returns {TemplateSource} Object with methods 'nodes' and 'data'.\n */\n RemoteTemplateEngine.prototype.makeTemplateSource = function (template, templateDocument, options, bindingContext) {\n var engine = this,\n source,\n templateId;\n\n if (typeof template === 'string') {\n templateId = createTemplateIdentifier(template);\n source = sources[templateId];\n\n if (!source) {\n source = new Source(template);\n source.requestedBy = bindingContext.$data.name;\n sources[templateId] = source;\n\n consoleLogger.info('templateStartLoading', {\n template: templateId,\n component: bindingContext.$data.name\n });\n\n renderer.render(template).then(function (rendered) {\n consoleLogger.info('templateLoadedFromServer', {\n template: templateId,\n component: bindingContext.$data.name\n });\n source.nodes(rendered);\n engine._releaseRender(templateId, 'async');\n }).fail(function () {\n consoleLogger.error('templateLoadingFail', {\n template: templateId,\n component: bindingContext.$data.name\n });\n });\n }\n\n if (source.requestedBy !== bindingContext.$data.name) {\n consoleLogger.info('templateLoadedFromCache', {\n template: templateId,\n component: bindingContext.$data.name\n });\n }\n\n return source;\n } else if (template.nodeType === 1 || template.nodeType === 8) {\n source = new ko.templateSources.anonymousTemplate(template);\n\n return source;\n }\n\n throw new Error('Unknown template type: ' + template);\n };\n\n /**\n * Overrided method of native knockout template engine.\n * Should return array of html elements.\n * @param {TemplateSource} templateSource - object with methods 'nodes' and 'data'.\n * @return {Array} - array of html elements\n */\n RemoteTemplateEngine.prototype.renderTemplateSource = function (templateSource) {\n var nodes = templateSource.nodes();\n\n return ko.utils.cloneNodes(nodes);\n };\n\n /**\n * Overrided method of native knockout template engine.\n * Created in order to invoke makeTemplateSource method with custom set of params.\n * @param {*} template - template identifier\n * @param {ko.bindingContext} bindingContext\n * @param {Object} options - options, passed to template binding\n * @param {HTMLElement} templateDocument - document\n * @return {Array} - array of html elements\n */\n RemoteTemplateEngine.prototype.renderTemplate = function (template, bindingContext, options, templateDocument) {\n var templateSource = this.makeTemplateSource(template, templateDocument, options, bindingContext);\n\n return this.renderTemplateSource(templateSource);\n };\n\n return new RemoteTemplateEngine;\n});\n","Magento_Ui/js/modal/confirm.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 'mage/translate',\n 'jquery-ui-modules/widget',\n 'Magento_Ui/js/modal/modal'\n], function ($, _, $t) {\n 'use strict';\n\n $.widget('mage.confirm', $.mage.modal, {\n options: {\n modalClass: 'confirm',\n title: '',\n focus: '.action-accept',\n actions: {\n\n /**\n * Callback always - called on all actions.\n */\n always: function () {},\n\n /**\n * Callback confirm.\n */\n confirm: function () {},\n\n /**\n * Callback cancel.\n */\n cancel: function () {}\n },\n buttons: [{\n text: $t('Cancel'),\n class: 'action-secondary action-dismiss',\n\n /**\n * Click handler.\n */\n click: function (event) {\n this.closeModal(event);\n }\n }, {\n text: $t('OK'),\n class: 'action-primary action-accept',\n\n /**\n * Click handler.\n */\n click: function (event) {\n this.closeModal(event, true);\n }\n }]\n },\n\n /**\n * Create widget.\n */\n _create: function () {\n this._super();\n this.modal.find(this.options.modalCloseBtn).off().on('click', _.bind(this.closeModal, this));\n this.openModal();\n },\n\n /**\n * Remove modal window.\n */\n _remove: function () {\n this.modal.remove();\n },\n\n /**\n * Open modal window.\n */\n openModal: function () {\n return this._super();\n },\n\n /**\n * Close modal window.\n */\n closeModal: function (event, result) {\n result = result || false;\n\n if (result) {\n this.options.actions.confirm(event);\n } else {\n this.options.actions.cancel(event);\n }\n this.options.actions.always(event);\n this.element.on('confirmclosed', _.bind(this._remove, this));\n\n return this._super();\n }\n });\n\n return function (config) {\n return $('<div></div>').html(config.content).confirm(config);\n };\n});\n","Magento_Ui/js/modal/modalToggle.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/modal'\n], function ($) {\n 'use strict';\n\n return function (config, el) {\n var widget,\n content;\n\n if (config.contentSelector) {\n content = $(config.contentSelector);\n } else if (config.content) {\n content = $('<div></div>').html(config.content);\n } else {\n content = $('<div></div>');\n }\n\n widget = content.modal(config);\n\n $(el).on(config.toggleEvent, function () {\n var state = widget.data('mage-modal').options.isOpen;\n\n if (state) {\n widget.modal('closeModal');\n } else {\n widget.modal('openModal');\n }\n\n return false;\n });\n\n return widget;\n };\n});\n","Magento_Ui/js/modal/prompt.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 'mage/template',\n 'text!ui/template/modal/modal-prompt-content.html',\n 'jquery-ui-modules/widget',\n 'Magento_Ui/js/modal/modal',\n 'mage/translate'\n], function ($, _, template, promptContentTmpl) {\n 'use strict';\n\n $.widget('mage.prompt', $.mage.modal, {\n options: {\n modalClass: 'prompt',\n promptContentTmpl: promptContentTmpl,\n promptField: '[data-role=\"promptField\"]',\n attributesForm: {},\n attributesField: {},\n value: '',\n validation: false,\n validationRules: [],\n keyEventHandlers: {\n\n /**\n * Enter key press handler,\n * submit result and close modal window\n * @param {Object} event - event\n */\n enterKey: function (event) {\n if (this.options.isOpen && this.modal.find(document.activeElement).length ||\n this.options.isOpen && this.modal[0] === document.activeElement) {\n this.closeModal(true);\n event.preventDefault();\n }\n },\n\n /**\n * Tab key press handler,\n * set focus to elements\n */\n tabKey: function () {\n if (document.activeElement === this.modal[0]) {\n this._setFocus('start');\n }\n },\n\n /**\n * Escape key press handler,\n * cancel and close modal window\n * @param {Object} event - event\n */\n escapeKey: function (event) {\n if (this.options.isOpen && this.modal.find(document.activeElement).length ||\n this.options.isOpen && this.modal[0] === document.activeElement) {\n this.closeModal();\n event.preventDefault();\n }\n }\n },\n actions: {\n\n /**\n * Callback always - called on all actions.\n */\n always: function () {},\n\n /**\n * Callback confirm.\n */\n confirm: function () {},\n\n /**\n * Callback cancel.\n */\n cancel: function () {}\n },\n buttons: [{\n text: $.mage.__('Cancel'),\n class: 'action-secondary action-dismiss',\n\n /**\n * Click handler.\n */\n click: function () {\n this.closeModal();\n }\n }, {\n text: $.mage.__('OK'),\n class: 'action-primary action-accept',\n\n /**\n * Click handler.\n */\n click: function () {\n this.closeModal(true);\n }\n }]\n },\n\n /**\n * Create widget.\n */\n _create: function () {\n this.options.focus = this.options.promptField;\n this.options.validation = this.options.validation && this.options.validationRules.length;\n this.options.outerClickHandler = this.options.outerClickHandler || _.bind(this.closeModal, this, false);\n this._super();\n this.modal.find(this.options.modalContent).append(this.getFormTemplate());\n this.modal.find(this.options.modalCloseBtn).off().on('click', _.bind(this.closeModal, this, false));\n\n if (this.options.validation) {\n this.setValidationClasses();\n }\n\n this.openModal();\n },\n\n /**\n * Form template getter.\n *\n * @returns {Object} Form template.\n */\n getFormTemplate: function () {\n var formTemplate,\n formAttr = '',\n inputAttr = '',\n attributeName;\n\n for (attributeName in this.options.attributesForm) {\n if (this.options.attributesForm.hasOwnProperty(attributeName)) {\n formAttr = formAttr + ' ' + attributeName + '=\"' +\n this.options.attributesForm[attributeName] + '\"';\n }\n }\n\n for (attributeName in this.options.attributesField) {\n if (this.options.attributesField.hasOwnProperty(attributeName)) {\n inputAttr = inputAttr + ' ' + attributeName + '=\"' +\n this.options.attributesField[attributeName] + '\"';\n }\n }\n\n formTemplate = $(template(this.options.promptContentTmpl, {\n data: this.options,\n formAttr: formAttr,\n inputAttr: inputAttr\n }));\n\n return formTemplate;\n },\n\n /**\n * Remove widget\n */\n _remove: function () {\n this.modal.remove();\n },\n\n /**\n * Validate prompt field\n */\n validate: function () {\n return $.validator.validateSingleElement(this.options.promptField);\n },\n\n /**\n * Add validation classes to prompt field\n */\n setValidationClasses: function () {\n this.modal.find(this.options.promptField).attr('class', $.proxy(function (i, val) {\n return val + ' ' + this.options.validationRules.join(' ');\n }, this));\n },\n\n /**\n * Open modal window\n */\n openModal: function () {\n this._super();\n this.modal.find(this.options.promptField).val(this.options.value);\n },\n\n /**\n * Close modal window\n */\n closeModal: function (result) {\n var value;\n\n if (result) {\n if (this.options.validation && !this.validate()) {\n return false;\n }\n\n value = this.modal.find(this.options.promptField).val();\n this.options.actions.confirm.call(this, value);\n } else {\n this.options.actions.cancel.call(this, result);\n }\n\n this.options.actions.always();\n this.element.on('promptclosed', _.bind(this._remove, this));\n\n return this._super();\n }\n });\n\n return function (config) {\n return $('<div class=\"prompt-message\"></div>').html(config.content).prompt(config);\n };\n});\n","Magento_Ui/js/modal/modal.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 'mage/template',\n 'text!ui/template/modal/modal-popup.html',\n 'text!ui/template/modal/modal-slide.html',\n 'text!ui/template/modal/modal-custom.html',\n 'Magento_Ui/js/lib/key-codes',\n 'jquery-ui-modules/widget',\n 'jquery-ui-modules/core',\n 'mage/translate',\n 'jquery/z-index'\n], function ($, _, template, popupTpl, slideTpl, customTpl, keyCodes) {\n 'use strict';\n\n /**\n * Detect browser transition end event.\n * @return {String|undefined} - transition event.\n */\n var transitionEvent = (function () {\n var transition,\n elementStyle = document.createElement('div').style,\n transitions = {\n 'transition': 'transitionend',\n 'OTransition': 'oTransitionEnd',\n 'MozTransition': 'transitionend',\n 'WebkitTransition': 'webkitTransitionEnd'\n };\n\n for (transition in transitions) {\n if (elementStyle[transition] !== undefined && transitions.hasOwnProperty(transition)) {\n return transitions[transition];\n }\n }\n })();\n\n /**\n * Modal Window Widget\n */\n $.widget('mage.modal', {\n options: {\n id: null,\n type: 'popup',\n title: '',\n subTitle: '',\n modalClass: '',\n focus: '[data-role=\"closeBtn\"]',\n autoOpen: false,\n clickableOverlay: true,\n popupTpl: popupTpl,\n slideTpl: slideTpl,\n customTpl: customTpl,\n modalVisibleClass: '_show',\n parentModalClass: '_has-modal',\n innerScrollClass: '_inner-scroll',\n responsive: false,\n innerScroll: false,\n modalTitle: '[data-role=\"title\"]',\n modalSubTitle: '[data-role=\"subTitle\"]',\n modalBlock: '[data-role=\"modal\"]',\n modalCloseBtn: '[data-role=\"closeBtn\"]',\n modalContent: '[data-role=\"content\"]',\n modalAction: '[data-role=\"action\"]',\n focusableScope: '[data-role=\"focusable-scope\"]',\n focusableStart: '[data-role=\"focusable-start\"]',\n focusableEnd: '[data-role=\"focusable-end\"]',\n appendTo: 'body',\n wrapperClass: 'modals-wrapper',\n overlayClass: 'modals-overlay',\n responsiveClass: 'modal-slide',\n trigger: '',\n modalLeftMargin: 45,\n closeText: $.mage.__('Close'),\n buttons: [{\n text: $.mage.__('Ok'),\n class: '',\n attr: {},\n\n /**\n * Default action on button click\n */\n click: function (event) {\n this.closeModal(event);\n }\n }],\n keyEventHandlers: {\n\n /**\n * Tab key press handler,\n * set focus to elements\n */\n tabKey: function () {\n if (document.activeElement === this.modal[0]) {\n this._setFocus('start');\n }\n },\n\n /**\n * Escape key press handler,\n * close modal window\n * @param {Object} event - event\n */\n escapeKey: function (event) {\n if (this.options.isOpen && this.modal.find(document.activeElement).length ||\n this.options.isOpen && this.modal[0] === document.activeElement) {\n this.closeModal(event);\n }\n }\n }\n },\n\n /**\n * Creates modal widget.\n */\n _create: function () {\n _.bindAll(\n this,\n 'keyEventSwitcher',\n '_tabSwitcher',\n 'closeModal'\n );\n\n this.options.id = this.uuid;\n this.options.transitionEvent = transitionEvent;\n this._createWrapper();\n this._renderModal();\n this._createButtons();\n\n if (this.options.trigger) {\n $(document).on('click', this.options.trigger, _.bind(this.toggleModal, this));\n }\n this._on(this.modal.find(this.options.modalCloseBtn), {\n 'click': this.options.modalCloseBtnHandler ? this.options.modalCloseBtnHandler : this.closeModal\n });\n this._on(this.element, {\n 'openModal': this.openModal,\n 'closeModal': this.closeModal\n });\n this.options.autoOpen ? this.openModal() : false;\n },\n\n /**\n * Returns element from modal node.\n * @return {Object} - element.\n */\n _getElem: function (elem) {\n return this.modal.find(elem);\n },\n\n /**\n * Gets visible modal count.\n * * @return {Number} - visible modal count.\n */\n _getVisibleCount: function () {\n var modals = this.modalWrapper.find(this.options.modalBlock);\n\n return modals.filter('.' + this.options.modalVisibleClass).length;\n },\n\n /**\n * Gets count of visible modal by slide type.\n * * @return {Number} - visible modal count.\n */\n _getVisibleSlideCount: function () {\n var elems = this.modalWrapper.find('[data-type=\"slide\"]');\n\n return elems.filter('.' + this.options.modalVisibleClass).length;\n },\n\n /**\n * Listener key events.\n * Call handler function if it exists\n */\n keyEventSwitcher: function (event) {\n var key = keyCodes[event.keyCode];\n\n if (this.options.keyEventHandlers.hasOwnProperty(key)) {\n this.options.keyEventHandlers[key].apply(this, arguments);\n }\n },\n\n /**\n * Set title for modal.\n *\n * @param {String} title\n */\n setTitle: function (title) {\n var $title = this.modal.find(this.options.modalTitle),\n $subTitle = this.modal.find(this.options.modalSubTitle);\n\n $title.text(title);\n $title.append($subTitle);\n },\n\n /**\n * Set sub title for modal.\n *\n * @param {String} subTitle\n */\n setSubTitle: function (subTitle) {\n this.options.subTitle = subTitle;\n this.modal.find(this.options.modalSubTitle).html(subTitle);\n },\n\n /**\n * Toggle modal.\n * * @return {Element} - current element.\n */\n toggleModal: function () {\n if (this.options.isOpen === true) {\n this.closeModal();\n } else {\n this.openModal();\n }\n },\n\n /**\n * Open modal.\n * * @return {Element} - current element.\n */\n openModal: function () {\n this.options.isOpen = true;\n this.focussedElement = document.activeElement;\n this._createOverlay();\n this._setActive();\n this._setKeyListener();\n this.modal.one(this.options.transitionEvent, _.bind(this._setFocus, this, 'end', 'opened'));\n this.modal.one(this.options.transitionEvent, _.bind(this._trigger, this, 'opened'));\n this.modal.addClass(this.options.modalVisibleClass);\n\n if (!this.options.transitionEvent) {\n this._trigger('opened');\n }\n\n return this.element;\n },\n\n /**\n * Set focus to element.\n * @param {String} position - can be \"start\" and \"end\"\n * positions.\n * If position is \"end\" - sets focus to first\n * focusable element in modal window scope.\n * If position is \"start\" - sets focus to last\n * focusable element in modal window scope\n *\n * @param {String} type - can be \"opened\" or false\n * If type is \"opened\" - looks to \"this.options.focus\"\n * property and sets focus\n */\n _setFocus: function (position, type) {\n var focusableElements,\n infelicity;\n\n if (type === 'opened' && this.options.focus) {\n this.modal.find($(this.options.focus)).trigger('focus');\n } else if (type === 'opened' && !this.options.focus) {\n this.modal.find(this.options.focusableScope).trigger('focus');\n } else if (position === 'end') {\n this.modal.find(this.options.modalCloseBtn).trigger('focus');\n } else if (position === 'start') {\n infelicity = 2; //Constant for find last focusable element\n focusableElements = this.modal.find(':focusable');\n focusableElements.eq(focusableElements.length - infelicity).trigger('focus');\n }\n },\n\n /**\n * Set events listener when modal is opened.\n */\n _setKeyListener: function () {\n this.modal.find(this.options.focusableStart).on('focusin', this._tabSwitcher);\n this.modal.find(this.options.focusableEnd).on('focusin', this._tabSwitcher);\n this.modal.on('keydown', this.keyEventSwitcher);\n },\n\n /**\n * Remove events listener when modal is closed.\n */\n _removeKeyListener: function () {\n this.modal.find(this.options.focusableStart).off('focusin', this._tabSwitcher);\n this.modal.find(this.options.focusableEnd).off('focusin', this._tabSwitcher);\n this.modal.off('keydown', this.keyEventSwitcher);\n },\n\n /**\n * Switcher for focus event.\n * @param {Object} e - event\n */\n _tabSwitcher: function (e) {\n var target = $(e.target);\n\n if (target.is(this.options.focusableStart)) {\n this._setFocus('start');\n } else if (target.is(this.options.focusableEnd)) {\n this._setFocus('end');\n }\n },\n\n /**\n * Close modal.\n * * @return {Element} - current element.\n */\n closeModal: function () {\n var that = this;\n\n this._removeKeyListener();\n this.options.isOpen = false;\n this.modal.one(this.options.transitionEvent, function () {\n that._close();\n });\n this.modal.removeClass(this.options.modalVisibleClass);\n\n if (!this.options.transitionEvent) {\n that._close();\n }\n\n return this.element;\n },\n\n /**\n * Helper for closeModal function.\n */\n _close: function () {\n var trigger = _.bind(this._trigger, this, 'closed', this.modal);\n\n $(this.focussedElement).trigger('focus');\n this._destroyOverlay();\n this._unsetActive();\n _.defer(trigger, this);\n },\n\n /**\n * Set z-index and margin for modal and overlay.\n */\n _setActive: function () {\n var zIndex = this.modal.zIndex(),\n baseIndex = zIndex + this._getVisibleCount();\n\n if (this.modal.data('active')) {\n return;\n }\n\n this.modal.data('active', true);\n\n this.overlay.zIndex(++baseIndex);\n this.prevOverlayIndex = this.overlay.zIndex();\n this.modal.zIndex(this.overlay.zIndex() + 1);\n\n if (this._getVisibleSlideCount()) {\n this.modal.css('marginLeft', this.options.modalLeftMargin * this._getVisibleSlideCount());\n }\n },\n\n /**\n * Unset styles for modal and set z-index for previous modal.\n */\n _unsetActive: function () {\n this.modal.removeAttr('style');\n this.modal.data('active', false);\n\n if (this.overlay) {\n this.overlay.zIndex(this.prevOverlayIndex - 1);\n }\n },\n\n /**\n * Creates wrapper to hold all modals.\n */\n _createWrapper: function () {\n this.modalWrapper = $(this.options.appendTo).find('.' + this.options.wrapperClass);\n\n if (!this.modalWrapper.length) {\n this.modalWrapper = $('<div></div>')\n .addClass(this.options.wrapperClass)\n .appendTo(this.options.appendTo);\n }\n },\n\n /**\n * Compile template and append to wrapper.\n */\n _renderModal: function () {\n $(template(\n this.options[this.options.type + 'Tpl'],\n {\n data: this.options\n })).appendTo(this.modalWrapper);\n this.modal = this.modalWrapper.find(this.options.modalBlock).last();\n this.element.appendTo(this._getElem(this.options.modalContent));\n\n if (this.element.is(':hidden')) {\n this.element.show();\n }\n },\n\n /**\n * Creates buttons pane.\n */\n _createButtons: function () {\n this.buttons = this._getElem(this.options.modalAction);\n _.each(this.options.buttons, function (btn, key) {\n var button = this.buttons[key];\n\n if (btn.attr) {\n $(button).attr(btn.attr);\n }\n\n if (btn.class) {\n $(button).addClass(btn.class);\n }\n\n if (!btn.click) {\n btn.click = this.closeModal;\n }\n $(button).on('click', _.bind(btn.click, this));\n }, this);\n },\n\n /**\n * Creates overlay, append it to wrapper, set previous click event on overlay.\n */\n _createOverlay: function () {\n var events,\n outerClickHandler = this.options.outerClickHandler || this.closeModal;\n\n this.overlay = $('.' + this.options.overlayClass);\n\n if (!this.overlay.length) {\n $(this.options.appendTo).addClass(this.options.parentModalClass);\n this.overlay = $('<div></div>')\n .addClass(this.options.overlayClass)\n .appendTo(this.modalWrapper);\n }\n events = $._data(this.overlay.get(0), 'events');\n events ? this.prevOverlayHandler = events.click[0].handler : false;\n this.options.clickableOverlay ? this.overlay.off().on('click', outerClickHandler) : false;\n },\n\n /**\n * Destroy overlay.\n */\n _destroyOverlay: function () {\n if (this._getVisibleCount()) {\n this.overlay.off().on('click', this.prevOverlayHandler);\n } else {\n $(this.options.appendTo).removeClass(this.options.parentModalClass);\n this.overlay.remove();\n this.overlay = null;\n }\n }\n });\n\n return $.mage.modal;\n});\n","Magento_Ui/js/modal/alert.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 'jquery-ui-modules/widget',\n 'Magento_Ui/js/modal/confirm',\n 'mage/translate'\n], function ($, _) {\n 'use strict';\n\n $.widget('mage.alert', $.mage.confirm, {\n options: {\n modalClass: 'confirm',\n title: $.mage.__('Attention'),\n actions: {\n\n /**\n * Callback always - called on all actions.\n */\n always: function () {}\n },\n buttons: [{\n text: $.mage.__('OK'),\n class: 'action-primary action-accept',\n\n /**\n * Click handler.\n */\n click: function () {\n this.closeModal(true);\n }\n }]\n },\n\n /**\n * Close modal window.\n */\n closeModal: function () {\n this.options.actions.always();\n this.element.on('alertclosed', _.bind(this._remove, this));\n\n return this._super();\n }\n });\n\n return function (config) {\n return $('<div></div>').html(config.content).alert(config);\n };\n});\n","Magento_Ui/js/modal/modal-component.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'Magento_Ui/js/lib/view/utils/async',\n 'uiCollection',\n 'uiRegistry',\n 'underscore',\n './modal'\n], function ($, Collection, registry, _) {\n 'use strict';\n\n return Collection.extend({\n defaults: {\n template: 'ui/modal/modal-component',\n title: '',\n subTitle: '',\n options: {\n modalClass: '',\n title: '',\n subTitle: '',\n buttons: [],\n keyEventHandlers: {}\n },\n valid: true,\n links: {\n title: 'options.title',\n subTitle: 'options.subTitle'\n },\n listens: {\n state: 'onState',\n title: 'setTitle',\n 'options.subTitle': 'setSubTitle'\n },\n modalClass: 'modal-component',\n onCancel: 'closeModal'\n },\n\n /**\n * Initializes component.\n *\n * @returns {Object} Chainable.\n */\n initialize: function () {\n this._super();\n _.bindAll(this,\n 'initModal',\n 'openModal',\n 'closeModal',\n 'toggleModal',\n 'setPrevValues',\n 'validate');\n this.initializeContent();\n\n return this;\n },\n\n /**\n * Initializes modal configuration\n *\n * @returns {Object} Chainable.\n */\n initConfig: function () {\n return this._super()\n .initSelector()\n .initModalEvents();\n },\n\n /**\n * Configure modal selector\n *\n * @returns {Object} Chainable.\n */\n initSelector: function () {\n var modalClass = this.name.replace(/\\./g, '_');\n\n this.contentSelector = '.' + this.modalClass;\n this.options.modalClass = this.options.modalClass + ' ' + modalClass;\n this.rootSelector = '.' + modalClass;\n\n return this;\n },\n\n /**\n * Configure modal keyboard handlers\n * and outer click\n *\n * @returns {Object} Chainable.\n */\n initModalEvents: function () {\n this.options.keyEventHandlers.escapeKey = this.options.outerClickHandler = this[this.onCancel].bind(this);\n\n return this;\n },\n\n /**\n * Initialize modal's content components\n */\n initializeContent: function () {\n $.async({\n component: this.name\n }, this.initModal);\n },\n\n /**\n * Init toolbar section so other components will be able to place something in it\n */\n initToolbarSection: function () {\n this.set('toolbarSection', this.modal.data('mage-modal').modal.find('header').get(0));\n },\n\n /**\n * Initializes observable properties.\n *\n * @returns {Object} Chainable.\n */\n initObservable: function () {\n this._super();\n this.observe(['state', 'focused']);\n\n return this;\n },\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 if (!this.modal) {\n this.overrideModalButtonCallback();\n this.options.modalCloseBtnHandler = this[this.onCancel].bind(this);\n this.modal = $(element).modal(this.options);\n this.initToolbarSection();\n\n if (this.waitCbk) {\n this.waitCbk();\n this.waitCbk = null;\n }\n }\n\n return this;\n },\n\n /**\n * Open modal\n */\n openModal: function () {\n if (this.modal) {\n this.state(true);\n } else {\n this.waitCbk = this.openModal;\n }\n },\n\n /**\n * Close modal\n */\n closeModal: function () {\n if (this.modal) {\n this.state(false);\n } else {\n this.waitCbk = this.closeModal;\n }\n },\n\n /**\n * Toggle modal\n */\n toggleModal: function () {\n if (this.modal) {\n this.state(!this.state());\n } else {\n this.waitCbk = this.toggleModal;\n }\n },\n\n /**\n * Sets title for modal\n *\n * @param {String} title\n */\n setTitle: function (title) {\n if (this.title !== title) {\n this.title = title;\n }\n\n if (this.modal) {\n this.modal.modal('setTitle', title);\n }\n },\n\n /**\n * Sets subTitle for modal\n *\n * @param {String} subTitle\n */\n setSubTitle: function (subTitle) {\n if (this.subTitle !== subTitle) {\n this.subTitle = subTitle;\n }\n\n if (this.modal) {\n this.modal.modal('setSubTitle', subTitle);\n }\n },\n\n /**\n * Wrap content in a modal of certain type\n *\n * @param {Boolean} state\n */\n onState: function (state) {\n if (state) {\n this.modal.modal('openModal');\n this.applyData();\n } else {\n this.modal.modal('closeModal');\n }\n },\n\n /**\n * Validate everything validatable in modal\n */\n validate: function (elem) {\n if (typeof elem === 'undefined') {\n return;\n }\n\n if (typeof elem.validate === 'function') {\n this.valid &= elem.validate().valid;\n } else if (elem.elems) {\n elem.elems().forEach(this.validate, this);\n }\n },\n\n /**\n * Reset data from provider\n */\n resetData: function () {\n this.elems().forEach(this.resetValue, this);\n },\n\n /**\n * Update 'applied' property with data from modal content\n */\n applyData: function () {\n var applied = {};\n\n this.elems().forEach(this.gatherValues.bind(this, applied), this);\n this.applied = applied;\n },\n\n /**\n * Gather values from modal content\n *\n * @param {Array} applied\n * @param {HTMLElement} elem\n */\n gatherValues: function (applied, elem) {\n if (typeof elem.value === 'function') {\n applied[elem.name] = elem.value();\n } else if (elem.elems) {\n elem.elems().forEach(this.gatherValues.bind(this, applied), this);\n }\n },\n\n /**\n * Set to previous values from modal content\n *\n * @param {HTMLElement} elem\n */\n setPrevValues: function (elem) {\n if (typeof elem.value === 'function') {\n this.modal.focus();\n elem.value(this.applied[elem.name]);\n } else if (elem.elems) {\n elem.elems().forEach(this.setPrevValues, this);\n }\n },\n\n /**\n * Triggers some method in every modal child elem, if this method is defined\n *\n * @param {Object} action - action configuration,\n * must contain actionName and targetName and\n * can contain params\n */\n triggerAction: function (action) {\n var targetName = action.targetName,\n params = action.params || [],\n actionName = action.actionName,\n target;\n\n target = registry.async(targetName);\n\n if (target && typeof target === 'function' && actionName) {\n params.unshift(actionName);\n target.apply(target, params);\n }\n },\n\n /**\n * Override modal buttons callback placeholders with real callbacks\n */\n overrideModalButtonCallback: function () {\n var buttons = this.options.buttons;\n\n if (buttons && buttons.length) {\n buttons.forEach(function (button) {\n button.click = this.getButtonClickHandler(button.actions);\n }, this);\n }\n },\n\n /**\n * Generate button click handler based on button's 'actions' configuration\n */\n getButtonClickHandler: function (actionsConfig) {\n var actions = actionsConfig.map(\n function (actionConfig) {\n if (_.isObject(actionConfig)) {\n return this.triggerAction.bind(this, actionConfig);\n }\n\n return this[actionConfig] ? this[actionConfig].bind(this) : function () {};\n }, this);\n\n return function () {\n actions.forEach(\n function (action) {\n action();\n }\n );\n };\n },\n\n /**\n * Cancels changes in modal:\n * returning elems values to the previous state,\n * and close modal\n */\n actionCancel: function () {\n this.elems().forEach(this.setPrevValues, this);\n this.closeModal();\n },\n\n /**\n * Accept changes in modal by not preventing them.\n * Can be extended by exporting 'gatherValues' result somewhere\n */\n actionDone: function () {\n this.valid = true;\n this.elems().forEach(this.validate, this);\n\n if (this.valid) {\n this.closeModal();\n }\n }\n });\n});\n","Magento_Ui/js/core/app.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n './renderer/types',\n './renderer/layout',\n '../lib/knockout/bootstrap'\n], function (types, layout) {\n 'use strict';\n\n return function (data, merge) {\n types.set(data.types);\n layout(data.components, undefined, true, merge);\n };\n});\n","Magento_Ui/js/core/renderer/types.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'mageUtils'\n], function (_, utils) {\n 'use strict';\n\n var store = {};\n\n /**\n * Flatten a nested data.\n *\n * @param {Object} data\n * @returns {Object}\n */\n function flatten(data) {\n var extender = data.extends || [],\n result = {};\n\n extender = utils.stringToArray(extender);\n\n extender.push(data);\n\n extender.forEach(function (item) {\n if (_.isString(item)) {\n item = store[item] || {};\n }\n\n utils.extend(result, item);\n });\n\n delete result.extends;\n\n return result;\n }\n\n return {\n /**\n * Set types to store object.\n *\n * @param {Object} types\n */\n set: function (types) {\n types = types || {};\n\n utils.extend(store, types);\n\n _.each(types, function (data, type) {\n store[type] = flatten(data);\n });\n },\n\n /**\n * Get type from store object.\n *\n * @param {String} type\n * @returns {*|{}}\n */\n get: function (type) {\n return store[type] || {};\n }\n };\n});\n","Magento_Ui/js/core/renderer/layout.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'jquery',\n 'mageUtils',\n 'uiRegistry',\n './types',\n '../../lib/logger/console-logger'\n], function (_, $, utils, registry, types, consoleLogger) {\n 'use strict';\n\n var templates = registry.create(),\n layout = {},\n cachedConfig = {};\n\n /**\n * Build name from parent name and node name\n *\n * @param {Object} parent\n * @param {Object} node\n * @param {String} [name]\n * @returns {String}\n */\n function getNodeName(parent, node, name) {\n var parentName = parent && parent.name;\n\n if (typeof name !== 'string') {\n name = node.name || name;\n }\n\n return utils.fullPath(parentName, name);\n }\n\n /**\n * Get node type from node or parent.\n *\n * @param {Object} parent\n * @param {Object} node\n * @returns {String}\n */\n function getNodeType(parent, node) {\n return node.type || parent && parent.childType;\n }\n\n /**\n * Get data scope based on parent data scope and node data scope.\n *\n * @param {Object} parent\n * @param {Object} node\n * @returns {String}\n */\n function getDataScope(parent, node) {\n var dataScope = node.dataScope,\n parentScope = parent && parent.dataScope;\n\n return !utils.isEmpty(parentScope) ?\n !utils.isEmpty(dataScope) ?\n parentScope + '.' + dataScope :\n parentScope :\n dataScope || '';\n }\n\n /**\n * Load node dependencies on other instances.\n *\n * @param {Object} node\n * @returns {jQueryPromise}\n */\n function loadDeps(node) {\n var loaded = $.Deferred(),\n loggerUtils = consoleLogger.utils;\n\n if (node.deps) {\n consoleLogger.utils.asyncLog(\n loaded,\n {\n data: {\n component: node.name,\n deps: node.deps\n },\n messages: loggerUtils.createMessages(\n 'depsStartRequesting',\n 'depsFinishRequesting',\n 'depsLoadingFail'\n )\n }\n );\n }\n\n registry.get(node.deps, function (deps) {\n node.provider = node.extendProvider ? deps && deps.name : node.provider;\n loaded.resolve(node);\n });\n\n return loaded.promise();\n }\n\n /**\n * Load node component file via requirejs.\n *\n * @param {Object} node\n * @returns {jQueryPromise}\n */\n function loadSource(node) {\n var loaded = $.Deferred(),\n source = node.component;\n\n consoleLogger.info('componentStartLoading', {\n component: node.component\n });\n\n require([source], function (constr) {\n consoleLogger.info('componentFinishLoading', {\n component: node.component\n });\n loaded.resolve(node, constr);\n }, function () {\n consoleLogger.error('componentLoadingFail', {\n component: node.component\n });\n });\n\n return loaded.promise();\n }\n\n /**\n * Create a new component instance and set it to the registry.\n *\n * @param {Object} node\n * @param {Function} Constr\n */\n function initComponent(node, Constr) {\n var component = new Constr(_.omit(node, 'children'));\n\n consoleLogger.info('componentStartInitialization', {\n component: node.component,\n componentName: node.name\n });\n\n registry.set(node.name, component);\n }\n\n /**\n * Application entry point.\n *\n * @param {Object} nodes\n * @param {Object} parent\n * @param {Boolean} cached\n * @param {Boolean} merge\n * @returns {Boolean|undefined}\n */\n function run(nodes, parent, cached, merge) {\n if (_.isBoolean(merge) && merge) {\n layout.merge(nodes);\n\n return false;\n }\n\n if (cached) {\n cachedConfig[_.keys(nodes)[0]] = JSON.parse(JSON.stringify(nodes));\n }\n\n _.each(nodes || [], layout.iterator.bind(layout, parent));\n }\n\n _.extend(layout, {\n /**\n * Determines if node ready to be added or process it.\n *\n * @param {Object} parent\n * @param {Object|String} node\n */\n iterator: function (parent, node) {\n var action = _.isString(node) ?\n this.addChild :\n this.process;\n\n action.apply(this, arguments);\n },\n\n /**\n * Prepare component.\n *\n * @param {Object} parent\n * @param {Object} node\n * @param {String} name\n * @returns {Object}\n */\n process: function (parent, node, name) {\n if (!parent && node.parent) {\n return this.waitParent(node, name);\n }\n\n if (node.nodeTemplate) {\n return this.waitTemplate.apply(this, arguments);\n }\n\n node = this.build.apply(this, arguments);\n\n if (!registry.has(node.name)) {\n this.addChild(parent, node)\n .manipulate(node)\n .initComponent(node);\n }\n\n if (node) {\n run(node.children, node);\n }\n\n return this;\n },\n\n /**\n * Detailed processing of component config.\n *\n * @param {Object} parent\n * @param {Object} node\n * @param {String} name\n * @returns {Boolean|Object}\n */\n build: function (parent, node, name) {\n var defaults = parent && parent.childDefaults || {},\n children = this.filterDisabledChildren(node.children),\n type = getNodeType(parent, node),\n dataScope = getDataScope(parent, node),\n component,\n extendDeps = true,\n nodeName;\n\n node.children = false;\n node.extendProvider = true;\n\n if (node.config && node.config.provider || node.provider) {\n node.extendProvider = false;\n }\n\n if (node.config && node.config.deps || node.deps) {\n extendDeps = false;\n }\n\n node = utils.extend({\n }, types.get(type), defaults, node);\n\n nodeName = getNodeName(parent, node, name);\n\n if (registry.has(nodeName)) {\n component = registry.get(nodeName);\n component.children = children;\n\n return component;\n }\n\n if (extendDeps && parent && parent.deps && type) {\n node.deps = parent.deps;\n }\n\n _.extend(node, node.config || {}, {\n index: node.name || name,\n name: nodeName,\n dataScope: dataScope,\n parentName: utils.getPart(nodeName, -2),\n parentScope: utils.getPart(dataScope, -2)\n });\n\n node.children = children;\n node.componentType = node.type;\n\n delete node.type;\n delete node.config;\n\n if (children) {\n node.initChildCount = _.size(children);\n }\n\n if (node.isTemplate) {\n node.isTemplate = false;\n\n templates.set(node.name, node);\n registry.get(node.parentName, function (parentComp) {\n parentComp.childTemplate = node;\n });\n\n return false;\n }\n\n if (node.componentDisabled === true) {\n return false;\n }\n\n return node;\n },\n\n /**\n * Filter out all disabled components.\n *\n * @param {Object} children\n * @returns {*}\n */\n filterDisabledChildren: function (children) {\n var cIds;\n\n //cleanup children config.componentDisabled = true\n if (children && typeof children === 'object') {\n cIds = Object.keys(children);\n\n if (cIds) {\n _.each(cIds, function (cId) {\n if (typeof children[cId] === 'object' &&\n children[cId].hasOwnProperty('config') &&\n typeof children[cId].config === 'object' &&\n children[cId].config.hasOwnProperty('componentDisabled') &&\n children[cId].config.componentDisabled === true) {\n delete children[cId];\n }\n });\n }\n }\n\n return children;\n },\n\n /**\n * Init component.\n *\n * @param {Object} node\n * @returns {Object}\n */\n initComponent: function (node) {\n if (!node.component) {\n return this;\n }\n\n loadDeps(node)\n .then(loadSource)\n .done(initComponent);\n\n return this;\n }\n });\n\n _.extend(layout, {\n /**\n * Loading component marked as isTemplate.\n *\n * @param {Object} parent\n * @param {Object} node\n * @returns {Object}\n */\n waitTemplate: function (parent, node) {\n var args = _.toArray(arguments);\n\n templates.get(node.nodeTemplate, function () {\n this.applyTemplate.apply(this, args);\n }.bind(this));\n\n return this;\n },\n\n /**\n * Waiting for parent component and process provided component.\n *\n * @param {Object} node\n * @param {String} name\n * @returns {Object}\n */\n waitParent: function (node, name) {\n var process = this.process.bind(this);\n\n registry.get(node.parent, function (parent) {\n process(parent, node, name);\n });\n\n return this;\n },\n\n /**\n * Processing component marked as isTemplate.\n *\n * @param {Object} parent\n * @param {Object} node\n * @param {String} name\n */\n applyTemplate: function (parent, node, name) {\n var template = templates.get(node.nodeTemplate);\n\n node = utils.extend({}, template, node);\n\n delete node.nodeTemplate;\n\n this.process(parent, node, name);\n }\n });\n\n _.extend(layout, {\n /**\n * Determines inserting strategy.\n *\n * @param {Object} node\n * @returns {Object}\n */\n manipulate: function (node) {\n var name = node.name;\n\n if (node.appendTo) {\n this.insert(name, node.appendTo, -1);\n }\n\n if (node.prependTo) {\n this.insert(name, node.prependTo, 0);\n }\n\n if (node.insertTo) {\n this.insertTo(name, node.insertTo);\n }\n\n return this;\n },\n\n /**\n * Insert component to provide target and position.\n *\n * @param {Object|String} item\n * @param {Object} target\n * @param {Number} position\n * @returns {Object}\n */\n insert: function (item, target, position) {\n registry.get(target, function (container) {\n container.insertChild(item, position);\n });\n\n return this;\n },\n\n /**\n * Insert component into multiple targets.\n *\n * @param {Object} item\n * @param {Array} targets\n * @returns {Object}\n */\n insertTo: function (item, targets) {\n _.each(targets, function (info, target) {\n this.insert(item, target, info.position);\n }, this);\n\n return this;\n },\n\n /**\n * Add provided child to parent.\n *\n * @param {Object} parent\n * @param {Object|String} child\n * @returns {Object}\n */\n addChild: function (parent, child) {\n var name;\n\n if (parent && parent.component) {\n name = child.name || child;\n\n this.insert(name, parent.name, child.sortOrder);\n }\n\n return this;\n },\n\n /**\n * Merge components configuration with cached configuration.\n *\n * @param {Array} components\n */\n merge: function (components) {\n var cachedKey = _.keys(components)[0],\n compared = utils.compare(cachedConfig[cachedKey], components),\n remove = this.filterComponents(this.getByProperty(compared.changes, 'type', 'remove'), true),\n update = this.getByProperty(compared.changes, 'type', 'update'),\n dataSources = this.getDataSources(components),\n names, index, name, component;\n\n _.each(dataSources, function (val, key) {\n name = key.replace(/\\.children|\\.config/g, '');\n component = registry.get(name);\n\n component.cacheData();\n component.updateConfig(\n true,\n this.getFullConfig(key, components),\n this.getFullConfig(key, cachedConfig[cachedKey])\n );\n }, this);\n\n _.each(remove, function (val) {\n component = registry.get(val.path);\n\n if (component) {\n component.destroy();\n }\n });\n\n update = _.compact(_.filter(update, function (val) {\n return !_.isEqual(val.oldValue, val.value);\n }));\n\n _.each(update, function (val) {\n names = val.path.split('.');\n index = Math.max(_.lastIndexOf(names, 'config'), _.lastIndexOf(names, 'children') + 2);\n name = _.without(names.splice(0, index), 'children', 'config').join('.');\n component = registry.get(name);\n\n if (val.name === 'sortOrder' && component) {\n registry.get(component.parentName).insertChild(component, val.value);\n } else if (component) {\n component.updateConfig(\n val.oldValue,\n val.value,\n val.path\n );\n }\n }, this);\n\n run(components, undefined, true);\n },\n\n /**\n * Recursive dataSource assignment.\n *\n * @param {Object} config\n * @param {String} parentPath\n * @returns {Object}\n */\n getDataSources: function (config, parentPath) {\n var dataSources = {},\n key, obj;\n\n /* eslint-disable no-loop-func, max-depth */\n for (key in config) {\n if (config.hasOwnProperty(key)) {\n if (\n key === 'type' &&\n config[key] === 'dataSource' &&\n config.hasOwnProperty('config')\n ) {\n dataSources[parentPath + '.config'] = config.config;\n } else if (_.isObject(config[key])) {\n obj = this.getDataSources(config[key], utils.fullPath(parentPath, key));\n\n _.each(obj, function (value, path) {\n dataSources[path] = value;\n });\n }\n }\n }\n\n /* eslint-enable no-loop-func, max-depth */\n\n return dataSources;\n },\n\n /**\n * Configuration getter.\n *\n * @param {String} path\n * @param {Object} config\n * @returns {Boolean|Object}\n */\n getFullConfig: function (path, config) {\n var index;\n\n path = path.split('.');\n index = _.lastIndexOf(path, 'config');\n\n if (!~index) {\n return false;\n }\n path = path.splice(0, index);\n\n _.each(path, function (val) {\n config = config[val];\n });\n\n return config.config;\n },\n\n /**\n * Filter data by property and value.\n *\n * @param {Object} data\n * @param {String} prop\n * @param {*} propValue\n */\n getByProperty: function (data, prop, propValue) {\n return _.filter(data, function (value) {\n return value[prop] === propValue;\n });\n },\n\n /**\n * Filter components.\n *\n * @param {Array} data\n * @param {Boolean} splitPath\n * @param {Number} index\n * @param {String} separator\n * @param {String} keyName\n * @returns {Array}\n */\n filterComponents: function (data, splitPath, index, separator, keyName) {\n var result = [],\n names, length;\n\n index = -2;\n separator = '.' || separator;\n keyName = 'children' || keyName;\n\n _.each(data, function (val) {\n names = val.path.split(separator);\n length = names.length;\n\n if (names[length + index] === keyName) {\n val.path = splitPath ? _.without(names, keyName).join(separator) : val.path;\n result.push(val);\n }\n });\n\n return result;\n }\n });\n\n return run;\n});\n","Magento_Ui/js/form/button-adapter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiClass',\n 'jquery',\n 'underscore',\n 'uiRegistry'\n], function (Class, $, _, registry) {\n 'use strict';\n\n return Class.extend({\n\n /**\n * Initialize actions and adapter.\n *\n * @param {Object} config\n * @param {Element} elem\n * @returns {Object}\n */\n initialize: function (config, elem) {\n return this._super()\n .initActions()\n .initAdapter(elem);\n },\n\n /**\n * Creates callback from declared actions.\n *\n * @returns {Object}\n */\n initActions: function () {\n var callbacks = [];\n\n _.each(this.actions, function (action) {\n callbacks.push({\n action: registry.async(action.targetName),\n args: _.union([action.actionName], action.params)\n });\n });\n\n /**\n * Callback function.\n */\n this.callback = function () {\n _.each(callbacks, function (callback) {\n callback.action.apply(callback.action, callback.args);\n });\n };\n\n return this;\n },\n\n /**\n * Attach callback handler on button.\n *\n * @param {Element} elem\n */\n initAdapter: function (elem) {\n $(elem).on('click', this.callback);\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/client.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'underscore',\n 'mageUtils',\n 'uiClass'\n], function ($, _, utils, Class) {\n 'use strict';\n\n /**\n * Before save validate request.\n *\n * @param {Object} data\n * @param {String} url\n * @param {String} selectorPrefix\n * @param {String} messagesClass\n * @returns {*}\n */\n function beforeSave(data, url, selectorPrefix, messagesClass) {\n var save = $.Deferred();\n\n data = utils.serialize(utils.filterFormData(data));\n data['form_key'] = window.FORM_KEY;\n\n if (!url || url === 'undefined') {\n return save.resolve();\n }\n\n $('body').trigger('processStart');\n\n $.ajax({\n url: url,\n data: data,\n\n /**\n * Success callback.\n * @param {Object} resp\n * @returns {Boolean}\n */\n success: function (resp) {\n if (!resp.error) {\n save.resolve();\n\n return true;\n }\n\n $('body').notification('clear');\n $.each(resp.messages || [resp.message] || [], function (key, message) {\n $('body').notification('add', {\n error: resp.error,\n message: message,\n\n /**\n * Insert method.\n *\n * @param {String} msg\n */\n insertMethod: function (msg) {\n var $wrapper = $('<div></div>').addClass(messagesClass).html(msg);\n\n $('.page-main-actions', selectorPrefix).after($wrapper);\n $('html, body').animate({\n scrollTop: $('.page-main-actions', selectorPrefix).offset().top\n });\n }\n });\n });\n },\n\n /**\n * Complete callback.\n */\n complete: function () {\n $('body').trigger('processStop');\n }\n });\n\n return save.promise();\n }\n\n return Class.extend({\n\n /**\n * Assembles data and submits it using 'utils.submit' method\n */\n save: function (data, options) {\n var url = this.urls.beforeSave,\n save = this._save.bind(this, data, options);\n\n beforeSave(data, url, this.selectorPrefix, this.messagesClass).then(save);\n\n return this;\n },\n\n /**\n * Save data.\n *\n * @param {Object} data\n * @param {Object} options\n * @returns {Object}\n * @private\n */\n _save: function (data, options) {\n var url = this.urls.save;\n\n $('body').trigger('processStart');\n options = options || {};\n\n if (!options.redirect) {\n url += 'back/edit';\n }\n\n if (options.ajaxSave) {\n utils.ajaxSubmit({\n url: url,\n data: data\n }, options);\n\n $('body').trigger('processStop');\n\n return this;\n }\n\n utils.submit({\n url: url,\n data: data\n }, options.attributes);\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'Magento_Ui/js/lib/spinner',\n 'rjsResolver',\n './adapter',\n 'uiCollection',\n 'mageUtils',\n 'jquery',\n 'Magento_Ui/js/core/app',\n 'mage/validation'\n], function (_, loader, resolver, adapter, Collection, utils, $, app) {\n 'use strict';\n\n /**\n * Format params\n *\n * @param {Object} params\n * @returns {Array}\n */\n function prepareParams(params) {\n var result = '?';\n\n _.each(params, function (value, key) {\n result += key + '=' + value + '&';\n });\n\n return result.slice(0, -1);\n }\n\n /**\n * Collect form data.\n *\n * @param {Array} items\n * @returns {Object}\n */\n function collectData(items) {\n var result = {},\n name;\n\n items = Array.prototype.slice.call(items);\n\n items.forEach(function (item) {\n switch (item.type) {\n case 'checkbox':\n result[item.name] = +!!item.checked;\n break;\n\n case 'radio':\n if (item.checked) {\n result[item.name] = item.value;\n }\n break;\n\n case 'select-multiple':\n name = item.name.substring(0, item.name.length - 2); //remove [] from the name ending\n result[name] = _.pluck(item.selectedOptions, 'value');\n break;\n\n default:\n result[item.name] = item.value;\n }\n });\n\n return result;\n }\n\n /**\n * Makes ajax request\n *\n * @param {Object} params\n * @param {Object} data\n * @param {String} url\n * @returns {*}\n */\n function makeRequest(params, data, url) {\n var save = $.Deferred();\n\n data = utils.serialize(data);\n data['form_key'] = window.FORM_KEY;\n\n if (!url) {\n save.resolve();\n }\n\n $('body').trigger('processStart');\n\n $.ajax({\n url: url + prepareParams(params),\n data: data,\n dataType: 'json',\n\n /**\n * Success callback.\n * @param {Object} resp\n * @returns {Boolean}\n */\n success: function (resp) {\n if (resp.ajaxExpired) {\n window.location.href = resp.ajaxRedirect;\n }\n\n if (!resp.error) {\n save.resolve(resp);\n\n return true;\n }\n\n $('body').notification('clear');\n $.each(resp.messages, function (key, message) {\n $('body').notification('add', {\n error: resp.error,\n message: message,\n\n /**\n * Inserts message on page\n * @param {String} msg\n */\n insertMethod: function (msg) {\n $('.page-main-actions').after(msg);\n }\n });\n });\n },\n\n /**\n * Complete callback.\n */\n complete: function () {\n $('body').trigger('processStop');\n }\n });\n\n return save.promise();\n }\n\n /**\n * Check if fields is valid.\n *\n * @param {Array}items\n * @returns {Boolean}\n */\n function isValidFields(items) {\n var result = true;\n\n _.each(items, function (item) {\n if (!$.validator.validateSingleElement(item)) {\n result = false;\n }\n });\n\n return result;\n }\n\n return Collection.extend({\n defaults: {\n additionalFields: [],\n additionalInvalid: false,\n selectorPrefix: '.page-content',\n messagesClass: 'messages',\n errorClass: '.admin__field._error',\n eventPrefix: '.${ $.index }',\n ajaxSave: false,\n ajaxSaveType: 'default',\n imports: {\n reloadUrl: '${ $.provider}:reloadUrl'\n },\n listens: {\n selectorPrefix: 'destroyAdapter initAdapter',\n '${ $.name }.${ $.reloadItem }': 'params.set reload'\n },\n exports: {\n selectorPrefix: '${ $.provider }:client.selectorPrefix',\n messagesClass: '${ $.provider }:client.messagesClass'\n }\n },\n\n /** @inheritdoc */\n initialize: function () {\n this._super()\n .initAdapter();\n\n resolver(this.hideLoader, this);\n\n return this;\n },\n\n /** @inheritdoc */\n initObservable: function () {\n return this._super()\n .observe([\n 'responseData',\n 'responseStatus'\n ]);\n },\n\n /** @inheritdoc */\n initConfig: function () {\n this._super();\n\n this.selector = '[data-form-part=' + this.namespace + ']';\n\n return this;\n },\n\n /**\n * Initialize adapter handlers.\n *\n * @returns {Object}\n */\n initAdapter: function () {\n adapter.on({\n 'reset': this.reset.bind(this),\n 'save': this.save.bind(this, true, {}),\n 'saveAndContinue': this.save.bind(this, false, {})\n }, this.selectorPrefix, this.eventPrefix);\n\n return this;\n },\n\n /**\n * Destroy adapter handlers.\n *\n * @returns {Object}\n */\n destroyAdapter: function () {\n adapter.off([\n 'reset',\n 'save',\n 'saveAndContinue'\n ], this.eventPrefix);\n\n return this;\n },\n\n /**\n * Hide loader.\n *\n * @returns {Object}\n */\n hideLoader: function () {\n loader.get(this.name).hide();\n\n return this;\n },\n\n /**\n * Validate and save form.\n *\n * @param {String} redirect\n * @param {Object} data\n */\n save: function (redirect, data) {\n this.validate();\n\n if (!this.additionalInvalid && !this.source.get('params.invalid')) {\n this.setAdditionalData(data)\n .submit(redirect);\n } else {\n this.focusInvalid();\n }\n },\n\n /**\n * Tries to set focus on first invalid form field.\n *\n * @returns {Object}\n */\n focusInvalid: function () {\n var invalidField = _.find(this.delegate('checkInvalid'));\n\n if (!_.isUndefined(invalidField) && _.isFunction(invalidField.focused)) {\n invalidField.focused(true);\n }\n\n return this;\n },\n\n /**\n * Set additional data to source before form submit and after validation.\n *\n * @param {Object} data\n * @returns {Object}\n */\n setAdditionalData: function (data) {\n _.each(data, function (value, name) {\n this.source.set('data.' + name, value);\n }, this);\n\n return this;\n },\n\n /**\n * Submits form\n *\n * @param {String} redirect\n */\n submit: function (redirect) {\n var additional = collectData(this.additionalFields),\n source = this.source;\n\n _.each(additional, function (value, name) {\n source.set('data.' + name, value);\n });\n\n source.save({\n redirect: redirect,\n ajaxSave: this.ajaxSave,\n ajaxSaveType: this.ajaxSaveType,\n response: {\n data: this.responseData,\n status: this.responseStatus\n },\n attributes: {\n id: this.namespace\n }\n });\n },\n\n /**\n * Validates each element and returns true, if all elements are valid.\n */\n validate: function () {\n this.additionalFields = document.querySelectorAll(this.selector);\n this.source.set('params.invalid', false);\n this.source.trigger('data.validate');\n this.set('additionalInvalid', !isValidFields(this.additionalFields));\n },\n\n /**\n * Trigger reset form data.\n */\n reset: function () {\n this.source.trigger('data.reset');\n $('[data-bind*=datepicker]').val('');\n },\n\n /**\n * Trigger overload form data.\n */\n overload: function () {\n this.source.trigger('data.overload');\n },\n\n /**\n * Updates data from server.\n */\n reload: function () {\n makeRequest(this.params, this.data, this.reloadUrl).then(function (data) {\n app(data, true);\n });\n }\n });\n});\n","Magento_Ui/js/form/provider.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiElement',\n './client',\n 'mageUtils'\n], function (_, Element, Client, utils) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n clientConfig: {\n urls: {\n save: '${ $.submit_url }',\n beforeSave: '${ $.validate_url }'\n }\n },\n ignoreTmpls: {\n data: true\n }\n },\n\n /**\n * Initializes provider component.\n *\n * @returns {Provider} Chainable.\n */\n initialize: function () {\n this._super()\n .initClient();\n\n return this;\n },\n\n /**\n * Initializes client component.\n *\n * @returns {Provider} Chainable.\n */\n initClient: function () {\n this.client = new Client(this.clientConfig);\n\n return this;\n },\n\n /**\n * Saves currently available data.\n *\n * @param {Object} [options] - Addtitional request options.\n * @returns {Provider} Chainable.\n */\n save: function (options) {\n var data = this.get('data');\n\n this.client.save(data, options);\n\n return this;\n },\n\n /**\n * Update data that stored in provider.\n *\n * @param {Boolean} isProvider\n * @param {Object} newData\n * @param {Object} oldData\n *\n * @returns {Provider}\n */\n updateConfig: function (isProvider, newData, oldData) {\n if (isProvider === true) {\n this.setData(oldData, newData, this);\n }\n\n return this;\n },\n\n /**\n * Set data to provider based on current data.\n *\n * @param {Object} oldData\n * @param {Object} newData\n * @param {Provider} current\n * @param {String} parentPath\n */\n setData: function (oldData, newData, current, parentPath) {\n _.each(newData, function (val, key) {\n if (_.isObject(val) || _.isArray(val)) {\n this.setData(oldData[key], val, current[key], utils.fullPath(parentPath, key));\n } else if (val != oldData[key] && oldData[key] == current[key]) {//eslint-disable-line eqeqeq\n this.set(utils.fullPath(parentPath, key), val);\n }\n }, this);\n }\n });\n});\n","Magento_Ui/js/form/adapter.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 'Magento_Ui/js/form/adapter/buttons'\n], function ($, _, buttons) {\n 'use strict';\n\n var selectorPrefix = '',\n eventPrefix;\n\n /**\n * Initialize listener.\n *\n * @param {Function} callback\n * @param {String} action\n */\n function initListener(callback, action) {\n var selector = selectorPrefix ? selectorPrefix + ' ' + buttons[action] : buttons[action],\n elem = $(selector)[0];\n\n if (!elem) {\n return;\n }\n\n if (elem.onclick) {\n elem.onclick = null;\n }\n\n $(elem).on('click' + eventPrefix, callback);\n }\n\n /**\n * Destroy listener.\n *\n * @param {String} action\n */\n function destroyListener(action) {\n var selector = selectorPrefix ? selectorPrefix + ' ' + buttons[action] : buttons[action],\n elem = $(selector)[0];\n\n if (!elem) {\n return;\n }\n\n if (elem.onclick) {\n elem.onclick = null;\n }\n\n $(elem).off('click' + eventPrefix);\n }\n\n return {\n\n /**\n * Attaches events handlers.\n *\n * @param {Object} handlers\n * @param {String} selectorPref\n * @param {String} eventPref\n */\n on: function (handlers, selectorPref, eventPref) {\n selectorPrefix = selectorPrefix || selectorPref;\n eventPrefix = eventPref;\n _.each(handlers, initListener);\n selectorPrefix = '';\n },\n\n /**\n * Removes events handlers.\n *\n * @param {Object} handlers\n * @param {String} eventPref\n */\n off: function (handlers, eventPref) {\n eventPrefix = eventPref;\n _.each(handlers, destroyListener);\n }\n };\n});\n","Magento_Ui/js/form/switcher.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiRegistry',\n 'uiClass'\n], function (_, registry, Class) {\n 'use strict';\n\n return Class.extend({\n defaults: {\n rules: []\n },\n\n /**\n * Initializes instance of a DataSwitcher.\n *\n * @returns {DataSwitcher} Chainable.\n */\n initialize: function () {\n this._super()\n .initRules();\n\n return this;\n },\n\n /**\n *\n * @returns {DataSwitcher} Chainable.\n */\n initRules: function () {\n this.rules.forEach(this.initRule, this);\n\n return this;\n },\n\n /**\n *\n * @param {Object} rule - Rule definition.\n * @returns {DataSwitcher} Chainable.\n */\n initRule: function (rule) {\n var handler = this.onValueChange.bind(this, rule);\n\n if (!rule.target) {\n rule.target = this.target;\n }\n\n if (!rule.property) {\n rule.property = this.property;\n }\n\n registry.get(rule.target, function (target) {\n this.applyRule(rule, target.get(rule.property));\n target.on(rule.property, handler);\n }.bind(this));\n\n return this;\n },\n\n /**\n *\n * @param {Object} rule - Rule definition.\n * @returns {DataSwitcher} Chainable.\n */\n addRule: function (rule) {\n this.rules.push(rule);\n this.initRule(rule);\n\n return this;\n },\n\n /**\n *\n * @param {Object} rule - Rule object.\n * @param {*} value - Current value associated with a rule.\n */\n applyRule: function (rule, value) {\n var actions = rule.actions;\n\n //TODO Refactor this logic in scope of MAGETWO-48585\n /* eslint-disable eqeqeq */\n if (rule.value != value) {\n return;\n } else if (rule.strict) {\n return;\n }\n\n /* eslint-enable eqeqeq */\n actions.forEach(this.applyAction, this);\n },\n\n /**\n *\n * @param {Object} action - Action object.\n */\n applyAction: function (action) {\n registry.get(action.target, function (target) {\n var callback = target[action.callback];\n\n callback.apply(target, action.params || []);\n });\n },\n\n /**\n *\n * @param {Object} rule - Rules object.\n * @param {*} value - Current value associated with a rule.\n */\n onValueChange: function (rule, value) {\n this.applyRule(rule, value);\n }\n });\n});\n","Magento_Ui/js/form/adapter/buttons.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine(function () {\n 'use strict';\n\n return {\n 'reset': '#reset',\n 'save': '#save',\n 'saveAndContinue': '#save_and_continue'\n };\n});\n","Magento_Ui/js/form/components/multiline.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n './group'\n], function (Group) {\n 'use strict';\n\n return Group.extend({\n defaults: {\n links: {\n value: '${ $.provider }:${ $.dataScope }'\n }\n },\n\n /**\n * Initialize Multiline component.\n *\n * @returns {Object}\n */\n initialize: function () {\n return this._super()\n ._prepareValue();\n },\n\n /**\n * {@inheritdoc}\n */\n initObservable: function () {\n this._super()\n .observe('value');\n\n return this;\n },\n\n /**\n * Prepare value for Multiline options.\n *\n * @returns {Object} Chainable.\n * @private\n */\n _prepareValue: function () {\n var value = this.value();\n\n if (typeof value === 'string') {\n this.value(value.split('\\n'));\n }\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/components/fieldset.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'Magento_Ui/js/lib/collapsible',\n 'underscore'\n], function (Collapsible, _) {\n 'use strict';\n\n return Collapsible.extend({\n defaults: {\n template: 'ui/form/fieldset',\n collapsible: false,\n changed: false,\n loading: false,\n error: false,\n opened: false,\n level: 0,\n visible: true,\n initializeFieldsetDataByDefault: false, /* Data in some fieldsets should be initialized before open */\n disabled: false,\n listens: {\n 'opened': 'onVisibilityChange'\n },\n additionalClasses: {}\n },\n\n /**\n * Extends instance with defaults. Invokes parent initialize method.\n * Calls initListeners and pushParams methods.\n */\n initialize: function () {\n _.bindAll(this, 'onChildrenUpdate', 'onChildrenError', 'onContentLoading');\n\n return this._super()\n ._setClasses();\n },\n\n /**\n * Initializes components' configuration.\n *\n * @returns {Fieldset} Chainable.\n */\n initConfig: function () {\n this._super();\n this._wasOpened = this.opened || !this.collapsible;\n\n return this;\n },\n\n /**\n * Calls initObservable of parent class.\n * Defines observable properties of instance.\n *\n * @returns {Object} Reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('changed loading error visible');\n\n return this;\n },\n\n /**\n * Calls parent's initElement method.\n * Assigns callbacks on various events of incoming element.\n *\n * @param {Object} elem\n * @return {Object} - reference to instance\n */\n initElement: function (elem) {\n elem.initContainer(this);\n\n elem.on({\n 'update': this.onChildrenUpdate,\n 'loading': this.onContentLoading,\n 'error': this.onChildrenError\n });\n\n if (this.disabled) {\n try {\n elem.disabled(true);\n }\n catch (e) {\n\n }\n }\n\n return this;\n },\n\n /**\n * Is being invoked on children update.\n * Sets changed property to one incoming.\n *\n * @param {Boolean} hasChanged\n */\n onChildrenUpdate: function (hasChanged) {\n if (!hasChanged) {\n hasChanged = _.some(this.delegate('hasChanged'));\n }\n\n this.bubble('update', hasChanged);\n this.changed(hasChanged);\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Group} Chainable.\n */\n _setClasses: function () {\n var additional = this.additionalClasses,\n classes;\n\n if (_.isString(additional)) {\n additional = this.additionalClasses.split(' ');\n classes = this.additionalClasses = {};\n\n additional.forEach(function (name) {\n classes[name] = true;\n }, this);\n }\n\n _.extend(this.additionalClasses, {\n 'admin__collapsible-block-wrapper': this.collapsible,\n _show: this.opened,\n _hide: !this.opened,\n _disabled: this.disabled\n });\n\n return this;\n },\n\n /**\n * Handler of the \"opened\" property changes.\n *\n * @param {Boolean} isOpened\n */\n onVisibilityChange: function (isOpened) {\n if (!this._wasOpened) {\n this._wasOpened = isOpened;\n }\n },\n\n /**\n * Is being invoked on children validation error.\n * Sets error property to one incoming.\n *\n * @param {String} message - error message.\n */\n onChildrenError: function (message) {\n var hasErrors = false;\n\n if (!message) {\n hasErrors = this._isChildrenHasErrors(hasErrors, this);\n }\n\n this.error(hasErrors || message);\n\n if (hasErrors || message) {\n this.open();\n }\n },\n\n /**\n * Returns errors of children if exist\n *\n * @param {Boolean} hasErrors\n * @param {*} container\n * @return {Boolean}\n * @private\n */\n _isChildrenHasErrors: function (hasErrors, container) {\n var self = this;\n\n if (hasErrors === false && container.hasOwnProperty('elems')) {\n hasErrors = container.elems.some('error');\n\n if (hasErrors === false && container.hasOwnProperty('_elems')) {\n container._elems.forEach(function (child) {\n\n if (hasErrors === false) {\n hasErrors = self._isChildrenHasErrors(hasErrors, child);\n }\n });\n }\n }\n\n return hasErrors;\n },\n\n /**\n * Callback that sets loading property to true.\n */\n onContentLoading: function (isLoading) {\n this.loading(isLoading);\n }\n });\n});\n","Magento_Ui/js/form/components/group.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiCollection'\n], function (_, Collection) {\n 'use strict';\n\n return Collection.extend({\n defaults: {\n visible: true,\n label: '',\n showLabel: true,\n required: false,\n template: 'ui/group/group',\n fieldTemplate: 'ui/form/field',\n breakLine: true,\n validateWholeGroup: false,\n additionalClasses: {}\n },\n\n /**\n * Extends this with defaults and config.\n * Then calls initObservable, iniListenes and extractData methods.\n */\n initialize: function () {\n this._super()\n ._setClasses();\n\n return this;\n },\n\n /**\n * Calls initObservable of parent class.\n * Defines observable properties of instance.\n *\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('visible')\n .observe({\n required: !!+this.required\n });\n\n return this;\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Group} Chainable.\n */\n _setClasses: function () {\n var additional = this.additionalClasses,\n classes;\n\n if (_.isString(additional)) {\n additional = this.additionalClasses.split(' ');\n classes = this.additionalClasses = {};\n\n additional.forEach(function (name) {\n classes[name] = true;\n }, this);\n }\n\n _.extend(this.additionalClasses, {\n 'admin__control-grouped': !this.breakLine,\n 'admin__control-fields': this.breakLine,\n required: this.required,\n _error: this.error,\n _disabled: this.disabled\n });\n\n return this;\n },\n\n /**\n * Defines if group has only one element.\n * @return {Boolean}\n */\n isSingle: function () {\n return this.elems.getLength() === 1;\n },\n\n /**\n * Defines if group has multiple elements.\n * @return {Boolean}\n */\n isMultiple: function () {\n return this.elems.getLength() > 1;\n },\n\n /**\n * Returns an array of child components previews.\n *\n * @returns {Array}\n */\n getPreview: function () {\n return this.elems.map('getPreview');\n }\n });\n});\n","Magento_Ui/js/form/components/tab_group.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'Magento_Ui/js/lib/collapsible'\n], function (_, Collapsible) {\n 'use strict';\n\n return Collapsible.extend({\n defaults: {\n listens: {\n '${ $.provider }:data.validate': 'onValidate'\n },\n collapsible: false,\n opened: true\n },\n\n /**\n * Invokes initElement method of parent class, calls 'initActivation' method\n * passing element to it.\n * @param {Object} elem\n * @returns {Object} - reference to instance\n */\n initElement: function (elem) {\n this._super()\n .initActivation(elem);\n\n return this;\n },\n\n /**\n * Activates element if one is first or if one has 'active' propert\n * set to true.\n *\n * @param {Object} elem\n * @returns {Object} - reference to instance\n */\n initActivation: function (elem) {\n var elems = this.elems(),\n isFirst = !elems.indexOf(elem);\n\n if (isFirst || elem.active()) {\n elem.activate();\n }\n\n return this;\n },\n\n /**\n * Delegates 'validate' method on element, then reads 'invalid' property\n * of params storage, and if defined, activates element, sets\n * 'allValid' property of instance to false and sets invalid's\n * 'focused' property to true.\n *\n * @param {Object} elem\n */\n validate: function (elem) {\n var result = elem.delegate('validate'),\n invalid;\n\n invalid = _.find(result, function (item) {\n return typeof item !== 'undefined' && !item.valid;\n });\n\n if (invalid) {\n elem.activate();\n invalid.target.focused(true);\n }\n\n return invalid;\n },\n\n /**\n * Sets 'allValid' property of instance to true, then calls 'validate' method\n * of instance for each element.\n */\n onValidate: function () {\n this.elems.sortBy(function (elem) {\n return !elem.active();\n }).some(this.validate, this);\n }\n });\n});\n","Magento_Ui/js/form/components/collection.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n 'uiRegistry',\n 'uiComponent',\n 'uiLayout',\n 'Magento_Ui/js/modal/confirm'\n], function (_, utils, registry, Component, layout, confirm) {\n 'use strict';\n\n var childTemplate = {\n parent: '${ $.$data.name }',\n name: '${ $.$data.childIndex }',\n dataScope: '${ $.name }',\n nodeTemplate: '${ $.$data.name }.${ $.$data.itemTemplate }'\n };\n\n return Component.extend({\n defaults: {\n lastIndex: 0,\n template: 'ui/form/components/collection'\n },\n\n /**\n * Extends instance with default config, calls initialize of parent\n * class, calls initChildren method.\n */\n initialize: function () {\n this._super()\n .initChildren();\n\n return this;\n },\n\n /**\n * Activates the incoming child and triggers the update event.\n *\n * @param {Object} elem - Incoming child.\n */\n initElement: function (elem) {\n this._super();\n\n elem.activate();\n\n this.bubble('update');\n\n return this;\n },\n\n /**\n * Loops over corresponding data in data storage,\n * creates child for each and pushes it's identifier to initialItems array.\n *\n * @returns {Collection} Chainable.\n */\n initChildren: function () {\n var children = this.source.get(this.dataScope),\n initial = this.initialItems = [];\n\n _.each(children, function (item, index) {\n initial.push(index);\n this.addChild(index);\n }, this);\n\n return this;\n },\n\n /**\n * Creates new item of collection, based on incoming 'index'.\n * If not passed creates one with 'new_' prefix.\n *\n * @param {String|Object} [index] - Index of a child.\n * @returns {Collection} Chainable.\n */\n addChild: function (index) {\n this.childIndex = !_.isString(index) ?\n 'new_' + this.lastIndex++ :\n index;\n\n layout([utils.template(childTemplate, this)]);\n\n return this;\n },\n\n /**\n * Returns true if current set of items differ from initial one,\n * or if some child has been changed.\n *\n * @returns {Boolean}\n */\n hasChanged: function () {\n var initial = this.initialItems,\n current = this.elems.pluck('index'),\n changed = !utils.equalArrays(initial, current);\n\n return changed || this.elems.some(function (elem) {\n return _.some(elem.delegate('hasChanged'));\n });\n },\n\n /**\n * Initiates validation of its' children components.\n *\n * @returns {Array} An array of validation results.\n */\n validate: function () {\n var elems;\n\n this.allValid = true;\n\n elems = this.elems.sortBy(function (elem) {\n return !elem.active();\n });\n\n elems = elems.map(this._validate, this);\n\n return _.flatten(elems);\n },\n\n /**\n * Iterator function for components validation.\n * Activates first invalid child component.\n *\n * @param {Object} elem - Element to run validation on.\n * @returns {Array} An array of validation results.\n */\n _validate: function (elem) {\n var result = elem.delegate('validate'),\n invalid;\n\n invalid = _.some(result, function (item) {\n return !item.valid;\n });\n\n if (this.allValid && invalid) {\n this.allValid = false;\n\n elem.activate();\n }\n\n return result;\n },\n\n /**\n * Creates function that removes element\n * from collection using '_removeChild' method.\n * @param {Object} elem - Element that should be removed.\n * @deprecated Not used anymore\n */\n removeAddress: function (elem) {\n var self = this;\n\n confirm({\n content: this.removeMessage,\n actions: {\n /** @inheritdoc */\n confirm: function () {\n self._removeAddress(elem);\n }\n }\n });\n },\n\n /**\n * Removes element from both collection and data storage,\n * activates first element if removed one was active,\n * triggers 'update' event.\n *\n * @param {Object} elem - Element to remove.\n */\n _removeAddress: function (elem) {\n var isActive = elem.active(),\n first;\n\n elem.destroy();\n\n first = this.elems.first();\n\n if (first && isActive) {\n first.activate();\n }\n\n this.bubble('update');\n }\n });\n});\n","Magento_Ui/js/form/components/button.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiElement',\n 'uiRegistry',\n 'uiLayout',\n 'mageUtils',\n 'underscore'\n], function (Element, registry, layout, utils, _) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n buttonClasses: {},\n additionalClasses: {},\n displayArea: 'outsideGroup',\n displayAsLink: false,\n elementTmpl: 'ui/form/element/button',\n template: 'ui/form/components/button/simple',\n visible: true,\n disabled: false,\n title: '',\n buttonTextId: '',\n ariLabelledby: ''\n },\n\n /**\n * Initializes component.\n *\n * @returns {Object} Chainable.\n */\n initialize: function () {\n return this._super()\n ._setClasses()\n ._setButtonClasses();\n },\n\n /** @inheritdoc */\n initObservable: function () {\n return this._super()\n .observe([\n 'visible',\n 'disabled',\n 'title',\n 'childError'\n ]);\n },\n\n /**\n * Performs configured actions\n */\n action: function () {\n this.actions.forEach(this.applyAction, this);\n },\n\n /**\n * Apply action on target component,\n * but previously create this component from template if it is not existed\n *\n * @param {Object} action - action configuration\n */\n applyAction: function (action) {\n var targetName = action.targetName,\n params = utils.copy(action.params) || [],\n actionName = action.actionName,\n target;\n\n if (!registry.has(targetName)) {\n this.getFromTemplate(targetName);\n }\n target = registry.async(targetName);\n\n if (target && typeof target === 'function' && actionName) {\n params.unshift(actionName);\n target.apply(target, params);\n }\n },\n\n /**\n * Create target component from template\n *\n * @param {Object} targetName - name of component,\n * that supposed to be a template and need to be initialized\n */\n getFromTemplate: function (targetName) {\n var parentName = targetName.split('.'),\n index = parentName.pop(),\n child;\n\n parentName = parentName.join('.');\n child = utils.template({\n parent: parentName,\n name: index,\n nodeTemplate: targetName\n });\n layout([child]);\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Object} Chainable.\n */\n _setClasses: function () {\n if (typeof this.additionalClasses === 'string') {\n if (this.additionalClasses === '') {\n this.additionalClasses = {};\n\n return this;\n }\n\n this.additionalClasses = this.additionalClasses\n .trim()\n .split(' ')\n .reduce(function (classes, name) {\n classes[name] = true;\n\n return classes;\n }, {}\n );\n }\n\n return this;\n },\n\n /**\n * Extends 'buttonClasses' object.\n *\n * @returns {Object} Chainable.\n */\n _setButtonClasses: function () {\n var additional = this.buttonClasses;\n\n if (_.isString(additional)) {\n this.buttonClasses = {};\n\n if (additional.trim().length) {\n additional = additional.trim().split(' ');\n\n additional.forEach(function (name) {\n if (name.length) {\n this.buttonClasses[name] = true;\n }\n }, this);\n }\n }\n\n _.extend(this.buttonClasses, {\n 'action-basic': !this.displayAsLink,\n 'action-additional': this.displayAsLink\n });\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/components/insert-form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n './insert',\n 'mageUtils',\n 'jquery'\n], function (Insert, utils, $) {\n 'use strict';\n\n /**\n * Get page actions element.\n *\n * @param {String} elem\n * @param {String} actionsClass\n * @returns {String}\n */\n function getPageActions(elem, actionsClass) {\n var el = document.createElement('div');\n\n el.innerHTML = elem;\n\n return el.getElementsByClassName(actionsClass)[0];\n }\n\n /**\n * Return element without page actions toolbar\n *\n * @param {String} elem\n * @param {String} actionsClass\n * @returns {String}\n */\n function removePageActions(elem, actionsClass) {\n var el = document.createElement('div'),\n actions;\n\n el.innerHTML = elem;\n actions = el.getElementsByClassName(actionsClass)[0];\n\n if (actions) {\n el.removeChild(actions);\n }\n\n return el.innerHTML;\n }\n\n return Insert.extend({\n defaults: {\n externalFormName: '${ $.ns }.${ $.ns }',\n pageActionsClass: 'page-actions',\n actionsContainerClass: 'page-main-actions',\n exports: {\n prefix: '${ $.externalFormName }:selectorPrefix'\n },\n imports: {\n toolbarSection: '${ $.toolbarContainer }:toolbarSection',\n prefix: '${ $.toolbarContainer }:rootSelector',\n messagesClass: '${ $.externalFormName }:messagesClass'\n },\n settings: {\n ajax: {\n ajaxSave: true,\n exports: {\n ajaxSave: '${ $.externalFormName }:ajaxSave'\n },\n imports: {\n responseStatus: '${ $.externalFormName }:responseStatus',\n responseData: '${ $.externalFormName }:responseData'\n }\n }\n },\n modules: {\n externalForm: '${ $.externalFormName }'\n }\n },\n\n /** @inheritdoc */\n initObservable: function () {\n return this._super()\n .observe('responseStatus');\n },\n\n /** @inheritdoc */\n initConfig: function (config) {\n var defaults = this.constructor.defaults;\n\n utils.extend(defaults, defaults.settings[config.formSubmitType] || {});\n\n return this._super();\n },\n\n /** @inheritdoc*/\n destroyInserted: function () {\n if (this.isRendered && this.externalForm()) {\n this.externalForm().delegate('destroy');\n this.removeActions();\n this.responseStatus(undefined);\n this.responseData = {};\n }\n\n return this._super();\n },\n\n /** @inheritdoc */\n onRender: function (data) {\n var actions = getPageActions(data, this.pageActionsClass);\n\n if (!data.length) {\n return this;\n }\n data = removePageActions(data, this.pageActionsClass);\n this.renderActions(actions);\n this._super(data);\n },\n\n /**\n * Insert actions in toolbar.\n *\n * @param {String} actions\n */\n renderActions: function (actions) {\n var $container = $('<div></div>');\n\n $container\n .addClass(this.actionsContainerClass)\n .append(actions);\n\n this.formHeader = $container;\n\n $(this.toolbarSection).append(this.formHeader);\n },\n\n /**\n * Remove actions toolbar.\n */\n removeActions: function () {\n $(this.formHeader).siblings('.' + this.messagesClass).remove();\n $(this.formHeader).remove();\n this.formHeader = $();\n },\n\n /**\n * Reset external form data.\n */\n resetForm: function () {\n if (this.externalSource()) {\n this.externalSource().trigger('data.reset');\n this.responseStatus(undefined);\n }\n }\n });\n});\n","Magento_Ui/js/form/components/html.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 'uiComponent'\n], function ($, _, Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n content: '',\n showSpinner: false,\n loading: false,\n visible: true,\n template: 'ui/content/content',\n additionalClasses: {},\n ignoreTmpls: {\n content: true\n }\n },\n\n /**\n * Extends instance with default config, calls 'initialize' method of\n * parent, calls 'initAjaxConfig'\n */\n initialize: function () {\n _.bindAll(this, 'onContainerToggle', 'onDataLoaded');\n\n this._super()\n ._setClasses()\n .initAjaxConfig();\n\n return this;\n },\n\n /**\n * Calls 'initObservable' method of parent, initializes observable\n * properties of instance\n *\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('content loading visible');\n\n return this;\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Group} Chainable.\n */\n _setClasses: function () {\n var additional = this.additionalClasses,\n classes;\n\n if (_.isString(additional)) {\n additional = this.additionalClasses.split(' ');\n classes = this.additionalClasses = {};\n\n additional.forEach(function (name) {\n classes[name] = true;\n }, this);\n }\n\n _.extend(this.additionalClasses, {\n 'admin__scope-old': !!additional\n });\n\n return this;\n },\n\n /** @inheritdoc */\n initContainer: function (parent) {\n this._super();\n\n parent.on('active', this.onContainerToggle);\n\n return this;\n },\n\n /**\n * Initializes default ajax config on instance\n *\n * @return {Object} - reference to instance\n */\n initAjaxConfig: function () {\n this.ajaxConfig = {\n url: this.url,\n data: {\n FORM_KEY: window.FORM_KEY\n },\n success: this.onDataLoaded\n };\n\n return this;\n },\n\n /**\n * Calls 'loadData' if both 'active' variable and 'shouldLoad'\n * property are truthy\n *\n * @param {Boolean} active\n */\n onContainerToggle: function (active) {\n if (active && this.shouldLoad()) {\n this.loadData();\n }\n },\n\n /**\n * Defines if instance has 'content' property defined.\n *\n * @return {Boolean} [description]\n */\n hasData: function () {\n return !!this.content();\n },\n\n /**\n * Defines if instance should load external data\n *\n * @return {Boolean}\n */\n shouldLoad: function () {\n return this.url && !this.hasData() && !this.loading();\n },\n\n /**\n * Sets loading property to true, makes ajax call\n *\n * @return {Object} - reference to instance\n */\n loadData: function () {\n this.loading(true);\n\n $.ajax(this.ajaxConfig);\n\n return this;\n },\n\n /**\n * Ajax's request success handler. Calls 'updateContent' passing 'data'\n * to it, then sets 'loading' property to false.\n *\n * @param {String} data\n */\n onDataLoaded: function (data) {\n this.updateContent(data)\n .loading(false);\n },\n\n /**\n * Sets incoming data 'content' property's value\n *\n * @param {String} content\n * @return {Object} - reference to instance\n */\n updateContent: function (content) {\n this.content(content);\n\n return this;\n },\n\n /**\n * Content getter\n *\n * @returns {String}\n */\n getContentUnsanitizedHtml: function () {\n return this.content();\n }\n });\n});\n","Magento_Ui/js/form/components/area.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n './tab'\n], function (_, Tab) {\n 'use strict';\n\n return Tab.extend({\n defaults: {\n uniqueNs: 'params.activeArea',\n template: 'ui/area',\n changed: false,\n loading: false\n },\n\n /**\n * Extends instance with defaults. Invokes parent initialize method.\n * Calls initListeners and pushParams methods.\n */\n initialize: function () {\n _.bindAll(this, 'onChildrenUpdate', 'onContentLoading');\n\n return this._super();\n },\n\n /**\n * Calls initObservable of parent class.\n * Defines observable properties of instance.\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('changed loading');\n\n return this;\n },\n\n /**\n * Calls parent's initElement method.\n * Assigns callbacks on various events of incoming element.\n * @param {Object} elem\n * @return {Object} - reference to instance\n */\n initElement: function (elem) {\n this._super();\n\n elem.on({\n 'update': this.onChildrenUpdate,\n 'loading': this.onContentLoading\n });\n\n return this;\n },\n\n /**\n * Is being invoked on children update.\n * Sets changed property to one incoming.\n * Invokes setActive method if settings\n * contain makeVisible property set to true.\n *\n * @param {Boolean} hasChanged\n */\n onChildrenUpdate: function (hasChanged) {\n if (!hasChanged) {\n hasChanged = _.some(this.delegate('hasChanged'));\n }\n\n this.changed(hasChanged);\n },\n\n /**\n * Callback that sets loading property to true.\n */\n onContentLoading: function (isLoading) {\n this.loading(isLoading);\n }\n });\n});\n","Magento_Ui/js/form/components/tab.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiCollection'\n], function (Collection) {\n 'use strict';\n\n return Collection.extend({\n defaults: {\n uniqueProp: 'active',\n active: false,\n wasActivated: false\n },\n\n /**\n * Extends instance with defaults. Invokes parent initialize method.\n * Calls initListeners and pushParams methods.\n */\n initialize: function () {\n this._super()\n .setUnique();\n },\n\n /**\n * Calls initObservable of parent class.\n * Defines observable properties of instance.\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('active wasActivated');\n\n return this;\n },\n\n /**\n * Sets active property to true, then invokes pushParams method.\n */\n activate: function () {\n this.active(true);\n this.wasActivated(true);\n\n this.setUnique();\n\n return true;\n }\n });\n});\n","Magento_Ui/js/form/components/collection/item.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n '../tab'\n], function (_, utils, Tab) {\n 'use strict';\n\n var previewConfig = {\n separator: ' ',\n prefix: ''\n };\n\n /**\n * Parses incoming data and returns result merged with default preview config\n *\n * @param {Object|String} data\n * @return {Object}\n */\n function parsePreview(data) {\n if (typeof data == 'string') {\n data = {\n items: data\n };\n }\n\n data.items = utils.stringToArray(data.items);\n\n return _.defaults(data, previewConfig);\n }\n\n return Tab.extend({\n defaults: {\n label: '',\n uniqueNs: 'activeCollectionItem',\n previewTpl: 'ui/form/components/collection/preview'\n },\n\n /**\n * Extends instance with default config, calls initializes of parent class\n */\n initialize: function () {\n _.bindAll(this, 'buildPreview', 'hasPreview');\n\n return this._super();\n },\n\n /**\n * Calls initProperties of parent class, initializes properties\n * of instance.\n *\n * @return {Object} - reference to instance\n */\n initConfig: function () {\n this._super();\n\n this.displayed = [];\n\n return this;\n },\n\n /**\n * Calls initObservable of parent class, initializes observable\n * properties of instance.\n *\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe({\n noPreview: true,\n indexed: {}\n });\n\n return this;\n },\n\n /**\n * Is being called when child element has been initialized,\n * calls initElement of parent class, binds to element's update event,\n * calls insertToArea and insertToIndexed methods passing element to it\n *\n * @param {Object} elem\n */\n initElement: function (elem) {\n this._super()\n .insertToIndexed(elem);\n\n return this;\n },\n\n /**\n * Adds element to observable indexed object of instance\n *\n * @param {Object} elem\n * @return {Object} - reference to instance\n */\n insertToIndexed: function (elem) {\n var indexed = this.indexed();\n\n indexed[elem.index] = elem;\n\n this.indexed(indexed);\n\n return this;\n },\n\n /**\n * Destroys current instance along with all of its' children.\n * Overrides base method to clear data when this method is called.\n */\n destroy: function () {\n this._super();\n this._clearData();\n },\n\n /**\n * Clears all data associated with component.\n * @private\n *\n * @returns {Item} Chainable.\n */\n _clearData: function () {\n this.source.remove(this.dataScope);\n\n return this;\n },\n\n /**\n * Formats incoming previews array via parsePreview function.\n *\n * @param {Array} previews\n * @return {Array} - formatted previews\n */\n formatPreviews: function (previews) {\n return previews.map(parsePreview);\n },\n\n /**\n * Creates string view of previews\n *\n * @param {Object} data\n * @return {Strict} - formatted preview string\n */\n buildPreview: function (data) {\n var preview = this.getPreview(data.items),\n prefix = data.prefix;\n\n return prefix + preview.join(data.separator);\n },\n\n /**\n * Defines if instance has preview for incoming data\n *\n * @param {Object} data\n * @return {Boolean}\n */\n hasPreview: function (data) {\n return !!this.getPreview(data.items).length;\n },\n\n /**\n * Creates an array of previews for elements specified in incoming\n * items array, calls updatePreview afterwards.\n *\n * @param {Array} items - An array of element's indexes.\n * @returns {Array} An array of previews.\n */\n getPreview: function (items) {\n var elems = this.indexed(),\n displayed = this.displayed,\n preview;\n\n items = items.map(function (index) {\n var elem = elems[index];\n\n preview = elem && elem.visible() ? elem.getPreview() : '';\n\n preview = Array.isArray(preview) ?\n _.compact(preview).join(', ') :\n preview;\n\n utils.toggle(displayed, index, !!preview);\n\n return preview;\n });\n\n this.noPreview(!displayed.length);\n\n return _.compact(items);\n }\n });\n});\n","Magento_Ui/js/form/element/date.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'moment',\n 'mageUtils',\n './abstract',\n 'moment-timezone-with-data'\n], function (moment, utils, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n options: {},\n\n storeTimeZone: 'UTC',\n\n validationParams: {\n dateFormat: '${ $.outputDateFormat }'\n },\n\n /**\n * Format of date that comes from the\n * server (ICU Date Format).\n *\n * Used only in date picker mode\n * (this.options.showsTime == false).\n *\n * @type {String}\n */\n inputDateFormat: 'y-MM-dd',\n\n /**\n * Format of date that should be sent to the\n * server (ICU Date Format).\n *\n * Used only in date picker mode\n * (this.options.showsTime == false).\n *\n * @type {String}\n */\n outputDateFormat: 'MM/dd/y',\n\n /**\n * Date/time format that is used to display date in\n * the input field.\n *\n * @type {String}\n */\n pickerDateTimeFormat: '',\n\n pickerDefaultDateFormat: 'MM/dd/y', // ICU Date Format\n pickerDefaultTimeFormat: 'h:mm a', // ICU Time Format\n\n elementTmpl: 'ui/form/element/date',\n\n /**\n * Format needed by moment timezone for conversion\n */\n timezoneFormat: 'YYYY-MM-DD HH:mm',\n\n listens: {\n 'value': 'onValueChange',\n 'shiftedValue': 'onShiftedValueChange'\n },\n\n /**\n * Date/time value shifted to corresponding timezone\n * according to this.storeTimeZone property. This value\n * will be sent to the server.\n *\n * @type {String}\n */\n shiftedValue: ''\n },\n\n /**\n * Initializes regular properties of instance.\n *\n * @returns {Object} Chainable.\n */\n initConfig: function () {\n this._super();\n\n if (!this.options.dateFormat) {\n this.options.dateFormat = this.pickerDefaultDateFormat;\n }\n\n if (!this.options.timeFormat) {\n this.options.timeFormat = this.pickerDefaultTimeFormat;\n }\n\n this.prepareDateTimeFormats();\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n initObservable: function () {\n return this._super().observe(['shiftedValue']);\n },\n\n /**\n * @inheritdoc\n */\n getPreview: function () {\n return this.shiftedValue();\n },\n\n /**\n * Prepares and sets date/time value that will be displayed\n * in the input field.\n *\n * @param {String} value\n */\n onValueChange: function (value) {\n var shiftedValue;\n\n if (value) {\n if (this.options.showsTime && !this.options.timeOnly) {\n shiftedValue = moment.tz(value, 'UTC').tz(this.storeTimeZone);\n } else {\n shiftedValue = moment(value, this.outputDateFormat, true);\n }\n\n if (!shiftedValue.isValid()) {\n shiftedValue = moment(value, this.inputDateFormat);\n }\n shiftedValue = shiftedValue.format(this.pickerDateTimeFormat);\n } else {\n shiftedValue = '';\n }\n\n if (shiftedValue !== this.shiftedValue()) {\n this.shiftedValue(shiftedValue);\n }\n },\n\n /**\n * Prepares and sets date/time value that will be sent\n * to the server.\n *\n * @param {String} shiftedValue\n */\n onShiftedValueChange: function (shiftedValue) {\n var value,\n formattedValue,\n momentValue;\n\n if (shiftedValue) {\n momentValue = moment(shiftedValue, this.pickerDateTimeFormat);\n\n if (this.options.showsTime && !this.options.timeOnly) {\n formattedValue = moment(momentValue).format(this.timezoneFormat);\n value = moment.tz(formattedValue, this.storeTimeZone).tz('UTC').toISOString();\n } else {\n value = momentValue.format(this.outputDateFormat);\n }\n } else {\n value = '';\n }\n\n if (value !== this.value()) {\n this.value(value);\n }\n },\n\n /**\n * Prepares and converts all date/time formats to be compatible\n * with moment.js library.\n */\n prepareDateTimeFormats: function () {\n if (this.options.timeOnly) {\n this.pickerDateTimeFormat = this.options.timeFormat;\n } else {\n this.pickerDateTimeFormat = this.options.dateFormat;\n\n if (this.options.showsTime) {\n this.pickerDateTimeFormat += ' ' + this.options.timeFormat;\n }\n }\n\n this.pickerDateTimeFormat = utils.convertToMomentFormat(this.pickerDateTimeFormat);\n\n if (this.options.dateFormat) {\n this.outputDateFormat = this.options.dateFormat;\n }\n\n this.inputDateFormat = this.options.timeOnly ?\n utils.convertToMomentFormat(this.pickerDefaultTimeFormat) :\n utils.convertToMomentFormat(this.inputDateFormat);\n this.outputDateFormat = this.options.timeOnly ?\n utils.convertToMomentFormat(this.options.timeFormat) :\n utils.convertToMomentFormat(this.outputDateFormat);\n\n this.validationParams.dateFormat = this.outputDateFormat;\n }\n });\n});\n","Magento_Ui/js/form/element/country.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiRegistry',\n './select'\n], function (_, registry, Select) {\n 'use strict';\n\n return Select.extend({\n defaults: {\n imports: {\n update: '${ $.parentName }.website_id:value'\n }\n },\n\n /**\n * Filters 'initialOptions' property by 'field' and 'value' passed,\n * calls 'setOptions' passing the result to it\n *\n * @param {*} value\n * @param {String} field\n */\n filter: function (value, field) {\n var result, defaultCountry, defaultValue;\n\n if (!field) { //validate field, if we are on update\n field = this.filterBy.field;\n }\n\n this._super(value, field);\n result = _.filter(this.initialOptions, function (item) {\n\n if (item[field]) {\n return ~item[field].indexOf(value);\n }\n\n return false;\n });\n\n this.setOptions(result);\n this.reset();\n\n if (!this.value()) {\n defaultCountry = _.filter(result, function (item) {\n return item['is_default'] && _.contains(item['is_default'], value);\n });\n\n if (defaultCountry.length) {\n defaultValue = defaultCountry.shift();\n this.value(defaultValue.value);\n }\n }\n }\n });\n});\n\n","Magento_Ui/js/form/element/url-input.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiLayout',\n 'mage/translate',\n 'Magento_Ui/js/form/element/abstract'\n], function (_, layout, $t, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n linkedElement: {},\n settingTemplate: 'ui/form/element/urlInput/setting',\n typeSelectorTemplate: 'ui/form/element/urlInput/typeSelector',\n options: [],\n linkedElementInstances: {},\n //checkbox\n isDisplayAdditionalSettings: true,\n settingValue: false,\n settingLabel: $t('Open in new tab'),\n tracks: {\n linkedElement: true\n },\n baseLinkSetting: {\n namePrefix: '${$.name}.',\n dataScopePrefix: '${$.dataScope}.',\n provider: '${$.provider}'\n },\n urlTypes: {},\n listens: {\n settingValue: 'checked',\n disabled: 'hideLinkedElement',\n linkType: 'createChildUrlInputComponent'\n },\n links: {\n linkType: '${$.provider}:${$.dataScope}.type',\n settingValue: '${$.provider}:${$.dataScope}.setting'\n }\n },\n\n /** @inheritdoc */\n initConfig: function (config) {\n var processedLinkTypes = {},\n baseLinkType = this.constructor.defaults.baseLinkSetting;\n\n _.each(config.urlTypes, function (linkSettingsArray, linkName) {\n //add link name by link type\n linkSettingsArray.name = baseLinkType.namePrefix + linkName;\n linkSettingsArray.dataScope = baseLinkType.dataScopePrefix + linkName;\n linkSettingsArray.type = linkName;\n linkSettingsArray.disabled = config.disabled;\n linkSettingsArray.visible = config.visible;\n processedLinkTypes[linkName] = {};\n _.extend(processedLinkTypes[linkName], baseLinkType, linkSettingsArray);\n });\n _.extend(this.constructor.defaults.urlTypes, processedLinkTypes);\n\n this._super();\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @returns {Abstract} Chainable.\n */\n initObservable: function () {\n this._super()\n .observe('componentTemplate options value linkType settingValue checked isDisplayAdditionalSettings')\n .setOptions();\n\n return this;\n },\n\n /**\n * Set options to select based on link types configuration\n *\n * @return {Object}\n */\n setOptions: function () {\n var result = [];\n\n _.each(this.urlTypes, function (option, key) {\n result.push({\n value: key,\n label: option.label,\n sortOrder: option.sortOrder || 0\n });\n });\n\n //sort options by sortOrder\n result.sort(function (a, b) {\n return a.sortOrder > b.sortOrder ? 1 : -1;\n });\n\n this.options(result);\n\n return this;\n },\n\n /** @inheritdoc */\n setPreview: function (visible) {\n this.linkedElement().visible(visible);\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @param {Boolean} disabled\n */\n hideLinkedElement: function (disabled) {\n this.linkedElement().disabled(disabled);\n },\n\n /** @inheritdoc */\n destroy: function () {\n _.each(this.linkedElementInstances, function (value) {\n value().destroy();\n });\n this._super();\n },\n\n /**\n * Create child component by value\n *\n * @param {String} value\n * @return void\n */\n createChildUrlInputComponent: function (value) {\n var elementConfig;\n\n if (!_.isEmpty(value) && _.isUndefined(this.linkedElementInstances[value])) {\n elementConfig = this.urlTypes[value];\n layout([elementConfig]);\n this.linkedElementInstances[value] = this.requestModule(elementConfig.name);\n }\n this.linkedElement = this.linkedElementInstances[value];\n\n },\n\n /**\n * Returns linked element to display related field in template\n * @return String\n */\n getLinkedElementName: function () {\n return this.linkedElement;\n },\n\n /**\n * Add ability to choose check box by clicking on label\n */\n checkboxClick: function () {\n if (!this.disabled()) {\n this.settingValue(!this.settingValue());\n }\n }\n });\n});\n","Magento_Ui/js/form/element/color-picker-palette.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @api\n */\ndefine([], function () {\n 'use strict';\n\n return [\n [\n 'rgb(0,0,0)', 'rgb(52,52,52)', 'rgb(83,83,83)', 'rgb(135,135,135)', 'rgb(193,193,193)',\n 'rgb(234,234,234)', 'rgb(240,240,240)', 'rgb(255,255,255)'\n ],\n [\n 'rgb(252,0,9)', 'rgb(253,135,10)', 'rgb(255,255,13)', 'rgb(35,255,9)', 'rgb(33,255,255)',\n 'rgb(0,0,254)', 'rgb(132,0,254)', 'rgb(251,0,255)'\n ],\n [\n 'rgb(240,192,194)', 'rgb(251,223,194)', 'rgb(255,241,193)', 'rgb(210,230,201)',\n 'rgb(199,217,220)', 'rgb(197,219,240)', 'rgb(208,200,227)', 'rgb(229,199,212)'\n ],\n [\n 'rgb(228,133,135)', 'rgb(246,193,139)', 'rgb(254,225,136)', 'rgb(168,208,152)',\n 'rgb(146,184,190)', 'rgb(143,184,227)', 'rgb(165,148,204)', 'rgb(202,147,175)'\n ],\n [\n 'rgb(214,78,83)', 'rgb(243,163,88)', 'rgb(254,211,83)', 'rgb(130,187,106)',\n 'rgb(99,149,159)', 'rgb(93,150,211)', 'rgb(123,100,182)', 'rgb(180,100,142)'\n ],\n [\n 'rgb(190,0,5)', 'rgb(222,126,44)', 'rgb(236,183,39)', 'rgb(89,155,61)', 'rgb(55,110,123)',\n 'rgb(49,112,185)', 'rgb(83,55,150)', 'rgb(147,55,101)'\n ],\n [\n 'rgb(133,0,3)', 'rgb(163,74,10)', 'rgb(177,127,7)', 'rgb(45,101,23)', 'rgb(18,62,74)',\n 'rgb(14,62,129)', 'rgb(40,15,97)', 'rgb(95,16,55)'\n ],\n [\n 'rgb(81,0,1)', 'rgb(100,48,7)', 'rgb(107,78,3)', 'rgb(31,63,16)',\n 'rgb(13,39,46)', 'rgb(10,40,79)', 'rgb(24,12,59)', 'rgb(59,10,36)'\n ]\n ];\n});\n","Magento_Ui/js/form/element/region.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiRegistry',\n './select',\n 'Magento_Checkout/js/model/default-post-code-resolver'\n], function (_, registry, Select, defaultPostCodeResolver) {\n 'use strict';\n\n return Select.extend({\n defaults: {\n skipValidation: false,\n imports: {\n countryOptions: '${ $.parentName }.country_id:indexedOptions',\n update: '${ $.parentName }.country_id:value'\n }\n },\n\n /**\n * {@inheritdoc}\n */\n initialize: function () {\n var option;\n\n this._super();\n\n option = _.find(this.countryOptions, function (row) {\n return row['is_default'] === true;\n });\n this.hideRegion(option);\n\n return this;\n },\n\n /**\n * Method called every time country selector's value gets changed.\n * Updates all validations and requirements for certain country.\n * @param {String} value - Selected country ID.\n */\n update: function (value) {\n var isRegionRequired,\n option;\n\n if (!value) {\n return;\n }\n\n option = _.isObject(this.countryOptions) && this.countryOptions[value];\n\n if (!option) {\n return;\n }\n\n this.hideRegion(option);\n\n defaultPostCodeResolver.setUseDefaultPostCode(!option['is_zipcode_optional']);\n\n isRegionRequired = !this.skipValidation && !!option['is_region_required'];\n\n if (!isRegionRequired) {\n this.error(false);\n }\n\n this.required(isRegionRequired);\n this.validation['required-entry'] = isRegionRequired;\n\n registry.get(this.customName, function (input) {\n input.required(isRegionRequired);\n input.validation['required-entry'] = isRegionRequired;\n input.validation['validate-not-number-first'] = !this.options().length;\n }.bind(this));\n },\n\n /**\n * Hide select and corresponding text input field if region must not be shown for selected country.\n *\n * @private\n * @param {Object}option\n */\n hideRegion: function (option) {\n if (!option || option['is_region_visible'] !== false) {\n return;\n }\n\n this.setVisible(false);\n\n if (this.customEntry) {\n this.toggleInput(false);\n }\n }\n });\n});\n","Magento_Ui/js/form/element/textarea.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n './abstract'\n], function (Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n cols: 15,\n rows: 2,\n elementTmpl: 'ui/form/element/textarea'\n }\n });\n});\n","Magento_Ui/js/form/element/text.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiElement',\n 'mageUtils'\n], function (Element, utils) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n visible: true,\n label: '',\n error: '',\n uid: utils.uniqueid(),\n disabled: false,\n links: {\n value: '${ $.provider }:${ $.dataScope }'\n }\n },\n\n /**\n * Has service\n *\n * @returns {Boolean} false.\n */\n hasService: function () {\n return false;\n },\n\n /**\n * Has addons\n *\n * @returns {Boolean} false.\n */\n hasAddons: function () {\n return false;\n },\n\n /**\n * Calls 'initObservable' of parent\n *\n * @returns {Object} Chainable.\n */\n initObservable: function () {\n this._super()\n .observe('disabled visible value');\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/wysiwyg.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'wysiwygAdapter',\n 'Magento_Ui/js/lib/view/utils/async',\n 'underscore',\n 'ko',\n './abstract',\n 'mage/adminhtml/events',\n 'Magento_Variable/variables'\n], function (wysiwyg, $, _, ko, Abstract, varienGlobalEvents) {\n 'use strict';\n\n return Abstract.extend({\n currentWysiwyg: undefined,\n defaults: {\n elementSelector: 'textarea',\n suffixRegExpPattern: '${ $.wysiwygUniqueSuffix }',\n $wysiwygEditorButton: '',\n links: {\n value: '${ $.provider }:${ $.dataScope }'\n },\n template: 'ui/form/field',\n elementTmpl: 'ui/form/element/wysiwyg',\n content: '',\n showSpinner: false,\n loading: false,\n listens: {\n disabled: 'setDisabled'\n }\n },\n\n /**\n *\n * @returns {} Chainable.\n */\n initialize: function () {\n this._super()\n .initNodeListener();\n\n $.async({\n component: this,\n selector: 'button'\n }, function (element) {\n this.$wysiwygEditorButton = this.$wysiwygEditorButton ?\n this.$wysiwygEditorButton.add($(element)) : $(element);\n }.bind(this));\n\n // disable editor completely after initialization is field is disabled\n varienGlobalEvents.attachEventHandler('wysiwygEditorInitialized', function () {\n if (!_.isUndefined(window.tinyMceEditors)) {\n this.currentWysiwyg = window.tinyMceEditors[this.wysiwygId];\n }\n\n if (this.disabled()) {\n this.setDisabled(true);\n }\n }.bind(this));\n\n return this;\n },\n\n /** @inheritdoc */\n initConfig: function (config) {\n var pattern = config.suffixRegExpPattern || this.constructor.defaults.suffixRegExpPattern;\n\n pattern = pattern.replace(/\\$/g, '\\\\$&');\n config.content = config.content.replace(new RegExp(pattern, 'g'), this.getUniqueSuffix(config));\n this._super();\n\n return this;\n },\n\n /**\n * Build unique id based on name, underscore separated.\n *\n * @param {Object} config\n */\n getUniqueSuffix: function (config) {\n return config.name.replace(/(\\.|-)/g, '_');\n },\n\n /**\n * @inheritdoc\n */\n destroy: function () {\n this._super();\n wysiwyg.removeEvents(this.wysiwygId);\n },\n\n /**\n *\n * @returns {exports}\n */\n initObservable: function () {\n this._super()\n .observe(['value', 'content']);\n\n return this;\n },\n\n /**\n *\n * @returns {} Chainable.\n */\n initNodeListener: function () {\n $.async({\n component: this,\n selector: this.elementSelector\n }, this.setElementNode.bind(this));\n\n return this;\n },\n\n /**\n *\n * @param {HTMLElement} node\n */\n setElementNode: function (node) {\n $(node).bindings({\n value: this.value\n });\n },\n\n /**\n * Set disabled property to wysiwyg component\n *\n * @param {Boolean} disabled\n */\n setDisabled: function (disabled) {\n if (this.$wysiwygEditorButton && disabled) {\n this.$wysiwygEditorButton.prop('disabled', 'disabled');\n } else if (this.$wysiwygEditorButton) {\n this.$wysiwygEditorButton.prop('disabled', false);\n }\n\n /* eslint-disable no-undef */\n if (!_.isUndefined(this.currentWysiwyg) && this.currentWysiwyg.activeEditor()) {\n this.currentWysiwyg.setEnabledStatus(!disabled);\n this.currentWysiwyg.getPluginButtons().prop('disabled', disabled);\n }\n },\n\n /**\n * Content getter\n *\n * @returns {String}\n */\n getContentUnsanitizedHtml: function () {\n return this.content();\n }\n });\n});\n","Magento_Ui/js/form/element/image-uploader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global Base64 */\ndefine([\n 'jquery',\n 'underscore',\n 'mageUtils',\n 'Magento_Ui/js/modal/alert',\n 'Magento_Ui/js/lib/validation/validator',\n 'Magento_Ui/js/form/element/file-uploader',\n 'mage/adminhtml/browser'\n], function ($, _, utils, uiAlert, validator, Element, browser) {\n 'use strict';\n\n return Element.extend({\n /**\n * {@inheritDoc}\n */\n initialize: function () {\n this._super();\n\n // Listen for file deletions from the media browser\n $(window).on('fileDeleted.mediabrowser', this.onDeleteFile.bind(this));\n },\n\n /**\n * Assign uid for media gallery\n *\n * @return {ImageUploader} Chainable.\n */\n initConfig: function () {\n var mediaGalleryUid = utils.uniqueid();\n\n this._super();\n\n _.extend(this, {\n mediaGalleryUid: mediaGalleryUid\n });\n\n return this;\n },\n\n /**\n * Add file event callback triggered from media gallery\n *\n * @param {ImageUploader} imageUploader - UI Class\n * @param {Event} e\n */\n addFileFromMediaGallery: function (imageUploader, e) {\n var $buttonEl = $(e.target),\n fileSize = $buttonEl.data('size'),\n fileMimeType = $buttonEl.data('mime-type'),\n filePathname = $buttonEl.val(),\n fileBasename = filePathname.split('/').pop();\n\n this.addFile({\n type: fileMimeType,\n name: fileBasename,\n size: fileSize,\n url: filePathname\n });\n },\n\n /**\n * Open the media browser dialog\n *\n * @param {ImageUploader} imageUploader - UI Class\n * @param {Event} e\n */\n openMediaBrowserDialog: function (imageUploader, e) {\n var $buttonEl = $(e.target),\n openDialogUrl = this.mediaGallery.openDialogUrl +\n 'target_element_id/' + $buttonEl.attr('id') +\n '/store/' + this.mediaGallery.storeId +\n '/type/image/?isAjax=true';\n\n if (this.mediaGallery.initialOpenSubpath) {\n openDialogUrl += '¤t_tree_path=' + Base64.idEncode(this.mediaGallery.initialOpenSubpath);\n }\n\n browser.openDialog(\n openDialogUrl,\n null,\n null,\n this.mediaGallery.openDialogTitle,\n {\n targetElementId: $buttonEl.attr('id')\n }\n );\n },\n\n /**\n * @param {jQuery.event} e\n * @param {Object} data\n * @returns {Object} Chainables\n */\n onDeleteFile: function (e, data) {\n var fileId = this.getFileId(),\n deletedFileIds = data.ids;\n\n if (fileId && $.inArray(fileId, deletedFileIds) > -1) {\n this.clear();\n }\n\n return this;\n },\n\n /**\n * {@inheritDoc}\n */\n clear: function () {\n this.value([]);\n\n return this;\n },\n\n /**\n * Gets the ID of the file used if set\n *\n * @return {String|Null} ID\n */\n getFileId: function () {\n return this.hasData() ? this.value()[0].id : null;\n },\n\n /**\n * Trigger native browser file upload UI via clicking on 'Upload' button\n *\n * @param {ImageUploader} imageUploader - UI Class\n * @param {Event} e\n */\n triggerImageUpload: function (imageUploader, e) {\n $(e.target).closest('.file-uploader').find('input[type=\"file\"]').trigger('click');\n },\n\n /**\n * Get list of file extensions allowed in comma delimited format\n *\n * @return {String}\n */\n getAllowedFileExtensionsInCommaDelimitedFormat: function () {\n var allowedExtensions = this.allowedExtensions.toUpperCase().split(' ');\n\n // if jpg and jpeg in allowed extensions, remove jpeg from list\n if (allowedExtensions.indexOf('JPG') !== -1 && allowedExtensions.indexOf('JPEG') !== -1) {\n allowedExtensions.splice(allowedExtensions.indexOf('JPEG'), 1);\n }\n\n return allowedExtensions.join(', ');\n }\n });\n});\n","Magento_Ui/js/form/element/single-checkbox-use-config.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'Magento_Ui/js/form/element/single-checkbox'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n isUseDefault: false,\n isUseConfig: false,\n listens: {\n 'isUseConfig': 'toggleElement',\n 'isUseDefault': 'toggleElement'\n }\n },\n\n /**\n * @inheritdoc\n */\n initObservable: function () {\n\n return this\n ._super()\n .observe('isUseConfig');\n },\n\n /**\n * Toggle element\n */\n toggleElement: function () {\n this.disabled(this.isUseDefault() || this.isUseConfig());\n\n if (this.source) {\n this.source.set('data.use_default.' + this.index, Number(this.isUseDefault()));\n }\n }\n });\n});\n","Magento_Ui/js/form/element/checkbox-set.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n './abstract'\n], function (_, utils, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n template: 'ui/form/element/checkbox-set',\n multiple: false,\n multipleScopeValue: null\n },\n\n /**\n * @inheritdoc\n */\n initConfig: function () {\n this._super();\n\n this.value = this.normalizeData(this.value);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n initLinks: function () {\n var scope = this.source.get(this.dataScope);\n\n this.multipleScopeValue = this.multiple && _.isArray(scope) ? utils.copy(scope) : undefined;\n\n return this._super();\n },\n\n /**\n * @inheritdoc\n */\n reset: function () {\n this.value(utils.copy(this.initialValue));\n this.error(false);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n clear: function () {\n var value = this.multiple ? [] : '';\n\n this.value(value);\n this.error(false);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n normalizeData: function (value) {\n if (!this.multiple) {\n return this._super();\n }\n\n return _.isArray(value) ? utils.copy(value) : [];\n },\n\n /**\n * @inheritdoc\n */\n setInitialValue: function () {\n this._super();\n\n this.initialValue = utils.copy(this.initialValue);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n getInitialValue: function () {\n var values = [this.multipleScopeValue, this.default, this.value.peek(), []],\n value;\n\n if (!this.multiple) {\n return this._super();\n }\n\n values.some(function (v) {\n return _.isArray(v) && (value = utils.copy(v));\n });\n\n return value;\n },\n\n /**\n * Returns labels which matches current value.\n *\n * @returns {String|Array}\n */\n getPreview: function () {\n var option;\n\n if (!this.multiple) {\n option = this.getOption(this.value());\n\n return option ? option.label : '';\n }\n\n return this.value.map(function (value) {\n return this.getOption(value).label;\n }, this);\n },\n\n /**\n * Returns option object associated with provided value.\n *\n * @param {String} value\n * @returns {Object}\n */\n getOption: function (value) {\n return _.findWhere(this.options, {\n value: value\n });\n },\n\n /**\n * @inheritdoc\n */\n hasChanged: function () {\n var value = this.value(),\n initial = this.initialValue;\n\n return this.multiple ?\n !utils.equalArrays(value, initial) :\n this._super();\n }\n });\n});\n","Magento_Ui/js/form/element/media.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'mageUtils',\n './abstract'\n], function (utils, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n links: {\n value: ''\n }\n },\n\n /**\n * Initializes file component.\n *\n * @returns {Media} Chainable.\n */\n initialize: function () {\n this._super()\n .initFormId();\n\n return this;\n },\n\n /**\n * Defines form ID with which file input will be associated.\n *\n * @returns {Media} Chainable.\n */\n initFormId: function () {\n var namespace;\n\n if (this.formId) {\n return this;\n }\n\n namespace = this.name.split('.');\n this.formId = namespace[0];\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/single-checkbox-toggle-notice.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'Magento_Ui/js/form/element/single-checkbox'\n], function (SingleCheckbox) {\n 'use strict';\n\n return SingleCheckbox.extend({\n defaults: {\n notices: [],\n tracks: {\n notice: true\n }\n },\n\n /**\n * Choose notice on initialization\n *\n * @returns {*|void|Element}\n */\n initialize: function () {\n this._super()\n .chooseNotice();\n\n return this;\n },\n\n /**\n * Choose notice function\n *\n * @returns void\n */\n chooseNotice: function () {\n var checkedNoticeNumber = Number(this.checked());\n\n this.notice = this.notices[checkedNoticeNumber];\n },\n\n /**\n * Choose notice on update\n *\n * @returns void\n */\n onUpdate: function () {\n this._super();\n this.chooseNotice();\n }\n });\n});\n","Magento_Ui/js/form/element/single-checkbox.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'Magento_Ui/js/form/element/abstract',\n 'underscore',\n 'mage/translate'\n], function (AbstractField, _, $t) {\n 'use strict';\n\n return AbstractField.extend({\n defaults: {\n template: 'ui/form/components/single/field',\n checked: false,\n initialChecked: false,\n multiple: false,\n prefer: 'checkbox', // 'radio' | 'checkbox' | 'toggle'\n valueMap: {},\n\n templates: {\n radio: 'ui/form/components/single/radio',\n checkbox: 'ui/form/components/single/checkbox',\n toggle: 'ui/form/components/single/switcher'\n },\n\n listens: {\n 'checked': 'onCheckedChanged',\n 'value': 'onExtendedValueChanged'\n }\n },\n\n /**\n * @inheritdoc\n */\n initConfig: function (config) {\n this._super();\n\n if (!config.elementTmpl) {\n if (!this.prefer && !this.multiple) {\n this.elementTmpl = this.templates.radio;\n } else if (this.prefer === 'radio') {\n this.elementTmpl = this.templates.radio;\n } else if (this.prefer === 'checkbox') {\n this.elementTmpl = this.templates.checkbox;\n } else if (this.prefer === 'toggle') {\n this.elementTmpl = this.templates.toggle;\n } else {\n this.elementTmpl = this.templates.checkbox;\n }\n }\n\n if (this.prefer === 'toggle' && _.isEmpty(this.toggleLabels)) {\n this.toggleLabels = {\n 'on': $t('Yes'),\n 'off': $t('No')\n };\n }\n\n if (typeof this.default === 'undefined' || this.default === null) {\n this.default = '';\n }\n\n if (typeof this.value === 'undefined' || this.value === null) {\n this.value = _.isEmpty(this.valueMap) || this.default !== '' ? this.default : this.valueMap.false;\n this.initialValue = this.value;\n } else {\n this.initialValue = this.value;\n }\n\n if (this.multiple && !_.isArray(this.value)) {\n this.value = []; // needed for correct observable assignment\n }\n\n this.initialChecked = this.checked;\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n initObservable: function () {\n return this\n ._super()\n .observe('checked');\n },\n\n /**\n * Get true/false key from valueMap by value.\n *\n * @param {*} value\n * @returns {Boolean|undefined}\n */\n getReverseValueMap: function getReverseValueMap(value) {\n var bool = false;\n\n _.some(this.valueMap, function (iValue, iBool) {\n if (iValue === value) {\n bool = iBool === 'true';\n\n return true;\n }\n });\n\n return bool;\n },\n\n /**\n * @inheritdoc\n */\n setInitialValue: function () {\n if (_.isEmpty(this.valueMap)) {\n this.on('value', this.onUpdate.bind(this));\n } else {\n this._super();\n this.checked(this.getReverseValueMap(this.value()));\n }\n\n return this;\n },\n\n /**\n * Handle dataScope changes for checkbox / radio button.\n *\n * @param {*} newExportedValue\n */\n onExtendedValueChanged: function (newExportedValue) {\n var isMappedUsed = !_.isEmpty(this.valueMap),\n oldChecked = this.checked.peek(),\n oldValue = this.initialValue,\n newChecked;\n\n if (this.multiple) {\n newChecked = newExportedValue.indexOf(oldValue) !== -1;\n } else if (isMappedUsed) {\n newChecked = this.getReverseValueMap(newExportedValue);\n } else if (typeof newExportedValue === 'boolean') {\n newChecked = newExportedValue;\n } else {\n newChecked = newExportedValue === oldValue;\n }\n\n if (newChecked !== oldChecked) {\n this.checked(newChecked);\n }\n },\n\n /**\n * Handle checked state changes for checkbox / radio button.\n *\n * @param {Boolean} newChecked\n */\n onCheckedChanged: function (newChecked) {\n var isMappedUsed = !_.isEmpty(this.valueMap),\n oldValue = this.initialValue,\n newValue;\n\n if (isMappedUsed) {\n newValue = this.valueMap[newChecked];\n } else {\n newValue = oldValue;\n }\n\n if (!this.multiple && newChecked) {\n this.value(newValue);\n } else if (!this.multiple && !newChecked) {\n if (typeof newValue === 'boolean') {\n this.value(newChecked);\n } else if (newValue === this.value.peek()) {\n this.value('');\n }\n\n if (isMappedUsed) {\n this.value(newValue);\n }\n } else if (this.multiple && newChecked && this.value.indexOf(newValue) === -1) {\n this.value.push(newValue);\n } else if (this.multiple && !newChecked && this.value.indexOf(newValue) !== -1) {\n this.value.splice(this.value.indexOf(newValue), 1);\n }\n },\n\n /**\n * @inheritdoc\n */\n onUpdate: function () {\n if (this.hasUnique) {\n this.setUnique();\n }\n\n return this._super();\n },\n\n /**\n * @inheritdoc\n */\n reset: function () {\n if (this.multiple && this.initialChecked) {\n this.value.push(this.initialValue);\n } else if (this.multiple && !this.initialChecked) {\n this.value.splice(this.value.indexOf(this.initialValue), 1);\n } else {\n this.value(this.initialValue);\n }\n\n this.error(false);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n clear: function () {\n if (this.multiple) {\n this.value([]);\n } else {\n this.value('');\n }\n\n this.error(false);\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/website.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiRegistry',\n './select'\n], function (_, registry, Select) {\n 'use strict';\n\n return Select.extend({\n defaults: {\n customerId: null,\n isGlobalScope: 0\n },\n\n /**\n * Website component constructor.\n * @returns {exports}\n */\n initialize: function () {\n this._super();\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/select.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n 'uiRegistry',\n './abstract',\n 'uiLayout'\n], function (_, utils, registry, Abstract, layout) {\n 'use strict';\n\n var inputNode = {\n parent: '${ $.$data.parentName }',\n component: 'Magento_Ui/js/form/element/abstract',\n template: '${ $.$data.template }',\n provider: '${ $.$data.provider }',\n name: '${ $.$data.index }_input',\n dataScope: '${ $.$data.customEntry }',\n customScope: '${ $.$data.customScope }',\n sortOrder: {\n after: '${ $.$data.name }'\n },\n displayArea: 'body',\n label: '${ $.$data.label }'\n };\n\n /**\n * Parses incoming options, considers options with undefined value property\n * as caption\n *\n * @param {Array} nodes\n * @return {Object}\n */\n function parseOptions(nodes, captionValue) {\n var caption,\n value;\n\n nodes = _.map(nodes, function (node) {\n value = node.value;\n\n if (value === null || value === captionValue) {\n if (_.isUndefined(caption)) {\n caption = node.label;\n }\n } else {\n return node;\n }\n });\n\n return {\n options: _.compact(nodes),\n caption: _.isString(caption) ? caption : false\n };\n }\n\n /**\n * Recursively loops over data to find non-undefined, non-array value\n *\n * @param {Array} data\n * @return {*} - first non-undefined value in array\n */\n function findFirst(data) {\n var value;\n\n data.some(function (node) {\n value = node.value;\n\n if (Array.isArray(value)) {\n value = findFirst(value);\n }\n\n return !_.isUndefined(value);\n });\n\n return value;\n }\n\n /**\n * Recursively set to object item like value and item.value like key.\n *\n * @param {Array} data\n * @param {Object} result\n * @returns {Object}\n */\n function indexOptions(data, result) {\n var value;\n\n result = result || {};\n\n data.forEach(function (item) {\n value = item.value;\n\n if (Array.isArray(value)) {\n indexOptions(value, result);\n } else {\n result[value] = item;\n }\n });\n\n return result;\n }\n\n return Abstract.extend({\n defaults: {\n customName: '${ $.parentName }.${ $.index }_input',\n elementTmpl: 'ui/form/element/select',\n caption: '',\n options: []\n },\n\n /**\n * Extends instance with defaults, extends config with formatted values\n * and options, and invokes initialize method of AbstractElement class.\n * If instance's 'customEntry' property is set to true, calls 'initInput'\n */\n initialize: function () {\n this._super();\n\n if (this.customEntry) {\n registry.get(this.name, this.initInput.bind(this));\n }\n\n if (this.filterBy) {\n this.initFilter();\n }\n\n return this;\n },\n\n /**\n * Calls 'initObservable' of parent, initializes 'options' and 'initialOptions'\n * properties, calls 'setOptions' passing options to it\n *\n * @returns {Object} Chainable.\n */\n initObservable: function () {\n this._super();\n\n this.initialOptions = this.options;\n\n this.observe('options caption')\n .setOptions(this.options());\n\n return this;\n },\n\n /**\n * Set link for filter.\n *\n * @returns {Object} Chainable\n */\n initFilter: function () {\n var filter = this.filterBy;\n\n this.filter(this.default, filter.field);\n this.setLinks({\n filter: filter.target\n }, 'imports');\n\n return this;\n },\n\n /**\n * Creates input from template, renders it via renderer.\n *\n * @returns {Object} Chainable.\n */\n initInput: function () {\n layout([utils.template(inputNode, this)]);\n\n return this;\n },\n\n /**\n * Matches specified value with existing options\n * or, if value is not specified, returns value of the first option.\n *\n * @returns {*}\n */\n normalizeData: function () {\n var value = this._super(),\n option;\n\n if (value !== '') {\n option = this.getOption(value);\n\n return option && option.value;\n }\n\n if (!this.caption()) {\n return findFirst(this.options);\n }\n },\n\n /**\n * Filters 'initialOptions' property by 'field' and 'value' passed,\n * calls 'setOptions' passing the result to it\n *\n * @param {*} value\n * @param {String} field\n */\n filter: function (value, field) {\n var source = this.initialOptions,\n result;\n\n field = field || this.filterBy.field;\n\n result = _.filter(source, function (item) {\n return item[field] === value || item.value === '';\n });\n\n this.setOptions(result);\n },\n\n /**\n * Change visibility for input.\n *\n * @param {Boolean} isVisible\n */\n toggleInput: function (isVisible) {\n registry.get(this.customName, function (input) {\n input.setVisible(isVisible);\n });\n },\n\n /**\n * Sets 'data' to 'options' observable array, if instance has\n * 'customEntry' property set to true, calls 'setHidden' method\n * passing !options.length as a parameter\n *\n * @param {Array} data\n * @returns {Object} Chainable\n */\n setOptions: function (data) {\n var captionValue = this.captionValue || '',\n result = parseOptions(data, captionValue),\n isVisible;\n\n this.indexedOptions = indexOptions(result.options);\n\n this.options(result.options);\n\n if (!this.caption()) {\n this.caption(result.caption);\n }\n\n if (this.customEntry) {\n isVisible = !!result.options.length;\n\n this.setVisible(isVisible);\n this.toggleInput(!isVisible);\n }\n\n return this;\n },\n\n /**\n * Processes preview for option by it's value, and sets the result\n * to 'preview' observable\n *\n * @returns {Object} Chainable.\n */\n getPreview: function () {\n var value = this.value(),\n option = this.indexedOptions[value],\n preview = option ? option.label : '';\n\n this.preview(preview);\n\n return preview;\n },\n\n /**\n * Get option from indexedOptions list.\n *\n * @param {Number} value\n * @returns {Object} Chainable\n */\n getOption: function (value) {\n return this.indexedOptions[value];\n },\n\n /**\n * Select first available option\n *\n * @returns {Object} Chainable.\n */\n clear: function () {\n var value = this.caption() ? '' : findFirst(this.options);\n\n this.value(value);\n\n return this;\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @returns {Object} Chainable.\n */\n setInitialValue: function () {\n if (_.isUndefined(this.value()) && !this.default) {\n this.clear();\n }\n\n return this._super();\n }\n });\n});\n","Magento_Ui/js/form/element/multiselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n './select'\n], function (_, utils, Select) {\n 'use strict';\n\n return Select.extend({\n defaults: {\n size: 5,\n elementTmpl: 'ui/form/element/multiselect',\n listens: {\n value: 'setDifferedFromDefault setPrepareToSendData'\n }\n },\n\n /**\n * @inheritdoc\n */\n setInitialValue: function () {\n this._super();\n\n this.initialValue = utils.copy(this.initialValue);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n normalizeData: function (value) {\n if (utils.isEmpty(value)) {\n value = [];\n }\n\n return _.isString(value) ? value.split(',') : value;\n },\n\n /**\n * Sets the prepared data to dataSource\n * by path, where key is component link to dataSource with\n * suffix \"-prepared-for-send\"\n *\n * @param {Array} data - current component value\n */\n setPrepareToSendData: function (data) {\n if (_.isUndefined(data) || !data.length) {\n data = '';\n }\n\n this.source.set(this.dataScope + '-prepared-for-send', data);\n },\n\n /**\n * @inheritdoc\n */\n getInitialValue: function () {\n var values = [\n this.normalizeData(this.source.get(this.dataScope)),\n this.normalizeData(this.default)\n ],\n value;\n\n values.some(function (v) {\n return _.isArray(v) && (value = utils.copy(v)) && !_.isEmpty(v);\n });\n\n return value;\n },\n\n /**\n * @inheritdoc\n */\n hasChanged: function () {\n var value = this.value(),\n initial = this.initialValue;\n\n return !utils.equalArrays(value, initial);\n },\n\n /**\n * @inheritdoc\n */\n reset: function () {\n this.value(utils.copy(this.initialValue));\n this.error(false);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n clear: function () {\n this.value([]);\n this.error(false);\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/post-code.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n './abstract'\n], function (_, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n imports: {\n countryOptions: '${ $.parentName }.country_id:indexedOptions',\n update: '${ $.parentName }.country_id:value'\n }\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @returns {Abstract} Chainable.\n */\n initObservable: function () {\n this._super();\n\n /**\n * equalityComparer function\n *\n * @returns boolean.\n */\n this.value.equalityComparer = function (oldValue, newValue) {\n return !oldValue && !newValue || oldValue === newValue;\n };\n\n return this;\n },\n\n /**\n * Method called every time country selector's value gets changed.\n * Updates all validations and requirements for certain country.\n * @param {String} value - Selected country ID.\n */\n update: function (value) {\n var isZipCodeOptional,\n option;\n\n if (!value) {\n return;\n }\n\n option = _.isObject(this.countryOptions) && this.countryOptions[value];\n\n if (!option) {\n return;\n }\n\n isZipCodeOptional = !!option['is_zipcode_optional'];\n\n if (isZipCodeOptional) {\n this.error(false);\n }\n\n this.validation['required-entry'] = !isZipCodeOptional;\n this.required(!isZipCodeOptional);\n }\n });\n});\n","Magento_Ui/js/form/element/boolean.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n './abstract'\n], function (Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n checked: false,\n links: {\n checked: 'value'\n }\n },\n\n /**\n * @returns {*|void|Element}\n */\n initObservable: function () {\n return this._super()\n .observe('checked');\n },\n\n /**\n * Converts provided value to boolean.\n *\n * @returns {Boolean}\n */\n normalizeData: function () {\n return !!+this._super();\n },\n\n /**\n * Calls 'onUpdate' method of parent, if value is defined and instance's\n * 'unique' property set to true, calls 'setUnique' method\n *\n * @return {Object} - reference to instance\n */\n onUpdate: function () {\n if (this.hasUnique) {\n this.setUnique();\n }\n\n return this._super();\n }\n });\n});\n","Magento_Ui/js/form/element/abstract.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n 'uiLayout',\n 'uiElement',\n 'Magento_Ui/js/lib/validation/validator'\n], function (_, utils, layout, Element, validator) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n visible: true,\n preview: '',\n focused: false,\n required: false,\n disabled: false,\n valueChangedByUser: false,\n elementTmpl: 'ui/form/element/input',\n tooltipTpl: 'ui/form/element/helper/tooltip',\n fallbackResetTpl: 'ui/form/element/helper/fallback-reset',\n 'input_type': 'input',\n placeholder: false,\n description: '',\n labelVisible: true,\n label: '',\n error: '',\n warn: '',\n notice: '',\n customScope: '',\n default: '',\n isDifferedFromDefault: false,\n showFallbackReset: false,\n additionalClasses: {},\n isUseDefault: '',\n serviceDisabled: false,\n valueUpdate: false, // ko binding valueUpdate\n\n switcherConfig: {\n component: 'Magento_Ui/js/form/switcher',\n name: '${ $.name }_switcher',\n target: '${ $.name }',\n property: 'value'\n },\n listens: {\n visible: 'setPreview',\n value: 'setDifferedFromDefault',\n '${ $.provider }:data.reset': 'reset',\n '${ $.provider }:data.overload': 'overload',\n '${ $.provider }:${ $.customScope ? $.customScope + \".\" : \"\"}data.validate': 'validate',\n 'isUseDefault': 'toggleUseDefault'\n },\n ignoreTmpls: {\n value: true\n },\n\n links: {\n value: '${ $.provider }:${ $.dataScope }'\n }\n },\n\n /**\n * Invokes initialize method of parent class,\n * contains initialization logic\n */\n initialize: function () {\n _.bindAll(this, 'reset');\n\n this._super()\n .setInitialValue()\n ._setClasses()\n .initSwitcher();\n\n return this;\n },\n\n /**\n * Checks if component has error.\n *\n * @returns {Object}\n */\n checkInvalid: function () {\n return this.error() && this.error().length ? this : null;\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @returns {Abstract} Chainable.\n */\n initObservable: function () {\n var rules = this.validation = this.validation || {};\n\n this._super();\n\n this.observe('error disabled focused preview visible value warn notice isDifferedFromDefault')\n .observe('isUseDefault serviceDisabled')\n .observe({\n 'required': !!rules['required-entry']\n });\n\n return this;\n },\n\n /**\n * Initializes regular properties of instance.\n *\n * @returns {Abstract} Chainable.\n */\n initConfig: function () {\n var uid = utils.uniqueid(),\n name,\n valueUpdate,\n scope;\n\n this._super();\n\n scope = this.dataScope.split('.');\n name = scope.length > 1 ? scope.slice(1) : scope;\n\n valueUpdate = this.showFallbackReset ? 'afterkeydown' : this.valueUpdate;\n\n _.extend(this, {\n uid: uid,\n noticeId: 'notice-' + uid,\n errorId: 'error-' + uid,\n tooltipId: 'tooltip-' + uid,\n inputName: utils.serializeName(name.join('.')),\n valueUpdate: valueUpdate\n });\n\n return this;\n },\n\n /**\n * Initializes switcher element instance.\n *\n * @returns {Abstract} Chainable.\n */\n initSwitcher: function () {\n if (this.switcherConfig.enabled) {\n layout([this.switcherConfig]);\n }\n\n return this;\n },\n\n /**\n * Sets initial value of the element and subscribes to it's changes.\n *\n * @returns {Abstract} Chainable.\n */\n setInitialValue: function () {\n this.initialValue = this.getInitialValue();\n\n if (this.value.peek() !== this.initialValue) {\n this.value(this.initialValue);\n }\n\n this.on('value', this.onUpdate.bind(this));\n this.isUseDefault(this.disabled());\n\n return this;\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Abstract} Chainable.\n */\n _setClasses: function () {\n var additional = this.additionalClasses;\n\n if (_.isString(additional)) {\n this.additionalClasses = {};\n\n if (additional.trim().length) {\n additional = additional.trim().split(' ');\n\n additional.forEach(function (name) {\n if (name.length) {\n this.additionalClasses[name] = true;\n }\n }, this);\n }\n }\n\n _.extend(this.additionalClasses, {\n _required: this.required,\n _error: this.error,\n _warn: this.warn,\n _disabled: this.disabled\n });\n\n return this;\n },\n\n /**\n * Gets initial value of element\n *\n * @returns {*} Elements' value.\n */\n getInitialValue: function () {\n var values = [this.value(), this.default],\n value;\n\n values.some(function (v) {\n if (v !== null && v !== undefined) {\n value = v;\n\n return true;\n }\n\n return false;\n });\n\n return this.normalizeData(value);\n },\n\n /**\n * Sets 'value' as 'hidden' property's value, triggers 'toggle' event,\n * sets instance's hidden identifier in params storage based on\n * 'value'.\n *\n * @returns {Abstract} Chainable.\n */\n setVisible: function (isVisible) {\n this.visible(isVisible);\n\n return this;\n },\n\n /**\n * Show element.\n *\n * @returns {Abstract} Chainable.\n */\n show: function () {\n this.visible(true);\n\n return this;\n },\n\n /**\n * Hide element.\n *\n * @returns {Abstract} Chainable.\n */\n hide: function () {\n this.visible(false);\n\n return this;\n },\n\n /**\n * Disable element.\n *\n * @returns {Abstract} Chainable.\n */\n disable: function () {\n this.disabled(true);\n\n return this;\n },\n\n /**\n * Enable element.\n *\n * @returns {Abstract} Chainable.\n */\n enable: function () {\n this.disabled(false);\n\n return this;\n },\n\n /**\n *\n * @param {(String|Object)} rule\n * @param {(Object|Boolean)} [options]\n * @returns {Abstract} Chainable.\n */\n setValidation: function (rule, options) {\n var rules = utils.copy(this.validation),\n changed;\n\n if (_.isObject(rule)) {\n _.extend(this.validation, rule);\n } else {\n this.validation[rule] = options;\n }\n\n changed = !utils.compare(rules, this.validation).equal;\n\n if (changed) {\n this.required(!!rules['required-entry']);\n this.validate();\n }\n\n return this;\n },\n\n /**\n * Returns unwrapped preview observable.\n *\n * @returns {String} Value of the preview observable.\n */\n getPreview: function () {\n return this.value();\n },\n\n /**\n * Checks if element has addons\n *\n * @returns {Boolean}\n */\n hasAddons: function () {\n return this.addbefore || this.addafter;\n },\n\n /**\n * Checks if element has service setting\n *\n * @returns {Boolean}\n */\n hasService: function () {\n return this.service && this.service.template;\n },\n\n /**\n * Defines if value has changed.\n *\n * @returns {Boolean}\n */\n hasChanged: function () {\n var notEqual = this.value() !== this.initialValue;\n\n return !this.visible() ? false : notEqual;\n },\n\n /**\n * Checks if 'value' is not empty.\n *\n * @returns {Boolean}\n */\n hasData: function () {\n return !utils.isEmpty(this.value());\n },\n\n /**\n * Sets value observable to initialValue property.\n *\n * @returns {Abstract} Chainable.\n */\n reset: function () {\n this.value(this.initialValue);\n this.error(false);\n\n return this;\n },\n\n /**\n * Sets current state as initial.\n */\n overload: function () {\n this.setInitialValue();\n this.bubble('update', this.hasChanged());\n },\n\n /**\n * Clears 'value' property.\n *\n * @returns {Abstract} Chainable.\n */\n clear: function () {\n this.value('');\n\n return this;\n },\n\n /**\n * Converts values like 'null' or 'undefined' to an empty string.\n *\n * @param {*} value - Value to be processed.\n * @returns {*}\n */\n normalizeData: function (value) {\n return utils.isEmpty(value) ? '' : value;\n },\n\n /**\n * Validates itself by it's validation rules using validator object.\n * If validation of a rule did not pass, writes it's message to\n * 'error' observable property.\n *\n * @returns {Object} Validate information.\n */\n validate: function () {\n var value = this.value(),\n result = validator(this.validation, value, this.validationParams),\n message = !this.disabled() && this.visible() ? result.message : '',\n isValid = this.disabled() || !this.visible() || result.passed;\n\n this.error(message);\n this.error.valueHasMutated();\n this.bubble('error', message);\n\n //TODO: Implement proper result propagation for form\n if (this.source && !isValid) {\n this.source.set('params.invalid', true);\n }\n\n return {\n valid: isValid,\n target: this\n };\n },\n\n /**\n * Callback that fires when 'value' property is updated.\n */\n onUpdate: function () {\n this.bubble('update', this.hasChanged());\n\n this.validate();\n },\n\n /**\n * Restore value to default\n */\n restoreToDefault: function () {\n this.value(this.default);\n this.focused(true);\n },\n\n /**\n * Update whether value differs from default value\n */\n setDifferedFromDefault: function () {\n var value = typeof this.value() != 'undefined' && this.value() !== null ? this.value() : '',\n defaultValue = typeof this.default != 'undefined' && this.default !== null ? this.default : '';\n\n this.isDifferedFromDefault(value !== defaultValue);\n },\n\n /**\n * @param {Boolean} state\n */\n toggleUseDefault: function (state) {\n this.disabled(state);\n\n if (this.source && this.hasService()) {\n this.source.set('data.use_default.' + this.index, Number(state));\n }\n },\n\n /**\n * Callback when value is changed by user\n */\n userChanges: function () {\n this.valueChangedByUser = true;\n },\n\n /**\n * Returns correct id for 'aria-describedby' accessibility attribute\n *\n * @returns {Boolean|String}\n */\n getDescriptionId: function () {\n var id = false;\n\n if (this.error()) {\n id = this.errorId;\n } else if (this.notice()) {\n id = this.noticeId;\n }\n\n return id;\n }\n });\n});\n","Magento_Ui/js/form/element/color-picker.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'mage/translate',\n 'Magento_Ui/js/form/element/abstract',\n 'Magento_Ui/js/form/element/color-picker-palette'\n], function ($t, Abstract, palette) {\n 'use strict';\n\n return Abstract.extend({\n\n defaults: {\n colorPickerConfig: {\n chooseText: $t('Apply'),\n cancelText: $t('Cancel'),\n maxSelectionSize: 8,\n clickoutFiresChange: true,\n allowEmpty: true,\n localStorageKey: 'magento.spectrum',\n palette: palette\n }\n },\n\n /**\n * Invokes initialize method of parent class,\n * contains initialization logic\n */\n initialize: function () {\n this._super();\n\n this.colorPickerConfig.value = this.value;\n\n return this;\n }\n });\n});\n","Magento_Ui/js/view/messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'ko',\n 'jquery',\n 'uiComponent',\n '../model/messageList',\n 'jquery-ui-modules/effect-blind'\n], function (ko, $, Component, globalMessages) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Ui/messages',\n selector: '[data-role=checkout-messages]',\n isHidden: false,\n hideTimeout: 5000,\n hideSpeed: 500,\n listens: {\n isHidden: 'onHiddenChange'\n }\n },\n\n /** @inheritdoc */\n initialize: function (config, messageContainer) {\n this._super()\n .initObservable();\n\n this.messageContainer = messageContainer || config.messageContainer || globalMessages;\n\n return this;\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe('isHidden');\n\n return this;\n },\n\n /**\n * Checks visibility.\n *\n * @return {Boolean}\n */\n isVisible: function () {\n return this.isHidden(this.messageContainer.hasMessages());\n },\n\n /**\n * Remove all messages.\n */\n removeAll: function () {\n this.messageContainer.clear();\n },\n\n /**\n * @param {Boolean} isHidden\n */\n onHiddenChange: function (isHidden) {\n // Hide message block if needed\n if (isHidden) {\n setTimeout(function () {\n $(this.selector).hide('slow');\n\n //commented because effect-blind.js(1.13.1) is having show & hide issue\n // $(this.selector).hide('blind', {}, this.hideSpeed);\n }.bind(this), this.hideTimeout);\n }\n }\n });\n});\n","Magento_Ui/js/model/messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'ko',\n 'uiClass'\n], function (ko, Class) {\n 'use strict';\n\n return Class.extend({\n /** @inheritdoc */\n initialize: function () {\n this._super()\n .initObservable();\n\n return this;\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this.errorMessages = ko.observableArray([]);\n this.successMessages = ko.observableArray([]);\n\n return this;\n },\n\n /**\n * Add message to list.\n * @param {Object} messageObj\n * @param {Object} type\n * @returns {Boolean}\n */\n add: function (messageObj, type) {\n var expr = /([%])\\w+/g,\n message;\n\n if (!messageObj.hasOwnProperty('parameters')) {\n this.clear();\n type.push(messageObj.message);\n\n return true;\n }\n message = messageObj.message.replace(expr, function (varName) {\n varName = varName.substr(1);\n\n if (!isNaN(varName)) {\n varName--;\n }\n\n if (messageObj.parameters.hasOwnProperty(varName)) {\n return messageObj.parameters[varName];\n }\n\n return messageObj.parameters.shift();\n });\n this.clear();\n type.push(message);\n\n return true;\n },\n\n /**\n * Add success message.\n *\n * @param {Object} message\n * @return {*|Boolean}\n */\n addSuccessMessage: function (message) {\n return this.add(message, this.successMessages);\n },\n\n /**\n * Add error message.\n *\n * @param {Object} message\n * @return {*|Boolean}\n */\n addErrorMessage: function (message) {\n return this.add(message, this.errorMessages);\n },\n\n /**\n * Get error messages.\n *\n * @return {Array}\n */\n getErrorMessages: function () {\n return this.errorMessages;\n },\n\n /**\n * Get success messages.\n *\n * @return {Array}\n */\n getSuccessMessages: function () {\n return this.successMessages;\n },\n\n /**\n * Checks if an instance has stored messages.\n *\n * @return {Boolean}\n */\n hasMessages: function () {\n return this.errorMessages().length > 0 || this.successMessages().length > 0;\n },\n\n /**\n * Removes stored messages.\n */\n clear: function () {\n this.errorMessages.removeAll();\n this.successMessages.removeAll();\n }\n });\n});\n","Magento_Ui/js/model/messageList.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n './messages'\n], function (Messages) {\n 'use strict';\n\n return new Messages();\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()) {\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/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/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","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 (parseInt(this.getPureValue()) === 0) { //eslint-disable-line radix\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/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 }\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/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/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/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 displayPriceMode == '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/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_Payment/js/transparent.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'mage/template',\n 'Magento_Ui/js/modal/alert',\n 'jquery-ui-modules/widget',\n 'Magento_Payment/js/model/credit-card-validation/validator',\n 'Magento_Checkout/js/model/full-screen-loader'\n], function ($, mageTemplate, alert, ui, validator, fullScreenLoader) {\n 'use strict';\n\n $.widget('mage.transparent', {\n options: {\n context: null,\n placeOrderSelector: '[data-role=\"review-save\"]',\n paymentFormSelector: '#co-payment-form',\n updateSelectorPrefix: '#checkout-',\n updateSelectorSuffix: '-load',\n hiddenFormTmpl:\n '<form target=\"<%= data.target %>\" action=\"<%= data.action %>\" method=\"POST\" ' +\n 'hidden enctype=\"application/x-www-form-urlencoded\" class=\"no-display\">' +\n '<% _.each(data.inputs, function(val, key){ %>' +\n '<input value=\"<%= val %>\" name=\"<%= key %>\" type=\"hidden\">' +\n '<% }); %>' +\n '</form>',\n reviewAgreementForm: '#checkout-agreements',\n cgiUrl: null,\n orderSaveUrl: null,\n controller: null,\n gateway: null,\n dateDelim: null,\n cardFieldsMap: null,\n expireYearLength: 2\n },\n\n /**\n * {Function}\n * @private\n */\n _create: function () {\n this.hiddenFormTmpl = mageTemplate(this.options.hiddenFormTmpl);\n\n if (this.options.context) {\n this.options.context.setPlaceOrderHandler($.proxy(this._orderSave, this));\n this.options.context.setValidateHandler($.proxy(this._validateHandler, this));\n } else {\n $(this.options.placeOrderSelector)\n .off('click')\n .on('click', $.proxy(this._placeOrderHandler, this));\n }\n\n this.element.validation();\n $('[data-container=\"' + this.options.gateway + '-cc-number\"]').on('focusout', function () {\n $(this).valid();\n });\n },\n\n /**\n * handler for credit card validation\n * @return {Boolean}\n * @private\n */\n _validateHandler: function () {\n return this.element.validation && this.element.validation('isValid');\n },\n\n /**\n * handler for Place Order button to call gateway for credit card validation\n * @return {Boolean}\n * @private\n */\n _placeOrderHandler: function () {\n if (this._validateHandler()) {\n this._orderSave();\n }\n\n return false;\n },\n\n /**\n * Save order and generate post data for gateway call\n * @private\n */\n _orderSave: function () {\n var postData = $(this.options.paymentFormSelector).serialize();\n\n if ($(this.options.reviewAgreementForm).length) {\n postData += '&' + $(this.options.reviewAgreementForm).serialize();\n }\n postData += '&controller=' + this.options.controller;\n postData += '&cc_type=' + this.element.find(\n '[data-container=\"' + this.options.gateway + '-cc-type\"]'\n ).val();\n\n return $.ajax({\n url: this.options.orderSaveUrl,\n type: 'post',\n context: this,\n data: postData,\n dataType: 'json',\n\n /**\n * {Function}\n */\n beforeSend: function () {\n fullScreenLoader.startLoader();\n },\n\n /**\n * {Function}\n */\n success: function (response) {\n var preparedData,\n msg,\n\n /**\n * {Function}\n */\n alertActionHandler = function () {\n // default action\n };\n\n if (response.success && response[this.options.gateway]) {\n preparedData = this._preparePaymentData(\n response[this.options.gateway].fields,\n this.options.cardFieldsMap\n );\n this._postPaymentToGateway(preparedData);\n } else {\n fullScreenLoader.stopLoader(true);\n\n msg = response['error_messages'];\n\n if (this.options.context) {\n this.options.context.clearTimeout().fail();\n alertActionHandler = this.options.context.alertActionHandler;\n }\n\n if (typeof msg === 'object') {\n msg = msg.join('\\n');\n }\n\n if (msg) {\n alert(\n {\n content: msg,\n actions: {\n\n /**\n * {Function}\n */\n always: alertActionHandler\n }\n }\n );\n }\n }\n }.bind(this)\n });\n },\n\n /**\n * Post data to gateway for credit card validation\n * @param {Object} data\n * @private\n */\n _postPaymentToGateway: function (data) {\n var tmpl,\n iframeSelector = '[data-container=\"' + this.options.gateway + '-transparent-iframe\"]';\n\n tmpl = this.hiddenFormTmpl({\n data: {\n target: $(iframeSelector).attr('name'),\n action: this.options.cgiUrl,\n inputs: data\n }\n });\n $(tmpl).appendTo($(iframeSelector)).trigger('submit');\n },\n\n /**\n * Add credit card fields to post data for gateway\n * @param {Object} data\n * @param {Object} ccfields\n * @private\n */\n _preparePaymentData: function (data, ccfields) {\n var preparedata;\n\n if (this.element.find('[data-container=\"' + this.options.gateway + '-cc-cvv\"]').length) {\n data[ccfields.cccvv] = this.element.find(\n '[data-container=\"' + this.options.gateway + '-cc-cvv\"]'\n ).val();\n }\n preparedata = this._prepareExpDate();\n data[ccfields.ccexpdate] = preparedata.month + this.options.dateDelim + preparedata.year;\n data[ccfields.ccnum] = this.element.find(\n '[data-container=\"' + this.options.gateway + '-cc-number\"]'\n ).val();\n\n return data;\n },\n\n /**\n * Grab Month and Year into one\n * @returns {Object}\n * @private\n */\n _prepareExpDate: function () {\n var year = this.element.find('[data-container=\"' + this.options.gateway + '-cc-year\"]').val(),\n month = parseInt(\n this.element.find('[data-container=\"' + this.options.gateway + '-cc-month\"]').val(),\n 10\n );\n\n if (year.length > this.options.expireYearLength) {\n year = year.substring(year.length - this.options.expireYearLength);\n }\n\n if (month < 10) {\n month = '0' + month;\n }\n\n return {\n month: month, year: year\n };\n }\n });\n\n return $.mage.transparent;\n});\n","Magento_Payment/js/cc-type.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget'\n], function ($) {\n 'use strict';\n\n $.widget('mage.creditCardType', {\n options: {\n typeCodes: ['SS', 'SM', 'SO'] // Type codes for Switch/Maestro/Solo credit cards.\n },\n\n /**\n * Bind change handler to select element and trigger the event to show/hide\n * the Switch/Maestro or Solo credit card type container for those credit card types.\n * @private\n */\n _create: function () {\n this.element.on('change', $.proxy(this._toggleCardType, this)).trigger('change');\n },\n\n /**\n * Toggle the Switch/Maestro and Solo credit card type container depending on which\n * credit card type is selected.\n * @private\n */\n _toggleCardType: function () {\n $(this.options.creditCardTypeContainer)\n .toggle($.inArray(this.element.val(), this.options.typeCodes) !== -1);\n }\n });\n\n return $.mage.creditCardType;\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-data.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([], function () {\n 'use strict';\n\n return {\n creditCard: null,\n creditCardNumber: null,\n expirationMonth: null,\n expirationYear: null,\n cvvCode: null\n };\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-number-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'mageUtils',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/credit-card-type'\n], function (utils, luhn10, creditCardTypes) {\n 'use strict';\n\n /**\n * @param {*} card\n * @param {*} isPotentiallyValid\n * @param {*} isValid\n * @return {Object}\n */\n function resultWrapper(card, isPotentiallyValid, isValid) {\n return {\n card: card,\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid\n };\n }\n\n return function (value) {\n var potentialTypes,\n cardType,\n valid,\n i,\n maxLength;\n\n if (utils.isEmpty(value)) {\n return resultWrapper(null, false, false);\n }\n\n value = value.replace(/\\s+/g, '');\n\n if (!/^\\d*$/.test(value)) {\n return resultWrapper(null, false, false);\n }\n\n potentialTypes = creditCardTypes.getCardTypes(value);\n\n if (potentialTypes.length === 0) {\n return resultWrapper(null, false, false);\n } else if (potentialTypes.length !== 1) {\n return resultWrapper(null, true, false);\n }\n\n cardType = potentialTypes[0];\n\n if (cardType.type === 'unionpay') { // UnionPay is not Luhn 10 compliant\n valid = true;\n } else {\n valid = luhn10(value);\n }\n\n for (i = 0; i < cardType.lengths.length; i++) {\n if (cardType.lengths[i] === value.length) {\n return resultWrapper(cardType, valid, valid);\n }\n }\n\n maxLength = Math.max.apply(null, cardType.lengths);\n\n if (value.length < maxLength) {\n return resultWrapper(cardType, true, false);\n }\n\n return resultWrapper(cardType, false, false);\n };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'mageUtils',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/parse-date',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator'\n], function (utils, parseDate, expirationMonth, expirationYear) {\n 'use strict';\n\n /**\n * @param {*} isValid\n * @param {*} isPotentiallyValid\n * @param {*} month\n * @param {*} year\n * @return {Object}\n */\n function resultWrapper(isValid, isPotentiallyValid, month, year) {\n return {\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid,\n month: month,\n year: year\n };\n }\n\n return function (value) {\n var date,\n monthValid,\n yearValid;\n\n if (utils.isEmpty(value)) {\n return resultWrapper(false, false, null, null);\n }\n\n value = value.replace(/^(\\d\\d) (\\d\\d(\\d\\d)?)$/, '$1/$2');\n date = parseDate(value);\n monthValid = expirationMonth(date.month);\n yearValid = expirationYear(date.year);\n\n if (monthValid.isValid && yearValid.isValid) {\n return resultWrapper(true, true, date.month, date.year);\n }\n\n if (monthValid.isPotentiallyValid && yearValid.isPotentiallyValid) {\n return resultWrapper(false, true, null, null);\n }\n\n return resultWrapper(false, false, null, null);\n };\n});\n","Magento_Payment/js/model/credit-card-validation/validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'Magento_Payment/js/model/credit-card-validation/cvv-validator',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-data',\n 'mage/translate'\n], function ($, cvvValidator, creditCardNumberValidator, yearValidator, monthValidator, creditCardData) {\n 'use strict';\n\n $('.payment-method-content input[type=\"number\"]').on('keyup', function () {\n if ($(this).val() < 0) {\n $(this).val($(this).val().replace(/^-/, ''));\n }\n });\n\n $.each({\n 'validate-card-type': [\n function (number, item, allowedTypes) {\n var cardInfo,\n i,\n l;\n\n if (!creditCardNumberValidator(number).isValid) {\n return false;\n }\n\n cardInfo = creditCardNumberValidator(number).card;\n\n for (i = 0, l = allowedTypes.length; i < l; i++) {\n if (cardInfo.title == allowedTypes[i].type) { //eslint-disable-line eqeqeq\n return true;\n }\n }\n\n return false;\n },\n $.mage.__('Please enter a valid credit card type number.')\n ],\n 'validate-card-number': [\n\n /**\n * Validate credit card number based on mod 10\n *\n * @param {*} number - credit card number\n * @return {Boolean}\n */\n function (number) {\n return creditCardNumberValidator(number).isValid;\n },\n $.mage.__('Please enter a valid credit card number.')\n ],\n 'validate-card-date': [\n\n /**\n * Validate credit card expiration month\n *\n * @param {String} date - month\n * @return {Boolean}\n */\n function (date) {\n return monthValidator(date).isValid;\n },\n $.mage.__('Incorrect credit card expiration month.')\n ],\n 'validate-card-cvv': [\n\n /**\n * Validate cvv\n *\n * @param {String} cvv - card verification value\n * @return {Boolean}\n */\n function (cvv) {\n var maxLength = creditCardData.creditCard ? creditCardData.creditCard.code.size : 3;\n\n return cvvValidator(cvv, maxLength).isValid;\n },\n $.mage.__('Please enter a valid credit card verification number.')\n ],\n 'validate-card-year': [\n\n /**\n * Validate credit card expiration year\n *\n * @param {String} date - year\n * @return {Boolean}\n */\n function (date) {\n return yearValidator(date).isValid;\n },\n $.mage.__('Incorrect credit card expiration year.')\n ]\n\n }, function (i, rule) {\n rule.unshift(i);\n $.validator.addMethod.apply($.validator, rule);\n });\n});\n","Magento_Payment/js/model/credit-card-validation/cvv-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([], function () {\n 'use strict';\n\n /**\n * @param {*} isValid\n * @param {*} isPotentiallyValid\n * @return {Object}\n */\n function resultWrapper(isValid, isPotentiallyValid) {\n return {\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid\n };\n }\n\n /**\n * CVV number validation.\n * Validate digit count for CVV code.\n *\n * @param {*} value\n * @param {Number} maxLength\n * @return {Object}\n */\n return function (value, maxLength) {\n var DEFAULT_LENGTH = 3;\n\n maxLength = maxLength || DEFAULT_LENGTH;\n\n if (!/^\\d*$/.test(value)) {\n return resultWrapper(false, false);\n }\n\n if (value.length === maxLength) {\n return resultWrapper(true, true);\n }\n\n if (value.length < maxLength) {\n return resultWrapper(false, true);\n }\n\n if (value.length > maxLength) {\n return resultWrapper(false, false);\n }\n };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.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 {*} isValid\n * @param {*} isPotentiallyValid\n * @return {Object}\n */\n function resultWrapper(isValid, isPotentiallyValid) {\n return {\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid\n };\n }\n\n return function (value) {\n var currentYear = new Date().getFullYear(),\n len = value.length,\n valid,\n expMaxLifetime = 19;\n\n if (value.replace(/\\s/g, '') === '') {\n return resultWrapper(false, true);\n }\n\n if (!/^\\d*$/.test(value)) {\n return resultWrapper(false, false);\n }\n\n if (len !== 4) {\n return resultWrapper(false, true);\n }\n\n value = parseInt(value, 10);\n valid = value >= currentYear && value <= currentYear + expMaxLifetime;\n\n return resultWrapper(valid, valid);\n };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator/parse-date.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 (value) {\n var month, len;\n\n if (value.match('/')) {\n value = value.split(/\\s*\\/\\s*/g);\n\n return {\n month: value[0],\n year: value.slice(1).join()\n };\n }\n\n len = value[0] === '0' || value.length > 5 || value.length === 4 || value.length === 3 ? 2 : 1;\n month = value.substr(0, len);\n\n return {\n month: month,\n year: value.substr(month.length, 4)\n };\n };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.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 {*} isValid\n * @param {*} isPotentiallyValid\n * @return {Object}\n */\n function resultWrapper(isValid, isPotentiallyValid) {\n return {\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid\n };\n }\n\n return function (value) {\n var month,\n monthValid;\n\n if (value.replace(/\\s/g, '') === '' || value === '0') {\n return resultWrapper(false, true);\n }\n\n if (!/^\\d*$/.test(value)) {\n return resultWrapper(false, false);\n }\n\n if (isNaN(value)) {\n return resultWrapper(false, false);\n }\n\n month = parseInt(value, 10);\n monthValid = month > 0 && month < 13;\n\n return resultWrapper(monthValid, monthValid);\n };\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'mageUtils'\n], function ($, utils) {\n 'use strict';\n\n var types = [\n {\n title: 'Visa',\n type: 'VI',\n pattern: '^4\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [16],\n code: {\n name: 'CVV',\n size: 3\n }\n },\n {\n title: 'MasterCard',\n type: 'MC',\n pattern: '^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$',\n gaps: [4, 8, 12],\n lengths: [16],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'American Express',\n type: 'AE',\n pattern: '^3([47]\\\\d*)?$',\n isAmex: true,\n gaps: [4, 10],\n lengths: [15],\n code: {\n name: 'CID',\n size: 4\n }\n },\n {\n title: 'Diners',\n type: 'DN',\n pattern: '^(3(0[0-5]|095|6|[8-9]))\\\\d*$',\n gaps: [4, 10],\n lengths: [14, 16, 17, 18, 19],\n code: {\n name: 'CVV',\n size: 3\n }\n },\n {\n title: 'Discover',\n type: 'DI',\n pattern: '^(6011(0|[2-4]|74|7[7-9]|8[6-9]|9)|6(4[4-9]|5))\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [16, 17, 18, 19],\n code: {\n name: 'CID',\n size: 3\n }\n },\n {\n title: 'JCB',\n type: 'JCB',\n pattern: '^35(2[8-9]|[3-8])\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [16, 17, 18, 19],\n code: {\n name: 'CVV',\n size: 3\n }\n },\n {\n title: 'UnionPay',\n type: 'UN',\n pattern: '^(622(1(2[6-9]|[3-9])|[3-8]|9([[0-1]|2[0-5]))|62[4-6]|628([2-8]))\\\\d*?$',\n gaps: [4, 8, 12],\n lengths: [16, 17, 18, 19],\n code: {\n name: 'CVN',\n size: 3\n }\n },\n {\n title: 'Maestro International',\n type: 'MI',\n pattern: '^(5(0|[6-9])|63|67(?!59|6770|6774))\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [12, 13, 14, 15, 16, 17, 18, 19],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'Maestro Domestic',\n type: 'MD',\n pattern: '^6759(?!24|38|40|6[3-9]|70|76)|676770|676774\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [12, 13, 14, 15, 16, 17, 18, 19],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'Hipercard',\n type: 'HC',\n pattern: '^((606282)|(637095)|(637568)|(637599)|(637609)|(637612))\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [13, 16],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'Elo',\n type: 'ELO',\n pattern: '^((509091)|(636368)|(636297)|(504175)|(438935)|(40117[8-9])|(45763[1-2])|' +\n '(457393)|(431274)|(50990[0-2])|(5099[7-9][0-9])|(50996[4-9])|(509[1-8][0-9][0-9])|' +\n '(5090(0[0-2]|0[4-9]|1[2-9]|[24589][0-9]|3[1-9]|6[0-46-9]|7[0-24-9]))|' +\n '(5067(0[0-24-8]|1[0-24-9]|2[014-9]|3[0-379]|4[0-9]|5[0-3]|6[0-5]|7[0-8]))|' +\n '(6504(0[5-9]|1[0-9]|2[0-9]|3[0-9]))|' +\n '(6504(8[5-9]|9[0-9])|6505(0[0-9]|1[0-9]|2[0-9]|3[0-8]))|' +\n '(6505(4[1-9]|5[0-9]|6[0-9]|7[0-9]|8[0-9]|9[0-8]))|' +\n '(6507(0[0-9]|1[0-8]))|(65072[0-7])|(6509(0[1-9]|1[0-9]|20))|' +\n '(6516(5[2-9]|6[0-9]|7[0-9]))|(6550(0[0-9]|1[0-9]))|' +\n '(6550(2[1-9]|3[0-9]|4[0-9]|5[0-8])))\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [16],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'Aura',\n type: 'AU',\n pattern: '^5078\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [19],\n code: {\n name: 'CVC',\n size: 3\n }\n }\n ];\n\n return {\n /**\n * @param {*} cardNumber\n * @return {Array}\n */\n getCardTypes: function (cardNumber) {\n var i, value,\n result = [];\n\n if (utils.isEmpty(cardNumber)) {\n return result;\n }\n\n if (cardNumber === '') {\n return $.extend(true, {}, types);\n }\n\n for (i = 0; i < types.length; i++) {\n value = types[i];\n\n if (new RegExp(value.pattern).test(cardNumber)) {\n result.push($.extend(true, {}, value));\n }\n }\n\n return result;\n }\n };\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.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 * Luhn algorithm verification\n */\n return function (a, b, c, d, e) {\n for (d = +a[b = a.length - 1], e = 0; b--;) {\n c = +a[b];\n d += ++e % 2 ? 2 * c % 10 + (c > 4) : c;\n }\n\n return !(d % 10);\n };\n});\n","Magento_Payment/js/view/payment/iframe.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'Magento_Payment/js/view/payment/cc-form',\n 'Magento_Ui/js/model/messageList',\n 'mage/translate',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/action/set-payment-information',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Ui/js/modal/alert'\n], function (\n $,\n Component,\n messageList,\n $t,\n fullScreenLoader,\n setPaymentInformationAction,\n additionalValidators,\n alert\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Payment/payment/iframe',\n timeoutId: null,\n timeoutMessage: 'Sorry, but something went wrong.'\n },\n\n /**\n * @returns {String}\n */\n getSource: function () {\n return window.checkoutConfig.payment.iframe.source[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getControllerName: function () {\n return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getPlaceOrderUrl: function () {\n return window.checkoutConfig.payment.iframe.placeOrderUrl[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getCgiUrl: function () {\n return window.checkoutConfig.payment.iframe.cgiUrl[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getSaveOrderUrl: function () {\n return window.checkoutConfig.payment.iframe.saveOrderUrl[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getDateDelim: function () {\n return window.checkoutConfig.payment.iframe.dateDelim[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getCardFieldsMap: function () {\n return window.checkoutConfig.payment.iframe.cardFieldsMap[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getExpireYearLength: function () {\n return window.checkoutConfig.payment.iframe.expireYearLength[this.getCode()];\n },\n\n /**\n * @param {Object} parent\n * @returns {Function}\n */\n originalPlaceOrder: function (parent) {\n return parent.placeOrder.bind(parent);\n },\n\n /**\n * @returns {Number}\n */\n getTimeoutTime: function () {\n return window.checkoutConfig.payment.iframe.timeoutTime[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getTimeoutMessage: function () {\n return $t(this.timeoutMessage);\n },\n\n /**\n * @override\n */\n placeOrder: function () {\n var self = this;\n\n if (this.validateHandler() &&\n additionalValidators.validate() &&\n this.isPlaceOrderActionAllowed() === true\n ) {\n fullScreenLoader.startLoader();\n\n this.isPlaceOrderActionAllowed(false);\n\n $.when(\n this.setPaymentInformation()\n ).done(\n this.done.bind(this)\n ).fail(\n this.fail.bind(this)\n ).always(\n function () {\n self.isPlaceOrderActionAllowed(true);\n }\n );\n\n this.initTimeoutHandler();\n }\n },\n\n /**\n * {Function}\n */\n setPaymentInformation: function () {\n return setPaymentInformationAction(\n this.messageContainer,\n {\n method: this.getCode()\n }\n );\n },\n\n /**\n * {Function}\n */\n initTimeoutHandler: function () {\n this.timeoutId = setTimeout(\n this.timeoutHandler.bind(this),\n this.getTimeoutTime()\n );\n\n $(window).off('clearTimeout')\n .on('clearTimeout', this.clearTimeout.bind(this));\n },\n\n /**\n * {Function}\n */\n clearTimeout: function () {\n clearTimeout(this.timeoutId);\n this.fail();\n\n return this;\n },\n\n /**\n * {Function}\n */\n timeoutHandler: function () {\n this.clearTimeout();\n\n alert(\n {\n content: this.getTimeoutMessage(),\n actions: {\n\n /**\n * {Function}\n */\n always: this.alertActionHandler.bind(this)\n }\n }\n );\n\n this.fail();\n },\n\n /**\n * {Function}\n */\n alertActionHandler: function () {\n fullScreenLoader.startLoader();\n window.location.reload();\n },\n\n /**\n * {Function}\n */\n fail: function () {\n fullScreenLoader.stopLoader();\n\n return this;\n },\n\n /**\n * {Function}\n */\n done: function () {\n this.placeOrderHandler().fail(function () {\n fullScreenLoader.stopLoader();\n });\n\n return this;\n }\n });\n});\n","Magento_Payment/js/view/payment/cc-form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'underscore',\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-data',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator',\n 'mage/translate'\n], function (_, Component, creditCardData, cardNumberValidator, $t) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n creditCardType: '',\n creditCardExpYear: '',\n creditCardExpMonth: '',\n creditCardNumber: '',\n creditCardSsStartMonth: '',\n creditCardSsStartYear: '',\n creditCardSsIssue: '',\n creditCardVerificationNumber: '',\n selectedCardType: null\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe([\n 'creditCardType',\n 'creditCardExpYear',\n 'creditCardExpMonth',\n 'creditCardNumber',\n 'creditCardVerificationNumber',\n 'creditCardSsStartMonth',\n 'creditCardSsStartYear',\n 'creditCardSsIssue',\n 'selectedCardType'\n ]);\n\n return this;\n },\n\n /**\n * Init component\n */\n initialize: function () {\n var self = this;\n\n this._super();\n\n //Set credit card number to credit card data object\n this.creditCardNumber.subscribe(function (value) {\n var result;\n\n self.selectedCardType(null);\n\n if (value === '' || value === null) {\n return false;\n }\n result = cardNumberValidator(value);\n\n if (!result.isPotentiallyValid && !result.isValid) {\n return false;\n }\n\n if (result.card !== null) {\n self.selectedCardType(result.card.type);\n creditCardData.creditCard = result.card;\n }\n\n if (result.isValid) {\n creditCardData.creditCardNumber = value;\n self.creditCardType(result.card.type);\n }\n });\n\n //Set expiration year to credit card data object\n this.creditCardExpYear.subscribe(function (value) {\n creditCardData.expirationYear = value;\n });\n\n //Set expiration month to credit card data object\n this.creditCardExpMonth.subscribe(function (value) {\n creditCardData.expirationMonth = value;\n });\n\n //Set cvv code to credit card data object\n this.creditCardVerificationNumber.subscribe(function (value) {\n creditCardData.cvvCode = value;\n });\n },\n\n /**\n * Get code\n * @returns {String}\n */\n getCode: function () {\n return 'cc';\n },\n\n /**\n * Get data\n * @returns {Object}\n */\n getData: function () {\n return {\n 'method': this.item.method,\n 'additional_data': {\n 'cc_cid': this.creditCardVerificationNumber(),\n 'cc_ss_start_month': this.creditCardSsStartMonth(),\n 'cc_ss_start_year': this.creditCardSsStartYear(),\n 'cc_ss_issue': this.creditCardSsIssue(),\n 'cc_type': this.creditCardType(),\n 'cc_exp_year': this.creditCardExpYear(),\n 'cc_exp_month': this.creditCardExpMonth(),\n 'cc_number': this.creditCardNumber()\n }\n };\n },\n\n /**\n * Get list of available credit card types\n * @returns {Object}\n */\n getCcAvailableTypes: function () {\n return window.checkoutConfig.payment.ccform.availableTypes[this.getCode()];\n },\n\n /**\n * Get payment icons\n * @param {String} type\n * @returns {Boolean}\n */\n getIcons: function (type) {\n return window.checkoutConfig.payment.ccform.icons.hasOwnProperty(type) ?\n window.checkoutConfig.payment.ccform.icons[type]\n : false;\n },\n\n /**\n * Get list of months\n * @returns {Object}\n */\n getCcMonths: function () {\n return window.checkoutConfig.payment.ccform.months[this.getCode()];\n },\n\n /**\n * Get list of years\n * @returns {Object}\n */\n getCcYears: function () {\n return window.checkoutConfig.payment.ccform.years[this.getCode()];\n },\n\n /**\n * Check if current payment has verification\n * @returns {Boolean}\n */\n hasVerification: function () {\n return window.checkoutConfig.payment.ccform.hasVerification[this.getCode()];\n },\n\n /**\n * @deprecated\n * @returns {Boolean}\n */\n hasSsCardType: function () {\n return window.checkoutConfig.payment.ccform.hasSsCardType[this.getCode()];\n },\n\n /**\n * Get image url for CVV\n * @returns {String}\n */\n getCvvImageUrl: function () {\n return window.checkoutConfig.payment.ccform.cvvImageUrl[this.getCode()];\n },\n\n /**\n * Get image for CVV\n * @returns {String}\n */\n getCvvImageHtml: function () {\n return '<img src=\"' + this.getCvvImageUrl() +\n '\" alt=\"' + $t('Card Verification Number Visual Reference') +\n '\" title=\"' + $t('Card Verification Number Visual Reference') +\n '\" />';\n },\n\n /**\n * Get unsanitized html for image for CVV\n * @returns {String}\n */\n getCvvImageUnsanitizedHtml: function () {\n return this.getCvvImageHtml();\n },\n\n /**\n * @deprecated\n * @returns {Object}\n */\n getSsStartYears: function () {\n return window.checkoutConfig.payment.ccform.ssStartYears[this.getCode()];\n },\n\n /**\n * Get list of available credit card types values\n * @returns {Object}\n */\n getCcAvailableTypesValues: function () {\n return _.map(this.getCcAvailableTypes(), function (value, key) {\n return {\n 'value': key,\n 'type': value\n };\n });\n },\n\n /**\n * Get list of available month values\n * @returns {Object}\n */\n getCcMonthsValues: function () {\n return _.map(this.getCcMonths(), function (value, key) {\n return {\n 'value': key,\n 'month': value\n };\n });\n },\n\n /**\n * Get list of available year values\n * @returns {Object}\n */\n getCcYearsValues: function () {\n return _.map(this.getCcYears(), function (value, key) {\n return {\n 'value': key,\n 'year': value\n };\n });\n },\n\n /**\n * @deprecated\n * @returns {Object}\n */\n getSsStartYearsValues: function () {\n return _.map(this.getSsStartYears(), function (value, key) {\n return {\n 'value': key,\n 'year': value\n };\n });\n },\n\n /**\n * Is legend available to display\n * @returns {Boolean}\n */\n isShowLegend: function () {\n return false;\n },\n\n /**\n * Get available credit card type by code\n * @param {String} code\n * @returns {String}\n */\n getCcTypeTitleByCode: function (code) {\n var title = '',\n keyValue = 'value',\n keyType = 'type';\n\n _.each(this.getCcAvailableTypesValues(), function (value) {\n if (value[keyValue] === code) {\n title = value[keyType];\n }\n });\n\n return title;\n },\n\n /**\n * Prepare credit card number to output\n * @param {String} number\n * @returns {String}\n */\n formatDisplayCcNumber: function (number) {\n return 'xxxx-' + number.substr(-4);\n },\n\n /**\n * Get credit card details\n * @returns {Array}\n */\n getInfo: function () {\n return [\n {\n 'name': 'Credit Card Type', value: this.getCcTypeTitleByCode(this.creditCardType())\n },\n {\n 'name': 'Credit Card Number', value: this.formatDisplayCcNumber(this.creditCardNumber())\n }\n ];\n }\n });\n});\n","Magento_Payment/js/view/payment/payments.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n 'use strict';\n\n rendererList.push(\n {\n type: 'free',\n component: 'Magento_Payment/js/view/payment/method-renderer/free-method'\n }\n );\n\n /** Add view logic here if needed */\n return Component.extend({});\n});\n","Magento_Payment/js/view/payment/method-renderer/free-method.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Payment/payment/free'\n },\n\n /** Returns is method available */\n isAvailable: function () {\n return quote.totals()['grand_total'] <= 0;\n }\n });\n});\n","Magento_Msrp/js/msrp.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'Magento_Catalog/js/price-utils',\n 'underscore',\n 'jquery-ui-modules/widget',\n 'mage/dropdown',\n 'mage/template'\n], function ($, priceUtils, _) {\n 'use strict';\n\n $.widget('mage.addToCart', {\n options: {\n showAddToCart: true,\n submitUrl: '',\n cartButtonId: '',\n singleOpenDropDown: true,\n dialog: {}, // Options for mage/dropdown\n dialogDelay: 500, // Delay in ms after resize dropdown shown again\n origin: '', //Required, type of popup: 'msrp', 'tier' or 'info' popup\n\n // Selectors\n cartForm: '.form.map.checkout',\n msrpLabelId: '#map-popup-msrp',\n msrpPriceElement: '#map-popup-msrp .price-wrapper',\n priceLabelId: '#map-popup-price',\n priceElement: '#map-popup-price .price',\n mapInfoLinks: '.map-show-info',\n displayPriceElement: '.old-price.map-old-price .price-wrapper',\n fallbackPriceElement: '.normal-price.map-fallback-price .price-wrapper',\n displayPriceContainer: '.old-price.map-old-price',\n fallbackPriceContainer: '.normal-price.map-fallback-price',\n popUpAttr: '[data-role=msrp-popup-template]',\n popupCartButtonId: '#map-popup-button',\n paypalCheckoutButons: '[data-action=checkout-form-submit]',\n popupId: '',\n realPrice: '',\n isSaleable: '',\n msrpPrice: '',\n helpLinkId: '',\n addToCartButton: '',\n\n // Text options\n productName: '',\n addToCartUrl: ''\n },\n\n openDropDown: null,\n triggerClass: 'dropdown-active',\n\n popUpOptions: {\n appendTo: 'body',\n dialogContentClass: 'active',\n closeOnMouseLeave: false,\n autoPosition: true,\n closeOnClickOutside: false,\n 'dialogClass': 'popup map-popup-wrapper',\n position: {\n my: 'left top',\n collision: 'fit none',\n at: 'left bottom',\n within: 'body'\n },\n shadowHinter: 'popup popup-pointer'\n },\n popupOpened: false,\n wasOpened: false,\n\n /**\n * Creates widget instance\n *\n * @private\n */\n _create: function () {\n if (this.options.origin === 'msrp') {\n this.initMsrpPopup();\n } else if (this.options.origin === 'info') {\n this.initInfoPopup();\n } else if (this.options.origin === 'tier') {\n this.initTierPopup();\n }\n $(this.options.cartButtonId).on('click', this._addToCartSubmit.bind(this));\n $(document).on('updateMsrpPriceBlock', this.onUpdateMsrpPrice.bind(this));\n $(this.options.cartForm).on('submit', this._onSubmitForm.bind(this));\n },\n\n /**\n * Init msrp popup\n *\n * @private\n */\n initMsrpPopup: function () {\n var popupDOM = $(this.options.popUpAttr)[0],\n $msrpPopup = $(popupDOM.innerHTML.trim());\n\n $msrpPopup.find(this.options.productIdInput).val(this.options.productId);\n $('body').append($msrpPopup);\n $msrpPopup.trigger('contentUpdated');\n\n $msrpPopup.find('button')\n .on('click',\n this.handleMsrpAddToCart.bind(this))\n .filter(this.options.popupCartButtonId)\n .text($(this.options.addToCartButton).text());\n\n $msrpPopup.find(this.options.paypalCheckoutButons).on('click',\n this.handleMsrpPaypalCheckout.bind(this));\n\n $(this.options.popupId).on('click',\n this.openPopup.bind(this));\n\n this.$popup = $msrpPopup;\n },\n\n /**\n * Init info popup\n *\n * @private\n */\n initInfoPopup: function () {\n var infoPopupDOM = $('[data-role=msrp-info-template]')[0],\n $infoPopup = $(infoPopupDOM.innerHTML.trim());\n\n $('body').append($infoPopup);\n\n $(this.options.helpLinkId).on('click', function (e) {\n this.popUpOptions.position.of = $(e.target);\n $infoPopup.dropdownDialog(this.popUpOptions).dropdownDialog('open');\n this._toggle($infoPopup);\n }.bind(this));\n\n this.$popup = $infoPopup;\n },\n\n /**\n * Init tier price popup\n * @private\n */\n initTierPopup: function () {\n var popupDOM = $(this.options.popUpAttr)[0],\n $tierPopup = $(popupDOM.innerHTML.trim());\n\n $('body').append($tierPopup);\n $tierPopup.find(this.options.productIdInput).val(this.options.productId);\n this.popUpOptions.position.of = $(this.options.helpLinkId);\n\n $tierPopup.find('button').on('click',\n this.handleTierAddToCart.bind(this))\n .filter(this.options.popupCartButtonId)\n .text($(this.options.addToCartButton).text());\n\n $tierPopup.find(this.options.paypalCheckoutButons).on('click',\n this.handleTierPaypalCheckout.bind(this));\n\n $(this.options.attr).on('click', function (e) {\n this.$popup = $tierPopup;\n this.tierOptions = $(e.target).data('tier-price');\n this.openPopup(e);\n }.bind(this));\n },\n\n /**\n * handle 'AddToCart' click on Msrp popup\n * @param {Object} ev\n *\n * @private\n */\n handleMsrpAddToCart: function (ev) {\n ev.preventDefault();\n\n if (this.options.addToCartButton) {\n $(this.options.addToCartButton).trigger('click');\n this.closePopup(this.$popup);\n }\n },\n\n /**\n * handle 'paypal checkout buttons' click on Msrp popup\n *\n * @private\n */\n handleMsrpPaypalCheckout: function () {\n this.closePopup(this.$popup);\n },\n\n /**\n * handle 'AddToCart' click on Tier popup\n *\n * @param {Object} ev\n * @private\n */\n handleTierAddToCart: function (ev) {\n ev.preventDefault();\n\n if (this.options.addToCartButton &&\n this.options.inputQty && !isNaN(this.tierOptions.qty)\n ) {\n $(this.options.inputQty).val(this.tierOptions.qty);\n $(this.options.addToCartButton).trigger('click');\n this.closePopup(this.$popup);\n }\n },\n\n /**\n * handle 'paypal checkout buttons' click on Tier popup\n *\n * @private\n */\n handleTierPaypalCheckout: function () {\n if (this.options.inputQty && !isNaN(this.tierOptions.qty)\n ) {\n $(this.options.inputQty).val(this.tierOptions.qty);\n this.closePopup(this.$popup);\n }\n },\n\n /**\n * Open and set up popup\n *\n * @param {Object} event\n */\n openPopup: function (event) {\n var options = this.tierOptions || this.options;\n\n this.popUpOptions.position.of = $(event.target);\n\n if (!this.wasOpened) {\n this.$popup.find(this.options.msrpLabelId).html(options.msrpPrice);\n this.$popup.find(this.options.priceLabelId).html(options.realPrice);\n this.wasOpened = true;\n }\n this.$popup.dropdownDialog(this.popUpOptions).dropdownDialog('open');\n this._toggle(this.$popup);\n\n if (!this.options.isSaleable) {\n this.$popup.find('form').hide();\n }\n },\n\n /**\n * Toggle MAP popup visibility\n *\n * @param {HTMLElement} $elem\n * @private\n */\n _toggle: function ($elem) {\n $(document).on('mouseup.msrp touchend.msrp', function (e) {\n if (!$elem.is(e.target) && $elem.has(e.target).length === 0) {\n this.closePopup($elem);\n }\n }.bind(this));\n $(window).on('resize', function () {\n this.closePopup($elem);\n }.bind(this));\n },\n\n /**\n * Close MAP information popup\n *\n * @param {HTMLElement} $elem\n */\n closePopup: function ($elem) {\n $elem.dropdownDialog('close');\n $(document).off('mouseup.msrp touchend.msrp');\n },\n\n /**\n * Handler for addToCart action\n *\n * @param {Object} e\n */\n _addToCartSubmit: function (e) {\n this.element.trigger('addToCart', this.element);\n\n if (this.element.data('stop-processing')) {\n return false;\n }\n\n if (this.options.addToCartButton) {\n $(this.options.addToCartButton).trigger('click');\n\n return false;\n }\n\n if (this.options.addToCartUrl) {\n $('.mage-dropdown-dialog > .ui-dialog-content').dropdownDialog('close');\n }\n\n e.preventDefault();\n $(this.options.cartForm).trigger('submit');\n },\n\n /**\n * Call on event updatePrice. Proxy to updateMsrpPrice method.\n *\n * @param {Event} event\n * @param {mixed} priceIndex\n * @param {Object} prices\n * @param {Object|undefined} $priceBox\n */\n onUpdateMsrpPrice: function onUpdateMsrpPrice(event, priceIndex, prices, $priceBox) {\n\n var defaultMsrp,\n defaultPrice,\n msrpPrice,\n finalPrice;\n\n defaultMsrp = _.chain(prices).map(function (price) {\n return price.msrpPrice.amount;\n }).reject(function (p) {\n return p === null;\n }).max().value();\n\n defaultPrice = _.chain(prices).map(function (p) {\n return p.finalPrice.amount;\n }).min().value();\n\n if (typeof priceIndex !== 'undefined') {\n msrpPrice = prices[priceIndex].msrpPrice.amount;\n finalPrice = prices[priceIndex].finalPrice.amount;\n\n if (msrpPrice === null || msrpPrice <= finalPrice) {\n this.updateNonMsrpPrice(priceUtils.formatPriceLocale(finalPrice), $priceBox);\n } else {\n this.updateMsrpPrice(\n priceUtils.formatPriceLocale(finalPrice),\n priceUtils.formatPriceLocale(msrpPrice),\n false,\n $priceBox);\n }\n } else {\n this.updateMsrpPrice(\n priceUtils.formatPriceLocale(defaultPrice),\n priceUtils.formatPriceLocale(defaultMsrp),\n true,\n $priceBox);\n }\n },\n\n /**\n * Update prices for configurable product with MSRP enabled\n *\n * @param {String} finalPrice\n * @param {String} msrpPrice\n * @param {Boolean} useDefaultPrice\n * @param {Object|undefined} $priceBox\n */\n updateMsrpPrice: function (finalPrice, msrpPrice, useDefaultPrice, $priceBox) {\n var options = this.tierOptions || this.options;\n\n $(this.options.fallbackPriceContainer, $priceBox).hide();\n $(this.options.displayPriceContainer, $priceBox).show();\n $(this.options.mapInfoLinks, $priceBox).show();\n\n if (useDefaultPrice || !this.wasOpened) {\n if (this.$popup) {\n this.$popup.find(this.options.msrpLabelId).html(options.msrpPrice);\n this.$popup.find(this.options.priceLabelId).html(options.realPrice);\n }\n\n $(this.options.displayPriceElement, $priceBox).html(msrpPrice);\n this.wasOpened = true;\n }\n\n if (!useDefaultPrice) {\n this.$popup.find(this.options.msrpPriceElement).html(msrpPrice);\n this.$popup.find(this.options.priceElement).html(finalPrice);\n $(this.options.displayPriceElement, $priceBox).html(msrpPrice);\n }\n },\n\n /**\n * Display non MAP price for irrelevant products\n *\n * @param {String} price\n * @param {Object|undefined} $priceBox\n */\n updateNonMsrpPrice: function (price, $priceBox) {\n $(this.options.fallbackPriceElement, $priceBox).html(price);\n $(this.options.displayPriceContainer, $priceBox).hide();\n $(this.options.mapInfoLinks, $priceBox).hide();\n $(this.options.fallbackPriceContainer, $priceBox).show();\n },\n\n /**\n * Handler for submit form\n *\n * @private\n */\n _onSubmitForm: function () {\n if ($(this.options.cartForm).valid()) {\n $(this.options.cartButtonId).prop('disabled', true);\n }\n }\n\n });\n\n return $.mage.addToCart;\n});\n","Magento_Msrp/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 'Magento_Tax/js/view/checkout/minicart/subtotal/totals',\n 'underscore'\n], function (Component, _) {\n 'use strict';\n\n return Component.extend({\n\n /**\n * @override\n */\n initialize: function () {\n this._super();\n this.displaySubtotal(this.isMsrpApplied(this.cart().items));\n this.cart.subscribe(function (updatedCart) {\n\n this.displaySubtotal(this.isMsrpApplied(updatedCart.items));\n }, this);\n },\n\n /**\n * Determine if subtotal should be hidden.\n * @param {Array} cartItems\n * @return {Boolean}\n */\n isMsrpApplied: function (cartItems) {\n return !_.find(cartItems, function (item) {\n if (_.has(item, 'canApplyMsrp')) {\n return item.canApplyMsrp;\n }\n\n return false;\n });\n }\n });\n});\n","Magento_Msrp/js/product/list/columns/msrp-price.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'underscore',\n 'Magento_Catalog/js/product/list/columns/price-box',\n 'Magento_Catalog/js/product/addtocart-button',\n 'mage/dropdown'\n], function ($, _, PriceBox) {\n 'use strict';\n\n return PriceBox.extend({\n defaults: {\n priceBoxSelector: '[data-role=msrp-price-box]',\n popupTmpl: 'Magento_Msrp/product/item/popup',\n popupTriggerSelector: '[data-role=msrp-popup-trigger]',\n popupSelector: '[data-role=msrp-popup]',\n popupOptions: {\n appendTo: 'body',\n dialogContentClass: 'active',\n closeOnMouseLeave: false,\n autoPosition: true,\n dialogClass: 'popup map-popup-wrapper',\n position: {\n my: 'left top',\n collision: 'fit none',\n at: 'left bottom',\n within: 'body'\n },\n shadowHinter: 'popup popup-pointer'\n }\n },\n\n /**\n * Create and open popup with Msrp information.\n *\n * @param {Object} data - element data\n * @param {DOMElement} elem - element\n * @param {Event} event - event object\n */\n openPopup: function (data, elem, event) {\n var $elem = $(elem),\n $popup = $elem.find(this.popupSelector),\n $trigger = $elem.find(this.popupTriggerSelector);\n\n event.stopPropagation();\n\n this.popupOptions.position.of = $trigger;\n this.popupOptions.triggerTarget = $trigger;\n\n $popup.dropdownDialog(this.popupOptions)\n .dropdownDialog('open');\n },\n\n /**\n * Set listeners.\n *\n * @param {DOMElement} elem - DOM element\n * @param {Object} data - element data\n */\n initListeners: function (elem, data) {\n var $trigger = $(elem).find(this.popupTriggerSelector);\n\n $trigger.on('click', this.openPopup.bind(this, data, elem));\n },\n\n /**\n * Check whether we can apply msrp, or should use standard price.\n *\n * @param {Object} row\n * @returns {Bool}\n */\n isMsrpApplicable: function (row) {\n return this.getPrice(row)['is_applicable'];\n },\n\n /**\n * Retrieve msrp formatted price\n *\n * @param {Object} row\n * @returns {String}\n */\n getPrice: function (row) {\n return row['price_info']['extension_attributes'].msrp;\n },\n\n /**\n * UnsanitizedHtml version of getPrice.\n *\n * @param {Object} row\n * @returns {String}\n */\n getPriceUnsanitizedHtml: function (row) {\n return this.getPrice(row);\n },\n\n /**\n * Get msrp_price property of a price.\n *\n * @param {Object} row\n * @return {HTMLElement} final price html\n */\n getMsrpPriceUnsanitizedHtml: function (row) {\n return this.getPrice(row)['msrp_price'];\n },\n\n /**\n * Returns path to the columns' body template.\n *\n * @returns {String}\n */\n getBody: function () {\n return this.bodyTmpl;\n },\n\n /**\n * Check if popup with actual price must be shown.\n *\n * @returns {Boolean}\n */\n isShowPriceOnGesture: function (row) {\n return this.getPrice(row)['is_shown_price_on_gesture'];\n },\n\n /**\n * Get msrp price supporting text.\n *\n * @returns {String}\n */\n getMsrpPriceMessage: function (row) {\n return this.getPrice(row)['msrp_message'];\n },\n\n /**\n * UnsanitizedHtml version of getMsrpPriceMessage.\n *\n * @returns {String}\n */\n getMsrpPriceMessageUnsanitizedHtml: function (row) {\n return this.getMsrpPriceMessage(row);\n },\n\n /**\n * Get msrp price supporting text, when actual price is hidden.\n *\n * @returns {String}\n */\n getExplanationMessage: function (row) {\n return this.getPrice(row)['explanation_message'];\n },\n\n /**\n * UnsanitizedHtml version of getExplanationMessage.\n *\n * @returns {String}\n */\n getExplanationMessageUnsanitizedHtml: function (row) {\n return this.getExplanationMessage(row);\n }\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_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} 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_Security/js/escaper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * A loose JavaScript version of Magento\\Framework\\Escaper\n *\n * Due to differences in how XML/HTML is processed in PHP vs JS there are a couple of minor differences in behavior\n * from the PHP counterpart.\n *\n * The first difference is that the default invocation of escapeHtml without allowedTags will double-escape existing\n * entities as the intention of such an invocation is that the input isn't supposed to contain any HTML.\n *\n * The second difference is that escapeHtml will not escape quotes. Since the input is actually being processed by the\n * DOM there is no chance of quotes being mixed with HTML syntax. And, since escapeHtml is not\n * intended to be used with raw injection into a HTML attribute, this is acceptable.\n *\n * @api\n */\ndefine([], function () {\n 'use strict';\n\n return {\n neverAllowedElements: ['script', 'img', 'embed', 'iframe', 'video', 'source', 'object', 'audio'],\n generallyAllowedAttributes: ['id', 'class', 'href', 'title', 'style'],\n forbiddenAttributesByElement: {\n a: ['style']\n },\n\n /**\n * Escape a string for safe injection into HTML\n *\n * @param {String} data\n * @param {Array|null} allowedTags\n * @returns {String}\n */\n escapeHtml: function (data, allowedTags) {\n var domParser = new DOMParser(),\n fragment = domParser.parseFromString('<div></div>', 'text/html');\n\n fragment = fragment.body.childNodes[0];\n allowedTags = typeof allowedTags === 'object' && allowedTags.length ? allowedTags : null;\n\n if (allowedTags) {\n fragment.innerHTML = data || '';\n allowedTags = this._filterProhibitedTags(allowedTags);\n\n this._removeComments(fragment);\n this._removeNotAllowedElements(fragment, allowedTags);\n this._removeNotAllowedAttributes(fragment);\n\n return fragment.innerHTML;\n }\n\n fragment.textContent = data || '';\n\n return fragment.innerHTML;\n },\n\n /**\n * Remove the always forbidden tags from a list of provided tags\n *\n * @param {Array} tags\n * @returns {Array}\n * @private\n */\n _filterProhibitedTags: function (tags) {\n return tags.filter(function (n) {\n return this.neverAllowedElements.indexOf(n) === -1;\n }.bind(this));\n },\n\n /**\n * Remove comment nodes from the given node\n *\n * @param {Node} node\n * @private\n */\n _removeComments: function (node) {\n var treeWalker = node.ownerDocument.createTreeWalker(\n node,\n NodeFilter.SHOW_COMMENT,\n function () {\n return NodeFilter.FILTER_ACCEPT;\n },\n false\n ),\n nodesToRemove = [];\n\n while (treeWalker.nextNode()) {\n nodesToRemove.push(treeWalker.currentNode);\n }\n\n nodesToRemove.forEach(function (nodeToRemove) {\n nodeToRemove.parentNode.removeChild(nodeToRemove);\n });\n },\n\n /**\n * Strip the given node of all disallowed tags while permitting any nested text nodes\n *\n * @param {Node} node\n * @param {Array|null} allowedTags\n * @private\n */\n _removeNotAllowedElements: function (node, allowedTags) {\n var treeWalker = node.ownerDocument.createTreeWalker(\n node,\n NodeFilter.SHOW_ELEMENT,\n function (currentNode) {\n return allowedTags.indexOf(currentNode.nodeName.toLowerCase()) === -1 ?\n NodeFilter.FILTER_ACCEPT\n // SKIP instead of REJECT because REJECT also rejects child nodes\n : NodeFilter.FILTER_SKIP;\n },\n false\n ),\n nodesToRemove = [];\n\n while (treeWalker.nextNode()) {\n if (allowedTags.indexOf(treeWalker.currentNode.nodeName.toLowerCase()) === -1) {\n nodesToRemove.push(treeWalker.currentNode);\n }\n }\n\n nodesToRemove.forEach(function (nodeToRemove) {\n nodeToRemove.parentNode.replaceChild(\n node.ownerDocument.createTextNode(nodeToRemove.textContent),\n nodeToRemove\n );\n });\n },\n\n /**\n * Remove any invalid attributes from the given node\n *\n * @param {Node} node\n * @private\n */\n _removeNotAllowedAttributes: function (node) {\n var treeWalker = node.ownerDocument.createTreeWalker(\n node,\n NodeFilter.SHOW_ELEMENT,\n function () {\n return NodeFilter.FILTER_ACCEPT;\n },\n false\n ),\n i,\n attribute,\n nodeName,\n attributesToRemove = [];\n\n while (treeWalker.nextNode()) {\n for (i = 0; i < treeWalker.currentNode.attributes.length; i++) {\n attribute = treeWalker.currentNode.attributes[i];\n nodeName = treeWalker.currentNode.nodeName.toLowerCase();\n\n if (this.generallyAllowedAttributes.indexOf(attribute.name) === -1 || // eslint-disable-line max-depth,max-len\n this._checkHrefValue(attribute) ||\n this.forbiddenAttributesByElement[nodeName] &&\n this.forbiddenAttributesByElement[nodeName].indexOf(attribute.name) !== -1\n ) {\n attributesToRemove.push(attribute);\n }\n }\n }\n\n attributesToRemove.forEach(function (attributeToRemove) {\n attributeToRemove.ownerElement.removeAttribute(attributeToRemove.name);\n });\n },\n\n /**\n * Check that attribute contains script content\n *\n * @param {Object} attribute\n * @private\n */\n _checkHrefValue: function (attribute) {\n return attribute.nodeName === 'href' && attribute.nodeValue.startsWith('javascript');\n }\n };\n});\n","Magento_PageBuilder/js/widget-initializer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'jquery',\n 'mage/apply/main',\n 'Magento_Ui/js/lib/view/utils/dom-observer'\n], function (_, $, mage, domObserver) {\n 'use strict';\n\n /**\n * Initializes components assigned to HTML elements.\n *\n *\n * @param {HTMLElement} el\n * @param {Array} data\n * @param {Object} breakpoints\n * @param {Object} currentViewport\n */\n function initializeWidget(el, data, breakpoints, currentViewport) {\n _.each(data, function (config, component) {\n config = config || {};\n config.breakpoints = breakpoints;\n config.currentViewport = currentViewport;\n mage.applyFor(el, config, component);\n });\n }\n\n return function (data, contextElement) {\n _.each(data.config, function (componentConfiguration, elementPath) {\n domObserver.get(\n elementPath,\n function (element) {\n var $element = $(element);\n\n if (contextElement) {\n $element = $(contextElement).find(element);\n }\n\n if ($element.length) {\n initializeWidget($element, componentConfiguration, data.breakpoints, data.currentViewport);\n }\n }\n );\n });\n };\n});\n","Magento_PageBuilder/js/events.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['uiEvents'], function (uiEvents) {\n 'use strict';\n\n return {\n\n /**\n * Calls callback when name event is triggered\n *\n * @param {String} events\n * @param {Function} callback\n * @param {Function} ns\n * @return {Object}\n */\n on: function (events, callback, ns) {\n uiEvents.on('pagebuilder:' + events, callback, 'pagebuilder:' + ns);\n\n return this;\n },\n\n /**\n * Removed callback from listening to target event\n *\n * @param {String} ns\n * @return {Object}\n */\n off: function (ns) {\n uiEvents.off('pagebuilder:' + ns);\n\n return this;\n },\n\n /**\n * Triggers event and executes all attached callbacks\n *\n * @param {String} name\n * @param {any} args\n * @returns {Boolean}\n */\n trigger: function (name, args) {\n return uiEvents.trigger('pagebuilder:' + name, args);\n }\n };\n});\n","Magento_PageBuilder/js/content-type/banner/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'Magento_PageBuilder/js/widget/show-on-hover',\n 'Magento_PageBuilder/js/widget/video-background'\n], function (showOnHover, videoBackground) {\n 'use strict';\n\n return function (config, element) {\n var videoElement = element[0].querySelector('[data-background-type=video]');\n\n showOnHover(config);\n\n if (videoElement) {\n videoBackground(config, videoElement);\n }\n };\n});\n","Magento_PageBuilder/js/content-type/tabs/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'Magento_PageBuilder/js/events',\n 'jquery-ui-modules/tabs'\n], function ($, events) {\n 'use strict';\n\n return function (config, element) {\n var $element = $(element);\n\n // Ignore stage builder preview tabs\n if ($element.is('.pagebuilder-tabs')) {\n return;\n }\n\n // Disambiguate between the mage/tabs component which is loaded randomly depending on requirejs order.\n $.ui.tabs({\n active: $element.data('activeTab') || 0,\n create:\n\n /**\n * Adjust the margin bottom of the navigation to correctly display the active tab\n */\n function () {\n var borderWidth = parseInt($element.find('.tabs-content').css('borderWidth').toString(), 10);\n\n $element.find('.tabs-navigation').css('marginBottom', -borderWidth);\n $element.find('.tabs-navigation li:not(:first-child)').css('marginLeft', -borderWidth);\n },\n activate:\n\n /**\n * Trigger redraw event since new content is being displayed\n */\n function () {\n events.trigger('contentType:redrawAfter', {\n element: element\n });\n }\n }, element);\n };\n});\n","Magento_PageBuilder/js/content-type/buttons/appearance/inline/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'Magento_PageBuilder/js/events'\n], function ($, events) {\n 'use strict';\n\n /**\n * Equalize the width of a list of button-item components\n *\n * @param {JQuery} buttonList\n */\n var equalizeButtonWidth = function (buttonList) {\n var buttonMinWidth = 0;\n\n buttonList.css('min-width', buttonMinWidth);\n buttonList.each(function () {\n var buttonWidth = this.offsetWidth;\n\n if (buttonWidth > buttonMinWidth) {\n buttonMinWidth = buttonWidth;\n }\n });\n buttonList.css('min-width', buttonMinWidth);\n };\n\n return function (config, element) {\n var $element = $(element),\n buttonSelector = '[data-element=\"link\"], [data-element=\"empty_link\"]';\n\n if ($element.data('sameWidth')) {\n equalizeButtonWidth($element.find(buttonSelector));\n $(window).on('resize', function () {\n equalizeButtonWidth($element.find(buttonSelector));\n });\n events.on('contentType:redrawAfter', function (eventData) {\n if ($element.closest(eventData.element).length > 0) {\n equalizeButtonWidth($element.find(buttonSelector));\n }\n });\n }\n };\n});\n","Magento_PageBuilder/js/content-type/row/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'Magento_PageBuilder/js/widget/video-background',\n 'jarallax'\n], function ($, videoBackground) {\n 'use strict';\n\n return function (config, element) {\n var $element = $(element),\n parallaxSpeed = null,\n elementStyle = null;\n\n if ($element.data('appearance') === 'contained') {\n $element = $(element).find('[data-element=\"inner\"]');\n }\n\n if ($element.data('background-type') === 'video') {\n videoBackground(config, $element[0]);\n\n return;\n }\n\n if ($element.data('enableParallax') !== 1) {\n return;\n }\n\n $element.addClass('jarallax');\n $element.attr('data-jarallax', '');\n\n parallaxSpeed = parseFloat($element.data('parallaxSpeed'));\n elementStyle = window.getComputedStyle($element[0]);\n\n window.jarallax($element[0], {\n imgPosition: elementStyle.backgroundPosition || '50% 50%',\n imgRepeat: elementStyle.backgroundRepeat || 'no-repeat',\n imgSize: elementStyle.backgroundSize || 'cover',\n speed: !isNaN(parallaxSpeed) ? parallaxSpeed : 0.5\n });\n };\n});\n","Magento_PageBuilder/js/content-type/slider/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'Magento_PageBuilder/js/events',\n 'slick'\n], function ($, events) {\n 'use strict';\n\n return function (config, sliderElement) {\n var $element = $(sliderElement);\n\n /**\n * Prevent each slick slider from being initialized more than once which could throw an error.\n */\n if ($element.hasClass('slick-initialized')) {\n $element.slick('unslick');\n }\n\n $element.slick({\n autoplay: $element.data('autoplay'),\n autoplaySpeed: $element.data('autoplay-speed') || 0,\n fade: $element.data('fade'),\n infinite: $element.data('infinite-loop'),\n arrows: $element.data('show-arrows'),\n dots: $element.data('show-dots')\n });\n\n // Redraw slide after content type gets redrawn\n events.on('contentType:redrawAfter', function (args) {\n if ($element.closest(args.element).length) {\n $element.slick('setPosition');\n }\n });\n // eslint-disable-next-line jquery-no-bind-unbind\n events.on('stage:viewportChangeAfter', $element.slick.bind($element, 'setPosition'));\n };\n});\n","Magento_PageBuilder/js/content-type/map/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'Magento_PageBuilder/js/utils/map'\n], function ($, GoogleMap) {\n 'use strict';\n\n return function (config, element) {\n var locations,\n controls,\n mapOptions = {};\n\n element = element[0];\n\n if (element !== undefined && element.hasAttribute('data-locations')) {\n\n /**\n * Set map display to none if no locations\n */\n if (element.getAttribute('data-locations') === '[]') {\n $(element).hide();\n\n return;\n }\n locations = JSON.parse(element.getAttribute('data-locations'));\n locations.forEach(function (location) {\n location.position.latitude = parseFloat(location.position.latitude);\n location.position.longitude = parseFloat(location.position.longitude);\n });\n controls = element.getAttribute('data-show-controls');\n mapOptions.disableDefaultUI = controls !== 'true';\n mapOptions.mapTypeControl = controls === 'true';\n new GoogleMap(element, locations, mapOptions);\n }\n };\n});\n","Magento_PageBuilder/js/content-type/products/appearance/carousel/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'underscore',\n 'matchMedia',\n 'Magento_PageBuilder/js/utils/breakpoints',\n 'Magento_PageBuilder/js/events',\n 'slick'\n], function ($, _, mediaCheck, breakpointsUtils, events) {\n 'use strict';\n\n /**\n * Build slick\n *\n * @param {jQuery} $carouselElement\n * @param {Object} config\n */\n function buildSlick($carouselElement, config) {\n /**\n * Prevent each slick slider from being initialized more than once which could throw an error.\n */\n if ($carouselElement.hasClass('slick-initialized')) {\n $carouselElement.slick('unslick');\n }\n\n config.slidesToScroll = config.slidesToShow;\n $carouselElement.slick(config);\n }\n\n /**\n * Initialize slider.\n *\n * @param {jQuery} $element\n * @param {Object} slickConfig\n * @param {Object} breakpoint\n */\n function initSlider($element, slickConfig, breakpoint) {\n var productCount = $element.find('.product-item').length,\n $carouselElement = $($element.children()),\n centerModeClass = 'center-mode',\n carouselMode = $element.data('carousel-mode'),\n slidesToShow = breakpoint.options.products[carouselMode] ?\n breakpoint.options.products[carouselMode].slidesToShow :\n breakpoint.options.products.default.slidesToShow;\n\n slickConfig.slidesToShow = parseFloat(slidesToShow);\n\n if (carouselMode === 'continuous' && productCount > slickConfig.slidesToShow) {\n $element.addClass(centerModeClass);\n slickConfig.centerPadding = $element.data('center-padding');\n slickConfig.centerMode = true;\n } else {\n $element.removeClass(centerModeClass);\n slickConfig.infinite = $element.data('infinite-loop');\n }\n\n buildSlick($carouselElement, slickConfig);\n }\n\n return function (config, element) {\n var $element = $(element),\n $carouselElement = $($element.children()),\n currentViewport = config.currentViewport,\n currentBreakpoint = config.breakpoints[currentViewport],\n slickConfig = {\n autoplay: $element.data('autoplay'),\n autoplaySpeed: $element.data('autoplay-speed') || 0,\n arrows: $element.data('show-arrows'),\n dots: $element.data('show-dots')\n };\n\n _.each(config.breakpoints, function (breakpoint) {\n mediaCheck({\n media: breakpointsUtils.buildMedia(breakpoint.conditions),\n\n /** @inheritdoc */\n entry: function () {\n initSlider($element, slickConfig, breakpoint);\n }\n });\n });\n\n //initialize slider when content type is added in mobile viewport\n if (currentViewport === 'mobile') {\n initSlider($element, slickConfig, currentBreakpoint);\n }\n\n // Redraw slide after content type gets redrawn\n events.on('contentType:redrawAfter', function (args) {\n if ($carouselElement.closest(args.element).length) {\n $carouselElement.slick('setPosition');\n }\n });\n\n events.on('stage:viewportChangeAfter', function (args) {\n var breakpoint = config.breakpoints[args.viewport];\n\n initSlider($element, slickConfig, breakpoint);\n });\n };\n});\n","Magento_PageBuilder/js/content-type/slide/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'underscore',\n 'Magento_PageBuilder/js/widget/show-on-hover',\n 'Magento_PageBuilder/js/widget/video-background'\n], function ($, _, showOnHover, videoBackground) {\n 'use strict';\n\n return function (config, element) {\n var videoElement = element[0].querySelector('[data-background-type=video]'),\n viewportElement = document.createElement('div'),\n $slider = null;\n\n showOnHover(config);\n\n if (videoElement) {\n $slider = $(element).closest('[data-content-type=slider]');\n viewportElement.classList.add('jarallax-viewport-element');\n videoElement.setAttribute('data-element-in-viewport', '.jarallax-viewport-element');\n videoElement.appendChild(viewportElement);\n videoBackground(config, videoElement);\n\n if ($slider.data('afterChangeIsSet')) {\n return;\n }\n\n $slider.on('afterChange init', function () {\n var videoSlides = $slider[0].querySelectorAll('.jarallax');\n\n _.each(videoSlides, function (videoSlide) {\n videoSlide.jarallax && videoSlide.jarallax.onScroll();\n });\n });\n $slider.data('afterChangeIsSet', true);\n }\n };\n});\n","Magento_PageBuilder/js/widget/video-background.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'jarallax',\n 'jarallaxVideo',\n 'vimeoWrapper'\n], function ($) {\n 'use strict';\n\n return function (config, element) {\n var $element = $(element),\n parallaxSpeed = $element.data('enableParallax') !== 1 ? 1 : parseFloat($element.data('parallaxSpeed'));\n\n if ($element.data('background-type') !== 'video') {\n return;\n }\n\n $element.addClass('jarallax');\n $element.attr('data-jarallax', '');\n\n window.jarallax($element[0], {\n imgSrc: $element.data('videoFallbackSrc'),\n speed: !isNaN(parallaxSpeed) ? parallaxSpeed : 0.5,\n videoLoop: $element.data('videoLoop'),\n videoPlayOnlyVisible: $element.data('videoPlayOnlyVisible'),\n videoLazyLoading: $element.data('videoLazyLoad'),\n disableVideo: false,\n elementInViewport: $element.data('elementInViewport') &&\n $element[0].querySelector($element.data('elementInViewport'))\n });\n $element[0].jarallax.video && $element[0].jarallax.video.on('started', function () {\n if ($element[0].jarallax.$video) {\n $element[0].jarallax.$video.style.visibility = 'visible';\n }\n });\n };\n});\n","Magento_PageBuilder/js/widget/show-on-hover.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 /**\n * Show the overlay on hover of specific elements\n *\n * @param {JQuery<Element>[]} $elements\n */\n function showOverlayOnHover($elements) {\n $elements.each(function (index, element) {\n var overlayEl = $(element).find('.pagebuilder-overlay'),\n overlayColor = overlayEl.attr('data-overlay-color');\n\n $(element).on('mouseenter', function () {\n overlayEl.css('background-color', overlayColor);\n });\n\n $(element).on('mouseleave', function () {\n overlayEl.css('background-color', 'transparent');\n });\n });\n }\n\n /**\n * Show button on hover of specific elements\n *\n * @param {JQuery<Element>[]} $elements\n * @param {String} buttonClass\n */\n function showButtonOnHover($elements, buttonClass) {\n $elements.each(function (index, element) {\n var buttonEl = $(element).find(buttonClass);\n\n $(element).on('mouseenter', function () {\n buttonEl.css({\n 'opacity': '1',\n 'visibility': 'visible'\n });\n });\n\n $(element).on('mouseleave', function () {\n buttonEl.css({\n 'opacity': '0',\n 'visibility': 'hidden'\n });\n });\n });\n }\n\n return function (config) {\n\n var buttonSelector = config.buttonSelector,\n overlayHoverSelector = 'div[data-content-type=\"%s\"][data-show-overlay=\"%s\"]'\n .replace('%s', config.dataRole)\n .replace('%s', config.showOverlay),\n overlayButtonSelector = 'div[data-content-type=\"%s\"][data-show-button=\"%s\"]'\n .replace('%s', config.dataRole)\n .replace('%s', config.showOverlay);\n\n showOverlayOnHover($(overlayHoverSelector));\n showButtonOnHover($(overlayButtonSelector), buttonSelector);\n };\n});\n","Magento_PageBuilder/js/resource/jarallax/jarallax.js":"/*!\n * Jarallax v2.0.3 (https://github.com/nk-o/jarallax)\n * Copyright 2022 nK <https://nkdev.info>\n * Licensed under MIT (https://github.com/nk-o/jarallax/blob/master/LICENSE)\n */\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.jarallax = factory());\n})(this, (function () { 'use strict';\n\n function ready(callback) {\n if ('complete' === document.readyState || 'interactive' === document.readyState) {\n // Already ready or interactive, execute callback\n callback();\n } else {\n document.addEventListener('DOMContentLoaded', callback, {\n capture: true,\n once: true,\n passive: true\n });\n }\n }\n\n /* eslint-disable import/no-mutable-exports */\n\n /* eslint-disable no-restricted-globals */\n let win;\n\n if ('undefined' !== typeof window) {\n win = window;\n } else if ('undefined' !== typeof global) {\n win = global;\n } else if ('undefined' !== typeof self) {\n win = self;\n } else {\n win = {};\n }\n\n var global$1 = win;\n\n const {\n navigator\n } = global$1;\n const isMobile = /*#__PURE__*/ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n let $deviceHelper;\n /**\n * The most popular mobile browsers changes height after page scroll and this generates image jumping.\n * We can fix it using this workaround with vh units.\n */\n\n function getDeviceHeight() {\n if (!$deviceHelper && document.body) {\n $deviceHelper = document.createElement('div');\n $deviceHelper.style.cssText = 'position: fixed; top: -9999px; left: 0; height: 100vh; width: 0;';\n document.body.appendChild($deviceHelper);\n }\n\n return ($deviceHelper ? $deviceHelper.clientHeight : 0) || global$1.innerHeight || document.documentElement.clientHeight;\n } // Window height data\n\n\n let wndH;\n\n function updateWndVars() {\n if (isMobile) {\n wndH = getDeviceHeight();\n } else {\n wndH = global$1.innerHeight || document.documentElement.clientHeight;\n }\n }\n\n updateWndVars();\n global$1.addEventListener('resize', updateWndVars);\n global$1.addEventListener('orientationchange', updateWndVars);\n global$1.addEventListener('load', updateWndVars);\n ready(() => {\n updateWndVars();\n }); // list with all jarallax instances\n // need to render all in one scroll/resize event\n\n const jarallaxList = []; // get all parents of the element.\n\n function getParents(elem) {\n const parents = [];\n\n while (null !== elem.parentElement) {\n elem = elem.parentElement;\n\n if (1 === elem.nodeType) {\n parents.push(elem);\n }\n }\n\n return parents;\n }\n\n function updateParallax() {\n if (!jarallaxList.length) {\n return;\n }\n\n jarallaxList.forEach((data, k) => {\n const {\n instance,\n oldData\n } = data;\n const clientRect = instance.$item.getBoundingClientRect();\n const newData = {\n width: clientRect.width,\n height: clientRect.height,\n top: clientRect.top,\n bottom: clientRect.bottom,\n wndW: global$1.innerWidth,\n wndH\n };\n const isResized = !oldData || oldData.wndW !== newData.wndW || oldData.wndH !== newData.wndH || oldData.width !== newData.width || oldData.height !== newData.height;\n const isScrolled = isResized || !oldData || oldData.top !== newData.top || oldData.bottom !== newData.bottom;\n jarallaxList[k].oldData = newData;\n\n if (isResized) {\n instance.onResize();\n }\n\n if (isScrolled) {\n instance.onScroll();\n }\n });\n global$1.requestAnimationFrame(updateParallax);\n }\n\n let instanceID = 0; // Jarallax class\n\n class Jarallax {\n constructor(item, userOptions) {\n const self = this;\n self.instanceID = instanceID;\n instanceID += 1;\n self.$item = item;\n self.defaults = {\n type: 'scroll',\n // type of parallax: scroll, scale, opacity, scale-opacity, scroll-opacity\n speed: 0.5,\n // supported value from -1 to 2\n imgSrc: null,\n imgElement: '.jarallax-img',\n imgSize: 'cover',\n imgPosition: '50% 50%',\n imgRepeat: 'no-repeat',\n // supported only for background, not for <img> tag\n keepImg: false,\n // keep <img> tag in it's default place\n elementInViewport: null,\n zIndex: -100,\n disableParallax: false,\n disableVideo: false,\n // video\n videoSrc: null,\n videoStartTime: 0,\n videoEndTime: 0,\n videoVolume: 0,\n videoLoop: true,\n videoPlayOnlyVisible: true,\n videoLazyLoading: true,\n // events\n onScroll: null,\n // function(calculations) {}\n onInit: null,\n // function() {}\n onDestroy: null,\n // function() {}\n onCoverImage: null // function() {}\n\n }; // prepare data-options\n\n const dataOptions = self.$item.dataset || {};\n const pureDataOptions = {};\n Object.keys(dataOptions).forEach(key => {\n const loweCaseOption = key.substr(0, 1).toLowerCase() + key.substr(1);\n\n if (loweCaseOption && 'undefined' !== typeof self.defaults[loweCaseOption]) {\n pureDataOptions[loweCaseOption] = dataOptions[key];\n }\n });\n self.options = self.extend({}, self.defaults, pureDataOptions, userOptions);\n self.pureOptions = self.extend({}, self.options); // prepare 'true' and 'false' strings to boolean\n\n Object.keys(self.options).forEach(key => {\n if ('true' === self.options[key]) {\n self.options[key] = true;\n } else if ('false' === self.options[key]) {\n self.options[key] = false;\n }\n }); // fix speed option [-1.0, 2.0]\n\n self.options.speed = Math.min(2, Math.max(-1, parseFloat(self.options.speed))); // prepare disableParallax callback\n\n if ('string' === typeof self.options.disableParallax) {\n self.options.disableParallax = new RegExp(self.options.disableParallax);\n }\n\n if (self.options.disableParallax instanceof RegExp) {\n const disableParallaxRegexp = self.options.disableParallax;\n\n self.options.disableParallax = () => disableParallaxRegexp.test(navigator.userAgent);\n }\n\n if ('function' !== typeof self.options.disableParallax) {\n self.options.disableParallax = () => false;\n } // prepare disableVideo callback\n\n\n if ('string' === typeof self.options.disableVideo) {\n self.options.disableVideo = new RegExp(self.options.disableVideo);\n }\n\n if (self.options.disableVideo instanceof RegExp) {\n const disableVideoRegexp = self.options.disableVideo;\n\n self.options.disableVideo = () => disableVideoRegexp.test(navigator.userAgent);\n }\n\n if ('function' !== typeof self.options.disableVideo) {\n self.options.disableVideo = () => false;\n } // custom element to check if parallax in viewport\n\n\n let elementInVP = self.options.elementInViewport; // get first item from array\n\n if (elementInVP && 'object' === typeof elementInVP && 'undefined' !== typeof elementInVP.length) {\n [elementInVP] = elementInVP;\n } // check if dom element\n\n\n if (!(elementInVP instanceof Element)) {\n elementInVP = null;\n }\n\n self.options.elementInViewport = elementInVP;\n self.image = {\n src: self.options.imgSrc || null,\n $container: null,\n useImgTag: false,\n // 1. Position fixed is needed for the most of browsers because absolute position have glitches\n // 2. On MacOS with smooth scroll there is a huge lags with absolute position - https://github.com/nk-o/jarallax/issues/75\n // 3. Previously used 'absolute' for mobile devices. But we re-tested on iPhone 12 and 'fixed' position is working better, then 'absolute', so for now position is always 'fixed'\n position: 'fixed'\n };\n\n if (self.initImg() && self.canInitParallax()) {\n self.init();\n }\n } // add styles to element\n // eslint-disable-next-line class-methods-use-this\n\n\n css(el, styles) {\n if ('string' === typeof styles) {\n return global$1.getComputedStyle(el).getPropertyValue(styles);\n }\n\n Object.keys(styles).forEach(key => {\n el.style[key] = styles[key];\n });\n return el;\n } // Extend like jQuery.extend\n // eslint-disable-next-line class-methods-use-this\n\n\n extend(out, ...args) {\n out = out || {};\n Object.keys(args).forEach(i => {\n if (!args[i]) {\n return;\n }\n\n Object.keys(args[i]).forEach(key => {\n out[key] = args[i][key];\n });\n });\n return out;\n } // get window size and scroll position. Useful for extensions\n // eslint-disable-next-line class-methods-use-this\n\n\n getWindowData() {\n return {\n width: global$1.innerWidth || document.documentElement.clientWidth,\n height: wndH,\n y: document.documentElement.scrollTop\n };\n } // Jarallax functions\n\n\n initImg() {\n const self = this; // find image element\n\n let $imgElement = self.options.imgElement;\n\n if ($imgElement && 'string' === typeof $imgElement) {\n $imgElement = self.$item.querySelector($imgElement);\n } // check if dom element\n\n\n if (!($imgElement instanceof Element)) {\n if (self.options.imgSrc) {\n $imgElement = new Image();\n $imgElement.src = self.options.imgSrc;\n } else {\n $imgElement = null;\n }\n }\n\n if ($imgElement) {\n if (self.options.keepImg) {\n self.image.$item = $imgElement.cloneNode(true);\n } else {\n self.image.$item = $imgElement;\n self.image.$itemParent = $imgElement.parentNode;\n }\n\n self.image.useImgTag = true;\n } // true if there is img tag\n\n\n if (self.image.$item) {\n return true;\n } // get image src\n\n\n if (null === self.image.src) {\n self.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n self.image.bgImage = self.css(self.$item, 'background-image');\n }\n\n return !(!self.image.bgImage || 'none' === self.image.bgImage);\n }\n\n canInitParallax() {\n return !this.options.disableParallax();\n }\n\n init() {\n const self = this;\n const containerStyles = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n overflow: 'hidden'\n };\n let imageStyles = {\n pointerEvents: 'none',\n transformStyle: 'preserve-3d',\n backfaceVisibility: 'hidden',\n willChange: 'transform,opacity'\n };\n\n if (!self.options.keepImg) {\n // save default user styles\n const curStyle = self.$item.getAttribute('style');\n\n if (curStyle) {\n self.$item.setAttribute('data-jarallax-original-styles', curStyle);\n }\n\n if (self.image.useImgTag) {\n const curImgStyle = self.image.$item.getAttribute('style');\n\n if (curImgStyle) {\n self.image.$item.setAttribute('data-jarallax-original-styles', curImgStyle);\n }\n }\n } // set relative position and z-index to the parent\n\n\n if ('static' === self.css(self.$item, 'position')) {\n self.css(self.$item, {\n position: 'relative'\n });\n }\n\n if ('auto' === self.css(self.$item, 'z-index')) {\n self.css(self.$item, {\n zIndex: 0\n });\n } // container for parallax image\n\n\n self.image.$container = document.createElement('div');\n self.css(self.image.$container, containerStyles);\n self.css(self.image.$container, {\n 'z-index': self.options.zIndex\n }); // it will remove some image overlapping\n // overlapping occur due to an image position fixed inside absolute position element\n // needed only when background in fixed position\n\n if ('fixed' === this.image.position) {\n self.css(self.image.$container, {\n '-webkit-clip-path': 'polygon(0 0, 100% 0, 100% 100%, 0 100%)',\n 'clip-path': 'polygon(0 0, 100% 0, 100% 100%, 0 100%)'\n });\n }\n\n self.image.$container.setAttribute('id', `jarallax-container-${self.instanceID}`);\n self.$item.appendChild(self.image.$container); // use img tag\n\n if (self.image.useImgTag) {\n imageStyles = self.extend({\n 'object-fit': self.options.imgSize,\n 'object-position': self.options.imgPosition,\n 'max-width': 'none'\n }, containerStyles, imageStyles); // use div with background image\n } else {\n self.image.$item = document.createElement('div');\n\n if (self.image.src) {\n imageStyles = self.extend({\n 'background-position': self.options.imgPosition,\n 'background-size': self.options.imgSize,\n 'background-repeat': self.options.imgRepeat,\n 'background-image': self.image.bgImage || `url(\"${self.image.src}\")`\n }, containerStyles, imageStyles);\n }\n }\n\n if ('opacity' === self.options.type || 'scale' === self.options.type || 'scale-opacity' === self.options.type || 1 === self.options.speed) {\n self.image.position = 'absolute';\n } // 1. Check if one of parents have transform style (without this check, scroll transform will be inverted if used parallax with position fixed)\n // discussion - https://github.com/nk-o/jarallax/issues/9\n // 2. Check if parents have overflow scroll\n\n\n if ('fixed' === self.image.position) {\n const $parents = getParents(self.$item).filter(el => {\n const styles = global$1.getComputedStyle(el);\n const parentTransform = styles['-webkit-transform'] || styles['-moz-transform'] || styles.transform;\n const overflowRegex = /(auto|scroll)/;\n return parentTransform && 'none' !== parentTransform || overflowRegex.test(styles.overflow + styles['overflow-y'] + styles['overflow-x']);\n });\n self.image.position = $parents.length ? 'absolute' : 'fixed';\n } // add position to parallax block\n\n\n imageStyles.position = self.image.position; // insert parallax image\n\n self.css(self.image.$item, imageStyles);\n self.image.$container.appendChild(self.image.$item); // set initial position and size\n\n self.onResize();\n self.onScroll(true); // call onInit event\n\n if (self.options.onInit) {\n self.options.onInit.call(self);\n } // remove default user background\n\n\n if ('none' !== self.css(self.$item, 'background-image')) {\n self.css(self.$item, {\n 'background-image': 'none'\n });\n }\n\n self.addToParallaxList();\n } // add to parallax instances list\n\n\n addToParallaxList() {\n jarallaxList.push({\n instance: this\n });\n\n if (1 === jarallaxList.length) {\n global$1.requestAnimationFrame(updateParallax);\n }\n } // remove from parallax instances list\n\n\n removeFromParallaxList() {\n const self = this;\n jarallaxList.forEach((data, key) => {\n if (data.instance.instanceID === self.instanceID) {\n jarallaxList.splice(key, 1);\n }\n });\n }\n\n destroy() {\n const self = this;\n self.removeFromParallaxList(); // return styles on container as before jarallax init\n\n const originalStylesTag = self.$item.getAttribute('data-jarallax-original-styles');\n self.$item.removeAttribute('data-jarallax-original-styles'); // null occurs if there is no style tag before jarallax init\n\n if (!originalStylesTag) {\n self.$item.removeAttribute('style');\n } else {\n self.$item.setAttribute('style', originalStylesTag);\n }\n\n if (self.image.useImgTag) {\n // return styles on img tag as before jarallax init\n const originalStylesImgTag = self.image.$item.getAttribute('data-jarallax-original-styles');\n self.image.$item.removeAttribute('data-jarallax-original-styles'); // null occurs if there is no style tag before jarallax init\n\n if (!originalStylesImgTag) {\n self.image.$item.removeAttribute('style');\n } else {\n self.image.$item.setAttribute('style', originalStylesTag);\n } // move img tag to its default position\n\n\n if (self.image.$itemParent) {\n self.image.$itemParent.appendChild(self.image.$item);\n }\n } // remove additional dom elements\n\n\n if (self.image.$container) {\n self.image.$container.parentNode.removeChild(self.image.$container);\n } // call onDestroy event\n\n\n if (self.options.onDestroy) {\n self.options.onDestroy.call(self);\n } // delete jarallax from item\n\n\n delete self.$item.jarallax;\n } // Fallback for removed function.\n // Does nothing now.\n // eslint-disable-next-line class-methods-use-this\n\n\n clipContainer() {}\n\n coverImage() {\n const self = this;\n const rect = self.image.$container.getBoundingClientRect();\n const contH = rect.height;\n const {\n speed\n } = self.options;\n const isScroll = 'scroll' === self.options.type || 'scroll-opacity' === self.options.type;\n let scrollDist = 0;\n let resultH = contH;\n let resultMT = 0; // scroll parallax\n\n if (isScroll) {\n // scroll distance and height for image\n if (0 > speed) {\n scrollDist = speed * Math.max(contH, wndH);\n\n if (wndH < contH) {\n scrollDist -= speed * (contH - wndH);\n }\n } else {\n scrollDist = speed * (contH + wndH);\n } // size for scroll parallax\n\n\n if (1 < speed) {\n resultH = Math.abs(scrollDist - wndH);\n } else if (0 > speed) {\n resultH = scrollDist / speed + Math.abs(scrollDist);\n } else {\n resultH += (wndH - contH) * (1 - speed);\n }\n\n scrollDist /= 2;\n } // store scroll distance\n\n\n self.parallaxScrollDistance = scrollDist; // vertical center\n\n if (isScroll) {\n resultMT = (wndH - resultH) / 2;\n } else {\n resultMT = (contH - resultH) / 2;\n } // apply result to item\n\n\n self.css(self.image.$item, {\n height: `${resultH}px`,\n marginTop: `${resultMT}px`,\n left: 'fixed' === self.image.position ? `${rect.left}px` : '0',\n width: `${rect.width}px`\n }); // call onCoverImage event\n\n if (self.options.onCoverImage) {\n self.options.onCoverImage.call(self);\n } // return some useful data. Used in the video cover function\n\n\n return {\n image: {\n height: resultH,\n marginTop: resultMT\n },\n container: rect\n };\n }\n\n isVisible() {\n return this.isElementInViewport || false;\n }\n\n onScroll(force) {\n const self = this;\n const rect = self.$item.getBoundingClientRect();\n const contT = rect.top;\n const contH = rect.height;\n const styles = {}; // check if in viewport\n\n let viewportRect = rect;\n\n if (self.options.elementInViewport) {\n viewportRect = self.options.elementInViewport.getBoundingClientRect();\n }\n\n self.isElementInViewport = 0 <= viewportRect.bottom && 0 <= viewportRect.right && viewportRect.top <= wndH && viewportRect.left <= global$1.innerWidth; // stop calculations if item is not in viewport\n\n if (force ? false : !self.isElementInViewport) {\n return;\n } // calculate parallax helping variables\n\n\n const beforeTop = Math.max(0, contT);\n const beforeTopEnd = Math.max(0, contH + contT);\n const afterTop = Math.max(0, -contT);\n const beforeBottom = Math.max(0, contT + contH - wndH);\n const beforeBottomEnd = Math.max(0, contH - (contT + contH - wndH));\n const afterBottom = Math.max(0, -contT + wndH - contH);\n const fromViewportCenter = 1 - 2 * ((wndH - contT) / (wndH + contH)); // calculate on how percent of section is visible\n\n let visiblePercent = 1;\n\n if (contH < wndH) {\n visiblePercent = 1 - (afterTop || beforeBottom) / contH;\n } else if (beforeTopEnd <= wndH) {\n visiblePercent = beforeTopEnd / wndH;\n } else if (beforeBottomEnd <= wndH) {\n visiblePercent = beforeBottomEnd / wndH;\n } // opacity\n\n\n if ('opacity' === self.options.type || 'scale-opacity' === self.options.type || 'scroll-opacity' === self.options.type) {\n styles.transform = 'translate3d(0,0,0)';\n styles.opacity = visiblePercent;\n } // scale\n\n\n if ('scale' === self.options.type || 'scale-opacity' === self.options.type) {\n let scale = 1;\n\n if (0 > self.options.speed) {\n scale -= self.options.speed * visiblePercent;\n } else {\n scale += self.options.speed * (1 - visiblePercent);\n }\n\n styles.transform = `scale(${scale}) translate3d(0,0,0)`;\n } // scroll\n\n\n if ('scroll' === self.options.type || 'scroll-opacity' === self.options.type) {\n let positionY = self.parallaxScrollDistance * fromViewportCenter; // fix if parallax block in absolute position\n\n if ('absolute' === self.image.position) {\n positionY -= contT;\n }\n\n styles.transform = `translate3d(0,${positionY}px,0)`;\n }\n\n self.css(self.image.$item, styles); // call onScroll event\n\n if (self.options.onScroll) {\n self.options.onScroll.call(self, {\n section: rect,\n beforeTop,\n beforeTopEnd,\n afterTop,\n beforeBottom,\n beforeBottomEnd,\n afterBottom,\n visiblePercent,\n fromViewportCenter\n });\n }\n }\n\n onResize() {\n this.coverImage();\n }\n\n } // global definition\n\n\n const jarallax = function (items, options, ...args) {\n // check for dom element\n // thanks: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object\n if ('object' === typeof HTMLElement ? items instanceof HTMLElement : items && 'object' === typeof items && null !== items && 1 === items.nodeType && 'string' === typeof items.nodeName) {\n items = [items];\n }\n\n const len = items.length;\n let k = 0;\n let ret;\n\n for (k; k < len; k += 1) {\n if ('object' === typeof options || 'undefined' === typeof options) {\n if (!items[k].jarallax) {\n items[k].jarallax = new Jarallax(items[k], options);\n }\n } else if (items[k].jarallax) {\n // eslint-disable-next-line prefer-spread\n ret = items[k].jarallax[options].apply(items[k].jarallax, args);\n }\n\n if ('undefined' !== typeof ret) {\n return ret;\n }\n }\n\n return items;\n };\n\n jarallax.constructor = Jarallax;\n\n const $ = global$1.jQuery; // jQuery support\n\n if ('undefined' !== typeof $) {\n const $Plugin = function (...args) {\n Array.prototype.unshift.call(args, this);\n const res = jarallax.apply(global$1, args);\n return 'object' !== typeof res ? res : this;\n };\n\n $Plugin.constructor = jarallax.constructor; // no conflict\n\n const old$Plugin = $.fn.jarallax;\n $.fn.jarallax = $Plugin;\n\n $.fn.jarallax.noConflict = function () {\n $.fn.jarallax = old$Plugin;\n return this;\n };\n } // data-jarallax initialization\n\n\n ready(() => {\n jarallax(document.querySelectorAll('[data-jarallax]'));\n });\n\n return jarallax;\n\n}));\n//# sourceMappingURL=jarallax.js.map\n","Magento_PageBuilder/js/resource/jarallax/jarallax-video.js":"/*!\n * Video Extension for Jarallax v2.0.3 (https://github.com/nk-o/jarallax)\n * Copyright 2022 nK <https://nkdev.info>\n * Licensed under MIT (https://github.com/nk-o/jarallax/blob/master/LICENSE)\n */\n\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.jarallaxVideo = factory());\n})(this, (function () { 'use strict';\n\n /*!\n * Name : Video Worker\n * Version : 2.0.0\n * Author : nK <https://nkdev.info>\n * GitHub : https://github.com/nk-o/video-worker\n */\n\n /* eslint-disable import/no-mutable-exports */\n\n /* eslint-disable no-restricted-globals */\n let win$1;\n\n if (typeof window !== 'undefined') {\n win$1 = window;\n } else if (typeof global !== 'undefined') {\n win$1 = global;\n } else if (typeof self !== 'undefined') {\n win$1 = self;\n } else {\n win$1 = {};\n }\n\n var global$1$1 = win$1; // Deferred\n // thanks http://stackoverflow.com/questions/18096715/implement-deferred-object-without-using-jquery\n\n function Deferred() {\n this.doneCallbacks = [];\n this.failCallbacks = [];\n }\n\n Deferred.prototype = {\n execute(list, args) {\n let i = list.length; // eslint-disable-next-line no-param-reassign\n\n args = Array.prototype.slice.call(args);\n\n while (i) {\n i -= 1;\n list[i].apply(null, args);\n }\n },\n\n resolve(...args) {\n this.execute(this.doneCallbacks, args);\n },\n\n reject(...args) {\n this.execute(this.failCallbacks, args);\n },\n\n done(callback) {\n this.doneCallbacks.push(callback);\n },\n\n fail(callback) {\n this.failCallbacks.push(callback);\n }\n\n };\n let ID = 0;\n let YoutubeAPIadded = 0;\n let VimeoAPIadded = 0;\n let loadingYoutubePlayer = 0;\n let loadingVimeoPlayer = 0;\n const loadingYoutubeDefer = /*#__PURE__*/new Deferred();\n const loadingVimeoDefer = /*#__PURE__*/new Deferred();\n\n class VideoWorker {\n constructor(url, options) {\n const self = this;\n self.url = url;\n self.options_default = {\n autoplay: false,\n loop: false,\n mute: false,\n volume: 100,\n showControls: true,\n accessibilityHidden: false,\n // start / end video time in seconds\n startTime: 0,\n endTime: 0\n };\n self.options = self.extend({}, self.options_default, options); // Fix wrong option name.\n // Thanks to https://github.com/nk-o/video-worker/issues/13.\n\n if (typeof self.options.showContols !== 'undefined') {\n self.options.showControls = self.options.showContols;\n delete self.options.showContols;\n } // check URL\n\n\n self.videoID = self.parseURL(url); // init\n\n if (self.videoID) {\n self.ID = ID;\n ID += 1;\n self.loadAPI();\n self.init();\n }\n } // Extend like jQuery.extend\n // eslint-disable-next-line class-methods-use-this\n\n\n extend(...args) {\n const out = args[0] || {};\n Object.keys(args).forEach(i => {\n if (!args[i]) {\n return;\n }\n\n Object.keys(args[i]).forEach(key => {\n out[key] = args[i][key];\n });\n });\n return out;\n }\n\n parseURL(url) {\n // parse youtube ID\n function getYoutubeID(ytUrl) {\n // eslint-disable-next-line no-useless-escape\n const regExp = /.*(?:youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=)([^#\\&\\?]*).*/;\n const match = ytUrl.match(regExp);\n return match && match[1].length === 11 ? match[1] : false;\n } // parse vimeo ID\n\n\n function getVimeoID(vmUrl) {\n // eslint-disable-next-line no-useless-escape\n const regExp = /https?:\\/\\/(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/([^/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|video\\/|)(\\d+)(?:$|\\/|\\?)/;\n const match = vmUrl.match(regExp);\n return match && match[3] ? match[3] : false;\n } // parse local string\n\n\n function getLocalVideos(locUrl) {\n // eslint-disable-next-line no-useless-escape\n const videoFormats = locUrl.split(/,(?=mp4\\:|webm\\:|ogv\\:|ogg\\:)/);\n const result = {};\n let ready = 0;\n videoFormats.forEach(val => {\n // eslint-disable-next-line no-useless-escape\n const match = val.match(/^(mp4|webm|ogv|ogg)\\:(.*)/);\n\n if (match && match[1] && match[2]) {\n // eslint-disable-next-line prefer-destructuring\n result[match[1] === 'ogv' ? 'ogg' : match[1]] = match[2];\n ready = 1;\n }\n });\n return ready ? result : false;\n }\n\n const Youtube = getYoutubeID(url);\n const Vimeo = getVimeoID(url);\n const Local = getLocalVideos(url);\n\n if (Youtube) {\n this.type = 'youtube';\n return Youtube;\n }\n\n if (Vimeo) {\n this.type = 'vimeo';\n return Vimeo;\n }\n\n if (Local) {\n this.type = 'local';\n return Local;\n }\n\n return false;\n }\n\n isValid() {\n return !!this.videoID;\n } // events\n\n\n on(name, callback) {\n this.userEventsList = this.userEventsList || []; // add new callback in events list\n\n (this.userEventsList[name] || (this.userEventsList[name] = [])).push(callback);\n }\n\n off(name, callback) {\n if (!this.userEventsList || !this.userEventsList[name]) {\n return;\n }\n\n if (!callback) {\n delete this.userEventsList[name];\n } else {\n this.userEventsList[name].forEach((val, key) => {\n if (val === callback) {\n this.userEventsList[name][key] = false;\n }\n });\n }\n }\n\n fire(name, ...args) {\n if (this.userEventsList && typeof this.userEventsList[name] !== 'undefined') {\n this.userEventsList[name].forEach(val => {\n // call with all arguments\n if (val) {\n val.apply(this, args);\n }\n });\n }\n }\n\n play(start) {\n const self = this;\n\n if (!self.player) {\n return;\n }\n\n if (self.type === 'youtube' && self.player.playVideo) {\n if (typeof start !== 'undefined') {\n self.player.seekTo(start || 0);\n }\n\n if (global$1$1.YT.PlayerState.PLAYING !== self.player.getPlayerState()) {\n self.player.playVideo();\n }\n }\n\n if (self.type === 'vimeo') {\n if (typeof start !== 'undefined') {\n self.player.setCurrentTime(start);\n }\n\n self.player.getPaused().then(paused => {\n if (paused) {\n self.player.play();\n }\n });\n }\n\n if (self.type === 'local') {\n if (typeof start !== 'undefined') {\n self.player.currentTime = start;\n }\n\n if (self.player.paused) {\n self.player.play();\n }\n }\n }\n\n pause() {\n const self = this;\n\n if (!self.player) {\n return;\n }\n\n if (self.type === 'youtube' && self.player.pauseVideo) {\n if (global$1$1.YT.PlayerState.PLAYING === self.player.getPlayerState()) {\n self.player.pauseVideo();\n }\n }\n\n if (self.type === 'vimeo') {\n self.player.getPaused().then(paused => {\n if (!paused) {\n self.player.pause();\n }\n });\n }\n\n if (self.type === 'local') {\n if (!self.player.paused) {\n self.player.pause();\n }\n }\n }\n\n mute() {\n const self = this;\n\n if (!self.player) {\n return;\n }\n\n if (self.type === 'youtube' && self.player.mute) {\n self.player.mute();\n }\n\n if (self.type === 'vimeo' && self.player.setVolume) {\n self.player.setVolume(0);\n }\n\n if (self.type === 'local') {\n self.$video.muted = true;\n }\n }\n\n unmute() {\n const self = this;\n\n if (!self.player) {\n return;\n }\n\n if (self.type === 'youtube' && self.player.mute) {\n self.player.unMute();\n }\n\n if (self.type === 'vimeo' && self.player.setVolume) {\n self.player.setVolume(self.options.volume);\n }\n\n if (self.type === 'local') {\n self.$video.muted = false;\n }\n }\n\n setVolume(volume = false) {\n const self = this;\n\n if (!self.player || !volume) {\n return;\n }\n\n if (self.type === 'youtube' && self.player.setVolume) {\n self.player.setVolume(volume);\n }\n\n if (self.type === 'vimeo' && self.player.setVolume) {\n self.player.setVolume(volume);\n }\n\n if (self.type === 'local') {\n self.$video.volume = volume / 100;\n }\n }\n\n getVolume(callback) {\n const self = this;\n\n if (!self.player) {\n callback(false);\n return;\n }\n\n if (self.type === 'youtube' && self.player.getVolume) {\n callback(self.player.getVolume());\n }\n\n if (self.type === 'vimeo' && self.player.getVolume) {\n self.player.getVolume().then(volume => {\n callback(volume);\n });\n }\n\n if (self.type === 'local') {\n callback(self.$video.volume * 100);\n }\n }\n\n getMuted(callback) {\n const self = this;\n\n if (!self.player) {\n callback(null);\n return;\n }\n\n if (self.type === 'youtube' && self.player.isMuted) {\n callback(self.player.isMuted());\n }\n\n if (self.type === 'vimeo' && self.player.getVolume) {\n self.player.getVolume().then(volume => {\n callback(!!volume);\n });\n }\n\n if (self.type === 'local') {\n callback(self.$video.muted);\n }\n }\n\n getImageURL(callback) {\n const self = this;\n\n if (self.videoImage) {\n callback(self.videoImage);\n return;\n }\n\n if (self.type === 'youtube') {\n const availableSizes = ['maxresdefault', 'sddefault', 'hqdefault', '0'];\n let step = 0;\n const tempImg = new Image();\n\n tempImg.onload = function () {\n // if no thumbnail, youtube add their own image with width = 120px\n if ((this.naturalWidth || this.width) !== 120 || step === availableSizes.length - 1) {\n // ok\n self.videoImage = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n callback(self.videoImage);\n } else {\n // try another size\n step += 1;\n this.src = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n }\n };\n\n tempImg.src = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n }\n\n if (self.type === 'vimeo') {\n let request = new XMLHttpRequest(); // https://vimeo.com/api/oembed.json?url=https://vimeo.com/235212527\n\n request.open('GET', `https://vimeo.com/api/oembed.json?url=${self.url}`, true);\n\n request.onreadystatechange = function () {\n if (this.readyState === 4) {\n if (this.status >= 200 && this.status < 400) {\n // Success!\n const response = JSON.parse(this.responseText);\n\n if (response.thumbnail_url) {\n self.videoImage = response.thumbnail_url;\n callback(self.videoImage);\n }\n }\n }\n };\n\n request.send();\n request = null;\n }\n } // fallback to the old version.\n\n\n getIframe(callback) {\n this.getVideo(callback);\n }\n\n getVideo(callback) {\n const self = this; // return generated video block\n\n if (self.$video) {\n callback(self.$video);\n return;\n } // generate new video block\n\n\n self.onAPIready(() => {\n let hiddenDiv;\n\n if (!self.$video) {\n hiddenDiv = document.createElement('div');\n hiddenDiv.style.display = 'none';\n } // Youtube\n\n\n if (self.type === 'youtube') {\n self.playerOptions = {\n // GDPR Compliance.\n host: 'https://www.youtube-nocookie.com',\n videoId: self.videoID,\n playerVars: {\n autohide: 1,\n rel: 0,\n autoplay: 0,\n // autoplay enable on mobile devices\n playsinline: 1\n }\n }; // hide controls\n\n if (!self.options.showControls) {\n self.playerOptions.playerVars.iv_load_policy = 3;\n self.playerOptions.playerVars.modestbranding = 1;\n self.playerOptions.playerVars.controls = 0;\n self.playerOptions.playerVars.showinfo = 0;\n self.playerOptions.playerVars.disablekb = 1;\n } // events\n\n\n let ytStarted;\n let ytProgressInterval;\n self.playerOptions.events = {\n onReady(e) {\n // mute\n if (self.options.mute) {\n e.target.mute();\n } else if (self.options.volume) {\n e.target.setVolume(self.options.volume);\n } // autoplay\n\n\n if (self.options.autoplay) {\n self.play(self.options.startTime);\n }\n\n self.fire('ready', e); // For seamless loops, set the endTime to 0.1 seconds less than the video's duration\n // https://github.com/nk-o/video-worker/issues/2\n\n if (self.options.loop && !self.options.endTime) {\n const secondsOffset = 0.1;\n self.options.endTime = self.player.getDuration() - secondsOffset;\n } // volumechange\n\n\n setInterval(() => {\n self.getVolume(volume => {\n if (self.options.volume !== volume) {\n self.options.volume = volume;\n self.fire('volumechange', e);\n }\n });\n }, 150);\n },\n\n onStateChange(e) {\n // loop\n if (self.options.loop && e.data === global$1$1.YT.PlayerState.ENDED) {\n self.play(self.options.startTime);\n }\n\n if (!ytStarted && e.data === global$1$1.YT.PlayerState.PLAYING) {\n ytStarted = 1;\n self.fire('started', e);\n }\n\n if (e.data === global$1$1.YT.PlayerState.PLAYING) {\n self.fire('play', e);\n }\n\n if (e.data === global$1$1.YT.PlayerState.PAUSED) {\n self.fire('pause', e);\n }\n\n if (e.data === global$1$1.YT.PlayerState.ENDED) {\n self.fire('ended', e);\n } // progress check\n\n\n if (e.data === global$1$1.YT.PlayerState.PLAYING) {\n ytProgressInterval = setInterval(() => {\n self.fire('timeupdate', e); // check for end of video and play again or stop\n\n if (self.options.endTime && self.player.getCurrentTime() >= self.options.endTime) {\n if (self.options.loop) {\n self.play(self.options.startTime);\n } else {\n self.pause();\n }\n }\n }, 150);\n } else {\n clearInterval(ytProgressInterval);\n }\n },\n\n onError(e) {\n self.fire('error', e);\n }\n\n };\n const firstInit = !self.$video;\n\n if (firstInit) {\n const div = document.createElement('div');\n div.setAttribute('id', self.playerID);\n hiddenDiv.appendChild(div);\n document.body.appendChild(hiddenDiv);\n }\n\n self.player = self.player || new global$1$1.YT.Player(self.playerID, self.playerOptions);\n\n if (firstInit) {\n self.$video = document.getElementById(self.playerID); // add accessibility attributes\n\n if (self.options.accessibilityHidden) {\n self.$video.setAttribute('tabindex', '-1');\n self.$video.setAttribute('aria-hidden', 'true');\n } // get video width and height\n\n\n self.videoWidth = parseInt(self.$video.getAttribute('width'), 10) || 1280;\n self.videoHeight = parseInt(self.$video.getAttribute('height'), 10) || 720;\n }\n } // Vimeo\n\n\n if (self.type === 'vimeo') {\n self.playerOptions = {\n // GDPR Compliance.\n dnt: 1,\n id: self.videoID,\n autopause: 0,\n transparent: 0,\n autoplay: self.options.autoplay ? 1 : 0,\n loop: self.options.loop ? 1 : 0,\n muted: self.options.mute ? 1 : 0\n };\n\n if (self.options.volume) {\n self.playerOptions.volume = self.options.volume;\n } // hide controls\n\n\n if (!self.options.showControls) {\n self.playerOptions.badge = 0;\n self.playerOptions.byline = 0;\n self.playerOptions.portrait = 0;\n self.playerOptions.title = 0;\n self.playerOptions.background = 1;\n }\n\n if (!self.$video) {\n let playerOptionsString = '';\n Object.keys(self.playerOptions).forEach(key => {\n if (playerOptionsString !== '') {\n playerOptionsString += '&';\n }\n\n playerOptionsString += `${key}=${encodeURIComponent(self.playerOptions[key])}`;\n }); // we need to create iframe manually because when we create it using API\n // js events won't triggers after iframe moved to another place\n\n self.$video = document.createElement('iframe');\n self.$video.setAttribute('id', self.playerID);\n self.$video.setAttribute('src', `https://player.vimeo.com/video/${self.videoID}?${playerOptionsString}`);\n self.$video.setAttribute('frameborder', '0');\n self.$video.setAttribute('mozallowfullscreen', '');\n self.$video.setAttribute('allowfullscreen', '');\n self.$video.setAttribute('title', 'Vimeo video player'); // add accessibility attributes\n\n if (self.options.accessibilityHidden) {\n self.$video.setAttribute('tabindex', '-1');\n self.$video.setAttribute('aria-hidden', 'true');\n }\n\n hiddenDiv.appendChild(self.$video);\n document.body.appendChild(hiddenDiv);\n }\n\n self.player = self.player || new global$1$1.Vimeo.Player(self.$video, self.playerOptions); // set current time for autoplay\n\n if (self.options.startTime && self.options.autoplay) {\n self.player.setCurrentTime(self.options.startTime);\n } // get video width and height\n\n\n self.player.getVideoWidth().then(width => {\n self.videoWidth = width || 1280;\n });\n self.player.getVideoHeight().then(height => {\n self.videoHeight = height || 720;\n }); // events\n\n let vmStarted;\n self.player.on('timeupdate', e => {\n if (!vmStarted) {\n self.fire('started', e);\n vmStarted = 1;\n }\n\n self.fire('timeupdate', e); // check for end of video and play again or stop\n\n if (self.options.endTime) {\n if (self.options.endTime && e.seconds >= self.options.endTime) {\n if (self.options.loop) {\n self.play(self.options.startTime);\n } else {\n self.pause();\n }\n }\n }\n });\n self.player.on('play', e => {\n self.fire('play', e); // check for the start time and start with it\n\n if (self.options.startTime && e.seconds === 0) {\n self.play(self.options.startTime);\n }\n });\n self.player.on('pause', e => {\n self.fire('pause', e);\n });\n self.player.on('ended', e => {\n self.fire('ended', e);\n });\n self.player.on('loaded', e => {\n self.fire('ready', e);\n });\n self.player.on('volumechange', e => {\n self.fire('volumechange', e);\n });\n self.player.on('error', e => {\n self.fire('error', e);\n });\n } // Local\n\n\n function addSourceToLocal(element, src, type) {\n const source = document.createElement('source');\n source.src = src;\n source.type = type;\n element.appendChild(source);\n }\n\n if (self.type === 'local') {\n if (!self.$video) {\n self.$video = document.createElement('video'); // show controls\n\n if (self.options.showControls) {\n self.$video.controls = true;\n } // mute\n\n\n if (self.options.mute) {\n self.$video.muted = true;\n } else if (self.$video.volume) {\n self.$video.volume = self.options.volume / 100;\n } // loop\n\n\n if (self.options.loop) {\n self.$video.loop = true;\n } // autoplay enable on mobile devices\n\n\n self.$video.setAttribute('playsinline', '');\n self.$video.setAttribute('webkit-playsinline', ''); // add accessibility attributes\n\n if (self.options.accessibilityHidden) {\n self.$video.setAttribute('tabindex', '-1');\n self.$video.setAttribute('aria-hidden', 'true');\n }\n\n self.$video.setAttribute('id', self.playerID);\n hiddenDiv.appendChild(self.$video);\n document.body.appendChild(hiddenDiv);\n Object.keys(self.videoID).forEach(key => {\n addSourceToLocal(self.$video, self.videoID[key], `video/${key}`);\n });\n }\n\n self.player = self.player || self.$video;\n let locStarted;\n self.player.addEventListener('playing', e => {\n if (!locStarted) {\n self.fire('started', e);\n }\n\n locStarted = 1;\n });\n self.player.addEventListener('timeupdate', function (e) {\n self.fire('timeupdate', e); // check for end of video and play again or stop\n\n if (self.options.endTime) {\n if (self.options.endTime && this.currentTime >= self.options.endTime) {\n if (self.options.loop) {\n self.play(self.options.startTime);\n } else {\n self.pause();\n }\n }\n }\n });\n self.player.addEventListener('play', e => {\n self.fire('play', e);\n });\n self.player.addEventListener('pause', e => {\n self.fire('pause', e);\n });\n self.player.addEventListener('ended', e => {\n self.fire('ended', e);\n });\n self.player.addEventListener('loadedmetadata', function () {\n // get video width and height\n self.videoWidth = this.videoWidth || 1280;\n self.videoHeight = this.videoHeight || 720;\n self.fire('ready'); // autoplay\n\n if (self.options.autoplay) {\n self.play(self.options.startTime);\n }\n });\n self.player.addEventListener('volumechange', e => {\n self.getVolume(volume => {\n self.options.volume = volume;\n });\n self.fire('volumechange', e);\n });\n self.player.addEventListener('error', e => {\n self.fire('error', e);\n });\n }\n\n callback(self.$video);\n });\n }\n\n init() {\n const self = this;\n self.playerID = `VideoWorker-${self.ID}`;\n }\n\n loadAPI() {\n const self = this;\n\n if (YoutubeAPIadded && VimeoAPIadded) {\n return;\n }\n\n let src = ''; // load Youtube API\n\n if (self.type === 'youtube' && !YoutubeAPIadded) {\n YoutubeAPIadded = 1;\n src = 'https://www.youtube.com/iframe_api';\n } // load Vimeo API\n\n\n if (self.type === 'vimeo' && !VimeoAPIadded) {\n VimeoAPIadded = 1; // Useful when Vimeo API added using RequireJS https://github.com/nk-o/video-worker/pull/7\n\n if (typeof global$1$1.Vimeo !== 'undefined') {\n return;\n }\n\n src = 'https://player.vimeo.com/api/player.js';\n }\n\n if (!src) {\n return;\n } // add script in head section\n\n\n let tag = document.createElement('script');\n let head = document.getElementsByTagName('head')[0];\n tag.src = src;\n head.appendChild(tag);\n head = null;\n tag = null;\n }\n\n onAPIready(callback) {\n const self = this; // Youtube\n\n if (self.type === 'youtube') {\n // Listen for global YT player callback\n if ((typeof global$1$1.YT === 'undefined' || global$1$1.YT.loaded === 0) && !loadingYoutubePlayer) {\n // Prevents Ready event from being called twice\n loadingYoutubePlayer = 1; // Creates deferred so, other players know when to wait.\n\n global$1$1.onYouTubeIframeAPIReady = function () {\n global$1$1.onYouTubeIframeAPIReady = null;\n loadingYoutubeDefer.resolve('done');\n callback();\n };\n } else if (typeof global$1$1.YT === 'object' && global$1$1.YT.loaded === 1) {\n callback();\n } else {\n loadingYoutubeDefer.done(() => {\n callback();\n });\n }\n } // Vimeo\n\n\n if (self.type === 'vimeo') {\n if (typeof global$1$1.Vimeo === 'undefined' && !loadingVimeoPlayer) {\n loadingVimeoPlayer = 1;\n const vimeoInterval = setInterval(() => {\n if (typeof global$1$1.Vimeo !== 'undefined') {\n clearInterval(vimeoInterval);\n loadingVimeoDefer.resolve('done');\n callback();\n }\n }, 20);\n } else if (typeof global$1$1.Vimeo !== 'undefined') {\n callback();\n } else {\n loadingVimeoDefer.done(() => {\n callback();\n });\n }\n } // Local\n\n\n if (self.type === 'local') {\n callback();\n }\n }\n\n }\n\n function ready(callback) {\n if ('complete' === document.readyState || 'interactive' === document.readyState) {\n // Already ready or interactive, execute callback\n callback();\n } else {\n document.addEventListener('DOMContentLoaded', callback, {\n capture: true,\n once: true,\n passive: true\n });\n }\n }\n\n /* eslint-disable import/no-mutable-exports */\n\n /* eslint-disable no-restricted-globals */\n let win;\n\n if ('undefined' !== typeof window) {\n win = window;\n } else if ('undefined' !== typeof global) {\n win = global;\n } else if ('undefined' !== typeof self) {\n win = self;\n } else {\n win = {};\n }\n\n var global$1 = win;\n\n function jarallaxVideo(jarallax = global$1.jarallax) {\n if ('undefined' === typeof jarallax) {\n return;\n }\n\n const Jarallax = jarallax.constructor; // append video after when block will be visible.\n\n const defOnScroll = Jarallax.prototype.onScroll;\n\n Jarallax.prototype.onScroll = function () {\n const self = this;\n defOnScroll.apply(self);\n const isReady = !self.isVideoInserted && self.video && (!self.options.videoLazyLoading || self.isElementInViewport) && !self.options.disableVideo();\n\n if (isReady) {\n self.isVideoInserted = true;\n self.video.getVideo(video => {\n const $parent = video.parentNode;\n self.css(video, {\n position: self.image.position,\n top: '0px',\n left: '0px',\n right: '0px',\n bottom: '0px',\n width: '100%',\n height: '100%',\n maxWidth: 'none',\n maxHeight: 'none',\n pointerEvents: 'none',\n transformStyle: 'preserve-3d',\n backfaceVisibility: 'hidden',\n willChange: 'transform,opacity',\n margin: 0,\n zIndex: -1\n });\n self.$video = video; // add Poster attribute to self-hosted video\n\n if ('local' === self.video.type) {\n if (self.image.src) {\n self.$video.setAttribute('poster', self.image.src);\n } else if (self.image.$item && 'IMG' === self.image.$item.tagName && self.image.$item.src) {\n self.$video.setAttribute('poster', self.image.$item.src);\n }\n } // insert video tag\n\n\n self.image.$container.appendChild(video); // remove parent video element (created by VideoWorker)\n\n $parent.parentNode.removeChild($parent); // call onVideoInsert event\n\n if (self.options.onVideoInsert) {\n self.options.onVideoInsert.call(self);\n }\n });\n }\n }; // cover video\n\n\n const defCoverImage = Jarallax.prototype.coverImage;\n\n Jarallax.prototype.coverImage = function () {\n const self = this;\n const imageData = defCoverImage.apply(self);\n const node = self.image.$item ? self.image.$item.nodeName : false;\n\n if (imageData && self.video && node && ('IFRAME' === node || 'VIDEO' === node)) {\n let h = imageData.image.height;\n let w = h * self.image.width / self.image.height;\n let ml = (imageData.container.width - w) / 2;\n let mt = imageData.image.marginTop;\n\n if (imageData.container.width > w) {\n w = imageData.container.width;\n h = w * self.image.height / self.image.width;\n ml = 0;\n mt += (imageData.image.height - h) / 2;\n } // add video height over than need to hide controls\n\n\n if ('IFRAME' === node) {\n h += 400;\n mt -= 200;\n }\n\n self.css(self.$video, {\n width: `${w}px`,\n marginLeft: `${ml}px`,\n height: `${h}px`,\n marginTop: `${mt}px`\n });\n }\n\n return imageData;\n }; // init video\n\n\n const defInitImg = Jarallax.prototype.initImg;\n\n Jarallax.prototype.initImg = function () {\n const self = this;\n const defaultResult = defInitImg.apply(self);\n\n if (!self.options.videoSrc) {\n self.options.videoSrc = self.$item.getAttribute('data-jarallax-video') || null;\n }\n\n if (self.options.videoSrc) {\n self.defaultInitImgResult = defaultResult;\n return true;\n }\n\n return defaultResult;\n };\n\n const defCanInitParallax = Jarallax.prototype.canInitParallax;\n\n Jarallax.prototype.canInitParallax = function () {\n const self = this;\n let defaultResult = defCanInitParallax.apply(self);\n\n if (!self.options.videoSrc) {\n return defaultResult;\n } // Init video api\n\n\n const video = new VideoWorker(self.options.videoSrc, {\n autoplay: true,\n loop: self.options.videoLoop,\n showControls: false,\n accessibilityHidden: true,\n startTime: self.options.videoStartTime || 0,\n endTime: self.options.videoEndTime || 0,\n mute: self.options.videoVolume ? 0 : 1,\n volume: self.options.videoVolume || 0\n }); // call onVideoWorkerInit event\n\n if (self.options.onVideoWorkerInit) {\n self.options.onVideoWorkerInit.call(self, video);\n }\n\n function resetDefaultImage() {\n if (self.image.$default_item) {\n self.image.$item = self.image.$default_item;\n self.image.$item.style.display = 'block'; // set image width and height\n\n self.coverImage();\n self.onScroll();\n }\n }\n\n if (video.isValid()) {\n // Force enable parallax.\n // When the parallax disabled on mobile devices, we still need to display videos.\n // https://github.com/nk-o/jarallax/issues/159\n if (this.options.disableParallax()) {\n defaultResult = true;\n self.image.position = 'absolute';\n self.options.type = 'scroll';\n self.options.speed = 1;\n } // if parallax will not be inited, we can add thumbnail on background.\n\n\n if (!defaultResult) {\n if (!self.defaultInitImgResult) {\n video.getImageURL(url => {\n // save default user styles\n const curStyle = self.$item.getAttribute('style');\n\n if (curStyle) {\n self.$item.setAttribute('data-jarallax-original-styles', curStyle);\n } // set new background\n\n\n self.css(self.$item, {\n 'background-image': `url(\"${url}\")`,\n 'background-position': 'center',\n 'background-size': 'cover'\n });\n });\n } // init video\n\n } else {\n video.on('ready', () => {\n if (self.options.videoPlayOnlyVisible) {\n const oldOnScroll = self.onScroll;\n\n self.onScroll = function () {\n oldOnScroll.apply(self);\n\n if (!self.videoError && (self.options.videoLoop || !self.options.videoLoop && !self.videoEnded)) {\n if (self.isVisible()) {\n video.play();\n } else {\n video.pause();\n }\n }\n };\n } else {\n video.play();\n }\n });\n video.on('started', () => {\n self.image.$default_item = self.image.$item;\n self.image.$item = self.$video; // set video width and height\n\n self.image.width = self.video.videoWidth || 1280;\n self.image.height = self.video.videoHeight || 720;\n self.coverImage();\n self.onScroll(); // hide image\n\n if (self.image.$default_item) {\n self.image.$default_item.style.display = 'none';\n }\n });\n video.on('ended', () => {\n self.videoEnded = true;\n\n if (!self.options.videoLoop) {\n // show default image if Loop disabled.\n resetDefaultImage();\n }\n });\n video.on('error', () => {\n self.videoError = true; // show default image if video loading error.\n\n resetDefaultImage();\n });\n self.video = video; // set image if not exists\n\n if (!self.defaultInitImgResult) {\n // set empty image on self-hosted video if not defined\n self.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n\n if ('local' !== video.type) {\n video.getImageURL(url => {\n self.image.bgImage = `url(\"${url}\")`;\n self.init();\n });\n return false;\n }\n }\n }\n }\n\n return defaultResult;\n }; // Destroy video parallax\n\n\n const defDestroy = Jarallax.prototype.destroy;\n\n Jarallax.prototype.destroy = function () {\n const self = this;\n\n if (self.image.$default_item) {\n self.image.$item = self.image.$default_item;\n delete self.image.$default_item;\n }\n\n defDestroy.apply(self);\n };\n }\n\n jarallaxVideo(); // data-jarallax-video initialization\n\n ready(() => {\n if ('undefined' !== typeof global$1.jarallax) {\n global$1.jarallax(document.querySelectorAll('[data-jarallax-video]'));\n }\n }); // We should add VideoWorker globally, since some project uses it.\n\n if (!global$1.VideoWorker) {\n global$1.VideoWorker = VideoWorker;\n }\n\n return jarallaxVideo;\n\n}));\n//# sourceMappingURL=jarallax-video.js.map\n","Magento_PageBuilder/js/resource/jarallax/jarallax-wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_PageBuilder/js/resource/jarallax/jarallax'\n], function(jarallax){\n 'use strict';\n\n window.jarallax = window.jarallax || jarallax;\n});\n","Magento_PageBuilder/js/resource/slick/slick.min.js":"/*\n _ _ _ _\n ___| (_) ___| | __ (_)___\n/ __| | |/ __| |/ / | / __|\n\\__ \\ | | (__| < _ | \\__ \\\n|___/_|_|\\___|_|\\_(_)/ |___/\n |__/\n\n Version: 1.9.0\n Author: Ken Wheeler\n Website: http://kenwheeler.github.io\n Docs: http://kenwheeler.github.io/slick\n Repo: http://github.com/kenwheeler/slick\n Issues: http://github.com/kenwheeler/slick/issues\n\n */\n(function(i){\"use strict\";\"function\"==typeof define&&define.amd?define([\"jquery\"],i):\"undefined\"!=typeof exports?module.exports=i(require(\"jquery\")):i(jQuery)})(function(i){\"use strict\";var e=window.Slick||{};e=function(){function e(e,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(e),appendDots:i(e),arrows:!0,asNavFor:null,prevArrow:'<button class=\"slick-prev\" aria-label=\"Previous\" type=\"button\">Previous</button>',nextArrow:'<button class=\"slick-next\" aria-label=\"Next\" type=\"button\">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:\"50px\",cssEase:\"ease\",customPaging:function(e,t){return i('<button type=\"button\" />').text(t+1)},dots:!1,dotsClass:\"slick-dots\",draggable:!0,easing:\"linear\",edgeFriction:.35,fade:!1,focusOnSelect:!1,focusOnChange:!1,infinite:!0,initialSlide:0,lazyLoad:\"ondemand\",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:\"window\",responsive:null,rows:1,rtl:!1,slide:\"\",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},n.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,scrolling:!1,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,swiping:!1,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},i.extend(n,n.initials),n.activeBreakpoint=null,n.animType=null,n.animProp=null,n.breakpoints=[],n.breakpointSettings=[],n.cssTransitions=!1,n.focussed=!1,n.interrupted=!1,n.hidden=\"hidden\",n.paused=!0,n.positionProp=null,n.respondTo=null,n.rowCount=1,n.shouldClick=!0,n.$slider=i(e),n.$slidesCache=null,n.transformType=null,n.transitionType=null,n.visibilityChange=\"visibilitychange\",n.windowWidth=0,n.windowTimer=null,s=i(e).data(\"slick\")||{},n.options=i.extend({},n.defaults,o,s),n.currentSlide=n.options.initialSlide,n.originalSettings=n.options,\"undefined\"!=typeof document.mozHidden?(n.hidden=\"mozHidden\",n.visibilityChange=\"mozvisibilitychange\"):\"undefined\"!=typeof document.webkitHidden&&(n.hidden=\"webkitHidden\",n.visibilityChange=\"webkitvisibilitychange\"),n.autoPlay=i.proxy(n.autoPlay,n),n.autoPlayClear=i.proxy(n.autoPlayClear,n),n.autoPlayIterator=i.proxy(n.autoPlayIterator,n),n.changeSlide=i.proxy(n.changeSlide,n),n.clickHandler=i.proxy(n.clickHandler,n),n.selectHandler=i.proxy(n.selectHandler,n),n.setPosition=i.proxy(n.setPosition,n),n.swipeHandler=i.proxy(n.swipeHandler,n),n.dragHandler=i.proxy(n.dragHandler,n),n.keyHandler=i.proxy(n.keyHandler,n),n.instanceUid=t++,n.htmlExpr=/^(?:\\s*(<[\\w\\W]+>)[^>]*)$/,n.registerBreakpoints(),n.init(!0)}var t=0;return e}(),e.prototype.activateADA=function(){var i=this;i.$slideTrack.find(\".slick-active\").attr({\"aria-hidden\":\"false\"}).find(\"a, input, button, select\").attr({tabindex:\"0\"})},e.prototype.addSlide=e.prototype.slickAdd=function(e,t,o){var s=this;if(\"boolean\"==typeof t)o=t,t=null;else if(t<0||t>=s.slideCount)return!1;s.unload(),\"number\"==typeof t?0===t&&0===s.$slides.length?i(e).appendTo(s.$slideTrack):o?i(e).insertBefore(s.$slides.eq(t)):i(e).insertAfter(s.$slides.eq(t)):o===!0?i(e).prependTo(s.$slideTrack):i(e).appendTo(s.$slideTrack),s.$slides=s.$slideTrack.children(this.options.slide),s.$slideTrack.children(this.options.slide).detach(),s.$slideTrack.append(s.$slides),s.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e)}),s.$slidesCache=s.$slides,s.reinit()},e.prototype.animateHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.animate({height:e},i.options.speed)}},e.prototype.animateSlide=function(e,t){var o={},s=this;s.animateHeight(),s.options.rtl===!0&&s.options.vertical===!1&&(e=-e),s.transformsEnabled===!1?s.options.vertical===!1?s.$slideTrack.animate({left:e},s.options.speed,s.options.easing,t):s.$slideTrack.animate({top:e},s.options.speed,s.options.easing,t):s.cssTransitions===!1?(s.options.rtl===!0&&(s.currentLeft=-s.currentLeft),i({animStart:s.currentLeft}).animate({animStart:e},{duration:s.options.speed,easing:s.options.easing,step:function(i){i=Math.ceil(i),s.options.vertical===!1?(o[s.animType]=\"translate(\"+i+\"px, 0px)\",s.$slideTrack.css(o)):(o[s.animType]=\"translate(0px,\"+i+\"px)\",s.$slideTrack.css(o))},complete:function(){t&&t.call()}})):(s.applyTransition(),e=Math.ceil(e),s.options.vertical===!1?o[s.animType]=\"translate3d(\"+e+\"px, 0px, 0px)\":o[s.animType]=\"translate3d(0px,\"+e+\"px, 0px)\",s.$slideTrack.css(o),t&&setTimeout(function(){s.disableTransition(),t.call()},s.options.speed))},e.prototype.getNavTarget=function(){var e=this,t=e.options.asNavFor;return t&&null!==t&&(t=i(t).not(e.$slider)),t},e.prototype.asNavFor=function(e){var t=this,o=t.getNavTarget();null!==o&&\"object\"==typeof o&&o.each(function(){var t=i(this).slick(\"getSlick\");t.unslicked||t.slideHandler(e,!0)})},e.prototype.applyTransition=function(i){var e=this,t={};e.options.fade===!1?t[e.transitionType]=e.transformType+\" \"+e.options.speed+\"ms \"+e.options.cssEase:t[e.transitionType]=\"opacity \"+e.options.speed+\"ms \"+e.options.cssEase,e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.autoPlay=function(){var i=this;i.autoPlayClear(),i.slideCount>i.options.slidesToShow&&(i.autoPlayTimer=setInterval(i.autoPlayIterator,i.options.autoplaySpeed))},e.prototype.autoPlayClear=function(){var i=this;i.autoPlayTimer&&clearInterval(i.autoPlayTimer)},e.prototype.autoPlayIterator=function(){var i=this,e=i.currentSlide+i.options.slidesToScroll;i.paused||i.interrupted||i.focussed||(i.options.infinite===!1&&(1===i.direction&&i.currentSlide+1===i.slideCount-1?i.direction=0:0===i.direction&&(e=i.currentSlide-i.options.slidesToScroll,i.currentSlide-1===0&&(i.direction=1))),i.slideHandler(e))},e.prototype.buildArrows=function(){var e=this;e.options.arrows===!0&&(e.$prevArrow=i(e.options.prevArrow).addClass(\"slick-arrow\"),e.$nextArrow=i(e.options.nextArrow).addClass(\"slick-arrow\"),e.slideCount>e.options.slidesToShow?(e.$prevArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.$nextArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.prependTo(e.options.appendArrows),e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.appendTo(e.options.appendArrows),e.options.infinite!==!0&&e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\")):e.$prevArrow.add(e.$nextArrow).addClass(\"slick-hidden\").attr({\"aria-disabled\":\"true\",tabindex:\"-1\"}))},e.prototype.buildDots=function(){var e,t,o=this;if(o.options.dots===!0&&o.slideCount>o.options.slidesToShow){for(o.$slider.addClass(\"slick-dotted\"),t=i(\"<ul />\").addClass(o.options.dotsClass),e=0;e<=o.getDotCount();e+=1)t.append(i(\"<li />\").append(o.options.customPaging.call(this,o,e)));o.$dots=t.appendTo(o.options.appendDots),o.$dots.find(\"li\").first().addClass(\"slick-active\")}},e.prototype.buildOut=function(){var e=this;e.$slides=e.$slider.children(e.options.slide+\":not(.slick-cloned)\").addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e).data(\"originalStyling\",i(t).attr(\"style\")||\"\")}),e.$slider.addClass(\"slick-slider\"),e.$slideTrack=0===e.slideCount?i('<div class=\"slick-track\"/>').appendTo(e.$slider):e.$slides.wrapAll('<div class=\"slick-track\"/>').parent(),e.$list=e.$slideTrack.wrap('<div class=\"slick-list\"/>').parent(),e.$slideTrack.css(\"opacity\",0),e.options.centerMode!==!0&&e.options.swipeToSlide!==!0||(e.options.slidesToScroll=1),i(\"img[data-lazy]\",e.$slider).not(\"[src]\").addClass(\"slick-loading\"),e.setupInfinite(),e.buildArrows(),e.buildDots(),e.updateDots(),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.options.draggable===!0&&e.$list.addClass(\"draggable\")},e.prototype.buildRows=function(){var i,e,t,o,s,n,r,l=this;if(o=document.createDocumentFragment(),n=l.$slider.children(),l.options.rows>0){for(r=l.options.slidesPerRow*l.options.rows,s=Math.ceil(n.length/r),i=0;i<s;i++){var d=document.createElement(\"div\");for(e=0;e<l.options.rows;e++){var a=document.createElement(\"div\");for(t=0;t<l.options.slidesPerRow;t++){var c=i*r+(e*l.options.slidesPerRow+t);n.get(c)&&a.appendChild(n.get(c))}d.appendChild(a)}o.appendChild(d)}l.$slider.empty().append(o),l.$slider.children().children().children().css({width:100/l.options.slidesPerRow+\"%\",display:\"inline-block\"})}},e.prototype.checkResponsive=function(e,t){var o,s,n,r=this,l=!1,d=r.$slider.width(),a=window.innerWidth||i(window).width();if(\"window\"===r.respondTo?n=a:\"slider\"===r.respondTo?n=d:\"min\"===r.respondTo&&(n=Math.min(a,d)),r.options.responsive&&r.options.responsive.length&&null!==r.options.responsive){s=null;for(o in r.breakpoints)r.breakpoints.hasOwnProperty(o)&&(r.originalSettings.mobileFirst===!1?n<r.breakpoints[o]&&(s=r.breakpoints[o]):n>r.breakpoints[o]&&(s=r.breakpoints[o]));null!==s?null!==r.activeBreakpoint?(s!==r.activeBreakpoint||t)&&(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):null!==r.activeBreakpoint&&(r.activeBreakpoint=null,r.options=r.originalSettings,e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e),l=s),e||l===!1||r.$slider.trigger(\"breakpoint\",[r,l])}},e.prototype.changeSlide=function(e,t){var o,s,n,r=this,l=i(e.currentTarget);switch(l.is(\"a\")&&e.preventDefault(),l.is(\"li\")||(l=l.closest(\"li\")),n=r.slideCount%r.options.slidesToScroll!==0,o=n?0:(r.slideCount-r.currentSlide)%r.options.slidesToScroll,e.data.message){case\"previous\":s=0===o?r.options.slidesToScroll:r.options.slidesToShow-o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide-s,!1,t);break;case\"next\":s=0===o?r.options.slidesToScroll:o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide+s,!1,t);break;case\"index\":var d=0===e.data.index?0:e.data.index||l.index()*r.options.slidesToScroll;r.slideHandler(r.checkNavigable(d),!1,t),l.children().trigger(\"focus\");break;default:return}},e.prototype.checkNavigable=function(i){var e,t,o=this;if(e=o.getNavigableIndexes(),t=0,i>e[e.length-1])i=e[e.length-1];else for(var s in e){if(i<e[s]){i=t;break}t=e[s]}return i},e.prototype.cleanUpEvents=function(){var e=this;e.options.dots&&null!==e.$dots&&(i(\"li\",e.$dots).off(\"click.slick\",e.changeSlide).off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)),e.options.accessibility===!0&&e.$dots.off(\"keydown.slick\",e.keyHandler)),e.$slider.off(\"focus.slick blur.slick\"),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&(e.$prevArrow&&e.$prevArrow.off(\"click.slick\",e.changeSlide),e.$nextArrow&&e.$nextArrow.off(\"click.slick\",e.changeSlide),e.options.accessibility===!0&&(e.$prevArrow&&e.$prevArrow.off(\"keydown.slick\",e.keyHandler),e.$nextArrow&&e.$nextArrow.off(\"keydown.slick\",e.keyHandler))),e.$list.off(\"touchstart.slick mousedown.slick\",e.swipeHandler),e.$list.off(\"touchmove.slick mousemove.slick\",e.swipeHandler),e.$list.off(\"touchend.slick mouseup.slick\",e.swipeHandler),e.$list.off(\"touchcancel.slick mouseleave.slick\",e.swipeHandler),e.$list.off(\"click.slick\",e.clickHandler),i(document).off(e.visibilityChange,e.visibility),e.cleanUpSlideEvents(),e.options.accessibility===!0&&e.$list.off(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().off(\"click.slick\",e.selectHandler),i(window).off(\"orientationchange.slick.slick-\"+e.instanceUid,e.orientationChange),i(window).off(\"resize.slick.slick-\"+e.instanceUid,e.resize),i(\"[draggable!=true]\",e.$slideTrack).off(\"dragstart\",e.preventDefault),i(window).off(\"load.slick.slick-\"+e.instanceUid,e.setPosition)},e.prototype.cleanUpSlideEvents=function(){var e=this;e.$list.off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.cleanUpRows=function(){var i,e=this;e.options.rows>0&&(i=e.$slides.children().children(),i.removeAttr(\"style\"),e.$slider.empty().append(i))},e.prototype.clickHandler=function(i){var e=this;e.shouldClick===!1&&(i.stopImmediatePropagation(),i.stopPropagation(),i.preventDefault())},e.prototype.destroy=function(e){var t=this;t.autoPlayClear(),t.touchObject={},t.cleanUpEvents(),i(\".slick-cloned\",t.$slider).detach(),t.$dots&&t.$dots.remove(),t.$prevArrow&&t.$prevArrow.length&&(t.$prevArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.prevArrow)&&t.$prevArrow.remove()),t.$nextArrow&&t.$nextArrow.length&&(t.$nextArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.nextArrow)&&t.$nextArrow.remove()),t.$slides&&(t.$slides.removeClass(\"slick-slide slick-active slick-center slick-visible slick-current\").removeAttr(\"aria-hidden\").removeAttr(\"data-slick-index\").each(function(){i(this).attr(\"style\",i(this).data(\"originalStyling\"))}),t.$slideTrack.children(this.options.slide).detach(),t.$slideTrack.detach(),t.$list.detach(),t.$slider.append(t.$slides)),t.cleanUpRows(),t.$slider.removeClass(\"slick-slider\"),t.$slider.removeClass(\"slick-initialized\"),t.$slider.removeClass(\"slick-dotted\"),t.unslicked=!0,e||t.$slider.trigger(\"destroy\",[t])},e.prototype.disableTransition=function(i){var e=this,t={};t[e.transitionType]=\"\",e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.fadeSlide=function(i,e){var t=this;t.cssTransitions===!1?(t.$slides.eq(i).css({zIndex:t.options.zIndex}),t.$slides.eq(i).animate({opacity:1},t.options.speed,t.options.easing,e)):(t.applyTransition(i),t.$slides.eq(i).css({opacity:1,zIndex:t.options.zIndex}),e&&setTimeout(function(){t.disableTransition(i),e.call()},t.options.speed))},e.prototype.fadeSlideOut=function(i){var e=this;e.cssTransitions===!1?e.$slides.eq(i).animate({opacity:0,zIndex:e.options.zIndex-2},e.options.speed,e.options.easing):(e.applyTransition(i),e.$slides.eq(i).css({opacity:0,zIndex:e.options.zIndex-2}))},e.prototype.filterSlides=e.prototype.slickFilter=function(i){var e=this;null!==i&&(e.$slidesCache=e.$slides,e.unload(),e.$slideTrack.children(this.options.slide).detach(),e.$slidesCache.filter(i).appendTo(e.$slideTrack),e.reinit())},e.prototype.focusHandler=function(){var e=this;e.$slider.off(\"focus.slick blur.slick\").on(\"focus.slick\",\"*\",function(t){var o=i(this);setTimeout(function(){e.options.pauseOnFocus&&o.is(\":focus\")&&(e.focussed=!0,e.autoPlay())},0)}).on(\"blur.slick\",\"*\",function(t){i(this);e.options.pauseOnFocus&&(e.focussed=!1,e.autoPlay())})},e.prototype.getCurrent=e.prototype.slickCurrentSlide=function(){var i=this;return i.currentSlide},e.prototype.getDotCount=function(){var i=this,e=0,t=0,o=0;if(i.options.infinite===!0)if(i.slideCount<=i.options.slidesToShow)++o;else for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else if(i.options.centerMode===!0)o=i.slideCount;else if(i.options.asNavFor)for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else o=1+Math.ceil((i.slideCount-i.options.slidesToShow)/i.options.slidesToScroll);return o-1},e.prototype.getLeft=function(i){var e,t,o,s,n=this,r=0;return n.slideOffset=0,t=n.$slides.first().outerHeight(!0),n.options.infinite===!0?(n.slideCount>n.options.slidesToShow&&(n.slideOffset=n.slideWidth*n.options.slidesToShow*-1,s=-1,n.options.vertical===!0&&n.options.centerMode===!0&&(2===n.options.slidesToShow?s=-1.5:1===n.options.slidesToShow&&(s=-2)),r=t*n.options.slidesToShow*s),n.slideCount%n.options.slidesToScroll!==0&&i+n.options.slidesToScroll>n.slideCount&&n.slideCount>n.options.slidesToShow&&(i>n.slideCount?(n.slideOffset=(n.options.slidesToShow-(i-n.slideCount))*n.slideWidth*-1,r=(n.options.slidesToShow-(i-n.slideCount))*t*-1):(n.slideOffset=n.slideCount%n.options.slidesToScroll*n.slideWidth*-1,r=n.slideCount%n.options.slidesToScroll*t*-1))):i+n.options.slidesToShow>n.slideCount&&(n.slideOffset=(i+n.options.slidesToShow-n.slideCount)*n.slideWidth,r=(i+n.options.slidesToShow-n.slideCount)*t),n.slideCount<=n.options.slidesToShow&&(n.slideOffset=0,r=0),n.options.centerMode===!0&&n.slideCount<=n.options.slidesToShow?n.slideOffset=n.slideWidth*Math.floor(n.options.slidesToShow)/2-n.slideWidth*n.slideCount/2:n.options.centerMode===!0&&n.options.infinite===!0?n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)-n.slideWidth:n.options.centerMode===!0&&(n.slideOffset=0,n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)),e=n.options.vertical===!1?i*n.slideWidth*-1+n.slideOffset:i*t*-1+r,n.options.variableWidth===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,n.options.centerMode===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow+1),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,e+=(n.$list.width()-o.outerWidth())/2)),e},e.prototype.getOption=e.prototype.slickGetOption=function(i){var e=this;return e.options[i]},e.prototype.getNavigableIndexes=function(){var i,e=this,t=0,o=0,s=[];for(e.options.infinite===!1?i=e.slideCount:(t=e.options.slidesToScroll*-1,o=e.options.slidesToScroll*-1,i=2*e.slideCount);t<i;)s.push(t),t=o+e.options.slidesToScroll,o+=e.options.slidesToScroll<=e.options.slidesToShow?e.options.slidesToScroll:e.options.slidesToShow;return s},e.prototype.getSlick=function(){return this},e.prototype.getSlideCount=function(){var e,t,o,s,n=this;return s=n.options.centerMode===!0?Math.floor(n.$list.width()/2):0,o=n.swipeLeft*-1+s,n.options.swipeToSlide===!0?(n.$slideTrack.find(\".slick-slide\").each(function(e,s){var r,l,d;if(r=i(s).outerWidth(),l=s.offsetLeft,n.options.centerMode!==!0&&(l+=r/2),d=l+r,o<d)return t=s,!1}),e=Math.abs(i(t).attr(\"data-slick-index\")-n.currentSlide)||1):n.options.slidesToScroll},e.prototype.goTo=e.prototype.slickGoTo=function(i,e){var t=this;t.changeSlide({data:{message:\"index\",index:parseInt(i)}},e)},e.prototype.init=function(e){var t=this;i(t.$slider).hasClass(\"slick-initialized\")||(i(t.$slider).addClass(\"slick-initialized\"),t.buildRows(),t.buildOut(),t.setProps(),t.startLoad(),t.loadSlider(),t.initializeEvents(),t.updateArrows(),t.updateDots(),t.checkResponsive(!0),t.focusHandler()),e&&t.$slider.trigger(\"init\",[t]),t.options.accessibility===!0&&t.initADA(),t.options.autoplay&&(t.paused=!1,t.autoPlay())},e.prototype.initADA=function(){var e=this,t=Math.ceil(e.slideCount/e.options.slidesToShow),o=e.getNavigableIndexes().filter(function(i){return i>=0&&i<e.slideCount});e.$slides.add(e.$slideTrack.find(\".slick-cloned\")).attr({\"aria-hidden\":\"true\",tabindex:\"-1\"}).find(\"a, input, button, select\").attr({tabindex:\"-1\"}),null!==e.$dots&&(e.$slides.not(e.$slideTrack.find(\".slick-cloned\")).each(function(t){var s=o.indexOf(t);if(i(this).attr({role:\"tabpanel\",id:\"slick-slide\"+e.instanceUid+t,tabindex:-1}),s!==-1){var n=\"slick-slide-control\"+e.instanceUid+s;i(\"#\"+n).length&&i(this).attr({\"aria-describedby\":n})}}),e.$dots.attr(\"role\",\"tablist\").find(\"li\").each(function(s){var n=o[s];i(this).attr({role:\"presentation\"}),i(this).find(\"button\").first().attr({role:\"tab\",id:\"slick-slide-control\"+e.instanceUid+s,\"aria-controls\":\"slick-slide\"+e.instanceUid+n,\"aria-label\":s+1+\" of \"+t,\"aria-selected\":null,tabindex:\"-1\"})}).eq(e.currentSlide).find(\"button\").attr({\"aria-selected\":\"true\",tabindex:\"0\"}).end());for(var s=e.currentSlide,n=s+e.options.slidesToShow;s<n;s++)e.options.focusOnChange?e.$slides.eq(s).attr({tabindex:\"0\"}):e.$slides.eq(s).removeAttr(\"tabindex\");e.activateADA()},e.prototype.initArrowEvents=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.off(\"click.slick\").on(\"click.slick\",{message:\"previous\"},i.changeSlide),i.$nextArrow.off(\"click.slick\").on(\"click.slick\",{message:\"next\"},i.changeSlide),i.options.accessibility===!0&&(i.$prevArrow.on(\"keydown.slick\",i.keyHandler),i.$nextArrow.on(\"keydown.slick\",i.keyHandler)))},e.prototype.initDotEvents=function(){var e=this;e.options.dots===!0&&e.slideCount>e.options.slidesToShow&&(i(\"li\",e.$dots).on(\"click.slick\",{message:\"index\"},e.changeSlide),e.options.accessibility===!0&&e.$dots.on(\"keydown.slick\",e.keyHandler)),e.options.dots===!0&&e.options.pauseOnDotsHover===!0&&e.slideCount>e.options.slidesToShow&&i(\"li\",e.$dots).on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.initSlideEvents=function(){var e=this;e.options.pauseOnHover&&(e.$list.on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)))},e.prototype.initializeEvents=function(){var e=this;e.initArrowEvents(),e.initDotEvents(),e.initSlideEvents(),e.$list.on(\"touchstart.slick mousedown.slick\",{action:\"start\"},e.swipeHandler),e.$list.on(\"touchmove.slick mousemove.slick\",{action:\"move\"},e.swipeHandler),e.$list.on(\"touchend.slick mouseup.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"touchcancel.slick mouseleave.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"click.slick\",e.clickHandler),i(document).on(e.visibilityChange,i.proxy(e.visibility,e)),e.options.accessibility===!0&&e.$list.on(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),i(window).on(\"orientationchange.slick.slick-\"+e.instanceUid,i.proxy(e.orientationChange,e)),i(window).on(\"resize.slick.slick-\"+e.instanceUid,i.proxy(e.resize,e)),i(\"[draggable!=true]\",e.$slideTrack).on(\"dragstart\",e.preventDefault),i(window).on(\"load.slick.slick-\"+e.instanceUid,e.setPosition),i(e.setPosition)},e.prototype.initUI=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.show(),i.$nextArrow.show()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.show()},e.prototype.keyHandler=function(i){var e=this;i.target.tagName.match(\"TEXTAREA|INPUT|SELECT\")||(37===i.keyCode&&e.options.accessibility===!0?e.changeSlide({data:{message:e.options.rtl===!0?\"next\":\"previous\"}}):39===i.keyCode&&e.options.accessibility===!0&&e.changeSlide({data:{message:e.options.rtl===!0?\"previous\":\"next\"}}))},e.prototype.lazyLoad=function(){function e(e){i(\"img[data-lazy]\",e).each(function(){var e=i(this),t=i(this).attr(\"data-lazy\"),o=i(this).attr(\"data-srcset\"),s=i(this).attr(\"data-sizes\")||r.$slider.attr(\"data-sizes\"),n=document.createElement(\"img\");n.onload=function(){e.animate({opacity:0},100,function(){o&&(e.attr(\"srcset\",o),s&&e.attr(\"sizes\",s)),e.attr(\"src\",t).animate({opacity:1},200,function(){e.removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\")}),r.$slider.trigger(\"lazyLoaded\",[r,e,t])})},n.onerror=function(){e.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),r.$slider.trigger(\"lazyLoadError\",[r,e,t])},n.src=t})}var t,o,s,n,r=this;if(r.options.centerMode===!0?r.options.infinite===!0?(s=r.currentSlide+(r.options.slidesToShow/2+1),n=s+r.options.slidesToShow+2):(s=Math.max(0,r.currentSlide-(r.options.slidesToShow/2+1)),n=2+(r.options.slidesToShow/2+1)+r.currentSlide):(s=r.options.infinite?r.options.slidesToShow+r.currentSlide:r.currentSlide,n=Math.ceil(s+r.options.slidesToShow),r.options.fade===!0&&(s>0&&s--,n<=r.slideCount&&n++)),t=r.$slider.find(\".slick-slide\").slice(s,n),\"anticipated\"===r.options.lazyLoad)for(var l=s-1,d=n,a=r.$slider.find(\".slick-slide\"),c=0;c<r.options.slidesToScroll;c++)l<0&&(l=r.slideCount-1),t=t.add(a.eq(l)),t=t.add(a.eq(d)),l--,d++;e(t),r.slideCount<=r.options.slidesToShow?(o=r.$slider.find(\".slick-slide\"),e(o)):r.currentSlide>=r.slideCount-r.options.slidesToShow?(o=r.$slider.find(\".slick-cloned\").slice(0,r.options.slidesToShow),e(o)):0===r.currentSlide&&(o=r.$slider.find(\".slick-cloned\").slice(r.options.slidesToShow*-1),e(o))},e.prototype.loadSlider=function(){var i=this;i.setPosition(),i.$slideTrack.css({opacity:1}),i.$slider.removeClass(\"slick-loading\"),i.initUI(),\"progressive\"===i.options.lazyLoad&&i.progressiveLazyLoad()},e.prototype.next=e.prototype.slickNext=function(){var i=this;i.changeSlide({data:{message:\"next\"}})},e.prototype.orientationChange=function(){var i=this;i.checkResponsive(),i.setPosition()},e.prototype.pause=e.prototype.slickPause=function(){var i=this;i.autoPlayClear(),i.paused=!0},e.prototype.play=e.prototype.slickPlay=function(){var i=this;i.autoPlay(),i.options.autoplay=!0,i.paused=!1,i.focussed=!1,i.interrupted=!1},e.prototype.postSlide=function(e){var t=this;if(!t.unslicked&&(t.$slider.trigger(\"afterChange\",[t,e]),t.animating=!1,t.slideCount>t.options.slidesToShow&&t.setPosition(),t.swipeLeft=null,t.options.autoplay&&t.autoPlay(),t.options.accessibility===!0&&(t.initADA(),t.options.focusOnChange))){var o=i(t.$slides.get(t.currentSlide));o.attr(\"tabindex\",0).focus()}},e.prototype.prev=e.prototype.slickPrev=function(){var i=this;i.changeSlide({data:{message:\"previous\"}})},e.prototype.preventDefault=function(i){i.preventDefault()},e.prototype.progressiveLazyLoad=function(e){e=e||1;var t,o,s,n,r,l=this,d=i(\"img[data-lazy]\",l.$slider);d.length?(t=d.first(),o=t.attr(\"data-lazy\"),s=t.attr(\"data-srcset\"),n=t.attr(\"data-sizes\")||l.$slider.attr(\"data-sizes\"),r=document.createElement(\"img\"),r.onload=function(){s&&(t.attr(\"srcset\",s),n&&t.attr(\"sizes\",n)),t.attr(\"src\",o).removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\"),l.options.adaptiveHeight===!0&&l.setPosition(),l.$slider.trigger(\"lazyLoaded\",[l,t,o]),l.progressiveLazyLoad()},r.onerror=function(){e<3?setTimeout(function(){l.progressiveLazyLoad(e+1)},500):(t.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),l.$slider.trigger(\"lazyLoadError\",[l,t,o]),l.progressiveLazyLoad())},r.src=o):l.$slider.trigger(\"allImagesLoaded\",[l])},e.prototype.refresh=function(e){var t,o,s=this;o=s.slideCount-s.options.slidesToShow,!s.options.infinite&&s.currentSlide>o&&(s.currentSlide=o),s.slideCount<=s.options.slidesToShow&&(s.currentSlide=0),t=s.currentSlide,s.destroy(!0),i.extend(s,s.initials,{currentSlide:t}),s.init(),e||s.changeSlide({data:{message:\"index\",index:t}},!1)},e.prototype.registerBreakpoints=function(){var e,t,o,s=this,n=s.options.responsive||null;if(\"array\"===i.type(n)&&n.length){s.respondTo=s.options.respondTo||\"window\";for(e in n)if(o=s.breakpoints.length-1,n.hasOwnProperty(e)){for(t=n[e].breakpoint;o>=0;)s.breakpoints[o]&&s.breakpoints[o]===t&&s.breakpoints.splice(o,1),o--;s.breakpoints.push(t),s.breakpointSettings[t]=n[e].settings}s.breakpoints.sort(function(i,e){return s.options.mobileFirst?i-e:e-i})}},e.prototype.reinit=function(){var e=this;e.$slides=e.$slideTrack.children(e.options.slide).addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.currentSlide>=e.slideCount&&0!==e.currentSlide&&(e.currentSlide=e.currentSlide-e.options.slidesToScroll),e.slideCount<=e.options.slidesToShow&&(e.currentSlide=0),e.registerBreakpoints(),e.setProps(),e.setupInfinite(),e.buildArrows(),e.updateArrows(),e.initArrowEvents(),e.buildDots(),e.updateDots(),e.initDotEvents(),e.cleanUpSlideEvents(),e.initSlideEvents(),e.checkResponsive(!1,!0),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.setPosition(),e.focusHandler(),e.paused=!e.options.autoplay,e.autoPlay(),e.$slider.trigger(\"reInit\",[e])},e.prototype.resize=function(){var e=this;i(window).width()!==e.windowWidth&&(clearTimeout(e.windowDelay),e.windowDelay=window.setTimeout(function(){e.windowWidth=i(window).width(),e.checkResponsive(),e.unslicked||e.setPosition()},50))},e.prototype.removeSlide=e.prototype.slickRemove=function(i,e,t){var o=this;return\"boolean\"==typeof i?(e=i,i=e===!0?0:o.slideCount-1):i=e===!0?--i:i,!(o.slideCount<1||i<0||i>o.slideCount-1)&&(o.unload(),t===!0?o.$slideTrack.children().remove():o.$slideTrack.children(this.options.slide).eq(i).remove(),o.$slides=o.$slideTrack.children(this.options.slide),o.$slideTrack.children(this.options.slide).detach(),o.$slideTrack.append(o.$slides),o.$slidesCache=o.$slides,void o.reinit())},e.prototype.setCSS=function(i){var e,t,o=this,s={};o.options.rtl===!0&&(i=-i),e=\"left\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",t=\"top\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",s[o.positionProp]=i,o.transformsEnabled===!1?o.$slideTrack.css(s):(s={},o.cssTransitions===!1?(s[o.animType]=\"translate(\"+e+\", \"+t+\")\",o.$slideTrack.css(s)):(s[o.animType]=\"translate3d(\"+e+\", \"+t+\", 0px)\",o.$slideTrack.css(s)))},e.prototype.setDimensions=function(){var i=this;i.options.vertical===!1?i.options.centerMode===!0&&i.$list.css({padding:\"0px \"+i.options.centerPadding}):(i.$list.height(i.$slides.first().outerHeight(!0)*i.options.slidesToShow),i.options.centerMode===!0&&i.$list.css({padding:i.options.centerPadding+\" 0px\"})),i.listWidth=i.$list.width(),i.listHeight=i.$list.height(),i.options.vertical===!1&&i.options.variableWidth===!1?(i.slideWidth=Math.ceil(i.listWidth/i.options.slidesToShow),i.$slideTrack.width(Math.ceil(i.slideWidth*i.$slideTrack.children(\".slick-slide\").length))):i.options.variableWidth===!0?i.$slideTrack.width(5e3*i.slideCount):(i.slideWidth=Math.ceil(i.listWidth),i.$slideTrack.height(Math.ceil(i.$slides.first().outerHeight(!0)*i.$slideTrack.children(\".slick-slide\").length)));var e=i.$slides.first().outerWidth(!0)-i.$slides.first().width();i.options.variableWidth===!1&&i.$slideTrack.children(\".slick-slide\").width(i.slideWidth-e)},e.prototype.setFade=function(){var e,t=this;t.$slides.each(function(o,s){e=t.slideWidth*o*-1,t.options.rtl===!0?i(s).css({position:\"relative\",right:e,top:0,zIndex:t.options.zIndex-2,opacity:0}):i(s).css({position:\"relative\",left:e,top:0,zIndex:t.options.zIndex-2,opacity:0})}),t.$slides.eq(t.currentSlide).css({zIndex:t.options.zIndex-1,opacity:1})},e.prototype.setHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.css(\"height\",e)}},e.prototype.setOption=e.prototype.slickSetOption=function(){var e,t,o,s,n,r=this,l=!1;if(\"object\"===i.type(arguments[0])?(o=arguments[0],l=arguments[1],n=\"multiple\"):\"string\"===i.type(arguments[0])&&(o=arguments[0],s=arguments[1],l=arguments[2],\"responsive\"===arguments[0]&&\"array\"===i.type(arguments[1])?n=\"responsive\":\"undefined\"!=typeof arguments[1]&&(n=\"single\")),\"single\"===n)r.options[o]=s;else if(\"multiple\"===n)i.each(o,function(i,e){r.options[i]=e});else if(\"responsive\"===n)for(t in s)if(\"array\"!==i.type(r.options.responsive))r.options.responsive=[s[t]];else{for(e=r.options.responsive.length-1;e>=0;)r.options.responsive[e].breakpoint===s[t].breakpoint&&r.options.responsive.splice(e,1),e--;r.options.responsive.push(s[t])}l&&(r.unload(),r.reinit())},e.prototype.setPosition=function(){var i=this;i.setDimensions(),i.setHeight(),i.options.fade===!1?i.setCSS(i.getLeft(i.currentSlide)):i.setFade(),i.$slider.trigger(\"setPosition\",[i])},e.prototype.setProps=function(){var i=this,e=document.body.style;i.positionProp=i.options.vertical===!0?\"top\":\"left\",\n\"top\"===i.positionProp?i.$slider.addClass(\"slick-vertical\"):i.$slider.removeClass(\"slick-vertical\"),void 0===e.WebkitTransition&&void 0===e.MozTransition&&void 0===e.msTransition||i.options.useCSS===!0&&(i.cssTransitions=!0),i.options.fade&&(\"number\"==typeof i.options.zIndex?i.options.zIndex<3&&(i.options.zIndex=3):i.options.zIndex=i.defaults.zIndex),void 0!==e.OTransform&&(i.animType=\"OTransform\",i.transformType=\"-o-transform\",i.transitionType=\"OTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.MozTransform&&(i.animType=\"MozTransform\",i.transformType=\"-moz-transform\",i.transitionType=\"MozTransition\",void 0===e.perspectiveProperty&&void 0===e.MozPerspective&&(i.animType=!1)),void 0!==e.webkitTransform&&(i.animType=\"webkitTransform\",i.transformType=\"-webkit-transform\",i.transitionType=\"webkitTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.msTransform&&(i.animType=\"msTransform\",i.transformType=\"-ms-transform\",i.transitionType=\"msTransition\",void 0===e.msTransform&&(i.animType=!1)),void 0!==e.transform&&i.animType!==!1&&(i.animType=\"transform\",i.transformType=\"transform\",i.transitionType=\"transition\"),i.transformsEnabled=i.options.useTransform&&null!==i.animType&&i.animType!==!1},e.prototype.setSlideClasses=function(i){var e,t,o,s,n=this;if(t=n.$slider.find(\".slick-slide\").removeClass(\"slick-active slick-center slick-current\").attr(\"aria-hidden\",\"true\"),n.$slides.eq(i).addClass(\"slick-current\"),n.options.centerMode===!0){var r=n.options.slidesToShow%2===0?1:0;e=Math.floor(n.options.slidesToShow/2),n.options.infinite===!0&&(i>=e&&i<=n.slideCount-1-e?n.$slides.slice(i-e+r,i+e+1).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(o=n.options.slidesToShow+i,t.slice(o-e+1+r,o+e+2).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\")),0===i?t.eq(t.length-1-n.options.slidesToShow).addClass(\"slick-center\"):i===n.slideCount-1&&t.eq(n.options.slidesToShow).addClass(\"slick-center\")),n.$slides.eq(i).addClass(\"slick-center\")}else i>=0&&i<=n.slideCount-n.options.slidesToShow?n.$slides.slice(i,i+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.length<=n.options.slidesToShow?t.addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(s=n.slideCount%n.options.slidesToShow,o=n.options.infinite===!0?n.options.slidesToShow+i:i,n.options.slidesToShow==n.options.slidesToScroll&&n.slideCount-i<n.options.slidesToShow?t.slice(o-(n.options.slidesToShow-s),o+s).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.slice(o,o+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"));\"ondemand\"!==n.options.lazyLoad&&\"anticipated\"!==n.options.lazyLoad||n.lazyLoad()},e.prototype.setupInfinite=function(){var e,t,o,s=this;if(s.options.fade===!0&&(s.options.centerMode=!1),s.options.infinite===!0&&s.options.fade===!1&&(t=null,s.slideCount>s.options.slidesToShow)){for(o=s.options.centerMode===!0?s.options.slidesToShow+1:s.options.slidesToShow,e=s.slideCount;e>s.slideCount-o;e-=1)t=e-1,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t-s.slideCount).prependTo(s.$slideTrack).addClass(\"slick-cloned\");for(e=0;e<o+s.slideCount;e+=1)t=e,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t+s.slideCount).appendTo(s.$slideTrack).addClass(\"slick-cloned\");s.$slideTrack.find(\".slick-cloned\").find(\"[id]\").each(function(){i(this).attr(\"id\",\"\")})}},e.prototype.interrupt=function(i){var e=this;i||e.autoPlay(),e.interrupted=i},e.prototype.selectHandler=function(e){var t=this,o=i(e.target).is(\".slick-slide\")?i(e.target):i(e.target).parents(\".slick-slide\"),s=parseInt(o.attr(\"data-slick-index\"));return s||(s=0),t.slideCount<=t.options.slidesToShow?void t.slideHandler(s,!1,!0):void t.slideHandler(s)},e.prototype.slideHandler=function(i,e,t){var o,s,n,r,l,d=null,a=this;if(e=e||!1,!(a.animating===!0&&a.options.waitForAnimate===!0||a.options.fade===!0&&a.currentSlide===i))return e===!1&&a.asNavFor(i),o=i,d=a.getLeft(o),r=a.getLeft(a.currentSlide),a.currentLeft=null===a.swipeLeft?r:a.swipeLeft,a.options.infinite===!1&&a.options.centerMode===!1&&(i<0||i>a.getDotCount()*a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):a.options.infinite===!1&&a.options.centerMode===!0&&(i<0||i>a.slideCount-a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):(a.options.autoplay&&clearInterval(a.autoPlayTimer),s=o<0?a.slideCount%a.options.slidesToScroll!==0?a.slideCount-a.slideCount%a.options.slidesToScroll:a.slideCount+o:o>=a.slideCount?a.slideCount%a.options.slidesToScroll!==0?0:o-a.slideCount:o,a.animating=!0,a.$slider.trigger(\"beforeChange\",[a,a.currentSlide,s]),n=a.currentSlide,a.currentSlide=s,a.setSlideClasses(a.currentSlide),a.options.asNavFor&&(l=a.getNavTarget(),l=l.slick(\"getSlick\"),l.slideCount<=l.options.slidesToShow&&l.setSlideClasses(a.currentSlide)),a.updateDots(),a.updateArrows(),a.options.fade===!0?(t!==!0?(a.fadeSlideOut(n),a.fadeSlide(s,function(){a.postSlide(s)})):a.postSlide(s),void a.animateHeight()):void(t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(d,function(){a.postSlide(s)}):a.postSlide(s)))},e.prototype.startLoad=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.hide(),i.$nextArrow.hide()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.hide(),i.$slider.addClass(\"slick-loading\")},e.prototype.swipeDirection=function(){var i,e,t,o,s=this;return i=s.touchObject.startX-s.touchObject.curX,e=s.touchObject.startY-s.touchObject.curY,t=Math.atan2(e,i),o=Math.round(180*t/Math.PI),o<0&&(o=360-Math.abs(o)),o<=45&&o>=0?s.options.rtl===!1?\"left\":\"right\":o<=360&&o>=315?s.options.rtl===!1?\"left\":\"right\":o>=135&&o<=225?s.options.rtl===!1?\"right\":\"left\":s.options.verticalSwiping===!0?o>=35&&o<=135?\"down\":\"up\":\"vertical\"},e.prototype.swipeEnd=function(i){var e,t,o=this;if(o.dragging=!1,o.swiping=!1,o.scrolling)return o.scrolling=!1,!1;if(o.interrupted=!1,o.shouldClick=!(o.touchObject.swipeLength>10),void 0===o.touchObject.curX)return!1;if(o.touchObject.edgeHit===!0&&o.$slider.trigger(\"edge\",[o,o.swipeDirection()]),o.touchObject.swipeLength>=o.touchObject.minSwipe){switch(t=o.swipeDirection()){case\"left\":case\"down\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide+o.getSlideCount()):o.currentSlide+o.getSlideCount(),o.currentDirection=0;break;case\"right\":case\"up\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide-o.getSlideCount()):o.currentSlide-o.getSlideCount(),o.currentDirection=1}\"vertical\"!=t&&(o.slideHandler(e),o.touchObject={},o.$slider.trigger(\"swipe\",[o,t]))}else o.touchObject.startX!==o.touchObject.curX&&(o.slideHandler(o.currentSlide),o.touchObject={})},e.prototype.swipeHandler=function(i){var e=this;if(!(e.options.swipe===!1||\"ontouchend\"in document&&e.options.swipe===!1||e.options.draggable===!1&&i.type.indexOf(\"mouse\")!==-1))switch(e.touchObject.fingerCount=i.originalEvent&&void 0!==i.originalEvent.touches?i.originalEvent.touches.length:1,e.touchObject.minSwipe=e.listWidth/e.options.touchThreshold,e.options.verticalSwiping===!0&&(e.touchObject.minSwipe=e.listHeight/e.options.touchThreshold),i.data.action){case\"start\":e.swipeStart(i);break;case\"move\":e.swipeMove(i);break;case\"end\":e.swipeEnd(i)}},e.prototype.swipeMove=function(i){var e,t,o,s,n,r,l=this;return n=void 0!==i.originalEvent?i.originalEvent.touches:null,!(!l.dragging||l.scrolling||n&&1!==n.length)&&(e=l.getLeft(l.currentSlide),l.touchObject.curX=void 0!==n?n[0].pageX:i.clientX,l.touchObject.curY=void 0!==n?n[0].pageY:i.clientY,l.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(l.touchObject.curX-l.touchObject.startX,2))),r=Math.round(Math.sqrt(Math.pow(l.touchObject.curY-l.touchObject.startY,2))),!l.options.verticalSwiping&&!l.swiping&&r>4?(l.scrolling=!0,!1):(l.options.verticalSwiping===!0&&(l.touchObject.swipeLength=r),t=l.swipeDirection(),void 0!==i.originalEvent&&l.touchObject.swipeLength>4&&(l.swiping=!0,i.preventDefault()),s=(l.options.rtl===!1?1:-1)*(l.touchObject.curX>l.touchObject.startX?1:-1),l.options.verticalSwiping===!0&&(s=l.touchObject.curY>l.touchObject.startY?1:-1),o=l.touchObject.swipeLength,l.touchObject.edgeHit=!1,l.options.infinite===!1&&(0===l.currentSlide&&\"right\"===t||l.currentSlide>=l.getDotCount()&&\"left\"===t)&&(o=l.touchObject.swipeLength*l.options.edgeFriction,l.touchObject.edgeHit=!0),l.options.vertical===!1?l.swipeLeft=e+o*s:l.swipeLeft=e+o*(l.$list.height()/l.listWidth)*s,l.options.verticalSwiping===!0&&(l.swipeLeft=e+o*s),l.options.fade!==!0&&l.options.touchMove!==!1&&(l.animating===!0?(l.swipeLeft=null,!1):void l.setCSS(l.swipeLeft))))},e.prototype.swipeStart=function(i){var e,t=this;return t.interrupted=!0,1!==t.touchObject.fingerCount||t.slideCount<=t.options.slidesToShow?(t.touchObject={},!1):(void 0!==i.originalEvent&&void 0!==i.originalEvent.touches&&(e=i.originalEvent.touches[0]),t.touchObject.startX=t.touchObject.curX=void 0!==e?e.pageX:i.clientX,t.touchObject.startY=t.touchObject.curY=void 0!==e?e.pageY:i.clientY,void(t.dragging=!0))},e.prototype.unfilterSlides=e.prototype.slickUnfilter=function(){var i=this;null!==i.$slidesCache&&(i.unload(),i.$slideTrack.children(this.options.slide).detach(),i.$slidesCache.appendTo(i.$slideTrack),i.reinit())},e.prototype.unload=function(){var e=this;i(\".slick-cloned\",e.$slider).remove(),e.$dots&&e.$dots.remove(),e.$prevArrow&&e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.remove(),e.$nextArrow&&e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.remove(),e.$slides.removeClass(\"slick-slide slick-active slick-visible slick-current\").attr(\"aria-hidden\",\"true\").css(\"width\",\"\")},e.prototype.unslick=function(i){var e=this;e.$slider.trigger(\"unslick\",[e,i]),e.destroy()},e.prototype.updateArrows=function(){var i,e=this;i=Math.floor(e.options.slidesToShow/2),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&!e.options.infinite&&(e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),0===e.currentSlide?(e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-e.options.slidesToShow&&e.options.centerMode===!1?(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-1&&e.options.centerMode===!0&&(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")))},e.prototype.updateDots=function(){var i=this;null!==i.$dots&&(i.$dots.find(\"li\").removeClass(\"slick-active\").end(),i.$dots.find(\"li\").eq(Math.floor(i.currentSlide/i.options.slidesToScroll)).addClass(\"slick-active\"))},e.prototype.visibility=function(){var i=this;i.options.autoplay&&(document[i.hidden]?i.interrupted=!0:i.interrupted=!1)},i.fn.slick=function(){var i,t,o=this,s=arguments[0],n=Array.prototype.slice.call(arguments,1),r=o.length;for(i=0;i<r;i++)if(\"object\"==typeof s||\"undefined\"==typeof s?o[i].slick=new e(o[i],s):t=o[i].slick[s].apply(o[i].slick,n),\"undefined\"!=typeof t)return t;return o}});\n","Magento_PageBuilder/js/utils/breakpoints.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore'\n], function (_) {\n 'use strict';\n\n return {\n /**\n * Build media query.\n *\n * @param {Object} conditions\n * @returns {String}\n */\n buildMedia: function (conditions) {\n var result = _.map(_.pairs(conditions), function (condition) {\n return '(' + condition.join(': ') + ')';\n });\n\n return result.join(' and ');\n }\n };\n});\n","Magento_PageBuilder/js/utils/map.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * googleMaps dependency is added within googlemaps.phtml through shim based on API key being set\n *\n * @api\n */\ndefine([\n 'underscore',\n 'module',\n 'Magento_PageBuilder/js/events'\n], function (_, module, events) {\n 'use strict';\n\n var google = window.google || {},\n\n /**\n * Generates a google map usable latitude and longitude object\n *\n * @param {Object} position\n * @return {google.maps.LatLng}\n */\n getGoogleLatitudeLongitude = function (position) {\n return new google.maps.LatLng(position.latitude, position.longitude);\n },\n gmAuthFailure = false;\n\n // jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n /**\n * Google's error listener for map loader failures\n */\n window.gm_authFailure = function () {\n events.trigger('googleMaps:authFailure');\n gmAuthFailure = true;\n };\n // jscs:enable requireCamelCaseOrUpperCaseIdentifiers\n\n return function (element, markers, additionalOptions) {\n var options,\n style;\n\n // If we've previously had an API key error, throw the error even again\n if (gmAuthFailure) {\n events.trigger('googleMaps:authFailure');\n\n return;\n }\n\n // If Google Maps isn't loaded don't try init the map, it won't work\n if (typeof google.maps === 'undefined') {\n return;\n }\n\n /**\n * Just in case of a bad JSON that bypassed validation\n */\n try {\n style = module.config().style ? JSON.parse(module.config().style) : [];\n }\n catch (error) {\n style = [];\n }\n options = _.extend({\n zoom: 8,\n center: getGoogleLatitudeLongitude({\n latitude: 30.2672,\n longitude: -97.7431\n }),\n scrollwheel: false,\n disableDoubleClickZoom: false,\n disableDefaultUI: false,\n mapTypeControl: true,\n mapTypeControlOptions: {\n style: google.maps.MapTypeControlStyle.DEFAULT\n },\n styles: style\n }, additionalOptions);\n\n /* Create the map */\n this.map = new google.maps.Map(element, options);\n this.markers = [];\n\n /**\n * Callback function on map config update\n * @param {Array} newMarkers\n * @param {Object} updateOptions\n */\n this.onUpdate = function (newMarkers, updateOptions) {\n this.map.setOptions(updateOptions);\n this.setMarkers(newMarkers);\n };\n\n /**\n * Sets the markers to selected map\n * @param {Object} newMarkers\n */\n this.setMarkers = function (newMarkers) {\n var activeInfoWindow,\n latitudeLongitudeBounds = new google.maps.LatLngBounds();\n\n this.markers.forEach(function (marker) {\n marker.setMap(null);\n }, this);\n\n this.markers = [];\n this.bounds = [];\n\n /**\n * Creates and set listener for markers\n */\n if (newMarkers && newMarkers.length) {\n newMarkers.forEach(function (newMarker) {\n var location = _.escape(newMarker['location_name']) || '',\n comment = newMarker.comment ?\n '<p>' + _.escape(newMarker.comment).replace(/(?:\\r\\n|\\r|\\n)/g, '<br/>') + '</p>'\n : '',\n phone = newMarker.phone ? '<p>Phone: ' + _.escape(newMarker.phone) + '</p>' : '',\n address = newMarker.address ? _.escape(newMarker.address) + '<br/>' : '',\n city = _.escape(newMarker.city) || '',\n country = newMarker.country ? _.escape(newMarker.country) : '',\n state = newMarker.state ? _.escape(newMarker.state) + ' ' : '',\n zipCode = newMarker.zipcode ? _.escape(newMarker.zipcode) : '',\n cityComma = city !== '' && (zipCode !== '' || state !== '') ? ', ' : '',\n lineBreak = city !== '' || zipCode !== '' ? '<br/>' : '',\n contentString =\n '<div>' +\n '<h3><b>' + location + '</b></h3>' +\n comment +\n phone +\n '<p><span>' + address +\n city + cityComma + state + zipCode + lineBreak +\n country + '</span></p>' +\n '</div>',\n infowindow = new google.maps.InfoWindow({\n content: contentString,\n maxWidth: 350\n }),\n newCreatedMarker = new google.maps.Marker({\n map: this.map,\n position: getGoogleLatitudeLongitude(newMarker.position),\n title: location\n });\n\n if (location) {\n newCreatedMarker.addListener('click', function () {\n if (activeInfoWindow) {\n activeInfoWindow.close();\n }\n\n infowindow.open(this.map, newCreatedMarker);\n activeInfoWindow = infowindow;\n }, this);\n }\n\n this.markers.push(newCreatedMarker);\n this.bounds.push(getGoogleLatitudeLongitude(newMarker.position));\n }, this);\n }\n\n /**\n * This sets the bounds of the map for multiple locations\n */\n if (this.bounds.length > 1) {\n this.bounds.forEach(function (bound) {\n latitudeLongitudeBounds.extend(bound);\n });\n this.map.fitBounds(latitudeLongitudeBounds);\n }\n\n /**\n * Zoom to 8 if there is only a single location\n */\n if (this.bounds.length === 1) {\n this.map.setCenter(this.bounds[0]);\n this.map.setZoom(8);\n }\n };\n\n this.setMarkers(markers);\n };\n});\n","Magento_SalesRule/js/form/element/manage-coupon-codes.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'uiRegistry',\n 'Magento_Ui/js/form/components/fieldset',\n 'Magento_Ui/js/lib/view/utils/async'\n], function (_, uiRegistry, fieldset, async) {\n 'use strict';\n\n return fieldset.extend({\n\n /*eslint-disable no-unused-vars*/\n /**\n * Initialize element\n *\n * @returns {Abstract} Chainable\n */\n initialize: function (elems, position) {\n var obj = this;\n\n this._super();\n\n async.async('#sales-rule-form-tab-coupons', document.getElementById('container'), function (node) {\n var useAutoGeneration = uiRegistry.get(\n 'sales_rule_form.sales_rule_form.rule_information.use_auto_generation'\n );\n\n useAutoGeneration.on('checked', function () {\n obj.enableDisableFields();\n });\n obj.enableDisableFields();\n });\n\n return this;\n },\n\n /*eslint-enable no-unused-vars*/\n /*eslint-disable lines-around-comment*/\n\n /**\n * Enable/disable fields on Coupons tab\n */\n enableDisableFields: function () {\n var selector,\n isUseAutoGenerationChecked,\n couponType,\n disableAuto;\n\n selector = '[id=sales-rule-form-tab-coupons] input, [id=sales-rule-form-tab-coupons] select, ' +\n '[id=sales-rule-form-tab-coupons] button';\n isUseAutoGenerationChecked = uiRegistry\n .get('sales_rule_form.sales_rule_form.rule_information.use_auto_generation')\n .checked();\n couponType = uiRegistry\n .get('sales_rule_form.sales_rule_form.rule_information.coupon_type')\n .value();\n /**\n * \\Magento\\Rule\\Model\\AbstractModel::COUPON_TYPE_AUTO\n */\n disableAuto = couponType === 3 || isUseAutoGenerationChecked;\n _.each(\n document.querySelectorAll(selector),\n function (element) {\n element.disabled = !disableAuto;\n }\n );\n }\n });\n});\n","Magento_SalesRule/js/form/element/coupon-type.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'uiRegistry',\n 'Magento_Ui/js/form/element/select'\n], function (_, uiRegistry, select) {\n 'use strict';\n\n return select.extend({\n\n /**\n * Hide fields on coupon tab\n */\n onUpdate: function () {\n\n /* eslint-disable eqeqeq */\n if (this.value() != this.displayOnlyForCouponType) {\n uiRegistry.get('sales_rule_form.sales_rule_form.rule_information.use_auto_generation').checked(false);\n }\n\n this.enableDisableFields();\n },\n\n /**\n * Enable/disable fields on Coupons tab\n */\n enableDisableFields: function () {\n var selector,\n isUseAutoGenerationChecked,\n couponType,\n disableAuto;\n\n selector = '[id=sales-rule-form-tab-coupons] input, [id=sales-rule-form-tab-coupons] select, ' +\n '[id=sales-rule-form-tab-coupons] button';\n isUseAutoGenerationChecked = uiRegistry\n .get('sales_rule_form.sales_rule_form.rule_information.use_auto_generation')\n .checked();\n couponType = uiRegistry\n .get('sales_rule_form.sales_rule_form.rule_information.coupon_type')\n .value();\n disableAuto = couponType === 3 || isUseAutoGenerationChecked;\n _.each(\n document.querySelectorAll(selector),\n function (element) {\n element.disabled = !disableAuto;\n }\n );\n }\n });\n});\n","Magento_SalesRule/js/view/cart/totals/discount.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_SalesRule/js/view/summary/discount'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_SalesRule/cart/totals/discount'\n },\n\n /**\n * @override\n *\n * @returns {Boolean}\n */\n isDisplayed: function () {\n return this.getPureValue() != 0; //eslint-disable-line eqeqeq\n }\n });\n});\n","Magento_SalesRule/js/view/payment/discount-messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Ui/js/view/messages',\n '../../model/payment/discount-messages'\n], function (Component, messageContainer) {\n 'use strict';\n\n return Component.extend({\n /** @inheritdoc */\n initialize: function (config) {\n return this._super(config, messageContainer);\n }\n });\n});\n","Magento_SalesRule/js/view/payment/captcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Captcha/js/view/checkout/defaultCaptcha',\n 'Magento_Captcha/js/model/captchaList',\n 'Magento_SalesRule/js/action/set-coupon-code',\n 'Magento_SalesRule/js/action/cancel-coupon',\n 'Magento_Checkout/js/model/quote',\n 'ko'\n ],\n function (defaultCaptcha, captchaList, setCouponCodeAction, cancelCouponAction, quote, ko) {\n 'use strict';\n\n var totals = quote.getTotals(),\n couponCode = ko.observable(null),\n isApplied;\n\n if (totals()) {\n couponCode(totals()['coupon_code']);\n }\n //Captcha can only be required for adding a coupon so we need to know if one was added already.\n isApplied = ko.observable(couponCode() != null);\n\n return defaultCaptcha.extend({\n /** @inheritdoc */\n initialize: function () {\n var self = this,\n currentCaptcha;\n\n this._super();\n //Getting coupon captcha model.\n currentCaptcha = captchaList.getCaptchaByFormId(this.formId);\n\n if (currentCaptcha != null) {\n if (!isApplied()) {\n //Show captcha if we don't have a coupon applied.\n currentCaptcha.setIsVisible(true);\n }\n this.setCurrentCaptcha(currentCaptcha);\n //Add captcha code to coupon-apply request.\n setCouponCodeAction.registerDataModifier(function (headers) {\n if (self.isRequired()) {\n headers['X-Captcha'] = self.captchaValue()();\n }\n });\n //Refresh captcha after failed request.\n setCouponCodeAction.registerFailCallback(function () {\n if (self.isRequired()) {\n self.refresh();\n }\n });\n //Hide captcha when a coupon has been applied.\n setCouponCodeAction.registerSuccessCallback(function () {\n self.setIsVisible(false);\n });\n //Show captcha again if it was canceled.\n cancelCouponAction.registerSuccessCallback(function () {\n if (self.isRequired()) {\n self.setIsVisible(true);\n }\n });\n }\n }\n });\n });\n","Magento_SalesRule/js/view/payment/discount.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko',\n 'uiComponent',\n 'Magento_Checkout/js/model/quote',\n 'Magento_SalesRule/js/action/set-coupon-code',\n 'Magento_SalesRule/js/action/cancel-coupon',\n 'Magento_SalesRule/js/model/coupon'\n], function ($, ko, Component, quote, setCouponCodeAction, cancelCouponAction, coupon) {\n 'use strict';\n\n var totals = quote.getTotals(),\n couponCode = coupon.getCouponCode(),\n isApplied = coupon.getIsApplied();\n\n if (totals()) {\n couponCode(totals()['coupon_code']);\n }\n isApplied(couponCode() != null);\n\n return Component.extend({\n defaults: {\n template: 'Magento_SalesRule/payment/discount'\n },\n couponCode: couponCode,\n\n /**\n * Applied flag\n */\n isApplied: isApplied,\n\n /**\n * Coupon code application procedure\n */\n apply: function () {\n if (this.validate()) {\n setCouponCodeAction(couponCode(), isApplied);\n }\n },\n\n /**\n * Cancel using coupon\n */\n cancel: function () {\n if (this.validate()) {\n couponCode('');\n cancelCouponAction(isApplied);\n }\n },\n\n /**\n * Coupon form validation\n *\n * @returns {Boolean}\n */\n validate: function () {\n var form = '#discount-form';\n\n return $(form).validation() && $(form).validation('isValid');\n }\n });\n});\n","Magento_SalesRule/js/view/summary/discount.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\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 return Component.extend({\n defaults: {\n template: 'Magento_SalesRule/summary/discount'\n },\n totals: quote.getTotals(),\n\n /**\n * @return {*|Boolean}\n */\n isDisplayed: function () {\n return this.isFullMode() && this.getPureValue() != 0; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {*}\n */\n getCouponCode: function () {\n if (!this.totals()) {\n return null;\n }\n\n return this.totals()['coupon_code'];\n },\n\n /**\n * @return {*}\n */\n getCouponLabel: function () {\n if (!this.totals()) {\n return null;\n }\n\n return this.totals()['coupon_label'];\n },\n\n /**\n * Get discount title\n *\n * @returns {null|String}\n */\n getTitle: function () {\n var discountSegments;\n\n if (!this.totals()) {\n return null;\n }\n\n discountSegments = this.totals()['total_segments'].filter(function (segment) {\n return segment.code.indexOf('discount') !== -1;\n });\n\n return discountSegments.length ? discountSegments[0].title : null;\n },\n\n /**\n * @return {Number}\n */\n getPureValue: function () {\n var price = 0;\n\n if (this.totals() && this.totals()['discount_amount']) {\n price = parseFloat(this.totals()['discount_amount']);\n }\n\n return price;\n },\n\n /**\n * @return {*|String}\n */\n getValue: function () {\n return this.getFormattedPrice(this.getPureValue());\n }\n });\n});\n","Magento_SalesRule/js/action/select-payment-method-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 'Magento_Checkout/js/model/quote',\n 'Magento_SalesRule/js/model/payment/discount-messages',\n 'Magento_Checkout/js/action/set-payment-information-extended',\n 'Magento_Checkout/js/action/get-totals',\n 'Magento_SalesRule/js/model/coupon'\n], function ($, wrapper, quote, messageContainer, setPaymentInformationExtended, getTotalsAction, coupon) {\n 'use strict';\n\n return function (selectPaymentMethodAction) {\n\n return wrapper.wrap(selectPaymentMethodAction, function (originalSelectPaymentMethodAction, paymentMethod) {\n\n originalSelectPaymentMethodAction(paymentMethod);\n\n if (paymentMethod === null) {\n return;\n }\n\n $.when(\n setPaymentInformationExtended(\n messageContainer,\n {\n method: paymentMethod.method\n },\n true\n )\n ).done(\n function () {\n var deferred = $.Deferred(),\n\n /**\n * Update coupon form.\n */\n updateCouponCallback = function () {\n if (quote.totals() && !quote.totals()['coupon_code']) {\n coupon.setCouponCode('');\n coupon.setIsApplied(false);\n }\n };\n\n getTotalsAction([], deferred);\n $.when(deferred).done(updateCouponCallback);\n }\n );\n });\n };\n\n});\n","Magento_SalesRule/js/action/set-coupon-code.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Customer store credit(balance) application\n */\ndefine([\n 'ko',\n 'jquery',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/resource-url-manager',\n 'Magento_Checkout/js/model/error-processor',\n 'Magento_SalesRule/js/model/payment/discount-messages',\n 'mage/storage',\n 'mage/translate',\n 'Magento_Checkout/js/action/get-payment-information',\n 'Magento_Checkout/js/model/totals',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/action/recollect-shipping-rates'\n], function (ko, $, quote, urlManager, errorProcessor, messageContainer, storage, $t, getPaymentInformationAction,\n totals, fullScreenLoader, recollectShippingRates\n) {\n 'use strict';\n\n var dataModifiers = [],\n successCallbacks = [],\n failCallbacks = [],\n action;\n\n /**\n * Apply provided coupon.\n *\n * @param {String} couponCode\n * @param {Boolean}isApplied\n * @returns {Deferred}\n */\n action = function (couponCode, isApplied) {\n var quoteId = quote.getQuoteId(),\n url = urlManager.getApplyCouponUrl(couponCode, quoteId),\n message = $t('Your coupon was successfully applied.'),\n data = {},\n headers = {};\n\n //Allowing to modify coupon-apply request\n dataModifiers.forEach(function (modifier) {\n modifier(headers, data);\n });\n fullScreenLoader.startLoader();\n\n return storage.put(\n url,\n data,\n false,\n null,\n headers\n ).done(function (response) {\n var deferred;\n\n if (response) {\n deferred = $.Deferred();\n\n isApplied(true);\n totals.isLoading(true);\n recollectShippingRates();\n getPaymentInformationAction(deferred);\n $.when(deferred).done(function () {\n fullScreenLoader.stopLoader();\n totals.isLoading(false);\n });\n messageContainer.addSuccessMessage({\n 'message': message\n });\n //Allowing to tap into apply-coupon process.\n successCallbacks.forEach(function (callback) {\n callback(response);\n });\n }\n }).fail(function (response) {\n fullScreenLoader.stopLoader();\n totals.isLoading(false);\n errorProcessor.process(response, messageContainer);\n //Allowing to tap into apply-coupon process.\n failCallbacks.forEach(function (callback) {\n callback(response);\n });\n });\n };\n\n /**\n * Modifying data to be sent.\n *\n * @param {Function} modifier\n */\n action.registerDataModifier = function (modifier) {\n dataModifiers.push(modifier);\n };\n\n /**\n * When successfully added a coupon.\n *\n * @param {Function} callback\n */\n action.registerSuccessCallback = function (callback) {\n successCallbacks.push(callback);\n };\n\n /**\n * When failed to add a coupon.\n *\n * @param {Function} callback\n */\n action.registerFailCallback = function (callback) {\n failCallbacks.push(callback);\n };\n\n return action;\n});\n","Magento_SalesRule/js/action/cancel-coupon.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Customer store credit(balance) application\n */\ndefine([\n 'jquery',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/resource-url-manager',\n 'Magento_Checkout/js/model/error-processor',\n 'Magento_SalesRule/js/model/payment/discount-messages',\n 'mage/storage',\n 'Magento_Checkout/js/action/get-payment-information',\n 'Magento_Checkout/js/model/totals',\n 'mage/translate',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/action/recollect-shipping-rates'\n], function ($, quote, urlManager, errorProcessor, messageContainer, storage, getPaymentInformationAction, totals, $t,\n fullScreenLoader, recollectShippingRates\n) {\n 'use strict';\n\n var successCallbacks = [],\n action,\n callSuccessCallbacks;\n\n /**\n * Execute callbacks when a coupon is successfully canceled.\n */\n callSuccessCallbacks = function () {\n successCallbacks.forEach(function (callback) {\n callback();\n });\n };\n\n /**\n * Cancel applied coupon.\n *\n * @param {Boolean} isApplied\n * @returns {Deferred}\n */\n action = function (isApplied) {\n var quoteId = quote.getQuoteId(),\n url = urlManager.getCancelCouponUrl(quoteId),\n message = $t('Your coupon was successfully removed.');\n\n messageContainer.clear();\n fullScreenLoader.startLoader();\n\n return storage.delete(\n url,\n false\n ).done(function () {\n var deferred = $.Deferred();\n\n totals.isLoading(true);\n recollectShippingRates();\n getPaymentInformationAction(deferred);\n $.when(deferred).done(function () {\n isApplied(false);\n totals.isLoading(false);\n fullScreenLoader.stopLoader();\n //Allowing to tap into coupon-cancel process.\n callSuccessCallbacks();\n });\n messageContainer.addSuccessMessage({\n 'message': message\n });\n }).fail(function (response) {\n totals.isLoading(false);\n fullScreenLoader.stopLoader();\n errorProcessor.process(response, messageContainer);\n });\n };\n\n /**\n * Callback for when the cancel-coupon process is finished.\n *\n * @param {Function} callback\n */\n action.registerSuccessCallback = function (callback) {\n successCallbacks.push(callback);\n };\n\n return action;\n});\n","Magento_SalesRule/js/model/shipping-save-processor-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'mage/utils/wrapper',\n 'Magento_Checkout/js/model/quote',\n 'Magento_SalesRule/js/model/coupon'\n], function (wrapper, quote, coupon) {\n 'use strict';\n\n return function (shippingSaveProcessor) {\n shippingSaveProcessor.saveShippingInformation = wrapper.wrapSuper(\n shippingSaveProcessor.saveShippingInformation,\n function (type) {\n var updateCouponCallback;\n\n /**\n * Update coupon form\n */\n updateCouponCallback = function () {\n if (quote.totals() && !quote.totals()['coupon_code']) {\n coupon.setCouponCode('');\n coupon.setIsApplied(false);\n }\n };\n\n return this._super(type).done(updateCouponCallback);\n }\n );\n\n return shippingSaveProcessor;\n };\n});\n","Magento_SalesRule/js/model/place-order-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 'Magento_Checkout/js/model/quote',\n 'Magento_SalesRule/js/model/coupon',\n 'Magento_Checkout/js/action/get-totals'\n], function ($, wrapper, quote, coupon, getTotalsAction) {\n 'use strict';\n\n return function (placeOrderAction) {\n return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, messageContainer) {\n var result;\n\n $.when(\n result = originalAction(paymentData, messageContainer)\n ).fail(\n function () {\n var deferred = $.Deferred(),\n\n /**\n * Update coupon form\n */\n updateCouponCallback = function () {\n if (quote.totals() && !quote.totals()['coupon_code']) {\n coupon.setCouponCode('');\n coupon.setIsApplied(false);\n }\n };\n\n getTotalsAction([], deferred);\n $.when(deferred).done(updateCouponCallback);\n }\n );\n\n return result;\n });\n };\n});\n","Magento_SalesRule/js/model/coupon.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * Coupon model.\n */\ndefine([\n 'ko',\n 'domReady!'\n], function (ko) {\n 'use strict';\n\n var couponCode = ko.observable(null),\n isApplied = ko.observable(null);\n\n return {\n couponCode: couponCode,\n isApplied: isApplied,\n\n /**\n * @return {*}\n */\n getCouponCode: function () {\n return couponCode;\n },\n\n /**\n * @return {Boolean}\n */\n getIsApplied: function () {\n return isApplied;\n },\n\n /**\n * @param {*} couponCodeValue\n */\n setCouponCode: function (couponCodeValue) {\n couponCode(couponCodeValue);\n },\n\n /**\n * @param {Boolean} isAppliedValue\n */\n setIsApplied: function (isAppliedValue) {\n isApplied(isAppliedValue);\n }\n };\n});\n","Magento_SalesRule/js/model/payment/discount-messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Ui/js/model/messages'\n], function (Messages) {\n 'use strict';\n\n return new Messages();\n});\n","PayPal_Braintree/js/form-builder.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(\n [\n 'jquery',\n 'underscore',\n 'mage/template'\n ],\n function ($, _, mageTemplate) {\n 'use strict';\n\n return {\n\n /**\n * @param {Object} formData\n * @returns {*|jQuery}\n */\n build: function (formData) {\n var formTmpl = mageTemplate('<form action=\"<%= data.action %>\"' +\n ' method=\"POST\" hidden enctype=\"application/x-www-form-urlencoded\">' +\n '<% _.each(data.fields, function(val, key){ %>' +\n '<input value=\\'<%= val %>\\' name=\"<%= key %>\" type=\"hidden\">' +\n '<% }); %>' +\n '</form>');\n\n return $(formTmpl({\n data: {\n action: formData.action,\n fields: formData.fields\n }\n })).appendTo($('[data-container=\"body\"]'));\n }\n };\n }\n);\n","PayPal_Braintree/js/validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n 'underscore'\n], function (_) {\n 'use strict';\n\n return {\n config: {},\n\n /**\n * Set configuration\n * @param {Object} config\n */\n setConfig: function (config) {\n this.config = config;\n },\n\n /**\n * Get List of available card types\n * @returns {*|exports.defaults.availableCardTypes|{}}\n */\n getAvailableCardTypes: function () {\n return this.config.availableCardTypes;\n },\n\n /**\n * Get list of card types\n * @returns {Object}\n */\n getCcTypesMapper: function () {\n return this.config.ccTypesMapper;\n },\n\n /**\n * Find mage card type by Braintree type\n * @param {String} type\n * @param {Object} availableTypes\n * @returns {*}\n */\n getMageCardType: function (type, availableTypes) {\n var storedCardType = null,\n mapper = this.getCcTypesMapper();\n\n if (type && typeof mapper[type] !== 'undefined') {\n storedCardType = mapper[type];\n\n if (_.indexOf(availableTypes, storedCardType) !== -1) {\n return storedCardType;\n }\n }\n\n return null;\n },\n\n /**\n * Filter list of available card types\n * @param {Object} availableTypes\n * @param {Object} countrySpecificCardTypes\n * @returns {Object}\n */\n collectTypes: function (availableTypes, countrySpecificCardTypes) {\n var key,\n filteredTypes = [];\n\n for (key in availableTypes) {\n if (_.indexOf(countrySpecificCardTypes, availableTypes[key]) !== -1) {\n filteredTypes.push(availableTypes[key]);\n }\n }\n\n return filteredTypes;\n },\n\n /**\n * Get list of card types for country\n * @param {String} countryId\n * @returns {*}\n */\n getCountrySpecificCardTypes: function (countryId) {\n if (typeof this.config.countrySpecificCardTypes[countryId] !== 'undefined') {\n return this.config.countrySpecificCardTypes[countryId];\n }\n\n return false;\n }\n };\n});\n","PayPal_Braintree/js/view/product-page.js":"define(\n ['uiComponent'],\n function (Component) {\n 'use strict';\n\n return Component.extend({\n\n });\n }\n);","PayPal_Braintree/js/view/payment/venmo.js":"define(\n [\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list'\n ],\n function (\n Component,\n rendererList\n ) {\n 'use strict';\n\n rendererList.push(\n {\n type: 'braintree_venmo',\n component: 'PayPal_Braintree/js/view/payment/method-renderer/venmo'\n }\n );\n\n return Component.extend({});\n }\n);\n","PayPal_Braintree/js/view/payment/braintree.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n 'use strict';\n\n let config = window.checkoutConfig.payment,\n braintreeType = 'braintree',\n payPalType = 'braintree_paypal',\n braintreeAchDirectDebit = 'braintree_ach_direct_debit',\n braintreeVenmo = 'braintree_venmo',\n braintreeLocalPayment = 'braintree_local_payment';\n\n if (config[braintreeType] && config[braintreeType].isActive && config[braintreeType].clientToken) {\n rendererList.push({\n type: braintreeType,\n component: 'PayPal_Braintree/js/view/payment/method-renderer/hosted-fields'\n });\n }\n\n if (config[payPalType] && config[payPalType].isActive) {\n rendererList.push({\n type: payPalType,\n component: 'PayPal_Braintree/js/view/payment/method-renderer/paypal'\n });\n }\n\n if (config[braintreeVenmo] && config[braintreeVenmo].isAllowed && config[braintreeVenmo].clientToken) {\n rendererList.push({\n type: braintreeVenmo,\n component: 'PayPal_Braintree/js/view/payment/method-renderer/venmo'\n });\n }\n\n if (config[braintreeAchDirectDebit] && config[braintreeAchDirectDebit].isActive && config[braintreeAchDirectDebit].clientToken) {\n rendererList.push({\n type: braintreeAchDirectDebit,\n component: 'PayPal_Braintree/js/view/payment/method-renderer/ach'\n });\n }\n\n if (config[braintreeLocalPayment] && config[braintreeLocalPayment].clientToken) {\n rendererList.push({\n type: braintreeLocalPayment,\n component: 'PayPal_Braintree/js/view/payment/method-renderer/lpm'\n });\n }\n\n /** Add view logic here if needed */\n return Component.extend({});\n});\n","PayPal_Braintree/js/view/payment/validator-handler.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\n\ndefine([\n 'jquery',\n 'Magento_Ui/js/model/messageList',\n 'PayPal_Braintree/js/view/payment/3d-secure',\n 'Magento_Checkout/js/model/full-screen-loader'\n], function ($, globalMessageList, verify3DSecure, fullScreenLoader) {\n 'use strict';\n\n return {\n validators: [],\n\n /**\n * Get payment config\n * @returns {Object}\n */\n getConfig: function () {\n return window.checkoutConfig.payment;\n },\n\n /**\n * Init list of validators\n */\n initialize: function () {\n var config = this.getConfig();\n\n if (config[verify3DSecure.getCode()].enabled) {\n verify3DSecure.setConfig(config[verify3DSecure.getCode()]);\n this.add(verify3DSecure);\n }\n },\n\n /**\n * Add new validator\n * @param {Object} validator\n */\n add: function (validator) {\n this.validators.push(validator);\n },\n\n /**\n * Run pull of validators\n * @param {Object} context\n * @param {Function} callback\n */\n validate: function (context, callback, errorCallback) {\n var self = this,\n deferred;\n\n // no available validators\n if (!self.validators.length) {\n callback();\n\n return;\n }\n\n // get list of deferred validators\n deferred = $.map(self.validators, function (current) {\n return current.validate(context);\n });\n\n $.when.apply($, deferred)\n .done(function () {\n callback();\n }).fail(function (error) {\n errorCallback();\n self.showError(error);\n });\n },\n\n /**\n * Show error message\n * @param {String} errorMessage\n */\n showError: function (errorMessage) {\n globalMessageList.addErrorMessage({\n message: errorMessage\n });\n fullScreenLoader.stopLoader(true);\n }\n };\n});\n","PayPal_Braintree/js/view/payment/ach.js":"define(\n [\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list'\n ],\n function (\n Component,\n rendererList\n ) {\n 'use strict';\n\n rendererList.push(\n {\n type: 'braintree_ach_direct_debit',\n component: 'PayPal_Braintree/js/view/payment/method-renderer/ach'\n }\n );\n\n return Component.extend({});\n }\n);\n","PayPal_Braintree/js/view/payment/3d-secure.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\n\ndefine([\n 'jquery',\n 'PayPal_Braintree/js/view/payment/adapter',\n 'Magento_Checkout/js/model/quote',\n 'mage/translate',\n 'braintreeThreeDSecure',\n 'Magento_Checkout/js/model/full-screen-loader'\n], function ($, braintree, quote, $t, threeDSecure, fullScreenLoader) {\n 'use strict';\n\n return {\n config: null,\n\n /**\n * Set 3d secure config\n * @param {Object} config\n */\n setConfig: function (config) {\n this.config = config;\n this.config.thresholdAmount = parseFloat(config.thresholdAmount);\n },\n\n /**\n * Get code\n * @returns {String}\n */\n getCode: function () {\n return 'three_d_secure';\n },\n\n /**\n * convert Non-ASCII characters into unicode\n * @param str\n * @returns {string}\n */\n escapeNonAsciiCharacters: function (str) {\n return str.split(\"\").map(function (c) { return /[^\\x00-\\x7F]$/.test(c) ? c : c.split(\"\").map(function (a) { return \"\\\\u00\" + a.charCodeAt().toString(16)}).join(\"\")}).join(\"\");\n },\n\n /**\n * Validate Braintree payment nonce\n * @param {Object} context\n * @returns {Object}\n */\n validate: function (context) {\n let clientInstance = braintree.getApiClient(),\n state = $.Deferred(),\n totalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2),\n billingAddress = quote.billingAddress();\n\n if (billingAddress.regionCode == null) {\n billingAddress.regionCode = undefined;\n }\n\n if (billingAddress.regionCode !== undefined && billingAddress.regionCode.length > 2) {\n billingAddress.regionCode = undefined;\n }\n\n // No 3d secure if using CVV verification on vaulted cards\n if (quote.paymentMethod().method.indexOf('braintree_cc_vault_') !== -1) {\n if (this.config.useCvvVault === true) {\n state.resolve();\n return state.promise();\n }\n }\n\n if (!this.isAmountAvailable(totalAmount) || !this.isCountryAvailable(billingAddress.countryId)) {\n state.resolve();\n return state.promise();\n }\n\n let firstName = this.escapeNonAsciiCharacters(billingAddress.firstname);\n let lastName = this.escapeNonAsciiCharacters(billingAddress.lastname);\n\n let challengeRequested = this.getChallengeRequested();\n\n fullScreenLoader.startLoader();\n\n let setup3d = function(clientInstance) {\n threeDSecure.create({\n version: 2,\n client: clientInstance\n }, function (threeDSecureErr, threeDSecureInstance) {\n if (threeDSecureErr) {\n fullScreenLoader.stopLoader();\n return state.reject($t('Please try again with another form of payment.'));\n }\n\n let threeDSContainer = document.createElement('div'),\n tdMask = document.createElement('div'),\n tdFrame = document.createElement('div'),\n tdBody = document.createElement('div');\n\n threeDSContainer.id = 'braintree-three-d-modal';\n tdMask.className =\"bt-mask\";\n tdFrame.className =\"bt-modal-frame\";\n tdBody.className =\"bt-modal-body\";\n\n tdFrame.appendChild(tdBody);\n threeDSContainer.appendChild(tdMask);\n threeDSContainer.appendChild(tdFrame);\n\n threeDSecureInstance.verifyCard({\n amount: totalAmount,\n nonce: context.paymentMethodNonce,\n bin: context.creditCardBin,\n challengeRequested: challengeRequested,\n billingAddress: {\n givenName: firstName,\n surname: lastName,\n phoneNumber: billingAddress.telephone,\n streetAddress: billingAddress.street[0],\n extendedAddress: billingAddress.street[1],\n locality: billingAddress.city,\n region: billingAddress.regionCode,\n postalCode: billingAddress.postcode,\n countryCodeAlpha2: billingAddress.countryId\n },\n onLookupComplete: function (data, next) {\n next();\n },\n addFrame: function (err, iframe) {\n fullScreenLoader.stopLoader();\n\n if (err) {\n console.log(\"Unable to verify card over 3D Secure\", err);\n return state.reject($t('Please try again with another form of payment.'));\n }\n\n tdBody.appendChild(iframe);\n document.body.appendChild(threeDSContainer);\n },\n removeFrame: function () {\n fullScreenLoader.startLoader();\n document.body.removeChild(threeDSContainer);\n }\n }, function (err, response) {\n fullScreenLoader.stopLoader();\n\n if (err) {\n console.error(\"3DSecure validation failed\", err);\n if (err.code === 'THREEDS_LOOKUP_VALIDATION_ERROR') {\n let errorMessage = err.details.originalError.details.originalError.error.message;\n if (errorMessage === 'Billing line1 format is invalid.' && billingAddress.street[0].length > 50) {\n return state.reject(\n $t('Billing line1 must be string and less than 50 characters. Please update the address and try again.')\n );\n\n } else if (errorMessage === 'Billing line2 format is invalid.' && billingAddress.street[1].length > 50) {\n return state.reject(\n $t('Billing line2 must be string and less than 50 characters. Please update the address and try again.')\n );\n }\n return state.reject($t(errorMessage));\n } else {\n return state.reject($t('Please try again with another form of payment.'));\n }\n }\n\n let liability = {\n shifted: response.liabilityShifted,\n shiftPossible: response.liabilityShiftPossible\n };\n\n if (liability.shifted || !liability.shifted && !liability.shiftPossible) {\n context.paymentMethodNonce = response.nonce;\n state.resolve();\n } else {\n state.reject($t('Please try again with another form of payment.'));\n }\n });\n });\n };\n\n if (!clientInstance) {\n require(['PayPal_Braintree/js/view/payment/method-renderer/cc-form'], function(c) {\n let config = c.extend({\n defaults: {\n clientConfig: {\n onReady: function() {}\n }\n }\n });\n braintree.setConfig(config.defaults.clientConfig);\n braintree.setup(setup3d);\n });\n } else {\n setup3d(clientInstance);\n }\n\n return state.promise();\n },\n\n /**\n * Check minimal amount for 3d secure activation\n * @param {Number} amount\n * @returns {Boolean}\n */\n isAmountAvailable: function (amount) {\n amount = parseFloat(amount.toString());\n\n return amount >= this.config.thresholdAmount;\n },\n\n /**\n * Check if current country is available for 3d secure\n * @param {String} countryId\n * @returns {Boolean}\n */\n isCountryAvailable: function (countryId) {\n let key,\n specificCountries = this.config.specificCountries;\n\n // all countries are available\n if (!specificCountries.length) {\n return true;\n }\n\n for (key in specificCountries) {\n if (countryId === specificCountries[key]) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * @returns {Boolean}\n */\n getChallengeRequested: function () {\n return this.config.challengeRequested;\n }\n };\n});\n","PayPal_Braintree/js/view/payment/adapter.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n 'jquery',\n 'braintree',\n 'braintreeDataCollector',\n 'braintreeHostedFields',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Ui/js/model/messageList',\n 'mage/translate'\n], function ($, client, dataCollector, hostedFields, fullScreenLoader, globalMessageList, $t) {\n 'use strict';\n\n return {\n apiClient: null,\n config: {},\n checkout: null,\n deviceData: null,\n clientInstance: null,\n hostedFieldsInstance: null,\n paypalInstance: null,\n code: 'braintree',\n\n /**\n * {Object}\n */\n events: {\n onClick: null,\n onCancel: null,\n onError: null\n },\n\n /**\n * Get Braintree api client\n * @returns {Object}\n */\n getApiClient: function () {\n return this.clientInstance;\n },\n\n /**\n * Set configuration\n * @param {Object} config\n */\n setConfig: function (config) {\n this.config = config;\n },\n\n /**\n * Get payment name\n * @returns {String}\n */\n getCode: function () {\n if (window.checkoutConfig.payment[this.code]) {\n return this.code;\n } else {\n return 'braintree_paypal';\n }\n },\n\n /**\n * Get client token\n * @returns {String|*}\n */\n getClientToken: function () {\n return window.checkoutConfig.payment[this.getCode()].clientToken;\n },\n\n /**\n * @returns {String}\n */\n getEnvironment: function () {\n return window.checkoutConfig.payment[this.getCode()].environment;\n },\n\n getCurrentCode: function (paypalType = null) {\n var code = 'braintree_paypal';\n if (paypalType !== 'paypal') {\n code = code + '_' + paypalType;\n }\n return code;\n },\n\n /**\n * @returns {String}\n */\n getColor: function (paypalType = null) {\n return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.color;\n },\n\n /**\n * @returns {String}\n */\n getShape: function (paypalType = null) {\n return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.shape;\n },\n\n /**\n * @returns {String}\n */\n getSize: function (paypalType = null) {\n return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.size;\n },\n\n /**\n * @returns {String}\n */\n getLabel: function (paypalType = null) {\n return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.label;\n },\n\n /**\n * @returns {String}\n */\n getBranding: function () {\n return null;\n },\n\n /**\n * @returns {String}\n */\n getFundingIcons: function () {\n return null;\n },\n\n /**\n * @returns {String}\n */\n getDisabledFunding: function () {\n return window.checkoutConfig.payment[this.getCode()].disabledFunding;\n },\n\n /**\n * Show error message\n *\n * @param {String} errorMessage\n */\n showError: function (errorMessage) {\n globalMessageList.addErrorMessage({\n message: errorMessage\n });\n fullScreenLoader.stopLoader(true);\n },\n\n /**\n * Disable submit button\n */\n disableButton: function () {\n // stop any previous shown loaders\n fullScreenLoader.stopLoader(true);\n fullScreenLoader.startLoader();\n $('[data-button=\"place\"]').attr('disabled', 'disabled');\n },\n\n /**\n * Enable submit button\n */\n enableButton: function () {\n $('[data-button=\"place\"]').removeAttr('disabled');\n fullScreenLoader.stopLoader();\n },\n\n /**\n * Has PayPal been init'd already\n */\n getPayPalInstance: function() {\n if (typeof this.config.paypalInstance !== 'undefined' && this.config.paypalInstance) {\n return this.config.paypalInstance;\n }\n\n return null;\n },\n\n setPayPalInstance: function(val) {\n this.config.paypalInstance = val;\n },\n\n /**\n * Setup Braintree SDK\n */\n setup: function (callback) {\n if (!this.getClientToken()) {\n this.showError($t('Sorry, but something went wrong.'));\n return;\n }\n\n if (this.clientInstance) {\n if (typeof this.config.onReady === 'function') {\n this.config.onReady(this);\n }\n\n if (typeof callback === \"function\") {\n callback(this.clientInstance);\n }\n return;\n }\n\n client.create({\n authorization: this.getClientToken()\n }, function (clientErr, clientInstance) {\n if (clientErr) {\n console.error('Braintree Setup Error', clientErr);\n return this.showError(\"Sorry, but something went wrong. Please contact the store owner.\");\n }\n\n var options = {\n client: clientInstance\n };\n\n if (typeof this.config.dataCollector === 'object' && typeof this.config.dataCollector.paypal === 'boolean') {\n options.paypal = true;\n }\n\n dataCollector.create(options, function (err, dataCollectorInstance) {\n if (err) {\n return console.log(err);\n }\n\n this.deviceData = dataCollectorInstance.deviceData;\n this.config.onDeviceDataReceived(this.deviceData);\n }.bind(this));\n\n this.clientInstance = clientInstance;\n\n if (typeof this.config.onReady === 'function') {\n this.config.onReady(this);\n }\n\n if (typeof callback === \"function\") {\n callback(this.clientInstance);\n }\n }.bind(this));\n },\n\n /**\n * Setup hosted fields instance\n */\n setupHostedFields: function () {\n var self = this;\n\n if (this.hostedFieldsInstance) {\n this.hostedFieldsInstance.teardown(function () {\n this.hostedFieldsInstance = null;\n this.setupHostedFields();\n }.bind(this));\n return;\n }\n\n hostedFields.create({\n client: this.clientInstance,\n fields: this.config.hostedFields,\n styles: {\n \"input\": {\n \"font-size\": \"14pt\",\n \"color\": \"#3A3A3A\"\n },\n \":focus\": {\n \"color\": \"black\"\n },\n \".valid\": {\n \"color\": \"green\"\n },\n \".invalid\": {\n \"color\": \"red\"\n }\n }\n }, function (createErr, hostedFieldsInstance) {\n if (createErr) {\n self.showError($t(\"Braintree hosted fields could not be initialized. Please contact the store owner.\"));\n console.error('Braintree hosted fields error', createErr);\n return;\n }\n\n this.config.onInstanceReady(hostedFieldsInstance);\n this.hostedFieldsInstance = hostedFieldsInstance;\n }.bind(this));\n },\n\n tokenizeHostedFields: function () {\n this.hostedFieldsInstance.tokenize({}, function (tokenizeErr, payload) {\n if (tokenizeErr) {\n switch (tokenizeErr.code) {\n case 'HOSTED_FIELDS_FIELDS_EMPTY':\n // occurs when none of the fields are filled in\n console.error('All fields are empty! Please fill out the form.');\n break;\n case 'HOSTED_FIELDS_FIELDS_INVALID':\n // occurs when certain fields do not pass client side validation\n console.error('Some fields are invalid:', tokenizeErr.details.invalidFieldKeys);\n break;\n case 'HOSTED_FIELDS_TOKENIZATION_FAIL_ON_DUPLICATE':\n // occurs when:\n // * the client token used for client authorization was generated\n // with a customer ID and the fail on duplicate payment method\n // option is set to true\n // * the card being tokenized has previously been vaulted (with any customer)\n // See: https://developers.braintreepayments.com/reference/request/client-token/generate/#options.fail_on_duplicate_payment_method\n console.error('This payment method already exists in your vault.');\n break;\n case 'HOSTED_FIELDS_TOKENIZATION_CVV_VERIFICATION_FAILED':\n // occurs when:\n // * the client token used for client authorization was generated\n // with a customer ID and the verify card option is set to true\n // and you have credit card verification turned on in the Braintree\n // control panel\n // * the cvv does not pass verfication (https://developers.braintreepayments.com/reference/general/testing/#avs-and-cvv/cid-responses)\n // See: https://developers.braintreepayments.com/reference/request/client-token/generate/#options.verify_card\n console.error('CVV did not pass verification');\n break;\n case 'HOSTED_FIELDS_FAILED_TOKENIZATION':\n // occurs for any other tokenization error on the server\n console.error('Tokenization failed server side. Is the card valid?');\n break;\n case 'HOSTED_FIELDS_TOKENIZATION_NETWORK_ERROR':\n // occurs when the Braintree gateway cannot be contacted\n console.error('Network error occurred when tokenizing.');\n break;\n default:\n console.error('Something bad happened!', tokenizeErr);\n }\n } else {\n this.config.onPaymentMethodReceived(payload);\n }\n }.bind(this));\n }\n };\n});\n\n","PayPal_Braintree/js/view/payment/lpm.js":"define(\n [\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list'\n ],\n function (\n Component,\n rendererList\n ) {\n 'use strict';\n\n rendererList.push(\n {\n type: 'braintree_local_payment',\n component: 'PayPal_Braintree/js/view/payment/method-renderer/lpm'\n }\n );\n\n return Component.extend({});\n }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n 'ko',\n 'jquery',\n 'Magento_Vault/js/view/payment/method-renderer/vault',\n 'PayPal_Braintree/js/view/payment/adapter',\n 'Magento_Ui/js/model/messageList',\n 'PayPal_Braintree/js/view/payment/validator-handler',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'braintree',\n 'braintreeHostedFields',\n 'mage/url'\n], function (\n ko,\n $,\n VaultComponent,\n Braintree,\n globalMessageList,\n validatorManager,\n additionalValidators,\n fullScreenLoader,\n client,\n hostedFields,\n url\n) {\n 'use strict';\n\n return VaultComponent.extend({\n defaults: {\n active: false,\n hostedFieldsInstance: null,\n imports: {\n onActiveChange: 'active'\n },\n modules: {\n hostedFields: '${ $.parentName }.braintree'\n },\n template: 'PayPal_Braintree/payment/cc/vault',\n updatePaymentUrl: url.build('braintree/payment/updatepaymentmethod'),\n vaultedCVV: ko.observable(\"\"),\n validatorManager: validatorManager,\n isValidCvv: false,\n onInstanceReady: function (instance) {\n instance.on('validityChange', this.onValidityChange.bind(this));\n }\n },\n\n /**\n * Event fired by Braintree SDK whenever input value length matches the validation length.\n * In the case of a CVV, this is 3, or 4 for AMEX.\n * @param event\n */\n onValidityChange: function (event) {\n if (event.emittedBy === 'cvv') {\n this.isValidCvv = event.fields.cvv.isValid;\n }\n },\n\n /**\n * @returns {exports}\n */\n initObservable: function () {\n this._super().observe(['active']);\n this.validatorManager.initialize();\n return this;\n },\n\n /**\n * Is payment option active?\n * @returns {boolean}\n */\n isActive: function () {\n let active = this.getId() === this.isChecked();\n this.active(active);\n return active;\n },\n\n /**\n * Fired whenever a payment option is changed.\n * @param isActive\n */\n onActiveChange: function (isActive) {\n let self = this;\n\n if (!isActive) {\n return;\n }\n\n if (self.showCvvVerify()) {\n if (self.hostedFieldsInstance) {\n self.hostedFieldsInstance.teardown(function (teardownError) {\n if (teardownError) {\n globalMessageList.addErrorMessage({\n message: teardownError.message\n });\n }\n self.hostedFieldsInstance = null;\n self.initHostedCvvField();\n });\n return;\n }\n self.initHostedCvvField();\n }\n },\n\n /**\n * Initialize the CVV input field with the Braintree Hosted Fields SDK.\n */\n initHostedCvvField: function () {\n let self = this;\n client.create({\n authorization: Braintree.getClientToken()\n }, function (clientError, clientInstance) {\n if (clientError) {\n globalMessageList.addErrorMessage({\n message: clientError.message\n });\n }\n hostedFields.create({\n client: clientInstance,\n fields: {\n cvv: {\n selector: '#' + self.getId() + '_cid',\n placeholder: '123'\n }\n }\n }, function (hostedError, hostedFieldsInstance) {\n if (hostedError) {\n globalMessageList.addErrorMessage({\n message: hostedError.message\n });\n return;\n }\n\n self.hostedFieldsInstance = hostedFieldsInstance;\n self.onInstanceReady(self.hostedFieldsInstance);\n });\n });\n },\n\n /**\n * Return the payment method code.\n * @returns {string}\n */\n getCode: function () {\n return 'braintree_cc_vault';\n },\n\n /**\n * Get last 4 digits of card\n * @returns {String}\n */\n getMaskedCard: function () {\n return this.details.maskedCC;\n },\n\n /**\n * Get expiration date\n * @returns {String}\n */\n getExpirationDate: function () {\n return this.details.expirationDate;\n },\n\n /**\n * Get card type\n * @returns {String}\n */\n getCardType: function () {\n return this.details.type;\n },\n\n /**\n * Get show CVV Field\n * @returns {Boolean}\n */\n showCvvVerify: function () {\n return window.checkoutConfig.payment[this.code].cvvVerify;\n },\n\n /**\n * Show or hide the error message.\n * @param selector\n * @param state\n * @returns {boolean}\n */\n validateCvv: function (selector, state) {\n let $selector = $(selector),\n invalidClass = 'braintree-hosted-fields-invalid';\n\n if (state === true) {\n $selector.removeClass(invalidClass);\n return true;\n }\n\n $selector.addClass(invalidClass);\n return false;\n },\n\n /**\n * Place order\n */\n placeOrder: function () {\n let self = this;\n\n if (self.showCvvVerify()) {\n if (!self.validateCvv('#' + self.getId() + '_cid', self.isValidCvv) || !additionalValidators.validate()) {\n return;\n }\n } else {\n if (!additionalValidators.validate()) {\n return;\n }\n }\n\n fullScreenLoader.startLoader();\n\n if (self.showCvvVerify() && typeof self.hostedFieldsInstance !== 'undefined') {\n self.hostedFieldsInstance.tokenize({}, function (error, payload) {\n if (error) {\n fullScreenLoader.stopLoader();\n globalMessageList.addErrorMessage({\n message: error.message\n });\n return;\n }\n $.getJSON(self.updatePaymentUrl, {\n 'nonce': payload.nonce,\n 'public_hash': self.publicHash\n }).done(function (response) {\n if (response.success === false) {\n fullScreenLoader.stopLoader();\n globalMessageList.addErrorMessage({\n message: 'CVV verification failed.'\n });\n return;\n }\n self.getPaymentMethodNonce();\n })\n });\n } else {\n self.getPaymentMethodNonce();\n }\n },\n\n /**\n * Send request to get payment method nonce\n */\n getPaymentMethodNonce: function () {\n let self = this;\n\n fullScreenLoader.startLoader();\n $.getJSON(self.nonceUrl, {\n 'public_hash': self.publicHash,\n 'cvv': self.vaultedCVV()\n }).done(function (response) {\n fullScreenLoader.stopLoader();\n self.hostedFields(function (formComponent) {\n formComponent.setPaymentMethodNonce(response.paymentMethodNonce);\n formComponent.setCreditCardBin(response.details.bin);\n formComponent.additionalData['public_hash'] = self.publicHash;\n formComponent.code = self.code;\n if (self.vaultedCVV()) {\n formComponent.additionalData['cvv'] = self.vaultedCVV();\n }\n\n self.validatorManager.validate(formComponent, function () {\n fullScreenLoader.stopLoader();\n return formComponent.placeOrder('parent');\n }, function() {\n // No teardown actions required.\n fullScreenLoader.stopLoader();\n formComponent.setPaymentMethodNonce(null);\n formComponent.setCreditCardBin(null);\n });\n\n });\n }).fail(function (response) {\n let error = JSON.parse(response.responseText);\n\n fullScreenLoader.stopLoader();\n globalMessageList.addErrorMessage({\n message: error.message\n });\n });\n }\n });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/venmo.js":"define(\n [\n 'Magento_Checkout/js/view/payment/default',\n 'braintree',\n 'braintreeDataCollector',\n 'braintreeVenmo',\n 'PayPal_Braintree/js/form-builder',\n 'Magento_Ui/js/model/messageList',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'mage/translate'\n ],\n function (\n Component,\n braintree,\n dataCollector,\n venmo,\n formBuilder,\n messageList,\n fullScreenLoader,\n additionalValidators,\n $t\n ) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n deviceData: null,\n paymentMethodNonce: null,\n template: 'PayPal_Braintree/payment/venmo',\n venmoInstance: null\n },\n\n clickVenmoBtn: function () {\n let self = this;\n\n if (!additionalValidators.validate()) {\n return false;\n }\n\n if (!this.venmoInstance) {\n this.setErrorMsg($t('Venmo not initialized, please try reloading.'));\n return;\n }\n\n this.venmoInstance.tokenize(function (tokenizeErr, payload) {\n if (tokenizeErr) {\n if (tokenizeErr.code === 'VENMO_CANCELED') {\n self.setErrorMsg($t('Venmo app is not available or the payment flow was cancelled.'));\n } else if (tokenizeErr.code === 'VENMO_APP_CANCELED') {\n self.setErrorMsg($t('Venmo payment flow cancelled.'));\n } else {\n self.setErrorMsg(tokenizeErr.message);\n }\n } else {\n self.handleVenmoSuccess(payload);\n }\n });\n },\n\n collectDeviceData: function (clientInstance, callback) {\n let self = this;\n dataCollector.create({\n client: clientInstance,\n paypal: true\n }, function (dataCollectorErr, dataCollectorInstance) {\n if (dataCollectorErr) {\n return;\n }\n self.deviceData = dataCollectorInstance.deviceData;\n callback();\n });\n },\n\n getClientToken: function () {\n return window.checkoutConfig.payment[this.getCode()].clientToken;\n },\n\n getCode: function() {\n return 'braintree_venmo';\n },\n\n getData: function () {\n let data = {\n 'method': this.getCode(),\n 'additional_data': {\n 'payment_method_nonce': this.paymentMethodNonce,\n 'device_data': this.deviceData\n }\n };\n\n data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n return data;\n },\n\n getPaymentMarkSrc: function () {\n return window.checkoutConfig.payment[this.getCode()].paymentMarkSrc;\n },\n\n getTitle: function() {\n return 'Venmo';\n },\n\n handleVenmoSuccess: function (payload) {\n this.setPaymentMethodNonce(payload.nonce);\n this.placeOrder();\n },\n\n initialize: function () {\n this._super();\n\n let self = this;\n\n braintree.create({\n authorization: self.getClientToken()\n }, function (clientError, clientInstance) {\n if (clientError) {\n this.setErrorMsg($t('Unable to initialize Braintree Client.'));\n return;\n }\n\n // Collect device data\n self.collectDeviceData(clientInstance, function () {\n // callback from collectDeviceData\n venmo.create({\n client: clientInstance,\n allowDesktop: true,\n allowDesktopWebLogin: true,\n mobileWebFallBack: true,\n paymentMethodUsage: 'single_use',\n allowNewBrowserTab: false\n }, function (venmoErr, venmoInstance) {\n if (venmoErr) {\n self.setErrorMsg($t('Error initializing Venmo: %1').replace('%1', venmoErr));\n return;\n }\n\n if (!venmoInstance.isBrowserSupported()) {\n console.log('Browser does not support Venmo');\n return;\n }\n\n self.setVenmoInstance(venmoInstance);\n });\n });\n });\n\n return this;\n },\n\n isAllowed: function () {\n return window.checkoutConfig.payment[this.getCode()].isAllowed;\n },\n\n setErrorMsg: function (message) {\n messageList.addErrorMessage({\n message: message\n });\n },\n\n setPaymentMethodNonce: function (nonce) {\n this.paymentMethodNonce = nonce;\n },\n\n setVenmoInstance: function (instance) {\n this.venmoInstance = instance;\n }\n });\n }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/paypal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n 'jquery',\n 'underscore',\n 'Magento_Checkout/js/view/payment/default',\n 'braintree',\n 'braintreeCheckoutPayPalAdapter',\n 'braintreePayPalCheckout',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Checkout/js/model/step-navigator',\n 'Magento_Vault/js/view/payment/vault-enabler',\n 'Magento_Checkout/js/action/create-billing-address',\n 'Magento_Checkout/js/action/select-billing-address',\n 'Magento_CheckoutAgreements/js/view/checkout-agreements',\n 'mage/translate'\n], function (\n $,\n _,\n Component,\n braintree,\n Braintree,\n paypalCheckout,\n quote,\n fullScreenLoader,\n additionalValidators,\n stepNavigator,\n VaultEnabler,\n createBillingAddress,\n selectBillingAddress,\n checkoutAgreements,\n $t\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'PayPal_Braintree/payment/paypal',\n code: 'braintree_paypal',\n active: false,\n paypalInstance: null,\n paymentMethodNonce: null,\n grandTotalAmount: null,\n isReviewRequired: false,\n customerEmail: null,\n\n /**\n * Additional payment data\n *\n * {Object}\n */\n additionalData: {},\n\n /**\n * {Array}\n */\n lineItemsArray: [\n 'name',\n 'kind',\n 'quantity',\n 'unitAmount',\n 'unitTaxAmount',\n 'productCode',\n 'description'\n ],\n\n /**\n * PayPal client configuration\n * {Object}\n */\n clientConfig: {\n offerCredit: false,\n offerCreditOnly: false,\n dataCollector: {\n paypal: true\n },\n\n buttonPayPalId: 'braintree_paypal_placeholder',\n buttonCreditId: 'braintree_paypal_credit_placeholder',\n buttonPaylaterId: 'braintree_paypal_paylater_placeholder',\n\n onDeviceDataReceived: function (deviceData) {\n this.additionalData['device_data'] = deviceData;\n },\n\n /**\n * Triggers when widget is loaded\n * @param {Object} context\n */\n onReady: function (context) {\n this.setupPayPal();\n },\n\n /**\n * Triggers on payment nonce receive\n * @param {Object} response\n */\n onPaymentMethodReceived: function (response) {\n this.beforePlaceOrder(response);\n }\n },\n imports: {\n onActiveChange: 'active'\n }\n },\n\n /**\n * Set list of observable attributes\n * @returns {exports.initObservable}\n */\n initObservable: function () {\n var self = this;\n\n this._super()\n .observe(['active', 'isReviewRequired', 'customerEmail']);\n\n window.addEventListener('hashchange', function (e) {\n var methodCode = quote.paymentMethod();\n\n if (methodCode === 'braintree_paypal' || methodCode === 'braintree_paypal_vault') {\n if (e.newURL.indexOf('payment') > 0 && self.grandTotalAmount !== null) {\n self.reInitPayPal();\n }\n }\n });\n\n quote.paymentMethod.subscribe(function (value) {\n var methodCode = value;\n\n if (methodCode === 'braintree_paypal' || methodCode === 'braintree_paypal_vault') {\n self.reInitPayPal();\n }\n });\n\n this.vaultEnabler = new VaultEnabler();\n this.vaultEnabler.setPaymentCode(this.getVaultCode());\n this.vaultEnabler.isActivePaymentTokenEnabler.subscribe(function () {\n self.onVaultPaymentTokenEnablerChange();\n });\n\n this.grandTotalAmount = quote.totals()['base_grand_total'];\n\n quote.totals.subscribe(function () {\n if (self.grandTotalAmount !== quote.totals()['base_grand_total']) {\n self.grandTotalAmount = quote.totals()['base_grand_total'];\n var methodCode = quote.paymentMethod();\n\n if (methodCode && (methodCode.method === 'braintree_paypal' || methodCode.method === 'braintree_paypal_vault')) {\n self.reInitPayPal();\n }\n }\n });\n\n // for each component initialization need update property\n this.isReviewRequired(false);\n this.initClientConfig();\n\n return this;\n },\n\n /**\n * Get payment name\n *\n * @returns {String}\n */\n getCode: function () {\n return this.code;\n },\n\n /**\n * Get payment title\n *\n * @returns {String}\n */\n getTitle: function () {\n return window.checkoutConfig.payment[this.getCode()].title;\n },\n\n /**\n * Check if payment is active\n *\n * @returns {Boolean}\n */\n isActive: function () {\n var active = this.getCode() === this.isChecked();\n\n this.active(active);\n\n return active;\n },\n\n /**\n * Triggers when payment method change\n * @param {Boolean} isActive\n */\n onActiveChange: function (isActive) {\n if (!isActive) {\n return;\n }\n\n // need always re-init Braintree with PayPal configuration\n this.reInitPayPal();\n },\n\n /**\n * Init config\n */\n initClientConfig: function () {\n this.clientConfig = _.extend(this.clientConfig, this.getPayPalConfig());\n\n _.each(this.clientConfig, function (fn, name) {\n if (typeof fn === 'function') {\n this.clientConfig[name] = fn.bind(this);\n }\n }, this);\n },\n\n /**\n * Set payment nonce\n * @param {String} paymentMethodNonce\n */\n setPaymentMethodNonce: function (paymentMethodNonce) {\n this.paymentMethodNonce = paymentMethodNonce;\n },\n\n /**\n * Update quote billing address\n * @param {Object}customer\n * @param {Object}address\n */\n setBillingAddress: function (customer, address) {\n var billingAddress = {\n street: [address.line1],\n city: address.city,\n postcode: address.postalCode,\n countryId: address.countryCode,\n email: customer.email,\n firstname: customer.firstName,\n lastname: customer.lastName,\n telephone: typeof customer.phone !== 'undefined' ? customer.phone : '00000000000'\n };\n\n billingAddress['region_code'] = typeof address.state === 'string' ? address.state : '';\n billingAddress = createBillingAddress(billingAddress);\n quote.billingAddress(billingAddress);\n },\n\n /**\n * Prepare data to place order\n * @param {Object} data\n */\n beforePlaceOrder: function (data) {\n this.setPaymentMethodNonce(data.nonce);\n this.customerEmail(data.details.email);\n if (quote.isVirtual()) {\n this.isReviewRequired(true);\n } else {\n if (this.isRequiredBillingAddress() === '1' || quote.billingAddress() === null) {\n if (typeof data.details.billingAddress !== 'undefined') {\n this.setBillingAddress(data.details, data.details.billingAddress);\n } else {\n this.setBillingAddress(data.details, data.details.shippingAddress);\n }\n } else {\n if (quote.shippingAddress() === quote.billingAddress()) {\n selectBillingAddress(quote.shippingAddress());\n } else {\n selectBillingAddress(quote.billingAddress());\n }\n }\n }\n this.placeOrder();\n },\n\n /**\n * Re-init PayPal Auth Flow\n */\n reInitPayPal: function () {\n this.disableButton();\n this.clientConfig.paypal.amount = parseFloat(this.grandTotalAmount).toFixed(2);\n\n if (!quote.isVirtual()) {\n this.clientConfig.paypal.enableShippingAddress = true;\n this.clientConfig.paypal.shippingAddressEditable = false;\n this.clientConfig.paypal.shippingAddressOverride = this.getShippingAddress();\n }\n // Send Line Items\n this.clientConfig.paypal.lineItems = this.getLineItems();\n\n Braintree.setConfig(this.clientConfig);\n\n if (Braintree.getPayPalInstance()) {\n Braintree.getPayPalInstance().teardown(function () {\n Braintree.setup();\n }.bind(this));\n Braintree.setPayPalInstance(null);\n } else {\n Braintree.setup();\n this.enableButton();\n }\n },\n\n /**\n * Setup PayPal instance\n */\n setupPayPal: function () {\n var self = this;\n\n if (Braintree.config.paypalInstance) {\n fullScreenLoader.stopLoader(true);\n return;\n }\n\n paypalCheckout.create({\n client: Braintree.clientInstance\n }, function (createErr, paypalCheckoutInstance) {\n if (createErr) {\n Braintree.showError($t(\"PayPal Checkout could not be initialized. Please contact the store owner.\"));\n console.error('paypalCheckout error', createErr);\n return;\n }\n let quoteObj = quote.totals();\n\n var configSDK = {\n components: 'buttons,messages,funding-eligibility',\n \"enable-funding\": \"paylater\",\n currency: quoteObj['base_currency_code']\n };\n var merchantCountry = window.checkoutConfig.payment['braintree_paypal'].merchantCountry;\n if (Braintree.getEnvironment() == 'sandbox' && merchantCountry != null) {\n configSDK[\"buyer-country\"] = merchantCountry;\n }\n paypalCheckoutInstance.loadPayPalSDK(configSDK, function () {\n this.loadPayPalButton(paypalCheckoutInstance, 'paypal');\n if (this.isCreditEnabled()) {\n this.loadPayPalButton(paypalCheckoutInstance, 'credit');\n }\n if (this.isPaylaterEnabled()) {\n this.loadPayPalButton(paypalCheckoutInstance, 'paylater');\n }\n\n }.bind(this));\n }.bind(this));\n },\n\n loadPayPalButton: function (paypalCheckoutInstance, funding) {\n var paypalPayment = Braintree.config.paypal,\n onPaymentMethodReceived = Braintree.config.onPaymentMethodReceived;\n var style = {\n color: Braintree.getColor(funding),\n shape: Braintree.getShape(funding),\n size: Braintree.getSize(funding),\n label: Braintree.getLabel(funding)\n };\n\n if (Braintree.getBranding()) {\n style.branding = Braintree.getBranding();\n }\n if (Braintree.getFundingIcons()) {\n style.fundingicons = Braintree.getFundingIcons();\n }\n\n if (funding === 'credit') {\n Braintree.config.buttonId = this.clientConfig.buttonCreditId;\n } else if (funding === 'paylater') {\n Braintree.config.buttonId = this.clientConfig.buttonPaylaterId;\n } else {\n Braintree.config.buttonId = this.clientConfig.buttonPayPalId;\n }\n // Render\n Braintree.config.paypalInstance = paypalCheckoutInstance;\n var events = Braintree.events;\n $('#' + Braintree.config.buttonId).html('');\n\n var button = paypal.Buttons({\n fundingSource: funding,\n env: Braintree.getEnvironment(),\n style: style,\n commit: true,\n locale: Braintree.config.paypal.locale,\n\n onInit: function (data, actions) {\n var agreements = checkoutAgreements().agreements,\n shouldDisableActions = false;\n\n actions.disable();\n\n _.each(agreements, function (item, index) {\n if (checkoutAgreements().isAgreementRequired(item)) {\n var paymentMethodCode = quote.paymentMethod().method,\n inputId = '#agreement_' + paymentMethodCode + '_' + item.agreementId,\n inputEl = document.querySelector(inputId);\n\n\n if (!inputEl.checked) {\n shouldDisableActions = true;\n }\n\n inputEl.addEventListener('change', function (event) {\n if (additionalValidators.validate()) {\n actions.enable();\n } else {\n actions.disable();\n }\n });\n }\n });\n\n if (!shouldDisableActions) {\n actions.enable();\n }\n },\n\n createOrder: function () {\n return paypalCheckoutInstance.createPayment(paypalPayment).catch(function (err) {\n throw err.details.originalError.details.originalError.paymentResource;\n });\n },\n\n onCancel: function (data) {\n console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));\n\n if (typeof events.onCancel === 'function') {\n events.onCancel();\n }\n },\n\n onError: function (err) {\n if (err.errorName === 'VALIDATION_ERROR' && err.errorMessage.indexOf('Value is invalid') !== -1) {\n Braintree.showError($t('Address failed validation. Please check and confirm your City, State, and Postal Code'));\n } else {\n Braintree.showError($t(\"PayPal Checkout could not be initialized. Please contact the store owner.\"));\n }\n Braintree.config.paypalInstance = null;\n console.error('Paypal checkout.js error', err);\n\n if (typeof events.onError === 'function') {\n events.onError(err);\n }\n }.bind(this),\n\n onClick: function (data) {\n if (!quote.isVirtual()) {\n this.clientConfig.paypal.enableShippingAddress = true;\n this.clientConfig.paypal.shippingAddressEditable = false;\n this.clientConfig.paypal.shippingAddressOverride = this.getShippingAddress();\n }\n\n // To check term & conditions input checked - validate additional validators.\n if (!additionalValidators.validate()) {\n return false;\n }\n\n if (typeof events.onClick === 'function') {\n events.onClick(data);\n }\n }.bind(this),\n\n onApprove: function (data, actions) {\n return paypalCheckoutInstance.tokenizePayment(data)\n .then(function (payload) {\n onPaymentMethodReceived(payload);\n });\n }\n\n });\n if (button.isEligible() && $('#' + Braintree.config.buttonId).length) {\n button.render('#' + Braintree.config.buttonId).then(function () {\n Braintree.enableButton();\n if (typeof Braintree.config.onPaymentMethodError === 'function') {\n Braintree.config.onPaymentMethodError();\n }\n }.bind(this)).then(function (data) {\n if (typeof events.onRender === 'function') {\n events.onRender(data);\n }\n });\n }\n },\n\n /**\n * Get locale\n * @returns {String}\n */\n getLocale: function () {\n return window.checkoutConfig.payment[this.getCode()].locale;\n },\n\n /**\n * Is Billing Address required from PayPal side\n * @returns {exports.isRequiredBillingAddress|(function())|boolean}\n */\n isRequiredBillingAddress: function () {\n return window.checkoutConfig.payment[this.getCode()].isRequiredBillingAddress;\n },\n\n /**\n * Get configuration for PayPal\n * @returns {Object}\n */\n getPayPalConfig: function () {\n var totals = quote.totals(),\n config = {},\n isActiveVaultEnabler = this.isActiveVault();\n\n config.paypal = {\n flow: 'checkout',\n amount: parseFloat(this.grandTotalAmount).toFixed(2),\n currency: totals['base_currency_code'],\n locale: this.getLocale(),\n\n /**\n * Triggers on any Braintree error\n */\n onError: function () {\n this.paymentMethodNonce = null;\n },\n\n /**\n * Triggers if browser doesn't support PayPal Checkout\n */\n onUnsupported: function () {\n this.paymentMethodNonce = null;\n }\n };\n\n if (isActiveVaultEnabler) {\n config.paypal.requestBillingAgreement = true;\n }\n\n if (!quote.isVirtual()) {\n config.paypal.enableShippingAddress = true;\n config.paypal.shippingAddressEditable = false;\n config.paypal.shippingAddressOverride = this.getShippingAddress();\n }\n\n if (this.getMerchantName()) {\n config.paypal.displayName = this.getMerchantName();\n }\n\n return config;\n },\n\n /**\n * Get shipping address\n * @returns {Object}\n */\n getShippingAddress: function () {\n var address = quote.shippingAddress();\n\n return {\n recipientName: address.firstname + ' ' + address.lastname,\n line1: address.street[0],\n line2: typeof address.street[2] === 'undefined' ? address.street[1] : address.street[1] + ' ' + address.street[2],\n city: address.city,\n countryCode: address.countryId,\n postalCode: address.postcode,\n state: address.regionCode\n };\n },\n\n /**\n * Get merchant name\n * @returns {String}\n */\n getMerchantName: function () {\n return window.checkoutConfig.payment[this.getCode()].merchantName;\n },\n\n /**\n * Get data\n * @returns {Object}\n */\n getData: function () {\n var data = {\n 'method': this.getCode(),\n 'additional_data': {\n 'payment_method_nonce': this.paymentMethodNonce\n }\n };\n\n data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n this.vaultEnabler.visitAdditionalData(data);\n\n return data;\n },\n\n /**\n * Returns payment acceptance mark image path\n * @returns {String}\n */\n getPaymentAcceptanceMarkSrc: function () {\n return window.checkoutConfig.payment[this.getCode()].paymentAcceptanceMarkSrc;\n },\n\n /**\n * @returns {String}\n */\n getVaultCode: function () {\n return window.checkoutConfig.payment[this.getCode()].vaultCode;\n },\n\n /**\n * Check if need to skip order review\n * @returns {Boolean}\n */\n isSkipOrderReview: function () {\n return window.checkoutConfig.payment[this.getCode()].skipOrderReview;\n },\n\n /**\n * Checks if vault is active\n * @returns {Boolean}\n */\n isActiveVault: function () {\n return this.vaultEnabler.isVaultEnabled() && this.vaultEnabler.isActivePaymentTokenEnabler();\n },\n\n /**\n * Re-init PayPal Auth flow to use Vault\n */\n onVaultPaymentTokenEnablerChange: function () {\n this.clientConfig.paypal.singleUse = !this.isActiveVault();\n this.reInitPayPal();\n },\n\n /**\n * Disable submit button\n */\n disableButton: function () {\n // stop any previous shown loaders\n fullScreenLoader.stopLoader(true);\n fullScreenLoader.startLoader();\n $('[data-button=\"place\"]').attr('disabled', 'disabled');\n },\n\n /**\n * Enable submit button\n */\n enableButton: function () {\n $('[data-button=\"place\"]').removeAttr('disabled');\n fullScreenLoader.stopLoader(true);\n },\n\n /**\n * Triggers when customer click \"Continue to PayPal\" button\n */\n payWithPayPal: function () {\n if (additionalValidators.validate()) {\n Braintree.checkout.paypal.initAuthFlow();\n }\n },\n\n /**\n * Get button id\n * @returns {String}\n */\n getPayPalButtonId: function () {\n return this.clientConfig.buttonPayPalId;\n },\n\n /**\n * Get button id\n * @returns {String}\n */\n getCreditButtonId: function () {\n return this.clientConfig.buttonCreditId;\n },\n\n /**\n * Get button id\n * @returns {String}\n */\n getPaylaterButtonId: function () {\n return this.clientConfig.buttonPaylaterId;\n },\n\n isPaylaterEnabled: function () {\n return window.checkoutConfig.payment['braintree_paypal_paylater']['isActive'];\n },\n\n isPaylaterMessageEnabled: function () {\n return window.checkoutConfig.payment['braintree_paypal_paylater']['isMessageActive'];\n },\n\n getGrandTotalAmount: function () {\n return parseFloat(this.grandTotalAmount).toFixed(2);\n },\n\n isCreditEnabled: function () {\n return window.checkoutConfig.payment['braintree_paypal_credit']['isActive'];\n },\n\n /**\n * Get Message Layout\n * @returns {*}\n */\n getMessagingLayout: function () {\n return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['layout'];\n },\n\n /**\n * Get Message Logo\n * @returns {*}\n */\n getMessagingLogo: function () {\n return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['logo'];\n },\n\n /**\n * Get Message Logo position\n * @returns {*}\n */\n getMessagingLogoPosition: function () {\n return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['logo_position'];\n },\n\n /**\n * Get Message Text Color\n * @returns {*}\n */\n getMessagingTextColor: function () {\n return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['text_color'];\n },\n\n /**\n * Get line items\n * @returns {Array}\n */\n getLineItems: function () {\n let self = this;\n let lineItems = [], storeCredit = 0, giftCardAccount = 0;\n let giftWrappingItems = 0, giftWrappingOrder = 0;\n $.each(quote.totals()['total_segments'], function(segmentsKey, segmentsItem) {\n if (segmentsItem['code'] === 'customerbalance') {\n storeCredit = parseFloat(Math.abs(segmentsItem['value']).toString()).toFixed(2);\n }\n if (segmentsItem['code'] === 'giftcardaccount') {\n giftCardAccount = parseFloat(Math.abs(segmentsItem['value']).toString()).toFixed(2);\n }\n if (segmentsItem['code'] === 'giftwrapping') {\n let extensionAttributes = segmentsItem['extension_attributes'];\n giftWrappingOrder = extensionAttributes['gw_base_price'];\n giftWrappingItems = extensionAttributes['gw_items_base_price'];\n }\n });\n if (this.canSendLineItems()) {\n $.each(quote.getItems(), function(quoteItemKey, quoteItem) {\n if (quoteItem.parent_item_id !== null || 0.0 === quoteItem.price) {\n return true;\n }\n\n let itemName = self.replaceUnsupportedCharacters(quoteItem.name);\n let itemSku = self.replaceUnsupportedCharacters(quoteItem.sku);\n\n let description = '';\n let itemQty = parseFloat(quoteItem.qty);\n let itemUnitAmount = parseFloat(quoteItem.price);\n if (itemQty > Math.floor(itemQty) && itemQty < Math.ceil(itemQty)) {\n description = 'Item quantity is ' + itemQty.toFixed(2) + ' and per unit amount is ' + itemUnitAmount.toFixed(2);\n itemUnitAmount = parseFloat(itemQty * itemUnitAmount);\n itemQty = parseFloat('1');\n }\n\n let lineItemValues = [\n itemName,\n 'debit',\n itemQty.toFixed(2),\n itemUnitAmount.toFixed(2),\n parseFloat(quoteItem.base_tax_amount).toFixed(2),\n itemSku,\n description\n ];\n\n let mappedLineItems = $.map(self.lineItemsArray, function(itemElement, itemIndex) {\n return [[\n self.lineItemsArray[itemIndex],\n lineItemValues[itemIndex]\n ]]\n });\n\n lineItems[quoteItemKey] = Object.fromEntries(mappedLineItems);\n });\n\n /**\n * Adds credit (refund or discount) kind as LineItems for the\n * PayPal transaction if discount amount is greater than 0(Zero)\n * as discountAmount lineItem field is not being used by PayPal.\n *\n * https://developer.paypal.com/braintree/docs/reference/response/transaction-line-item/php#discount_amount\n */\n let baseDiscountAmount = parseFloat(Math.abs(quote.totals()['base_discount_amount']).toString()).toFixed(2);\n if (baseDiscountAmount > 0) {\n let discountLineItem = {\n 'name': 'Discount',\n 'kind': 'credit',\n 'quantity': 1.00,\n 'unitAmount': baseDiscountAmount\n };\n\n lineItems = $.merge(lineItems, [discountLineItem]);\n }\n\n /**\n * Adds shipping as LineItems for the PayPal transaction\n * if shipping amount is greater than 0(Zero) to manage\n * the totals with client-side implementation as there is\n * no any field exist in the client-side implementation\n * to send the shipping amount to the Braintree.\n */\n if (quote.totals()['base_shipping_amount'] > 0) {\n let shippingLineItem = {\n 'name': 'Shipping',\n 'kind': 'debit',\n 'quantity': 1.00,\n 'unitAmount': quote.totals()['base_shipping_amount']\n };\n\n lineItems = $.merge(lineItems, [shippingLineItem]);\n }\n\n /**\n * Adds credit (Store Credit) kind as LineItems for the\n * PayPal transaction if store credit is greater than 0(Zero)\n * to manage the totals with client-side implementation\n */\n if (storeCredit > 0) {\n let storeCreditItem = {\n 'name': 'Store Credit',\n 'kind': 'credit',\n 'quantity': 1.00,\n 'unitAmount': storeCredit\n };\n\n lineItems = $.merge(lineItems, [storeCreditItem]);\n }\n\n /**\n * Adds Gift Wrapping for items as LineItems for the PayPal\n * transaction if it is greater than 0(Zero) to manage\n * the totals with client-side implementation\n */\n if (giftWrappingItems > 0) {\n let gwItems = {\n 'name': 'Gift Wrapping for Items',\n 'kind': 'debit',\n 'quantity': 1.00,\n 'unitAmount': giftWrappingItems\n };\n\n lineItems = $.merge(lineItems, [gwItems]);\n }\n\n /**\n * Adds Gift Wrapping for order as LineItems for the PayPal\n * transaction if it is greater than 0(Zero) to manage\n * the totals with client-side implementation\n */\n if (giftWrappingOrder > 0) {\n let gwOrderItem = {\n 'name': 'Gift Wrapping for Order',\n 'kind': 'debit',\n 'quantity': 1.00,\n 'unitAmount': giftWrappingOrder\n };\n\n lineItems = $.merge(lineItems, [gwOrderItem]);\n }\n\n /**\n * Adds Gift Cards as credit LineItems for the PayPal\n * transaction if it is greater than 0(Zero) to manage\n * the totals with client-side implementation\n */\n if (giftCardAccount > 0) {\n let giftCardItem = {\n 'name': 'Gift Cards',\n 'kind': 'credit',\n 'quantity': 1.00,\n 'unitAmount': giftCardAccount\n };\n\n lineItems = $.merge(lineItems, [giftCardItem]);\n }\n\n if (lineItems.length >= 250) {\n lineItems = [];\n }\n }\n return lineItems;\n },\n\n /**\n * Regex to replace all unsupported characters.\n *\n * @param str\n */\n replaceUnsupportedCharacters: function (str) {\n str.replace('/[^a-zA-Z0-9\\s\\-.\\']/', '');\n return str.substr(0, 127);\n },\n\n /**\n * Can send line items\n *\n * @returns {Boolean}\n */\n canSendLineItems: function () {\n return window.checkoutConfig.payment[this.getCode()].canSendLineItems;\n }\n });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/ach.js":"define(\n [\n 'Magento_Checkout/js/view/payment/default',\n 'ko',\n 'jquery',\n 'braintree',\n 'braintreeDataCollector',\n 'braintreeAch',\n 'PayPal_Braintree/js/form-builder',\n 'Magento_Ui/js/model/messageList',\n 'Magento_Checkout/js/action/select-billing-address',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/model/quote',\n 'mage/translate'\n ],\n function (\n Component,\n ko,\n $,\n braintree,\n dataCollector,\n ach,\n formBuilder,\n messageList,\n selectBillingAddress,\n fullScreenLoader,\n quote,\n $t\n ) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n deviceData: null,\n paymentMethodNonce: null,\n template: 'PayPal_Braintree/payment/ach',\n achInstance: null,\n routingNumber: ko.observable(\"\"),\n accountNumber: ko.observable(\"\"),\n accountType: ko.observable(\"checking\"),\n ownershipType: ko.observable(\"personal\"),\n firstName: ko.observable(\"\"),\n lastName: ko.observable(\"\"),\n businessName: ko.observable(\"\"),\n hasAuthorization: ko.observable(false),\n business: ko.observable(false), // for ownership type\n personal: ko.observable(true) // for ownership type\n },\n\n clickAchBtn: function () {\n if (!this.validateForm('#' + this.getCode() + '-form')) {\n return;\n }\n\n fullScreenLoader.startLoader();\n\n var self = this;\n\n var billingAddress = quote.billingAddress();\n\n let regionCode;\n\n let bankDetails = {\n routingNumber: self.routingNumber(),\n accountNumber: self.accountNumber(),\n accountType: self.accountType(),\n ownershipType: self.ownershipType(),\n billingAddress: {\n streetAddress: billingAddress.street[0],\n extendedAddress: billingAddress.street[1],\n locality: billingAddress.city,\n region: billingAddress.regionCode,\n postalCode: billingAddress.postcode,\n }\n };\n\n if (bankDetails.ownershipType === 'personal') {\n bankDetails.firstName = self.firstName();\n bankDetails.lastName = self.lastName();\n } else {\n bankDetails.businessName = self.businessName();\n }\n\n var mandateText = document.getElementById('braintree-ach-mandate').textContent;\n\n // if no region code is available, lets find one!\n if (typeof billingAddress.regionCode === 'undefined') {\n $.get('/rest/V1/directory/countries/' + billingAddress.countryId).done(function (data) {\n if (typeof data.available_regions !== 'undefined') {\n for (var i = 0; i < data.available_regions.length; ++i) {\n if (data.available_regions[i].id === billingAddress.regionId) {\n regionCode = data.available_regions[i].code;\n bankDetails.billingAddress.region = regionCode;\n self.tokenizeAch(bankDetails, mandateText);\n }\n }\n } else {\n fullScreenLoader.stopLoader();\n self.tokenizeAch(bankDetails, mandateText);\n }\n }).fail(function() {\n fullScreenLoader.stopLoader();\n });\n } else {\n self.tokenizeAch(bankDetails, mandateText);\n }\n },\n\n tokenizeAch: function (bankDetails, mandateText) {\n var self = this;\n this.achInstance.tokenize({\n bankDetails: bankDetails,\n mandateText: mandateText\n }, function (tokenizeErr, tokenizedPayload) {\n if (tokenizeErr) {\n self.setErrorMsg($t('There was an error with the provided bank details. Please check and try again.'));\n self.hasAuthorization(false);\n } else {\n fullScreenLoader.stopLoader();\n self.handleAchSuccess(tokenizedPayload);\n }\n });\n },\n\n getClientToken: function () {\n return window.checkoutConfig.payment[this.getCode()].clientToken;\n },\n\n getCode: function () {\n return 'braintree_ach_direct_debit';\n },\n\n getStoreName: function () {\n return window.checkoutConfig.payment[this.getCode()].storeName;\n },\n\n getData: function () {\n let data = {\n 'method': this.getCode(),\n 'additional_data': {\n 'payment_method_nonce': this.paymentMethodNonce,\n }\n };\n\n data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n return data;\n },\n\n getTitle: function() {\n return 'ACH Direct Debit';\n },\n\n handleAchSuccess: function (payload) {\n this.setPaymentMethodNonce(payload.nonce);\n this.placeOrder();\n },\n\n initialize: function () {\n this._super();\n\n var self = this;\n\n braintree.create({\n authorization: self.getClientToken()\n }, function (clientError, clientInstance) {\n if (clientError) {\n this.setErrorMsg($t('Unable to initialize Braintree Client.'));\n return;\n }\n\n ach.create({\n client: clientInstance\n }, function (achErr, achInstance) {\n if (achErr) {\n self.setErrorMsg($t('Error initializing ACH: %1').replace('%1', achErr));\n return;\n }\n\n self.setAchInstance(achInstance);\n });\n });\n\n return this;\n },\n\n isAllowed: function () {\n return window.checkoutConfig.payment[this.getCode()].isAllowed;\n },\n\n changeOwnershipType: function (data, event) {\n var self = this;\n if (event.currentTarget.value === 'business') {\n self.business(true);\n self.personal(false);\n } else {\n self.business(false);\n self.personal(true);\n }\n },\n\n isBusiness: function () {\n return this.business;\n },\n\n isPersonal: function () {\n return this.personal;\n },\n\n setErrorMsg: function (message) {\n messageList.addErrorMessage({\n message: message\n });\n },\n\n setPaymentMethodNonce: function (nonce) {\n this.paymentMethodNonce = nonce;\n },\n\n setAchInstance: function (instance) {\n this.achInstance = instance;\n },\n\n validateForm: function (form) {\n return $(form).validation() && $(form).validation('isValid');\n }\n });\n }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/cc-form.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine(\n [\n 'underscore',\n 'jquery',\n 'Magento_Payment/js/view/payment/cc-form',\n 'Magento_Checkout/js/model/quote',\n 'PayPal_Braintree/js/view/payment/adapter',\n 'mage/translate',\n 'PayPal_Braintree/js/validator',\n 'PayPal_Braintree/js/view/payment/validator-handler',\n 'Magento_Checkout/js/model/full-screen-loader'\n ],\n function (\n _,\n $,\n Component,\n quote,\n braintree,\n $t,\n validator,\n validatorManager,\n fullScreenLoader\n ) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n active: false,\n braintreeClient: null,\n braintreeDeviceData: null,\n paymentMethodNonce: null,\n lastBillingAddress: null,\n validatorManager: validatorManager,\n code: 'braintree',\n isProcessing: false,\n creditCardBin: null,\n\n /**\n * Additional payment data\n *\n * {Object}\n */\n additionalData: {},\n\n /**\n * Braintree client configuration\n *\n * {Object}\n */\n clientConfig: {\n onReady: function (context) {\n context.setupHostedFields();\n },\n\n /**\n * Triggers on payment nonce receive\n * @param {Object} response\n */\n onPaymentMethodReceived: function (response) {\n this.handleNonce(response);\n this.isProcessing = false;\n },\n\n /**\n * Allow a new nonce to be generated\n */\n onPaymentMethodError: function() {\n this.isProcessing = false;\n },\n\n /**\n * Device data initialization\n * @param {String} deviceData\n */\n onDeviceDataReceived: function (deviceData) {\n this.additionalData['device_data'] = deviceData;\n },\n\n /**\n * After Braintree instance initialization\n */\n onInstanceReady: function () {},\n\n /**\n * Triggers on any Braintree error\n * @param {Object} response\n */\n onError: function (response) {\n this.isProcessing = false;\n braintree.showError($t('Payment ' + this.getTitle() + ' can\\'t be initialized'));\n throw response.message;\n },\n\n /**\n * Triggers when customer click \"Cancel\"\n */\n onCancelled: function () {\n this.paymentMethodNonce = null;\n this.isProcessing = false;\n }\n },\n imports: {\n onActiveChange: 'active'\n }\n },\n\n /**\n * Set list of observable attributes\n *\n * @returns {exports.initObservable}\n */\n initObservable: function () {\n validator.setConfig(window.checkoutConfig.payment[this.getCode()]);\n this._super()\n .observe(['active']);\n this.validatorManager.initialize();\n this.initClientConfig();\n\n return this;\n },\n\n /**\n * Get payment name\n *\n * @returns {String}\n */\n getCode: function () {\n return this.code;\n },\n\n /**\n * Check if payment is active\n *\n * @returns {Boolean}\n */\n isActive: function () {\n let active = this.getCode() === this.isChecked();\n this.active(active);\n\n return active;\n },\n\n /**\n * Triggers when payment method change\n * @param {Boolean} isActive\n */\n onActiveChange: function (isActive) {\n if (!isActive) {\n return;\n }\n\n this.initBraintree();\n },\n\n /**\n * Init config\n */\n initClientConfig: function () {\n _.each(this.clientConfig, function (fn, name) {\n if (typeof fn === 'function') {\n this.clientConfig[name] = fn.bind(this);\n }\n }, this);\n },\n\n /**\n * Init Braintree configuration\n */\n initBraintree: function () {\n let intervalId = setInterval(function () {\n // stop loader when frame will be loaded\n if ($('#braintree-hosted-field-number').length) {\n clearInterval(intervalId);\n fullScreenLoader.stopLoader(true);\n }\n }, 500);\n\n if (braintree.checkout) {\n braintree.checkout.teardown(function () {\n braintree.checkout = null;\n });\n }\n\n fullScreenLoader.startLoader();\n braintree.setConfig(this.clientConfig);\n braintree.setup();\n },\n\n /**\n * Get full selector name\n *\n * @param {String} field\n * @returns {String}\n */\n getSelector: function (field) {\n return '#' + this.getCode() + '_' + field;\n },\n\n /**\n * Get list of available CC types\n *\n * @returns {Object}\n */\n getCcAvailableTypes: function () {\n let availableTypes = validator.getAvailableCardTypes(),\n billingAddress = quote.billingAddress(),\n billingCountryId;\n\n this.lastBillingAddress = quote.shippingAddress();\n\n if (!billingAddress) {\n billingAddress = this.lastBillingAddress;\n }\n\n billingCountryId = billingAddress.countryId;\n\n if (billingCountryId && validator.getCountrySpecificCardTypes(billingCountryId)) {\n return validator.collectTypes(\n availableTypes,\n validator.getCountrySpecificCardTypes(billingCountryId)\n );\n }\n\n return availableTypes;\n },\n\n /**\n * @returns {String}\n */\n getEnvironment: function () {\n return window.checkoutConfig.payment[this.getCode()].environment;\n },\n\n /**\n * Get data\n *\n * @returns {Object}\n */\n getData: function () {\n let data = {\n 'method': this.getCode(),\n 'additional_data': {\n 'payment_method_nonce': this.paymentMethodNonce,\n 'g-recaptcha-response' : $(\"#token-grecaptcha-braintree\").val()\n }\n };\n\n data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n return data;\n },\n\n /**\n * Set payment nonce\n * @param {String} paymentMethodNonce\n */\n setPaymentMethodNonce: function (paymentMethodNonce) {\n this.paymentMethodNonce = paymentMethodNonce;\n },\n\n /**\n * Set credit card bin\n * @param creditCardBin\n */\n setCreditCardBin: function (creditCardBin) {\n this.creditCardBin = creditCardBin;\n },\n\n /**\n * Prepare payload to place order\n * @param {Object} payload\n */\n handleNonce: function (payload) {\n let self = this;\n\n this.setPaymentMethodNonce(payload.nonce);\n this.setCreditCardBin(payload.details.bin);\n\n // place order on success validation\n self.validatorManager.validate(self, function () {\n return self.placeOrder('parent');\n }, function() {\n self.isProcessing = false;\n self.paymentMethodNonce = null;\n self.creditCardBin = null;\n });\n },\n\n /**\n * Action to place order\n * @param {String} key\n */\n placeOrder: function (key) {\n if (key) {\n return this._super();\n }\n\n if (this.isProcessing) {\n return false;\n } else {\n this.isProcessing = true;\n }\n\n braintree.tokenizeHostedFields();\n return false;\n },\n\n /**\n * Get payment icons\n * @param {String} type\n * @returns {Boolean}\n */\n getIcons: function (type) {\n return window.checkoutConfig.payment.braintree.icons.hasOwnProperty(type) ?\n window.checkoutConfig.payment.braintree.icons[type]\n : false;\n },\n });\n }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/paypal-vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n 'jquery',\n 'underscore',\n 'Magento_Vault/js/view/payment/method-renderer/vault',\n 'Magento_Ui/js/model/messageList',\n 'Magento_Checkout/js/model/full-screen-loader'\n], function ($, _, VaultComponent, globalMessageList, fullScreenLoader) {\n 'use strict';\n\n return VaultComponent.extend({\n defaults: {\n template: 'PayPal_Braintree/payment/paypal/vault',\n additionalData: {}\n },\n\n /**\n * Get PayPal payer email\n * @returns {String}\n */\n getPayerEmail: function () {\n return this.details.payerEmail;\n },\n\n /**\n * Get type of payment\n * @returns {String}\n */\n getPaymentIcon: function () {\n return window.checkoutConfig.payment['braintree_paypal'].paymentIcon;\n },\n\n /**\n * Place order\n */\n beforePlaceOrder: function () {\n this.getPaymentMethodNonce();\n },\n\n /**\n * Send request to get payment method nonce\n */\n getPaymentMethodNonce: function () {\n var self = this;\n\n fullScreenLoader.startLoader();\n $.getJSON(self.nonceUrl, {\n 'public_hash': self.publicHash\n })\n .done(function (response) {\n fullScreenLoader.stopLoader();\n self.additionalData['payment_method_nonce'] = response.paymentMethodNonce;\n self.placeOrder();\n })\n .fail(function (response) {\n var error = JSON.parse(response.responseText);\n\n fullScreenLoader.stopLoader();\n globalMessageList.addErrorMessage({\n message: error.message\n });\n });\n },\n\n /**\n * Get payment method data\n * @returns {Object}\n */\n getData: function () {\n var data = {\n 'method': this.code,\n 'additional_data': {\n 'public_hash': this.publicHash\n }\n };\n\n data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n return data;\n }\n });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/hosted-fields.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\n\ndefine([\n 'jquery',\n 'PayPal_Braintree/js/view/payment/method-renderer/cc-form',\n 'PayPal_Braintree/js/validator',\n 'Magento_Vault/js/view/payment/vault-enabler',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'mage/translate'\n], function ($, Component, validator, VaultEnabler, additionalValidators, $t) {\n 'use strict';\n\n return Component.extend({\n\n defaults: {\n template: 'PayPal_Braintree/payment/form',\n clientConfig: {\n\n /**\n * {String}\n */\n id: 'co-transparent-form-braintree'\n },\n isValidCardNumber: false,\n isValidExpirationDate: false,\n isValidCvvNumber: false,\n\n onInstanceReady: function (instance) {\n instance.on('validityChange', this.onValidityChange.bind(this));\n instance.on('cardTypeChange', this.onCardTypeChange.bind(this));\n }\n },\n\n /**\n * @returns {exports.initialize}\n */\n initialize: function () {\n this._super();\n this.vaultEnabler = new VaultEnabler();\n this.vaultEnabler.setPaymentCode(this.getVaultCode());\n\n return this;\n },\n\n /**\n * Init config\n */\n initClientConfig: function () {\n this._super();\n\n this.clientConfig.hostedFields = this.getHostedFields();\n this.clientConfig.onInstanceReady = this.onInstanceReady.bind(this);\n },\n\n /**\n * @returns {Object}\n */\n getData: function () {\n var data = this._super();\n\n this.vaultEnabler.visitAdditionalData(data);\n\n return data;\n },\n\n /**\n * @returns {Bool}\n */\n isVaultEnabled: function () {\n return this.vaultEnabler.isVaultEnabled();\n },\n\n /**\n * Get Braintree Hosted Fields\n * @returns {Object}\n */\n getHostedFields: function () {\n var self = this,\n fields = {\n number: {\n selector: self.getSelector('cc_number'),\n placeholder: $t('4111 1111 1111 1111')\n },\n expirationDate: {\n selector: self.getSelector('expirationDate'),\n placeholder: $t('MM/YYYY')\n }\n };\n\n if (self.hasVerification()) {\n fields.cvv = {\n selector: self.getSelector('cc_cid'),\n placeholder: $t('123')\n };\n }\n\n return fields;\n },\n\n /**\n * Triggers on Hosted Field changes\n * @param {Object} event\n * @returns {Boolean}\n */\n onValidityChange: function (event) {\n // Handle a change in validation or card type\n if (event.emittedBy === 'number') {\n this.selectedCardType(null);\n\n if (event.cards.length === 1) {\n this.isValidCardNumber = event.fields.number.isValid;\n this.selectedCardType(\n validator.getMageCardType(event.cards[0].type, this.getCcAvailableTypes())\n );\n this.validateCardType();\n } else {\n this.isValidCardNumber = event.fields.number.isValid;\n this.validateCardType();\n }\n }\n\n // Other field validations\n if (event.emittedBy === 'expirationDate') {\n this.isValidExpirationDate = event.fields.expirationDate.isValid;\n }\n if (event.emittedBy === 'cvv') {\n this.isValidCvvNumber = event.fields.cvv.isValid;\n }\n },\n\n /**\n * Triggers on Hosted Field card type changes\n * @param {Object} event\n * @returns {Boolean}\n */\n onCardTypeChange: function (event) {\n if (event.cards.length === 1) {\n this.selectedCardType(\n validator.getMageCardType(event.cards[0].type, this.getCcAvailableTypes())\n );\n } else {\n this.selectedCardType(null);\n }\n },\n\n /**\n * Toggle invalid class on selector\n * @param selector\n * @param state\n * @returns {boolean}\n */\n validateField: function (selector, state) {\n var $selector = $(this.getSelector(selector)),\n invalidClass = 'braintree-hosted-fields-invalid';\n\n if (state === true) {\n $selector.removeClass(invalidClass);\n return true;\n }\n\n $selector.addClass(invalidClass);\n return false;\n },\n\n /**\n * Validate current credit card type\n * @returns {Boolean}\n */\n validateCardType: function () {\n return this.validateField(\n 'cc_number',\n (this.isValidCardNumber)\n );\n },\n\n /**\n * Validate current expiry date\n * @returns {boolean}\n */\n validateExpirationDate: function () {\n return this.validateField(\n 'expirationDate',\n (this.isValidExpirationDate === true)\n );\n },\n\n /**\n * Validate current CVV field\n * @returns {boolean}\n */\n validateCvvNumber: function () {\n var self = this;\n\n if (self.hasVerification() === false) {\n return true;\n }\n\n return this.validateField(\n 'cc_cid',\n (this.isValidCvvNumber === true)\n );\n },\n\n /**\n * Validate all fields\n * @returns {boolean}\n */\n validateFormFields: function () {\n return (this.validateCardType() && this.validateExpirationDate() && this.validateCvvNumber()) === true;\n },\n\n /**\n * Trigger order placing\n */\n placeOrderClick: function () {\n if (this.validateFormFields() && additionalValidators.validate()) {\n this.placeOrder();\n }\n },\n /**\n * @returns {String}\n */\n getVaultCode: function () {\n return window.checkoutConfig.payment[this.getCode()].ccVaultCode;\n }\n });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/lpm.js":"define(\n [\n 'Magento_Checkout/js/view/payment/default',\n 'ko',\n 'jquery',\n 'braintree',\n 'braintreeLpm',\n 'PayPal_Braintree/js/form-builder',\n 'Magento_Ui/js/model/messageList',\n 'Magento_Checkout/js/action/select-billing-address',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'mage/url',\n 'mage/translate'\n ],\n function (\n Component,\n ko,\n $,\n braintree,\n lpm,\n formBuilder,\n messageList,\n selectBillingAddress,\n fullScreenLoader,\n quote,\n additionalValidators,\n url,\n $t\n ) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n code: 'braintree_local_payment',\n paymentMethodsAvailable: ko.observable(false),\n paymentMethodNonce: null,\n template: 'PayPal_Braintree/payment/lpm'\n },\n\n clickPaymentBtn: function (method) {\n var self = this;\n\n if (additionalValidators.validate()) {\n fullScreenLoader.startLoader();\n\n braintree.create({\n authorization: self.getClientToken()\n }, function (clientError, clientInstance) {\n if (clientError) {\n self.setErrorMsg($t('Unable to initialize Braintree Client.'));\n fullScreenLoader.stopLoader();\n return;\n }\n\n lpm.create({\n client: clientInstance,\n merchantAccountId: self.getMerchantAccountId()\n }, function (lpmError, lpmInstance) {\n if (lpmError) {\n self.setErrorMsg(lpmError);\n fullScreenLoader.stopLoader();\n return;\n }\n\n lpmInstance.startPayment({\n amount: self.getAmount(),\n currencyCode: self.getCurrencyCode(),\n email: self.getCustomerDetails().email,\n phone: self.getCustomerDetails().phone,\n givenName: self.getCustomerDetails().firstName,\n surname: self.getCustomerDetails().lastName,\n shippingAddressRequired: !quote.isVirtual(),\n address: self.getAddress(),\n paymentType: method,\n onPaymentStart: function (data, start) {\n start();\n },\n // This is a required option, however it will apparently never be used in the current payment flow.\n // Therefore, both values are set to allow the payment flow to continute, rather than erroring out.\n fallback: {\n url: 'N/A',\n buttonText: 'N/A'\n }\n }, function (startPaymentError, payload) {\n fullScreenLoader.stopLoader();\n if (startPaymentError) {\n switch (startPaymentError.code) {\n case 'LOCAL_PAYMENT_POPUP_CLOSED':\n self.setErrorMsg($t('Local Payment popup was closed unexpectedly.'));\n break;\n case 'LOCAL_PAYMENT_WINDOW_OPEN_FAILED':\n self.setErrorMsg($t('Local Payment popup failed to open.'));\n break;\n case 'LOCAL_PAYMENT_WINDOW_CLOSED':\n self.setErrorMsg($t('Local Payment popup was closed. Payment cancelled.'));\n break;\n default:\n self.setErrorMsg('Error! ' + startPaymentError);\n break;\n }\n } else {\n // Send the nonce to your server to create a transaction\n self.setPaymentMethodNonce(payload.nonce);\n self.placeOrder();\n }\n });\n });\n });\n }\n },\n\n getAddress: function () {\n var shippingAddress = quote.shippingAddress();\n\n if (quote.isVirtual()) {\n return {\n countryCode: shippingAddress.countryId\n }\n }\n\n return {\n streetAddress: shippingAddress.street[0],\n extendedAddress: shippingAddress.street[1],\n locality: shippingAddress.city,\n postalCode: shippingAddress.postcode,\n region: shippingAddress.region,\n countryCode: shippingAddress.countryId\n }\n },\n\n getAmount: function () {\n return quote.totals()['base_grand_total'].toString();\n },\n\n getBillingAddress: function () {\n return quote.billingAddress();\n },\n\n getClientToken: function () {\n return window.checkoutConfig.payment[this.getCode()].clientToken;\n },\n\n getCode: function () {\n return this.code;\n },\n\n getCurrencyCode: function () {\n return quote.totals()['base_currency_code'];\n },\n\n getCustomerDetails: function () {\n var billingAddress = quote.billingAddress();\n return {\n firstName: billingAddress.firstname,\n lastName: billingAddress.lastname,\n phone: billingAddress.telephone,\n email: typeof quote.guestEmail === 'string' ? quote.guestEmail : window.checkoutConfig.customerData.email\n }\n },\n\n getData: function () {\n let data = {\n 'method': this.getCode(),\n 'additional_data': {\n 'payment_method_nonce': this.paymentMethodNonce,\n }\n };\n\n data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n return data;\n },\n\n getMerchantAccountId: function () {\n return window.checkoutConfig.payment[this.getCode()].merchantAccountId;\n },\n\n getPaymentMethod: function (method) {\n var methods = this.getPaymentMethods();\n\n for (var i = 0; i < methods.length; i++) {\n if (methods[i].method === method) {\n return methods[i]\n }\n }\n },\n\n getPaymentMethods: function () {\n return window.checkoutConfig.payment[this.getCode()].allowedMethods;\n },\n\n getPaymentMarkSrc: function () {\n return window.checkoutConfig.payment[this.getCode()].paymentIcons;\n },\n\n getTitle: function () {\n return window.checkoutConfig.payment[this.getCode()].title;\n },\n\n initialize: function () {\n this._super();\n return this;\n },\n\n isActive: function () {\n var address = quote.billingAddress() || quote.shippingAddress();\n var methods = this.getPaymentMethods();\n\n for (var i = 0; i < methods.length; i++) {\n if (methods[i].countries.includes(address.countryId)) {\n return true;\n }\n }\n\n return false;\n },\n\n isValidCountryAndCurrency: function (method) {\n var address = quote.billingAddress();\n\n if (!address) {\n this.paymentMethodsAvailable(false);\n return false;\n }\n\n var countryId = address.countryId;\n var quoteCurrency = quote.totals()['base_currency_code'];\n var paymentMethodDetails = this.getPaymentMethod(method);\n\n if ((countryId !== 'GB' && paymentMethodDetails.countries.includes(countryId) && (quoteCurrency === 'EUR' || quoteCurrency === 'PLN')) || (countryId === 'GB' && paymentMethodDetails.countries.includes(countryId) && quoteCurrency === 'GBP')) {\n this.paymentMethodsAvailable(true);\n return true;\n }\n\n return false;\n },\n\n setErrorMsg: function (message) {\n messageList.addErrorMessage({\n message: message\n });\n },\n\n setPaymentMethodNonce: function (nonce) {\n this.paymentMethodNonce = nonce;\n },\n\n validateForm: function (form) {\n return $(form).validation() && $(form).validation('isValid');\n }\n });\n }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/multishipping/paypal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n 'jquery',\n 'underscore',\n 'braintreeCheckoutPayPalAdapter',\n 'Magento_Checkout/js/model/quote',\n 'PayPal_Braintree/js/view/payment/method-renderer/paypal',\n 'Magento_Checkout/js/action/set-payment-information',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'mage/translate'\n], function (\n $,\n _,\n Braintree,\n quote,\n Component,\n setPaymentInformationAction,\n additionalValidators,\n fullScreenLoader,\n $t\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'PayPal_Braintree/payment/multishipping/paypal',\n submitButtonSelector: '[id=\"parent-payment-continue\"]',\n reviewButtonHtml: ''\n },\n\n /**\n * @override\n */\n initObservable: function () {\n this.reviewButtonHtml = $(this.submitButtonSelector).html();\n return this._super();\n },\n\n initClientConfig: function () {\n this.clientConfig = _.extend(this.clientConfig, this.getPayPalConfig());\n this.clientConfig.paypal.enableShippingAddress = false;\n\n _.each(this.clientConfig, function (fn, name) {\n if (typeof fn === 'function') {\n this.clientConfig[name] = fn.bind(this);\n }\n }, this);\n this.clientConfig.buttonPayPalId = 'parent-payment-continue';\n\n },\n\n /**\n * @override\n */\n onActiveChange: function (isActive) {\n this.updateSubmitButtonHtml(isActive);\n this._super(isActive);\n },\n\n /**\n * @override\n */\n beforePlaceOrder: function (data) {\n this._super(data);\n },\n\n /**\n * Re-init PayPal Auth Flow\n */\n reInitPayPal: function () {\n this.disableButton();\n this.clientConfig.paypal.amount = parseFloat(this.grandTotalAmount).toFixed(2);\n\n if (!quote.isVirtual()) {\n this.clientConfig.paypal.enableShippingAddress = false;\n this.clientConfig.paypal.shippingAddressEditable = false;\n }\n\n Braintree.setConfig(this.clientConfig);\n\n if (Braintree.getPayPalInstance()) {\n Braintree.getPayPalInstance().teardown(function () {\n Braintree.setup();\n }.bind(this));\n Braintree.setPayPalInstance(null);\n } else {\n Braintree.setup();\n this.enableButton();\n }\n },\n\n loadPayPalButton: function (paypalCheckoutInstance, funding) {\n let paypalPayment = Braintree.config.paypal,\n onPaymentMethodReceived = Braintree.config.onPaymentMethodReceived;\n let style = {\n color: Braintree.getColor(funding),\n shape: Braintree.getShape(funding),\n size: Braintree.getSize(funding),\n label: Braintree.getLabel(funding)\n };\n\n if (Braintree.getBranding()) {\n style.branding = Braintree.getBranding();\n }\n if (Braintree.getFundingIcons()) {\n style.fundingicons = Braintree.getFundingIcons();\n }\n\n if (funding === 'credit') {\n Braintree.config.buttonId = this.clientConfig.buttonCreditId;\n } else if (funding === 'paylater') {\n Braintree.config.buttonId = this.clientConfig.buttonPaylaterId;\n } else {\n Braintree.config.buttonId = this.clientConfig.buttonPayPalId;\n }\n\n // Render\n Braintree.config.paypalInstance = paypalCheckoutInstance;\n var events = Braintree.events;\n $('#' + Braintree.config.buttonId).html('');\n\n var button = paypal.Buttons({\n fundingSource: funding,\n env: Braintree.getEnvironment(),\n style: style,\n commit: true,\n locale: Braintree.config.paypal.locale,\n\n createOrder: function () {\n return paypalCheckoutInstance.createPayment(paypalPayment);\n },\n\n onCancel: function (data) {\n console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));\n\n if (typeof events.onCancel === 'function') {\n events.onCancel();\n }\n },\n\n onError: function (err) {\n Braintree.showError($t(\"PayPal Checkout could not be initialized. Please contact the store owner.\"));\n Braintree.config.paypalInstance = null;\n console.error('Paypal checkout.js error', err);\n\n if (typeof events.onError === 'function') {\n events.onError(err);\n }\n }.bind(this),\n\n onClick: function (data) {\n // To check term & conditions input checked - validate additional validators.\n if (!additionalValidators.validate()) {\n return false;\n }\n\n if (typeof events.onClick === 'function') {\n events.onClick(data);\n }\n }.bind(this),\n\n onApprove: function (data, actions) {\n return paypalCheckoutInstance.tokenizePayment(data)\n .then(function (payload) {\n onPaymentMethodReceived(payload);\n });\n }\n\n });\n if (button.isEligible() && $('#' + Braintree.config.buttonId).length) {\n\n button.render('#' + Braintree.config.buttonId).then(function () {\n Braintree.enableButton();\n if (typeof Braintree.config.onPaymentMethodError === 'function') {\n Braintree.config.onPaymentMethodError();\n }\n }.bind(this)).then(function (data) {\n if (typeof events.onRender === 'function') {\n events.onRender(data);\n }\n });\n }\n },\n\n /**\n * Get configuration for PayPal\n * @returns {Object}\n */\n getPayPalConfig: function () {\n var totals = quote.totals(),\n config = {},\n isActiveVaultEnabler = this.isActiveVault();\n\n config.paypal = {\n flow: 'checkout',\n amount: parseFloat(this.grandTotalAmount).toFixed(2),\n currency: totals['base_currency_code'],\n locale: this.getLocale(),\n requestBillingAgreement: true,\n /**\n * Triggers on any Braintree error\n */\n onError: function () {\n this.paymentMethodNonce = null;\n },\n\n /**\n * Triggers if browser doesn't support PayPal Checkout\n */\n onUnsupported: function () {\n this.paymentMethodNonce = null;\n }\n };\n\n if (!quote.isVirtual()) {\n config.paypal.enableShippingAddress = false;\n config.paypal.shippingAddressEditable = false;\n }\n\n if (this.getMerchantName()) {\n config.paypal.displayName = this.getMerchantName();\n }\n\n return config;\n },\n\n getShippingAddress: function () {\n\n return {};\n },\n\n /**\n * @override\n */\n getData: function () {\n var data = this._super();\n\n data['additional_data']['is_active_payment_token_enabler'] = true;\n\n return data;\n },\n\n /**\n * @override\n */\n isActiveVault: function () {\n return true;\n },\n\n /**\n * Skipping order review step on checkout with multiple addresses is not allowed.\n *\n * @returns {Boolean}\n */\n isSkipOrderReview: function () {\n return false;\n },\n\n /**\n * Checks if payment method nonce is already received.\n *\n * @returns {Boolean}\n */\n isPaymentMethodNonceReceived: function () {\n return this.paymentMethodNonce !== null;\n },\n\n /**\n * Update submit button on multi-addresses checkout billing form.\n *\n * @param {Boolean} isActive\n */\n updateSubmitButtonHtml: function (isActive) {\n $(this.submitButtonSelector).removeClass(\"primary\");\n if (this.isPaymentMethodNonceReceived() || !isActive) {\n $(this.submitButtonSelector).addClass(\"primary\");\n $(this.submitButtonSelector).html(this.reviewButtonHtml);\n }\n },\n\n /**\n * @override\n */\n placeOrder: function () {\n if (!this.isPaymentMethodNonceReceived()) {\n this.payWithPayPal();\n } else {\n fullScreenLoader.startLoader();\n\n $.when(\n setPaymentInformationAction(\n this.messageContainer,\n this.getData()\n )\n ).done(this.done.bind(this))\n .fail(this.fail.bind(this));\n }\n },\n\n /**\n * {Function}\n */\n fail: function () {\n fullScreenLoader.stopLoader();\n\n return this;\n },\n\n /**\n * {Function}\n */\n done: function () {\n fullScreenLoader.stopLoader();\n $('#multishipping-billing-form').submit();\n\n return this;\n }\n });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/multishipping/hosted-fields.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\n\ndefine([\n 'jquery',\n 'PayPal_Braintree/js/view/payment/method-renderer/hosted-fields',\n 'PayPal_Braintree/js/validator',\n 'Magento_Ui/js/model/messageList',\n 'mage/translate',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/action/set-payment-information',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'PayPal_Braintree/js/view/payment/adapter'\n], function (\n $,\n Component,\n validator,\n messageList,\n $t,\n fullScreenLoader,\n setPaymentInformationAction,\n additionalValidators,\n braintree\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'PayPal_Braintree/payment/multishipping/form'\n },\n\n /**\n * Get list of available CC types\n *\n * @returns {Object}\n */\n getCcAvailableTypes: function () {\n let availableTypes = validator.getAvailableCardTypes(),\n billingCountryId;\n\n billingCountryId = $('#multishipping_billing_country_id').val();\n\n if (billingCountryId && validator.getCountrySpecificCardTypes(billingCountryId)) {\n return validator.collectTypes(\n availableTypes, validator.getCountrySpecificCardTypes(billingCountryId)\n );\n }\n\n return availableTypes;\n },\n\n /**\n * @override\n */\n handleNonce: function (payload) {\n let self = this;\n this.setPaymentMethodNonce(payload.nonce);\n this.setCreditCardBin(payload.details.bin);\n\n // place order on success validation\n self.validatorManager.validate(self, function () {\n return self.setPaymentInformation();\n }, function() {\n self.isProcessing = false;\n self.paymentMethodNonce = null;\n self.creditCardBin = null;\n });\n },\n\n /**\n * @override\n */\n placeOrder: function () {\n if (this.isProcessing) {\n return false;\n } else {\n this.isProcessing = true;\n }\n\n braintree.tokenizeHostedFields();\n return false;\n },\n\n /**\n * @override\n */\n setPaymentInformation: function () {\n if (additionalValidators.validate()) {\n fullScreenLoader.startLoader();\n $.when(\n setPaymentInformationAction(\n this.messageContainer,\n this.getData()\n )\n ).done(this.done.bind(this))\n .fail(this.fail.bind(this));\n }\n },\n\n /**\n * {Function}\n */\n fail: function () {\n fullScreenLoader.stopLoader();\n\n return this;\n },\n\n /**\n * {Function}\n */\n done: function () {\n fullScreenLoader.stopLoader();\n $('#multishipping-billing-form').submit();\n\n return this;\n }\n });\n});\n","PayPal_Braintree/js/applepay/api.js":"/**\n * Braintree Apple Pay button API\n *\n **/\ndefine(\n [\n 'jquery',\n 'underscore',\n 'uiComponent',\n 'mage/translate',\n 'mage/storage',\n 'Magento_Customer/js/customer-data'\n ],\n function (\n $,\n _,\n Component,\n $t,\n storage,\n customerData\n ) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n clientToken: null,\n quoteId: 0,\n displayName: null,\n actionSuccess: null,\n grandTotalAmount: 0,\n isLoggedIn: false,\n storeCode: \"default\",\n shippingAddress: {},\n countryDirectory: null,\n shippingMethods: {}\n },\n\n initialize: function () {\n this._super();\n if (!this.countryDirectory) {\n storage.get(\"rest/V1/directory/countries\").done(function (result) {\n this.countryDirectory = {};\n let i, data, x, region;\n for (i = 0; i < result.length; ++i) {\n data = result[i];\n this.countryDirectory[data.two_letter_abbreviation] = {};\n if (typeof data.available_regions !== 'undefined') {\n for (x = 0; x < data.available_regions.length; ++x) {\n region = data.available_regions[x];\n this.countryDirectory[data.two_letter_abbreviation][region.name.toLowerCase().replace(/[^A-Z0-9]/ig, '')] = region.id;\n }\n }\n }\n }.bind(this));\n }\n },\n\n /**\n * Get region ID\n */\n getRegionId: function (countryCode, regionName) {\n if (typeof regionName !== 'string') {\n return null;\n }\n\n regionName = regionName.toLowerCase().replace(/[^A-Z0-9]/ig, '');\n\n if (typeof this.countryDirectory[countryCode] !== 'undefined' && typeof this.countryDirectory[countryCode][regionName] !== 'undefined') {\n return this.countryDirectory[countryCode][regionName];\n }\n\n return 0;\n },\n\n /**\n * Set & get api token\n */\n setClientToken: function (value) {\n this.clientToken = value;\n },\n getClientToken: function () {\n return this.clientToken;\n },\n\n /**\n * Set and get quote id\n */\n setQuoteId: function (value) {\n this.quoteId = value;\n },\n getQuoteId: function () {\n return this.quoteId;\n },\n\n /**\n * Set and get display name\n */\n setDisplayName: function (value) {\n this.displayName = value;\n },\n getDisplayName: function () {\n return this.displayName;\n },\n\n /**\n * Set and get success redirection url\n */\n setActionSuccess: function (value) {\n this.actionSuccess = value;\n },\n getActionSuccess: function () {\n return this.actionSuccess;\n },\n\n /**\n * Set and get grand total\n */\n setGrandTotalAmount: function (value) {\n this.grandTotalAmount = parseFloat(value).toFixed(2);\n },\n getGrandTotalAmount: function () {\n return parseFloat(this.grandTotalAmount);\n },\n\n /**\n * Set and get is logged in\n */\n setIsLoggedIn: function (value) {\n this.isLoggedIn = value;\n },\n getIsLoggedIn: function () {\n return this.isLoggedIn;\n },\n\n /**\n * Set and get store code\n */\n setStoreCode: function (value) {\n this.storeCode = value;\n },\n getStoreCode: function () {\n return this.storeCode;\n },\n\n /**\n * API Urls for logged in / guest\n */\n getApiUrl: function (uri) {\n if (this.getIsLoggedIn() === true) {\n return \"rest/\" + this.getStoreCode() + \"/V1/carts/mine/\" + uri;\n } else {\n return \"rest/\" + this.getStoreCode() + \"/V1/guest-carts/\" + this.getQuoteId() + \"/\" + uri;\n }\n },\n\n /**\n * Payment request info\n */\n getPaymentRequest: function () {\n return {\n total: {\n label: this.getDisplayName(),\n amount: this.getGrandTotalAmount()\n },\n requiredShippingContactFields: ['postalAddress', 'name', 'email', 'phone'],\n requiredBillingContactFields: ['postalAddress', 'name']\n };\n },\n\n /**\n * Retrieve shipping methods based on address\n */\n onShippingContactSelect: function (event, session) {\n // Get the address.\n let address = event.shippingContact;\n\n // Create a payload.\n let payload = {\n address: {\n city: address.locality,\n region: address.administrativeArea,\n country_id: address.countryCode.toUpperCase(),\n postcode: address.postalCode,\n save_in_address_book: 0\n }\n };\n\n this.shippingAddress = payload.address;\n\n // POST to endpoint for shipping methods.\n storage.post(\n this.getApiUrl(\"estimate-shipping-methods\"),\n JSON.stringify(payload)\n ).done(function (result) {\n // Stop if no shipping methods.\n let virtualFlag = false;\n if (result.length === 0) {\n let productItems = customerData.get('cart')().items;\n _.each(productItems,\n function (item) {\n if (item.is_virtual || item.product_type == 'bundle') {\n virtualFlag = true;\n } else {\n virtualFlag = false;\n }\n }\n );\n if (!virtualFlag) {\n session.abort();\n alert($t(\"There are no shipping methods available for you right now. Please try again or use an alternative payment method.\"));\n return false;\n }\n }\n\n let shippingMethods = [];\n this.shippingMethods = {};\n\n // Format shipping methods array.\n for (let i = 0; i < result.length; i++) {\n if (typeof result[i].method_code !== 'string') {\n continue;\n }\n\n let method = {\n identifier: result[i].method_code,\n label: result[i].method_title,\n detail: result[i].carrier_title ? result[i].carrier_title : \"\",\n amount: parseFloat(result[i].amount).toFixed(2)\n };\n\n // Add method object to array.\n shippingMethods.push(method);\n\n this.shippingMethods[result[i].method_code] = result[i];\n\n if (!this.shippingMethod) {\n this.shippingMethod = result[i].method_code;\n }\n }\n\n // Create payload to get totals\n let totalsPayload = {\n \"addressInformation\": {\n \"address\": {\n \"countryId\": this.shippingAddress.country_id,\n \"region\": this.shippingAddress.region,\n \"regionId\": this.getRegionId(this.shippingAddress.country_id, this.shippingAddress.region),\n \"postcode\": this.shippingAddress.postcode\n },\n \"shipping_method_code\": virtualFlag ? null : this.shippingMethods[shippingMethods[0].identifier].method_code,\n \"shipping_carrier_code\": virtualFlag ? null : this.shippingMethods[shippingMethods[0].identifier].carrier_code\n }\n };\n\n // POST to endpoint to get totals, using 1st shipping method\n storage.post(\n this.getApiUrl(\"totals-information\"),\n JSON.stringify(totalsPayload)\n ).done(function (result) {\n // Set total\n this.setGrandTotalAmount(result.base_grand_total);\n\n // Pass shipping methods back\n session.completeShippingContactSelection(\n ApplePaySession.STATUS_SUCCESS,\n shippingMethods,\n {\n label: this.getDisplayName(),\n amount: this.getGrandTotalAmount()\n },\n [{\n type: 'final',\n label: $t('Shipping'),\n amount: virtualFlag ? 0 : shippingMethods[0].amount\n }]\n );\n }.bind(this)).fail(function (result) {\n session.abort();\n alert($t(\"We're unable to fetch the cart totals for you. Please try an alternative payment method.\"));\n console.error(\"Braintree ApplePay: Unable to get totals\", result);\n return false;\n });\n\n }.bind(this)).fail(function (result) {\n session.abort();\n alert($t(\"We're unable to find any shipping methods for you. Please try an alternative payment method.\"));\n console.error(\"Braintree ApplePay: Unable to find shipping methods for estimate-shipping-methods\", result);\n return false;\n });\n },\n\n /**\n * Record which shipping method has been selected & Updated totals\n */\n onShippingMethodSelect: function (event, session) {\n let shippingMethod = event.shippingMethod;\n this.shippingMethod = shippingMethod.identifier;\n\n let payload = {\n \"addressInformation\": {\n \"address\": {\n \"countryId\": this.shippingAddress.country_id,\n \"region\": this.shippingAddress.region,\n \"regionId\": this.getRegionId(this.shippingAddress.country_id, this.shippingAddress.region),\n \"postcode\": this.shippingAddress.postcode\n },\n \"shipping_method_code\": this.shippingMethods[this.shippingMethod].method_code,\n \"shipping_carrier_code\": this.shippingMethods[this.shippingMethod].carrier_code\n }\n };\n\n storage.post(\n this.getApiUrl(\"totals-information\"),\n JSON.stringify(payload)\n ).done(function (r) {\n this.setGrandTotalAmount(r.base_grand_total);\n\n session.completeShippingMethodSelection(\n ApplePaySession.STATUS_SUCCESS,\n {\n label: this.getDisplayName(),\n amount: this.getGrandTotalAmount()\n },\n [{\n type: 'final',\n label: $t('Shipping'),\n amount: shippingMethod.amount\n }]\n );\n }.bind(this));\n },\n\n /**\n * Place the order\n */\n startPlaceOrder: function (nonce, event, session, device_data) {\n let shippingContact = event.payment.shippingContact,\n billingContact = event.payment.billingContact,\n payload = {\n \"addressInformation\": {\n \"shipping_address\": {\n \"email\": shippingContact.emailAddress,\n \"telephone\": shippingContact.phoneNumber,\n \"firstname\": shippingContact.givenName,\n \"lastname\": shippingContact.familyName,\n \"street\": shippingContact.addressLines,\n \"city\": shippingContact.locality,\n \"region\": shippingContact.administrativeArea,\n \"region_id\": this.getRegionId(shippingContact.countryCode.toUpperCase(), shippingContact.administrativeArea),\n \"region_code\": null,\n \"country_id\": shippingContact.countryCode.toUpperCase(),\n \"postcode\": shippingContact.postalCode,\n \"same_as_billing\": 0,\n \"customer_address_id\": 0,\n \"save_in_address_book\": 0\n },\n \"billing_address\": {\n \"email\": shippingContact.emailAddress,\n \"telephone\": shippingContact.phoneNumber,\n \"firstname\": billingContact.givenName,\n \"lastname\": billingContact.familyName,\n \"street\": billingContact.addressLines,\n \"city\": billingContact.locality,\n \"region\": billingContact.administrativeArea,\n \"region_id\": this.getRegionId(billingContact.countryCode.toUpperCase(), billingContact.administrativeArea),\n \"region_code\": null,\n \"country_id\": billingContact.countryCode.toUpperCase(),\n \"postcode\": billingContact.postalCode,\n \"same_as_billing\": 0,\n \"customer_address_id\": 0,\n \"save_in_address_book\": 0\n },\n \"shipping_method_code\": this.shippingMethod ? this.shippingMethods[this.shippingMethod].method_code : '' ,\n \"shipping_carrier_code\": this.shippingMethod ? this.shippingMethods[this.shippingMethod].carrier_code : ''\n }\n };\n\n // Set addresses\n storage.post(\n this.getApiUrl(\"shipping-information\"),\n JSON.stringify(payload)\n ).done(function () {\n // Submit payment information\n let paymentInformation = {\n \"email\": shippingContact.emailAddress,\n \"paymentMethod\": {\n \"method\": \"braintree_applepay\",\n \"additional_data\": {\n \"payment_method_nonce\": nonce,\n \"device_data\": device_data\n }\n }\n };\n if (window.checkout && window.checkout.agreementIds) {\n paymentInformation.paymentMethod.extension_attributes = {\n \"agreement_ids\": window.checkout.agreementIds\n };\n }\n storage.post(\n this.getApiUrl(\"payment-information\"),\n JSON.stringify(paymentInformation)\n ).done(function (r) {\n document.location = this.getActionSuccess();\n session.completePayment(ApplePaySession.STATUS_SUCCESS);\n }.bind(this)).fail(function (r) {\n session.completePayment(ApplePaySession.STATUS_FAILURE);\n session.abort();\n alert($t(\"We're unable to take your payment through Apple Pay. Please try an again or use an alternative payment method.\"));\n console.error(\"Braintree ApplePay Unable to take payment\", r);\n return false;\n });\n\n }.bind(this)).fail(function (r) {\n console.error(\"Braintree ApplePay Unable to set shipping information\", r);\n session.completePayment(ApplePaySession.STATUS_INVALID_BILLING_POSTAL_ADDRESS);\n });\n }\n });\n });\n","PayPal_Braintree/js/applepay/button.js":"/**\n * Braintree Apple Pay button\n **/\ndefine(\n [\n 'uiComponent',\n \"knockout\",\n \"jquery\",\n 'braintree',\n 'braintreeDataCollector',\n 'braintreeApplePay',\n 'mage/translate',\n 'Magento_Checkout/js/model/payment/additional-validators',\n ],\n function (\n Component,\n ko,\n jQuery,\n braintree,\n dataCollector,\n applePay,\n $t,\n additionalValidators\n ) {\n 'use strict';\n\n var that;\n\n return {\n init: function (element, context) {\n // No element or context\n if (!element || !context) {\n return;\n }\n\n // Context must implement these methods\n if (typeof context.getClientToken !== 'function') {\n console.error(\"Braintree ApplePay Context passed does not provide a getClientToken method\", context);\n return;\n }\n if (typeof context.getPaymentRequest !== 'function') {\n console.error(\"Braintree ApplePay Context passed does not provide a getPaymentRequest method\", context);\n return;\n }\n if (typeof context.startPlaceOrder !== 'function') {\n console.error(\"Braintree ApplePay Context passed does not provide a startPlaceOrder method\", context);\n return;\n }\n\n if (this.deviceSupported() === false) {\n return;\n }\n\n // init braintree api\n braintree.create({\n authorization: context.getClientToken()\n }, function (clientErr, clientInstance) {\n if (clientErr) {\n console.error('Error creating client:', clientErr);\n return;\n }\n\n dataCollector.create({\n client: clientInstance\n }, function (dataCollectorErr, dataCollectorInstance) {\n if (dataCollectorErr) {\n return;\n }\n\n applePay.create({\n client: clientInstance\n }, function (applePayErr, applePayInstance) {\n // No instance\n if (applePayErr) {\n console.error('Braintree ApplePay Error creating applePayInstance:', applePayErr);\n return;\n }\n\n // Create a button within the KO element, as apple pay can only be instantiated through\n // a valid on click event (ko onclick bind interferes with this).\n var el = document.createElement('div');\n el.className = \"braintree-apple-pay-button\";\n el.title = $t(\"Pay with Apple Pay\");\n el.alt = $t(\"Pay with Apple Pay\");\n el.addEventListener('click', function (e) {\n e.preventDefault();\n\n if (!additionalValidators.validate()) {\n return false;\n }\n // Payment request object\n var paymentRequest = applePayInstance.createPaymentRequest(context.getPaymentRequest());\n if (!paymentRequest) {\n alert($t(\"We're unable to take payments through Apple Pay at the moment. Please try an alternative payment method.\"));\n console.error('Braintree ApplePay Unable to create paymentRequest', paymentRequest);\n return;\n }\n\n // Show the loader\n jQuery(\"body\").loader('show');\n\n // Init apple pay session\n try {\n var session = new ApplePaySession(1, paymentRequest);\n } catch (err) {\n jQuery(\"body\").loader('hide');\n console.error('Braintree ApplePay Unable to create ApplePaySession', err);\n alert($t(\"We're unable to take payments through Apple Pay at the moment. Please try an alternative payment method.\"));\n return false;\n }\n\n // Handle invalid merchant\n session.onvalidatemerchant = function (event) {\n applePayInstance.performValidation({\n validationURL: event.validationURL,\n displayName: context.getDisplayName()\n }, function (validationErr, merchantSession) {\n if (validationErr) {\n session.abort();\n console.error('Braintree ApplePay Error validating merchant:', validationErr);\n alert($t(\"We're unable to take payments through Apple Pay at the moment. Please try an alternative payment method.\"));\n return;\n }\n\n session.completeMerchantValidation(merchantSession);\n });\n };\n\n // Attach payment auth event\n session.onpaymentauthorized = function (event) {\n applePayInstance.tokenize({\n token: event.payment.token\n }, function (tokenizeErr, payload) {\n if (tokenizeErr) {\n console.error('Error tokenizing Apple Pay:', tokenizeErr);\n session.completePayment(ApplePaySession.STATUS_FAILURE);\n return;\n }\n\n // Pass the nonce back to the payment method\n context.startPlaceOrder(payload.nonce, event, session, dataCollectorInstance.deviceData);\n });\n };\n\n // Attach onShippingContactSelect method\n if (typeof context.onShippingContactSelect === 'function') {\n session.onshippingcontactselected = function (event) {\n return context.onShippingContactSelect(event, session);\n };\n }\n\n // Attach onShippingMethodSelect method\n if (typeof context.onShippingMethodSelect === 'function') {\n session.onshippingmethodselected = function (event) {\n return context.onShippingMethodSelect(event, session);\n };\n }\n\n // Hook\n if (typeof context.onButtonClick === 'function') {\n context.onButtonClick(session, this, e);\n } else {\n jQuery(\"body\").loader('hide');\n session.begin();\n }\n });\n element.appendChild(el);\n });\n });\n\n });\n },\n\n /**\n * Check the site is using HTTPS & apple pay is supported on this device.\n * @return boolean\n */\n deviceSupported: function () {\n if (location.protocol != 'https:') {\n console.warn(\"Braintree Apple Pay requires your checkout be served over HTTPS\");\n return false;\n }\n\n if ((window.ApplePaySession && ApplePaySession.canMakePayments()) !== true) {\n console.warn(\"Braintree Apple Pay is not supported on this device/browser\");\n return false;\n }\n\n return true;\n }\n };\n }\n);\n","PayPal_Braintree/js/applepay/implementations/shortcut.js":"/**\n * Braintree Apple Pay mini cart payment method integration.\n **/\ndefine(\n [\n 'uiComponent',\n 'PayPal_Braintree/js/applepay/button',\n 'PayPal_Braintree/js/applepay/api',\n 'mage/translate',\n 'domReady!'\n ],\n function (\n Component,\n button,\n buttonApi,\n $t\n ) {\n 'use strict';\n\n return Component.extend({\n\n defaults: {\n id: null,\n clientToken: null,\n quoteId: 0,\n displayName: null,\n actionSuccess: null,\n grandTotalAmount: 0,\n isLoggedIn: false,\n storeCode: \"default\"\n },\n\n /**\n * @returns {Object}\n */\n initialize: function () {\n this._super();\n if (!this.displayName) {\n this.displayName = $t('Store');\n }\n\n var api = new buttonApi();\n api.setGrandTotalAmount(parseFloat(this.grandTotalAmount).toFixed(2));\n api.setClientToken(this.clientToken);\n api.setDisplayName(this.displayName);\n api.setQuoteId(this.quoteId);\n api.setActionSuccess(this.actionSuccess);\n api.setIsLoggedIn(this.isLoggedIn);\n api.setStoreCode(this.storeCode);\n\n // Attach the button\n button.init(\n document.getElementById(this.id),\n api\n );\n\n return this;\n }\n });\n }\n);\n","PayPal_Braintree/js/applepay/implementations/core-checkout/method-applepay.js":"define([\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n 'use strict';\n\n let config = window.checkoutConfig.payment;\n\n if (config['braintree_applepay'].clientToken) {\n rendererList.push({\n type: 'braintree_applepay',\n component: 'PayPal_Braintree/js/applepay/implementations/core-checkout/method-renderer/applepay'\n });\n }\n\n return Component.extend({});\n});\n","PayPal_Braintree/js/applepay/implementations/core-checkout/method-renderer/applepay.js":"/**\n * Braintree Apple Pay payment method integration.\n **/\ndefine([\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Checkout/js/model/quote',\n 'PayPal_Braintree/js/applepay/button'\n], function (\n Component,\n quote,\n button\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'PayPal_Braintree/applepay/core-checkout',\n paymentMethodNonce: null,\n deviceData: null,\n grandTotalAmount: 0,\n deviceSupported: button.deviceSupported()\n },\n\n /**\n * Inject the apple pay button into the target element\n */\n getApplePayBtn: function (id) {\n button.init(\n document.getElementById(id),\n this\n );\n },\n\n /**\n * Subscribe to grand totals\n */\n initObservable: function () {\n this._super();\n this.grandTotalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2);\n\n quote.totals.subscribe(function () {\n if (this.grandTotalAmount !== quote.totals()['base_grand_total']) {\n this.grandTotalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2);\n }\n }.bind(this));\n\n return this;\n },\n\n /**\n * Apple pay place order method\n */\n startPlaceOrder: function (nonce, event, session, device_data) {\n this.setPaymentMethodNonce(nonce);\n this.setDeviceData(device_data);\n this.placeOrder();\n\n session.completePayment(ApplePaySession.STATUS_SUCCESS);\n },\n\n /**\n * Save nonce\n */\n setPaymentMethodNonce: function (nonce) {\n this.paymentMethodNonce = nonce;\n },\n\n /**\n * Save nonce\n */\n setDeviceData: function (device_data) {\n this.deviceData = device_data;\n },\n\n /**\n * Retrieve the client token\n * @returns null|string\n */\n getClientToken: function () {\n return window.checkoutConfig.payment[this.getCode()].clientToken;\n },\n\n /**\n * Payment request data\n */\n getPaymentRequest: function () {\n return {\n total: {\n label: this.getDisplayName(),\n amount: this.grandTotalAmount\n }\n };\n },\n\n /**\n * Merchant display name\n */\n getDisplayName: function () {\n return window.checkoutConfig.payment[this.getCode()].merchantName;\n },\n\n /**\n * Get data\n * @returns {Object}\n */\n getData: function () {\n var data = {\n 'method': this.getCode(),\n 'additional_data': {\n 'payment_method_nonce': this.paymentMethodNonce,\n 'device_data': this.deviceData\n }\n };\n return data;\n },\n\n /**\n * Return image url for the apple pay mark\n */\n getPaymentMarkSrc: function () {\n return window.checkoutConfig.payment[this.getCode()].paymentMarkSrc;\n }\n });\n});\n","PayPal_Braintree/js/reCaptcha/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","PayPal_Braintree/js/model/step-navigator-mixin.js":"define([\n 'mage/utils/wrapper',\n 'jquery'\n], function (wrapper, $) {\n 'use strict';\n\n let mixin = {\n handleHash: function (originalFn) {\n var hashString = window.location.hash.replace('#', '');\n if (hashString.indexOf('venmo') > -1) {\n return false;\n }\n\n return originalFn();\n }\n };\n\n return function (target) {\n return wrapper.extend(target, mixin);\n };\n});\n","PayPal_Braintree/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\n if (recaptchaRegistry.triggers.hasOwnProperty('recaptcha-checkout-braintree')) {\n //ReCaptcha is present for checkout\n recaptchaDeferred = $.Deferred();\n recaptchaRegistry.addListener('recaptcha-checkout-braintree', 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['recaptcha-checkout-braintree']();\n //remove listener so that place order action is only triggered by the 'Place Order' button\n recaptchaRegistry.removeListener('recaptcha-checkout-braintree');\n return recaptchaDeferred;\n }\n\n //No ReCaptcha, just sending the request\n return originalAction(serviceUrl, payload, messageContainer);\n });\n };\n});\n","PayPal_Braintree/js/paypal/form-builder.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(\n [\n 'jquery',\n 'underscore',\n 'mage/template'\n ],\n function ($, _, mageTemplate) {\n 'use strict';\n\n return {\n\n /**\n * @param {Object} formData\n * @returns {*|jQuery}\n */\n build: function (formData) {\n var formTmpl = mageTemplate('<form action=\"<%= data.action %>\"' +\n ' method=\"POST\" hidden enctype=\"application/x-www-form-urlencoded\">' +\n '<% _.each(data.fields, function(val, key){ %>' +\n '<input value=\\'<%= val %>\\' name=\"<%= key %>\" type=\"hidden\">' +\n '<% }); %>' +\n '</form>');\n\n return $(formTmpl({\n data: {\n action: formData.action,\n fields: formData.fields\n }\n })).appendTo($('[data-container=\"body\"]'));\n }\n };\n }\n);\n","PayPal_Braintree/js/paypal/button.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(\n [\n 'rjsResolver',\n 'uiRegistry',\n 'uiComponent',\n 'underscore',\n 'jquery',\n 'Magento_Customer/js/customer-data',\n 'mage/translate',\n 'braintree',\n 'braintreeDataCollector',\n 'braintreePayPalCheckout',\n 'PayPal_Braintree/js/form-builder',\n 'domReady!'\n ],\n function (\n resolver,\n registry,\n Component,\n _,\n $,\n customerData,\n $t,\n braintree,\n dataCollector,\n paypalCheckout,\n formBuilder\n ) {\n 'use strict';\n let buttonIds = [];\n\n return {\n events: {\n onClick: null,\n onCancel: null,\n onError: null\n },\n\n /**\n * @param token\n * @param currency\n * @param env\n * @param local\n * @param lineItems\n */\n init: function (token, currency, env, local, lineItems) {\n if ($('.action-braintree-paypal-message').length) {\n $('.product-add-form form').on('keyup change paste', 'input, select, textarea', function () {\n var currentPrice, currencySymbol;\n currentPrice = $(\".product-info-main span\").find(\"[data-price-type='finalPrice']\").text();\n currencySymbol = $('.action-braintree-paypal-message[data-pp-type=\"product\"]').data('currency-symbol');\n $('.action-braintree-paypal-message[data-pp-type=\"product\"]').attr('data-pp-amount', currentPrice.replace(currencySymbol,''));\n });\n }\n\n buttonIds = [];\n $('.action-braintree-paypal-logo').each(function () {\n if (!$(this).hasClass(\"button-loaded\")) {\n $(this).addClass('button-loaded');\n buttonIds.push($(this).attr('id'));\n }\n });\n\n if (buttonIds.length > 0) {\n this.loadSDK(token, currency, env, local, lineItems);\n }\n },\n\n /**\n * Load Braintree PayPal SDK\n * @param token\n * @param currency\n * @param env\n * @param local\n * @param lineItems\n */\n loadSDK: function (token, currency, env, local, lineItems) {\n braintree.create({\n authorization: token\n }, function (clientErr, clientInstance) {\n if (clientErr) {\n console.error('paypalCheckout error', clientErr);\n return this.showError(\"PayPal Checkout could not be initialized. Please contact the store owner.\");\n }\n dataCollector.create({\n client: clientInstance,\n paypal: true\n }, function (err, dataCollectorInstance) {\n if (err) {\n return console.log(err);\n }\n });\n paypalCheckout.create({\n client: clientInstance\n }, function (err, paypalCheckoutInstance) {\n if (typeof paypal !== 'undefined' ) {\n this.renderPayPalButtons(buttonIds, paypalCheckoutInstance, lineItems);\n this.renderPayPalMessages();\n } else {\n var configSDK = {\n components: 'buttons,messages,funding-eligibility',\n \"enable-funding\": \"paylater\",\n currency: currency\n };\n if (env === 'sandbox' && local !== '') {\n configSDK[\"buyer-country\"] = local;\n }\n paypalCheckoutInstance.loadPayPalSDK(configSDK, function () {\n this.renderPayPalButtons(buttonIds, paypalCheckoutInstance, lineItems);\n this.renderPayPalMessages();\n }.bind(this));\n }\n }.bind(this));\n }.bind(this));\n },\n\n /**\n * Render PayPal buttons\n *\n * @param ids\n * @param paypalCheckoutInstance\n * @param lineItems\n */\n renderPayPalButtons: function (ids, paypalCheckoutInstance, lineItems) {\n _.each(ids, function (id) {\n this.payPalButton(id, paypalCheckoutInstance, lineItems);\n }.bind(this));\n },\n\n /**\n * Render PayPal messages\n */\n renderPayPalMessages: function () {\n $('.action-braintree-paypal-message').each(function () {\n paypal.Messages({\n amount: $(this).data('pp-amount'),\n pageType: $(this).data('pp-type'),\n style: {\n layout: $(this).data('messaging-layout'),\n text: {\n color: $(this).data('messaging-text-color')\n },\n logo: {\n type: $(this).data('messaging-logo'),\n position: $(this).data('messaging-logo-position')\n }\n }\n }).render('#' + $(this).attr('id'));\n\n\n });\n },\n\n /**\n * @param id\n * @param paypalCheckoutInstance\n * @param lineItems\n */\n payPalButton: function (id, paypalCheckoutInstance, lineItems) {\n let data = $('#' + id);\n let style = {\n color: data.data('color'),\n shape: data.data('shape'),\n size: data.data('size'),\n label: data.data('label')\n };\n\n if (data.data('fundingicons')) {\n style.fundingicons = data.data('fundingicons');\n }\n\n // Render\n var paypalActions;\n var button = paypal.Buttons({\n fundingSource: data.data('funding'),\n style: style,\n createOrder: function () {\n return paypalCheckoutInstance.createPayment({\n amount: data.data('amount'),\n locale: data.data('locale'),\n currency: data.data('currency'),\n flow: 'checkout',\n enableShippingAddress: true,\n displayName: data.data('displayname'),\n lineItems: $.parseJSON(lineItems)\n });\n },\n validate: function (actions) {\n var cart = customerData.get('cart'),\n customer = customerData.get('customer'),\n declinePayment = false,\n isGuestCheckoutAllowed;\n isGuestCheckoutAllowed = cart().isGuestCheckoutAllowed;\n declinePayment = !customer().firstname && !isGuestCheckoutAllowed;\n if (declinePayment) {\n actions.disable();\n }\n paypalActions = actions;\n },\n\n onCancel: function (data) {\n jQuery(\"#maincontent\").trigger('processStop');\n },\n\n onError: function (err) {\n console.error('paypalCheckout button render error', err);\n jQuery(\"#maincontent\").trigger('processStop');\n },\n\n onClick: function (data) {\n var cart = customerData.get('cart'),\n customer = customerData.get('customer'),\n declinePayment = false,\n isGuestCheckoutAllowed;\n\n isGuestCheckoutAllowed = cart().isGuestCheckoutAllowed;\n declinePayment = !customer().firstname && !isGuestCheckoutAllowed && (typeof isGuestCheckoutAllowed !== 'undefined');\n if (declinePayment) {\n alert($t('To check out, please sign in with your email address.'));\n }\n },\n\n onApprove: function (data1) {\n return paypalCheckoutInstance.tokenizePayment(data1, function (err, payload) {\n jQuery(\"#maincontent\").trigger('processStart');\n\n // Map the shipping address correctly\n var address = payload.details.shippingAddress;\n var recipientFirstName, recipientLastName;\n if (typeof address.recipientName !== 'undefined') {\n var recipientName = address.recipientName.split(\" \");\n recipientFirstName = recipientName[0].replace(/'/g, \"'\");\n recipientLastName = recipientName[1].replace(/'/g, \"'\");\n } else {\n recipientFirstName = payload.details.firstName.replace(/'/g, \"'\");\n recipientLastName = payload.details.lastName.replace(/'/g, \"'\");\n }\n payload.details.shippingAddress = {\n streetAddress: typeof address.line2 !== 'undefined' ? address.line1.replace(/'/g, \"'\") + \" \" + address.line2.replace(/'/g, \"'\") : address.line1.replace(/'/g, \"'\"),\n locality: address.city.replace(/'/g, \"'\"),\n postalCode: address.postalCode,\n countryCodeAlpha2: address.countryCode,\n email: payload.details.email.replace(/'/g, \"'\"),\n recipientFirstName: recipientFirstName,\n recipientLastName: recipientLastName,\n telephone: typeof payload.details.phone !== 'undefined' ? payload.details.phone : '',\n region: typeof address.state !== 'undefined' ? address.state.replace(/'/g, \"'\") : ''\n };\n\n payload.details.email = payload.details.email.replace(/'/g, \"'\");\n payload.details.firstName = payload.details.firstName.replace(/'/g, \"'\");\n payload.details.lastName = payload.details.lastName.replace(/'/g, \"'\");\n if (typeof payload.details.businessName !== 'undefined') {\n payload.details.businessName = payload.details.businessName.replace(/'/g, \"'\");\n }\n\n // Map the billing address correctly\n let isRequiredBillingAddress = data.data('requiredbillingaddress');\n if ((isRequiredBillingAddress === 1) && (typeof payload.details.billingAddress !== 'undefined')) {\n var billingAddress = payload.details.billingAddress;\n payload.details.billingAddress = {\n streetAddress: typeof billingAddress.line2 !== 'undefined' ? billingAddress.line1.replace(/'/g, \"'\") + \" \" + billingAddress.line2.replace(/'/g, \"'\") : billingAddress.line1.replace(/'/g, \"'\"),\n locality: billingAddress.city.replace(/'/g, \"'\"),\n postalCode: billingAddress.postalCode,\n countryCodeAlpha2: billingAddress.countryCode,\n telephone: typeof payload.details.phone !== 'undefined' ? payload.details.phone : '',\n region: typeof billingAddress.state !== 'undefined' ? billingAddress.state.replace(/'/g, \"'\") : ''\n };\n }\n\n if (data.data('location') == 'productpage') {\n var form = $(\"#product_addtocart_form\");\n if (!(form.validation() && form.validation('isValid'))) {\n return false;\n }\n payload.additionalData = form.serialize();\n }\n\n var actionSuccess = data.data('actionsuccess');\n formBuilder.build(\n {\n action: actionSuccess,\n fields: {\n result: JSON.stringify(payload)\n }\n }\n ).submit();\n });\n }\n });\n if (!button.isEligible()) {\n console.log('PayPal button is not elligible')\n data.parent().remove();\n return;\n }\n if ($('#' + data.attr('id')).length) {\n button.render('#' + data.attr('id'));\n }\n },\n }\n }\n);\n","PayPal_Braintree/js/paypal/product-page.js":"define(\n ['PayPal_Braintree/js/paypal/button', 'jquery'],\n function (button, $) {\n 'use strict';\n\n return button.extend({\n\n defaults: {\n label: 'buynow',\n branding: true,\n },\n\n /**\n * The validation on the add-to-cart form is done after the PayPal window has opened.\n * This is because the validate method exposed by the PP Button requires an event to disable/enable the button.\n * We can't fire an event due to the way the mage.validation widget works and we can't do something gross like\n * an interval because the validation() method shows the error messages and focuses the user's input on the\n * first erroring input field.\n * @param payload\n * @returns {*}\n */\n beforeSubmit: function (payload) {\n var form = $(\"#product_addtocart_form\");\n\n if (!(form.validation() && form.validation('isValid'))) {\n return false;\n }\n\n payload.additionalData = form.serialize();\n\n return payload;\n }\n });\n }\n);","PayPal_Braintree/js/paypal/credit/calculator.js":"define([\n 'underscore',\n 'uiComponent',\n 'jquery'\n], function (_, Component, $) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: \"PayPal_Braintree/credit/calculator\",\n displaySummary: true, // \"From X per month\"\n displayInterestDetails: false, // Display the more in-depth summary of interest rates\n instalmentsFrom: 0,\n currentInstalment: {\n term: 0,\n monthlyPayment: 0,\n apr: 0,\n cost: 0,\n costIncInterest: 0\n },\n endpoint: null,\n instalments: [],\n visible: false,\n merchantName: ''\n },\n\n initObservable: function () {\n this._super();\n if (this.instalments.length > 0) {\n this.currentInstalment = this.instalments[0];\n this.instalmentsFrom = this.instalments[this.instalments.length-1].monthlyPayment;\n this.visible = true;\n } else {\n this.loadInstalments();\n }\n\n this.observe(['instalments', 'currentInstalment', 'instalmentsFrom', 'visible']);\n return this;\n },\n\n isCurrentInstalment: function (term) {\n return (this.currentInstalment().term === term);\n },\n\n setCurrentInstalment: function (instalment) {\n this.currentInstalment(instalment);\n },\n\n loadInstalments: function () {\n if (!this.endpoint) {\n return false;\n }\n\n var self = this;\n require(['Magento_Checkout/js/model/quote', 'jquery'], function (quote, $) {\n if (typeof quote.totals().base_grand_total === 'undefined') {\n return false;\n }\n\n $.getJSON(self.endpoint, {amount: quote.totals().base_grand_total}, function (response) {\n self.instalments(response);\n self.setCurrentInstalment(response[0]);\n self.visible(true);\n });\n });\n }\n });\n});\n","PayPal_Braintree/js/googlepay/api.js":"/**\n * Braintree Google Pay button api\n **/\ndefine([\n 'uiComponent',\n 'mage/translate',\n 'mage/storage',\n 'jquery',\n 'PayPal_Braintree/js/form-builder'\n], function (Component, $t, storage, jQuery, formBuilder) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n clientToken: null,\n merchantId: null,\n currencyCode: null,\n actionSuccess: null,\n amount: null,\n cardTypes: [],\n btnColor: 0\n },\n\n /**\n * Set & get environment\n * \"PRODUCTION\" or \"TEST\"\n */\n setEnvironment: function (value) {\n this.environment = value;\n },\n getEnvironment: function () {\n return this.environment;\n },\n\n /**\n * Set & get api token\n */\n setClientToken: function (value) {\n this.clientToken = value;\n },\n getClientToken: function () {\n return this.clientToken;\n },\n\n /**\n * Set and get display name\n */\n setMerchantId: function (value) {\n this.merchantId = value;\n },\n getMerchantId: function () {\n return this.merchantId;\n },\n\n /**\n * Set and get currency code\n */\n setAmount: function (value) {\n this.amount = parseFloat(value).toFixed(2);\n },\n getAmount: function () {\n return this.amount;\n },\n\n /**\n * Set and get currency code\n */\n setCurrencyCode: function (value) {\n this.currencyCode = value;\n },\n getCurrencyCode: function () {\n return this.currencyCode;\n },\n\n /**\n * Set and get success redirection url\n */\n setActionSuccess: function (value) {\n this.actionSuccess = value;\n },\n getActionSuccess: function () {\n return this.actionSuccess;\n },\n\n /**\n * Set and get success redirection url\n */\n setCardTypes: function (value) {\n this.cardTypes = value;\n },\n getCardTypes: function () {\n return this.cardTypes;\n },\n\n /**\n * BTN Color\n */\n setBtnColor: function (value) {\n this.btnColor = value;\n },\n getBtnColor: function () {\n return this.btnColor;\n },\n\n /**\n * Payment request info\n */\n getPaymentRequest: function () {\n var result = {\n transactionInfo: {\n totalPriceStatus: 'ESTIMATED',\n totalPrice: this.getAmount(),\n currencyCode: this.getCurrencyCode()\n },\n allowedPaymentMethods: [\n {\n \"type\": \"CARD\",\n \"parameters\": {\n \"allowedCardNetworks\": this.getCardTypes(),\n \"billingAddressRequired\": true,\n \"billingAddressParameters\": {\n format: 'FULL',\n phoneNumberRequired: true\n },\n },\n\n }\n ],\n shippingAddressRequired: true,\n emailRequired: true,\n };\n\n if (this.getEnvironment() !== \"TEST\") {\n result.merchantInfo = { merchantId: this.getMerchantId() };\n }\n\n return result;\n },\n\n /**\n * Place the order\n */\n startPlaceOrder: function (nonce, paymentData, deviceData) {\n var payload = {\n details: {\n shippingAddress: {\n streetAddress: paymentData.shippingAddress.address1 + \"\\n\"\n + paymentData.shippingAddress.address2,\n locality: paymentData.shippingAddress.locality,\n postalCode: paymentData.shippingAddress.postalCode,\n countryCodeAlpha2: paymentData.shippingAddress.countryCode,\n email: paymentData.email,\n name: paymentData.shippingAddress.name,\n telephone: typeof paymentData.shippingAddress.phoneNumber !== 'undefined' ? paymentData.shippingAddress.phoneNumber : '',\n region: typeof paymentData.shippingAddress.administrativeArea !== 'undefined' ? paymentData.shippingAddress.administrativeArea : ''\n },\n billingAddress: {\n streetAddress: paymentData.paymentMethodData.info.billingAddress.address1 + \"\\n\"\n + paymentData.paymentMethodData.info.billingAddress.address2,\n locality: paymentData.paymentMethodData.info.billingAddress.locality,\n postalCode: paymentData.paymentMethodData.info.billingAddress.postalCode,\n countryCodeAlpha2: paymentData.paymentMethodData.info.billingAddress.countryCode,\n email: paymentData.email,\n name: paymentData.paymentMethodData.info.billingAddress.name,\n telephone: typeof paymentData.paymentMethodData.info.billingAddress.phoneNumber !== 'undefined' ? paymentData.paymentMethodData.info.billingAddress.phoneNumber : '',\n region: typeof paymentData.paymentMethodData.info.billingAddress.administrativeArea !== 'undefined' ? paymentData.paymentMethodData.info.billingAddress.administrativeArea : ''\n }\n },\n nonce: nonce,\n deviceData: deviceData,\n };\n\n formBuilder.build({\n action: this.getActionSuccess(),\n fields: {\n result: JSON.stringify(payload)\n }\n }).submit();\n }\n });\n});\n","PayPal_Braintree/js/googlepay/button.js":"/**\n * Braintree Google Pay button\n **/\ndefine(\n [\n 'uiComponent',\n \"knockout\",\n \"jquery\",\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_CheckoutAgreements/js/view/checkout-agreements',\n 'braintree',\n 'braintreeDataCollector',\n 'braintreeGooglePay',\n 'mage/translate',\n 'googlePayLibrary'\n ],\n function (\n Component,\n ko,\n jQuery,\n additionalValidators,\n checkoutAgreements,\n braintree,\n dataCollector,\n googlePay,\n $t\n ) {\n 'use strict';\n\n return {\n init: function (element, context) {\n\n // No element or context\n if (!element || !context ) {\n return;\n }\n\n // Context must implement these methods\n if (typeof context.getClientToken !== 'function') {\n console.error(\"Braintree GooglePay Context passed does not provide a getClientToken method\", context);\n return;\n }\n if (typeof context.getPaymentRequest !== 'function') {\n console.error(\"Braintree GooglePay Context passed does not provide a getPaymentRequest method\", context);\n return;\n }\n if (typeof context.startPlaceOrder !== 'function') {\n console.error(\"Braintree GooglePay Context passed does not provide a startPlaceOrder method\", context);\n return;\n }\n\n // init google pay object\n var paymentsClient = new google.payments.api.PaymentsClient({\n environment: context.getEnvironment()\n });\n\n // Create a button within the KO element, as google pay can only be instantiated through\n // a valid on click event (ko onclick bind interferes with this).\n var deviceData;\n var button = document.createElement('button');\n button.className = \"braintree-googlepay-button long \" + (context.getBtnColor() == 1 ? 'black' : 'white');\n button.title = $t(\"Buy with Google Pay\");\n\n // init braintree api\n braintree.create({\n authorization: context.getClientToken()\n }, function (clientErr, clientInstance) {\n if (clientErr) {\n console.error('Error creating client:', clientErr);\n return;\n }\n dataCollector.create({\n client: clientInstance\n }, function (dataCollectorErr, dataCollectorInstance) {\n if (dataCollectorErr) {\n return;\n }\n googlePay.create({\n client: clientInstance,\n googlePayVersion: 2\n }, function (googlePayErr, googlePaymentInstance) {\n // No instance\n if (googlePayErr) {\n console.error('Braintree GooglePay Error creating googlePayInstance:', googlePayErr);\n return;\n }\n\n paymentsClient.isReadyToPay({\n apiVersion: 2,\n apiVersionMinor: 0,\n allowedPaymentMethods: googlePaymentInstance.createPaymentDataRequest().allowedPaymentMethods\n }).then(function(response) {\n if (response.result) {\n button.addEventListener('click', function (event) {\n\n var agreements = checkoutAgreements().agreements,\n shouldDisableActions = false;\n\n\n _.each(agreements, function (item, index) {\n if (checkoutAgreements().isAgreementRequired(item)) {\n var inputId = '#agreement_braintree_googlepay_' + item.agreementId,\n inputEl = document.querySelector(inputId);\n\n if (inputEl !== null && !inputEl.checked) {\n shouldDisableActions = true;\n }\n\n }\n });\n\n if (!additionalValidators.validate()) {\n event.preventDefault();\n return false;\n }\n\n if (!shouldDisableActions) {\n event.preventDefault();\n jQuery(\"body\").loader('show');\n var responseData;\n\n var paymentDataRequest = googlePaymentInstance.createPaymentDataRequest(context.getPaymentRequest());\n paymentsClient.loadPaymentData(paymentDataRequest).then(function (paymentData) {\n // Persist the paymentData (shipping address etc)\n responseData = paymentData;\n // Return the braintree nonce promise\n return googlePaymentInstance.parseResponse(paymentData);\n }).then(function (result) {\n context.startPlaceOrder(result.nonce, responseData, dataCollectorInstance.deviceData);\n }).catch(function (err) {\n // Handle errors\n // err = {statusCode: \"CANCELED\"}\n console.error(err);\n jQuery(\"body\").loader('hide');\n });\n }\n });\n\n element.appendChild(button);\n }\n }).catch(function (err) {\n console.error(err);\n jQuery(\"body\").loader('hide');\n });\n });\n });\n });\n }\n };\n }\n);\n","PayPal_Braintree/js/googlepay/implementations/shortcut.js":"/**\n * Braintree Google Pay mini cart payment method integration.\n **/\ndefine(\n [\n 'uiComponent',\n 'PayPal_Braintree/js/googlepay/button',\n 'PayPal_Braintree/js/googlepay/api',\n 'mage/translate',\n 'domReady!'\n ],\n function (\n Component,\n button,\n buttonApi,\n $t\n ) {\n 'use strict';\n\n return Component.extend({\n\n defaults: {\n id: null,\n clientToken: null,\n merchantId: null,\n currencyCode: null,\n actionSuccess: null,\n amount: null,\n environment: \"TEST\",\n cardType: [],\n btnColor: 0\n },\n\n /**\n * @returns {Object}\n */\n initialize: function () {\n this._super();\n\n var api = new buttonApi();\n api.setEnvironment(this.environment);\n api.setCurrencyCode(this.currencyCode);\n api.setClientToken(this.clientToken);\n api.setMerchantId(this.merchantId);\n api.setActionSuccess(this.actionSuccess);\n api.setAmount(this.amount);\n api.setCardTypes(this.cardTypes)\n api.setBtnColor(this.btnColor);\n\n // Attach the button\n button.init(\n document.getElementById(this.id),\n api\n );\n\n return this;\n }\n });\n }\n);\n","PayPal_Braintree/js/googlepay/implementations/core-checkout/method-googlepay.js":"define([\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n 'use strict';\n\n let config = window.checkoutConfig.payment;\n\n if (config['braintree_googlepay'].clientToken) {\n rendererList.push({\n type: 'braintree_googlepay',\n component: 'PayPal_Braintree/js/googlepay/implementations/core-checkout/method-renderer/googlepay'\n });\n }\n\n return Component.extend({});\n});\n","PayPal_Braintree/js/googlepay/implementations/core-checkout/method-renderer/googlepay.js":"/**\n * Braintree Google Pay payment method integration.\n **/\ndefine([\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Checkout/js/model/quote',\n 'PayPal_Braintree/js/googlepay/button'\n], function (\n Component,\n quote,\n button\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'PayPal_Braintree/googlepay/core-checkout',\n paymentMethodNonce: null,\n deviceData: null,\n grandTotalAmount: 0\n },\n\n /**\n * Inject the google pay button into the target element\n */\n getGooglePayBtn: function (id) {\n button.init(\n document.getElementById(id),\n this\n );\n },\n\n /**\n * Subscribe to grand totals\n */\n initObservable: function () {\n this._super();\n this.grandTotalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2);\n this.currencyCode = quote.totals()['base_currency_code'];\n\n quote.totals.subscribe(function () {\n if (this.grandTotalAmount !== quote.totals()['base_grand_total']) {\n this.grandTotalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2);\n }\n }.bind(this));\n\n return this;\n },\n\n /**\n * Google pay place order method\n */\n startPlaceOrder: function (nonce, paymentData, device_data) {\n this.setPaymentMethodNonce(nonce);\n this.setDeviceData(device_data);\n this.placeOrder();\n },\n\n /**\n * Save nonce\n */\n setPaymentMethodNonce: function (nonce) {\n this.paymentMethodNonce = nonce;\n },\n\n /**\n * Save device_data\n */\n setDeviceData: function (device_data) {\n this.deviceData = device_data;\n },\n\n /**\n * Retrieve the client token\n * @returns null|string\n */\n getClientToken: function () {\n return window.checkoutConfig.payment[this.getCode()].clientToken;\n },\n\n /**\n * Payment request info\n */\n getPaymentRequest: function () {\n var result = {\n transactionInfo: {\n totalPriceStatus: 'FINAL',\n totalPrice: this.grandTotalAmount,\n currencyCode: this.currencyCode\n },\n allowedPaymentMethods: [\n {\n \"type\": \"CARD\",\n \"parameters\": {\n \"allowedCardNetworks\": this.getCardTypes(),\n \"billingAddressRequired\": false,\n },\n\n }\n ],\n shippingAddressRequired: false,\n emailRequired: false,\n };\n\n if (this.getEnvironment() !== \"TEST\") {\n result.merchantInfo = { merchantId: this.getMerchantId() };\n }\n\n return result;\n },\n\n /**\n * Merchant display name\n */\n getMerchantId: function () {\n return window.checkoutConfig.payment[this.getCode()].merchantId;\n },\n\n /**\n * Environment\n */\n getEnvironment: function () {\n return window.checkoutConfig.payment[this.getCode()].environment;\n },\n\n /**\n * Card Types\n */\n getCardTypes: function () {\n return window.checkoutConfig.payment[this.getCode()].cardTypes;\n },\n\n /**\n * BTN Color\n */\n getBtnColor: function () {\n return window.checkoutConfig.payment[this.getCode()].btnColor;\n },\n\n /**\n * Get data\n * @returns {Object}\n */\n getData: function () {\n return {\n 'method': this.getCode(),\n 'additional_data': {\n 'payment_method_nonce': this.paymentMethodNonce,\n 'device_data': this.deviceData\n }\n };\n },\n\n /**\n * Return image url for the google pay mark\n */\n getPaymentMarkSrc: function () {\n return window.checkoutConfig.payment[this.getCode()].paymentMarkSrc;\n }\n });\n});\n","Magento_Swatches/js/swatch-renderer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'underscore',\n 'mage/template',\n 'mage/smart-keyboard-handler',\n 'mage/translate',\n 'priceUtils',\n 'jquery-ui-modules/widget',\n 'jquery/jquery.parsequery',\n 'mage/validation/validation'\n], function ($, _, mageTemplate, keyboardHandler, $t, priceUtils) {\n 'use strict';\n\n /**\n * Extend form validation to support swatch accessibility\n */\n $.widget('mage.validation', $.mage.validation, {\n /**\n * Handle form with swatches validation. Focus on first invalid swatch block.\n *\n * @param {jQuery.Event} event\n * @param {Object} validation\n */\n listenFormValidateHandler: function (event, validation) {\n var swatchWrapper, firstActive, swatches, swatch, successList, errorList, firstSwatch;\n\n this._superApply(arguments);\n\n swatchWrapper = '.swatch-attribute-options';\n swatches = $(event.target).find(swatchWrapper);\n\n if (!swatches.length) {\n return;\n }\n\n swatch = '.swatch-attribute';\n firstActive = $(validation.errorList[0].element || []);\n successList = validation.successList;\n errorList = validation.errorList;\n firstSwatch = $(firstActive).parent(swatch).find(swatchWrapper);\n\n keyboardHandler.focus(swatches);\n\n $.each(successList, function (index, item) {\n $(item).parent(swatch).find(swatchWrapper).attr('aria-invalid', false);\n });\n\n $.each(errorList, function (index, item) {\n $(item.element).parent(swatch).find(swatchWrapper).attr('aria-invalid', true);\n });\n\n if (firstSwatch.length) {\n $(firstSwatch).trigger('focus');\n }\n }\n });\n\n /**\n * Render tooltips by attributes (only to up).\n * Required element attributes:\n * - data-option-type (integer, 0-3)\n * - data-option-label (string)\n * - data-option-tooltip-thumb\n * - data-option-tooltip-value\n * - data-thumb-width\n * - data-thumb-height\n */\n $.widget('mage.SwatchRendererTooltip', {\n options: {\n delay: 200, //how much ms before tooltip to show\n tooltipClass: 'swatch-option-tooltip' //configurable, but remember about css\n },\n\n /**\n * @private\n */\n _init: function () {\n var $widget = this,\n $this = this.element,\n $element = $('.' + $widget.options.tooltipClass),\n timer,\n type = parseInt($this.data('option-type'), 10),\n label = $this.data('option-label'),\n thumb = $this.data('option-tooltip-thumb'),\n value = $this.data('option-tooltip-value'),\n width = $this.data('thumb-width'),\n height = $this.data('thumb-height'),\n $image,\n $title,\n $corner;\n\n if (!$element.length) {\n $element = $('<div class=\"' +\n $widget.options.tooltipClass +\n '\"><div class=\"image\"></div><div class=\"title\"></div><div class=\"corner\"></div></div>'\n );\n $('body').append($element);\n }\n\n $image = $element.find('.image');\n $title = $element.find('.title');\n $corner = $element.find('.corner');\n\n $this.on('mouseenter', function () {\n if (!$this.hasClass('disabled')) {\n timer = setTimeout(\n function () {\n var leftOpt = null,\n leftCorner = 0,\n left,\n $window;\n\n if (type === 2) {\n // Image\n $image.css({\n 'background': 'url(\"' + thumb + '\") no-repeat center', //Background case\n 'background-size': 'initial',\n 'width': width + 'px',\n 'height': height + 'px'\n });\n $image.show();\n } else if (type === 1) {\n // Color\n $image.css({\n background: value\n });\n $image.show();\n } else if (type === 0 || type === 3) {\n // Default\n $image.hide();\n }\n\n $title.text(label);\n\n leftOpt = $this.offset().left;\n left = leftOpt + $this.width() / 2 - $element.width() / 2;\n $window = $(window);\n\n // the numbers (5 and 5) is magick constants for offset from left or right page\n if (left < 0) {\n left = 5;\n } else if (left + $element.width() > $window.width()) {\n left = $window.width() - $element.width() - 5;\n }\n\n // the numbers (6, 3 and 18) is magick constants for offset tooltip\n leftCorner = 0;\n\n if ($element.width() < $this.width()) {\n leftCorner = $element.width() / 2 - 3;\n } else {\n leftCorner = (leftOpt > left ? leftOpt - left : left - leftOpt) + $this.width() / 2 - 6;\n }\n\n $corner.css({\n left: leftCorner\n });\n $element.css({\n left: left,\n top: $this.offset().top - $element.height() - $corner.height() - 18\n }).show();\n },\n $widget.options.delay\n );\n }\n });\n\n $this.on('mouseleave', function () {\n $element.hide();\n clearTimeout(timer);\n });\n\n $(document).on('tap', function () {\n $element.hide();\n clearTimeout(timer);\n });\n\n $this.on('tap', function (event) {\n event.stopPropagation();\n });\n }\n });\n\n /**\n * Render swatch controls with options and use tooltips.\n * Required two json:\n * - jsonConfig (magento's option config)\n * - jsonSwatchConfig (swatch's option config)\n *\n * Tuning:\n * - numberToShow (show \"more\" button if options are more)\n * - onlySwatches (hide selectboxes)\n * - moreButtonText (text for \"more\" button)\n * - selectorProduct (selector for product container)\n * - selectorProductPrice (selector for change price)\n */\n $.widget('mage.SwatchRenderer', {\n options: {\n classes: {\n attributeClass: 'swatch-attribute',\n attributeLabelClass: 'swatch-attribute-label',\n attributeSelectedOptionLabelClass: 'swatch-attribute-selected-option',\n attributeOptionsWrapper: 'swatch-attribute-options',\n attributeInput: 'swatch-input',\n optionClass: 'swatch-option',\n selectClass: 'swatch-select',\n moreButton: 'swatch-more',\n loader: 'swatch-option-loading'\n },\n // option's json config\n jsonConfig: {},\n\n // swatch's json config\n jsonSwatchConfig: {},\n\n // selector of parental block of prices and swatches (need to know where to seek for price block)\n selectorProduct: '.product-info-main',\n\n // selector of price wrapper (need to know where set price)\n selectorProductPrice: '[data-role=priceBox]',\n\n //selector of product images gallery wrapper\n mediaGallerySelector: '[data-gallery-role=gallery-placeholder]',\n\n // selector of category product tile wrapper\n selectorProductTile: '.product-item',\n\n // number of controls to show (false or zero = show all)\n numberToShow: false,\n\n // show only swatch controls\n onlySwatches: false,\n\n // enable label for control\n enableControlLabel: true,\n\n // control label id\n controlLabelId: '',\n\n // text for more button\n moreButtonText: $t('More'),\n\n // Callback url for media\n mediaCallback: '',\n\n // Local media cache\n mediaCache: {},\n\n // Cache for BaseProduct images. Needed when option unset\n mediaGalleryInitial: [{}],\n\n // Use ajax to get image data\n useAjax: false,\n\n /**\n * Defines the mechanism of how images of a gallery should be\n * updated when user switches between configurations of a product.\n *\n * As for now value of this option can be either 'replace' or 'prepend'.\n *\n * @type {String}\n */\n gallerySwitchStrategy: 'replace',\n\n // whether swatches are rendered in product list or on product page\n inProductList: false,\n\n // sly-old-price block selector\n slyOldPriceSelector: '.sly-old-price',\n\n // tier prise selectors start\n tierPriceTemplateSelector: '#tier-prices-template',\n tierPriceBlockSelector: '[data-role=\"tier-price-block\"]',\n tierPriceTemplate: '',\n // tier prise selectors end\n\n // A price label selector\n normalPriceLabelSelector: '.product-info-main .normal-price .price-label',\n qtyInfo: '#qty'\n },\n\n /**\n * Get chosen product\n *\n * @returns int|null\n */\n getProduct: function () {\n var products = this._CalcProducts();\n\n return _.isArray(products) ? products[0] : null;\n },\n\n /**\n * Get chosen product id\n *\n * @returns int|null\n */\n getProductId: function () {\n var products = this._CalcProducts();\n\n return _.isArray(products) && products.length === 1 ? products[0] : null;\n },\n\n /**\n * @private\n */\n _init: function () {\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');\n } else {\n console.log('SwatchRenderer: No input data received');\n }\n },\n\n /**\n * @private\n */\n _sortAttributes: function () {\n this.options.jsonConfig.attributes = _.sortBy(this.options.jsonConfig.attributes, function (attribute) {\n return parseInt(attribute.position, 10);\n });\n },\n\n /**\n * @private\n */\n _create: function () {\n var options = this.options,\n gallery = $('[data-gallery-role=gallery-placeholder]', '.column.main'),\n productData = this._determineProductData(),\n $main = productData.isInProductView ?\n this.element.parents('.column.main') :\n this.element.parents('.product-item-info');\n\n if (productData.isInProductView) {\n gallery.data('gallery') ?\n this._onGalleryLoaded(gallery) :\n gallery.on('gallery:loaded', this._onGalleryLoaded.bind(this, gallery));\n } else {\n options.mediaGalleryInitial = [{\n 'img': $main.find('.product-image-photo').attr('src')\n }];\n }\n\n this.productForm = this.element.parents(this.options.selectorProductTile).find('form:first');\n this.inProductList = this.productForm.length > 0;\n $(this.options.qtyInfo).on('input', this._onQtyChanged.bind(this));\n },\n\n /**\n * Determine product id and related data\n *\n * @returns {{productId: *, isInProductView: bool}}\n * @private\n */\n _determineProductData: function () {\n // Check if product is in a list of products.\n var productId,\n isInProductView = false;\n\n productId = this.element.parents('.product-item-details')\n .find('.price-box.price-final_price').attr('data-product-id');\n\n if (!productId) {\n // Check individual product.\n productId = $('[name=product]').val();\n isInProductView = productId > 0;\n }\n\n return {\n productId: productId,\n isInProductView: isInProductView\n };\n },\n\n /**\n * Render controls\n *\n * @private\n */\n _RenderControls: function () {\n var $widget = this,\n container = this.element,\n classes = this.options.classes,\n chooseText = this.options.jsonConfig.chooseText,\n showTooltip = this.options.showTooltip;\n\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 '<span id=\"' + controlLabelId + '\" class=\"' + classes.attributeLabelClass + '\">' +\n $('<i></i>').text(item.label).html() +\n '</span>' +\n '<span class=\"' + classes.attributeSelectedOptionLabelClass + '\"></span>';\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 '<div aria-activedescendant=\"\" ' +\n 'tabindex=\"0\" ' +\n 'aria-invalid=\"false\" ' +\n 'aria-required=\"true\" ' +\n 'role=\"listbox\" ' + listLabel +\n 'class=\"' + classes.attributeOptionsWrapper + ' clearfix\">' +\n options + select +\n '</div>' + 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\n disableSwatchForOutOfStockProducts: function () {\n let $widget = this, container = this.element;\n\n $.each(this.options.jsonConfig.attributes, function () {\n let item = this;\n\n if ($widget.options.jsonConfig.canDisplayShowOutOfStockStatus) {\n let salableProducts = $widget.options.jsonConfig.salable[item.id],\n swatchOptions = $(container).find(`[data-attribute-id='${item.id}']`).find('.swatch-option');\n\n swatchOptions.each(function (key, value) {\n let optionId = $(value).data('option-id');\n\n if (!salableProducts.hasOwnProperty(optionId)) {\n $(value).attr('disabled', true).addClass('disabled');\n }\n });\n }\n });\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 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 countAttributes = 0,\n html = '';\n\n if (!this.options.jsonSwatchConfig.hasOwnProperty(config.id)) {\n return '';\n }\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\n // Add more button\n if (moreLimit === countAttributes++) {\n 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 attr =\n ' id=\"' + controlId + '-item-' + id + '\"' +\n ' index=\"' + index + '\"' +\n ' aria-checked=\"false\"' +\n ' aria-describedby=\"' + controlId + '\"' +\n ' tabindex=\"0\"' +\n ' data-option-type=\"' + type + '\"' +\n ' data-option-id=\"' + id + '\"' +\n ' data-option-label=\"' + label + '\"' +\n ' aria-label=\"' + label + '\"' +\n ' role=\"option\"' +\n ' data-thumb-width=\"' + width + '\"' +\n ' data-thumb-height=\"' + height + '\"';\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 += '<div class=\"' + optionClass + ' image\" ' + attr +\n ' style=\"background: url(' + value + ') no-repeat center; background-size: initial;width:' +\n swatchImageWidth + 'px; height:' + swatchImageHeight + 'px\">' + '' +\n '</div>';\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 },\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 =\n '<select class=\"' + this.options.classes.selectClass + ' ' + config.code + '\">' +\n '<option value=\"0\" data-option-id=\"0\">' + chooseText + '</option>';\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 * Input for submit form.\n * This control shouldn't have \"type=hidden\", \"display: none\" for validation work :(\n *\n * @param {Object} config\n * @private\n */\n _RenderFormInput: function (config) {\n return '<input class=\"' + this.options.classes.attributeInput + ' super-attribute-select\" ' +\n 'name=\"super_attribute[' + config.id + ']\" ' +\n 'type=\"text\" ' +\n 'value=\"\" ' +\n 'data-selector=\"super_attribute[' + config.id + ']\" ' +\n 'data-validate=\"{required: true}\" ' +\n 'aria-required=\"true\" ' +\n 'aria-invalid=\"false\">';\n },\n\n /**\n * Event listener\n *\n * @private\n */\n _EventListener: function () {\n var $widget = this,\n options = this.options.classes,\n target;\n\n $widget.element.on('click', '.' + options.optionClass, function () {\n return $widget._OnClick($(this), $widget);\n });\n\n $widget.element.on('change', '.' + options.selectClass, function () {\n return $widget._OnChange($(this), $widget);\n });\n\n $widget.element.on('click', '.' + options.moreButton, function (e) {\n e.preventDefault();\n\n return $widget._OnMoreClick($(this));\n });\n\n $widget.element.on('keydown', function (e) {\n if (e.which === 13) {\n target = $(e.target);\n\n if (target.is('.' + options.optionClass)) {\n return $widget._OnClick(target, $widget);\n } else if (target.is('.' + options.selectClass)) {\n return $widget._OnChange(target, $widget);\n } else if (target.is('.' + options.moreButton)) {\n e.preventDefault();\n\n return $widget._OnMoreClick(target);\n }\n }\n });\n },\n\n /**\n * Load media gallery using ajax or json config.\n *\n * @private\n */\n _loadMedia: function () {\n var $main = this.inProductList ?\n this.element.parents('.product-item-info') :\n this.element.parents('.column.main'),\n images;\n\n if (this.options.useAjax) {\n this._debouncedLoadProductMedia();\n } else {\n images = this.options.jsonConfig.images[this.getProduct()];\n\n if (!images) {\n images = this.options.mediaGalleryInitial;\n }\n this.updateBaseImage(this._sortImages(images), $main, !this.inProductList);\n }\n },\n\n /**\n * Sorting images array\n *\n * @private\n */\n _sortImages: function (images) {\n return _.sortBy(images, function (image) {\n return parseInt(image.position, 10);\n });\n },\n\n /**\n * Event for swatch options\n *\n * @param {Object} $this\n * @param {Object} $widget\n * @private\n */\n _OnClick: function ($this, $widget) {\n var $parent = $this.parents('.' + $widget.options.classes.attributeClass),\n $wrapper = $this.parents('.' + $widget.options.classes.attributeOptionsWrapper),\n $label = $parent.find('.' + $widget.options.classes.attributeSelectedOptionLabelClass),\n attributeId = $parent.data('attribute-id'),\n $input = $parent.find('.' + $widget.options.classes.attributeInput),\n checkAdditionalData = JSON.parse(this.options.jsonSwatchConfig[attributeId]['additional_data']),\n $priceBox = $widget.element.parents($widget.options.selectorProduct)\n .find(this.options.selectorProductPrice);\n\n if ($widget.inProductList) {\n $input = $widget.productForm.find(\n '.' + $widget.options.classes.attributeInput + '[name=\"super_attribute[' + attributeId + ']\"]'\n );\n }\n\n if ($this.hasClass('disabled')) {\n return;\n }\n\n if ($this.hasClass('selected')) {\n $parent.removeAttr('data-option-selected').find('.selected').removeClass('selected');\n $input.val('');\n $label.text('');\n $this.attr('aria-checked', false);\n } else {\n $parent.attr('data-option-selected', $this.data('option-id')).find('.selected').removeClass('selected');\n $label.text($this.data('option-label'));\n $input.val($this.data('option-id'));\n $input.attr('data-attr-name', this._getAttributeCodeById(attributeId));\n $this.addClass('selected');\n $widget._toggleCheckedAttributes($this, $wrapper);\n }\n\n $widget._Rebuild();\n\n if ($priceBox.is(':data(mage-priceBox)')) {\n $widget._UpdatePrice();\n }\n\n $(document).trigger('updateMsrpPriceBlock',\n [\n this._getSelectedOptionPriceIndex(),\n $widget.options.jsonConfig.optionPrices,\n $priceBox\n ]);\n\n if (parseInt(checkAdditionalData['update_product_preview_image'], 10) === 1) {\n $widget._loadMedia();\n }\n\n $input.trigger('change');\n },\n\n /**\n * Get selected option price index\n *\n * @return {String|undefined}\n * @private\n */\n _getSelectedOptionPriceIndex: function () {\n var allowedProduct = this._getAllowedProductWithMinPrice(this._CalcProducts());\n\n if (_.isEmpty(allowedProduct)) {\n return undefined;\n }\n\n return allowedProduct;\n },\n\n /**\n * Get human readable attribute code (eg. size, color) by it ID from configuration\n *\n * @param {Number} attributeId\n * @returns {*}\n * @private\n */\n _getAttributeCodeById: function (attributeId) {\n var attribute = this.options.jsonConfig.mappedAttributes[attributeId];\n\n return attribute ? attribute.code : attributeId;\n },\n\n /**\n * Toggle accessibility attributes\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-checked', false);\n $this.attr('aria-checked', true);\n },\n\n /**\n * Event for select\n *\n * @param {Object} $this\n * @param {Object} $widget\n * @private\n */\n _OnChange: function ($this, $widget) {\n var $parent = $this.parents('.' + $widget.options.classes.attributeClass),\n attributeId = $parent.data('attribute-id'),\n $input = $parent.find('.' + $widget.options.classes.attributeInput);\n\n if ($widget.productForm.length > 0) {\n $input = $widget.productForm.find(\n '.' + $widget.options.classes.attributeInput + '[name=\"super_attribute[' + attributeId + ']\"]'\n );\n }\n\n if ($this.val() > 0) {\n $parent.attr('data-option-selected', $this.val());\n $input.val($this.val());\n } else {\n $parent.removeAttr('data-option-selected');\n $input.val('');\n }\n\n $widget._Rebuild();\n $widget._UpdatePrice();\n $widget._loadMedia();\n $input.trigger('change');\n },\n\n /**\n * Event for more switcher\n *\n * @param {Object} $this\n * @private\n */\n _OnMoreClick: function ($this) {\n $this.nextAll().show();\n $this.trigger('blur').remove();\n },\n\n /**\n * Rewind options for controls\n *\n * @private\n */\n _Rewind: function (controls) {\n controls.find('div[data-option-id], option[data-option-id]')\n .removeClass('disabled')\n .prop('disabled', false);\n controls.find('div[data-option-empty], option[data-option-empty]')\n .attr('disabled', true)\n .addClass('disabled')\n .attr('tabindex', '-1');\n this.disableSwatchForOutOfStockProducts();\n },\n\n /**\n * Rebuild container\n *\n * @private\n */\n _Rebuild: function () {\n var $widget = this,\n controls = $widget.element.find('.' + $widget.options.classes.attributeClass + '[data-attribute-id]'),\n selected = controls.filter('[data-option-selected]');\n\n // Enable all options\n $widget._Rewind(controls);\n\n // done if nothing selected\n if (selected.length <= 0) {\n return;\n }\n\n // Disable not available options\n controls.each(function () {\n var $this = $(this),\n id = $this.data('attribute-id'),\n products = $widget._CalcProducts(id);\n\n if (selected.length === 1 && selected.first().data('attribute-id') === id) {\n return;\n }\n\n $this.find('[data-option-id]').each(function () {\n var $element = $(this),\n option = $element.data('option-id');\n\n if (!$widget.optionsMap.hasOwnProperty(id) || !$widget.optionsMap[id].hasOwnProperty(option) ||\n $element.hasClass('selected') ||\n $element.is(':selected')) {\n return;\n }\n\n if (_.intersection(products, $widget.optionsMap[id][option].products).length <= 0) {\n $element.attr('disabled', true).addClass('disabled');\n }\n });\n });\n },\n\n /**\n * Get selected product list\n *\n * @returns {Array}\n * @private\n */\n _CalcProducts: function ($skipAttributeId) {\n var $widget = this,\n selectedOptions = '.' + $widget.options.classes.attributeClass + '[data-option-selected]',\n products = [];\n\n // Generate intersection of products\n $widget.element.find(selectedOptions).each(function () {\n var id = $(this).data('attribute-id'),\n option = $(this).attr('data-option-selected');\n\n if ($skipAttributeId !== undefined && $skipAttributeId === id) {\n return;\n }\n\n if (!$widget.optionsMap.hasOwnProperty(id) || !$widget.optionsMap[id].hasOwnProperty(option)) {\n return;\n }\n\n if (products.length === 0) {\n products = $widget.optionsMap[id][option].products;\n } else {\n products = _.intersection(products, $widget.optionsMap[id][option].products);\n }\n });\n\n return products;\n },\n\n /**\n * Update total price\n *\n * @private\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 $productPrice.trigger(\n 'updatePrice',\n {\n 'prices': $widget._getPrices(result, $productPrice.priceBox('option').prices)\n }\n );\n\n isShow = typeof result != 'undefined' && result.oldPrice.amount !== result.finalPrice.amount;\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,\n '$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 /**\n * Get new prices for selected options\n *\n * @returns {*}\n * @private\n */\n _getNewPrices: function () {\n var $widget = this,\n newPrices = $widget.options.jsonConfig.prices,\n allowedProduct = this._getAllowedProductWithMinPrice(this._CalcProducts());\n\n if (!_.isEmpty(allowedProduct)) {\n newPrices = this.options.jsonConfig.optionPrices[allowedProduct];\n }\n\n return newPrices;\n },\n\n /**\n * Get prices\n *\n * @param {Object} newPrices\n * @param {Object} displayPrices\n * @returns {*}\n * @private\n */\n _getPrices: function (newPrices, displayPrices) {\n var $widget = this;\n\n if (_.isEmpty(newPrices)) {\n newPrices = $widget._getNewPrices();\n }\n _.each(displayPrices, function (price, code) {\n\n if (newPrices[code]) {\n displayPrices[code].amount = newPrices[code].amount - displayPrices[code].amount;\n }\n });\n\n return displayPrices;\n },\n\n /**\n * Get product with minimum price from selected options.\n *\n * @param {Array} allowedProducts\n * @returns {String}\n * @private\n */\n _getAllowedProductWithMinPrice: function (allowedProducts) {\n var optionPrices = this.options.jsonConfig.optionPrices,\n product = {},\n optionFinalPrice, optionMinPrice;\n\n _.each(allowedProducts, function (allowedProduct) {\n optionFinalPrice = parseFloat(optionPrices[allowedProduct].finalPrice.amount);\n\n if (_.isEmpty(product) || optionFinalPrice < optionMinPrice) {\n optionMinPrice = optionFinalPrice;\n product = allowedProduct;\n }\n }, this);\n\n return product;\n },\n\n /**\n * Gets all product media and change current to the needed one\n *\n * @private\n */\n _LoadProductMedia: function () {\n var $widget = this,\n $this = $widget.element,\n productData = this._determineProductData(),\n mediaCallData,\n mediaCacheKey,\n\n /**\n * Processes product media data\n *\n * @param {Object} data\n * @returns void\n */\n mediaSuccessCallback = function (data) {\n if (!(mediaCacheKey in $widget.options.mediaCache)) {\n $widget.options.mediaCache[mediaCacheKey] = data;\n }\n $widget._ProductMediaCallback($this, data, productData.isInProductView);\n setTimeout(function () {\n $widget._DisableProductMediaLoader($this);\n }, 300);\n };\n\n if (!$widget.options.mediaCallback) {\n return;\n }\n\n mediaCallData = {\n 'product_id': this.getProduct()\n };\n\n mediaCacheKey = JSON.stringify(mediaCallData);\n\n if (mediaCacheKey in $widget.options.mediaCache) {\n $widget._XhrKiller();\n $widget._EnableProductMediaLoader($this);\n mediaSuccessCallback($widget.options.mediaCache[mediaCacheKey]);\n } else {\n mediaCallData.isAjax = true;\n $widget._XhrKiller();\n $widget._EnableProductMediaLoader($this);\n $widget.xhr = $.ajax({\n url: $widget.options.mediaCallback,\n cache: true,\n type: 'GET',\n dataType: 'json',\n data: mediaCallData,\n success: mediaSuccessCallback\n }).done(function () {\n $widget._XhrKiller();\n });\n }\n },\n\n /**\n * Enable loader\n *\n * @param {Object} $this\n * @private\n */\n _EnableProductMediaLoader: function ($this) {\n var $widget = this;\n\n if ($('body.catalog-product-view').length > 0) {\n $this.parents('.column.main').find('.photo.image')\n .addClass($widget.options.classes.loader);\n } else {\n //Category View\n $this.parents('.product-item-info').find('.product-image-photo')\n .addClass($widget.options.classes.loader);\n }\n },\n\n /**\n * Disable loader\n *\n * @param {Object} $this\n * @private\n */\n _DisableProductMediaLoader: function ($this) {\n var $widget = this;\n\n if ($('body.catalog-product-view').length > 0) {\n $this.parents('.column.main').find('.photo.image')\n .removeClass($widget.options.classes.loader);\n } else {\n //Category View\n $this.parents('.product-item-info').find('.product-image-photo')\n .removeClass($widget.options.classes.loader);\n }\n },\n\n /**\n * Callback for product media\n *\n * @param {Object} $this\n * @param {String} response\n * @param {Boolean} isInProductView\n * @private\n */\n _ProductMediaCallback: function ($this, response, isInProductView) {\n var $main = isInProductView ? $this.parents('.column.main') : $this.parents('.product-item-info'),\n $widget = this,\n images = [],\n\n /**\n * Check whether object supported or not\n *\n * @param {Object} e\n * @returns {*|Boolean}\n */\n support = function (e) {\n return e.hasOwnProperty('large') && e.hasOwnProperty('medium') && e.hasOwnProperty('small');\n };\n\n if (_.size($widget) < 1 || !support(response)) {\n this.updateBaseImage(this.options.mediaGalleryInitial, $main, isInProductView);\n\n return;\n }\n\n images.push({\n full: response.large,\n img: response.medium,\n thumb: response.small,\n isMain: true\n });\n\n if (response.hasOwnProperty('gallery')) {\n $.each(response.gallery, function () {\n if (!support(this) || response.large === this.large) {\n return;\n }\n images.push({\n full: this.large,\n img: this.medium,\n thumb: this.small\n });\n });\n }\n\n this.updateBaseImage(images, $main, isInProductView);\n },\n\n /**\n * Check if images to update are initial and set their type\n * @param {Array} images\n */\n _setImageType: function (images) {\n\n images.map(function (img) {\n if (!img.type) {\n img.type = 'image';\n }\n });\n\n return images;\n },\n\n /**\n * Update [gallery-placeholder] or [product-image-photo]\n * @param {Array} images\n * @param {jQuery} context\n * @param {Boolean} isInProductView\n */\n updateBaseImage: function (images, context, isInProductView) {\n var justAnImage = images[0],\n initialImages = this.options.mediaGalleryInitial,\n imagesToUpdate,\n gallery = context.find(this.options.mediaGallerySelector).data('gallery'),\n isInitial;\n\n if (isInProductView) {\n if (_.isUndefined(gallery)) {\n context.find(this.options.mediaGallerySelector).on('gallery:loaded', function () {\n this.updateBaseImage(images, context, isInProductView);\n }.bind(this));\n\n return;\n }\n\n imagesToUpdate = images.length ? this._setImageType($.extend(true, [], images)) : [];\n isInitial = _.isEqual(imagesToUpdate, initialImages);\n\n if (this.options.gallerySwitchStrategy === 'prepend' && !isInitial) {\n imagesToUpdate = imagesToUpdate.concat(initialImages);\n }\n\n imagesToUpdate = this._setImageIndex(imagesToUpdate);\n\n gallery.updateData(imagesToUpdate);\n this._addFotoramaVideoEvents(isInitial);\n } else if (justAnImage && justAnImage.img) {\n context.find('.product-image-photo').attr('src', justAnImage.img);\n }\n },\n\n /**\n * Add video events\n *\n * @param {Boolean} isInitial\n * @private\n */\n _addFotoramaVideoEvents: function (isInitial) {\n if (_.isUndefined($.mage.AddFotoramaVideoEvents)) {\n return;\n }\n\n if (isInitial) {\n $(this.options.mediaGallerySelector).AddFotoramaVideoEvents();\n\n return;\n }\n\n $(this.options.mediaGallerySelector).AddFotoramaVideoEvents({\n selectedOption: this.getProduct(),\n dataMergeStrategy: this.options.gallerySwitchStrategy\n });\n },\n\n /**\n * Set correct indexes for image set.\n *\n * @param {Array} images\n * @private\n */\n _setImageIndex: function (images) {\n var length = images.length,\n i;\n\n for (i = 0; length > i; i++) {\n images[i].i = i + 1;\n }\n\n return images;\n },\n\n /**\n * Kill doubled AJAX requests\n *\n * @private\n */\n _XhrKiller: function () {\n var $widget = this;\n\n if ($widget.xhr !== undefined && $widget.xhr !== null) {\n $widget.xhr.abort();\n $widget.xhr = null;\n }\n },\n\n /**\n * Emulate mouse click on all swatches that should be selected\n * @param {Object} [selectedAttributes]\n * @private\n */\n _EmulateSelected: function (selectedAttributes) {\n $.each(selectedAttributes, $.proxy(function (attributeCode, optionId) {\n var elem = this.element.find('.' + this.options.classes.attributeClass +\n '[data-attribute-code=\"' + attributeCode + '\"] [data-option-id=\"' + optionId + '\"]'),\n parentInput = elem.parent();\n\n if (elem.hasClass('selected')) {\n return;\n }\n\n if (parentInput.hasClass(this.options.classes.selectClass)) {\n parentInput.val(optionId);\n parentInput.trigger('change');\n } else {\n elem.trigger('click');\n }\n }, this));\n },\n\n /**\n * Emulate mouse click or selection change on all swatches that should be selected\n * @param {Object} [selectedAttributes]\n * @private\n */\n _EmulateSelectedByAttributeId: function (selectedAttributes) {\n $.each(selectedAttributes, $.proxy(function (attributeId, optionId) {\n var elem = this.element.find('.' + this.options.classes.attributeClass +\n '[data-attribute-id=\"' + attributeId + '\"] [data-option-id=\"' + optionId + '\"]'),\n parentInput = elem.parent();\n\n if (elem.hasClass('selected')) {\n return;\n }\n\n if (parentInput.hasClass(this.options.classes.selectClass)) {\n parentInput.val(optionId);\n parentInput.trigger('change');\n } else {\n elem.trigger('click');\n }\n }, this));\n },\n\n /**\n * Get default options values settings with either URL query parameters\n * @private\n */\n _getSelectedAttributes: function () {\n var hashIndex = window.location.href.indexOf('#'),\n selectedAttributes = {},\n params;\n\n if (hashIndex !== -1) {\n params = $.parseQuery(window.location.href.substr(hashIndex + 1));\n\n selectedAttributes = _.invert(_.mapObject(_.invert(params), function (attributeId) {\n var attribute = this.options.jsonConfig.mappedAttributes[attributeId];\n\n return attribute ? attribute.code : attributeId;\n }.bind(this)));\n }\n\n return selectedAttributes;\n },\n\n /**\n * Callback which fired after gallery gets initialized.\n *\n * @param {HTMLElement} element - DOM element associated with a gallery.\n */\n _onGalleryLoaded: function (element) {\n var galleryObject = element.data('gallery');\n\n this.options.mediaGalleryInitial = galleryObject.returnCurrentImages();\n },\n\n /**\n * Sets mediaCache for cases when jsonConfig contains preSelectedGallery on layered navigation result pages\n *\n * @private\n */\n _setPreSelectedGallery: function () {\n var mediaCallData;\n\n if (this.options.jsonConfig.preSelectedGallery) {\n mediaCallData = {\n 'product_id': this.getProduct()\n };\n\n this.options.mediaCache[JSON.stringify(mediaCallData)] = this.options.jsonConfig.preSelectedGallery;\n }\n },\n\n /**\n * Callback for quantity change event.\n */\n _onQtyChanged: function () {\n var $price = this.element.parents(this.options.selectorProduct)\n .find(this.options.selectorProductPrice);\n\n $price.trigger(\n 'updatePrice',\n {\n 'prices': this._getPrices(this._getNewPrices(), $price.priceBox('option').prices)\n }\n );\n }\n });\n\n return $.mage.SwatchRenderer;\n});\n","Magento_Swatches/js/catalog-add-to-cart.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\nrequire([\n 'jquery'\n], function ($) {\n 'use strict';\n\n /**\n * Add selected swatch attributes to redirect url\n *\n * @see Magento_Catalog/js/catalog-add-to-cart\n */\n $('body').on('catalogCategoryAddToCartRedirect', function (event, data) {\n $(data.form).find('[name*=\"super\"]').each(function (index, item) {\n var $item = $(item),\n attr;\n\n if ($item.attr('data-attr-name')) {\n attr = $item.attr('data-attr-name');\n } else {\n attr = $item.parent().attr('attribute-code');\n }\n data.redirectParameters.push(attr + '=' + $item.val());\n\n });\n });\n});\n","Magento_Swatches/js/configurable-customer-data.js":"require([\n 'jquery',\n 'Magento_ConfigurableProduct/js/options-updater'\n], function ($, Updater) {\n 'use strict';\n\n var selectors = {\n formSelector: '#product_addtocart_form',\n swatchSelector: '.swatch-opt'\n },\n swatchWidgetName = 'mage-SwatchRenderer',\n widgetInitEvent = 'swatch.initialized',\n\n /**\n * Sets all configurable swatch attribute's selected values\n */\n updateSwatchOptions = function () {\n var swatchWidget = $(selectors.swatchSelector).data(swatchWidgetName);\n\n if (!swatchWidget || !swatchWidget._EmulateSelectedByAttributeId) {\n return;\n }\n swatchWidget._EmulateSelectedByAttributeId(this.productOptions);\n },\n updater = new Updater(widgetInitEvent, updateSwatchOptions);\n\n updater.listen();\n});\n","Magento_Weee/js/tax-toggle.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n /**\n * @param {Object} config\n * @param {jQuery.Event} e\n */\n function onToggle(config, e) {\n var elem = $(e.currentTarget),\n expandedClassName = config.expandedClassName || 'cart-tax-total-expanded';\n\n elem.toggleClass(expandedClassName);\n\n $(config.itemTaxId).toggle();\n }\n\n return function (data, el) {\n $(el).on('click', onToggle.bind(null, data));\n };\n});\n","Magento_Weee/js/price/adjustment.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'Magento_Ui/js/grid/columns/column'\n], function (Element) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n bodyTmpl: 'Magento_Weee/price/adjustment',\n dataSource: '${ $.parentName }.provider',\n //Weee configuration constants can be configured from backend\n inclFptWithDesc: 1,//show FPT and description\n inclFpt: 0, //show FPT attribute\n exclFpt: 2, //do not show FPT\n bothFptPrices: 3 //show price without FPT and with FPT and with description\n },\n\n /**\n * Get Weee attributes.\n *\n * @param {Object} row\n * @return {HTMLElement} Weee html\n */\n getWeeeAttributes: function (row) {\n return row['price_info']['extension_attributes']['weee_attributes'];\n },\n\n /**\n * Get Weee without Tax attributes.\n *\n * @param {Object} taxAmount\n * @return {HTMLElement} Weee html\n */\n getWeeeTaxWithoutTax: function (taxAmount) {\n return taxAmount['amount_excl_tax'];\n },\n\n /**\n * UnsanitizedHtml version of getWeeeTaxWithoutTax.\n *\n * @param {Object} taxAmount\n * @return {HTMLElement} Weee html\n */\n getWeeeTaxWithoutTaxUnsanitizedHtml: function (taxAmount) {\n return this.getWeeeTaxWithoutTax(taxAmount);\n },\n\n /**\n * Get Weee with Tax attributes.\n *\n * @param {Object} taxAmount\n * @return {HTMLElement} Weee html\n */\n getWeeeTaxWithTax: function (taxAmount) {\n return taxAmount['tax_amount_incl_tax'];\n },\n\n /**\n * UnsanitizedHtml version of getWeeeTaxWithTax.\n *\n * @param {Object} taxAmount\n * @return {HTMLElement} Weee html\n */\n getWeeeTaxWithTaxUnsanitizedHtml: function (taxAmount) {\n return this.getWeeeTaxWithTax(taxAmount);\n },\n\n /**\n * Get Weee Tax name.\n *\n * @param {String} taxAmount\n * @return {String} Weee name\n */\n getWeeTaxAttributeName: function (taxAmount) {\n return taxAmount['attribute_code'];\n },\n\n /**\n * Set price 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 * Check if Weee Tax must be shown.\n *\n * @param {Object} row\n * @return {Boolean}\n */\n isShown: function (row) {\n return row['price_info']['extension_attributes']['weee_attributes'].length;\n },\n\n /**\n * Get Weee final price.\n *\n * @param {Object} row\n * @return {HTMLElement} Weee final price html\n */\n getWeeeAdjustment: function (row) {\n return row['price_info']['extension_attributes']['weee_adjustment'];\n },\n\n /**\n * UnsanitizedHtml version of getWeeeAdjustment.\n *\n * @param {Object} row\n * @return {HTMLElement} Weee final price html\n */\n getWeeeAdjustmentUnsanitizedHtml: function (row) {\n return this.getWeeeAdjustment(row);\n },\n\n /**\n * Return whether display setting is to display price including FPT only.\n *\n * @return {Boolean}\n */\n displayPriceInclFpt: function () {\n return +this.source.data.displayWeee === this.inclFpt;\n },\n\n /**\n * Return whether display setting is to display\n * price including FPT and FPT description.\n *\n * @return {Boolean}\n */\n displayPriceInclFptDescr: function () {\n return +this.source.data.displayWeee === this.inclFptWithDesc;\n },\n\n /**\n * Return whether display setting is to display price\n * excluding FPT but including FPT description and final price.\n *\n * @return {Boolean}\n */\n displayPriceExclFptDescr: function () {\n return +this.source.data.displayWeee === this.exclFpt;\n },\n\n /**\n * Return whether display setting is to display price excluding FPT.\n *\n * @return {Boolean}\n */\n displayPriceExclFpt: function () {\n return +this.source.data.displayWeee === this.bothFptPrices;\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.inclFptWithDesc;\n },\n\n /**\n * Return whether display setting is to display price including tax.\n *\n * @return {Boolean}\n */\n displayPriceInclTax: function () {\n return +this.source.data.displayTaxes === this.exclFpt;\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 displayBothPricesTax: function () {\n return +this.source.data.displayTaxes === this.bothFptPrices;\n }\n });\n});\n","Magento_Weee/js/view/cart/totals/weee.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Weee/js/view/checkout/summary/weee'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n\n /**\n * @override\n */\n isFullMode: function () {\n return true;\n }\n });\n});\n","Magento_Weee/js/view/checkout/summary/weee.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_Checkout/js/model/totals',\n 'Magento_Catalog/js/price-utils'\n], function (Component, quote, totals) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Weee/checkout/summary/weee'\n },\n isIncludedInSubtotal: window.checkoutConfig.isIncludedInSubtotal,\n totals: totals.totals,\n\n /**\n * @returns {Number}\n */\n getWeeeTaxSegment: function () {\n var weee = totals.getSegment('weee_tax') || totals.getSegment('weee');\n\n if (weee !== null && weee.hasOwnProperty('value')) {\n return weee.value;\n }\n\n return 0;\n },\n\n /**\n * Get weee value\n * @returns {String}\n */\n getValue: function () {\n return this.getFormattedPrice(this.getWeeeTaxSegment());\n },\n\n /**\n * Weee display flag\n * @returns {Boolean}\n */\n isDisplayed: function () {\n return this.isFullMode() && this.getWeeeTaxSegment() > 0;\n }\n });\n});\n","Magento_Weee/js/view/checkout/summary/item/price/row_incl_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_Weee/js/view/checkout/summary/item/price/weee'\n], function (weee) {\n 'use strict';\n\n return weee.extend({\n defaults: {\n template: 'Magento_Weee/checkout/summary/item/price/row_incl_tax',\n displayArea: 'row_incl_tax'\n },\n\n /**\n * @param {Object} item\n * @return {Number}\n */\n getFinalRowDisplayPriceInclTax: function (item) {\n var rowTotalInclTax = parseFloat(item['row_total_incl_tax']);\n\n if (!window.checkoutConfig.getIncludeWeeeFlag) {\n rowTotalInclTax += this.getRowWeeeTaxInclTax(item);\n }\n\n return rowTotalInclTax;\n },\n\n /**\n * @param {Object} item\n * @return {Number}\n */\n getRowDisplayPriceInclTax: function (item) {\n var rowTotalInclTax = parseFloat(item['row_total_incl_tax']);\n\n if (window.checkoutConfig.getIncludeWeeeFlag) {\n rowTotalInclTax += this.getRowWeeeTaxInclTax(item);\n }\n\n return rowTotalInclTax;\n },\n\n /**\n * @param {Object}item\n * @return {Number}\n */\n getRowWeeeTaxInclTax: function (item) {\n var totalWeeeTaxInclTaxApplied = 0,\n weeeTaxAppliedAmounts;\n\n if (item['weee_tax_applied']) {\n weeeTaxAppliedAmounts = JSON.parse(item['weee_tax_applied']);\n weeeTaxAppliedAmounts.forEach(function (weeeTaxAppliedAmount) {\n totalWeeeTaxInclTaxApplied += parseFloat(Math.max(weeeTaxAppliedAmount['row_amount_incl_tax'], 0));\n });\n }\n\n return totalWeeeTaxInclTaxApplied;\n }\n\n });\n});\n","Magento_Weee/js/view/checkout/summary/item/price/row_excl_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_Weee/js/view/checkout/summary/item/price/weee'\n], function (weee) {\n 'use strict';\n\n return weee.extend({\n defaults: {\n template: 'Magento_Weee/checkout/summary/item/price/row_excl_tax'\n },\n\n /**\n * @param {Object} item\n * @return {Number}\n */\n getFinalRowDisplayPriceExclTax: function (item) {\n var rowTotalExclTax = parseFloat(item['row_total']);\n\n if (!window.checkoutConfig.getIncludeWeeeFlag) {\n rowTotalExclTax += parseFloat(item['qty']) *\n parseFloat(item['weee_tax_applied_amount']);\n }\n\n return rowTotalExclTax;\n },\n\n /**\n * @param {Object} item\n * @return {Number}\n */\n getRowDisplayPriceExclTax: function (item) {\n var rowTotalExclTax = parseFloat(item['row_total']);\n\n if (window.checkoutConfig.getIncludeWeeeFlag) {\n rowTotalExclTax += this.getRowWeeeTaxExclTax(item);\n }\n\n return rowTotalExclTax;\n },\n\n /**\n * @param {Object} item\n * @return {Number}\n */\n getRowWeeeTaxExclTax: function (item) {\n var totalWeeeTaxExclTaxApplied = 0,\n weeeTaxAppliedAmounts;\n\n if (item['weee_tax_applied']) {\n weeeTaxAppliedAmounts = JSON.parse(item['weee_tax_applied']);\n weeeTaxAppliedAmounts.forEach(function (weeeTaxAppliedAmount) {\n totalWeeeTaxExclTaxApplied += parseFloat(Math.max(weeeTaxAppliedAmount['row_amount'], 0));\n });\n }\n\n return totalWeeeTaxExclTaxApplied;\n }\n\n });\n});\n","Magento_Weee/js/view/checkout/summary/item/price/weee.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) {\n 'use strict';\n\n return Component.extend({\n /**\n * @param {Object} item\n * @return {Boolean}\n */\n isDisplayPriceWithWeeeDetails: function (item) {\n if (!parseFloat(item['weee_tax_applied_amount']) || parseFloat(item['weee_tax_applied_amount'] <= 0)) {\n return false;\n }\n\n return window.checkoutConfig.isDisplayPriceWithWeeeDetails;\n },\n\n /**\n * @param {Object} item\n * @return {Boolean}\n */\n isDisplayFinalPrice: function (item) {\n if (!parseFloat(item['weee_tax_applied_amount'])) {\n return false;\n }\n\n return window.checkoutConfig.isDisplayFinalPrice;\n },\n\n /**\n * @param {Object} item\n * @return {Array}\n */\n getWeeeTaxApplied: function (item) {\n if (item['weee_tax_applied']) {\n return JSON.parse(item['weee_tax_applied']);\n }\n\n return [];\n }\n });\n});\n","Magento_Translation/js/i18n-config.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n(function () {\n 'use strict';\n\n require.config({\n config: {\n 'Magento_Ui/js/lib/knockout/bindings/i18n': {\n inlineTranslation: true\n }\n }\n });\n})();\n","Magento_Translation/js/mage-translation-dictionary.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'text!js-translation.json'\n], function (dict) {\n 'use strict';\n\n return JSON.parse(dict);\n});\n","Magento_Translation/js/add-class.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).addClass(config.class);\n };\n});\n","Amasty_Label/js/initLabel.js":"/**\n * Initialize Module depends on the area\n * @return widget\n */\n\ndefine([\n 'jquery',\n 'Amasty_Label/vendor/tooltipster/js/tooltipster.min',\n 'Amasty_Label/js/label',\n 'matchMedia',\n 'domReady!'\n// eslint-disable-next-line no-unused-vars\n], function ($, tooltipster) {\n 'use strict';\n\n $.widget('mage.amInitLabel', {\n options: {\n mode: null,\n isAdminArea: null,\n config: null,\n productId: null,\n selector: null\n },\n classes: {\n amSearchSection: 'amsearch-products-section'\n },\n tooltipVendorClass: 'tooltip',\n mediaBreakpoint: 'all and (max-width: 768px)',\n\n /**\n * @inheritDoc\n */\n _create: function () {\n var self = this,\n element = self.element.closest('.product-item, .item');\n\n // remove label duplication\n if (this.element.parent().hasClass(this.classes.amSearchSection)\n && this.element.parent().find(this.options.selector).length > 1) {\n return;\n }\n\n this.renderTooltip();\n\n // observe only on category pages and without swatches\n if (self.options.mode === 'prod'\n || self.options.isAdminArea\n || self.element.hasClass('amlabel-swatch')\n || self.isIE()\n ) {\n self.execLabel();\n } else if (self.options.mode === 'cat' && element.length && !self.element.hasClass('amlabel-swatch')) {\n self._handleIntersect(element);\n } else {\n self.execLabel();\n }\n },\n\n /**\n * Exec Amasty Label widget\n * @public\n * @returns {void}\n */\n execLabel: function () {\n this.element.amShowLabel(this.options.config);\n },\n\n /**\n * @public\n * @returns {Boolean}\n */\n isIE: function () {\n var ua = window.navigator.userAgent;\n\n return ua.indexOf('MSIE ') > -1 || ua.indexOf('Trident/') > -1;\n },\n\n /**\n * @public\n * @returns {void}\n */\n renderTooltip: function () {\n var tooltipOptions = this.options.config.tooltip,\n tooltipContent = decodeURIComponent(tooltipOptions.content);\n\n if (this._isHiddenOnMobile()) {\n return;\n }\n\n if (+tooltipOptions.status > 1 && tooltipContent && !this._isEmpty(tooltipContent)) {\n this.element.addClass(this.tooltipVendorClass).tooltipster({\n theme: 'tooltipster-shadow',\n interactive: true,\n content: $('<span>', {\n html: tooltipContent\n }),\n styles: {\n backgroundColor: tooltipOptions.backgroundColor,\n textColor: tooltipOptions.color\n }\n });\n }\n },\n\n /**\n * @param {String} html\n * @private\n * @returns {Boolean}\n */\n _isEmpty: function (html) {\n return html === null || html.match(/^ *$/) !== null;\n },\n\n /**\n * @private\n * @returns {Boolean}\n */\n _isHiddenOnMobile: function () {\n return matchMedia(this.mediaBreakpoint).matches && +this.options.config.tooltip.status === 3;\n },\n\n /**\n * Use IntersectionObserver to lazy loading Amasty Label widget\n *\n * @param {Object} element\n * @protected\n * @returns {function}\n */\n _handleIntersect: function (element) {\n var self = this,\n observer;\n\n observer = new IntersectionObserver(function (entries) {\n if (entries[0].isIntersecting) {\n self.execLabel();\n observer.disconnect();\n }\n });\n\n observer.observe(element[0]);\n }\n });\n\n return $.mage.amInitLabel;\n});\n","Amasty_Label/js/label.js":"define([\n 'jquery',\n 'underscore',\n 'Magento_Ui/js/modal/modal'\n], function ($, _) {\n 'use strict';\n\n $.widget('mage.amShowLabel', {\n options: {},\n textElement: null,\n image: null,\n imageWidth: null,\n imageHeight: null,\n parent: null,\n imageLabel: ['.amasty-label-container', '.amasty-label-image', '.amlabel-text'],\n fotoramaStage: '[data-fotorama-stage=\"fotorama__stage\"]',\n galleryPlaceholder: '[data-gallery-role=\"gallery-placeholder\"]',\n positionWrapper: 'amlabel-position-wrapper',\n mainContainer: '[data-gallery-role=\"amasty-main-container\"]',\n slickSlider: {\n selectors: {\n slider: '.slick-slider',\n slide: '.slick-slide'\n },\n classes: {\n cloned: 'slick-cloned',\n initialized: 'slick-initialized'\n }\n },\n\n /**\n * @inheritDoc\n * @private\n */\n _create: function () {\n var items,\n priceContainer,\n newParent,\n me;\n\n this.parentResizeListener = new ResizeObserver(function () {\n this.setLabelStyle();\n this._refreshSLickSlider();\n }.bind(this));\n\n this.element = $(this.element);\n\n if (this.element.attr('amlabel-js-observed')) {\n return;\n }\n\n this.element.attr('amlabel-js-observed', 1);\n\n /* code for moving product label */\n if (this.options.move === 1) {\n items = this.element.closest('.page-wrapper').find(this.getPriceSelector());\n\n if (items.length) { // find any element with product 'id'\n items = this._filterItems(items);\n\n priceContainer = items.first();\n newParent = this.getNewParent(priceContainer);\n\n // eslint-disable-next-line max-depth\n if (newParent && newParent.length) {\n priceContainer.attr('label-observered-' + this.options.label, '1');\n newParent.append(this.element);\n } else {\n this.element.hide();\n\n return;\n }\n } else {\n this.element.hide();\n\n return;\n }\n }\n\n this.image = this.element.find('.amasty-label-image');\n this.textElement = this.element.find('.amlabel-text');\n this.parent = this.element.parent();\n\n if (!this.image.length) {\n this.setStyleIfNotExist(\n this.element,\n {\n 'width': '100px',\n 'height': '50px'\n }\n );\n }\n\n if (!this.image.length && this.options.position.includes('center')) {\n this.textElement.addClass('-am-centered');\n }\n\n /* move label to container from settings*/\n if (this.options.path && this.options.path !== '') {\n newParent = this.parent.find(this.options.path);\n\n if (newParent.length) {\n this.parent = newParent;\n newParent.append(this.element);\n }\n }\n\n /* required for child position absolute */\n if (!(this.parent.css('position') === 'absolute' || this.parent.css('position') === 'relative')) {\n this.parent.css('position', 'relative');\n }\n\n if (this.parent.prop('tagName') === 'A' && !this.parent.closest('.block.widget').hasClass('list')) {\n this.parent.css('display', 'block');\n }\n\n /* fix issue with hover on product grid */\n if (!this.element.closest('.sidebar').length) {\n this.element.closest('.product-item-info').css('zIndex', '996');\n }\n\n /* get default image size */\n if (!this.imageLoaded(this.image)) {\n me = this;\n\n this.image.on('load', function () {\n me.element.fadeIn();\n me.imageWidth = this.naturalWidth;\n me.imageHeight = this.naturalHeight;\n me.setLabelStyle();\n });\n } else {\n this.element.fadeIn();\n\n if (this.image[0]) {\n this.imageWidth = this.image[0].naturalWidth;\n this.imageHeight = this.image[0].naturalHeight;\n }\n }\n\n this.setLabelPosition();\n this.updateStyles();\n\n /* observe zoom load event for moving label*/\n this.productPageZoomEvent();\n this.createResizeEvent();\n this.createFotoramaEvent();\n this.createRedirectEvent();\n this._refreshSLickSlider();\n },\n\n /**\n * @returns {void}\n */\n _refreshSLickSlider: function () {\n var slider = this.element.closest(this.slickSlider.selectors.slider);\n\n if (slider.length && slider.hasClass(this.slickSlider.classes.initialized)) {\n slider.slick('refresh');\n }\n },\n\n /**\n * Skip labels from slick slider cloned nodes,\n * Skip labels that already exist in the product container,\n * Skip labels from bundle packs\n *\n * @param {Array} items\n * @return {Array}\n */\n _filterItems: function (items) {\n return items.filter(function (index, element) {\n return !$(element).closest(this.slickSlider.selectors.slide).hasClass(this.slickSlider.classes.cloned)\n && !$(element).closest('.amrelated-pack-item').length\n && !$(element).closest('.product-item-info')\n .find('.amasty-label-container-' + this.options.label + '-' + this.options.product + '-cat')\n .length;\n }.bind(this));\n },\n\n /**\n * @return {void}\n */\n createRedirectEvent: function () {\n this.element.on('click', function (e) {\n this.openLink(e);\n }.bind(this));\n },\n\n /**\n * @param {event} event\n * @return {void}\n */\n openLink: function (event) {\n var redirectUrl = this.options['redirect_url'];\n\n if (redirectUrl && !this.isEmpty(redirectUrl)) {\n event.preventDefault();\n window.open(redirectUrl, '_blank');\n }\n },\n\n /**\n * @return {void}\n */\n createResizeEvent: function () {\n $(window).on('resize', _.debounce(function () {\n this.reloadParentSize();\n }.bind(this), 300));\n\n $(window).on('orientationchange', function () {\n this.reloadParentSize();\n }.bind(this));\n },\n\n /**\n * @return {void}\n */\n createFotoramaEvent: function () {\n $(this.galleryPlaceholder).on('fotorama:load', this.updatePositionInFotorama.bind(this));\n },\n\n /**\n * @return {void}\n */\n updatePositionInFotorama: function () {\n var self = this,\n newParent = this.parent.find(this.options.path),\n elementToMove = null;\n\n if (this\n && this.options.path\n && this.options.mode === 'prod'\n ) {\n if (newParent.length && newParent !== this.parent) {\n this.parent.css('position', '');\n this.parent = newParent;\n\n elementToMove = this.element.parent().hasClass(this.positionWrapper)\n ? this.element.parent()\n : this.element;\n newParent.append(elementToMove);\n newParent.css({ 'position': 'relative' });\n\n self.setLabelsEventOnFotorama();\n }\n }\n },\n\n setLabelsEventOnFotorama: function () {\n var self = this,\n fotoramaStage = $(this.fotoramaStage),\n mousedownOnFotoramaStage = $._data(fotoramaStage[0], 'events').mousedown,\n pointerdownOnFotoramaStage = $._data(fotoramaStage[0], 'events').pointerdown;\n\n if (!fotoramaStage[0].eventsUpdated) {\n fotoramaStage.on('mousedown pointerdown', function (e) {\n if (e.which === 1 && $(e.target).is(self.imageLabel.join(','))) {\n $(this).trigger('focusout');\n self.openLink(e);\n e.stopImmediatePropagation();\n }\n });\n\n // eslint-disable-next-line max-depth\n if (fotoramaStage.length && mousedownOnFotoramaStage) {\n mousedownOnFotoramaStage.unshift(mousedownOnFotoramaStage.pop());\n }\n\n if (fotoramaStage.length && pointerdownOnFotoramaStage) {\n pointerdownOnFotoramaStage.unshift(pointerdownOnFotoramaStage.pop());\n }\n\n fotoramaStage[0].eventsUpdated = true;\n }\n },\n\n /**\n * @param {Object} img\n * @return {boolean}\n */\n imageLoaded: function (img) {\n return !(!img.complete\n || typeof img.naturalWidth !== 'undefined' && img.naturalWidth === 0);\n },\n\n /**\n * @return {void}\n */\n productPageZoomEvent: function () {\n var amastyGallery = $(this.mainContainerSelector);\n\n if (this.options.mode === 'prod') {\n if (amastyGallery.length) {\n this.parent = amastyGallery;\n amastyGallery.append(this.element.parent());\n amastyGallery.css('position', 'relative');\n }\n }\n },\n\n /**\n * @return {void}\n */\n updateStyles: function () {\n this.setLabelStyle();\n this.setLabelPosition();\n },\n\n /**\n * @param {Object} element\n * @param {Object} styles\n * @return {void}\n */\n setStyleIfNotExist: function (element, styles) {\n // eslint-disable-next-line guard-for-in, vars-on-top\n for (var style in styles) {\n // eslint-disable-next-line\n var current = element.attr('style');\n\n if (!current ||\n current.indexOf('; ' + style) === -1 && current.indexOf(';' + style) === -1\n ) {\n // eslint-disable-next-line no-undef\n element.css(style, styles[style]);\n }\n }\n },\n\n /**\n * @return {void}\n */\n setLabelStyle: function () {\n var parentWidth,\n tmpWidth,\n tmpHeight,\n lineCount,\n redirectUrl = this.options['redirect_url'],\n display = this.options.alignment === 1 ? 'inline-block' : 'block';\n\n /* for text element */\n this.setStyleIfNotExist(\n this.textElement,\n {\n 'padding': '0 3px',\n 'position': 'absolute',\n 'box-sizing': 'border-box',\n 'white-space': 'nowrap',\n 'width': '100%'\n }\n );\n\n if (this.image.length) {\n /* for image */\n this.image.css({ 'width': '100%' });\n\n /* get block size depend settings */\n if (this.options.size > 0) {\n parentWidth = Math.round(this.parent.css('width').replace(/[^\\d.]/g, ''));\n\n if (!parentWidth) {\n this.parentResizeListener.observe(this.parent[0]);\n\n return;\n }\n\n // eslint-disable-next-line max-depth\n if (parentWidth) {\n this.parentResizeListener.disconnect();\n // eslint-disable-next-line no-mixed-operators\n this.imageWidth = Math.round(parentWidth * this.options.size / 100);\n }\n } else {\n this.imageWidth += 'px';\n }\n\n this.setStyleIfNotExist(this.element, { 'width': this.imageWidth });\n this.imageHeight = this.image.height();\n\n /* if container doesn't load(height = 0 ) set proportional height */\n if (!this.imageHeight && this.image[0] && this.image[0].naturalWidth !== 0) {\n tmpWidth = this.image[0].naturalWidth;\n tmpHeight = this.image[0].naturalHeight;\n\n this.imageHeight = Math.round(this.imageWidth * (tmpHeight / tmpWidth));\n }\n\n lineCount = this.textElement.html().split('<br>').length;\n lineCount = lineCount >= 1 ? lineCount : 1;\n this.textElement.css('lineHeight', Math.round(this.imageHeight / lineCount) + 'px');\n\n /* for whole block */\n if (this.imageHeight) {\n this.setStyleIfNotExist(this.element, {\n 'height': this.imageHeight + 'px'\n });\n }\n\n this._fitLabelText();\n }\n\n this.image\n .attr('width', this.image.width() + 'px')\n .attr('height', this.image.height() + 'px');\n\n this.element.parent().css({\n 'line-height': 'normal',\n 'position': 'absolute'\n });\n\n // dont reload display for configurable child label. visibility child label processed in reload.js\n if (!this.element.hasClass('amlabel-swatch')) {\n this.setStyleIfNotExist(\n this.element,\n {\n 'position': 'relative',\n 'display': display\n }\n );\n }\n\n if (redirectUrl && !this.isEmpty(redirectUrl)) {\n this.element.addClass('-link');\n }\n\n this.reloadParentSize();\n },\n\n /**\n * @return {void}\n */\n _fitLabelText: function () {\n if (this.options.size) {\n var flag = 1;\n\n this.textElement.css({ 'width': 'auto' });\n this.textElement.parent().css('display', 'block');\n\n while (this.textElement.width() > 0.9 * this.textElement.parent().width() && flag++ < 15) {\n this.textElement.css({ 'fontSize': 100 - flag * 5 + '%' });\n }\n\n this.textElement.parent().css('display', 'none');\n this.textElement.css({ 'width': '100%' });\n }\n },\n\n /**\n * @param {*} html\n * @return {Boolean}\n */\n isEmpty: function (html) {\n return html === null || html.match(/^ *$/) !== null;\n },\n\n setPosition: function (position) {\n this.options.position = position;\n this.setLabelPosition();\n this.reloadParentSize();\n },\n\n /**\n * @return {void}\n */\n setStyle: function () {\n this.setLabelStyle();\n },\n\n /**\n * @return {void}\n */\n reloadParentSize: function () {\n var parent = this.element.parent(),\n height = null,\n width = 5;\n\n parent.css({\n 'position': 'relative',\n 'display': 'inline-block',\n 'width': 'auto',\n 'height': 'auto'\n });\n\n height = parent.height();\n\n if (this.options.alignment === 1) {\n parent.children().each(function (index, element) {\n width += $(element).width() + parseInt($(element).css('margin-left'), 10)\n + parseInt($(element).css('margin-right'), 10);\n });\n } else {\n width = parent.width();\n }\n\n parent.css({\n 'position': 'absolute',\n 'display': 'block',\n 'height': height ? height + 'px' : '',\n 'width': width ? width + 'px' : ''\n });\n },\n\n /**\n * @return {string}\n */\n getWidgetLabelCode: function () {\n var label = '';\n\n if (this.element.parents('.widget-product-grid, .widget').length) {\n label = 'widget';\n }\n\n return label;\n },\n\n /**\n * @return {*|void}\n */\n setLabelPosition: function () {\n var parent,\n labelOrderMatch,\n className = 'amlabel-position-' + this.options.position\n + '-' + this.options.product + '-' + this.options.mode + this.getWidgetLabelCode(),\n wrapper = this.parent.find('.' + className);\n\n if (wrapper.length) {\n labelOrderMatch = false;\n\n $.each(wrapper.find('.amasty-label-container'), function (index, prevLabel) {\n var nextLabel = $(prevLabel).next(),\n currentOrder = parseInt(this.options.order, 10),\n prevOrder = null,\n nextOrder = null;\n\n if ($(prevLabel).length && $(prevLabel).data('mageAmShowLabel')) {\n prevOrder = parseInt($(prevLabel).data('mageAmShowLabel').options.order, 10);\n }\n\n if (nextLabel.length && $(nextLabel).data('mageAmShowLabel')) {\n nextOrder = parseInt(nextLabel.data('mageAmShowLabel').options.order, 10);\n }\n\n if (currentOrder >= prevOrder && (!nextOrder || currentOrder <= nextOrder)) {\n labelOrderMatch = true;\n\n $(prevLabel).after(this.element);\n\n return false;\n }\n }.bind(this));\n\n if (!labelOrderMatch) {\n wrapper.prepend(this.element);\n }\n } else {\n parent = this.element.parent();\n if (parent.hasClass(this.positionWrapper)) {\n parent.parent().html(this.element);\n }\n\n this.element.wrap('<div class=\"' + className + ' ' + this.positionWrapper + '\"></div>');\n wrapper = this.element.parent();\n }\n\n if (this.options.alignment === 1) {\n wrapper.children(':not(:first-child)').each(function (index, element) {\n this.setStyleIfNotExist(\n $(element),\n {\n 'marginLeft': this.options.margin + 'px'\n }\n );\n }.bind(this));\n } else {\n wrapper.children(':not(:first-child)').each(function (index, element) {\n this.setStyleIfNotExist(\n $(element),\n {\n 'marginTop': this.options.margin + 'px'\n }\n );\n }.bind(this));\n }\n\n // clear styles before changing\n wrapper.css({\n 'top': '',\n 'left': '',\n 'right': '',\n 'bottom': '',\n 'margin-top': '',\n 'margin-bottom': '',\n 'margin-left': '',\n 'margin-right': ''\n });\n\n switch (this.options.position) {\n case 'top-left':\n wrapper.css({\n 'top': 0,\n 'left': 0\n });\n break;\n case 'top-center':\n wrapper.css({\n 'top': 0,\n 'left': 0,\n 'right': 0,\n 'margin-left': 'auto',\n 'margin-right': 'auto'\n });\n break;\n case 'top-right':\n wrapper.css({\n 'top': 0,\n 'right': 0,\n 'text-align': 'right'\n });\n break;\n\n case 'middle-left':\n wrapper.css({\n 'left': 0,\n 'top': 0,\n 'bottom': 0,\n 'margin-top': 'auto',\n 'margin-bottom': 'auto'\n });\n break;\n case 'middle-center':\n wrapper.css({\n 'top': 0,\n 'bottom': 0,\n 'margin-top': 'auto',\n 'margin-bottom': 'auto',\n 'left': 0,\n 'right': 0,\n 'margin-left': 'auto',\n 'margin-right': 'auto'\n });\n break;\n case 'middle-right':\n wrapper.css({\n 'top': 0,\n 'bottom': 0,\n 'margin-top': 'auto',\n 'margin-bottom': 'auto',\n 'right': 0,\n 'text-align': 'right'\n });\n break;\n\n case 'bottom-left':\n wrapper.css({\n 'bottom': 0,\n 'left': 0\n });\n break;\n case 'bottom-center':\n wrapper.css({\n 'bottom': 0,\n 'left': 0,\n 'right': 0,\n 'margin-left': 'auto',\n 'margin-right': 'auto'\n });\n break;\n case 'bottom-right':\n wrapper.css({\n 'bottom': 0,\n 'right': 0,\n 'text-align': 'right'\n });\n break;\n }\n },\n\n /**\n * @param {jQuery} item\n * @return {jQuery | null}\n */\n getNewParent: function (item) {\n var imageContainer = null,\n productContainer = item.closest('.item.product');\n\n if (!productContainer.length) {\n productContainer = item.closest('.product-item');\n }\n\n if (productContainer && productContainer.length) {\n imageContainer = productContainer.find(this.options.path).first();\n }\n\n return imageContainer;\n },\n\n /**\n * @return {string}\n */\n getPriceSelector: function () {\n var notLabelObservered = ':not([label-observered-' + this.options.label + '])';\n\n return '[data-product-id=\"' + this.options.product + '\"]' + notLabelObservered + ', ' +\n '[id=\"product-price-' + this.options.product + '\"]' + notLabelObservered + ', ' +\n '[name=\"product\"][value=\"' + this.options.product + '\"]' + notLabelObservered;\n }\n });\n\n return $.mage.amShowLabel;\n});\n","Amasty_Label/js/configurable/configurable.js":"define([\n 'jquery',\n 'underscore',\n 'Amasty_Label/js/configurable/reload',\n 'Magento_Ui/js/modal/modal'\n], function ($, _, reloader) {\n 'use strict';\n\n return function (widget) {\n $.widget('mage.configurable', widget, {\n /**\n * Trigger label reload\n *\n * @return {void}\n */\n _processLabelReload: function () {\n var productId = this.simpleProduct,\n imageContainer = null,\n originalProductId = this.options.spConfig['original_product_id'];\n\n if (this.inProductList) {\n imageContainer = this.element.closest('li.item').find(this.options.spConfig['label_category']);\n } else {\n imageContainer = this.element.closest('.column.main').find(this.options.spConfig['label_product']);\n }\n\n if (!productId) {\n productId = this.options.spConfig['original_product_id'];\n }\n\n if (typeof this.options.spConfig['label_reload'] != 'undefined') {\n reloader.reload(\n imageContainer,\n productId,\n this.options.spConfig['label_reload'],\n this.inProductList ? 1 : 0,\n originalProductId\n );\n }\n },\n\n /**\n * OVERRIDE\n *\n * @inheritDoc\n */\n _changeProductImage: function (noLabel) {\n if (noLabel !== true) {\n this._processLabelReload();\n }\n\n var images,\n initialImages = this.options.mediaGalleryInitial,\n gallery = $(this.options.mediaGallerySelector).data('gallery');\n\n if (_.isUndefined(gallery)) {\n $(this.options.mediaGallerySelector).on('gallery:loaded', function () {\n this._changeProductImage(true); // skip label reloading to prevent duplicates\n }.bind(this));\n\n return;\n }\n\n images = this.options.spConfig.images[this.simpleProduct];\n\n if (images) {\n images = this._sortImages(images);\n\n if (this.options.gallerySwitchStrategy === 'prepend') {\n images = images.concat(initialImages);\n }\n\n images = $.extend(true, [], images);\n images = this._setImageIndex(images);\n\n gallery.updateData(images);\n this._addFotoramaVideoEvents(false);\n } else {\n gallery.updateData(initialImages);\n this._addFotoramaVideoEvents(true);\n }\n }\n });\n\n return $.mage.configurable;\n };\n});\n","Amasty_Label/js/configurable/reload.js":"define([\n 'jquery',\n 'underscore'\n], function ($, _) {\n 'use strict';\n\n return {\n cache: new Map(),\n xhrRequest: null,\n selectors: {\n imageContainer: '.product-image-container',\n postDataElement: '.action[data-post]'\n },\n\n /**\n * @param {String | jQuery} container\n * @param {object} data\n *\n * @private\n */\n reloadLabels: function (container, data) {\n var self = this,\n postData;\n\n if (!data.labels) {\n return;\n }\n\n if (typeof container !== 'string') {\n var label = data.labels instanceof Object ? Object.values(data.labels)[0] : data.labels;\n\n container.find('.amasty-label-container').remove();\n label = container.last().after(label);\n label.trigger('contentUpdated');\n\n return;\n }\n\n $(container).each(function (index, item) {\n postData = JSON.parse($(item).find(self.selectors.postDataElement).attr('data-post'));\n\n $(item).find(self.selectors.imageContainer)\n .after(data.labels[postData.data.product])\n .trigger('contentUpdated');\n });\n },\n\n /**\n * @param {string} url\n * @param {object} params\n * @param {function} callback\n *\n * @private\n */\n doAjax: function (url, params, callback) {\n if (this.xhrRequest !== null) {\n this.xhrRequest.abort();\n }\n\n this.xhrRequest = $.ajax({\n url: url,\n data: params,\n method: 'GET',\n cache: true,\n dataType: 'json',\n showLoader: false,\n success: function (data) {\n var cacheKey = this.generateCacheKey(params);\n\n this.cache.set(cacheKey, data);\n callback(data);\n }.bind(this)\n });\n },\n\n /**\n * @param {object} params\n *\n * @private\n */\n generateCacheKey: function (params) {\n var processedEntry;\n\n return Object.entries(params).reduce(function (carry, entry) {\n processedEntry = typeof entry[1] === 'object' ? entry[1].join('-') : entry[1];\n\n return carry + '_' + entry[0] + '_' + processedEntry;\n }, '');\n },\n\n /**\n * @param {String | jQuery} container\n * @param {number | Array} productId\n * @param {string} reloadUrl\n * @param {boolean} inProductList\n */\n reload: function (container, productId, reloadUrl, inProductList) {\n var imageBlock = $(container).find('.amasty-label-for-' + productId),\n params = {\n product_ids: _.isArray(productId) ? productId.join(',') : productId,\n in_product_list: inProductList\n },\n cacheKey = this.generateCacheKey(params);\n\n if (this.cache.has(cacheKey)) {\n this.reloadLabels(container, this.cache.get(cacheKey));\n } else {\n this.doAjax(reloadUrl, params, this.reloadLabels.bind(this, container));\n }\n\n imageBlock.show();\n }\n };\n});\n","Amasty_Label/js/configurable/swatch-renderer.js":"define([\n 'jquery',\n 'Amasty_Label/js/configurable/reload',\n 'Amasty_Label/js/initLabel'\n], function ($, reloader) {\n 'use strict';\n\n return function (widget) {\n $.widget('mage.SwatchRenderer', widget, {\n _loadMedia: function () {\n if (!window.isAmSwatchClickTriggered) {\n this.loadLabels();\n } else {\n window.isAmSwatchClickTriggered = false;\n }\n\n return this._super();\n },\n\n _LoadProductMedia: function () {\n this.loadLabels();\n\n return this._super();\n },\n\n loadLabels: function () {\n var productIds = this._CalcProducts(),\n imageContainer = null;\n\n if (this.inProductList) {\n imageContainer = this.element.closest('li.item')\n .find(this.options.jsonConfig['label_category']);\n } else {\n imageContainer = this.element.closest('.column.main')\n .find(this.options.jsonConfig['label_product']);\n }\n\n if (productIds.length === 0) {\n productIds.push(this.options.jsonConfig['original_product_id']);\n }\n\n if (typeof this.options.jsonConfig['label_reload'] != 'undefined') {\n !this.inProductList ?? imageContainer.find('.amlabel-position-wrapper').remove();\n reloader.reload(\n imageContainer,\n productIds[0],\n this.options.jsonConfig['label_reload'],\n this.inProductList ? 1 : 0\n );\n }\n }\n });\n\n return $.mage.SwatchRenderer;\n };\n});\n","Amasty_Label/js/uiWidget/amLoadUiLabel.js":"define([\n 'jquery',\n 'underscore',\n 'Amasty_Label/js/configurable/reload',\n 'mage/url',\n 'Magento_Customer/js/customer-data',\n 'Magento_Catalog/js/product/view/product-ids-resolver',\n 'uiRegistry'\n], function ($, _, reloader, url, customerData, productResolver, registry) {\n 'use strict';\n\n $.widget('mage.amInitLabelUi', {\n options: {\n config: null,\n productsLifetime: 1000,\n scope: 'group'\n },\n selectors: {\n widgetWrapper: '[data-bind=\"scope: \\'%1.%2\\'\"]',\n imageContainer: '.block-viewed-products-grid .product-item-info',\n addToCartForm: '#product_addtocart_form'\n },\n modules: {\n recentlyViewed: 'ns = widget_recently_viewed'\n },\n controller: 'amasty_label/ajax/label',\n\n /**\n * Widget constructor.\n * @protected\n */\n _create: function () {\n this.uiWidget('trigger', true);\n },\n\n /**\n * @public\n * @return {Object}\n */\n uiWidget: function () {\n return registry.get(this.modules.recentlyViewed, function (component) {\n this.setLabelHtml(component);\n }.bind(this));\n },\n\n /**\n * @public\n * @return {void}\n */\n setLabelHtml: function (component) {\n var self = this,\n idsData = Object.keys(component.ids()\n ? component.ids()\n : this.filterIds(JSON.parse(window.localStorage.getItem('recently_viewed_product')))),\n target = $(this.selectors.widgetWrapper\n .replace('%1', component.dataScope)\n .replace('%2', component.ns)),\n isSyncWidgetWithBackend = +component.idsStorage.allowToSendRequest,\n options = {\n childList: true,\n subtree: true\n },\n observer;\n\n if (!idsData.length && !isSyncWidgetWithBackend) {\n return;\n }\n\n observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n if (mutation.type === 'childList'\n && mutation.previousSibling\n && typeof mutation.previousSibling.dataset !== 'undefined'\n && typeof mutation.previousSibling.dataset.post !== 'undefined'\n ) {\n reloader.reload(\n self.selectors.imageContainer,\n isSyncWidgetWithBackend ? Object.keys(component.ids()) : idsData,\n url.build(self.controller),\n true\n );\n\n observer.disconnect();\n }\n });\n });\n\n observer.observe(target[0], options);\n },\n\n /**\n * @param ids\n * @public\n * @return {Object}\n */\n filterIds: function (ids) {\n var result = {},\n lifetime = this.options.productsLifetime,\n currentTime = new Date().getTime() / 1000,\n currentProductIds = productResolver($(this.selectors.addToCartForm)),\n productCurrentScope = this.options.scope,\n scopeId = productCurrentScope === 'store' ? window.checkout.storeId :\n productCurrentScope === 'group' ? window.checkout.storeGroupId :\n window.checkout.websiteId;\n\n _.each(ids, function (id, key) {\n if (\n currentTime - ids[key]['added_at'] < lifetime &&\n !_.contains(currentProductIds, ids[key]['product_id']) &&\n (!id.hasOwnProperty('scope_id') || ids[key]['scope_id'] === scopeId)\n ) {\n result[id['product_id']] = id;\n }\n }, this);\n\n return result;\n }\n });\n\n return $.mage.amInitLabelUi;\n});\n","Amasty_Label/vendor/tooltipster/js/tooltipster.min.js":"!function(t,i){\"function\"==typeof define&&define.amd?define([\"jquery\"],function(t){return i(t)}):\"object\"==typeof exports?module.exports=i(require(\"jquery\")):i(jQuery)}(0,function(t){var i={animation:\"fade\",animationDuration:350,content:null,contentAsHTML:!1,contentCloning:!1,debug:!0,delay:300,delayTouch:[300,500],functionInit:null,functionBefore:null,functionReady:null,functionAfter:null,functionFormat:null,IEmin:6,interactive:!1,multiple:!1,parent:null,plugins:[\"sideTip\"],repositionOnScroll:!1,restoration:\"none\",selfDestruction:!0,theme:[],timer:0,trackerInterval:500,trackOrigin:!1,trackTooltip:!1,trigger:\"hover\",triggerClose:{click:!1,mouseleave:!1,originClick:!1,scroll:!1,tap:!1,touchleave:!1},triggerOpen:{click:!1,mouseenter:!1,tap:!1,touchstart:!1},updateAnimation:\"rotate\",zIndex:9999999,styles:{backgroundColor:\"\",textColor:\"\"}},o=\"undefined\"!=typeof window?window:null,e={hasTouchCapability:!(!o||!(\"ontouchstart\"in o||o.DocumentTouch&&o.document instanceof o.DocumentTouch||o.navigator.maxTouchPoints)),hasTransitions:function(){if(!o)return!1;var t=(o.document.body||o.document.documentElement).style,i=\"transition\",e=[\"Moz\",\"Webkit\",\"Khtml\",\"O\",\"ms\"];if(\"string\"==typeof t[i])return!0;i=i.charAt(0).toUpperCase()+i.substr(1);for(var n=0;n<e.length;n++)if(\"string\"==typeof t[e[n]+i])return!0;return!1}(),IE:!1,semVer:\"4.2.8\",window:o},n=function(){this.__$emitterPrivate=t({}),this.__$emitterPublic=t({}),this.__instancesLatestArr=[],this.__plugins={},this._env=e};function s(t){this.$container,this.constraints=null,this.__$tooltip,this.__init(t)}function r(i,o){var e=!0;return t.each(i,function(t,n){if(void 0===o[t]||i[t]!==o[t])return e=!1,!1}),e}function _(i){var o=i.attr(\"id\"),n=o?e.window.document.getElementById(o):null;return n?n===i[0]:t.contains(e.window.document.body,i[0])}n.prototype={__bridge:function(o,e,n){if(!e[n]){var s=function(){};s.prototype=o;var r=new s;r.__init&&r.__init(e),t.each(o,function(t,o){0!=t.indexOf(\"__\")&&(e[t]?i.debug&&console.log(\"The \"+t+\" method of the \"+n+\" plugin conflicts with another plugin or native methods\"):(e[t]=function(){return r[t].apply(r,Array.prototype.slice.apply(arguments))},e[t].bridged=r))}),e[n]=r}return this},__setWindow:function(t){return e.window=t,this},_getRuler:function(t){return new s(t)},_off:function(){return this.__$emitterPrivate.off.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_on:function(){return this.__$emitterPrivate.on.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_one:function(){return this.__$emitterPrivate.one.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_plugin:function(i){if(\"string\"==typeof i){var o=i,e=null;return o.indexOf(\".\")>0?e=this.__plugins[o]:t.each(this.__plugins,function(t,i){if(i.name.substring(i.name.length-o.length-1)==\".\"+o)return e=i,!1}),e}if(i.name.indexOf(\".\")<0)throw new Error(\"Plugins must be namespaced\");return this.__plugins[i.name]=i,i.core&&this.__bridge(i.core,this,i.name),this},_trigger:function(){var t=Array.prototype.slice.apply(arguments);return\"string\"==typeof t[0]&&(t[0]={type:t[0]}),this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate,t),this.__$emitterPublic.trigger.apply(this.__$emitterPublic,t),this},instances:function(i){var o=[];return t(i||\".tooltipstered\").each(function(){var i=t(this),e=i.data(\"tooltipster-ns\");e&&t.each(e,function(t,e){o.push(i.data(e))})}),o},instancesLatest:function(){return this.__instancesLatestArr},off:function(){return this.__$emitterPublic.off.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},on:function(){return this.__$emitterPublic.on.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},one:function(){return this.__$emitterPublic.one.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},origins:function(i){return t((i?i+\" \":\"\")+\".tooltipstered\").toArray()},setDefaults:function(o){return t.extend(i,o),this},triggerHandler:function(){return this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this}},t.tooltipster=new n,t.Tooltipster=function(i,o){this.__callbacks={close:[],open:[]},this.__closingTime,this.__Content,this.__contentBcr,this.__destroyed=!1,this.__$emitterPrivate=t({}),this.__$emitterPublic=t({}),this.__enabled=!0,this.__garbageCollector,this.__Geometry,this.__lastPosition,this.__namespace=\"tooltipster-\"+Math.round(1e6*Math.random()),this.__options,this.__$originParents,this.__pointerIsOverOrigin=!1,this.__previousThemes=[],this.__state=\"closed\",this.__timeouts={close:[],open:null},this.__touchEvents=[],this.__tracker=null,this._$origin,this._$tooltip,this.__init(i,o)},t.Tooltipster.prototype={__init:function(o,n){var s=this;if(s._$origin=t(o),s.__options=t.extend(!0,{},i,n),s.__optionsFormat(),!e.IE||e.IE>=s.__options.IEmin){var r=null;if(void 0===s._$origin.data(\"tooltipster-initialTitle\")&&(void 0===(r=s._$origin.attr(\"title\"))&&(r=null),s._$origin.data(\"tooltipster-initialTitle\",r)),null!==s.__options.content)s.__contentSet(s.__options.content);else{var _,a=s._$origin.attr(\"data-tooltip-content\");a&&(_=t(a)),_&&_[0]?s.__contentSet(_.first()):s.__contentSet(r)}s._$origin.removeAttr(\"title\").addClass(\"tooltipstered\"),s.__prepareOrigin(),s.__prepareGC(),t.each(s.__options.plugins,function(t,i){s._plug(i)}),e.hasTouchCapability&&t(e.window.document.body).on(\"touchmove.\"+s.__namespace+\"-triggerOpen\",function(t){s._touchRecordEvent(t)}),s._on(\"created\",function(){s.__prepareTooltip()})._on(\"repositioned\",function(t){s.__lastPosition=t.position})}else s.__options.disabled=!0},__contentInsert:function(){var t=this._$tooltip.find(\".tooltipster-content\"),i=this.__Content;return this._trigger({type:\"format\",content:this.__Content,format:function(t){i=t}}),this.__options.functionFormat&&(i=this.__options.functionFormat.call(this,this,{origin:this._$origin[0]},this.__Content)),\"string\"!=typeof i||this.__options.contentAsHTML?t.empty().append(i):t.text(i),this},__contentSet:function(i){return i instanceof t&&this.__options.contentCloning&&(i=i.clone(!0)),this.__Content=i,this._trigger({type:\"updated\",content:i}),this},__destroyError:function(){throw new Error(\"This tooltip has been destroyed and cannot execute your method call.\")},__geometry:function(){var i=this._$origin,o=this._$origin.is(\"area\");if(o){var n=this._$origin.parent().attr(\"name\");i=t('img[usemap=\"#'+n+'\"]')}var s=i[0].getBoundingClientRect(),r=t(e.window.document),_=t(e.window),a=i,l={available:{document:null,window:null},document:{size:{height:r.height(),width:r.width()}},window:{scroll:{left:e.window.scrollX||e.window.document.documentElement.scrollLeft,top:e.window.scrollY||e.window.document.documentElement.scrollTop},size:{height:_.height(),width:_.width()}},origin:{fixedLineage:!1,offset:{},size:{height:s.bottom-s.top,width:s.right-s.left},usemapImage:o?i[0]:null,windowOffset:{bottom:s.bottom,left:s.left,right:s.right,top:s.top}}};if(o){var p=this._$origin.attr(\"shape\"),c=this._$origin.attr(\"coords\");if(c&&(c=c.split(\",\"),t.map(c,function(t,i){c[i]=parseInt(t)})),\"default\"!=p)switch(p){case\"circle\":var h=c[0],d=c[1],u=c[2],g=d-u,f=h-u;l.origin.size.height=2*u,l.origin.size.width=l.origin.size.height,l.origin.windowOffset.left+=f,l.origin.windowOffset.top+=g;break;case\"rect\":var m=c[0],w=c[1],v=c[2],y=c[3];l.origin.size.height=y-w,l.origin.size.width=v-m,l.origin.windowOffset.left+=m,l.origin.windowOffset.top+=w;break;case\"poly\":for(var b=0,$=0,C=0,O=0,T=\"even\",z=0;z<c.length;z++){var E=c[z];\"even\"==T?(E>C&&(C=E,0===z&&(b=C)),E<b&&(b=E),T=\"odd\"):(E>O&&(O=E,1==z&&($=O)),E<$&&($=E),T=\"even\")}l.origin.size.height=O-$,l.origin.size.width=C-b,l.origin.windowOffset.left+=b,l.origin.windowOffset.top+=$}}for(this._trigger({type:\"geometry\",edit:function(t){l.origin.size.height=t.height,l.origin.windowOffset.left=t.left,l.origin.windowOffset.top=t.top,l.origin.size.width=t.width},geometry:{height:l.origin.size.height,left:l.origin.windowOffset.left,top:l.origin.windowOffset.top,width:l.origin.size.width}}),l.origin.windowOffset.right=l.origin.windowOffset.left+l.origin.size.width,l.origin.windowOffset.bottom=l.origin.windowOffset.top+l.origin.size.height,l.origin.offset.left=l.origin.windowOffset.left+l.window.scroll.left,l.origin.offset.top=l.origin.windowOffset.top+l.window.scroll.top,l.origin.offset.bottom=l.origin.offset.top+l.origin.size.height,l.origin.offset.right=l.origin.offset.left+l.origin.size.width,l.available.document={bottom:{height:l.document.size.height-l.origin.offset.bottom,width:l.document.size.width},left:{height:l.document.size.height,width:l.origin.offset.left},right:{height:l.document.size.height,width:l.document.size.width-l.origin.offset.right},top:{height:l.origin.offset.top,width:l.document.size.width}},l.available.window={bottom:{height:Math.max(l.window.size.height-Math.max(l.origin.windowOffset.bottom,0),0),width:l.window.size.width},left:{height:l.window.size.height,width:Math.max(l.origin.windowOffset.left,0)},right:{height:l.window.size.height,width:Math.max(l.window.size.width-Math.max(l.origin.windowOffset.right,0),0)},top:{height:Math.max(l.origin.windowOffset.top,0),width:l.window.size.width}};\"html\"!=a[0].tagName.toLowerCase();){if(\"fixed\"==a.css(\"position\")){l.origin.fixedLineage=!0;break}a=a.parent()}return l},__optionsFormat:function(){return\"number\"==typeof this.__options.animationDuration&&(this.__options.animationDuration=[this.__options.animationDuration,this.__options.animationDuration]),\"number\"==typeof this.__options.delay&&(this.__options.delay=[this.__options.delay,this.__options.delay]),\"number\"==typeof this.__options.delayTouch&&(this.__options.delayTouch=[this.__options.delayTouch,this.__options.delayTouch]),\"string\"==typeof this.__options.theme&&(this.__options.theme=[this.__options.theme]),null===this.__options.parent?this.__options.parent=t(e.window.document.body):\"string\"==typeof this.__options.parent&&(this.__options.parent=t(this.__options.parent)),\"hover\"==this.__options.trigger?(this.__options.triggerOpen={mouseenter:!0,touchstart:!0},this.__options.triggerClose={mouseleave:!0,originClick:!0,touchleave:!0}):\"click\"==this.__options.trigger&&(this.__options.triggerOpen={click:!0,tap:!0},this.__options.triggerClose={click:!0,tap:!0}),this._trigger(\"options\"),this},__prepareGC:function(){var i=this;return i.__options.selfDestruction?i.__garbageCollector=setInterval(function(){var o=(new Date).getTime();i.__touchEvents=t.grep(i.__touchEvents,function(t,i){return o-t.time>6e4}),_(i._$origin)||i.close(function(){i.destroy()})},2e4):clearInterval(i.__garbageCollector),i},__prepareOrigin:function(){var t=this;if(t._$origin.off(\".\"+t.__namespace+\"-triggerOpen\"),e.hasTouchCapability&&t._$origin.on(\"touchstart.\"+t.__namespace+\"-triggerOpen touchend.\"+t.__namespace+\"-triggerOpen touchcancel.\"+t.__namespace+\"-triggerOpen\",function(i){t._touchRecordEvent(i)}),t.__options.triggerOpen.click||t.__options.triggerOpen.tap&&e.hasTouchCapability){var i=\"\";t.__options.triggerOpen.click&&(i+=\"click.\"+t.__namespace+\"-triggerOpen \"),t.__options.triggerOpen.tap&&e.hasTouchCapability&&(i+=\"touchend.\"+t.__namespace+\"-triggerOpen\"),t._$origin.on(i,function(i){t._touchIsMeaningfulEvent(i)&&t._open(i)})}if(t.__options.triggerOpen.mouseenter||t.__options.triggerOpen.touchstart&&e.hasTouchCapability){i=\"\";t.__options.triggerOpen.mouseenter&&(i+=\"mouseenter.\"+t.__namespace+\"-triggerOpen \"),t.__options.triggerOpen.touchstart&&e.hasTouchCapability&&(i+=\"touchstart.\"+t.__namespace+\"-triggerOpen\"),t._$origin.on(i,function(i){!t._touchIsTouchEvent(i)&&t._touchIsEmulatedEvent(i)||(t.__pointerIsOverOrigin=!0,t._openShortly(i))})}if(t.__options.triggerClose.mouseleave||t.__options.triggerClose.touchleave&&e.hasTouchCapability){i=\"\";t.__options.triggerClose.mouseleave&&(i+=\"mouseleave.\"+t.__namespace+\"-triggerOpen \"),t.__options.triggerClose.touchleave&&e.hasTouchCapability&&(i+=\"touchend.\"+t.__namespace+\"-triggerOpen touchcancel.\"+t.__namespace+\"-triggerOpen\"),t._$origin.on(i,function(i){t._touchIsMeaningfulEvent(i)&&(t.__pointerIsOverOrigin=!1)})}return t},__prepareTooltip:function(){var i=this,o=i.__options.interactive?\"auto\":\"\";return i._$tooltip.attr(\"id\",i.__namespace).css({\"pointer-events\":o,zIndex:i.__options.zIndex}),t.each(i.__previousThemes,function(t,o){i._$tooltip.removeClass(o)}),t.each(i.__options.theme,function(t,o){i._$tooltip.addClass(o)}),i.__previousThemes=t.merge([],i.__options.theme),i},__scrollHandler:function(i){if(this.__options.triggerClose.scroll)this._close(i);else if(_(this._$origin)&&_(this._$tooltip)){var o=null;if(i.target===e.window.document)this.__Geometry.origin.fixedLineage||this.__options.repositionOnScroll&&this.reposition(i);else{o=this.__geometry();var n=!1;if(\"fixed\"!=this._$origin.css(\"position\")&&this.__$originParents.each(function(i,e){var s=t(e),r=s.css(\"overflow-x\"),_=s.css(\"overflow-y\");if(\"visible\"!=r||\"visible\"!=_){var a=e.getBoundingClientRect();if(\"visible\"!=r&&(o.origin.windowOffset.left<a.left||o.origin.windowOffset.right>a.right))return n=!0,!1;if(\"visible\"!=_&&(o.origin.windowOffset.top<a.top||o.origin.windowOffset.bottom>a.bottom))return n=!0,!1}if(\"fixed\"==s.css(\"position\"))return!1}),n)this._$tooltip.css(\"visibility\",\"hidden\");else if(this._$tooltip.css(\"visibility\",\"visible\"),this.__options.repositionOnScroll)this.reposition(i);else{var s=o.origin.offset.left-this.__Geometry.origin.offset.left,r=o.origin.offset.top-this.__Geometry.origin.offset.top;this._$tooltip.css({left:this.__lastPosition.coord.left+s,top:this.__lastPosition.coord.top+r})}}this._trigger({type:\"scroll\",event:i,geo:o})}return this},__stateSet:function(t){return this.__state=t,this._trigger({type:\"state\",state:t}),this},__timeoutsClear:function(){return clearTimeout(this.__timeouts.open),this.__timeouts.open=null,t.each(this.__timeouts.close,function(t,i){clearTimeout(i)}),this.__timeouts.close=[],this},__trackerStart:function(){var t=this,i=t._$tooltip.find(\".tooltipster-content\");return t.__options.trackTooltip&&(t.__contentBcr=i[0].getBoundingClientRect()),t.__tracker=setInterval(function(){if(_(t._$origin)&&_(t._$tooltip)){if(t.__options.trackOrigin){var o=t.__geometry(),e=!1;r(o.origin.size,t.__Geometry.origin.size)&&(t.__Geometry.origin.fixedLineage?r(o.origin.windowOffset,t.__Geometry.origin.windowOffset)&&(e=!0):r(o.origin.offset,t.__Geometry.origin.offset)&&(e=!0)),e||(t.__options.triggerClose.mouseleave?t._close():t.reposition())}if(t.__options.trackTooltip){var n=i[0].getBoundingClientRect();n.height===t.__contentBcr.height&&n.width===t.__contentBcr.width||(t.reposition(),t.__contentBcr=n)}}else t._close()},t.__options.trackerInterval),t},_close:function(i,o,n){var s=this,r=!0;if(s._trigger({type:\"close\",event:i,stop:function(){r=!1}}),r||n){o&&s.__callbacks.close.push(o),s.__callbacks.open=[],s.__timeoutsClear();var _=function(){t.each(s.__callbacks.close,function(t,o){o.call(s,s,{event:i,origin:s._$origin[0]})}),s.__callbacks.close=[]};if(\"closed\"!=s.__state){var a=!0,l=(new Date).getTime()+s.__options.animationDuration[1];if(\"disappearing\"==s.__state&&l>s.__closingTime&&s.__options.animationDuration[1]>0&&(a=!1),a){s.__closingTime=l,\"disappearing\"!=s.__state&&s.__stateSet(\"disappearing\");var p=function(){clearInterval(s.__tracker),s._trigger({type:\"closing\",event:i}),s._$tooltip.off(\".\"+s.__namespace+\"-triggerClose\").removeClass(\"tooltipster-dying\"),t(e.window).off(\".\"+s.__namespace+\"-triggerClose\"),s.__$originParents.each(function(i,o){t(o).off(\"scroll.\"+s.__namespace+\"-triggerClose\")}),s.__$originParents=null,t(e.window.document.body).off(\".\"+s.__namespace+\"-triggerClose\"),s._$origin.off(\".\"+s.__namespace+\"-triggerClose\"),s._off(\"dismissable\"),s.__stateSet(\"closed\"),s._trigger({type:\"after\",event:i}),s.__options.functionAfter&&s.__options.functionAfter.call(s,s,{event:i,origin:s._$origin[0]}),_()};e.hasTransitions?(s._$tooltip.css({\"-moz-animation-duration\":s.__options.animationDuration[1]+\"ms\",\"-ms-animation-duration\":s.__options.animationDuration[1]+\"ms\",\"-o-animation-duration\":s.__options.animationDuration[1]+\"ms\",\"-webkit-animation-duration\":s.__options.animationDuration[1]+\"ms\",\"animation-duration\":s.__options.animationDuration[1]+\"ms\",\"transition-duration\":s.__options.animationDuration[1]+\"ms\"}),s._$tooltip.clearQueue().removeClass(\"tooltipster-show\").addClass(\"tooltipster-dying\"),s.__options.animationDuration[1]>0&&s._$tooltip.delay(s.__options.animationDuration[1]),s._$tooltip.queue(p)):s._$tooltip.stop().fadeOut(s.__options.animationDuration[1],p)}}else _()}return s},_off:function(){return this.__$emitterPrivate.off.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_on:function(){return this.__$emitterPrivate.on.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_one:function(){return this.__$emitterPrivate.one.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_open:function(i,o){var n=this;if(!n.__destroying&&_(n._$origin)&&n.__enabled){var s=!0;if(\"closed\"==n.__state&&(n._trigger({type:\"before\",event:i,stop:function(){s=!1}}),s&&n.__options.functionBefore&&(s=n.__options.functionBefore.call(n,n,{event:i,origin:n._$origin[0]}))),!1!==s&&null!==n.__Content){o&&n.__callbacks.open.push(o),n.__callbacks.close=[],n.__timeoutsClear();var r,a=function(){\"stable\"!=n.__state&&n.__stateSet(\"stable\"),t.each(n.__callbacks.open,function(t,i){i.call(n,n,{origin:n._$origin[0],tooltip:n._$tooltip[0]})}),n.__callbacks.open=[]};if(\"closed\"!==n.__state)r=0,\"disappearing\"===n.__state?(n.__stateSet(\"appearing\"),e.hasTransitions?(n._$tooltip.clearQueue().removeClass(\"tooltipster-dying\").addClass(\"tooltipster-show\"),n.__options.animationDuration[0]>0&&n._$tooltip.delay(n.__options.animationDuration[0]),n._$tooltip.queue(a)):n._$tooltip.stop().fadeIn(a)):\"stable\"==n.__state&&a();else{if(n.__stateSet(\"appearing\"),r=n.__options.animationDuration[0],n.__contentInsert(),n.reposition(i,!0),e.hasTransitions?(n._$tooltip.addClass(\"tooltipster-\"+n.__options.animation).addClass(\"tooltipster-initial\").css({\"-moz-animation-duration\":n.__options.animationDuration[0]+\"ms\",\"-ms-animation-duration\":n.__options.animationDuration[0]+\"ms\",\"-o-animation-duration\":n.__options.animationDuration[0]+\"ms\",\"-webkit-animation-duration\":n.__options.animationDuration[0]+\"ms\",\"animation-duration\":n.__options.animationDuration[0]+\"ms\",\"transition-duration\":n.__options.animationDuration[0]+\"ms\"}),setTimeout(function(){\"closed\"!=n.__state&&(n._$tooltip.addClass(\"tooltipster-show\").removeClass(\"tooltipster-initial\"),n.__options.animationDuration[0]>0&&n._$tooltip.delay(n.__options.animationDuration[0]),n._$tooltip.queue(a))},0)):n._$tooltip.css(\"display\",\"none\").fadeIn(n.__options.animationDuration[0],a),n.__trackerStart(),t(e.window).on(\"resize.\"+n.__namespace+\"-triggerClose\",function(i){var o=t(document.activeElement);(o.is(\"input\")||o.is(\"textarea\"))&&t.contains(n._$tooltip[0],o[0])||n.reposition(i)}).on(\"scroll.\"+n.__namespace+\"-triggerClose\",function(t){n.__scrollHandler(t)}),n.__$originParents=n._$origin.parents(),n.__$originParents.each(function(i,o){t(o).on(\"scroll.\"+n.__namespace+\"-triggerClose\",function(t){n.__scrollHandler(t)})}),n.__options.triggerClose.mouseleave||n.__options.triggerClose.touchleave&&e.hasTouchCapability){n._on(\"dismissable\",function(t){t.dismissable?t.delay?(h=setTimeout(function(){n._close(t.event)},t.delay),n.__timeouts.close.push(h)):n._close(t):clearTimeout(h)});var l=n._$origin,p=\"\",c=\"\",h=null;n.__options.interactive&&(l=l.add(n._$tooltip)),n.__options.triggerClose.mouseleave&&(p+=\"mouseenter.\"+n.__namespace+\"-triggerClose \",c+=\"mouseleave.\"+n.__namespace+\"-triggerClose \"),n.__options.triggerClose.touchleave&&e.hasTouchCapability&&(p+=\"touchstart.\"+n.__namespace+\"-triggerClose\",c+=\"touchend.\"+n.__namespace+\"-triggerClose touchcancel.\"+n.__namespace+\"-triggerClose\"),l.on(c,function(t){if(n._touchIsTouchEvent(t)||!n._touchIsEmulatedEvent(t)){var i=\"mouseleave\"==t.type?n.__options.delay:n.__options.delayTouch;n._trigger({delay:i[1],dismissable:!0,event:t,type:\"dismissable\"})}}).on(p,function(t){!n._touchIsTouchEvent(t)&&n._touchIsEmulatedEvent(t)||n._trigger({dismissable:!1,event:t,type:\"dismissable\"})})}n.__options.triggerClose.originClick&&n._$origin.on(\"click.\"+n.__namespace+\"-triggerClose\",function(t){n._touchIsTouchEvent(t)||n._touchIsEmulatedEvent(t)||n._close(t)}),(n.__options.triggerClose.click||n.__options.triggerClose.tap&&e.hasTouchCapability)&&setTimeout(function(){if(\"closed\"!=n.__state){var i=\"\",o=t(e.window.document.body);n.__options.triggerClose.click&&(i+=\"click.\"+n.__namespace+\"-triggerClose \"),n.__options.triggerClose.tap&&e.hasTouchCapability&&(i+=\"touchend.\"+n.__namespace+\"-triggerClose\"),o.on(i,function(i){n._touchIsMeaningfulEvent(i)&&(n._touchRecordEvent(i),n.__options.interactive&&t.contains(n._$tooltip[0],i.target)||n._close(i))}),n.__options.triggerClose.tap&&e.hasTouchCapability&&o.on(\"touchstart.\"+n.__namespace+\"-triggerClose\",function(t){n._touchRecordEvent(t)})}},0),n._trigger(\"ready\"),n.__options.functionReady&&n.__options.functionReady.call(n,n,{origin:n._$origin[0],tooltip:n._$tooltip[0]})}if(n.__options.timer>0){h=setTimeout(function(){n._close()},n.__options.timer+r);n.__timeouts.close.push(h)}}}return n},_openShortly:function(t){var i=this,o=!0;if(\"stable\"!=i.__state&&\"appearing\"!=i.__state&&!i.__timeouts.open&&(i._trigger({type:\"start\",event:t,stop:function(){o=!1}}),o)){var e=0==t.type.indexOf(\"touch\")?i.__options.delayTouch:i.__options.delay;e[0]?i.__timeouts.open=setTimeout(function(){i.__timeouts.open=null,i.__pointerIsOverOrigin&&i._touchIsMeaningfulEvent(t)?(i._trigger(\"startend\"),i._open(t)):i._trigger(\"startcancel\")},e[0]):(i._trigger(\"startend\"),i._open(t))}return i},_optionsExtract:function(i,o){var e=this,n=t.extend(!0,{},o),s=e.__options[i];return s||(s={},t.each(o,function(t,i){var o=e.__options[t];void 0!==o&&(s[t]=o)})),t.each(n,function(i,o){void 0!==s[i]&&(\"object\"!=typeof o||o instanceof Array||null==o||\"object\"!=typeof s[i]||s[i]instanceof Array||null==s[i]?n[i]=s[i]:t.extend(n[i],s[i]))}),n},_plug:function(i){var o=t.tooltipster._plugin(i);if(!o)throw new Error('The \"'+i+'\" plugin is not defined');return o.instance&&t.tooltipster.__bridge(o.instance,this,o.name),this},_touchIsEmulatedEvent:function(t){for(var i=!1,o=(new Date).getTime(),e=this.__touchEvents.length-1;e>=0;e--){var n=this.__touchEvents[e];if(!(o-n.time<500))break;n.target===t.target&&(i=!0)}return i},_touchIsMeaningfulEvent:function(t){return this._touchIsTouchEvent(t)&&!this._touchSwiped(t.target)||!this._touchIsTouchEvent(t)&&!this._touchIsEmulatedEvent(t)},_touchIsTouchEvent:function(t){return 0==t.type.indexOf(\"touch\")},_touchRecordEvent:function(t){return this._touchIsTouchEvent(t)&&(t.time=(new Date).getTime(),this.__touchEvents.push(t)),this},_touchSwiped:function(t){for(var i=!1,o=this.__touchEvents.length-1;o>=0;o--){var e=this.__touchEvents[o];if(\"touchmove\"==e.type){i=!0;break}if(\"touchstart\"==e.type&&t===e.target)break}return i},_trigger:function(){var i=Array.prototype.slice.apply(arguments);return\"string\"==typeof i[0]&&(i[0]={type:i[0]}),i[0].instance=this,i[0].origin=this._$origin?this._$origin[0]:null,i[0].tooltip=this._$tooltip?this._$tooltip[0]:null,this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate,i),t.tooltipster._trigger.apply(t.tooltipster,i),this.__$emitterPublic.trigger.apply(this.__$emitterPublic,i),this},_unplug:function(i){var o=this;if(o[i]){var e=t.tooltipster._plugin(i);e.instance&&t.each(e.instance,function(t,e){o[t]&&o[t].bridged===o[i]&&delete o[t]}),o[i].__destroy&&o[i].__destroy(),delete o[i]}return o},close:function(t){return this.__destroyed?this.__destroyError():this._close(null,t),this},content:function(t){var i=this;if(void 0===t)return i.__Content;if(i.__destroyed)i.__destroyError();else if(i.__contentSet(t),null!==i.__Content){if(\"closed\"!==i.__state&&(i.__contentInsert(),i.reposition(),i.__options.updateAnimation))if(e.hasTransitions){var o=i.__options.updateAnimation;i._$tooltip.addClass(\"tooltipster-update-\"+o),setTimeout(function(){\"closed\"!=i.__state&&i._$tooltip.removeClass(\"tooltipster-update-\"+o)},1e3)}else i._$tooltip.fadeTo(200,.5,function(){\"closed\"!=i.__state&&i._$tooltip.fadeTo(200,1)})}else i._close();return i},destroy:function(){var i=this;if(i.__destroyed)i.__destroyError();else{\"closed\"!=i.__state?i.option(\"animationDuration\",0)._close(null,null,!0):i.__timeoutsClear(),i._trigger(\"destroy\"),i.__destroyed=!0,i._$origin.removeData(i.__namespace).off(\".\"+i.__namespace+\"-triggerOpen\"),t(e.window.document.body).off(\".\"+i.__namespace+\"-triggerOpen\");var o=i._$origin.data(\"tooltipster-ns\");if(o)if(1===o.length){var n=null;\"previous\"==i.__options.restoration?n=i._$origin.data(\"tooltipster-initialTitle\"):\"current\"==i.__options.restoration&&(n=\"string\"==typeof i.__Content?i.__Content:t(\"<div></div>\").append(i.__Content).html()),n&&i._$origin.attr(\"title\",n),i._$origin.removeClass(\"tooltipstered\"),i._$origin.removeData(\"tooltipster-ns\").removeData(\"tooltipster-initialTitle\")}else o=t.grep(o,function(t,o){return t!==i.__namespace}),i._$origin.data(\"tooltipster-ns\",o);i._trigger(\"destroyed\"),i._off(),i.off(),i.__Content=null,i.__$emitterPrivate=null,i.__$emitterPublic=null,i.__options.parent=null,i._$origin=null,i._$tooltip=null,t.tooltipster.__instancesLatestArr=t.grep(t.tooltipster.__instancesLatestArr,function(t,o){return i!==t}),clearInterval(i.__garbageCollector)}return i},disable:function(){return this.__destroyed?(this.__destroyError(),this):(this._close(),this.__enabled=!1,this)},elementOrigin:function(){if(!this.__destroyed)return this._$origin[0];this.__destroyError()},elementTooltip:function(){return this._$tooltip?this._$tooltip[0]:null},enable:function(){return this.__enabled=!0,this},hide:function(t){return this.close(t)},instance:function(){return this},off:function(){return this.__destroyed||this.__$emitterPublic.off.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},on:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.on.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},one:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.one.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},open:function(t){return this.__destroyed?this.__destroyError():this._open(null,t),this},option:function(i,o){return void 0===o?this.__options[i]:(this.__destroyed?this.__destroyError():(this.__options[i]=o,this.__optionsFormat(),t.inArray(i,[\"trigger\",\"triggerClose\",\"triggerOpen\"])>=0&&this.__prepareOrigin(),\"selfDestruction\"===i&&this.__prepareGC()),this)},reposition:function(t,i){return this.__destroyed?this.__destroyError():\"closed\"!=this.__state&&_(this._$origin)&&(i||_(this._$tooltip))&&(i||this._$tooltip.detach(),this.__Geometry=this.__geometry(),this._trigger({type:\"reposition\",event:t,helper:{geo:this.__Geometry}})),this},show:function(t){return this.open(t)},status:function(){return{destroyed:this.__destroyed,enabled:this.__enabled,open:\"closed\"!==this.__state,state:this.__state}},triggerHandler:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this}},t.fn.tooltipster=function(){var o=Array.prototype.slice.apply(arguments),e=\"You are using a single HTML element as content for several tooltips. You probably want to set the contentCloning option to TRUE.\";if(0===this.length)return this;if(\"string\"==typeof o[0]){var n=\"#*$~&\";return this.each(function(){var i=t(this).data(\"tooltipster-ns\"),s=i?t(this).data(i[0]):null;if(!s)throw new Error(\"You called Tooltipster's \\\"\"+o[0]+'\" method on an uninitialized element');if(\"function\"!=typeof s[o[0]])throw new Error('Unknown method \"'+o[0]+'\"');this.length>1&&\"content\"==o[0]&&(o[1]instanceof t||\"object\"==typeof o[1]&&null!=o[1]&&o[1].tagName)&&!s.__options.contentCloning&&s.__options.debug&&console.log(e);var r=s[o[0]](o[1],o[2]);if(r!==s||\"instance\"===o[0])return n=r,!1}),\"#*$~&\"!==n?n:this}t.tooltipster.__instancesLatestArr=[];var s=o[0]&&void 0!==o[0].multiple,r=s&&o[0].multiple||!s&&i.multiple,_=o[0]&&void 0!==o[0].content,a=_&&o[0].content||!_&&i.content,l=o[0]&&void 0!==o[0].contentCloning,p=l&&o[0].contentCloning||!l&&i.contentCloning,c=o[0]&&void 0!==o[0].debug,h=c&&o[0].debug||!c&&i.debug;return this.length>1&&(a instanceof t||\"object\"==typeof a&&null!=a&&a.tagName)&&!p&&h&&console.log(e),this.each(function(){var i=!1,e=t(this),n=e.data(\"tooltipster-ns\"),s=null;n?r?i=!0:h&&(console.log(\"Tooltipster: one or more tooltips are already attached to the element below. Ignoring.\"),console.log(this)):i=!0,i&&(s=new t.Tooltipster(this,o[0]),n||(n=[]),n.push(s.__namespace),e.data(\"tooltipster-ns\",n),e.data(s.__namespace,s),s.__options.functionInit&&s.__options.functionInit.call(s,s,{origin:this}),s._trigger(\"init\")),t.tooltipster.__instancesLatestArr.push(s)}),this},s.prototype={__init:function(i){this.__$tooltip=i,this.__$tooltip.css({left:0,overflow:\"hidden\",position:\"absolute\",top:0}).find(\".tooltipster-content\").css(\"overflow\",\"auto\"),this.$container=t('<div class=\"tooltipster-ruler\"></div>').append(this.__$tooltip).appendTo(e.window.document.body)},__forceRedraw:function(){var t=this.__$tooltip.parent();this.__$tooltip.detach(),this.__$tooltip.appendTo(t)},constrain:function(t,i){return this.constraints={width:t,height:i},this.__$tooltip.css({display:\"block\",height:\"\",overflow:\"auto\",width:t}),this},destroy:function(){this.__$tooltip.detach().find(\".tooltipster-content\").css({display:\"\",overflow:\"\"}),this.$container.remove()},free:function(){return this.constraints=null,this.__$tooltip.css({display:\"\",height:\"\",overflow:\"visible\",width:\"\"}),this},measure:function(){this.__forceRedraw();var t=this.__$tooltip[0].getBoundingClientRect(),i={size:{height:t.height||t.bottom-t.top,width:t.width||t.right-t.left}};if(this.constraints){var o=this.__$tooltip.find(\".tooltipster-content\"),n=this.__$tooltip.outerHeight(),s=o[0].getBoundingClientRect(),r={height:n<=this.constraints.height,width:t.width<=this.constraints.width&&s.width>=o[0].scrollWidth-1};i.fits=r.height&&r.width}return e.IE&&e.IE<=11&&i.size.width!==e.window.document.documentElement.clientWidth&&(i.size.width=Math.ceil(i.size.width)+1),i}};var a=navigator.userAgent.toLowerCase();-1!=a.indexOf(\"msie\")?e.IE=parseInt(a.split(\"msie\")[1]):-1!==a.toLowerCase().indexOf(\"trident\")&&-1!==a.indexOf(\" rv:11\")?e.IE=11:-1!=a.toLowerCase().indexOf(\"edge/\")&&(e.IE=parseInt(a.toLowerCase().split(\"edge/\")[1]));return t.tooltipster._plugin({name:\"tooltipster.sideTip\",instance:{__defaults:function(){return{arrow:!0,distance:6,functionPosition:null,maxWidth:null,minIntersection:16,minWidth:0,position:null,side:\"top\",viewportAware:!0,defaultStyles:{backgroundColor:\"#fff\",textColor:\"#000\"}}},__init:function(t){var i=this;i.__instance=t,i.__namespace=\"tooltipster-sideTip-\"+Math.round(1e6*Math.random()),i.__previousState=\"closed\",i.__options,i.__optionsFormat(),i.__instance._on(\"state.\"+i.__namespace,function(t){\"closed\"==t.state?i.__close():\"appearing\"==t.state&&\"closed\"==i.__previousState&&i.__create(),i.__previousState=t.state}),i.__instance._on(\"options.\"+i.__namespace,function(){i.__optionsFormat()}),i.__instance._on(\"reposition.\"+i.__namespace,function(t){i.__reposition(t.event,t.helper)})},__close:function(){this.__instance.content()instanceof t&&this.__instance.content().detach(),this.__instance._$tooltip.remove(),this.__instance._$tooltip=null},__create:function(){var i=this.__instance.__options.styles,o=t('<div class=\"tooltipster-base tooltipster-sidetip\"><div class=\"tooltipster-box\"><div class=\"tooltipster-content\"></div></div><div class=\"tooltipster-arrow\"><div class=\"tooltipster-arrow-uncropped\"><div class=\"tooltipster-arrow-border\"></div><div class=\"tooltipster-arrow-background\"></div></div></div></div>');o.find(\".tooltipster-box\").css({color:i.textColor?i.textColor:this.__options.defaultStyles.textColor,backgroundColor:i.backgroundColor?i.backgroundColor:this.__options.defaultStyles.backgroundColor}),o.find(\".tooltipster-arrow-border\").css({backgroundColor:i.backgroundColor?i.backgroundColor:this.__options.defaultStyles.backgroundColor}),this.__options.arrow||o.find(\".tooltipster-box\").css(\"margin\",0).end().find(\".tooltipster-arrow\").hide(),this.__options.minWidth&&o.css(\"min-width\",this.__options.minWidth+\"px\"),this.__options.maxWidth&&o.css(\"max-width\",this.__options.maxWidth+\"px\"),this.__instance._$tooltip=o,this.__instance._trigger(\"created\")},__destroy:function(){this.__instance._off(\".\"+self.__namespace)},__optionsFormat:function(){if(this.__options=this.__instance._optionsExtract(\"tooltipster.sideTip\",this.__defaults()),this.__options.position&&(this.__options.side=this.__options.position),\"object\"!=typeof this.__options.distance&&(this.__options.distance=[this.__options.distance]),this.__options.distance.length<4&&(void 0===this.__options.distance[1]&&(this.__options.distance[1]=this.__options.distance[0]),void 0===this.__options.distance[2]&&(this.__options.distance[2]=this.__options.distance[0]),void 0===this.__options.distance[3]&&(this.__options.distance[3]=this.__options.distance[1])),this.__options.distance={top:this.__options.distance[0],right:this.__options.distance[1],bottom:this.__options.distance[2],left:this.__options.distance[3]},\"string\"==typeof this.__options.side){this.__options.side=[this.__options.side,{top:\"bottom\",right:\"left\",bottom:\"top\",left:\"right\"}[this.__options.side]],\"left\"==this.__options.side[0]||\"right\"==this.__options.side[0]?this.__options.side.push(\"top\",\"bottom\"):this.__options.side.push(\"right\",\"left\")}6===t.tooltipster._env.IE&&!0!==this.__options.arrow&&(this.__options.arrow=!1)},__reposition:function(i,o){var e,n=this,s=n.__targetFind(o),r=[];n.__instance._$tooltip.detach();var _=n.__instance._$tooltip.clone(),a=t.tooltipster._getRuler(_),l=!1,p=n.__instance.option(\"animation\");switch(p&&_.removeClass(\"tooltipster-\"+p),t.each([\"window\",\"document\"],function(e,p){var c=null;if(n.__instance._trigger({container:p,helper:o,satisfied:l,takeTest:function(t){c=t},results:r,type:\"positionTest\"}),1==c||0!=c&&0==l&&(\"window\"!=p||n.__options.viewportAware))for(e=0;e<n.__options.side.length;e++){var h={horizontal:0,vertical:0},d=n.__options.side[e];\"top\"==d||\"bottom\"==d?h.vertical=n.__options.distance[d]:h.horizontal=n.__options.distance[d],n.__sideChange(_,d),t.each([\"natural\",\"constrained\"],function(t,e){if(c=null,n.__instance._trigger({container:p,event:i,helper:o,mode:e,results:r,satisfied:l,side:d,takeTest:function(t){c=t},type:\"positionTest\"}),1==c||0!=c&&0==l){var _={container:p,distance:h,fits:null,mode:e,outerSize:null,side:d,size:null,target:s[d],whole:null},u=(\"natural\"==e?a.free():a.constrain(o.geo.available[p][d].width-h.horizontal,o.geo.available[p][d].height-h.vertical)).measure();if(_.size=u.size,_.outerSize={height:u.size.height+h.vertical,width:u.size.width+h.horizontal},\"natural\"==e?o.geo.available[p][d].width>=_.outerSize.width&&o.geo.available[p][d].height>=_.outerSize.height?_.fits=!0:_.fits=!1:_.fits=u.fits,\"window\"==p&&(_.fits?_.whole=\"top\"==d||\"bottom\"==d?o.geo.origin.windowOffset.right>=n.__options.minIntersection&&o.geo.window.size.width-o.geo.origin.windowOffset.left>=n.__options.minIntersection:o.geo.origin.windowOffset.bottom>=n.__options.minIntersection&&o.geo.window.size.height-o.geo.origin.windowOffset.top>=n.__options.minIntersection:_.whole=!1),r.push(_),_.whole)l=!0;else if(\"natural\"==_.mode&&(_.fits||_.size.width<=o.geo.available[p][d].width))return!1}})}}),n.__instance._trigger({edit:function(t){r=t},event:i,helper:o,results:r,type:\"positionTested\"}),r.sort(function(t,i){return t.whole&&!i.whole?-1:!t.whole&&i.whole?1:t.whole&&i.whole?(o=n.__options.side.indexOf(t.side))<(e=n.__options.side.indexOf(i.side))?-1:o>e?1:\"natural\"==t.mode?-1:1:t.fits&&!i.fits?-1:!t.fits&&i.fits?1:t.fits&&i.fits?(o=n.__options.side.indexOf(t.side))<(e=n.__options.side.indexOf(i.side))?-1:o>e?1:\"natural\"==t.mode?-1:1:\"document\"==t.container&&\"bottom\"==t.side&&\"natural\"==t.mode?-1:1;var o,e}),(e=r[0]).coord={},e.side){case\"left\":case\"right\":e.coord.top=Math.floor(e.target-e.size.height/2);break;case\"bottom\":case\"top\":e.coord.left=Math.floor(e.target-e.size.width/2)}switch(e.side){case\"left\":e.coord.left=o.geo.origin.windowOffset.left-e.outerSize.width;break;case\"right\":e.coord.left=o.geo.origin.windowOffset.right+e.distance.horizontal;break;case\"top\":e.coord.top=o.geo.origin.windowOffset.top-e.outerSize.height;break;case\"bottom\":e.coord.top=o.geo.origin.windowOffset.bottom+e.distance.vertical}\"window\"==e.container?\"top\"==e.side||\"bottom\"==e.side?e.coord.left<0?o.geo.origin.windowOffset.right-this.__options.minIntersection>=0?e.coord.left=0:e.coord.left=o.geo.origin.windowOffset.right-this.__options.minIntersection-1:e.coord.left>o.geo.window.size.width-e.size.width&&(o.geo.origin.windowOffset.left+this.__options.minIntersection<=o.geo.window.size.width?e.coord.left=o.geo.window.size.width-e.size.width:e.coord.left=o.geo.origin.windowOffset.left+this.__options.minIntersection+1-e.size.width):e.coord.top<0?o.geo.origin.windowOffset.bottom-this.__options.minIntersection>=0?e.coord.top=0:e.coord.top=o.geo.origin.windowOffset.bottom-this.__options.minIntersection-1:e.coord.top>o.geo.window.size.height-e.size.height&&(o.geo.origin.windowOffset.top+this.__options.minIntersection<=o.geo.window.size.height?e.coord.top=o.geo.window.size.height-e.size.height:e.coord.top=o.geo.origin.windowOffset.top+this.__options.minIntersection+1-e.size.height):(e.coord.left>o.geo.window.size.width-e.size.width&&(e.coord.left=o.geo.window.size.width-e.size.width),e.coord.left<0&&(e.coord.left=0)),n.__sideChange(_,e.side),o.tooltipClone=_[0],o.tooltipParent=n.__instance.option(\"parent\").parent[0],o.mode=e.mode,o.whole=e.whole,o.origin=n.__instance._$origin[0],o.tooltip=n.__instance._$tooltip[0],delete e.container,delete e.fits,delete e.mode,delete e.outerSize,delete e.whole,e.distance=e.distance.horizontal||e.distance.vertical;var c,h,d,u=t.extend(!0,{},e);if(n.__instance._trigger({edit:function(t){e=t},event:i,helper:o,position:u,type:\"position\"}),n.__options.functionPosition){var g=n.__options.functionPosition.call(n,n.__instance,o,u);g&&(e=g)}a.destroy(),\"top\"==e.side||\"bottom\"==e.side?(c={prop:\"left\",val:e.target-e.coord.left},h=e.size.width-this.__options.minIntersection):(c={prop:\"top\",val:e.target-e.coord.top},h=e.size.height-this.__options.minIntersection),c.val<this.__options.minIntersection?c.val=this.__options.minIntersection:c.val>h&&(c.val=h),d=o.geo.origin.fixedLineage?o.geo.origin.windowOffset:{left:o.geo.origin.windowOffset.left+o.geo.window.scroll.left,top:o.geo.origin.windowOffset.top+o.geo.window.scroll.top},e.coord={left:d.left+(e.coord.left-o.geo.origin.windowOffset.left),top:d.top+(e.coord.top-o.geo.origin.windowOffset.top)},n.__sideChange(n.__instance._$tooltip,e.side),o.geo.origin.fixedLineage?n.__instance._$tooltip.css(\"position\",\"fixed\"):n.__instance._$tooltip.css(\"position\",\"\"),n.__instance._$tooltip.css({left:e.coord.left,top:e.coord.top,height:e.size.height,width:e.size.width}).find(\".tooltipster-arrow\").css({left:\"\",top:\"\"}).css(c.prop,c.val),n.__instance._$tooltip.appendTo(n.__instance.option(\"parent\")),n.__instance._trigger({type:\"repositioned\",event:i,position:e})},__sideChange:function(t,i){t.removeClass(\"tooltipster-bottom\").removeClass(\"tooltipster-left\").removeClass(\"tooltipster-right\").removeClass(\"tooltipster-top\").addClass(\"tooltipster-\"+i)},__targetFind:function(t){var i={},o=this.__instance._$origin[0].getClientRects();o.length>1&&(1==this.__instance._$origin.css(\"opacity\")&&(this.__instance._$origin.css(\"opacity\",.99),o=this.__instance._$origin[0].getClientRects(),this.__instance._$origin.css(\"opacity\",1)));if(o.length<2)i.top=Math.floor(t.geo.origin.windowOffset.left+t.geo.origin.size.width/2),i.bottom=i.top,i.left=Math.floor(t.geo.origin.windowOffset.top+t.geo.origin.size.height/2),i.right=i.left;else{var e=o[0];i.top=Math.floor(e.left+(e.right-e.left)/2),e=o.length>2?o[Math.ceil(o.length/2)-1]:o[0],i.right=Math.floor(e.top+(e.bottom-e.top)/2),e=o[o.length-1],i.bottom=Math.floor(e.left+(e.right-e.left)/2),e=o.length>2?o[Math.ceil((o.length+1)/2)-1]:o[o.length-1],i.left=Math.floor(e.top+(e.bottom-e.top)/2)}return i}}}),t});\n","Amasty_Base/vendor/slick/slick.min.js":"/* phpcs:ignoreFile */\n/*\n _ _ _ _\n ___| (_) ___| | __ (_)___\n/ __| | |/ __| |/ / | / __|\n\\__ \\ | | (__| < _ | \\__ \\\n|___/_|_|\\___|_|\\_(_)/ |___/\n |__/\n Version: 1.9.0\n Author: Ken Wheeler\n Website: http://kenwheeler.github.io\n Docs: http://kenwheeler.github.io/slick\n Repo: http://github.com/kenwheeler/slick\n Issues: http://github.com/kenwheeler/slick/issues\n */\n(function(i){\"use strict\";\"function\"==typeof define&&define.amd?define([\"jquery\"],i):\"undefined\"!=typeof exports?module.exports=i(require(\"jquery\")):i(jQuery)})(function(i){\"use strict\";var e=window.Slick||{};e=function(){function e(e,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(e),appendDots:i(e),arrows:!0,asNavFor:null,prevArrow:'<button class=\"slick-prev\" aria-label=\"Previous\" type=\"button\">Previous</button>',nextArrow:'<button class=\"slick-next\" aria-label=\"Next\" type=\"button\">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:\"50px\",cssEase:\"ease\",customPaging:function(e,t){return i('<button type=\"button\" />').text(t+1)},dots:!1,dotsClass:\"slick-dots\",draggable:!0,easing:\"linear\",edgeFriction:.35,fade:!1,focusOnSelect:!1,focusOnChange:!1,infinite:!0,initialSlide:0,lazyLoad:\"ondemand\",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:\"window\",responsive:null,rows:1,rtl:!1,slide:\"\",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},n.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,scrolling:!1,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,swiping:!1,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},i.extend(n,n.initials),n.activeBreakpoint=null,n.animType=null,n.animProp=null,n.breakpoints=[],n.breakpointSettings=[],n.cssTransitions=!1,n.focussed=!1,n.interrupted=!1,n.hidden=\"hidden\",n.paused=!0,n.positionProp=null,n.respondTo=null,n.rowCount=1,n.shouldClick=!0,n.$slider=i(e),n.$slidesCache=null,n.transformType=null,n.transitionType=null,n.visibilityChange=\"visibilitychange\",n.windowWidth=0,n.windowTimer=null,s=i(e).data(\"slick\")||{},n.options=i.extend({},n.defaults,o,s),n.currentSlide=n.options.initialSlide,n.originalSettings=n.options,\"undefined\"!=typeof document.mozHidden?(n.hidden=\"mozHidden\",n.visibilityChange=\"mozvisibilitychange\"):\"undefined\"!=typeof document.webkitHidden&&(n.hidden=\"webkitHidden\",n.visibilityChange=\"webkitvisibilitychange\"),n.autoPlay=i.proxy(n.autoPlay,n),n.autoPlayClear=i.proxy(n.autoPlayClear,n),n.autoPlayIterator=i.proxy(n.autoPlayIterator,n),n.changeSlide=i.proxy(n.changeSlide,n),n.clickHandler=i.proxy(n.clickHandler,n),n.selectHandler=i.proxy(n.selectHandler,n),n.setPosition=i.proxy(n.setPosition,n),n.swipeHandler=i.proxy(n.swipeHandler,n),n.dragHandler=i.proxy(n.dragHandler,n),n.keyHandler=i.proxy(n.keyHandler,n),n.instanceUid=t++,n.htmlExpr=/^(?:\\s*(<[\\w\\W]+>)[^>]*)$/,n.registerBreakpoints(),n.init(!0)}var t=0;return e}(),e.prototype.activateADA=function(){var i=this;i.$slideTrack.find(\".slick-active\").attr({\"aria-hidden\":\"false\"}).find(\"a, input, button, select\").attr({tabindex:\"0\"})},e.prototype.addSlide=e.prototype.slickAdd=function(e,t,o){var s=this;if(\"boolean\"==typeof t)o=t,t=null;else if(t<0||t>=s.slideCount)return!1;s.unload(),\"number\"==typeof t?0===t&&0===s.$slides.length?i(e).appendTo(s.$slideTrack):o?i(e).insertBefore(s.$slides.eq(t)):i(e).insertAfter(s.$slides.eq(t)):o===!0?i(e).prependTo(s.$slideTrack):i(e).appendTo(s.$slideTrack),s.$slides=s.$slideTrack.children(this.options.slide),s.$slideTrack.children(this.options.slide).detach(),s.$slideTrack.append(s.$slides),s.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e)}),s.$slidesCache=s.$slides,s.reinit()},e.prototype.animateHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.animate({height:e},i.options.speed)}},e.prototype.animateSlide=function(e,t){var o={},s=this;s.animateHeight(),s.options.rtl===!0&&s.options.vertical===!1&&(e=-e),s.transformsEnabled===!1?s.options.vertical===!1?s.$slideTrack.animate({left:e},s.options.speed,s.options.easing,t):s.$slideTrack.animate({top:e},s.options.speed,s.options.easing,t):s.cssTransitions===!1?(s.options.rtl===!0&&(s.currentLeft=-s.currentLeft),i({animStart:s.currentLeft}).animate({animStart:e},{duration:s.options.speed,easing:s.options.easing,step:function(i){i=Math.ceil(i),s.options.vertical===!1?(o[s.animType]=\"translate(\"+i+\"px, 0px)\",s.$slideTrack.css(o)):(o[s.animType]=\"translate(0px,\"+i+\"px)\",s.$slideTrack.css(o))},complete:function(){t&&t.call()}})):(s.applyTransition(),e=Math.ceil(e),s.options.vertical===!1?o[s.animType]=\"translate3d(\"+e+\"px, 0px, 0px)\":o[s.animType]=\"translate3d(0px,\"+e+\"px, 0px)\",s.$slideTrack.css(o),t&&setTimeout(function(){s.disableTransition(),t.call()},s.options.speed))},e.prototype.getNavTarget=function(){var e=this,t=e.options.asNavFor;return t&&null!==t&&(t=i(t).not(e.$slider)),t},e.prototype.asNavFor=function(e){var t=this,o=t.getNavTarget();null!==o&&\"object\"==typeof o&&o.each(function(){var t=i(this).slick(\"getSlick\");t.unslicked||t.slideHandler(e,!0)})},e.prototype.applyTransition=function(i){var e=this,t={};e.options.fade===!1?t[e.transitionType]=e.transformType+\" \"+e.options.speed+\"ms \"+e.options.cssEase:t[e.transitionType]=\"opacity \"+e.options.speed+\"ms \"+e.options.cssEase,e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.autoPlay=function(){var i=this;i.autoPlayClear(),i.slideCount>i.options.slidesToShow&&(i.autoPlayTimer=setInterval(i.autoPlayIterator,i.options.autoplaySpeed))},e.prototype.autoPlayClear=function(){var i=this;i.autoPlayTimer&&clearInterval(i.autoPlayTimer)},e.prototype.autoPlayIterator=function(){var i=this,e=i.currentSlide+i.options.slidesToScroll;i.paused||i.interrupted||i.focussed||(i.options.infinite===!1&&(1===i.direction&&i.currentSlide+1===i.slideCount-1?i.direction=0:0===i.direction&&(e=i.currentSlide-i.options.slidesToScroll,i.currentSlide-1===0&&(i.direction=1))),i.slideHandler(e))},e.prototype.buildArrows=function(){var e=this;e.options.arrows===!0&&(e.$prevArrow=i(e.options.prevArrow).addClass(\"slick-arrow\"),e.$nextArrow=i(e.options.nextArrow).addClass(\"slick-arrow\"),e.slideCount>e.options.slidesToShow?(e.$prevArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.$nextArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.prependTo(e.options.appendArrows),e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.appendTo(e.options.appendArrows),e.options.infinite!==!0&&e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\")):e.$prevArrow.add(e.$nextArrow).addClass(\"slick-hidden\").attr({\"aria-disabled\":\"true\",tabindex:\"-1\"}))},e.prototype.buildDots=function(){var e,t,o=this;if(o.options.dots===!0&&o.slideCount>o.options.slidesToShow){for(o.$slider.addClass(\"slick-dotted\"),t=i(\"<ul />\").addClass(o.options.dotsClass),e=0;e<=o.getDotCount();e+=1)t.append(i(\"<li />\").append(o.options.customPaging.call(this,o,e)));o.$dots=t.appendTo(o.options.appendDots),o.$dots.find(\"li\").first().addClass(\"slick-active\")}},e.prototype.buildOut=function(){var e=this;e.$slides=e.$slider.children(e.options.slide+\":not(.slick-cloned)\").addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e).data(\"originalStyling\",i(t).attr(\"style\")||\"\")}),e.$slider.addClass(\"slick-slider\"),e.$slideTrack=0===e.slideCount?i('<div class=\"slick-track\"/>').appendTo(e.$slider):e.$slides.wrapAll('<div class=\"slick-track\"/>').parent(),e.$list=e.$slideTrack.wrap('<div class=\"slick-list\"/>').parent(),e.$slideTrack.css(\"opacity\",0),e.options.centerMode!==!0&&e.options.swipeToSlide!==!0||(e.options.slidesToScroll=1),i(\"img[data-lazy]\",e.$slider).not(\"[src]\").addClass(\"slick-loading\"),e.setupInfinite(),e.buildArrows(),e.buildDots(),e.updateDots(),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.options.draggable===!0&&e.$list.addClass(\"draggable\")},e.prototype.buildRows=function(){var i,e,t,o,s,n,r,l=this;if(o=document.createDocumentFragment(),n=l.$slider.children(),l.options.rows>0){for(r=l.options.slidesPerRow*l.options.rows,s=Math.ceil(n.length/r),i=0;i<s;i++){var d=document.createElement(\"div\");for(e=0;e<l.options.rows;e++){var a=document.createElement(\"div\");for(t=0;t<l.options.slidesPerRow;t++){var c=i*r+(e*l.options.slidesPerRow+t);n.get(c)&&a.appendChild(n.get(c))}d.appendChild(a)}o.appendChild(d)}l.$slider.empty().append(o),l.$slider.children().children().children().css({width:100/l.options.slidesPerRow+\"%\",display:\"inline-block\"})}},e.prototype.checkResponsive=function(e,t){var o,s,n,r=this,l=!1,d=r.$slider.width(),a=window.innerWidth||i(window).width();if(\"window\"===r.respondTo?n=a:\"slider\"===r.respondTo?n=d:\"min\"===r.respondTo&&(n=Math.min(a,d)),r.options.responsive&&r.options.responsive.length&&null!==r.options.responsive){s=null;for(o in r.breakpoints)r.breakpoints.hasOwnProperty(o)&&(r.originalSettings.mobileFirst===!1?n<r.breakpoints[o]&&(s=r.breakpoints[o]):n>r.breakpoints[o]&&(s=r.breakpoints[o]));null!==s?null!==r.activeBreakpoint?(s!==r.activeBreakpoint||t)&&(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):null!==r.activeBreakpoint&&(r.activeBreakpoint=null,r.options=r.originalSettings,e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e),l=s),e||l===!1||r.$slider.trigger(\"breakpoint\",[r,l])}},e.prototype.changeSlide=function(e,t){var o,s,n,r=this,l=i(e.currentTarget);switch(l.is(\"a\")&&e.preventDefault(),l.is(\"li\")||(l=l.closest(\"li\")),n=r.slideCount%r.options.slidesToScroll!==0,o=n?0:(r.slideCount-r.currentSlide)%r.options.slidesToScroll,e.data.message){case\"previous\":s=0===o?r.options.slidesToScroll:r.options.slidesToShow-o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide-s,!1,t);break;case\"next\":s=0===o?r.options.slidesToScroll:o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide+s,!1,t);break;case\"index\":var d=0===e.data.index?0:e.data.index||l.index()*r.options.slidesToScroll;r.slideHandler(r.checkNavigable(d),!1,t),l.children().trigger(\"focus\");break;default:return}},e.prototype.checkNavigable=function(i){var e,t,o=this;if(e=o.getNavigableIndexes(),t=0,i>e[e.length-1])i=e[e.length-1];else for(var s in e){if(i<e[s]){i=t;break}t=e[s]}return i},e.prototype.cleanUpEvents=function(){var e=this;e.options.dots&&null!==e.$dots&&(i(\"li\",e.$dots).off(\"click.slick\",e.changeSlide).off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)),e.options.accessibility===!0&&e.$dots.off(\"keydown.slick\",e.keyHandler)),e.$slider.off(\"focus.slick blur.slick\"),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&(e.$prevArrow&&e.$prevArrow.off(\"click.slick\",e.changeSlide),e.$nextArrow&&e.$nextArrow.off(\"click.slick\",e.changeSlide),e.options.accessibility===!0&&(e.$prevArrow&&e.$prevArrow.off(\"keydown.slick\",e.keyHandler),e.$nextArrow&&e.$nextArrow.off(\"keydown.slick\",e.keyHandler))),e.$list.off(\"touchstart.slick mousedown.slick\",e.swipeHandler),e.$list.off(\"touchmove.slick mousemove.slick\",e.swipeHandler),e.$list.off(\"touchend.slick mouseup.slick\",e.swipeHandler),e.$list.off(\"touchcancel.slick mouseleave.slick\",e.swipeHandler),e.$list.off(\"click.slick\",e.clickHandler),i(document).off(e.visibilityChange,e.visibility),e.cleanUpSlideEvents(),e.options.accessibility===!0&&e.$list.off(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().off(\"click.slick\",e.selectHandler),i(window).off(\"orientationchange.slick.slick-\"+e.instanceUid,e.orientationChange),i(window).off(\"resize.slick.slick-\"+e.instanceUid,e.resize),i(\"[draggable!=true]\",e.$slideTrack).off(\"dragstart\",e.preventDefault),i(window).off(\"load.slick.slick-\"+e.instanceUid,e.setPosition)},e.prototype.cleanUpSlideEvents=function(){var e=this;e.$list.off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.cleanUpRows=function(){var i,e=this;e.options.rows>0&&(i=e.$slides.children().children(),i.removeAttr(\"style\"),e.$slider.empty().append(i))},e.prototype.clickHandler=function(i){var e=this;e.shouldClick===!1&&(i.stopImmediatePropagation(),i.stopPropagation(),i.preventDefault())},e.prototype.destroy=function(e){var t=this;t.autoPlayClear(),t.touchObject={},t.cleanUpEvents(),i(\".slick-cloned\",t.$slider).detach(),t.$dots&&t.$dots.remove(),t.$prevArrow&&t.$prevArrow.length&&(t.$prevArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.prevArrow)&&t.$prevArrow.remove()),t.$nextArrow&&t.$nextArrow.length&&(t.$nextArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.nextArrow)&&t.$nextArrow.remove()),t.$slides&&(t.$slides.removeClass(\"slick-slide slick-active slick-center slick-visible slick-current\").removeAttr(\"aria-hidden\").removeAttr(\"data-slick-index\").each(function(){i(this).attr(\"style\",i(this).data(\"originalStyling\"))}),t.$slideTrack.children(this.options.slide).detach(),t.$slideTrack.detach(),t.$list.detach(),t.$slider.append(t.$slides)),t.cleanUpRows(),t.$slider.removeClass(\"slick-slider\"),t.$slider.removeClass(\"slick-initialized\"),t.$slider.removeClass(\"slick-dotted\"),t.unslicked=!0,e||t.$slider.trigger(\"destroy\",[t])},e.prototype.disableTransition=function(i){var e=this,t={};t[e.transitionType]=\"\",e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.fadeSlide=function(i,e){var t=this;t.cssTransitions===!1?(t.$slides.eq(i).css({zIndex:t.options.zIndex}),t.$slides.eq(i).animate({opacity:1},t.options.speed,t.options.easing,e)):(t.applyTransition(i),t.$slides.eq(i).css({opacity:1,zIndex:t.options.zIndex}),e&&setTimeout(function(){t.disableTransition(i),e.call()},t.options.speed))},e.prototype.fadeSlideOut=function(i){var e=this;e.cssTransitions===!1?e.$slides.eq(i).animate({opacity:0,zIndex:e.options.zIndex-2},e.options.speed,e.options.easing):(e.applyTransition(i),e.$slides.eq(i).css({opacity:0,zIndex:e.options.zIndex-2}))},e.prototype.filterSlides=e.prototype.slickFilter=function(i){var e=this;null!==i&&(e.$slidesCache=e.$slides,e.unload(),e.$slideTrack.children(this.options.slide).detach(),e.$slidesCache.filter(i).appendTo(e.$slideTrack),e.reinit())},e.prototype.focusHandler=function(){var e=this;e.$slider.off(\"focus.slick blur.slick\").on(\"focus.slick\",\"*\",function(t){var o=i(this);setTimeout(function(){e.options.pauseOnFocus&&o.is(\":focus\")&&(e.focussed=!0,e.autoPlay())},0)}).on(\"blur.slick\",\"*\",function(t){i(this);e.options.pauseOnFocus&&(e.focussed=!1,e.autoPlay())})},e.prototype.getCurrent=e.prototype.slickCurrentSlide=function(){var i=this;return i.currentSlide},e.prototype.getDotCount=function(){var i=this,e=0,t=0,o=0;if(i.options.infinite===!0)if(i.slideCount<=i.options.slidesToShow)++o;else for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else if(i.options.centerMode===!0)o=i.slideCount;else if(i.options.asNavFor)for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else o=1+Math.ceil((i.slideCount-i.options.slidesToShow)/i.options.slidesToScroll);return o-1},e.prototype.getLeft=function(i){var e,t,o,s,n=this,r=0;return n.slideOffset=0,t=n.$slides.first().outerHeight(!0),n.options.infinite===!0?(n.slideCount>n.options.slidesToShow&&(n.slideOffset=n.slideWidth*n.options.slidesToShow*-1,s=-1,n.options.vertical===!0&&n.options.centerMode===!0&&(2===n.options.slidesToShow?s=-1.5:1===n.options.slidesToShow&&(s=-2)),r=t*n.options.slidesToShow*s),n.slideCount%n.options.slidesToScroll!==0&&i+n.options.slidesToScroll>n.slideCount&&n.slideCount>n.options.slidesToShow&&(i>n.slideCount?(n.slideOffset=(n.options.slidesToShow-(i-n.slideCount))*n.slideWidth*-1,r=(n.options.slidesToShow-(i-n.slideCount))*t*-1):(n.slideOffset=n.slideCount%n.options.slidesToScroll*n.slideWidth*-1,r=n.slideCount%n.options.slidesToScroll*t*-1))):i+n.options.slidesToShow>n.slideCount&&(n.slideOffset=(i+n.options.slidesToShow-n.slideCount)*n.slideWidth,r=(i+n.options.slidesToShow-n.slideCount)*t),n.slideCount<=n.options.slidesToShow&&(n.slideOffset=0,r=0),n.options.centerMode===!0&&n.slideCount<=n.options.slidesToShow?n.slideOffset=n.slideWidth*Math.floor(n.options.slidesToShow)/2-n.slideWidth*n.slideCount/2:n.options.centerMode===!0&&n.options.infinite===!0?n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)-n.slideWidth:n.options.centerMode===!0&&(n.slideOffset=0,n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)),e=n.options.vertical===!1?i*n.slideWidth*-1+n.slideOffset:i*t*-1+r,n.options.variableWidth===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,n.options.centerMode===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow+1),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,e+=(n.$list.width()-o.outerWidth())/2)),e},e.prototype.getOption=e.prototype.slickGetOption=function(i){var e=this;return e.options[i]},e.prototype.getNavigableIndexes=function(){var i,e=this,t=0,o=0,s=[];for(e.options.infinite===!1?i=e.slideCount:(t=e.options.slidesToScroll*-1,o=e.options.slidesToScroll*-1,i=2*e.slideCount);t<i;)s.push(t),t=o+e.options.slidesToScroll,o+=e.options.slidesToScroll<=e.options.slidesToShow?e.options.slidesToScroll:e.options.slidesToShow;return s},e.prototype.getSlick=function(){return this},e.prototype.getSlideCount=function(){var e,t,o,s,n=this;return s=n.options.centerMode===!0?Math.floor(n.$list.width()/2):0,o=n.swipeLeft*-1+s,n.options.swipeToSlide===!0?(n.$slideTrack.find(\".slick-slide\").each(function(e,s){var r,l,d;if(r=i(s).outerWidth(),l=s.offsetLeft,n.options.centerMode!==!0&&(l+=r/2),d=l+r,o<d)return t=s,!1}),e=Math.abs(i(t).attr(\"data-slick-index\")-n.currentSlide)||1):n.options.slidesToScroll},e.prototype.goTo=e.prototype.slickGoTo=function(i,e){var t=this;t.changeSlide({data:{message:\"index\",index:parseInt(i)}},e)},e.prototype.init=function(e){var t=this;i(t.$slider).hasClass(\"slick-initialized\")||(i(t.$slider).addClass(\"slick-initialized\"),t.buildRows(),t.buildOut(),t.setProps(),t.startLoad(),t.loadSlider(),t.initializeEvents(),t.updateArrows(),t.updateDots(),t.checkResponsive(!0),t.focusHandler()),e&&t.$slider.trigger(\"init\",[t]),t.options.accessibility===!0&&t.initADA(),t.options.autoplay&&(t.paused=!1,t.autoPlay())},e.prototype.initADA=function(){var e=this,t=Math.ceil(e.slideCount/e.options.slidesToShow),o=e.getNavigableIndexes().filter(function(i){return i>=0&&i<e.slideCount});e.$slides.add(e.$slideTrack.find(\".slick-cloned\")).attr({\"aria-hidden\":\"true\",tabindex:\"-1\"}).find(\"a, input, button, select\").attr({tabindex:\"-1\"}),null!==e.$dots&&(e.$slides.not(e.$slideTrack.find(\".slick-cloned\")).each(function(t){var s=o.indexOf(t);if(i(this).attr({role:\"tabpanel\",id:\"slick-slide\"+e.instanceUid+t,tabindex:-1}),s!==-1){var n=\"slick-slide-control\"+e.instanceUid+s;i(\"#\"+n).length&&i(this).attr({\"aria-describedby\":n})}}),e.$dots.attr(\"role\",\"tablist\").find(\"li\").each(function(s){var n=o[s];i(this).attr({role:\"presentation\"}),i(this).find(\"button\").first().attr({role:\"tab\",id:\"slick-slide-control\"+e.instanceUid+s,\"aria-controls\":\"slick-slide\"+e.instanceUid+n,\"aria-label\":s+1+\" of \"+t,\"aria-selected\":null,tabindex:\"-1\"})}).eq(e.currentSlide).find(\"button\").attr({\"aria-selected\":\"true\",tabindex:\"0\"}).end());for(var s=e.currentSlide,n=s+e.options.slidesToShow;s<n;s++)e.options.focusOnChange?e.$slides.eq(s).attr({tabindex:\"0\"}):e.$slides.eq(s).removeAttr(\"tabindex\");e.activateADA()},e.prototype.initArrowEvents=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.off(\"click.slick\").on(\"click.slick\",{message:\"previous\"},i.changeSlide),i.$nextArrow.off(\"click.slick\").on(\"click.slick\",{message:\"next\"},i.changeSlide),i.options.accessibility===!0&&(i.$prevArrow.on(\"keydown.slick\",i.keyHandler),i.$nextArrow.on(\"keydown.slick\",i.keyHandler)))},e.prototype.initDotEvents=function(){var e=this;e.options.dots===!0&&e.slideCount>e.options.slidesToShow&&(i(\"li\",e.$dots).on(\"click.slick\",{message:\"index\"},e.changeSlide),e.options.accessibility===!0&&e.$dots.on(\"keydown.slick\",e.keyHandler)),e.options.dots===!0&&e.options.pauseOnDotsHover===!0&&e.slideCount>e.options.slidesToShow&&i(\"li\",e.$dots).on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.initSlideEvents=function(){var e=this;e.options.pauseOnHover&&(e.$list.on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)))},e.prototype.initializeEvents=function(){var e=this;e.initArrowEvents(),e.initDotEvents(),e.initSlideEvents(),e.$list.on(\"touchstart.slick mousedown.slick\",{action:\"start\"},e.swipeHandler),e.$list.on(\"touchmove.slick mousemove.slick\",{action:\"move\"},e.swipeHandler),e.$list.on(\"touchend.slick mouseup.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"touchcancel.slick mouseleave.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"click.slick\",e.clickHandler),i(document).on(e.visibilityChange,i.proxy(e.visibility,e)),e.options.accessibility===!0&&e.$list.on(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),i(window).on(\"orientationchange.slick.slick-\"+e.instanceUid,i.proxy(e.orientationChange,e)),i(window).on(\"resize.slick.slick-\"+e.instanceUid,i.proxy(e.resize,e)),i(\"[draggable!=true]\",e.$slideTrack).on(\"dragstart\",e.preventDefault),i(window).on(\"load.slick.slick-\"+e.instanceUid,e.setPosition),i(e.setPosition)},e.prototype.initUI=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.show(),i.$nextArrow.show()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.show()},e.prototype.keyHandler=function(i){var e=this;i.target.tagName.match(\"TEXTAREA|INPUT|SELECT\")||(37===i.keyCode&&e.options.accessibility===!0?e.changeSlide({data:{message:e.options.rtl===!0?\"next\":\"previous\"}}):39===i.keyCode&&e.options.accessibility===!0&&e.changeSlide({data:{message:e.options.rtl===!0?\"previous\":\"next\"}}))},e.prototype.lazyLoad=function(){function e(e){i(\"img[data-lazy]\",e).each(function(){var e=i(this),t=i(this).attr(\"data-lazy\"),o=i(this).attr(\"data-srcset\"),s=i(this).attr(\"data-sizes\")||r.$slider.attr(\"data-sizes\"),n=document.createElement(\"img\");n.onload=function(){e.animate({opacity:0},100,function(){o&&(e.attr(\"srcset\",o),s&&e.attr(\"sizes\",s)),e.attr(\"src\",t).animate({opacity:1},200,function(){e.removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\")}),r.$slider.trigger(\"lazyLoaded\",[r,e,t])})},n.onerror=function(){e.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),r.$slider.trigger(\"lazyLoadError\",[r,e,t])},n.src=t})}var t,o,s,n,r=this;if(r.options.centerMode===!0?r.options.infinite===!0?(s=r.currentSlide+(r.options.slidesToShow/2+1),n=s+r.options.slidesToShow+2):(s=Math.max(0,r.currentSlide-(r.options.slidesToShow/2+1)),n=2+(r.options.slidesToShow/2+1)+r.currentSlide):(s=r.options.infinite?r.options.slidesToShow+r.currentSlide:r.currentSlide,n=Math.ceil(s+r.options.slidesToShow),r.options.fade===!0&&(s>0&&s--,n<=r.slideCount&&n++)),t=r.$slider.find(\".slick-slide\").slice(s,n),\"anticipated\"===r.options.lazyLoad)for(var l=s-1,d=n,a=r.$slider.find(\".slick-slide\"),c=0;c<r.options.slidesToScroll;c++)l<0&&(l=r.slideCount-1),t=t.add(a.eq(l)),t=t.add(a.eq(d)),l--,d++;e(t),r.slideCount<=r.options.slidesToShow?(o=r.$slider.find(\".slick-slide\"),e(o)):r.currentSlide>=r.slideCount-r.options.slidesToShow?(o=r.$slider.find(\".slick-cloned\").slice(0,r.options.slidesToShow),e(o)):0===r.currentSlide&&(o=r.$slider.find(\".slick-cloned\").slice(r.options.slidesToShow*-1),e(o))},e.prototype.loadSlider=function(){var i=this;i.setPosition(),i.$slideTrack.css({opacity:1}),i.$slider.removeClass(\"slick-loading\"),i.initUI(),\"progressive\"===i.options.lazyLoad&&i.progressiveLazyLoad()},e.prototype.next=e.prototype.slickNext=function(){var i=this;i.changeSlide({data:{message:\"next\"}})},e.prototype.orientationChange=function(){var i=this;i.checkResponsive(),i.setPosition()},e.prototype.pause=e.prototype.slickPause=function(){var i=this;i.autoPlayClear(),i.paused=!0},e.prototype.play=e.prototype.slickPlay=function(){var i=this;i.autoPlay(),i.options.autoplay=!0,i.paused=!1,i.focussed=!1,i.interrupted=!1},e.prototype.postSlide=function(e){var t=this;if(!t.unslicked&&(t.$slider.trigger(\"afterChange\",[t,e]),t.animating=!1,t.slideCount>t.options.slidesToShow&&t.setPosition(),t.swipeLeft=null,t.options.autoplay&&t.autoPlay(),t.options.accessibility===!0&&(t.initADA(),t.options.focusOnChange))){var o=i(t.$slides.get(t.currentSlide));o.attr(\"tabindex\",0).focus()}},e.prototype.prev=e.prototype.slickPrev=function(){var i=this;i.changeSlide({data:{message:\"previous\"}})},e.prototype.preventDefault=function(i){i.preventDefault()},e.prototype.progressiveLazyLoad=function(e){e=e||1;var t,o,s,n,r,l=this,d=i(\"img[data-lazy]\",l.$slider);d.length?(t=d.first(),o=t.attr(\"data-lazy\"),s=t.attr(\"data-srcset\"),n=t.attr(\"data-sizes\")||l.$slider.attr(\"data-sizes\"),r=document.createElement(\"img\"),r.onload=function(){s&&(t.attr(\"srcset\",s),n&&t.attr(\"sizes\",n)),t.attr(\"src\",o).removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\"),l.options.adaptiveHeight===!0&&l.setPosition(),l.$slider.trigger(\"lazyLoaded\",[l,t,o]),l.progressiveLazyLoad()},r.onerror=function(){e<3?setTimeout(function(){l.progressiveLazyLoad(e+1)},500):(t.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),l.$slider.trigger(\"lazyLoadError\",[l,t,o]),l.progressiveLazyLoad())},r.src=o):l.$slider.trigger(\"allImagesLoaded\",[l])},e.prototype.refresh=function(e){var t,o,s=this;o=s.slideCount-s.options.slidesToShow,!s.options.infinite&&s.currentSlide>o&&(s.currentSlide=o),s.slideCount<=s.options.slidesToShow&&(s.currentSlide=0),t=s.currentSlide,s.destroy(!0),i.extend(s,s.initials,{currentSlide:t}),s.init(),e||s.changeSlide({data:{message:\"index\",index:t}},!1)},e.prototype.registerBreakpoints=function(){var e,t,o,s=this,n=s.options.responsive||null;if(\"array\"===i.type(n)&&n.length){s.respondTo=s.options.respondTo||\"window\";for(e in n)if(o=s.breakpoints.length-1,n.hasOwnProperty(e)){for(t=n[e].breakpoint;o>=0;)s.breakpoints[o]&&s.breakpoints[o]===t&&s.breakpoints.splice(o,1),o--;s.breakpoints.push(t),s.breakpointSettings[t]=n[e].settings}s.breakpoints.sort(function(i,e){return s.options.mobileFirst?i-e:e-i})}},e.prototype.reinit=function(){var e=this;e.$slides=e.$slideTrack.children(e.options.slide).addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.currentSlide>=e.slideCount&&0!==e.currentSlide&&(e.currentSlide=e.currentSlide-e.options.slidesToScroll),e.slideCount<=e.options.slidesToShow&&(e.currentSlide=0),e.registerBreakpoints(),e.setProps(),e.setupInfinite(),e.buildArrows(),e.updateArrows(),e.initArrowEvents(),e.buildDots(),e.updateDots(),e.initDotEvents(),e.cleanUpSlideEvents(),e.initSlideEvents(),e.checkResponsive(!1,!0),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.setPosition(),e.focusHandler(),e.paused=!e.options.autoplay,e.autoPlay(),e.$slider.trigger(\"reInit\",[e])},e.prototype.resize=function(){var e=this;i(window).width()!==e.windowWidth&&(clearTimeout(e.windowDelay),e.windowDelay=window.setTimeout(function(){e.windowWidth=i(window).width(),e.checkResponsive(),e.unslicked||e.setPosition()},50))},e.prototype.removeSlide=e.prototype.slickRemove=function(i,e,t){var o=this;return\"boolean\"==typeof i?(e=i,i=e===!0?0:o.slideCount-1):i=e===!0?--i:i,!(o.slideCount<1||i<0||i>o.slideCount-1)&&(o.unload(),t===!0?o.$slideTrack.children().remove():o.$slideTrack.children(this.options.slide).eq(i).remove(),o.$slides=o.$slideTrack.children(this.options.slide),o.$slideTrack.children(this.options.slide).detach(),o.$slideTrack.append(o.$slides),o.$slidesCache=o.$slides,void o.reinit())},e.prototype.setCSS=function(i){var e,t,o=this,s={};o.options.rtl===!0&&(i=-i),e=\"left\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",t=\"top\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",s[o.positionProp]=i,o.transformsEnabled===!1?o.$slideTrack.css(s):(s={},o.cssTransitions===!1?(s[o.animType]=\"translate(\"+e+\", \"+t+\")\",o.$slideTrack.css(s)):(s[o.animType]=\"translate3d(\"+e+\", \"+t+\", 0px)\",o.$slideTrack.css(s)))},e.prototype.setDimensions=function(){var i=this;i.options.vertical===!1?i.options.centerMode===!0&&i.$list.css({padding:\"0px \"+i.options.centerPadding}):(i.$list.height(i.$slides.first().outerHeight(!0)*i.options.slidesToShow),i.options.centerMode===!0&&i.$list.css({padding:i.options.centerPadding+\" 0px\"})),i.listWidth=i.$list.width(),i.listHeight=i.$list.height(),i.options.vertical===!1&&i.options.variableWidth===!1?(i.slideWidth=Math.ceil(i.listWidth/i.options.slidesToShow),i.$slideTrack.width(Math.ceil(i.slideWidth*i.$slideTrack.children(\".slick-slide\").length))):i.options.variableWidth===!0?i.$slideTrack.width(5e3*i.slideCount):(i.slideWidth=Math.ceil(i.listWidth),i.$slideTrack.height(Math.ceil(i.$slides.first().outerHeight(!0)*i.$slideTrack.children(\".slick-slide\").length)));var e=i.$slides.first().outerWidth(!0)-i.$slides.first().width();i.options.variableWidth===!1&&i.$slideTrack.children(\".slick-slide\").width(i.slideWidth-e)},e.prototype.setFade=function(){var e,t=this;t.$slides.each(function(o,s){e=t.slideWidth*o*-1,t.options.rtl===!0?i(s).css({position:\"relative\",right:e,top:0,zIndex:t.options.zIndex-2,opacity:0}):i(s).css({position:\"relative\",left:e,top:0,zIndex:t.options.zIndex-2,opacity:0})}),t.$slides.eq(t.currentSlide).css({zIndex:t.options.zIndex-1,opacity:1})},e.prototype.setHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.css(\"height\",e)}},e.prototype.setOption=e.prototype.slickSetOption=function(){var e,t,o,s,n,r=this,l=!1;if(\"object\"===i.type(arguments[0])?(o=arguments[0],l=arguments[1],n=\"multiple\"):\"string\"===i.type(arguments[0])&&(o=arguments[0],s=arguments[1],l=arguments[2],\"responsive\"===arguments[0]&&\"array\"===i.type(arguments[1])?n=\"responsive\":\"undefined\"!=typeof arguments[1]&&(n=\"single\")),\"single\"===n)r.options[o]=s;else if(\"multiple\"===n)i.each(o,function(i,e){r.options[i]=e});else if(\"responsive\"===n)for(t in s)if(\"array\"!==i.type(r.options.responsive))r.options.responsive=[s[t]];else{for(e=r.options.responsive.length-1;e>=0;)r.options.responsive[e].breakpoint===s[t].breakpoint&&r.options.responsive.splice(e,1),e--;r.options.responsive.push(s[t])}l&&(r.unload(),r.reinit())},e.prototype.setPosition=function(){var i=this;i.setDimensions(),i.setHeight(),i.options.fade===!1?i.setCSS(i.getLeft(i.currentSlide)):i.setFade(),i.$slider.trigger(\"setPosition\",[i])},e.prototype.setProps=function(){var i=this,e=document.body.style;i.positionProp=i.options.vertical===!0?\"top\":\"left\",\n \"top\"===i.positionProp?i.$slider.addClass(\"slick-vertical\"):i.$slider.removeClass(\"slick-vertical\"),void 0===e.WebkitTransition&&void 0===e.MozTransition&&void 0===e.msTransition||i.options.useCSS===!0&&(i.cssTransitions=!0),i.options.fade&&(\"number\"==typeof i.options.zIndex?i.options.zIndex<3&&(i.options.zIndex=3):i.options.zIndex=i.defaults.zIndex),void 0!==e.OTransform&&(i.animType=\"OTransform\",i.transformType=\"-o-transform\",i.transitionType=\"OTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.MozTransform&&(i.animType=\"MozTransform\",i.transformType=\"-moz-transform\",i.transitionType=\"MozTransition\",void 0===e.perspectiveProperty&&void 0===e.MozPerspective&&(i.animType=!1)),void 0!==e.webkitTransform&&(i.animType=\"webkitTransform\",i.transformType=\"-webkit-transform\",i.transitionType=\"webkitTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.msTransform&&(i.animType=\"msTransform\",i.transformType=\"-ms-transform\",i.transitionType=\"msTransition\",void 0===e.msTransform&&(i.animType=!1)),void 0!==e.transform&&i.animType!==!1&&(i.animType=\"transform\",i.transformType=\"transform\",i.transitionType=\"transition\"),i.transformsEnabled=i.options.useTransform&&null!==i.animType&&i.animType!==!1},e.prototype.setSlideClasses=function(i){var e,t,o,s,n=this;if(t=n.$slider.find(\".slick-slide\").removeClass(\"slick-active slick-center slick-current\").attr(\"aria-hidden\",\"true\"),n.$slides.eq(i).addClass(\"slick-current\"),n.options.centerMode===!0){var r=n.options.slidesToShow%2===0?1:0;e=Math.floor(n.options.slidesToShow/2),n.options.infinite===!0&&(i>=e&&i<=n.slideCount-1-e?n.$slides.slice(i-e+r,i+e+1).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(o=n.options.slidesToShow+i,t.slice(o-e+1+r,o+e+2).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\")),0===i?t.eq(t.length-1-n.options.slidesToShow).addClass(\"slick-center\"):i===n.slideCount-1&&t.eq(n.options.slidesToShow).addClass(\"slick-center\")),n.$slides.eq(i).addClass(\"slick-center\")}else i>=0&&i<=n.slideCount-n.options.slidesToShow?n.$slides.slice(i,i+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.length<=n.options.slidesToShow?t.addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(s=n.slideCount%n.options.slidesToShow,o=n.options.infinite===!0?n.options.slidesToShow+i:i,n.options.slidesToShow==n.options.slidesToScroll&&n.slideCount-i<n.options.slidesToShow?t.slice(o-(n.options.slidesToShow-s),o+s).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.slice(o,o+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"));\"ondemand\"!==n.options.lazyLoad&&\"anticipated\"!==n.options.lazyLoad||n.lazyLoad()},e.prototype.setupInfinite=function(){var e,t,o,s=this;if(s.options.fade===!0&&(s.options.centerMode=!1),s.options.infinite===!0&&s.options.fade===!1&&(t=null,s.slideCount>s.options.slidesToShow)){for(o=s.options.centerMode===!0?s.options.slidesToShow+1:s.options.slidesToShow,e=s.slideCount;e>s.slideCount-o;e-=1)t=e-1,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t-s.slideCount).prependTo(s.$slideTrack).addClass(\"slick-cloned\");for(e=0;e<o+s.slideCount;e+=1)t=e,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t+s.slideCount).appendTo(s.$slideTrack).addClass(\"slick-cloned\");s.$slideTrack.find(\".slick-cloned\").find(\"[id]\").each(function(){i(this).attr(\"id\",\"\")})}},e.prototype.interrupt=function(i){var e=this;i||e.autoPlay(),e.interrupted=i},e.prototype.selectHandler=function(e){var t=this,o=i(e.target).is(\".slick-slide\")?i(e.target):i(e.target).parents(\".slick-slide\"),s=parseInt(o.attr(\"data-slick-index\"));return s||(s=0),t.slideCount<=t.options.slidesToShow?void t.slideHandler(s,!1,!0):void t.slideHandler(s)},e.prototype.slideHandler=function(i,e,t){var o,s,n,r,l,d=null,a=this;if(e=e||!1,!(a.animating===!0&&a.options.waitForAnimate===!0||a.options.fade===!0&&a.currentSlide===i))return e===!1&&a.asNavFor(i),o=i,d=a.getLeft(o),r=a.getLeft(a.currentSlide),a.currentLeft=null===a.swipeLeft?r:a.swipeLeft,a.options.infinite===!1&&a.options.centerMode===!1&&(i<0||i>a.getDotCount()*a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):a.options.infinite===!1&&a.options.centerMode===!0&&(i<0||i>a.slideCount-a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):(a.options.autoplay&&clearInterval(a.autoPlayTimer),s=o<0?a.slideCount%a.options.slidesToScroll!==0?a.slideCount-a.slideCount%a.options.slidesToScroll:a.slideCount+o:o>=a.slideCount?a.slideCount%a.options.slidesToScroll!==0?0:o-a.slideCount:o,a.animating=!0,a.$slider.trigger(\"beforeChange\",[a,a.currentSlide,s]),n=a.currentSlide,a.currentSlide=s,a.setSlideClasses(a.currentSlide),a.options.asNavFor&&(l=a.getNavTarget(),l=l.slick(\"getSlick\"),l.slideCount<=l.options.slidesToShow&&l.setSlideClasses(a.currentSlide)),a.updateDots(),a.updateArrows(),a.options.fade===!0?(t!==!0?(a.fadeSlideOut(n),a.fadeSlide(s,function(){a.postSlide(s)})):a.postSlide(s),void a.animateHeight()):void(t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(d,function(){a.postSlide(s)}):a.postSlide(s)))},e.prototype.startLoad=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.hide(),i.$nextArrow.hide()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.hide(),i.$slider.addClass(\"slick-loading\")},e.prototype.swipeDirection=function(){var i,e,t,o,s=this;return i=s.touchObject.startX-s.touchObject.curX,e=s.touchObject.startY-s.touchObject.curY,t=Math.atan2(e,i),o=Math.round(180*t/Math.PI),o<0&&(o=360-Math.abs(o)),o<=45&&o>=0?s.options.rtl===!1?\"left\":\"right\":o<=360&&o>=315?s.options.rtl===!1?\"left\":\"right\":o>=135&&o<=225?s.options.rtl===!1?\"right\":\"left\":s.options.verticalSwiping===!0?o>=35&&o<=135?\"down\":\"up\":\"vertical\"},e.prototype.swipeEnd=function(i){var e,t,o=this;if(o.dragging=!1,o.swiping=!1,o.scrolling)return o.scrolling=!1,!1;if(o.interrupted=!1,o.shouldClick=!(o.touchObject.swipeLength>10),void 0===o.touchObject.curX)return!1;if(o.touchObject.edgeHit===!0&&o.$slider.trigger(\"edge\",[o,o.swipeDirection()]),o.touchObject.swipeLength>=o.touchObject.minSwipe){switch(t=o.swipeDirection()){case\"left\":case\"down\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide+o.getSlideCount()):o.currentSlide+o.getSlideCount(),o.currentDirection=0;break;case\"right\":case\"up\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide-o.getSlideCount()):o.currentSlide-o.getSlideCount(),o.currentDirection=1}\"vertical\"!=t&&(o.slideHandler(e),o.touchObject={},o.$slider.trigger(\"swipe\",[o,t]))}else o.touchObject.startX!==o.touchObject.curX&&(o.slideHandler(o.currentSlide),o.touchObject={})},e.prototype.swipeHandler=function(i){var e=this;if(!(e.options.swipe===!1||\"ontouchend\"in document&&e.options.swipe===!1||e.options.draggable===!1&&i.type.indexOf(\"mouse\")!==-1))switch(e.touchObject.fingerCount=i.originalEvent&&void 0!==i.originalEvent.touches?i.originalEvent.touches.length:1,e.touchObject.minSwipe=e.listWidth/e.options.touchThreshold,e.options.verticalSwiping===!0&&(e.touchObject.minSwipe=e.listHeight/e.options.touchThreshold),i.data.action){case\"start\":e.swipeStart(i);break;case\"move\":e.swipeMove(i);break;case\"end\":e.swipeEnd(i)}},e.prototype.swipeMove=function(i){var e,t,o,s,n,r,l=this;return n=void 0!==i.originalEvent?i.originalEvent.touches:null,!(!l.dragging||l.scrolling||n&&1!==n.length)&&(e=l.getLeft(l.currentSlide),l.touchObject.curX=void 0!==n?n[0].pageX:i.clientX,l.touchObject.curY=void 0!==n?n[0].pageY:i.clientY,l.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(l.touchObject.curX-l.touchObject.startX,2))),r=Math.round(Math.sqrt(Math.pow(l.touchObject.curY-l.touchObject.startY,2))),!l.options.verticalSwiping&&!l.swiping&&r>4?(l.scrolling=!0,!1):(l.options.verticalSwiping===!0&&(l.touchObject.swipeLength=r),t=l.swipeDirection(),void 0!==i.originalEvent&&l.touchObject.swipeLength>4&&(l.swiping=!0,i.preventDefault()),s=(l.options.rtl===!1?1:-1)*(l.touchObject.curX>l.touchObject.startX?1:-1),l.options.verticalSwiping===!0&&(s=l.touchObject.curY>l.touchObject.startY?1:-1),o=l.touchObject.swipeLength,l.touchObject.edgeHit=!1,l.options.infinite===!1&&(0===l.currentSlide&&\"right\"===t||l.currentSlide>=l.getDotCount()&&\"left\"===t)&&(o=l.touchObject.swipeLength*l.options.edgeFriction,l.touchObject.edgeHit=!0),l.options.vertical===!1?l.swipeLeft=e+o*s:l.swipeLeft=e+o*(l.$list.height()/l.listWidth)*s,l.options.verticalSwiping===!0&&(l.swipeLeft=e+o*s),l.options.fade!==!0&&l.options.touchMove!==!1&&(l.animating===!0?(l.swipeLeft=null,!1):void l.setCSS(l.swipeLeft))))},e.prototype.swipeStart=function(i){var e,t=this;return t.interrupted=!0,1!==t.touchObject.fingerCount||t.slideCount<=t.options.slidesToShow?(t.touchObject={},!1):(void 0!==i.originalEvent&&void 0!==i.originalEvent.touches&&(e=i.originalEvent.touches[0]),t.touchObject.startX=t.touchObject.curX=void 0!==e?e.pageX:i.clientX,t.touchObject.startY=t.touchObject.curY=void 0!==e?e.pageY:i.clientY,void(t.dragging=!0))},e.prototype.unfilterSlides=e.prototype.slickUnfilter=function(){var i=this;null!==i.$slidesCache&&(i.unload(),i.$slideTrack.children(this.options.slide).detach(),i.$slidesCache.appendTo(i.$slideTrack),i.reinit())},e.prototype.unload=function(){var e=this;i(\".slick-cloned\",e.$slider).remove(),e.$dots&&e.$dots.remove(),e.$prevArrow&&e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.remove(),e.$nextArrow&&e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.remove(),e.$slides.removeClass(\"slick-slide slick-active slick-visible slick-current\").attr(\"aria-hidden\",\"true\").css(\"width\",\"\")},e.prototype.unslick=function(i){var e=this;e.$slider.trigger(\"unslick\",[e,i]),e.destroy()},e.prototype.updateArrows=function(){var i,e=this;i=Math.floor(e.options.slidesToShow/2),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&!e.options.infinite&&(e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),0===e.currentSlide?(e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-e.options.slidesToShow&&e.options.centerMode===!1?(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-1&&e.options.centerMode===!0&&(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")))},e.prototype.updateDots=function(){var i=this;null!==i.$dots&&(i.$dots.find(\"li\").removeClass(\"slick-active\").end(),i.$dots.find(\"li\").eq(Math.floor(i.currentSlide/i.options.slidesToScroll)).addClass(\"slick-active\"))},e.prototype.visibility=function(){var i=this;i.options.autoplay&&(document[i.hidden]?i.interrupted=!0:i.interrupted=!1)},i.fn.slick=function(){var i,t,o=this,s=arguments[0],n=Array.prototype.slice.call(arguments,1),r=o.length;for(i=0;i<r;i++)if(\"object\"==typeof s||\"undefined\"==typeof s?o[i].slick=new e(o[i],s):t=o[i].slick[s].apply(o[i].slick,n),\"undefined\"!=typeof t)return t;return o}});\n","Amasty_Base/js/http_build_query.js":"/**\n * PHP htp_build_query() analog\n */\ndefine(\n [],\n function () {\n 'use strict';\n\n /**\n * Encodes param according to RFC3986 standard.\n *\n * @param {string} str\n * @returns {string}\n */\n function encodeComponentRaw(str)\n {\n str = (str + '');\n return encodeURIComponent(str)\n .replace(/!/g, '%21')\n .replace(/'/g, '%27')\n .replace(/\\(/g, '%28')\n .replace(/\\)/g, '%29')\n .replace(/\\*/g, '%2A');\n }\n\n /**\n * Encodes param according to RF1738 standard.\n *\n * @param {string} str\n * @returns {string}\n */\n function encodeComponent(str)\n {\n return encodeComponentRaw(str).replace(/%20/g, '+');\n }\n\n /**\n * Encode single GET param.\n *\n * @param {string} key\n * @param {string} val\n * @param {string} argSeparator\n * @param {function (string)} encodeFunc\n * @returns {string}\n */\n function buildParam(key, val, argSeparator, encodeFunc)\n {\n var result = [];\n if (val === true) {\n val = '1';\n } else if (val === false) {\n val = '0';\n }\n\n if (val !== null) {\n if (typeof val === 'object') {\n for (var index in val) {\n if (val[index] !== null) {\n result.push(buildParam(key + '[' + index + ']', val[index], argSeparator, encodeFunc));\n }\n }\n\n return result.join(argSeparator);\n } else if (typeof val !== 'function') {\n return encodeFunc(key) + '=' + encodeFunc(val);\n } else {\n throw new Error('There was an error processing for http_build_query().');\n }\n } else {\n return '';\n }\n };\n\n /**\n * Builds HTTP query in the same way as PHP htp_build_query() function.\n *\n * @param {array} formData\n * @param {string} numericPrefix\n * @param {string} argSeparator\n * @param {string} encType\n * @returns {string}\n */\n function httpBuildQuery(formData, numericPrefix, argSeparator, encType)\n {\n var result = [],\n encode = (encType == 'PHP_QUERY_RFC3986') ? encodeComponentRaw : encodeComponent;\n if (!argSeparator) {\n argSeparator = '&';\n }\n\n for (var key in formData) {\n if (numericPrefix && !isNaN(key)) {\n key = String(numericPrefix) + key;\n }\n var query = buildParam(key, formData[key], argSeparator, encode);\n if (query !== '') {\n result.push(query);\n }\n }\n\n return result.join(argSeparator);\n };\n\n return function (formData, numericPrefix, argSeparator, encType) {\n return httpBuildQuery(formData, numericPrefix, argSeparator, encType);\n }\n }\n);\n","Smartwave_Filterproducts/js/packery.pkgd.js":"/*!\n * Packery PACKAGED v1.4.3\n * bin-packing layout library\n *\n * Licensed GPLv3 for open source use\n * or Flickity Commercial License for commercial use\n *\n * http://packery.metafizzy.co\n * Copyright 2015 Metafizzy\n */\n\n/**\n * Bridget makes jQuery widgets\n * v1.1.0\n * MIT license\n */\n\n( function( window ) {\n\n\n\n// -------------------------- utils -------------------------- //\n\nvar slice = Array.prototype.slice;\n\nfunction noop() {}\n\n// -------------------------- definition -------------------------- //\n\nfunction defineBridget( $ ) {\n\n// bail if no jQuery\nif ( !$ ) {\n return;\n}\n\n// -------------------------- addOptionMethod -------------------------- //\n\n/**\n * adds option method -> $().plugin('option', {...})\n * @param {Function} PluginClass - constructor class\n */\nfunction addOptionMethod( PluginClass ) {\n // don't overwrite original option method\n if ( PluginClass.prototype.option ) {\n return;\n }\n\n // option setter\n PluginClass.prototype.option = function( opts ) {\n // bail out if not an object\n if ( !$.isPlainObject( opts ) ){\n return;\n }\n this.options = $.extend( true, this.options, opts );\n };\n}\n\n// -------------------------- plugin bridge -------------------------- //\n\n// helper function for logging errors\n// $.error breaks jQuery chaining\nvar logError = typeof console === 'undefined' ? noop :\n function( message ) {\n console.error( message );\n };\n\n/**\n * jQuery plugin bridge, access methods like $elem.plugin('method')\n * @param {String} namespace - plugin name\n * @param {Function} PluginClass - constructor class\n */\nfunction bridge( namespace, PluginClass ) {\n // add to jQuery fn namespace\n $.fn[ namespace ] = function( options ) {\n if ( typeof options === 'string' ) {\n // call plugin method when first argument is a string\n // get arguments for method\n var args = slice.call( arguments, 1 );\n\n for ( var i=0, len = this.length; i < len; i++ ) {\n var elem = this[i];\n var instance = $.data( elem, namespace );\n if ( !instance ) {\n logError( \"cannot call methods on \" + namespace + \" prior to initialization; \" +\n \"attempted to call '\" + options + \"'\" );\n continue;\n }\n if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) {\n logError( \"no such method '\" + options + \"' for \" + namespace + \" instance\" );\n continue;\n }\n\n // trigger method with arguments\n var returnValue = instance[ options ].apply( instance, args );\n\n // break look and return first value if provided\n if ( returnValue !== undefined ) {\n return returnValue;\n }\n }\n // return this if no return value\n return this;\n } else {\n return this.each( function() {\n var instance = $.data( this, namespace );\n if ( instance ) {\n // apply options & init\n instance.option( options );\n instance._init();\n } else {\n // initialize new instance\n instance = new PluginClass( this, options );\n $.data( this, namespace, instance );\n }\n });\n }\n };\n\n}\n\n// -------------------------- bridget -------------------------- //\n\n/**\n * converts a Prototypical class into a proper jQuery plugin\n * the class must have a ._init method\n * @param {String} namespace - plugin name, used in $().pluginName\n * @param {Function} PluginClass - constructor class\n */\n$.bridget = function( namespace, PluginClass ) {\n addOptionMethod( PluginClass );\n bridge( namespace, PluginClass );\n};\n\nreturn $.bridget;\n\n}\n\n// transport\nif ( typeof define === 'function' && define.amd ) {\n // AMD\n define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget );\n} else if ( typeof exports === 'object' ) {\n defineBridget( require('jquery') );\n} else {\n // get jquery from browser global\n defineBridget( window.jQuery );\n}\ndefineBridget( window.jQuery );\n})( window );\n\n/*!\n * classie v1.0.1\n * class helper functions\n * from bonzo https://github.com/ded/bonzo\n * MIT license\n * \n * classie.has( elem, 'my-class' ) -> true/false\n * classie.add( elem, 'my-new-class' )\n * classie.remove( elem, 'my-unwanted-class' )\n * classie.toggle( elem, 'my-class' )\n */\n\n/*jshint browser: true, strict: true, undef: true, unused: true */\n/*global define: false, module: false */\n\n( function( window ) {\n\n\n\n// class helper functions from bonzo https://github.com/ded/bonzo\n\nfunction classReg( className ) {\n return new RegExp(\"(^|\\\\s+)\" + className + \"(\\\\s+|$)\");\n}\n\n// classList support for class management\n// altho to be fair, the api sucks because it won't accept multiple classes at once\nvar hasClass, addClass, removeClass;\n\nif ( 'classList' in document.documentElement ) {\n hasClass = function( elem, c ) {\n return elem.classList.contains( c );\n };\n addClass = function( elem, c ) {\n elem.classList.add( c );\n };\n removeClass = function( elem, c ) {\n elem.classList.remove( c );\n };\n}\nelse {\n hasClass = function( elem, c ) {\n return classReg( c ).test( elem.className );\n };\n addClass = function( elem, c ) {\n if ( !hasClass( elem, c ) ) {\n elem.className = elem.className + ' ' + c;\n }\n };\n removeClass = function( elem, c ) {\n elem.className = elem.className.replace( classReg( c ), ' ' );\n };\n}\n\nfunction toggleClass( elem, c ) {\n var fn = hasClass( elem, c ) ? removeClass : addClass;\n fn( elem, c );\n}\n\nvar classie = {\n // full names\n hasClass: hasClass,\n addClass: addClass,\n removeClass: removeClass,\n toggleClass: toggleClass,\n // short names\n has: hasClass,\n add: addClass,\n remove: removeClass,\n toggle: toggleClass\n};\n\n// transport\nif ( typeof define === 'function' && define.amd ) {\n // AMD\n define( 'classie/classie',classie );\n} else if ( typeof exports === 'object' ) {\n // CommonJS\n module.exports = classie;\n} else {\n // browser global\n window.classie = classie;\n}\n\n})( window );\n\n/*!\n * getStyleProperty v1.0.4\n * original by kangax\n * http://perfectionkills.com/feature-testing-css-properties/\n * MIT license\n */\n\n/*jshint browser: true, strict: true, undef: true */\n/*global define: false, exports: false, module: false */\n\n( function( window ) {\n\n\n\nvar prefixes = 'Webkit Moz ms Ms O'.split(' ');\nvar docElemStyle = document.documentElement.style;\n\nfunction getStyleProperty( propName ) {\n if ( !propName ) {\n return;\n }\n\n // test standard property first\n if ( typeof docElemStyle[ propName ] === 'string' ) {\n return propName;\n }\n\n // capitalize\n propName = propName.charAt(0).toUpperCase() + propName.slice(1);\n\n // test vendor specific properties\n var prefixed;\n for ( var i=0, len = prefixes.length; i < len; i++ ) {\n prefixed = prefixes[i] + propName;\n if ( typeof docElemStyle[ prefixed ] === 'string' ) {\n return prefixed;\n }\n }\n}\n\n// transport\nif ( typeof define === 'function' && define.amd ) {\n // AMD\n define( 'get-style-property/get-style-property',[],function() {\n return getStyleProperty;\n });\n} else if ( typeof exports === 'object' ) {\n // CommonJS for Component\n module.exports = getStyleProperty;\n} else {\n // browser global\n window.getStyleProperty = getStyleProperty;\n}\n\n})( window );\n\n/*!\n * getSize v1.2.2\n * measure size of elements\n * MIT license\n */\n\n/*jshint browser: true, strict: true, undef: true, unused: true */\n/*global define: false, exports: false, require: false, module: false, console: false */\n\n( function( window, undefined ) {\n\n\n\n// -------------------------- helpers -------------------------- //\n\n// get a number from a string, not a percentage\nfunction getStyleSize( value ) {\n var num = parseFloat( value );\n // not a percent like '100%', and a number\n var isValid = value.indexOf('%') === -1 && !isNaN( num );\n return isValid && num;\n}\n\nfunction noop() {}\n\nvar logError = typeof console === 'undefined' ? noop :\n function( message ) {\n console.error( message );\n };\n\n// -------------------------- measurements -------------------------- //\n\nvar measurements = [\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'paddingBottom',\n 'marginLeft',\n 'marginRight',\n 'marginTop',\n 'marginBottom',\n 'borderLeftWidth',\n 'borderRightWidth',\n 'borderTopWidth',\n 'borderBottomWidth'\n];\n\nfunction getZeroSize() {\n var size = {\n width: 0,\n height: 0,\n innerWidth: 0,\n innerHeight: 0,\n outerWidth: 0,\n outerHeight: 0\n };\n for ( var i=0, len = measurements.length; i < len; i++ ) {\n var measurement = measurements[i];\n size[ measurement ] = 0;\n }\n return size;\n}\n\n\n\nfunction defineGetSize( getStyleProperty ) {\n\n// -------------------------- setup -------------------------- //\n\nvar isSetup = false;\n\nvar getStyle, boxSizingProp, isBoxSizeOuter;\n\n/**\n * setup vars and functions\n * do it on initial getSize(), rather than on script load\n * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n */\nfunction setup() {\n // setup once\n if ( isSetup ) {\n return;\n }\n isSetup = true;\n\n var getComputedStyle = window.getComputedStyle;\n getStyle = ( function() {\n var getStyleFn = getComputedStyle ?\n function( elem ) {\n return getComputedStyle( elem, null );\n } :\n function( elem ) {\n return elem.currentStyle;\n };\n\n return function getStyle( elem ) {\n var style = getStyleFn( elem );\n if ( !style ) {\n logError( 'Style returned ' + style +\n '. Are you running this code in a hidden iframe on Firefox? ' +\n 'See http://bit.ly/getsizebug1' );\n }\n return style;\n };\n })();\n\n // -------------------------- box sizing -------------------------- //\n\n boxSizingProp = getStyleProperty('boxSizing');\n\n /**\n * WebKit measures the outer-width on style.width on border-box elems\n * IE & Firefox measures the inner-width\n */\n if ( boxSizingProp ) {\n var div = document.createElement('div');\n div.style.width = '200px';\n div.style.padding = '1px 2px 3px 4px';\n div.style.borderStyle = 'solid';\n div.style.borderWidth = '1px 2px 3px 4px';\n div.style[ boxSizingProp ] = 'border-box';\n\n var body = document.body || document.documentElement;\n body.appendChild( div );\n var style = getStyle( div );\n\n isBoxSizeOuter = getStyleSize( style.width ) === 200;\n body.removeChild( div );\n }\n\n}\n\n// -------------------------- getSize -------------------------- //\n\nfunction getSize( elem ) {\n setup();\n\n // use querySeletor if elem is string\n if ( typeof elem === 'string' ) {\n elem = document.querySelector( elem );\n }\n\n // do not proceed on non-objects\n if ( !elem || typeof elem !== 'object' || !elem.nodeType ) {\n return;\n }\n\n var style = getStyle( elem );\n\n // if hidden, everything is 0\n if ( style.display === 'none' ) {\n return getZeroSize();\n }\n\n var size = {};\n size.width = elem.offsetWidth;\n size.height = elem.offsetHeight;\n\n var isBorderBox = size.isBorderBox = !!( boxSizingProp &&\n style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' );\n\n // get all measurements\n for ( var i=0, len = measurements.length; i < len; i++ ) {\n var measurement = measurements[i];\n var value = style[ measurement ];\n value = mungeNonPixel( elem, value );\n var num = parseFloat( value );\n // any 'auto', 'medium' value will be 0\n size[ measurement ] = !isNaN( num ) ? num : 0;\n }\n\n var paddingWidth = size.paddingLeft + size.paddingRight;\n var paddingHeight = size.paddingTop + size.paddingBottom;\n var marginWidth = size.marginLeft + size.marginRight;\n var marginHeight = size.marginTop + size.marginBottom;\n var borderWidth = size.borderLeftWidth + size.borderRightWidth;\n var borderHeight = size.borderTopWidth + size.borderBottomWidth;\n\n var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;\n\n // overwrite width and height if we can get it from style\n var styleWidth = getStyleSize( style.width );\n if ( styleWidth !== false ) {\n size.width = styleWidth +\n // add padding and border unless it's already including it\n ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );\n }\n\n var styleHeight = getStyleSize( style.height );\n if ( styleHeight !== false ) {\n size.height = styleHeight +\n // add padding and border unless it's already including it\n ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );\n }\n\n size.innerWidth = size.width - ( paddingWidth + borderWidth );\n size.innerHeight = size.height - ( paddingHeight + borderHeight );\n\n size.outerWidth = size.width + marginWidth;\n size.outerHeight = size.height + marginHeight;\n\n return size;\n}\n\n// IE8 returns percent values, not pixels\n// taken from jQuery's curCSS\nfunction mungeNonPixel( elem, value ) {\n // IE8 and has percent value\n if ( window.getComputedStyle || value.indexOf('%') === -1 ) {\n return value;\n }\n var style = elem.style;\n // Remember the original values\n var left = style.left;\n var rs = elem.runtimeStyle;\n var rsLeft = rs && rs.left;\n\n // Put in the new values to get a computed value out\n if ( rsLeft ) {\n rs.left = elem.currentStyle.left;\n }\n style.left = value;\n value = style.pixelLeft;\n\n // Revert the changed values\n style.left = left;\n if ( rsLeft ) {\n rs.left = rsLeft;\n }\n\n return value;\n}\n\nreturn getSize;\n\n}\n\n// transport\nif ( typeof define === 'function' && define.amd ) {\n // AMD for RequireJS\n define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize );\n} else if ( typeof exports === 'object' ) {\n // CommonJS for Component\n module.exports = defineGetSize( require('desandro-get-style-property') );\n} else {\n // browser global\n window.getSize = defineGetSize( window.getStyleProperty );\n}\n\n})( window );\n\n/*!\n * eventie v1.0.6\n * event binding helper\n * eventie.bind( elem, 'click', myFn )\n * eventie.unbind( elem, 'click', myFn )\n * MIT license\n */\n\n/*jshint browser: true, undef: true, unused: true */\n/*global define: false, module: false */\n\n( function( window ) {\n\n\n\nvar docElem = document.documentElement;\n\nvar bind = function() {};\n\nfunction getIEEvent( obj ) {\n var event = window.event;\n // add event.target\n event.target = event.target || event.srcElement || obj;\n return event;\n}\n\nif ( docElem.addEventListener ) {\n bind = function( obj, type, fn ) {\n obj.addEventListener( type, fn, false );\n };\n} else if ( docElem.attachEvent ) {\n bind = function( obj, type, fn ) {\n obj[ type + fn ] = fn.handleEvent ?\n function() {\n var event = getIEEvent( obj );\n fn.handleEvent.call( fn, event );\n } :\n function() {\n var event = getIEEvent( obj );\n fn.call( obj, event );\n };\n obj.attachEvent( \"on\" + type, obj[ type + fn ] );\n };\n}\n\nvar unbind = function() {};\n\nif ( docElem.removeEventListener ) {\n unbind = function( obj, type, fn ) {\n obj.removeEventListener( type, fn, false );\n };\n} else if ( docElem.detachEvent ) {\n unbind = function( obj, type, fn ) {\n obj.detachEvent( \"on\" + type, obj[ type + fn ] );\n try {\n delete obj[ type + fn ];\n } catch ( err ) {\n // can't delete window object properties\n obj[ type + fn ] = undefined;\n }\n };\n}\n\nvar eventie = {\n bind: bind,\n unbind: unbind\n};\n\n// ----- module definition ----- //\n\nif ( typeof define === 'function' && define.amd ) {\n // AMD\n define( 'eventie/eventie',eventie );\n} else if ( typeof exports === 'object' ) {\n // CommonJS\n module.exports = eventie;\n} else {\n // browser global\n window.eventie = eventie;\n}\nwindow.eventie = eventie;\n})( window );\n\n/*!\n * EventEmitter v4.2.11 - git.io/ee\n * Unlicense - http://unlicense.org/\n * Oliver Caldwell - http://oli.me.uk/\n * @preserve\n */\n\n;(function () {\n \n\n /**\n * Class for managing events.\n * Can be extended to provide event functionality in other classes.\n *\n * @class EventEmitter Manages event registering and emitting.\n */\n function EventEmitter() {}\n\n // Shortcuts to improve speed and size\n var proto = EventEmitter.prototype;\n var exports = this;\n var originalGlobalValue = exports.EventEmitter;\n\n /**\n * Finds the index of the listener for the event in its storage array.\n *\n * @param {Function[]} listeners Array of listeners to search through.\n * @param {Function} listener Method to look for.\n * @return {Number} Index of the specified listener, -1 if not found\n * @api private\n */\n function indexOfListener(listeners, listener) {\n var i = listeners.length;\n while (i--) {\n if (listeners[i].listener === listener) {\n return i;\n }\n }\n\n return -1;\n }\n\n /**\n * Alias a method while keeping the context correct, to allow for overwriting of target method.\n *\n * @param {String} name The name of the target method.\n * @return {Function} The aliased method\n * @api private\n */\n function alias(name) {\n return function aliasClosure() {\n return this[name].apply(this, arguments);\n };\n }\n\n /**\n * Returns the listener array for the specified event.\n * Will initialise the event object and listener arrays if required.\n * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.\n * Each property in the object response is an array of listener functions.\n *\n * @param {String|RegExp} evt Name of the event to return the listeners from.\n * @return {Function[]|Object} All listener functions for the event.\n */\n proto.getListeners = function getListeners(evt) {\n var events = this._getEvents();\n var response;\n var key;\n\n // Return a concatenated array of all matching events if\n // the selector is a regular expression.\n if (evt instanceof RegExp) {\n response = {};\n for (key in events) {\n if (events.hasOwnProperty(key) && evt.test(key)) {\n response[key] = events[key];\n }\n }\n }\n else {\n response = events[evt] || (events[evt] = []);\n }\n\n return response;\n };\n\n /**\n * Takes a list of listener objects and flattens it into a list of listener functions.\n *\n * @param {Object[]} listeners Raw listener objects.\n * @return {Function[]} Just the listener functions.\n */\n proto.flattenListeners = function flattenListeners(listeners) {\n var flatListeners = [];\n var i;\n\n for (i = 0; i < listeners.length; i += 1) {\n flatListeners.push(listeners[i].listener);\n }\n\n return flatListeners;\n };\n\n /**\n * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.\n *\n * @param {String|RegExp} evt Name of the event to return the listeners from.\n * @return {Object} All listener functions for an event in an object.\n */\n proto.getListenersAsObject = function getListenersAsObject(evt) {\n var listeners = this.getListeners(evt);\n var response;\n\n if (listeners instanceof Array) {\n response = {};\n response[evt] = listeners;\n }\n\n return response || listeners;\n };\n\n /**\n * Adds a listener function to the specified event.\n * The listener will not be added if it is a duplicate.\n * If the listener returns true then it will be removed after it is called.\n * If you pass a regular expression as the event name then the listener will be added to all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to attach the listener to.\n * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.addListener = function addListener(evt, listener) {\n var listeners = this.getListenersAsObject(evt);\n var listenerIsWrapped = typeof listener === 'object';\n var key;\n\n for (key in listeners) {\n if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {\n listeners[key].push(listenerIsWrapped ? listener : {\n listener: listener,\n once: false\n });\n }\n }\n\n return this;\n };\n\n /**\n * Alias of addListener\n */\n proto.on = alias('addListener');\n\n /**\n * Semi-alias of addListener. It will add a listener that will be\n * automatically removed after its first execution.\n *\n * @param {String|RegExp} evt Name of the event to attach the listener to.\n * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.addOnceListener = function addOnceListener(evt, listener) {\n return this.addListener(evt, {\n listener: listener,\n once: true\n });\n };\n\n /**\n * Alias of addOnceListener.\n */\n proto.once = alias('addOnceListener');\n\n /**\n * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.\n * You need to tell it what event names should be matched by a regex.\n *\n * @param {String} evt Name of the event to create.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.defineEvent = function defineEvent(evt) {\n this.getListeners(evt);\n return this;\n };\n\n /**\n * Uses defineEvent to define multiple events.\n *\n * @param {String[]} evts An array of event names to define.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.defineEvents = function defineEvents(evts) {\n for (var i = 0; i < evts.length; i += 1) {\n this.defineEvent(evts[i]);\n }\n return this;\n };\n\n /**\n * Removes a listener function from the specified event.\n * When passed a regular expression as the event name, it will remove the listener from all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to remove the listener from.\n * @param {Function} listener Method to remove from the event.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.removeListener = function removeListener(evt, listener) {\n var listeners = this.getListenersAsObject(evt);\n var index;\n var key;\n\n for (key in listeners) {\n if (listeners.hasOwnProperty(key)) {\n index = indexOfListener(listeners[key], listener);\n\n if (index !== -1) {\n listeners[key].splice(index, 1);\n }\n }\n }\n\n return this;\n };\n\n /**\n * Alias of removeListener\n */\n proto.off = alias('removeListener');\n\n /**\n * Adds listeners in bulk using the manipulateListeners method.\n * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.\n * You can also pass it a regular expression to add the array of listeners to all events that match it.\n * Yeah, this function does quite a bit. That's probably a bad thing.\n *\n * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.\n * @param {Function[]} [listeners] An optional array of listener functions to add.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.addListeners = function addListeners(evt, listeners) {\n // Pass through to manipulateListeners\n return this.manipulateListeners(false, evt, listeners);\n };\n\n /**\n * Removes listeners in bulk using the manipulateListeners method.\n * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.\n * You can also pass it an event name and an array of listeners to be removed.\n * You can also pass it a regular expression to remove the listeners from all events that match it.\n *\n * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.\n * @param {Function[]} [listeners] An optional array of listener functions to remove.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.removeListeners = function removeListeners(evt, listeners) {\n // Pass through to manipulateListeners\n return this.manipulateListeners(true, evt, listeners);\n };\n\n /**\n * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.\n * The first argument will determine if the listeners are removed (true) or added (false).\n * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.\n * You can also pass it an event name and an array of listeners to be added/removed.\n * You can also pass it a regular expression to manipulate the listeners of all events that match it.\n *\n * @param {Boolean} remove True if you want to remove listeners, false if you want to add.\n * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.\n * @param {Function[]} [listeners] An optional array of listener functions to add/remove.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {\n var i;\n var value;\n var single = remove ? this.removeListener : this.addListener;\n var multiple = remove ? this.removeListeners : this.addListeners;\n\n // If evt is an object then pass each of its properties to this method\n if (typeof evt === 'object' && !(evt instanceof RegExp)) {\n for (i in evt) {\n if (evt.hasOwnProperty(i) && (value = evt[i])) {\n // Pass the single listener straight through to the singular method\n if (typeof value === 'function') {\n single.call(this, i, value);\n }\n else {\n // Otherwise pass back to the multiple function\n multiple.call(this, i, value);\n }\n }\n }\n }\n else {\n // So evt must be a string\n // And listeners must be an array of listeners\n // Loop over it and pass each one to the multiple method\n i = listeners.length;\n while (i--) {\n single.call(this, evt, listeners[i]);\n }\n }\n\n return this;\n };\n\n /**\n * Removes all listeners from a specified event.\n * If you do not specify an event then all listeners will be removed.\n * That means every event will be emptied.\n * You can also pass a regex to remove all events that match it.\n *\n * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.removeEvent = function removeEvent(evt) {\n var type = typeof evt;\n var events = this._getEvents();\n var key;\n\n // Remove different things depending on the state of evt\n if (type === 'string') {\n // Remove all listeners for the specified event\n delete events[evt];\n }\n else if (evt instanceof RegExp) {\n // Remove all events matching the regex.\n for (key in events) {\n if (events.hasOwnProperty(key) && evt.test(key)) {\n delete events[key];\n }\n }\n }\n else {\n // Remove all listeners in all events\n delete this._events;\n }\n\n return this;\n };\n\n /**\n * Alias of removeEvent.\n *\n * Added to mirror the node API.\n */\n proto.removeAllListeners = alias('removeEvent');\n\n /**\n * Emits an event of your choice.\n * When emitted, every listener attached to that event will be executed.\n * If you pass the optional argument array then those arguments will be passed to every listener upon execution.\n * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.\n * So they will not arrive within the array on the other side, they will be separate.\n * You can also pass a regular expression to emit to all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to emit and execute listeners for.\n * @param {Array} [args] Optional array of arguments to be passed to each listener.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.emitEvent = function emitEvent(evt, args) {\n var listeners = this.getListenersAsObject(evt);\n var listener;\n var i;\n var key;\n var response;\n\n for (key in listeners) {\n if (listeners.hasOwnProperty(key)) {\n i = listeners[key].length;\n\n while (i--) {\n // If the listener returns true then it shall be removed from the event\n // The function is executed either with a basic call or an apply if there is an args array\n listener = listeners[key][i];\n\n if (listener.once === true) {\n this.removeListener(evt, listener.listener);\n }\n\n response = listener.listener.apply(this, args || []);\n\n if (response === this._getOnceReturnValue()) {\n this.removeListener(evt, listener.listener);\n }\n }\n }\n }\n\n return this;\n };\n\n /**\n * Alias of emitEvent\n */\n proto.trigger = alias('emitEvent');\n\n /**\n * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.\n * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.\n *\n * @param {String|RegExp} evt Name of the event to emit and execute listeners for.\n * @param {...*} Optional additional arguments to be passed to each listener.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.emit = function emit(evt) {\n var args = Array.prototype.slice.call(arguments, 1);\n return this.emitEvent(evt, args);\n };\n\n /**\n * Sets the current value to check against when executing listeners. If a\n * listeners return value matches the one set here then it will be removed\n * after execution. This value defaults to true.\n *\n * @param {*} value The new value to check for when executing listeners.\n * @return {Object} Current instance of EventEmitter for chaining.\n */\n proto.setOnceReturnValue = function setOnceReturnValue(value) {\n this._onceReturnValue = value;\n return this;\n };\n\n /**\n * Fetches the current value to check against when executing listeners. If\n * the listeners return value matches this one then it should be removed\n * automatically. It will return true by default.\n *\n * @return {*|Boolean} The current value to check for or the default, true.\n * @api private\n */\n proto._getOnceReturnValue = function _getOnceReturnValue() {\n if (this.hasOwnProperty('_onceReturnValue')) {\n return this._onceReturnValue;\n }\n else {\n return true;\n }\n };\n\n /**\n * Fetches the events object and creates one if required.\n *\n * @return {Object} The events storage object.\n * @api private\n */\n proto._getEvents = function _getEvents() {\n return this._events || (this._events = {});\n };\n\n /**\n * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.\n *\n * @return {Function} Non conflicting EventEmitter class.\n */\n EventEmitter.noConflict = function noConflict() {\n exports.EventEmitter = originalGlobalValue;\n return EventEmitter;\n };\n\n // Expose the class either via AMD, CommonJS or the global object\n if (typeof define === 'function' && define.amd) {\n define('eventEmitter/EventEmitter',[],function () {\n return EventEmitter;\n });\n }\n else if (typeof module === 'object' && module.exports){\n module.exports = EventEmitter;\n }\n else {\n exports.EventEmitter = EventEmitter;\n }\n}.call(this));\n\n/*!\n * docReady v1.0.4\n * Cross browser DOMContentLoaded event emitter\n * MIT license\n */\n\n/*jshint browser: true, strict: true, undef: true, unused: true*/\n/*global define: false, require: false, module: false */\n\n( function( window ) {\n\n\n\nvar document = window.document;\n// collection of functions to be triggered on ready\nvar queue = [];\n\nfunction docReady( fn ) {\n // throw out non-functions\n if ( typeof fn !== 'function' ) {\n return;\n }\n\n if ( docReady.isReady ) {\n // ready now, hit it\n fn();\n } else {\n // queue function when ready\n queue.push( fn );\n }\n}\n\ndocReady.isReady = false;\n\n// triggered on various doc ready events\nfunction onReady( event ) {\n // bail if already triggered or IE8 document is not ready just yet\n var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete';\n if ( docReady.isReady || isIE8NotReady ) {\n return;\n }\n\n trigger();\n}\n\nfunction trigger() {\n docReady.isReady = true;\n // process queue\n for ( var i=0, len = queue.length; i < len; i++ ) {\n var fn = queue[i];\n fn();\n }\n}\n\nfunction defineDocReady( eventie ) {\n // trigger ready if page is ready\n if ( document.readyState === 'complete' ) {\n trigger();\n } else {\n // listen for events\n window.eventie.bind( document, 'DOMContentLoaded', onReady );\n window.eventie.bind( document, 'readystatechange', onReady );\n window.eventie.bind( window, 'load', onReady );\n }\n\n return docReady;\n}\n\n// transport\nif ( typeof define === 'function' && define.amd ) {\n // AMD\n define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady );\n} else if ( typeof exports === 'object' ) {\n module.exports = defineDocReady( require('eventie') );\n} else {\n // browser global\n window.docReady = defineDocReady( window.eventie );\n}\n\n})( window );\n\n/**\n * matchesSelector v1.0.3\n * matchesSelector( element, '.selector' )\n * MIT license\n */\n\n/*jshint browser: true, strict: true, undef: true, unused: true */\n/*global define: false, module: false */\n\n( function( ElemProto ) {\n\n \n\n var matchesMethod = ( function() {\n // check for the standard method name first\n if ( ElemProto.matches ) {\n return 'matches';\n }\n // check un-prefixed\n if ( ElemProto.matchesSelector ) {\n return 'matchesSelector';\n }\n // check vendor prefixes\n var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];\n\n for ( var i=0, len = prefixes.length; i < len; i++ ) {\n var prefix = prefixes[i];\n var method = prefix + 'MatchesSelector';\n if ( ElemProto[ method ] ) {\n return method;\n }\n }\n })();\n\n // ----- match ----- //\n\n function match( elem, selector ) {\n return elem[ matchesMethod ]( selector );\n }\n\n // ----- appendToFragment ----- //\n\n function checkParent( elem ) {\n // not needed if already has parent\n if ( elem.parentNode ) {\n return;\n }\n var fragment = document.createDocumentFragment();\n fragment.appendChild( elem );\n }\n\n // ----- query ----- //\n\n // fall back to using QSA\n // thx @jonathantneal https://gist.github.com/3062955\n function query( elem, selector ) {\n // append to fragment if no parent\n checkParent( elem );\n\n // match elem with all selected elems of parent\n var elems = elem.parentNode.querySelectorAll( selector );\n for ( var i=0, len = elems.length; i < len; i++ ) {\n // return true if match\n if ( elems[i] === elem ) {\n return true;\n }\n }\n // otherwise return false\n return false;\n }\n\n // ----- matchChild ----- //\n\n function matchChild( elem, selector ) {\n checkParent( elem );\n return match( elem, selector );\n }\n\n // ----- matchesSelector ----- //\n\n var matchesSelector;\n\n if ( matchesMethod ) {\n // IE9 supports matchesSelector, but doesn't work on orphaned elems\n // check for that\n var div = document.createElement('div');\n var supportsOrphans = match( div, 'div' );\n matchesSelector = supportsOrphans ? match : matchChild;\n } else {\n matchesSelector = query;\n }\n\n // transport\n if ( typeof define === 'function' && define.amd ) {\n // AMD\n define( 'matches-selector/matches-selector',[],function() {\n return matchesSelector;\n });\n } else if ( typeof exports === 'object' ) {\n module.exports = matchesSelector;\n }\n else {\n // browser global\n window.matchesSelector = matchesSelector;\n }\n\n})( Element.prototype );\n\n/**\n * Fizzy UI utils v1.0.1\n * MIT license\n */\n\n/*jshint browser: true, undef: true, unused: true, strict: true */\n\n( function( window, factory ) {\n /*global define: false, module: false, require: false */\n \n // universal module definition\n\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'fizzy-ui-utils/utils',[\n 'doc-ready/doc-ready',\n 'matches-selector/matches-selector'\n ], function( docReady, matchesSelector ) {\n return factory( window, docReady, matchesSelector );\n });\n } else if ( typeof exports == 'object' ) {\n // CommonJS\n module.exports = factory(\n window,\n require('doc-ready'),\n require('desandro-matches-selector')\n );\n } else {\n // browser global\n window.fizzyUIUtils = factory(\n window,\n window.docReady,\n window.matchesSelector\n );\n }\n\n}( window, function factory( window, docReady, matchesSelector ) {\n\n\n\nvar utils = {};\n\n// ----- extend ----- //\n\n// extends objects\nutils.extend = function( a, b ) {\n for ( var prop in b ) {\n a[ prop ] = b[ prop ];\n }\n return a;\n};\n\n// ----- modulo ----- //\n\nutils.modulo = function( num, div ) {\n return ( ( num % div ) + div ) % div;\n};\n\n// ----- isArray ----- //\n \nvar objToString = Object.prototype.toString;\nutils.isArray = function( obj ) {\n return objToString.call( obj ) == '[object Array]';\n};\n\n// ----- makeArray ----- //\n\n// turn element or nodeList into an array\nutils.makeArray = function( obj ) {\n var ary = [];\n if ( utils.isArray( obj ) ) {\n // use object if already an array\n ary = obj;\n } else if ( obj && typeof obj.length == 'number' ) {\n // convert nodeList to array\n for ( var i=0, len = obj.length; i < len; i++ ) {\n ary.push( obj[i] );\n }\n } else {\n // array of single index\n ary.push( obj );\n }\n return ary;\n};\n\n// ----- indexOf ----- //\n\n// index of helper cause IE8\nutils.indexOf = Array.prototype.indexOf ? function( ary, obj ) {\n return ary.indexOf( obj );\n } : function( ary, obj ) {\n for ( var i=0, len = ary.length; i < len; i++ ) {\n if ( ary[i] === obj ) {\n return i;\n }\n }\n return -1;\n };\n\n// ----- removeFrom ----- //\n\nutils.removeFrom = function( ary, obj ) {\n var index = utils.indexOf( ary, obj );\n if ( index != -1 ) {\n ary.splice( index, 1 );\n }\n};\n\n// ----- isElement ----- //\n\n// http://stackoverflow.com/a/384380/182183\nutils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ?\n function isElementDOM2( obj ) {\n return obj instanceof HTMLElement;\n } :\n function isElementQuirky( obj ) {\n return obj && typeof obj == 'object' &&\n obj.nodeType == 1 && typeof obj.nodeName == 'string';\n };\n\n// ----- setText ----- //\n\nutils.setText = ( function() {\n var setTextProperty;\n function setText( elem, text ) {\n // only check setTextProperty once\n setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' );\n elem[ setTextProperty ] = text;\n }\n return setText;\n})();\n\n// ----- getParent ----- //\n\nutils.getParent = function( elem, selector ) {\n while ( elem != document.body ) {\n elem = elem.parentNode;\n if ( matchesSelector( elem, selector ) ) {\n return elem;\n }\n }\n};\n\n// ----- getQueryElement ----- //\n\n// use element as selector string\nutils.getQueryElement = function( elem ) {\n if ( typeof elem == 'string' ) {\n return document.querySelector( elem );\n }\n return elem;\n};\n\n// ----- handleEvent ----- //\n\n// enable .ontype to trigger from .addEventListener( elem, 'type' )\nutils.handleEvent = function( event ) {\n var method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\n// ----- filterFindElements ----- //\n\nutils.filterFindElements = function( elems, selector ) {\n // make array of elems\n elems = utils.makeArray( elems );\n var ffElems = [];\n\n for ( var i=0, len = elems.length; i < len; i++ ) {\n var elem = elems[i];\n // check that elem is an actual element\n if ( !utils.isElement( elem ) ) {\n continue;\n }\n // filter & find items if we have a selector\n if ( selector ) {\n // filter siblings\n if ( matchesSelector( elem, selector ) ) {\n ffElems.push( elem );\n }\n // find children\n var childElems = elem.querySelectorAll( selector );\n // concat childElems to filterFound array\n for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {\n ffElems.push( childElems[j] );\n }\n } else {\n ffElems.push( elem );\n }\n }\n\n return ffElems;\n};\n\n// ----- debounceMethod ----- //\n\nutils.debounceMethod = function( _class, methodName, threshold ) {\n // original method\n var method = _class.prototype[ methodName ];\n var timeoutName = methodName + 'Timeout';\n\n _class.prototype[ methodName ] = function() {\n var timeout = this[ timeoutName ];\n if ( timeout ) {\n clearTimeout( timeout );\n }\n var args = arguments;\n\n var _this = this;\n this[ timeoutName ] = setTimeout( function() {\n method.apply( _this, args );\n delete _this[ timeoutName ];\n }, threshold || 100 );\n };\n};\n\n// ----- htmlInit ----- //\n\n// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/\nutils.toDashed = function( str ) {\n return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {\n return $1 + '-' + $2;\n }).toLowerCase();\n};\n\nvar console = window.console;\n/**\n * allow user to initialize classes via .js-namespace class\n * htmlInit( Widget, 'widgetName' )\n * options are parsed from data-namespace-option attribute\n */\nutils.htmlInit = function( WidgetClass, namespace ) {\n docReady( function() {\n var dashedNamespace = utils.toDashed( namespace );\n var elems = document.querySelectorAll( '.js-' + dashedNamespace );\n var dataAttr = 'data-' + dashedNamespace + '-options';\n\n for ( var i=0, len = elems.length; i < len; i++ ) {\n var elem = elems[i];\n var attr = elem.getAttribute( dataAttr );\n var options;\n try {\n options = attr && JSON.parse( attr );\n } catch ( error ) {\n // log error, do not initialize\n if ( console ) {\n console.error( 'Error parsing ' + dataAttr + ' on ' +\n elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' +\n error );\n }\n continue;\n }\n // initialize\n var instance = new WidgetClass( elem, options );\n // make available via $().data('layoutname')\n var jQuery = window.jQuery;\n if ( jQuery ) {\n jQuery.data( elem, namespace, instance );\n }\n }\n });\n};\n\n// ----- ----- //\n\nreturn utils;\n\n}));\n\n/**\n * Outlayer Item\n */\n\n( function( window, factory ) {\n \n // universal module definition\n if ( typeof define === 'function' && define.amd ) {\n // AMD\n define( 'outlayer/item',[\n 'eventEmitter/EventEmitter',\n 'get-size/get-size',\n 'get-style-property/get-style-property',\n 'fizzy-ui-utils/utils'\n ],\n function( EventEmitter, getSize, getStyleProperty, utils ) {\n return factory( window, EventEmitter, getSize, getStyleProperty, utils );\n }\n );\n } else if (typeof exports === 'object') {\n // CommonJS\n module.exports = factory(\n window,\n require('wolfy87-eventemitter'),\n require('get-size'),\n require('desandro-get-style-property'),\n require('fizzy-ui-utils')\n );\n } else {\n // browser global\n window.Outlayer = {};\n window.Outlayer.Item = factory(\n window,\n window.EventEmitter,\n window.getSize,\n window.getStyleProperty,\n window.fizzyUIUtils\n );\n }\n\n}( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) {\n\n\n// ----- helpers ----- //\n\nvar getComputedStyle = window.getComputedStyle;\nvar getStyle = getComputedStyle ?\n function( elem ) {\n return getComputedStyle( elem, null );\n } :\n function( elem ) {\n return elem.currentStyle;\n };\n\n\nfunction isEmptyObj( obj ) {\n for ( var prop in obj ) {\n return false;\n }\n prop = null;\n return true;\n}\n\n// -------------------------- CSS3 support -------------------------- //\n\nvar transitionProperty = getStyleProperty('transition');\nvar transformProperty = getStyleProperty('transform');\nvar supportsCSS3 = transitionProperty && transformProperty;\nvar is3d = !!getStyleProperty('perspective');\n\nvar transitionEndEvent = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'otransitionend',\n transition: 'transitionend'\n}[ transitionProperty ];\n\n// properties that could have vendor prefix\nvar prefixableProperties = [\n 'transform',\n 'transition',\n 'transitionDuration',\n 'transitionProperty'\n];\n\n// cache all vendor properties\nvar vendorProperties = ( function() {\n var cache = {};\n for ( var i=0, len = prefixableProperties.length; i < len; i++ ) {\n var prop = prefixableProperties[i];\n var supportedProp = getStyleProperty( prop );\n if ( supportedProp && supportedProp !== prop ) {\n cache[ prop ] = supportedProp;\n }\n }\n return cache;\n})();\n\n// -------------------------- Item -------------------------- //\n\nfunction Item( element, layout ) {\n if ( !element ) {\n return;\n }\n\n this.element = element;\n // parent layout class, i.e. Masonry, Isotope, or Packery\n this.layout = layout;\n this.position = {\n x: 0,\n y: 0\n };\n\n this._create();\n}\n\n// inherit EventEmitter\nutils.extend( Item.prototype, EventEmitter.prototype );\n\nItem.prototype._create = function() {\n // transition objects\n this._transn = {\n ingProperties: {},\n clean: {},\n onEnd: {}\n };\n\n this.css({\n position: 'absolute'\n });\n};\n\n// trigger specified handler for event type\nItem.prototype.handleEvent = function( event ) {\n var method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\nItem.prototype.getSize = function() {\n this.size = getSize( this.element );\n};\n\n/**\n * apply CSS styles to element\n * @param {Object} style\n */\nItem.prototype.css = function( style ) {\n var elemStyle = this.element.style;\n\n for ( var prop in style ) {\n // use vendor property if available\n var supportedProp = vendorProperties[ prop ] || prop;\n elemStyle[ supportedProp ] = style[ prop ];\n }\n};\n\n // measure position, and sets it\nItem.prototype.getPosition = function() {\n var style = getStyle( this.element );\n var layoutOptions = this.layout.options;\n var isOriginLeft = layoutOptions.isOriginLeft;\n var isOriginTop = layoutOptions.isOriginTop;\n var xValue = style[ isOriginLeft ? 'left' : 'right' ];\n var yValue = style[ isOriginTop ? 'top' : 'bottom' ];\n // convert percent to pixels\n var layoutSize = this.layout.size;\n var x = xValue.indexOf('%') != -1 ?\n ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 );\n var y = yValue.indexOf('%') != -1 ?\n ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 );\n\n // clean up 'auto' or other non-integer values\n x = isNaN( x ) ? 0 : x;\n y = isNaN( y ) ? 0 : y;\n // remove padding from measurement\n x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;\n y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;\n\n this.position.x = x;\n this.position.y = y;\n};\n\n// set settled position, apply padding\nItem.prototype.layoutPosition = function() {\n var layoutSize = this.layout.size;\n var layoutOptions = this.layout.options;\n var style = {};\n\n // x\n var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight';\n var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right';\n var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left';\n\n var x = this.position.x + layoutSize[ xPadding ];\n // set in percentage or pixels\n style[ xProperty ] = this.getXValue( x );\n // reset other property\n style[ xResetProperty ] = '';\n\n // y\n var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom';\n var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom';\n var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top';\n\n var y = this.position.y + layoutSize[ yPadding ];\n // set in percentage or pixels\n style[ yProperty ] = this.getYValue( y );\n // reset other property\n style[ yResetProperty ] = '';\n\n this.css( style );\n this.emitEvent( 'layout', [ this ] );\n};\n\nItem.prototype.getXValue = function( x ) {\n var layoutOptions = this.layout.options;\n return layoutOptions.percentPosition && !layoutOptions.isHorizontal ?\n ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';\n};\n\nItem.prototype.getYValue = function( y ) {\n var layoutOptions = this.layout.options;\n return layoutOptions.percentPosition && layoutOptions.isHorizontal ?\n ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';\n};\n\n\nItem.prototype._transitionTo = function( x, y ) {\n this.getPosition();\n // get current x & y from top/left\n var curX = this.position.x;\n var curY = this.position.y;\n\n var compareX = parseInt( x, 10 );\n var compareY = parseInt( y, 10 );\n var didNotMove = compareX === this.position.x && compareY === this.position.y;\n\n // save end position\n this.setPosition( x, y );\n\n // if did not move and not transitioning, just go to layout\n if ( didNotMove && !this.isTransitioning ) {\n this.layoutPosition();\n return;\n }\n\n var transX = x - curX;\n var transY = y - curY;\n var transitionStyle = {};\n transitionStyle.transform = this.getTranslate( transX, transY );\n\n this.transition({\n to: transitionStyle,\n onTransitionEnd: {\n transform: this.layoutPosition\n },\n isCleaning: true\n });\n};\n\nItem.prototype.getTranslate = function( x, y ) {\n // flip cooridinates if origin on right or bottom\n var layoutOptions = this.layout.options;\n x = layoutOptions.isOriginLeft ? x : -x;\n y = layoutOptions.isOriginTop ? y : -y;\n\n if ( is3d ) {\n return 'translate3d(' + x + 'px, ' + y + 'px, 0)';\n }\n\n return 'translate(' + x + 'px, ' + y + 'px)';\n};\n\n// non transition + transform support\nItem.prototype.goTo = function( x, y ) {\n this.setPosition( x, y );\n this.layoutPosition();\n};\n\n// use transition and transforms if supported\nItem.prototype.moveTo = supportsCSS3 ?\n Item.prototype._transitionTo : Item.prototype.goTo;\n\nItem.prototype.setPosition = function( x, y ) {\n this.position.x = parseInt( x, 10 );\n this.position.y = parseInt( y, 10 );\n};\n\n// ----- transition ----- //\n\n/**\n * @param {Object} style - CSS\n * @param {Function} onTransitionEnd\n */\n\n// non transition, just trigger callback\nItem.prototype._nonTransition = function( args ) {\n this.css( args.to );\n if ( args.isCleaning ) {\n this._removeStyles( args.to );\n }\n for ( var prop in args.onTransitionEnd ) {\n args.onTransitionEnd[ prop ].call( this );\n }\n};\n\n/**\n * proper transition\n * @param {Object} args - arguments\n * @param {Object} to - style to transition to\n * @param {Object} from - style to start transition from\n * @param {Boolean} isCleaning - removes transition styles after transition\n * @param {Function} onTransitionEnd - callback\n */\nItem.prototype._transition = function( args ) {\n // redirect to nonTransition if no transition duration\n if ( !parseFloat( this.layout.options.transitionDuration ) ) {\n this._nonTransition( args );\n return;\n }\n\n var _transition = this._transn;\n // keep track of onTransitionEnd callback by css property\n for ( var prop in args.onTransitionEnd ) {\n _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];\n }\n // keep track of properties that are transitioning\n for ( prop in args.to ) {\n _transition.ingProperties[ prop ] = true;\n // keep track of properties to clean up when transition is done\n if ( args.isCleaning ) {\n _transition.clean[ prop ] = true;\n }\n }\n\n // set from styles\n if ( args.from ) {\n this.css( args.from );\n // force redraw. http://blog.alexmaccaw.com/css-transitions\n var h = this.element.offsetHeight;\n // hack for JSHint to hush about unused var\n h = null;\n }\n // enable transition\n this.enableTransition( args.to );\n // set styles that are transitioning\n this.css( args.to );\n\n this.isTransitioning = true;\n\n};\n\n// dash before all cap letters, including first for\n// WebkitTransform => -webkit-transform\nfunction toDashedAll( str ) {\n return str.replace( /([A-Z])/g, function( $1 ) {\n return '-' + $1.toLowerCase();\n });\n}\n\nvar transitionProps = 'opacity,' +\n toDashedAll( vendorProperties.transform || 'transform' );\n\nItem.prototype.enableTransition = function(/* style */) {\n // HACK changing transitionProperty during a transition\n // will cause transition to jump\n if ( this.isTransitioning ) {\n return;\n }\n\n // make `transition: foo, bar, baz` from style object\n // HACK un-comment this when enableTransition can work\n // while a transition is happening\n // var transitionValues = [];\n // for ( var prop in style ) {\n // // dash-ify camelCased properties like WebkitTransition\n // prop = vendorProperties[ prop ] || prop;\n // transitionValues.push( toDashedAll( prop ) );\n // }\n // enable transition styles\n this.css({\n transitionProperty: transitionProps,\n transitionDuration: this.layout.options.transitionDuration\n });\n // listen for transition end event\n this.element.addEventListener( transitionEndEvent, this, false );\n};\n\nItem.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ];\n\n// ----- events ----- //\n\nItem.prototype.onwebkitTransitionEnd = function( event ) {\n this.ontransitionend( event );\n};\n\nItem.prototype.onotransitionend = function( event ) {\n this.ontransitionend( event );\n};\n\n// properties that I munge to make my life easier\nvar dashedVendorProperties = {\n '-webkit-transform': 'transform',\n '-moz-transform': 'transform',\n '-o-transform': 'transform'\n};\n\nItem.prototype.ontransitionend = function( event ) {\n // disregard bubbled events from children\n if ( event.target !== this.element ) {\n return;\n }\n var _transition = this._transn;\n // get property name of transitioned property, convert to prefix-free\n var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;\n\n // remove property that has completed transitioning\n delete _transition.ingProperties[ propertyName ];\n // check if any properties are still transitioning\n if ( isEmptyObj( _transition.ingProperties ) ) {\n // all properties have completed transitioning\n this.disableTransition();\n }\n // clean style\n if ( propertyName in _transition.clean ) {\n // clean up style\n this.element.style[ event.propertyName ] = '';\n delete _transition.clean[ propertyName ];\n }\n // trigger onTransitionEnd callback\n if ( propertyName in _transition.onEnd ) {\n var onTransitionEnd = _transition.onEnd[ propertyName ];\n onTransitionEnd.call( this );\n delete _transition.onEnd[ propertyName ];\n }\n\n this.emitEvent( 'transitionEnd', [ this ] );\n};\n\nItem.prototype.disableTransition = function() {\n this.removeTransitionStyles();\n this.element.removeEventListener( transitionEndEvent, this, false );\n this.isTransitioning = false;\n};\n\n/**\n * removes style property from element\n * @param {Object} style\n**/\nItem.prototype._removeStyles = function( style ) {\n // clean up transition styles\n var cleanStyle = {};\n for ( var prop in style ) {\n cleanStyle[ prop ] = '';\n }\n this.css( cleanStyle );\n};\n\nvar cleanTransitionStyle = {\n transitionProperty: '',\n transitionDuration: ''\n};\n\nItem.prototype.removeTransitionStyles = function() {\n // remove transition\n this.css( cleanTransitionStyle );\n};\n\n// ----- show/hide/remove ----- //\n\n// remove element from DOM\nItem.prototype.removeElem = function() {\n this.element.parentNode.removeChild( this.element );\n // remove display: none\n this.css({ display: '' });\n this.emitEvent( 'remove', [ this ] );\n};\n\nItem.prototype.remove = function() {\n // just remove element if no transition support or no transition\n if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {\n this.removeElem();\n return;\n }\n\n // start transition\n var _this = this;\n this.once( 'transitionEnd', function() {\n _this.removeElem();\n });\n this.hide();\n};\n\nItem.prototype.reveal = function() {\n delete this.isHidden;\n // remove display: none\n this.css({ display: '' });\n\n var options = this.layout.options;\n\n var onTransitionEnd = {};\n var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');\n onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;\n\n this.transition({\n from: options.hiddenStyle,\n to: options.visibleStyle,\n isCleaning: true,\n onTransitionEnd: onTransitionEnd\n });\n};\n\nItem.prototype.onRevealTransitionEnd = function() {\n // check if still visible\n // during transition, item may have been hidden\n if ( !this.isHidden ) {\n this.emitEvent('reveal');\n }\n};\n\n/**\n * get style property use for hide/reveal transition end\n * @param {String} styleProperty - hiddenStyle/visibleStyle\n * @returns {String}\n */\nItem.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) {\n var optionStyle = this.layout.options[ styleProperty ];\n // use opacity\n if ( optionStyle.opacity ) {\n return 'opacity';\n }\n // get first property\n for ( var prop in optionStyle ) {\n return prop;\n }\n};\n\nItem.prototype.hide = function() {\n // set flag\n this.isHidden = true;\n // remove display: none\n this.css({ display: '' });\n\n var options = this.layout.options;\n\n var onTransitionEnd = {};\n var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');\n onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;\n\n this.transition({\n from: options.visibleStyle,\n to: options.hiddenStyle,\n // keep hidden stuff hidden\n isCleaning: true,\n onTransitionEnd: onTransitionEnd\n });\n};\n\nItem.prototype.onHideTransitionEnd = function() {\n // check if still hidden\n // during transition, item may have been un-hidden\n if ( this.isHidden ) {\n this.css({ display: 'none' });\n this.emitEvent('hide');\n }\n};\n\nItem.prototype.destroy = function() {\n this.css({\n position: '',\n left: '',\n right: '',\n top: '',\n bottom: '',\n transition: '',\n transform: ''\n });\n};\n\nreturn Item;\n\n}));\n\n/*!\n * Outlayer v1.4.2\n * the brains and guts of a layout library\n * MIT license\n */\n\n( function( window, factory ) {\n \n // universal module definition\n\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'outlayer/outlayer',[\n 'eventie/eventie',\n 'eventEmitter/EventEmitter',\n 'get-size/get-size',\n 'fizzy-ui-utils/utils',\n './item'\n ],\n function( eventie, EventEmitter, getSize, utils, Item ) {\n return factory( window, eventie, EventEmitter, getSize, utils, Item);\n }\n );\n } else if ( typeof exports == 'object' ) {\n // CommonJS\n module.exports = factory(\n window,\n require('eventie'),\n require('wolfy87-eventemitter'),\n require('get-size'),\n require('fizzy-ui-utils'),\n require('./item')\n );\n } else {\n // browser global\n window.Outlayer = factory(\n window,\n window.eventie,\n window.EventEmitter,\n window.getSize,\n window.fizzyUIUtils,\n window.Outlayer.Item\n );\n }\n\n}( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) {\n\n\n// ----- vars ----- //\n\nvar console = window.console;\nvar jQuery = window.jQuery;\nvar noop = function() {};\n\n// -------------------------- Outlayer -------------------------- //\n\n// globally unique identifiers\nvar GUID = 0;\n// internal store of all Outlayer intances\nvar instances = {};\n\n\n/**\n * @param {Element, String} element\n * @param {Object} options\n * @constructor\n */\nfunction Outlayer( element, options ) {\n var queryElement = utils.getQueryElement( element );\n if ( !queryElement ) {\n if ( console ) {\n console.error( 'Bad element for ' + this.constructor.namespace +\n ': ' + ( queryElement || element ) );\n }\n return;\n }\n this.element = queryElement;\n // add jQuery\n if ( jQuery ) {\n this.$element = jQuery( this.element );\n }\n\n // options\n this.options = utils.extend( {}, this.constructor.defaults );\n this.option( options );\n\n // add id for Outlayer.getFromElement\n var id = ++GUID;\n this.element.outlayerGUID = id; // expando\n instances[ id ] = this; // associate via id\n\n // kick it off\n this._create();\n\n if ( this.options.isInitLayout ) {\n this.layout();\n }\n}\n\n// settings are for internal use only\nOutlayer.namespace = 'outlayer';\nOutlayer.Item = Item;\n\n// default options\nOutlayer.defaults = {\n containerStyle: {\n position: 'relative'\n },\n isInitLayout: true,\n isOriginLeft: true,\n isOriginTop: true,\n isResizeBound: true,\n isResizingContainer: true,\n // item options\n transitionDuration: '0.4s',\n hiddenStyle: {\n opacity: 0,\n transform: 'scale(0.001)'\n },\n visibleStyle: {\n opacity: 1,\n transform: 'scale(1)'\n }\n};\n\n// inherit EventEmitter\nutils.extend( Outlayer.prototype, EventEmitter.prototype );\n\n/**\n * set options\n * @param {Object} opts\n */\nOutlayer.prototype.option = function( opts ) {\n utils.extend( this.options, opts );\n};\n\nOutlayer.prototype._create = function() {\n // get items from children\n this.reloadItems();\n // elements that affect layout, but are not laid out\n this.stamps = [];\n this.stamp( this.options.stamp );\n // set container style\n utils.extend( this.element.style, this.options.containerStyle );\n\n // bind resize method\n if ( this.options.isResizeBound ) {\n this.bindResize();\n }\n};\n\n// goes through all children again and gets bricks in proper order\nOutlayer.prototype.reloadItems = function() {\n // collection of item elements\n this.items = this._itemize( this.element.children );\n};\n\n\n/**\n * turn elements into Outlayer.Items to be used in layout\n * @param {Array or NodeList or HTMLElement} elems\n * @returns {Array} items - collection of new Outlayer Items\n */\nOutlayer.prototype._itemize = function( elems ) {\n\n var itemElems = this._filterFindItemElements( elems );\n var Item = this.constructor.Item;\n\n // create new Outlayer Items for collection\n var items = [];\n for ( var i=0, len = itemElems.length; i < len; i++ ) {\n var elem = itemElems[i];\n var item = new Item( elem, this );\n items.push( item );\n }\n\n return items;\n};\n\n/**\n * get item elements to be used in layout\n * @param {Array or NodeList or HTMLElement} elems\n * @returns {Array} items - item elements\n */\nOutlayer.prototype._filterFindItemElements = function( elems ) {\n return utils.filterFindElements( elems, this.options.itemSelector );\n};\n\n/**\n * getter method for getting item elements\n * @returns {Array} elems - collection of item elements\n */\nOutlayer.prototype.getItemElements = function() {\n var elems = [];\n for ( var i=0, len = this.items.length; i < len; i++ ) {\n elems.push( this.items[i].element );\n }\n return elems;\n};\n\n// ----- init & layout ----- //\n\n/**\n * lays out all items\n */\nOutlayer.prototype.layout = function() {\n this._resetLayout();\n this._manageStamps();\n\n // don't animate first layout\n var isInstant = this.options.isLayoutInstant !== undefined ?\n this.options.isLayoutInstant : !this._isLayoutInited;\n this.layoutItems( this.items, isInstant );\n\n // flag for initalized\n this._isLayoutInited = true;\n};\n\n// _init is alias for layout\nOutlayer.prototype._init = Outlayer.prototype.layout;\n\n/**\n * logic before any new layout\n */\nOutlayer.prototype._resetLayout = function() {\n this.getSize();\n};\n\n\nOutlayer.prototype.getSize = function() {\n this.size = getSize( this.element );\n};\n\n/**\n * get measurement from option, for columnWidth, rowHeight, gutter\n * if option is String -> get element from selector string, & get size of element\n * if option is Element -> get size of element\n * else use option as a number\n *\n * @param {String} measurement\n * @param {String} size - width or height\n * @private\n */\nOutlayer.prototype._getMeasurement = function( measurement, size ) {\n var option = this.options[ measurement ];\n var elem;\n if ( !option ) {\n // default to 0\n this[ measurement ] = 0;\n } else {\n // use option as an element\n if ( typeof option === 'string' ) {\n elem = this.element.querySelector( option );\n } else if ( utils.isElement( option ) ) {\n elem = option;\n }\n // use size of element, if element\n this[ measurement ] = elem ? getSize( elem )[ size ] : option;\n }\n};\n\n/**\n * layout a collection of item elements\n * @api public\n */\nOutlayer.prototype.layoutItems = function( items, isInstant ) {\n items = this._getItemsForLayout( items );\n\n this._layoutItems( items, isInstant );\n\n this._postLayout();\n};\n\n/**\n * get the items to be laid out\n * you may want to skip over some items\n * @param {Array} items\n * @returns {Array} items\n */\nOutlayer.prototype._getItemsForLayout = function( items ) {\n var layoutItems = [];\n for ( var i=0, len = items.length; i < len; i++ ) {\n var item = items[i];\n if ( !item.isIgnored ) {\n layoutItems.push( item );\n }\n }\n return layoutItems;\n};\n\n/**\n * layout items\n * @param {Array} items\n * @param {Boolean} isInstant\n */\nOutlayer.prototype._layoutItems = function( items, isInstant ) {\n this._emitCompleteOnItems( 'layout', items );\n\n if ( !items || !items.length ) {\n // no items, emit event with empty array\n return;\n }\n\n var queue = [];\n\n for ( var i=0, len = items.length; i < len; i++ ) {\n var item = items[i];\n // get x/y object from method\n var position = this._getItemLayoutPosition( item );\n // enqueue\n position.item = item;\n position.isInstant = isInstant || item.isLayoutInstant;\n queue.push( position );\n }\n\n this._processLayoutQueue( queue );\n};\n\n/**\n * get item layout position\n * @param {Outlayer.Item} item\n * @returns {Object} x and y position\n */\nOutlayer.prototype._getItemLayoutPosition = function( /* item */ ) {\n return {\n x: 0,\n y: 0\n };\n};\n\n/**\n * iterate over array and position each item\n * Reason being - separating this logic prevents 'layout invalidation'\n * thx @paul_irish\n * @param {Array} queue\n */\nOutlayer.prototype._processLayoutQueue = function( queue ) {\n for ( var i=0, len = queue.length; i < len; i++ ) {\n var obj = queue[i];\n this._positionItem( obj.item, obj.x, obj.y, obj.isInstant );\n }\n};\n\n/**\n * Sets position of item in DOM\n * @param {Outlayer.Item} item\n * @param {Number} x - horizontal position\n * @param {Number} y - vertical position\n * @param {Boolean} isInstant - disables transitions\n */\nOutlayer.prototype._positionItem = function( item, x, y, isInstant ) {\n if ( isInstant ) {\n // if not transition, just set CSS\n item.goTo( x, y );\n } else {\n item.moveTo( x, y );\n }\n};\n\n/**\n * Any logic you want to do after each layout,\n * i.e. size the container\n */\nOutlayer.prototype._postLayout = function() {\n this.resizeContainer();\n};\n\nOutlayer.prototype.resizeContainer = function() {\n if ( !this.options.isResizingContainer ) {\n return;\n }\n var size = this._getContainerSize();\n if ( size ) {\n this._setContainerMeasure( size.width, true );\n this._setContainerMeasure( size.height, false );\n }\n};\n\n/**\n * Sets width or height of container if returned\n * @returns {Object} size\n * @param {Number} width\n * @param {Number} height\n */\nOutlayer.prototype._getContainerSize = noop;\n\n/**\n * @param {Number} measure - size of width or height\n * @param {Boolean} isWidth\n */\nOutlayer.prototype._setContainerMeasure = function( measure, isWidth ) {\n if ( measure === undefined ) {\n return;\n }\n\n var elemSize = this.size;\n // add padding and border width if border box\n if ( elemSize.isBorderBox ) {\n measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +\n elemSize.borderLeftWidth + elemSize.borderRightWidth :\n elemSize.paddingBottom + elemSize.paddingTop +\n elemSize.borderTopWidth + elemSize.borderBottomWidth;\n }\n\n measure = Math.max( measure, 0 );\n this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';\n};\n\n/**\n * emit eventComplete on a collection of items events\n * @param {String} eventName\n * @param {Array} items - Outlayer.Items\n */\nOutlayer.prototype._emitCompleteOnItems = function( eventName, items ) {\n var _this = this;\n function onComplete() {\n _this.dispatchEvent( eventName + 'Complete', null, [ items ] );\n }\n\n var count = items.length;\n if ( !items || !count ) {\n onComplete();\n return;\n }\n\n var doneCount = 0;\n function tick() {\n doneCount++;\n if ( doneCount === count ) {\n onComplete();\n }\n }\n\n // bind callback\n for ( var i=0, len = items.length; i < len; i++ ) {\n var item = items[i];\n item.once( eventName, tick );\n }\n};\n\n/**\n * emits events via eventEmitter and jQuery events\n * @param {String} type - name of event\n * @param {Event} event - original event\n * @param {Array} args - extra arguments\n */\nOutlayer.prototype.dispatchEvent = function( type, event, args ) {\n // add original event to arguments\n var emitArgs = event ? [ event ].concat( args ) : args;\n this.emitEvent( type, emitArgs );\n\n if ( jQuery ) {\n // set this.$element\n this.$element = this.$element || jQuery( this.element );\n if ( event ) {\n // create jQuery event\n var $event = jQuery.Event( event );\n $event.type = type;\n this.$element.trigger( $event, args );\n } else {\n // just trigger with type if no event available\n this.$element.trigger( type, args );\n }\n }\n};\n\n// -------------------------- ignore & stamps -------------------------- //\n\n\n/**\n * keep item in collection, but do not lay it out\n * ignored items do not get skipped in layout\n * @param {Element} elem\n */\nOutlayer.prototype.ignore = function( elem ) {\n var item = this.getItem( elem );\n if ( item ) {\n item.isIgnored = true;\n }\n};\n\n/**\n * return item to layout collection\n * @param {Element} elem\n */\nOutlayer.prototype.unignore = function( elem ) {\n var item = this.getItem( elem );\n if ( item ) {\n delete item.isIgnored;\n }\n};\n\n/**\n * adds elements to stamps\n * @param {NodeList, Array, Element, or String} elems\n */\nOutlayer.prototype.stamp = function( elems ) {\n elems = this._find( elems );\n if ( !elems ) {\n return;\n }\n\n this.stamps = this.stamps.concat( elems );\n // ignore\n for ( var i=0, len = elems.length; i < len; i++ ) {\n var elem = elems[i];\n this.ignore( elem );\n }\n};\n\n/**\n * removes elements to stamps\n * @param {NodeList, Array, or Element} elems\n */\nOutlayer.prototype.unstamp = function( elems ) {\n elems = this._find( elems );\n if ( !elems ){\n return;\n }\n\n for ( var i=0, len = elems.length; i < len; i++ ) {\n var elem = elems[i];\n // filter out removed stamp elements\n utils.removeFrom( this.stamps, elem );\n this.unignore( elem );\n }\n\n};\n\n/**\n * finds child elements\n * @param {NodeList, Array, Element, or String} elems\n * @returns {Array} elems\n */\nOutlayer.prototype._find = function( elems ) {\n if ( !elems ) {\n return;\n }\n // if string, use argument as selector string\n if ( typeof elems === 'string' ) {\n elems = this.element.querySelectorAll( elems );\n }\n elems = utils.makeArray( elems );\n return elems;\n};\n\nOutlayer.prototype._manageStamps = function() {\n if ( !this.stamps || !this.stamps.length ) {\n return;\n }\n\n this._getBoundingRect();\n\n for ( var i=0, len = this.stamps.length; i < len; i++ ) {\n var stamp = this.stamps[i];\n this._manageStamp( stamp );\n }\n};\n\n// update boundingLeft / Top\nOutlayer.prototype._getBoundingRect = function() {\n // get bounding rect for container element\n var boundingRect = this.element.getBoundingClientRect();\n var size = this.size;\n this._boundingRect = {\n left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,\n top: boundingRect.top + size.paddingTop + size.borderTopWidth,\n right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),\n bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )\n };\n};\n\n/**\n * @param {Element} stamp\n**/\nOutlayer.prototype._manageStamp = noop;\n\n/**\n * get x/y position of element relative to container element\n * @param {Element} elem\n * @returns {Object} offset - has left, top, right, bottom\n */\nOutlayer.prototype._getElementOffset = function( elem ) {\n var boundingRect = elem.getBoundingClientRect();\n var thisRect = this._boundingRect;\n var size = getSize( elem );\n var offset = {\n left: boundingRect.left - thisRect.left - size.marginLeft,\n top: boundingRect.top - thisRect.top - size.marginTop,\n right: thisRect.right - boundingRect.right - size.marginRight,\n bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom\n };\n return offset;\n};\n\n// -------------------------- resize -------------------------- //\n\n// enable event handlers for listeners\n// i.e. resize -> onresize\nOutlayer.prototype.handleEvent = function( event ) {\n var method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\n/**\n * Bind layout to window resizing\n */\nOutlayer.prototype.bindResize = function() {\n // bind just one listener\n if ( this.isResizeBound ) {\n return;\n }\n window.eventie.bind( window, 'resize', this );\n this.isResizeBound = true;\n};\n\n/**\n * Unbind layout to window resizing\n */\nOutlayer.prototype.unbindResize = function() {\n if ( this.isResizeBound ) {\n window.eventie.unbind( window, 'resize', this );\n }\n this.isResizeBound = false;\n};\n\n// original debounce by John Hann\n// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/\n\n// this fires every resize\nOutlayer.prototype.onresize = function() {\n if ( this.resizeTimeout ) {\n clearTimeout( this.resizeTimeout );\n }\n\n var _this = this;\n function delayed() {\n _this.resize();\n delete _this.resizeTimeout;\n }\n\n this.resizeTimeout = setTimeout( delayed, 100 );\n};\n\n// debounced, layout on resize\nOutlayer.prototype.resize = function() {\n // don't trigger if size did not change\n // or if resize was unbound. See #9\n if ( !this.isResizeBound || !this.needsResizeLayout() ) {\n return;\n }\n\n this.layout();\n};\n\n/**\n * check if layout is needed post layout\n * @returns Boolean\n */\nOutlayer.prototype.needsResizeLayout = function() {\n var size = getSize( this.element );\n // check that this.size and size are there\n // IE8 triggers resize on body size change, so they might not be\n var hasSizes = this.size && size;\n return hasSizes && size.innerWidth !== this.size.innerWidth;\n};\n\n// -------------------------- methods -------------------------- //\n\n/**\n * add items to Outlayer instance\n * @param {Array or NodeList or Element} elems\n * @returns {Array} items - Outlayer.Items\n**/\nOutlayer.prototype.addItems = function( elems ) {\n var items = this._itemize( elems );\n // add items to collection\n if ( items.length ) {\n this.items = this.items.concat( items );\n }\n return items;\n};\n\n/**\n * Layout newly-appended item elements\n * @param {Array or NodeList or Element} elems\n */\nOutlayer.prototype.appended = function( elems ) {\n var items = this.addItems( elems );\n if ( !items.length ) {\n return;\n }\n // layout and reveal just the new items\n this.layoutItems( items, true );\n this.reveal( items );\n};\n\n/**\n * Layout prepended elements\n * @param {Array or NodeList or Element} elems\n */\nOutlayer.prototype.prepended = function( elems ) {\n var items = this._itemize( elems );\n if ( !items.length ) {\n return;\n }\n // add items to beginning of collection\n var previousItems = this.items.slice(0);\n this.items = items.concat( previousItems );\n // start new layout\n this._resetLayout();\n this._manageStamps();\n // layout new stuff without transition\n this.layoutItems( items, true );\n this.reveal( items );\n // layout previous items\n this.layoutItems( previousItems );\n};\n\n/**\n * reveal a collection of items\n * @param {Array of Outlayer.Items} items\n */\nOutlayer.prototype.reveal = function( items ) {\n this._emitCompleteOnItems( 'reveal', items );\n\n var len = items && items.length;\n for ( var i=0; len && i < len; i++ ) {\n var item = items[i];\n item.reveal();\n }\n};\n\n/**\n * hide a collection of items\n * @param {Array of Outlayer.Items} items\n */\nOutlayer.prototype.hide = function( items ) {\n this._emitCompleteOnItems( 'hide', items );\n\n var len = items && items.length;\n for ( var i=0; len && i < len; i++ ) {\n var item = items[i];\n item.hide();\n }\n};\n\n/**\n * reveal item elements\n * @param {Array}, {Element}, {NodeList} items\n */\nOutlayer.prototype.revealItemElements = function( elems ) {\n var items = this.getItems( elems );\n this.reveal( items );\n};\n\n/**\n * hide item elements\n * @param {Array}, {Element}, {NodeList} items\n */\nOutlayer.prototype.hideItemElements = function( elems ) {\n var items = this.getItems( elems );\n this.hide( items );\n};\n\n/**\n * get Outlayer.Item, given an Element\n * @param {Element} elem\n * @param {Function} callback\n * @returns {Outlayer.Item} item\n */\nOutlayer.prototype.getItem = function( elem ) {\n // loop through items to get the one that matches\n for ( var i=0, len = this.items.length; i < len; i++ ) {\n var item = this.items[i];\n if ( item.element === elem ) {\n // return item\n return item;\n }\n }\n};\n\n/**\n * get collection of Outlayer.Items, given Elements\n * @param {Array} elems\n * @returns {Array} items - Outlayer.Items\n */\nOutlayer.prototype.getItems = function( elems ) {\n elems = utils.makeArray( elems );\n var items = [];\n for ( var i=0, len = elems.length; i < len; i++ ) {\n var elem = elems[i];\n var item = this.getItem( elem );\n if ( item ) {\n items.push( item );\n }\n }\n\n return items;\n};\n\n/**\n * remove element(s) from instance and DOM\n * @param {Array or NodeList or Element} elems\n */\nOutlayer.prototype.remove = function( elems ) {\n var removeItems = this.getItems( elems );\n\n this._emitCompleteOnItems( 'remove', removeItems );\n\n // bail if no items to remove\n if ( !removeItems || !removeItems.length ) {\n return;\n }\n\n for ( var i=0, len = removeItems.length; i < len; i++ ) {\n var item = removeItems[i];\n item.remove();\n // remove item from collection\n utils.removeFrom( this.items, item );\n }\n};\n\n// ----- destroy ----- //\n\n// remove and disable Outlayer instance\nOutlayer.prototype.destroy = function() {\n // clean up dynamic styles\n var style = this.element.style;\n style.height = '';\n style.position = '';\n style.width = '';\n // destroy items\n for ( var i=0, len = this.items.length; i < len; i++ ) {\n var item = this.items[i];\n item.destroy();\n }\n\n this.unbindResize();\n\n var id = this.element.outlayerGUID;\n delete instances[ id ]; // remove reference to instance by id\n delete this.element.outlayerGUID;\n // remove data for jQuery\n if ( jQuery ) {\n jQuery.removeData( this.element, this.constructor.namespace );\n }\n\n};\n\n// -------------------------- data -------------------------- //\n\n/**\n * get Outlayer instance from element\n * @param {Element} elem\n * @returns {Outlayer}\n */\nOutlayer.data = function( elem ) {\n elem = utils.getQueryElement( elem );\n var id = elem && elem.outlayerGUID;\n return id && instances[ id ];\n};\n\n\n// -------------------------- create Outlayer class -------------------------- //\n\n/**\n * create a layout class\n * @param {String} namespace\n */\nOutlayer.create = function( namespace, options ) {\n // sub-class Outlayer\n function Layout() {\n Outlayer.apply( this, arguments );\n }\n // inherit Outlayer prototype, use Object.create if there\n if ( Object.create ) {\n Layout.prototype = Object.create( Outlayer.prototype );\n } else {\n utils.extend( Layout.prototype, Outlayer.prototype );\n }\n // set contructor, used for namespace and Item\n Layout.prototype.constructor = Layout;\n\n Layout.defaults = utils.extend( {}, Outlayer.defaults );\n // apply new options\n utils.extend( Layout.defaults, options );\n // keep prototype.settings for backwards compatibility (Packery v1.2.0)\n Layout.prototype.settings = {};\n\n Layout.namespace = namespace;\n\n Layout.data = Outlayer.data;\n\n // sub-class Item\n Layout.Item = function LayoutItem() {\n Item.apply( this, arguments );\n };\n\n Layout.Item.prototype = new Item();\n\n // -------------------------- declarative -------------------------- //\n\n utils.htmlInit( Layout, namespace );\n\n // -------------------------- jQuery bridge -------------------------- //\n\n // make into jQuery plugin\n if ( jQuery && jQuery.bridget ) {\n jQuery.bridget( namespace, Layout );\n }\n\n return Layout;\n};\n\n// ----- fin ----- //\n\n// back in global\nOutlayer.Item = Item;\n\nreturn Outlayer;\n\n}));\n\n\n/**\n * Rect\n * low-level utility class for basic geometry\n */\n\n( function( window, factory ) {\n \n // universal module definition\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'packery/js/rect',factory );\n } else if ( typeof exports == 'object' ) {\n // CommonJS\n module.exports = factory();\n } else {\n // browser global\n window.Packery = window.Packery || {};\n window.Packery.Rect = factory();\n }\n\n}( window, function factory() {\n\n\n// -------------------------- Packery -------------------------- //\n\n// global namespace\nvar Packery = window.Packery = function() {};\n\n// -------------------------- Rect -------------------------- //\n\nfunction Rect( props ) {\n // extend properties from defaults\n for ( var prop in Rect.defaults ) {\n this[ prop ] = Rect.defaults[ prop ];\n }\n\n for ( prop in props ) {\n this[ prop ] = props[ prop ];\n }\n\n}\n\n// make available\nPackery.Rect = Rect;\n\nRect.defaults = {\n x: 0,\n y: 0,\n width: 0,\n height: 0\n};\n\n/**\n * Determines whether or not this rectangle wholly encloses another rectangle or point.\n * @param {Rect} rect\n * @returns {Boolean}\n**/\nRect.prototype.contains = function( rect ) {\n // points don't have width or height\n var otherWidth = rect.width || 0;\n var otherHeight = rect.height || 0;\n return this.x <= rect.x &&\n this.y <= rect.y &&\n this.x + this.width >= rect.x + otherWidth &&\n this.y + this.height >= rect.y + otherHeight;\n};\n\n/**\n * Determines whether or not the rectangle intersects with another.\n * @param {Rect} rect\n * @returns {Boolean}\n**/\nRect.prototype.overlaps = function( rect ) {\n var thisRight = this.x + this.width;\n var thisBottom = this.y + this.height;\n var rectRight = rect.x + rect.width;\n var rectBottom = rect.y + rect.height;\n\n // http://stackoverflow.com/a/306332\n return this.x < rectRight &&\n thisRight > rect.x &&\n this.y < rectBottom &&\n thisBottom > rect.y;\n};\n\n/**\n * @param {Rect} rect - the overlapping rect\n * @returns {Array} freeRects - rects representing the area around the rect\n**/\nRect.prototype.getMaximalFreeRects = function( rect ) {\n\n // if no intersection, return false\n if ( !this.overlaps( rect ) ) {\n return false;\n }\n\n var freeRects = [];\n var freeRect;\n\n var thisRight = this.x + this.width;\n var thisBottom = this.y + this.height;\n var rectRight = rect.x + rect.width;\n var rectBottom = rect.y + rect.height;\n\n // top\n if ( this.y < rect.y ) {\n freeRect = new Rect({\n x: this.x,\n y: this.y,\n width: this.width,\n height: rect.y - this.y\n });\n freeRects.push( freeRect );\n }\n\n // right\n if ( thisRight > rectRight ) {\n freeRect = new Rect({\n x: rectRight,\n y: this.y,\n width: thisRight - rectRight,\n height: this.height\n });\n freeRects.push( freeRect );\n }\n\n // bottom\n if ( thisBottom > rectBottom ) {\n freeRect = new Rect({\n x: this.x,\n y: rectBottom,\n width: this.width,\n height: thisBottom - rectBottom\n });\n freeRects.push( freeRect );\n }\n\n // left\n if ( this.x < rect.x ) {\n freeRect = new Rect({\n x: this.x,\n y: this.y,\n width: rect.x - this.x,\n height: this.height\n });\n freeRects.push( freeRect );\n }\n\n return freeRects;\n};\n\nRect.prototype.canFit = function( rect ) {\n return this.width >= rect.width && this.height >= rect.height;\n};\n\nreturn Rect;\n\n}));\n\n/**\n * Packer\n * bin-packing algorithm\n */\n\n( function( window, factory ) {\n \n // universal module definition\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'packery/js/packer',[ './rect' ], factory );\n } else if ( typeof exports == 'object' ) {\n // CommonJS\n module.exports = factory(\n require('./rect')\n );\n } else {\n // browser global\n var Packery = window.Packery = window.Packery || {};\n Packery.Packer = factory( Packery.Rect );\n }\n\n}( window, function factory( Rect ) {\n\n\n// -------------------------- Packer -------------------------- //\n\n/**\n * @param {Number} width\n * @param {Number} height\n * @param {String} sortDirection\n * topLeft for vertical, leftTop for horizontal\n */\nfunction Packer( width, height, sortDirection ) {\n this.width = width || 0;\n this.height = height || 0;\n this.sortDirection = sortDirection || 'downwardLeftToRight';\n\n this.reset();\n}\n\nPacker.prototype.reset = function() {\n this.spaces = [];\n this.newSpaces = [];\n\n var initialSpace = new Rect({\n x: 0,\n y: 0,\n width: this.width,\n height: this.height\n });\n\n this.spaces.push( initialSpace );\n // set sorter\n this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight;\n};\n\n// change x and y of rect to fit with in Packer's available spaces\nPacker.prototype.pack = function( rect ) {\n for ( var i=0, len = this.spaces.length; i < len; i++ ) {\n var space = this.spaces[i];\n if ( space.canFit( rect ) ) {\n this.placeInSpace( rect, space );\n break;\n }\n }\n};\n\nPacker.prototype.placeInSpace = function( rect, space ) {\n // place rect in space\n rect.x = space.x;\n rect.y = space.y;\n\n this.placed( rect );\n};\n\n// update spaces with placed rect\nPacker.prototype.placed = function( rect ) {\n // update spaces\n var revisedSpaces = [];\n for ( var i=0, len = this.spaces.length; i < len; i++ ) {\n var space = this.spaces[i];\n var newSpaces = space.getMaximalFreeRects( rect );\n // add either the original space or the new spaces to the revised spaces\n if ( newSpaces ) {\n revisedSpaces.push.apply( revisedSpaces, newSpaces );\n } else {\n revisedSpaces.push( space );\n }\n }\n\n this.spaces = revisedSpaces;\n\n this.mergeSortSpaces();\n};\n\nPacker.prototype.mergeSortSpaces = function() {\n // remove redundant spaces\n Packer.mergeRects( this.spaces );\n this.spaces.sort( this.sorter );\n};\n\n// add a space back\nPacker.prototype.addSpace = function( rect ) {\n this.spaces.push( rect );\n this.mergeSortSpaces();\n};\n\n// -------------------------- utility functions -------------------------- //\n\n/**\n * Remove redundant rectangle from array of rectangles\n * @param {Array} rects: an array of Rects\n * @returns {Array} rects: an array of Rects\n**/\nPacker.mergeRects = function( rects ) {\n for ( var i=0, len = rects.length; i < len; i++ ) {\n var rect = rects[i];\n // skip over this rect if it was already removed\n if ( !rect ) {\n continue;\n }\n // clone rects we're testing, remove this rect\n var compareRects = rects.slice(0);\n // do not compare with self\n compareRects.splice( i, 1 );\n // compare this rect with others\n var removedCount = 0;\n for ( var j=0, jLen = compareRects.length; j < jLen; j++ ) {\n var compareRect = compareRects[j];\n // if this rect contains another,\n // remove that rect from test collection\n var indexAdjust = i > j ? 0 : 1;\n if ( rect.contains( compareRect ) ) {\n // console.log( 'current test rects:' + testRects.length, testRects );\n // console.log( i, j, indexAdjust, rect, compareRect );\n rects.splice( j + indexAdjust - removedCount, 1 );\n removedCount++;\n }\n }\n }\n\n return rects;\n};\n\n\n// -------------------------- sorters -------------------------- //\n\n// functions for sorting rects in order\nvar sorters = {\n // top down, then left to right\n downwardLeftToRight: function( a, b ) {\n return a.y - b.y || a.x - b.x;\n },\n // left to right, then top down\n rightwardTopToBottom: function( a, b ) {\n return a.x - b.x || a.y - b.y;\n }\n};\n\n\n// -------------------------- -------------------------- //\n\nreturn Packer;\n\n}));\n/**\n * Packery Item Element\n**/\n\n( function( window, factory ) {\n \n // universal module definition\n\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( 'packery/js/item',[\n 'get-style-property/get-style-property',\n 'outlayer/outlayer',\n './rect'\n ],\n factory );\n } else if ( typeof exports == 'object' ) {\n // CommonJS\n module.exports = factory(\n require('desandro-get-style-property'),\n require('outlayer'),\n require('./rect')\n );\n } else {\n // browser global\n window.Packery.Item = factory(\n window.getStyleProperty,\n window.Outlayer,\n window.Packery.Rect\n );\n }\n\n}( window, function factory( getStyleProperty, Outlayer, Rect ) {\n\n\n// -------------------------- Item -------------------------- //\n\nvar transformProperty = getStyleProperty('transform');\n\n// sub-class Item\nvar Item = function PackeryItem() {\n Outlayer.Item.apply( this, arguments );\n};\n\nItem.prototype = new Outlayer.Item();\n\nvar protoCreate = Item.prototype._create;\nItem.prototype._create = function() {\n // call default _create logic\n protoCreate.call( this );\n this.rect = new Rect();\n // rect used for placing, in drag or Packery.fit()\n this.placeRect = new Rect();\n};\n\n// -------------------------- drag -------------------------- //\n\nItem.prototype.dragStart = function() {\n this.getPosition();\n this.removeTransitionStyles();\n // remove transform property from transition\n if ( this.isTransitioning && transformProperty ) {\n this.element.style[ transformProperty ] = 'none';\n }\n this.getSize();\n // create place rect, used for position when dragged then dropped\n // or when positioning\n this.isPlacing = true;\n this.needsPositioning = false;\n this.positionPlaceRect( this.position.x, this.position.y );\n this.isTransitioning = false;\n this.didDrag = false;\n};\n\n/**\n * handle item when it is dragged\n * @param {Number} x - horizontal position of dragged item\n * @param {Number} y - vertical position of dragged item\n */\nItem.prototype.dragMove = function( x, y ) {\n this.didDrag = true;\n var packerySize = this.layout.size;\n x -= packerySize.paddingLeft;\n y -= packerySize.paddingTop;\n this.positionPlaceRect( x, y );\n};\n\nItem.prototype.dragStop = function() {\n this.getPosition();\n var isDiffX = this.position.x != this.placeRect.x;\n var isDiffY = this.position.y != this.placeRect.y;\n // set post-drag positioning flag\n this.needsPositioning = isDiffX || isDiffY;\n // reset flag\n this.didDrag = false;\n};\n\n// -------------------------- placing -------------------------- //\n\n/**\n * position a rect that will occupy space in the packer\n * @param {Number} x\n * @param {Number} y\n * @param {Boolean} isMaxYContained\n */\nItem.prototype.positionPlaceRect = function( x, y, isMaxYOpen ) {\n this.placeRect.x = this.getPlaceRectCoord( x, true );\n this.placeRect.y = this.getPlaceRectCoord( y, false, isMaxYOpen );\n};\n\n/**\n * get x/y coordinate for place rect\n * @param {Number} coord - x or y\n * @param {Boolean} isX\n * @param {Boolean} isMaxOpen - does not limit value to outer bound\n * @returns {Number} coord - processed x or y\n */\nItem.prototype.getPlaceRectCoord = function( coord, isX, isMaxOpen ) {\n var measure = isX ? 'Width' : 'Height';\n var size = this.size[ 'outer' + measure ];\n var segment = this.layout[ isX ? 'columnWidth' : 'rowHeight' ];\n var parentSize = this.layout.size[ 'inner' + measure ];\n\n // additional parentSize calculations for Y\n if ( !isX ) {\n parentSize = Math.max( parentSize, this.layout.maxY );\n // prevent gutter from bumping up height when non-vertical grid\n if ( !this.layout.rowHeight ) {\n parentSize -= this.layout.gutter;\n }\n }\n\n var max;\n\n if ( segment ) {\n segment += this.layout.gutter;\n // allow for last column to reach the edge\n parentSize += isX ? this.layout.gutter : 0;\n // snap to closest segment\n coord = Math.round( coord / segment );\n // contain to outer bound\n // contain non-growing bound, allow growing bound to grow\n var mathMethod;\n if ( this.layout.options.isHorizontal ) {\n mathMethod = !isX ? 'floor' : 'ceil';\n } else {\n mathMethod = isX ? 'floor' : 'ceil';\n }\n var maxSegments = Math[ mathMethod ]( parentSize / segment );\n maxSegments -= Math.ceil( size / segment );\n max = maxSegments;\n } else {\n max = parentSize - size;\n }\n\n coord = isMaxOpen ? coord : Math.min( coord, max );\n coord *= segment || 1;\n\n return Math.max( 0, coord );\n};\n\nItem.prototype.copyPlaceRectPosition = function() {\n this.rect.x = this.placeRect.x;\n this.rect.y = this.placeRect.y;\n};\n\n// ----- ----- //\n\n// remove element from DOM\nItem.prototype.removeElem = function() {\n this.element.parentNode.removeChild( this.element );\n // add space back to packer\n this.layout.packer.addSpace( this.rect );\n this.emitEvent( 'remove', [ this ] );\n};\n\n// ----- ----- //\n\nreturn Item;\n\n}));\n\n/*!\n * Packery v1.4.3\n * bin-packing layout library\n *\n * Licensed GPLv3 for open source use\n * or Flickity Commercial License for commercial use\n *\n * http://packery.metafizzy.co\n * Copyright 2015 Metafizzy\n */\n\n( function( window, factory ) {\n \n // universal module definition\n if ( typeof define == 'function' && define.amd ) {\n // AMD\n define( [\n 'classie/classie',\n 'get-size/get-size',\n 'outlayer/outlayer',\n 'packery/js/rect',\n 'packery/js/packer',\n 'packery/js/item'\n ],\n factory );\n } else if ( typeof exports == 'object' ) {\n // CommonJS\n module.exports = factory(\n require('desandro-classie'),\n require('get-size'),\n require('outlayer'),\n require('./rect'),\n require('./packer'),\n require('./item')\n );\n } else {\n // browser global\n window.Packery = factory(\n window.classie,\n window.getSize,\n window.Outlayer,\n window.Packery.Rect,\n window.Packery.Packer,\n window.Packery.Item\n );\n }\n\n}( window, function factory( classie, getSize, Outlayer, Rect, Packer, Item ) {\n\n\n// ----- Rect ----- //\n\n// allow for pixel rounding errors IE8-IE11 & Firefox; #227\nRect.prototype.canFit = function( rect ) {\n return this.width >= rect.width - 1 && this.height >= rect.height - 1;\n};\n\n// -------------------------- Packery -------------------------- //\n\n// create an Outlayer layout class\nvar Packery = Outlayer.create('packery');\nPackery.Item = Item;\n\nPackery.prototype._create = function() {\n // call super\n Outlayer.prototype._create.call( this );\n\n // initial properties\n this.packer = new Packer();\n\n // Left over from v1.0\n this.stamp( this.options.stamped );\n\n // create drag handlers\n var _this = this;\n this.handleDraggabilly = {\n dragStart: function() {\n _this.itemDragStart( this.element );\n },\n dragMove: function() {\n _this.itemDragMove( this.element, this.position.x, this.position.y );\n },\n dragEnd: function() {\n _this.itemDragEnd( this.element );\n }\n };\n\n this.handleUIDraggable = {\n start: function handleUIDraggableStart( event, ui ) {\n // HTML5 may trigger dragstart, dismiss HTML5 dragging\n if ( !ui ) {\n return;\n }\n _this.itemDragStart( event.currentTarget );\n },\n drag: function handleUIDraggableDrag( event, ui ) {\n if ( !ui ) {\n return;\n }\n _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top );\n },\n stop: function handleUIDraggableStop( event, ui ) {\n if ( !ui ) {\n return;\n }\n _this.itemDragEnd( event.currentTarget );\n }\n };\n\n};\n\n\n// ----- init & layout ----- //\n\n/**\n * logic before any new layout\n */\nPackery.prototype._resetLayout = function() {\n this.getSize();\n\n this._getMeasurements();\n\n // reset packer\n var packer = this.packer;\n // packer settings, if horizontal or vertical\n if ( this.options.isHorizontal ) {\n packer.width = Number.POSITIVE_INFINITY;\n packer.height = this.size.innerHeight + this.gutter;\n packer.sortDirection = 'rightwardTopToBottom';\n } else {\n packer.width = this.size.innerWidth + this.gutter;\n packer.height = Number.POSITIVE_INFINITY;\n packer.sortDirection = 'downwardLeftToRight';\n }\n\n packer.reset();\n\n // layout\n this.maxY = 0;\n this.maxX = 0;\n};\n\n/**\n * update columnWidth, rowHeight, & gutter\n * @private\n */\nPackery.prototype._getMeasurements = function() {\n this._getMeasurement( 'columnWidth', 'width' );\n this._getMeasurement( 'rowHeight', 'height' );\n this._getMeasurement( 'gutter', 'width' );\n};\n\nPackery.prototype._getItemLayoutPosition = function( item ) {\n this._packItem( item );\n return item.rect;\n};\n\n\n/**\n * layout item in packer\n * @param {Packery.Item} item\n */\nPackery.prototype._packItem = function( item ) {\n this._setRectSize( item.element, item.rect );\n // pack the rect in the packer\n this.packer.pack( item.rect );\n this._setMaxXY( item.rect );\n};\n\n/**\n * set max X and Y value, for size of container\n * @param {Packery.Rect} rect\n * @private\n */\nPackery.prototype._setMaxXY = function( rect ) {\n this.maxX = Math.max( rect.x + rect.width, this.maxX );\n this.maxY = Math.max( rect.y + rect.height, this.maxY );\n};\n\n/**\n * set the width and height of a rect, applying columnWidth and rowHeight\n * @param {Element} elem\n * @param {Packery.Rect} rect\n */\nPackery.prototype._setRectSize = function( elem, rect ) {\n var size = getSize( elem );\n var w = size.outerWidth;\n var h = size.outerHeight;\n // size for columnWidth and rowHeight, if available\n // only check if size is non-zero, #177\n if ( w || h ) {\n w = this._applyGridGutter( w, this.columnWidth );\n h = this._applyGridGutter( h, this.rowHeight );\n }\n // rect must fit in packer\n rect.width = Math.min( w, this.packer.width );\n rect.height = Math.min( h, this.packer.height );\n};\n\n/**\n * fits item to columnWidth/rowHeight and adds gutter\n * @param {Number} measurement - item width or height\n * @param {Number} gridSize - columnWidth or rowHeight\n * @returns measurement\n */\nPackery.prototype._applyGridGutter = function( measurement, gridSize ) {\n // just add gutter if no gridSize\n if ( !gridSize ) {\n return measurement + this.gutter;\n }\n gridSize += this.gutter;\n // fit item to columnWidth/rowHeight\n var remainder = measurement % gridSize;\n var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';\n measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize;\n return measurement;\n};\n\nPackery.prototype._getContainerSize = function() {\n if ( this.options.isHorizontal ) {\n return {\n width: this.maxX - this.gutter\n };\n } else {\n return {\n height: this.maxY - this.gutter\n };\n }\n};\n\n\n// -------------------------- stamp -------------------------- //\n\n/**\n * makes space for element\n * @param {Element} elem\n */\nPackery.prototype._manageStamp = function( elem ) {\n\n var item = this.getItem( elem );\n var rect;\n if ( item && item.isPlacing ) {\n rect = item.placeRect;\n } else {\n var offset = this._getElementOffset( elem );\n rect = new Rect({\n x: this.options.isOriginLeft ? offset.left : offset.right,\n y: this.options.isOriginTop ? offset.top : offset.bottom\n });\n }\n\n this._setRectSize( elem, rect );\n // save its space in the packer\n this.packer.placed( rect );\n this._setMaxXY( rect );\n};\n\n// -------------------------- methods -------------------------- //\n\nfunction verticalSorter( a, b ) {\n return a.position.y - b.position.y || a.position.x - b.position.x;\n}\n\nfunction horizontalSorter( a, b ) {\n return a.position.x - b.position.x || a.position.y - b.position.y;\n}\n\nPackery.prototype.sortItemsByPosition = function() {\n var sorter = this.options.isHorizontal ? horizontalSorter : verticalSorter;\n this.items.sort( sorter );\n};\n\n/**\n * Fit item element in its current position\n * Packery will position elements around it\n * useful for expanding elements\n *\n * @param {Element} elem\n * @param {Number} x - horizontal destination position, optional\n * @param {Number} y - vertical destination position, optional\n */\nPackery.prototype.fit = function( elem, x, y ) {\n var item = this.getItem( elem );\n if ( !item ) {\n return;\n }\n\n // prepare internal properties\n this._getMeasurements();\n\n // stamp item to get it out of layout\n this.stamp( item.element );\n // required for positionPlaceRect\n item.getSize();\n // set placing flag\n item.isPlacing = true;\n // fall back to current position for fitting\n x = x === undefined ? item.rect.x: x;\n y = y === undefined ? item.rect.y: y;\n\n // position it best at its destination\n item.positionPlaceRect( x, y, true );\n\n this._bindFitEvents( item );\n item.moveTo( item.placeRect.x, item.placeRect.y );\n // layout everything else\n this.layout();\n\n // return back to regularly scheduled programming\n this.unstamp( item.element );\n this.sortItemsByPosition();\n // un set placing flag, back to normal\n item.isPlacing = false;\n // copy place rect position\n item.copyPlaceRectPosition();\n};\n\n/**\n * emit event when item is fit and other items are laid out\n * @param {Packery.Item} item\n * @private\n */\nPackery.prototype._bindFitEvents = function( item ) {\n var _this = this;\n var ticks = 0;\n function tick() {\n ticks++;\n if ( ticks != 2 ) {\n return;\n }\n _this.dispatchEvent( 'fitComplete', null, [ item ] );\n }\n // when item is laid out\n item.on( 'layout', function() {\n tick();\n return true;\n });\n // when all items are laid out\n this.on( 'layoutComplete', function() {\n tick();\n return true;\n });\n};\n\n// -------------------------- resize -------------------------- //\n\n// debounced, layout on resize\nPackery.prototype.resize = function() {\n // don't trigger if size did not change\n var size = getSize( this.element );\n // check that this.size and size are there\n // IE8 triggers resize on body size change, so they might not be\n var hasSizes = this.size && size;\n var innerSize = this.options.isHorizontal ? 'innerHeight' : 'innerWidth';\n if ( hasSizes && size[ innerSize ] == this.size[ innerSize ] ) {\n return;\n }\n\n this.layout();\n};\n\n// -------------------------- drag -------------------------- //\n\n/**\n * handle an item drag start event\n * @param {Element} elem\n */\nPackery.prototype.itemDragStart = function( elem ) {\n this.stamp( elem );\n var item = this.getItem( elem );\n if ( item ) {\n item.dragStart();\n }\n};\n\n/**\n * handle an item drag move event\n * @param {Element} elem\n * @param {Number} x - horizontal change in position\n * @param {Number} y - vertical change in position\n */\nPackery.prototype.itemDragMove = function( elem, x, y ) {\n var item = this.getItem( elem );\n if ( item ) {\n item.dragMove( x, y );\n }\n\n // debounce\n var _this = this;\n // debounce triggering layout\n function delayed() {\n _this.layout();\n delete _this.dragTimeout;\n }\n\n this.clearDragTimeout();\n\n this.dragTimeout = setTimeout( delayed, 40 );\n};\n\nPackery.prototype.clearDragTimeout = function() {\n if ( this.dragTimeout ) {\n clearTimeout( this.dragTimeout );\n }\n};\n\n/**\n * handle an item drag end event\n * @param {Element} elem\n */\nPackery.prototype.itemDragEnd = function( elem ) {\n var item = this.getItem( elem );\n var itemDidDrag;\n if ( item ) {\n itemDidDrag = item.didDrag;\n item.dragStop();\n }\n // if elem didn't move, or if it doesn't need positioning\n // unignore and unstamp and call it a day\n if ( !item || ( !itemDidDrag && !item.needsPositioning ) ) {\n this.unstamp( elem );\n return;\n }\n // procced with dragged item\n\n classie.add( item.element, 'is-positioning-post-drag' );\n\n // save this var, as it could get reset in dragStart\n var onLayoutComplete = this._getDragEndLayoutComplete( elem, item );\n\n if ( item.needsPositioning ) {\n item.on( 'layout', onLayoutComplete );\n item.moveTo( item.placeRect.x, item.placeRect.y );\n } else if ( item ) {\n // item didn't need placement\n item.copyPlaceRectPosition();\n }\n\n this.clearDragTimeout();\n this.on( 'layoutComplete', onLayoutComplete );\n this.layout();\n\n};\n\n/**\n * get drag end callback\n * @param {Element} elem\n * @param {Packery.Item} item\n * @returns {Function} onLayoutComplete\n */\nPackery.prototype._getDragEndLayoutComplete = function( elem, item ) {\n var itemNeedsPositioning = item && item.needsPositioning;\n var completeCount = 0;\n var asyncCount = itemNeedsPositioning ? 2 : 1;\n var _this = this;\n\n return function onLayoutComplete() {\n completeCount++;\n // don't proceed if not complete\n if ( completeCount != asyncCount ) {\n return true;\n }\n // reset item\n if ( item ) {\n classie.remove( item.element, 'is-positioning-post-drag' );\n item.isPlacing = false;\n item.copyPlaceRectPosition();\n }\n\n _this.unstamp( elem );\n // only sort when item moved\n _this.sortItemsByPosition();\n\n // emit item drag event now that everything is done\n if ( itemNeedsPositioning ) {\n _this.dispatchEvent( 'dragItemPositioned', null, [ item ] );\n }\n // listen once\n return true;\n };\n};\n\n/**\n * binds Draggabilly events\n * @param {Draggabilly} draggie\n */\nPackery.prototype.bindDraggabillyEvents = function( draggie ) {\n draggie.on( 'dragStart', this.handleDraggabilly.dragStart );\n draggie.on( 'dragMove', this.handleDraggabilly.dragMove );\n draggie.on( 'dragEnd', this.handleDraggabilly.dragEnd );\n};\n\n/**\n * binds jQuery UI Draggable events\n * @param {jQuery} $elems\n */\nPackery.prototype.bindUIDraggableEvents = function( $elems ) {\n $elems\n .on( 'dragstart', this.handleUIDraggable.start )\n .on( 'drag', this.handleUIDraggable.drag )\n .on( 'dragstop', this.handleUIDraggable.stop );\n};\n\nPackery.Rect = Rect;\nPackery.Packer = Packer;\n\nreturn Packery;\n\n}));\n\n","Smartwave_Filterproducts/js/imagesloaded.js":"/*!\n * imagesLoaded PACKAGED v5.0.0\n * JavaScript is all like \"You images are done yet or what?\"\n * MIT License\n */\n\n/**\n * EvEmitter v2.1.1\n * Lil' event emitter\n * MIT License\n */\n\n( function( global, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS - Browserify, Webpack\n module.exports = factory();\n } else {\n // Browser globals\n global.EvEmitter = factory();\n }\n\n}( typeof window != 'undefined' ? window : this, function() {\n\nfunction EvEmitter() {}\n\nlet proto = EvEmitter.prototype;\n\nproto.on = function( eventName, listener ) {\n if ( !eventName || !listener ) return this;\n\n // set events hash\n let events = this._events = this._events || {};\n // set listeners array\n let listeners = events[ eventName ] = events[ eventName ] || [];\n // only add once\n if ( !listeners.includes( listener ) ) {\n listeners.push( listener );\n }\n\n return this;\n};\n\nproto.once = function( eventName, listener ) {\n if ( !eventName || !listener ) return this;\n\n // add event\n this.on( eventName, listener );\n // set once flag\n // set onceEvents hash\n let onceEvents = this._onceEvents = this._onceEvents || {};\n // set onceListeners object\n let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};\n // set flag\n onceListeners[ listener ] = true;\n\n return this;\n};\n\nproto.off = function( eventName, listener ) {\n let listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) return this;\n\n let index = listeners.indexOf( listener );\n if ( index != -1 ) {\n listeners.splice( index, 1 );\n }\n\n return this;\n};\n\nproto.emitEvent = function( eventName, args ) {\n let listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) return this;\n\n // copy over to avoid interference if .off() in listener\n listeners = listeners.slice( 0 );\n args = args || [];\n // once stuff\n let onceListeners = this._onceEvents && this._onceEvents[ eventName ];\n\n for ( let listener of listeners ) {\n let isOnce = onceListeners && onceListeners[ listener ];\n if ( isOnce ) {\n // remove listener\n // remove before trigger to prevent recursion\n this.off( eventName, listener );\n // unset once flag\n delete onceListeners[ listener ];\n }\n // trigger listener\n listener.apply( this, args );\n }\n\n return this;\n};\n\nproto.allOff = function() {\n delete this._events;\n delete this._onceEvents;\n return this;\n};\n\nreturn EvEmitter;\n\n} ) );\n/*!\n * imagesLoaded v5.0.0\n * JavaScript is all like \"You images are done yet or what?\"\n * MIT License\n */\n\n( function( window, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS\n module.exports = factory( window, require('ev-emitter') );\n } else {\n // browser global\n window.imagesLoaded = factory( window, window.EvEmitter );\n }\n\n} )( typeof window !== 'undefined' ? window : this,\n function factory( window, EvEmitter ) {\n\nlet $ = window.jQuery;\nlet console = window.console;\n\n// -------------------------- helpers -------------------------- //\n\n// turn element or nodeList into an array\nfunction makeArray( obj ) {\n // use object if already an array\n if ( Array.isArray( obj ) ) return obj;\n\n let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';\n // convert nodeList to array\n if ( isArrayLike ) return [ ...obj ];\n\n // array of single index\n return [ obj ];\n}\n\n// -------------------------- imagesLoaded -------------------------- //\n\n/**\n * @param {[Array, Element, NodeList, String]} elem\n * @param {[Object, Function]} options - if function, use as callback\n * @param {Function} onAlways - callback function\n * @returns {ImagesLoaded}\n */\nfunction ImagesLoaded( elem, options, onAlways ) {\n // coerce ImagesLoaded() without new, to be new ImagesLoaded()\n if ( !( this instanceof ImagesLoaded ) ) {\n return new ImagesLoaded( elem, options, onAlways );\n }\n // use elem as selector string\n let queryElem = elem;\n if ( typeof elem == 'string' ) {\n queryElem = document.querySelectorAll( elem );\n }\n // bail if bad element\n if ( !queryElem ) {\n console.error(`Bad element for imagesLoaded ${queryElem || elem}`);\n return;\n }\n\n this.elements = makeArray( queryElem );\n this.options = {};\n // shift arguments if no options set\n if ( typeof options == 'function' ) {\n onAlways = options;\n } else {\n Object.assign( this.options, options );\n }\n\n if ( onAlways ) this.on( 'always', onAlways );\n\n this.getImages();\n // add jQuery Deferred object\n if ( $ ) this.jqDeferred = new $.Deferred();\n\n // HACK check async to allow time to bind listeners\n setTimeout( this.check.bind( this ) );\n}\n\nImagesLoaded.prototype = Object.create( EvEmitter.prototype );\n\nImagesLoaded.prototype.getImages = function() {\n this.images = [];\n\n // filter & find items if we have an item selector\n this.elements.forEach( this.addElementImages, this );\n};\n\nconst elementNodeTypes = [ 1, 9, 11 ];\n\n/**\n * @param {Node} elem\n */\nImagesLoaded.prototype.addElementImages = function( elem ) {\n // filter siblings\n if ( elem.nodeName === 'IMG' ) {\n this.addImage( elem );\n }\n // get background image on element\n if ( this.options.background === true ) {\n this.addElementBackgroundImages( elem );\n }\n\n // find children\n // no non-element nodes, #143\n let { nodeType } = elem;\n if ( !nodeType || !elementNodeTypes.includes( nodeType ) ) return;\n\n let childImgs = elem.querySelectorAll('img');\n // concat childElems to filterFound array\n for ( let img of childImgs ) {\n this.addImage( img );\n }\n\n // get child background images\n if ( typeof this.options.background == 'string' ) {\n let children = elem.querySelectorAll( this.options.background );\n for ( let child of children ) {\n this.addElementBackgroundImages( child );\n }\n }\n};\n\nconst reURL = /url\\((['\"])?(.*?)\\1\\)/gi;\n\nImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {\n let style = getComputedStyle( elem );\n // Firefox returns null if in a hidden iframe https://bugzil.la/548397\n if ( !style ) return;\n\n // get url inside url(\"...\")\n let matches = reURL.exec( style.backgroundImage );\n while ( matches !== null ) {\n let url = matches && matches[2];\n if ( url ) {\n this.addBackground( url, elem );\n }\n matches = reURL.exec( style.backgroundImage );\n }\n};\n\n/**\n * @param {Image} img\n */\nImagesLoaded.prototype.addImage = function( img ) {\n let loadingImage = new LoadingImage( img );\n this.images.push( loadingImage );\n};\n\nImagesLoaded.prototype.addBackground = function( url, elem ) {\n let background = new Background( url, elem );\n this.images.push( background );\n};\n\nImagesLoaded.prototype.check = function() {\n this.progressedCount = 0;\n this.hasAnyBroken = false;\n // complete if no images\n if ( !this.images.length ) {\n this.complete();\n return;\n }\n\n /* eslint-disable-next-line func-style */\n let onProgress = ( image, elem, message ) => {\n // HACK - Chrome triggers event before object properties have changed. #83\n setTimeout( () => {\n this.progress( image, elem, message );\n } );\n };\n\n this.images.forEach( function( loadingImage ) {\n loadingImage.once( 'progress', onProgress );\n loadingImage.check();\n } );\n};\n\nImagesLoaded.prototype.progress = function( image, elem, message ) {\n this.progressedCount++;\n this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;\n // progress event\n this.emitEvent( 'progress', [ this, image, elem ] );\n if ( this.jqDeferred && this.jqDeferred.notify ) {\n this.jqDeferred.notify( this, image );\n }\n // check if completed\n if ( this.progressedCount === this.images.length ) {\n this.complete();\n }\n\n if ( this.options.debug && console ) {\n console.log( `progress: ${message}`, image, elem );\n }\n};\n\nImagesLoaded.prototype.complete = function() {\n let eventName = this.hasAnyBroken ? 'fail' : 'done';\n this.isComplete = true;\n this.emitEvent( eventName, [ this ] );\n this.emitEvent( 'always', [ this ] );\n if ( this.jqDeferred ) {\n let jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';\n this.jqDeferred[ jqMethod ]( this );\n }\n};\n\n// -------------------------- -------------------------- //\n\nfunction LoadingImage( img ) {\n this.img = img;\n}\n\nLoadingImage.prototype = Object.create( EvEmitter.prototype );\n\nLoadingImage.prototype.check = function() {\n // If complete is true and browser supports natural sizes,\n // try to check for image status manually.\n let isComplete = this.getIsImageComplete();\n if ( isComplete ) {\n // report based on naturalWidth\n this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );\n return;\n }\n\n // If none of the checks above matched, simulate loading on detached element.\n this.proxyImage = new Image();\n // add crossOrigin attribute. #204\n if ( this.img.crossOrigin ) {\n this.proxyImage.crossOrigin = this.img.crossOrigin;\n }\n this.proxyImage.addEventListener( 'load', this );\n this.proxyImage.addEventListener( 'error', this );\n // bind to image as well for Firefox. #191\n this.img.addEventListener( 'load', this );\n this.img.addEventListener( 'error', this );\n this.proxyImage.src = this.img.currentSrc || this.img.src;\n};\n\nLoadingImage.prototype.getIsImageComplete = function() {\n // check for non-zero, non-undefined naturalWidth\n // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671\n return this.img.complete && this.img.naturalWidth;\n};\n\nLoadingImage.prototype.confirm = function( isLoaded, message ) {\n this.isLoaded = isLoaded;\n let { parentNode } = this.img;\n // emit progress with parent <picture> or self <img>\n let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;\n this.emitEvent( 'progress', [ this, elem, message ] );\n};\n\n// ----- events ----- //\n\n// trigger specified handler for event type\nLoadingImage.prototype.handleEvent = function( event ) {\n let method = 'on' + event.type;\n if ( this[ method ] ) {\n this[ method ]( event );\n }\n};\n\nLoadingImage.prototype.onload = function() {\n this.confirm( true, 'onload' );\n this.unbindEvents();\n};\n\nLoadingImage.prototype.onerror = function() {\n this.confirm( false, 'onerror' );\n this.unbindEvents();\n};\n\nLoadingImage.prototype.unbindEvents = function() {\n this.proxyImage.removeEventListener( 'load', this );\n this.proxyImage.removeEventListener( 'error', this );\n this.img.removeEventListener( 'load', this );\n this.img.removeEventListener( 'error', this );\n};\n\n// -------------------------- Background -------------------------- //\n\nfunction Background( url, element ) {\n this.url = url;\n this.element = element;\n this.img = new Image();\n}\n\n// inherit LoadingImage prototype\nBackground.prototype = Object.create( LoadingImage.prototype );\n\nBackground.prototype.check = function() {\n this.img.addEventListener( 'load', this );\n this.img.addEventListener( 'error', this );\n this.img.src = this.url;\n // check if image is already complete\n let isComplete = this.getIsImageComplete();\n if ( isComplete ) {\n this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );\n this.unbindEvents();\n }\n};\n\nBackground.prototype.unbindEvents = function() {\n this.img.removeEventListener( 'load', this );\n this.img.removeEventListener( 'error', this );\n};\n\nBackground.prototype.confirm = function( isLoaded, message ) {\n this.isLoaded = isLoaded;\n this.emitEvent( 'progress', [ this, this.element, message ] );\n};\n\n// -------------------------- jQuery -------------------------- //\n\nImagesLoaded.makeJQueryPlugin = function( jQuery ) {\n jQuery = jQuery || window.jQuery;\n if ( !jQuery ) return;\n\n // set local variable\n $ = jQuery;\n // $().imagesLoaded()\n $.fn.imagesLoaded = function( options, onAlways ) {\n let instance = new ImagesLoaded( this, options, onAlways );\n return instance.jqDeferred.promise( $( this ) );\n };\n};\n// try making plugin\nImagesLoaded.makeJQueryPlugin();\n\n// -------------------------- -------------------------- //\n\nreturn ImagesLoaded;\n\n} );\n","Smartwave_Filterproducts/js/lazyload/jquery.lazyload.js":"/*!\n * Lazy Load - JavaScript plugin for lazy loading images\n *\n * Copyright (c) 2007-2019 Mika Tuupola\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/mit-license.php\n *\n * Project home:\n * https://appelsiini.net/projects/lazyload\n *\n * Version: 2.0.0-rc.2\n *\n */\n\n(function (root, factory) {\n if (typeof exports === \"object\") {\n module.exports = factory(root);\n } else if (typeof define === \"function\" && define.amd) {\n define([], factory);\n } else {\n root.LazyLoad = factory(root);\n }\n}) (typeof global !== \"undefined\" ? global : this.window || this.global, function (root) {\n\n \"use strict\";\n\n if (typeof define === \"function\" && define.amd){\n root = window;\n }\n\n const defaults = {\n src: \"data-src\",\n srcset: \"data-srcset\",\n selector: \".lazyload\",\n root: null,\n rootMargin: \"0px\",\n threshold: 0\n };\n\n /**\n * Merge two or more objects. Returns a new object.\n * @private\n * @param {Boolean} deep If true, do a deep (or recursive) merge [optional]\n * @param {Object} objects The objects to merge together\n * @returns {Object} Merged values of defaults and options\n */\n const extend = function () {\n\n let extended = {};\n let deep = false;\n let i = 0;\n let length = arguments.length;\n\n /* Check if a deep merge */\n if (Object.prototype.toString.call(arguments[0]) === \"[object Boolean]\") {\n deep = arguments[0];\n i++;\n }\n\n /* Merge the object into the extended object */\n let merge = function (obj) {\n for (let prop in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, prop)) {\n /* If deep merge and property is an object, merge properties */\n if (deep && Object.prototype.toString.call(obj[prop]) === \"[object Object]\") {\n extended[prop] = extend(true, extended[prop], obj[prop]);\n } else {\n extended[prop] = obj[prop];\n }\n }\n }\n };\n\n /* Loop through each object and conduct a merge */\n for (; i < length; i++) {\n let obj = arguments[i];\n merge(obj);\n }\n\n return extended;\n };\n\n function LazyLoad(images, options) {\n this.settings = extend(defaults, options || {});\n this.images = images || document.querySelectorAll(this.settings.selector);\n this.observer = null;\n this.init();\n }\n\n LazyLoad.prototype = {\n init: function() {\n\n /* Without observers load everything and bail out early. */\n if (!root.IntersectionObserver) {\n this.loadImages();\n return;\n }\n\n let self = this;\n let observerConfig = {\n root: this.settings.root,\n rootMargin: this.settings.rootMargin,\n threshold: [this.settings.threshold]\n };\n\n this.observer = new IntersectionObserver(function(entries) {\n Array.prototype.forEach.call(entries, function (entry) {\n if (entry.isIntersecting) {\n self.observer.unobserve(entry.target);\n let src = entry.target.getAttribute(self.settings.src);\n let srcset = entry.target.getAttribute(self.settings.srcset);\n if (\"img\" === entry.target.tagName.toLowerCase()) {\n if (src) {\n entry.target.src = src;\n }\n if (srcset) {\n entry.target.srcset = srcset;\n }\n } else {\n entry.target.style.backgroundImage = \"url(\" + src + \")\";\n }\n }\n });\n }, observerConfig);\n\n Array.prototype.forEach.call(this.images, function (image) {\n self.observer.observe(image);\n });\n },\n\n loadAndDestroy: function () {\n if (!this.settings) { return; }\n this.loadImages();\n this.destroy();\n },\n\n loadImages: function () {\n if (!this.settings) { return; }\n\n let self = this;\n Array.prototype.forEach.call(this.images, function (image) {\n let src = image.getAttribute(self.settings.src);\n let srcset = image.getAttribute(self.settings.srcset);\n if (\"img\" === image.tagName.toLowerCase()) {\n if (src) {\n image.src = src;\n }\n if (srcset) {\n image.srcset = srcset;\n }\n } else {\n image.style.backgroundImage = \"url('\" + src + \"')\";\n }\n });\n },\n\n destroy: function () {\n if (!this.settings) { return; }\n this.observer.disconnect();\n this.settings = null;\n }\n };\n\n root.lazyload = function(images, options) {\n return new LazyLoad(images, options);\n };\n\n if (root.jQuery) {\n const $ = root.jQuery;\n $.fn.lazyload = function (options) {\n options = options || {};\n options.attribute = options.attribute || \"data-src\";\n new LazyLoad($.makeArray(this), options);\n return this;\n };\n }\n\n return LazyLoad;\n});\n"} }});