Your IP : 216.73.217.13


Current Path : /proc/thread-self/cwd/static/frontend/Magento/luma/it_IT/js/bundle/
Upload File :
Current File : //proc/thread-self/cwd/static/frontend/Magento/luma/it_IT/js/bundle/bundle3.js

require.config({"config": {
        "jsbuild":{"Magento_Ui/js/lib/knockout/bindings/tooltip.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'ko',\n    'underscore',\n    'mage/template',\n    'text!ui/template/tooltip/tooltip.html',\n    '../template/renderer'\n], function ($, ko, _, template, tooltipTmpl, renderer) {\n    'use strict';\n\n    var tooltip,\n        defaults,\n        positions,\n        transformProp,\n        checkedPositions = {},\n        iterator = 0,\n        previousTooltip,\n        tooltipData,\n        positionData = {},\n        tooltipsCollection = {},\n        isTouchDevice = (function () {\n            return 'ontouchstart' in document.documentElement;\n        })(),\n        CLICK_EVENT = (function () {\n            return isTouchDevice ? 'touchstart' : 'click';\n        })();\n\n    defaults = {\n        tooltipWrapper: '[data-tooltip=tooltip-wrapper]',\n        tooltipContentBlock: 'data-tooltip-content',\n        closeButtonClass: 'action-close',\n        tailClass: 'data-tooltip-tail',\n        action: 'hover',\n        delay: 300,\n        track: false,\n        step: 20,\n        position: 'top',\n        closeButton: false,\n        showed: false,\n        strict: true,\n        center: false,\n        closeOnScroll: true\n    };\n\n    tooltipData = {\n        tooltipClasses: '',\n        trigger: false,\n        timeout: 0,\n        element: false,\n        event: false,\n        targetElement: {},\n        showed: false,\n        currentID: 0\n    };\n\n    /**\n     * Polyfill for css transform\n     */\n    transformProp = (function () {\n        var style = document.createElement('div').style,\n            base = 'Transform',\n            vendors = ['webkit', 'moz', 'ms', 'o'],\n            vi = vendors.length,\n            property;\n\n        if (typeof style.transform !== 'undefined') {\n            return 'transform';\n        }\n\n        while (vi--) {\n            property = vendors[vi] + base;\n\n            if (typeof style[property] !== 'undefined') {\n                return property;\n            }\n        }\n    })();\n\n    positions = {\n\n        /*eslint max-depth: [0, 0]*/\n\n        map: {\n            horizontal: {\n                s: 'w',\n                p: 'left'\n            },\n            vertical: {\n                s: 'h',\n                p: 'top'\n            }\n        },\n\n        /**\n         * Wrapper function to get tooltip data (position, className, etc)\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        top: function (s) {\n            return positions._topLeftChecker(s, positions.map, 'vertical', '_bottom', 'top', 'right');\n        },\n\n        /**\n         * Wrapper function to get tooltip data (position, className, etc)\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        left: function (s) {\n            return positions._topLeftChecker(s, positions.map, 'horizontal', '_right', 'left', 'top');\n        },\n\n        /**\n         * Wrapper function to get tooltip data (position, className, etc)\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        bottom: function (s) {\n            return positions._bottomRightChecker(s, positions.map, 'vertical', '_top', 'bottom', 'left');\n        },\n\n        /**\n         * Wrapper function to get tooltip data (position, className, etc)\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        right: function (s) {\n            return positions._bottomRightChecker(s, positions.map, 'horizontal', '_left', 'right', 'bottom');\n        },\n\n        /**\n         * Check can tooltip setted on current position or not. If can't setted - delegate call.\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @param {Object} map - mapping for get direction positions\n         * @param {String} direction - vertical or horizontal\n         * @param {String} className - class whats should be setted to tooltip\n         * @param {String} side - parent method name\n         * @param {String} delegate - method name if tooltip can't be setted in current position\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        _topLeftChecker: function (s, map, direction, className, side, delegate) {\n            var result = {\n                    position: {}\n                },\n                config = tooltip.getTooltip(tooltipData.currentID),\n                startPosition = !config.strict ? s.eventPosition : s.elementPosition,\n                changedDirection;\n\n            checkedPositions[side] = true;\n\n            if (\n                startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - config.step >\n                s.scrollPosition[map[direction].p]\n            ) {\n                result.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] -\n                    config.step;\n                result.className = className;\n                result.side = side;\n                changedDirection = direction === 'vertical' ? 'horizontal' : 'vertical';\n                result = positions._normalize(s, result, config, delegate, map, changedDirection);\n            } else if (!checkedPositions[delegate]) {\n                result = positions[delegate].apply(null, arguments);\n            } else {\n                result = positions.positionCenter(s, result);\n            }\n\n            return result;\n        },\n\n        /**\n         * Check can tooltip setted on current position or not. If can't setted - delegate call.\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @param {Object} map - mapping for get direction positions\n         * @param {String} direction - vertical or horizontal\n         * @param {String} className - class whats should be setted to tooltip\n         * @param {String} side - parent method name\n         * @param {String} delegate - method name if tooltip can't be setted in current position\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        _bottomRightChecker: function (s, map, direction, className, side, delegate) {\n            var result = {\n                    position: {}\n                },\n                config = tooltip.getTooltip(tooltipData.currentID),\n                startPosition = !config.strict ? s.eventPosition : {\n                    top: s.elementPosition.top + s.elementSize.h,\n                    left: s.elementPosition.left + s.elementSize.w\n                },\n                changedDirection;\n\n            checkedPositions[side] = true;\n\n            if (\n                startPosition[map[direction].p] + s.tooltipSize[map[direction].s] + config.step <\n                s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]\n            ) {\n                result.position[map[direction].p] = startPosition[map[direction].p] + config.step;\n                result.className = className;\n                result.side = side;\n                changedDirection = direction === 'vertical' ? 'horizontal' : 'vertical';\n                result = positions._normalize(s, result, config, delegate, map, changedDirection);\n            } else if (!checkedPositions[delegate]) {\n                result = positions[delegate].apply(null, arguments);\n            } else {\n                result = positions.positionCenter(s, result);\n            }\n\n            return result;\n        },\n\n        /**\n         * Centered tooltip if tooltip does not fit in window\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @param {Object} data - current data (position, className, etc)\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        positionCenter: function (s, data) {\n            data = positions._positionCenter(s, data, 'horizontal', positions.map);\n            data = positions._positionCenter(s, data, 'vertical', positions.map);\n\n            return data;\n        },\n\n        /**\n         * Centered tooltip side\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @param {Object} data - current data (position, className, etc)\n         * @param {String} direction - vertical or horizontal\n         * @param {Object} map - mapping for get direction positions\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        _positionCenter: function (s, data, direction, map) {\n            if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) {\n                data.position[map[direction].p] = (s.windowSize[map[direction].s] -\n                    s.tooltipSize[map[direction].s]) / 2 + s.scrollPosition[map[direction].p];\n            } else {\n                data.position[map[direction].p] = s.scrollPosition[map[direction].p];\n                data.tooltipSize = {};\n                data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s];\n            }\n\n            return data;\n        },\n\n        /**\n         * Normalize horizontal or vertical position.\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @param {Object} data - current data (position, className, etc)\n         * @param {Object} config - tooltip config\n         * @param {String} delegate - method name if tooltip can't be setted in current position\n         * @param {Object} map - mapping for get direction positions\n         * @param {String} direction - vertical or horizontal\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        _normalize: function (s, data, config, delegate, map, direction) {\n            var startPosition = !config.center ? s.eventPosition : {\n                    left: s.elementPosition.left + s.elementSize.w / 2,\n                    top: s.elementPosition.top + s.elementSize.h / 2\n                },\n                depResult;\n\n            if (startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 >\n                s.scrollPosition[map[direction].p] && startPosition[map[direction].p] +\n                s.tooltipSize[map[direction].s] / 2 <\n                s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]\n            ) {\n                data.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2;\n            } else {\n\n                /*eslint-disable no-lonely-if*/\n                if (!checkedPositions[delegate]) {\n                    depResult = positions[delegate].apply(null, arguments);\n\n                    if (depResult.hasOwnProperty('className')) {\n                        data = depResult;\n                    } else {\n                        data = positions._normalizeTail(s, data, config, delegate, map, direction, startPosition);\n                    }\n                } else {\n                    data = positions._normalizeTail(s, data, config, delegate, map, direction, startPosition);\n                }\n            }\n\n            return data;\n        },\n\n        /**\n         * Calc tail position.\n         *\n         * @param {Object} s - object with sizes and positions elements\n         * @param {Object} data - current data (position, className, etc)\n         * @param {Object} config - tooltip config\n         * @param {String} delegate - method name if tooltip can't be setted in current position\n         * @param {Object} map - mapping for get direction positions\n         * @param {String} direction - vertical or horizontal\n         * @param {Object} startPosition - start position\n         * @returns {Object} tooltip data (position, className, etc)\n         */\n        _normalizeTail: function (s, data, config, delegate, map, direction, startPosition) {\n            data.tail = {};\n\n            if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) {\n\n                if (\n                    startPosition[map[direction].p] >\n                    s.windowSize[map[direction].s] / 2 + s.scrollPosition[map[direction].p]\n                ) {\n                    data.position[map[direction].p] = s.windowSize[map[direction].s] +\n                        s.scrollPosition[map[direction].p] - s.tooltipSize[map[direction].s];\n                    data.tail[map[direction].p] = startPosition[map[direction].p] -\n                        s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p];\n                } else {\n                    data.position[map[direction].p] = s.scrollPosition[map[direction].p];\n                    data.tail[map[direction].p] = startPosition[map[direction].p] -\n                        s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p];\n                }\n            } else {\n                data.position[map[direction].p] = s.scrollPosition[map[direction].p];\n                data.tail[map[direction].p] = s.eventPosition[map[direction].p] - s.windowSize[map[direction].s] / 2;\n                data.tooltipSize = {};\n                data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s];\n            }\n\n            return data;\n        }\n    };\n\n    tooltip = {\n\n        /**\n         * Set new tooltip to tooltipCollection, save config, and add unic id\n         *\n         * @param {Object} config - tooltip config\n         * @returns {String} tooltip id\n         */\n        setTooltip: function (config) {\n            var property = 'id-' + iterator;\n\n            tooltipsCollection[property] = config;\n            iterator++;\n\n            return property;\n        },\n\n        /**\n         * Get tooltip config by id\n         *\n         * @param {String} id - tooltip id\n         * @returns {Object} tooltip config\n         */\n        getTooltip: function (id) {\n            return tooltipsCollection[id];\n        },\n\n        /**\n         * Set content to current tooltip\n         *\n         * @param {Object} tooltipElement - tooltip element\n         * @param {Object} viewModel - tooltip view model\n         * @param {String} id - tooltip id\n         * @param {Object} bindingCtx - tooltip context\n         * @param {Object} event - action event\n         */\n        setContent: function (tooltipElement, viewModel, id, bindingCtx, event) {\n            var html = $(tooltipElement).html(),\n                config = tooltip.getTooltip(id),\n                body = $('body');\n\n            tooltipData.currentID = id;\n            tooltipData.trigger = $(event.currentTarget);\n            tooltip.setTargetData(event);\n            body.on('mousemove.setTargetData', tooltip.setTargetData);\n            tooltip.clearTimeout(id);\n\n            tooltipData.timeout = _.delay(function () {\n                body.off('mousemove.setTargetData', tooltip.setTargetData);\n\n                if (tooltipData.trigger[0] === tooltipData.targetElement) {\n                    tooltip.destroy(id);\n                    event.stopPropagation();\n                    tooltipElement = tooltip.createTooltip(id);\n                    tooltipElement.find('.' + defaults.tooltipContentBlock).append(html);\n                    tooltipElement.applyBindings(bindingCtx);\n                    tooltip.setHandlers(id);\n                    tooltip.setPosition(tooltipElement, id);\n                    previousTooltip = id;\n                }\n\n            }, config.delay);\n        },\n\n        /**\n         * Set position to current tooltip\n         *\n         * @param {Object} tooltipElement - tooltip element\n         * @param {String} id - tooltip id\n         */\n        setPosition: function (tooltipElement, id) {\n            var config = tooltip.getTooltip(id);\n\n            tooltip.sizeData = {\n                windowSize: {\n                    h: $(window).outerHeight(),\n                    w: $(window).outerWidth()\n                },\n                scrollPosition: {\n                    top: $(window).scrollTop(),\n                    left: $(window).scrollLeft()\n                },\n                tooltipSize: {\n                    h: tooltipElement.outerHeight(),\n                    w: tooltipElement.outerWidth()\n                },\n                elementSize: {\n                    h: tooltipData.trigger.outerHeight(),\n                    w: tooltipData.trigger.outerWidth()\n                },\n                elementPosition: tooltipData.trigger.offset(),\n                eventPosition: this.getEventPosition(tooltipData.event)\n            };\n\n            _.extend(positionData, positions[config.position](tooltip.sizeData));\n            tooltipElement.css(positionData.position);\n            tooltipElement.addClass(positionData.className);\n            tooltip._setTooltipSize(positionData, tooltipElement);\n            tooltip._setTailPosition(positionData, tooltipElement);\n            checkedPositions = {};\n        },\n\n        /**\n         * Check position data and change tooltip size if needs\n         *\n         * @param {Object} data - position data\n         * @param {Object} tooltipElement - tooltip element\n         */\n        _setTooltipSize: function (data, tooltipElement) {\n            if (data.tooltipSize) {\n                data.tooltipSize.w ?\n                    tooltipElement.css('width', data.tooltipSize.w) :\n                    tooltipElement.css('height', data.tooltipSize.h);\n            }\n        },\n\n        /**\n         * Check position data and set position to tail\n         *\n         * @param {Object} data - position data\n         * @param {Object} tooltipElement - tooltip element\n         */\n        _setTailPosition: function (data, tooltipElement) {\n            var tail,\n                tailMargin;\n\n            if (data.tail) {\n                tail = tooltipElement.find('.' + defaults.tailClass);\n\n                if (data.tail.left) {\n                    tailMargin = parseInt(tail.css('margin-left'), 10);\n                    tail.css('margin-left', tailMargin + data.tail.left);\n                } else {\n                    tailMargin = parseInt(tail.css('margin-top'), 10);\n                    tail.css('margin-top', tailMargin + data.tail.top);\n                }\n            }\n        },\n\n        /**\n         * Resolves position for tooltip\n         *\n         * @param {Object} event\n         * @returns {Object}\n         */\n        getEventPosition: function (event) {\n            var position = {\n                left: event.originalEvent && event.originalEvent.pageX || 0,\n                top: event.originalEvent && event.originalEvent.pageY || 0\n            };\n\n            if (position.left === 0 && position.top === 0) {\n                _.extend(position, event.target.getBoundingClientRect());\n            }\n\n            return position;\n        },\n\n        /**\n         * Close tooltip if action happened outside handler and tooltip element\n         *\n         * @param {String} id - tooltip id\n         * @param {Object} event - action event\n         */\n        outerClick: function (id, event) {\n            var tooltipElement = $(event.target).parents(defaults.tooltipWrapper)[0],\n                isTrigger = event.target === tooltipData.trigger[0] || $.contains(tooltipData.trigger[0], event.target);\n\n            if (tooltipData.showed && tooltipElement !== tooltipData.element[0] && !isTrigger) {\n                tooltip.destroy(id);\n            }\n        },\n\n        /**\n         * Parse keydown event and if event trigger is escape key - close tooltip\n         *\n         * @param {Object} event - action event\n         */\n        keydownHandler: function (event) {\n            if (tooltipData.showed && event.keyCode === 27) {\n                tooltip.destroy(tooltipData.currentID);\n            }\n        },\n\n        /**\n         * Change tooltip position when track is enabled\n         *\n         * @param {Object} event - current event\n         */\n        track: function (event) {\n            var inequality = {},\n                map = positions.map,\n                translate = {\n                    left: 'translateX',\n                    top: 'translateY'\n                },\n                eventPosition = {\n                    left: event.pageX,\n                    top: event.pageY\n                },\n                tooltipSize = {\n                    w: tooltipData.element.outerWidth(),\n                    h: tooltipData.element.outerHeight()\n                },\n                direction = positionData.side === 'bottom' || positionData.side === 'top' ? 'horizontal' : 'vertical';\n\n            inequality[map[direction].p] = eventPosition[map[direction].p] - (positionData.position[map[direction].p] +\n                tooltipSize[map[direction].s] / 2);\n\n            if (positionData.position[map[direction].p] + inequality[map[direction].p] +\n                tooltip.sizeData.tooltipSize[map[direction].s] >\n                tooltip.sizeData.windowSize[map[direction].s] + tooltip.sizeData.scrollPosition[map[direction].p] ||\n                inequality[map[direction].p] + positionData.position[map[direction].p] <\n                tooltip.sizeData.scrollPosition[map[direction].p]) {\n\n                return false;\n            }\n\n            tooltipData.element[0].style[transformProp] = translate[map[direction].p] +\n                '(' + inequality[map[direction].p] + 'px)';\n        },\n\n        /**\n         * Set handlers to tooltip\n         *\n         * @param {String} id - tooltip id\n         */\n        setHandlers: function (id) {\n            var config = tooltip.getTooltip(id);\n\n            if (config.track) {\n                tooltipData.trigger.on('mousemove.track', tooltip.track);\n            }\n\n            if (config.action === 'click') {\n                $(window).on(CLICK_EVENT + '.outerClick', tooltip.outerClick.bind(null, id));\n            }\n\n            if (config.closeButton) {\n                $('.' + config.closeButtonClass).on('click.closeButton', tooltip.destroy.bind(null, id));\n            }\n\n            if (config.closeOnScroll) {\n                document.addEventListener('scroll', tooltip.destroy, true);\n                $(window).on('scroll.tooltip', tooltip.outerClick.bind(null, id));\n            }\n\n            $(window).on('keydown.tooltip', tooltip.keydownHandler);\n            $(window).on('resize.outerClick', tooltip.outerClick.bind(null, id));\n        },\n\n        /**\n         * Toggle tooltip\n         *\n         * @param {Object} tooltipElement - tooltip element\n         * @param {Object} viewModel - tooltip view model\n         * @param {String} id - tooltip id\n         */\n        toggleTooltip: function (tooltipElement, viewModel, id) {\n            if (previousTooltip === id && tooltipData.showed) {\n                tooltip.destroy(id);\n\n                return false;\n            }\n\n            tooltip.setContent.apply(null, arguments);\n\n            return false;\n        },\n\n        /**\n         * Create tooltip and append to DOM\n         *\n         * @param {String} id - tooltip id\n         * @returns {Object} tooltip element\n         */\n        createTooltip: function (id) {\n            var body = $('body'),\n                config = tooltip.getTooltip(id);\n\n            $(template(tooltipTmpl, {\n                data: config\n            })).appendTo(body);\n\n            tooltipData.showed = true;\n            tooltipData.element = $(config.tooltipWrapper);\n\n            return tooltipData.element;\n        },\n\n        /**\n         * Check action and clean timeout\n         *\n         * @param {String} id - tooltip id\n         */\n        clearTimeout: function (id) {\n            var config = tooltip.getTooltip(id);\n\n            if (config.action === 'hover') {\n                clearTimeout(tooltipData.timeout);\n            }\n        },\n\n        /**\n         * Check previous tooltip\n         */\n        checkPreviousTooltip: function () {\n            if (!tooltipData.timeout) {\n                tooltip.destroy();\n            }\n        },\n\n        /**\n         * Destroy tooltip instance\n         */\n        destroy: function () {\n            if (tooltipData.element) {\n                tooltipData.element.remove();\n                tooltipData.showed = false;\n            }\n\n            positionData = {};\n            tooltipData.timeout = false;\n            tooltip.removeHandlers();\n        },\n\n        /**\n         * Remove tooltip handlers\n         */\n        removeHandlers: function () {\n            $('.' + defaults.closeButtonClass).off('click.closeButton');\n            tooltipData.trigger.off('mousemove.track');\n            document.removeEventListener('scroll', tooltip.destroy, true);\n            $(window).off('scroll.tooltip');\n            $(window).off(CLICK_EVENT + '.outerClick');\n            $(window).off('keydown.tooltip');\n            $(window).off('resize.outerClick');\n        },\n\n        /**\n         * Set target element\n         *\n         * @param {Object} event - current event\n         */\n        setTargetData: function (event) {\n            tooltipData.event = event;\n\n            //TODO: bug chrome v.49; Link to issue https://bugs.chromium.org/p/chromium/issues/detail?id=161464\n            if (event.timeStamp - (tooltipData.timestamp || 0) < 1) {\n                return;\n            }\n\n            if (event.type === 'mousemove') {\n                tooltipData.targetElement = event.target;\n            } else {\n                tooltipData.targetElement = event.currentTarget;\n                tooltipData.timestamp = event.timeStamp;\n            }\n        },\n\n        /**\n         * Merged user config with defaults configuration\n         *\n         * @param {Object} config - user config\n         * @returns {Object} merged config\n         */\n        processingConfig: function (config) {\n            return _.extend({}, defaults, config);\n        }\n    };\n\n    ko.bindingHandlers.tooltip = {\n\n        /**\n         * Initialize tooltip\n         *\n         * @param {Object} elem - tooltip DOM element\n         * @param {Function} valueAccessor - ko observable property, tooltip data\n         * @param {Object} allBindings - all bindings on current element\n         * @param {Object} viewModel - current element viewModel\n         * @param {Object} bindingCtx - current element binding context\n         */\n        init: function (elem, valueAccessor, allBindings, viewModel, bindingCtx) {\n            var config = tooltip.processingConfig(valueAccessor()),\n                $parentScope = config.parentScope ? $(config.parentScope) : $(elem).parent(),\n                tooltipId;\n\n            $(elem).addClass('hidden');\n\n            if (isTouchDevice) {\n                config.action = 'click';\n            }\n            tooltipId = tooltip.setTooltip(config);\n\n            if (config.action === 'hover') {\n                $parentScope.on(\n                    'mouseenter',\n                    config.trigger,\n                    tooltip.setContent.bind(null, elem, viewModel, tooltipId, bindingCtx)\n                );\n                $parentScope.on(\n                    'mouseleave',\n                    config.trigger,\n                    tooltip.checkPreviousTooltip.bind(null, tooltipId)\n                );\n            } else if (config.action === 'click') {\n                $parentScope.on(\n                    'click',\n                    config.trigger,\n                    tooltip.toggleTooltip.bind(null, elem, viewModel, tooltipId, bindingCtx)\n                );\n            }\n\n            return {\n                controlsDescendantBindings: true\n            };\n        }\n    };\n\n    renderer.addAttribute('tooltip');\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/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/simple-checked.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.simpleChecked = {\n        'after': ['attr'],\n\n        /**\n         * Implements same functionality as a standard 'simpleChecked' 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) {\n            var isCheckbox = element.type === 'checkbox',\n                isRadio = element.type === 'radio',\n                updateView,\n                updateModel;\n\n            if (!isCheckbox && !isRadio) {\n                return;\n            }\n\n            /**\n             * Updates checked observable\n             */\n            updateModel = function () {\n                var  modelValue = ko.dependencyDetection.ignore(valueAccessor),\n                    isChecked = element.checked;\n\n                if (ko.computedContext.isInitial()) {\n                    return;\n                }\n\n                if (modelValue.peek() === isChecked) {\n                    return;\n                }\n\n                if (isRadio && !isChecked) {\n                    return;\n                }\n\n                modelValue(isChecked);\n            };\n\n            /**\n             * Updates checkbox state\n             */\n            updateView = function () {\n                var modelValue = ko.utils.unwrapObservable(valueAccessor());\n\n                element.checked = !!modelValue;\n            };\n\n            ko.utils.registerEventHandler(element, 'change', updateModel);\n\n            ko.computed(updateModel, null, {\n                disposeWhenNodeIsRemoved: element\n            });\n            ko.computed(updateView, null, {\n                disposeWhenNodeIsRemoved: element\n            });\n        }\n    };\n\n    ko.expressionRewriting._twoWayBindings.simpleChecked = true;\n\n    renderer.addAttribute('simpleChecked');\n    renderer.addAttribute('simple-checked', {\n        binding: 'simpleChecked'\n    });\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/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/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 = /&nbsp;/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('&nbsp;', 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/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/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/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/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/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/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/autoselect.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], function (ko, $, renderer) {\n    'use strict';\n\n    /**\n     * 'Focus' event handler.\n     *\n     * @param {EventObject} e\n     */\n    function onFocus(e) {\n        e.target.select();\n    }\n\n    ko.bindingHandlers.autoselect = {\n\n        /**\n         * Adds event handler which automatically\n         * selects inputs' element text when field gets focused.\n         */\n        init: function (element, valueAccessor) {\n            var enabled = ko.unwrap(valueAccessor());\n\n            if (enabled !== false) {\n                $(element).on('focus', onFocus);\n            }\n        }\n    };\n\n    renderer.addAttribute('autoselect');\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/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/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/registry/registry.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], function ($, _) {\n    'use strict';\n\n    var privateData = new WeakMap();\n\n    /**\n     * Extracts private item storage associated\n     * with a provided registry instance.\n     *\n     * @param {Object} container\n     * @returns {Object}\n     */\n    function getItems(container) {\n        return privateData.get(container).items;\n    }\n\n    /**\n     * Extracts private requests array associated\n     * with a provided registry instance.\n     *\n     * @param {Object} container\n     * @returns {Array}\n     */\n    function getRequests(container) {\n        return privateData.get(container).requests;\n    }\n\n    /**\n     * Wrapper function used for convenient access to the elements.\n     * See 'async' method for examples of usage and comparison\n     * with a regular 'get' method.\n     *\n     * @param {(String|Object|Function)} name - Key of the requested element.\n     * @param {Registry} registry - Instance of a registry\n     *      where to search for the element.\n     * @param {(Function|String)} [method] - Optional callback function\n     *      or a name of the elements' method which\n     *      will be invoked when element is available in registry.\n     * @returns {*}\n     */\n    function async(name, registry, method) {\n        var args = _.toArray(arguments).slice(3);\n\n        if (_.isString(method)) {\n            registry.get(name, function (component) {\n                component[method].apply(component, args);\n            });\n        } else if (_.isFunction(method)) {\n            registry.get(name, method);\n        } else if (!args.length) {\n            return registry.get(name);\n        }\n    }\n\n    /**\n     * Checks that every property of the query object\n     * is present and equal to the corresponding\n     * property in target object.\n     * Note that non-strict comparison is used.\n     *\n     * @param {Object} query - Query object.\n     * @param {Object} target - Target object.\n     * @returns {Boolean}\n     */\n    function compare(query, target) {\n        var matches = true,\n            index,\n            keys,\n            key;\n\n        if (!_.isObject(query) || !_.isObject(target)) {\n            return false;\n        }\n\n        keys = Object.getOwnPropertyNames(query);\n        index = keys.length;\n\n        while (matches && index--) {\n            key = keys[index];\n\n            /* eslint-disable eqeqeq */\n            if (target[key] != query[key]) {\n                matches = false;\n            }\n\n            /* eslint-enable eqeqeq */\n        }\n\n        return matches;\n    }\n\n    /**\n     * Explodes incoming string into object if\n     * string is defined as a set of key = value pairs.\n     *\n     * @param {(String|*)} query - String to be processed.\n     * @returns {Object|*} Either created object or an unmodified incoming\n     *      value if conversion was not possible.\n     * @example Sample conversions.\n     *      'key = value, key2 = value2'\n     *      => {key: 'value', key2: 'value2'}\n     */\n    function explode(query) {\n        var result = {},\n            index,\n            data;\n\n        if (typeof query !== 'string' || !~query.indexOf('=')) {\n            return query;\n        }\n\n        query = query.split(',');\n        index = query.length;\n\n        while (index--) {\n            data = query[index].split('=');\n\n            result[data[0].trim()] = data[1].trim();\n        }\n\n        return result;\n    }\n\n    /**\n     * Extracts items from the provided data object\n     * which matches specified search criteria.\n     *\n     * @param {Object} data - Data object where to perform a lookup.\n     * @param {(String|Object|Function)} query - Search criteria.\n     * @param {Boolean} findAll - Flag that defines whether to\n     *      search for all applicable items or to stop on a first found entry.\n     * @returns {Array|Object|*}\n     */\n    function find(data, query, findAll) {\n        var iterator,\n            item;\n\n        query = explode(query);\n\n        if (typeof query === 'string') {\n            item = data[query];\n\n            if (findAll) {\n                return item ? [item] : [];\n            }\n\n            return item;\n        }\n\n        iterator = !_.isFunction(query) ?\n            compare.bind(null, query) :\n            query;\n\n        return findAll ?\n            _.filter(data, iterator) :\n            _.find(data, iterator);\n    }\n\n    /**\n     * @constructor\n     */\n    function Registry() {\n        var data = {\n            items: {},\n            requests: []\n        };\n\n        this._updateRequests = _.debounce(this._updateRequests.bind(this), 10);\n        privateData.set(this, data);\n    }\n\n    Registry.prototype = {\n        constructor: Registry,\n\n        /**\n         * Retrieves item from registry which matches specified search criteria.\n         *\n         * @param {(Object|String|Function|Array)} query - Search condition (see examples).\n         * @param {Function} [callback] - Callback that will be invoked when\n         *      all of the requested items are available.\n         * @returns {*}\n         *\n         * @example Requesting item by it's name.\n         *      var obj = {index: 'test', sample: true};\n         *\n         *      registry.set('first', obj);\n         *      registry.get('first') === obj;\n         *      => true\n         *\n         * @example Requesting item with a specific properties.\n         *      registry.get('sample = 1, index = test') === obj;\n         *      => true\n         *      registry.get('sample = 0, index = foo') === obj;\n         *      => false\n         *\n         * @example Declaring search criteria as an object.\n         *      registry.get({sample: true}) === obj;\n         *      => true;\n         *\n         * @example Providing custom search handler.\n         *      registry.get(function (item) { return item.sample === true; }) === obj;\n         *      => true\n         *\n         * @example Sample asynchronous request declaration.\n         *      registry.get('index = test', function (item) {});\n         *\n         * @example Requesting multiple elements.\n         *      registry.set('second', {index: 'test2'});\n         *      registry.get(['first', 'second'], function (first, second) {});\n         */\n        get: function (query, callback) {\n            if (typeof callback !== 'function') {\n                return find(getItems(this), query);\n            }\n\n            this._addRequest(query, callback);\n        },\n\n        /**\n         * Sets provided item to the registry.\n         *\n         * @param {String} id - Item's identifier.\n         * @param {*} item - Item's data.\n         * returns {Registry} Chainable.\n         */\n        set: function (id, item) {\n            getItems(this)[id] = item;\n\n            this._updateRequests();\n\n            return this;\n        },\n\n        /**\n         * Removes specified item from registry.\n         * Note that search query is not applicable.\n         *\n         * @param {String} id - Item's identifier.\n         * @returns {Registry} Chainable.\n         */\n        remove: function (id) {\n            delete getItems(this)[id];\n\n            return this;\n        },\n\n        /**\n         * Retrieves a collection of elements that match\n         * provided search criteria.\n         *\n         * @param {(Object|String|Function)} query - Search query.\n         *      See 'get' method for the syntax examples.\n         * @returns {Array} Found elements.\n         */\n        filter: function (query) {\n            return find(getItems(this), query, true);\n        },\n\n        /**\n         * Checks that at least one element in collection\n         * matches provided search criteria.\n         *\n         * @param {(Object|String|Function)} query - Search query.\n         *      See 'get' method for the syntax examples.\n         * @returns {Boolean}\n         */\n        has: function (query) {\n            return !!this.get(query);\n        },\n\n        /**\n         * Checks that registry contains a provided item.\n         *\n         * @param {*} item - Item to be checked.\n         * @returns {Boolean}\n         */\n        contains: function (item) {\n            return _.contains(getItems(this), item);\n        },\n\n        /**\n         * Extracts identifier of an item if it's present in registry.\n         *\n         * @param {*} item - Item whose identifier will be extracted.\n         * @returns {String|Undefined}\n         */\n        indexOf: function (item) {\n            return _.findKey(getItems(this), function (elem) {\n                return item === elem;\n            });\n        },\n\n        /**\n         * Same as a 'get' method except that it returns\n         * a promise object instead of invoking provided callback.\n         *\n         * @param {(String|Function|Object|Array)} query - Search query.\n         *      See 'get' method for the syntax examples.\n         * @returns {jQueryPromise}\n         */\n        promise: function (query) {\n            var defer    = $.Deferred(),\n                callback = defer.resolve.bind(defer);\n\n            this.get(query, callback);\n\n            return defer.promise();\n        },\n\n        /**\n         * Creates a wrapper function over the provided search query\n         * in order to provide somehow more convenient access to the\n         * registry's items.\n         *\n         * @param {(String|Object|Function)} query - Search criteria.\n         *      See 'get' method for the syntax examples.\n         * @returns {Function}\n         *\n         * @example Comparison with a 'get' method on retrieving items.\n         *      var module = registry.async('name');\n         *\n         *      module();\n         *      => registry.get('name');\n         *\n         * @example Asynchronous request.\n         *      module(function (component) {});\n         *      => registry.get('name', function (component) {});\n         *\n         * @example Requesting item and invoking it's method with specified parameters.\n         *      module('trigger', true);\n         *      => registry.get('name', function (component) {\n         *          component.trigger(true);\n         *      });\n         */\n        async: function (query) {\n            return async.bind(null, query, this);\n        },\n\n        /**\n         * Creates new instance of a Registry.\n         *\n         * @returns {Registry} New instance.\n         */\n        create: function () {\n            return new Registry;\n        },\n\n        /**\n         * Adds new request to the queue or resolves it immediately\n         * if all of the required items are available.\n         *\n         * @private\n         * @param {(Object|String|Function|Array)} queries - Search criteria.\n         *      See 'get' method for the syntax examples.\n         * @param {Function} callback - Callback that will be invoked when\n         *      all of the requested items are available.\n         * @returns {Registry}\n         */\n        _addRequest: function (queries, callback) {\n            var request;\n\n            if (!Array.isArray(queries)) {\n                queries = queries ? [queries] : [];\n            }\n\n            request = {\n                queries: queries.map(explode),\n                callback: callback\n            };\n\n            this._canResolve(request) ?\n                this._resolveRequest(request) :\n                getRequests(this).push(request);\n\n            return this;\n        },\n\n        /**\n         * Updates requests list resolving applicable items.\n         *\n         * @private\n         * @returns {Registry} Chainable.\n         */\n        _updateRequests: function () {\n            getRequests(this)\n                .filter(this._canResolve, this)\n                .forEach(this._resolveRequest, this);\n\n            return this;\n        },\n\n        /**\n         * Resolves provided request invoking it's callback\n         * with items specified in query parameters.\n         *\n         * @private\n         * @param {Object} request - Request object.\n         * @returns {Registry} Chainable.\n         */\n        _resolveRequest: function (request) {\n            var requests = getRequests(this),\n                items    = request.queries.map(this.get, this),\n                index    = requests.indexOf(request);\n\n            request.callback.apply(null, items);\n\n            if (~index) {\n                requests.splice(index, 1);\n            }\n\n            return this;\n        },\n\n        /**\n         * Checks if provided request can be resolved.\n         *\n         * @private\n         * @param {Object} request - Request object.\n         * @returns {Boolean}\n         */\n        _canResolve: function (request) {\n            var queries = request.queries;\n\n            return queries.every(this.has, this);\n        }\n    };\n\n    return new Registry;\n});\n","Magento_Ui/js/lib/view/utils/dom-observer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'underscore',\n    'domReady!'\n], function ($, _) {\n    'use strict';\n\n    var counter = 1,\n        watchers,\n        globalObserver,\n        disabledNodes = [];\n\n    watchers = {\n        selectors: {},\n        nodes: {}\n    };\n\n    /**\n     * Checks if node represents an element node (nodeType === 1).\n     *\n     * @param {HTMLElement} node\n     * @returns {Boolean}\n     */\n    function isElementNode(node) {\n        return node.nodeType === 1;\n    }\n\n    /**\n     * Extracts all child descendant\n     * elements of a specified node.\n     *\n     * @param {HTMLElement} node\n     * @returns {Array}\n     */\n    function extractChildren(node) {\n        var children = node.querySelectorAll('*');\n\n        return _.toArray(children);\n    }\n\n    /**\n     * Extracts node identifier. If ID is not specified,\n     * then it will be created for the provided node.\n     *\n     * @param {HTMLElement} node\n     * @returns {Number}\n     */\n    function getNodeId(node) {\n        var id = node._observeId;\n\n        if (!id) {\n            id = node._observeId = counter++;\n        }\n\n        return id;\n    }\n\n    /**\n     * Invokes callback passing node to it.\n     *\n     * @param {HTMLElement} node\n     * @param {Object} data\n     */\n    function trigger(node, data) {\n        var id = getNodeId(node),\n            ids = data.invoked;\n\n        if (_.contains(ids, id)) {\n            return;\n        }\n\n        data.callback(node);\n        data.invoked.push(id);\n    }\n\n    /**\n     * Adds node to the observer list.\n     *\n     * @param {HTMLElement} node\n     * @returns {Object}\n     */\n    function createNodeData(node) {\n        var nodes   = watchers.nodes,\n            id      = getNodeId(node);\n\n        nodes[id] = nodes[id] || {};\n\n        return nodes[id];\n    }\n\n    /**\n     * Returns data associated with a specified node.\n     *\n     * @param {HTMLElement} node\n     * @returns {Object|Undefined}\n     */\n    function getNodeData(node) {\n        var nodeId = node._observeId;\n\n        return watchers.nodes[nodeId];\n    }\n\n    /**\n     * Removes data associated with a specified node.\n     *\n     * @param {HTMLElement} node\n     */\n    function removeNodeData(node) {\n        var nodeId = node._observeId;\n\n        delete watchers.nodes[nodeId];\n    }\n\n    /**\n     * Adds removal listener for a specified node.\n     *\n     * @param {HTMLElement} node\n     * @param {Object} data\n     */\n    function addRemovalListener(node, data) {\n        var nodeData = createNodeData(node);\n\n        (nodeData.remove = nodeData.remove || []).push(data);\n    }\n\n    /**\n     * Adds listener for the nodes which matches specified selector.\n     *\n     * @param {String} selector - CSS selector.\n     * @param {Object} data\n     */\n    function addSelectorListener(selector, data) {\n        var storage = watchers.selectors;\n\n        (storage[selector] = storage[selector] || []).push(data);\n    }\n\n    /**\n     * Calls handlers associated with an added node.\n     * Adds listeners for the node removal.\n     *\n     * @param {HTMLElement} node - Added node.\n     */\n    function processAdded(node) {\n        _.each(watchers.selectors, function (listeners, selector) {\n            for (let data of listeners) {\n                if (!data.ctx.contains(node) || !$(node, data.ctx).is(selector)) {\n                    break;\n                }\n\n                if (data.type === 'add') {\n                    trigger(node, data);\n                } else if (data.type === 'remove') {\n                    addRemovalListener(node, data);\n                }\n            }\n        });\n    }\n\n    /**\n     * Calls handlers associated with a removed node.\n     *\n     * @param {HTMLElement} node - Removed node.\n     */\n    function processRemoved(node) {\n        var nodeData    = getNodeData(node),\n            listeners   = nodeData && nodeData.remove;\n\n\n        if (!listeners) {\n            return;\n        }\n\n        for (let data of listeners) {\n            trigger(node, data);\n        }\n        removeNodeData(node);\n    }\n\n    /**\n     * Removes all non-element nodes from provided array\n     * and appends to it descendant elements.\n     *\n     * @param {Array} nodes\n     * @returns {Array}\n     */\n    function formNodesList(nodes) {\n        var result = [],\n            children;\n\n        nodes = _.toArray(nodes).filter(isElementNode);\n\n        for (let node of nodes) {\n            result.push(node);\n\n            children = extractChildren(node);\n            result.push(...children);\n        }\n\n        return result;\n    }\n\n    /**\n     * Collects all removed and added nodes from\n     * mutation records into separate arrays\n     * while removing duplicates between both types of changes.\n     *\n     * @param {Array} mutations - An array of mutation records.\n     * @returns {Object} Object with 'removed' and 'added' nodes arrays.\n     */\n    function formChangesLists(mutations) {\n        var removed = [],\n            added = [];\n\n        for (let record of mutations) {\n            removed.push(...record.removedNodes);\n            added.push(...record.addedNodes);\n        }\n\n        removed = removed.filter(function (node) {\n            var addIndex = added.indexOf(node),\n                wasAdded = !!~addIndex;\n\n            if (wasAdded) {\n                added.splice(addIndex, 1);\n            }\n\n            return !wasAdded;\n        });\n\n        return {\n            removed: formNodesList(removed),\n            added: formNodesList(added)\n        };\n    }\n\n    /**\n     * Verify if the DOM node is a child of a defined disabled node, if so we shouldn't observe provided mutation.\n     *\n     * @param {Object} mutation - a single mutation\n     * @returns {Boolean}\n     */\n    function shouldObserveMutation(mutation) {\n        var isDisabled;\n\n        if (disabledNodes.length > 0) {\n            // Iterate through the disabled nodes and determine if this mutation is occurring inside one of them\n            isDisabled = _.find(disabledNodes, function (node) {\n                return node === mutation.target || $.contains(node, mutation.target);\n            });\n\n            // If we find a matching node we should not observe the mutation\n            return !isDisabled;\n        }\n\n        return true;\n    }\n\n    /**\n     * Should we observe these mutations? Check the first and last mutation to determine if this is a disabled mutation,\n     * we check both the first and last in case one has been removed from the DOM during the process of the mutation.\n     *\n     * @param {Array} mutations - An array of mutation records.\n     * @returns {Boolean}\n     */\n    function shouldObserveMutations(mutations) {\n        var firstMutation,\n            lastMutation;\n\n        if (mutations.length > 0) {\n            firstMutation = mutations[0];\n            lastMutation = mutations[mutations.length - 1];\n\n            return shouldObserveMutation(firstMutation) && shouldObserveMutation(lastMutation);\n        }\n\n        return true;\n    }\n\n    globalObserver = new MutationObserver(function (mutations) {\n        var changes;\n\n        if (shouldObserveMutations(mutations)) {\n            let node;\n\n            changes = formChangesLists(mutations);\n\n            for (node of changes.removed) {\n                processRemoved(node);\n            }\n            for (node of changes.added) {\n                processAdded(node);\n            }\n        }\n    });\n\n    globalObserver.observe(document.body, {\n        subtree: true,\n        childList: true\n    });\n\n    return {\n        /**\n         * Disable a node from being observed by the mutations, you may want to disable specific aspects of the\n         * application which are heavy on DOM changes. The observer running on some actions could cause significant\n         * delays and degrade the performance of that specific part of the application exponentially.\n         *\n         * @param {HTMLElement} node - a HTML node within the document\n         */\n        disableNode: function (node) {\n            disabledNodes.push(node);\n        },\n\n        /**\n         * Adds listener for the appearance of nodes that matches provided\n         * selector and which are inside of the provided context. Callback will be\n         * also invoked on elements which a currently present.\n         *\n         * @param {String} selector - CSS selector.\n         * @param {Function} callback - Function that will invoked when node appears.\n         * @param {HTMLElement} [ctx=document.body] - Context inside of which to search for the node.\n         */\n        get: function (selector, callback, ctx) {\n            var data,\n                nodes;\n\n            data = {\n                ctx: ctx || document.body,\n                type: 'add',\n                callback: callback,\n                invoked: []\n            };\n\n            nodes = $(selector, data.ctx).toArray();\n\n            for (let node of nodes) {\n                trigger(node, data);\n            }\n            addSelectorListener(selector, data);\n        },\n\n        /**\n         * Adds listener for the nodes removal.\n         *\n         * @param {(jQueryObject|HTMLElement|Array|String)} selector\n         * @param {Function} callback - Function that will invoked when node is removed.\n         * @param {HTMLElement} [ctx=document.body] - Context inside of which to search for the node.\n         */\n        remove: function (selector, callback, ctx) {\n            var nodes = [],\n                data;\n\n            data = {\n                ctx: ctx || document.body,\n                type: 'remove',\n                callback: callback,\n                invoked: []\n            };\n\n            if (typeof selector === 'object') {\n                nodes = !_.isUndefined(selector.length) ?\n                    _.toArray(selector) :\n                    [selector];\n            } else if (_.isString(selector)) {\n                nodes = $(selector, ctx).toArray();\n\n                addSelectorListener(selector, data);\n            }\n\n            for (let node of nodes) {\n                addRemovalListener(node, data);\n            }\n        },\n\n        /**\n         * Removes listeners.\n         *\n         * @param {String} selector\n         * @param {Function} [fn]\n         */\n        off: function (selector, fn) {\n            var selectors = watchers.selectors,\n                listeners = selectors[selector];\n\n            if (selector && !fn) {\n                delete selectors[selector];\n            } else if (listeners && fn) {\n                selectors[selector] = listeners.filter(function (data) {\n                    return data.callback !== fn;\n                });\n            }\n        }\n    };\n});\n","Magento_Ui/js/lib/view/utils/bindings.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], function (ko, $, _) {\n    'use strict';\n\n    /**\n     * Checks if provided  value is a dom element.\n     *\n     * @param {*} node - Value to be checked.\n     * @returns {Boolean}\n     */\n    function isDomElement(node) {\n        return typeof node === 'object' && node.tagName && node.nodeType;\n    }\n\n    /**\n     * Removes from the provided array all non-root nodes located inside\n     * of the comment element as long as the closing comment tags.\n     *\n     * @param {(Array|ArrayLike)} nodes - An array of nodes to be processed.\n     * @returns {Array}\n     */\n    function normalize(nodes) {\n        var result;\n\n        nodes   = _.toArray(nodes);\n        result  = nodes.slice();\n\n        nodes.forEach(function (node) {\n            if (node.nodeType === 8) {\n                result = !ko.virtualElements.hasBindingValue(node) ?\n                    _.without(result, node) :\n                    _.difference(result, ko.virtualElements.childNodes(node));\n            }\n        });\n\n        return result;\n    }\n\n    /**\n     * Extends binding context of each item in the collection.\n     *\n     * @param {...Object} extenders - Multiple extender objects to be applied to the context.\n     * @returns {jQueryCollection} Chainable.\n     */\n    $.fn.extendCtx = function () {\n        var nodes       = normalize(this),\n            extenders   = _.toArray(arguments);\n\n        nodes.forEach(function (node) {\n            var ctx  = ko.contextFor(node),\n                data = [ctx].concat(extenders);\n\n            _.extend.apply(_, data);\n        });\n\n        return this;\n    };\n\n    /**\n     * Evaluates bindings specified in each DOM element of collection.\n     *\n     * @param {(HTMLElement|Object)} [ctx] - Context to use for bindings evaluation.\n     *      If not specified then current context of a collections' item will be used.\n     * @returns {jQueryCollection} Chainable.\n     */\n    $.fn.applyBindings = function (ctx) {\n        var nodes = normalize(this),\n            nodeCtx;\n\n        if (isDomElement(ctx)) {\n            ctx = ko.contextFor(ctx);\n        }\n\n        nodes.forEach(function (node) {\n            nodeCtx = ctx || ko.contextFor(node);\n\n            ko.applyBindings(nodeCtx, node);\n        });\n\n        return this;\n    };\n\n    /**\n     * Adds specified bindings to each DOM element in\n     * collection and evaluates them with provided context.\n     *\n     * @param {(Object|Function)} data - Either bindings object or a function\n     *      which returns bindings data for each element in collection.\n     * @param {(HTMLElement|Object)} [ctx] - Context to use for bindings evaluation.\n     *      If not specified then current context of a collections' item will be used.\n     * @returns {jQueryCollection} Chainable.\n     */\n    $.fn.bindings = function (data, ctx) {\n        var nodes    = normalize(this),\n            bindings = data,\n            nodeCtx;\n\n        if (isDomElement(ctx)) {\n            ctx = ko.contextFor(ctx);\n        }\n\n        nodes.forEach(function (node) {\n            nodeCtx = ctx || ko.contextFor(node);\n\n            if (_.isFunction(data)) {\n                bindings = data(nodeCtx, node);\n            }\n\n            ko.applyBindingsToNode(node, bindings, nodeCtx);\n        });\n\n        return this;\n    };\n});\n","Magento_Ui/js/lib/view/utils/raf.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    var processMap = new WeakMap(),\n        origRaf,\n        raf;\n\n    origRaf = window.requestAnimationFrame ||\n        window.webkitRequestAnimationFrame ||\n        window.mozRequestAnimationFrame ||\n        window.onRequestAnimationFrame ||\n        window.msRequestAnimationFrame ||\n        function (callback) {\n            if (typeof callback != 'function') {\n                throw new Error('raf argument \"callback\" must be of type function');\n            }\n            window.setTimeout(callback, 1000 / 60);\n        };\n\n    /**\n     * Creates new process object or extracts the\n     * the existing one.\n     *\n     * @param {*} id - Process identifier.\n     * @param {Number} fps - Required FPS count.\n     * @returns {Object}\n     */\n    function getProcess(id, fps) {\n        var process = processMap.get(id);\n\n        if (!process) {\n            process = {};\n            processMap.set(id, process);\n        }\n\n        if (process.fps !== fps) {\n            process.fps        = fps;\n            process.interval   = 1000 / fps;\n            process.update     = Date.now();\n        }\n\n        return process;\n    }\n\n    /**\n     * Proxy method which delegates call to the 'requestAnimationFrame'\n     * function and optionally can keep track of the FPS with which\n     * provided function is called.\n     *\n     * @param {Function} callback - Callback function to be passed to 'requestAnimationFrame'.\n     * @param {Number} [fps] - If specified, will update FPS counter for the provided function.\n     * @returns {Number|Boolean} ID of request or a flag which indicates\n     *      whether callback fits specified FPS.\n     */\n    raf = function (callback, fps) {\n        var rafId = origRaf(callback);\n\n        return fps ? raf.tick(callback, fps) : rafId;\n    };\n\n    /**\n     * Updates FPS counter for the specified process\n     * and returns a flag which indicates whether\n     * counter value is equal or greater than the required FPS.\n     *\n     * @param {*} id - Process identifier.\n     * @param {Number} fps - Required FPS count.\n     * @returns {Boolean}\n     */\n    raf.tick = function (id, fps) {\n        var process  = getProcess(id, fps),\n            now      = Date.now(),\n            delta    = now - process.update,\n            interval = process.interval;\n\n        if (fps >= 60 || delta >= interval) {\n            process.update = now - delta % interval;\n\n            return true;\n        }\n\n        return false;\n    };\n\n    return raf;\n});\n","Magento_Ui/js/lib/view/utils/async.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    'underscore',\n    'uiRegistry',\n    './dom-observer',\n    'Magento_Ui/js/lib/knockout/extender/bound-nodes',\n    './bindings'\n], function (ko, $, _, registry, domObserver, boundedNodes) {\n    'use strict';\n\n    /**\n     * Checks if provided value is a dom element.\n     *\n     * @param {*} node - Value to be checked.\n     * @returns {Boolean}\n     */\n    function isDomElement(node) {\n        return typeof node === 'object' && node.tagName && node.nodeType;\n    }\n\n    /**\n     * Parses provided string and extracts\n     * component, context and selector data from it.\n     *\n     * @param {String} str - String to be processed.\n     * @returns {Object} Data retrieved from string.\n     *\n     * @example Sample format.\n     *      '{{component}}:{{ctx}} -> {{selector}}'\n     *\n     *      component - Name of component.\n     *      ctx - Selector of the root node upon which component is binded.\n     *      selector - Selector of DOM elements located\n     *          inside of a previously specified context.\n     */\n    function parseSelector(str) {\n        var data    = str.trim().split('->'),\n            result  = {},\n            componentData;\n\n        if (data.length === 1) {\n            if (!~data[0].indexOf(':')) {\n                result.selector = data[0];\n            } else {\n                componentData = data[0];\n            }\n        } else {\n            componentData   = data[0];\n            result.selector = data[1];\n        }\n\n        if (componentData) {\n            componentData = componentData.split(':');\n\n            result.component = componentData[0];\n            result.ctx = componentData[1];\n        }\n\n        _.each(result, function (value, key) {\n            result[key] = value.trim();\n        });\n\n        return result;\n    }\n\n    /**\n     * Internal method used to normalize argumnets passed\n     * to 'async' module methods.\n     *\n     * @param {(String|Object)} selector\n     * @param {(HTMLElement|Object|String)} [ctx]\n     * @returns {Object}\n     */\n    function parseData(selector, ctx) {\n        var data = {};\n\n        if (arguments.length === 2) {\n            data.selector = selector;\n\n            if (isDomElement(ctx)) {\n                data.ctx = ctx;\n            } else {\n                data.component = ctx;\n                data.ctx = '*';\n            }\n        } else {\n            data = _.isString(selector) ?\n                parseSelector(selector) :\n                selector;\n        }\n\n        return data;\n    }\n\n    /**\n     * Creates promise that will be resolved\n     * when requested component is registred.\n     *\n     * @param {String} name - Name of component.\n     * @returns {jQueryPromise}\n     */\n    function waitComponent(name) {\n        var deffer = $.Deferred();\n\n        if (_.isString(name)) {\n            registry.get(name, function (component) {\n                deffer.resolve(component);\n            });\n        } else {\n            deffer.resolve(name);\n        }\n\n        return deffer.promise();\n    }\n\n    /**\n     * Creates listener for the nodes binded to provided component.\n     *\n     * @param {Object} data - Listener data.\n     * @param {Object} component - Associated with nodes component.\n     */\n    function setRootListener(data, component) {\n        boundedNodes.get(component, function (root) {\n            if (!$(root).is(data.ctx || '*')) {\n                return;\n            }\n\n            data.selector ?\n                domObserver.get(data.selector, data.fn, root) :\n                data.fn(root);\n        });\n    }\n\n    /*eslint-disable no-unused-vars*/\n    /**\n     * Sets listener for the appearance of elements which\n     * matches specified selector data.\n     *\n     * @param {(String|Object)} selector - Valid css selector or a string\n     *      in format acceptable by 'parseSelector' method or an object with\n     *      'component', 'selector' and 'ctx' properties.\n     * @param {(HTMLElement|Object|String)} [ctx] - Optional context parameter\n     *      which might be a DOM element, component instance or components' name.\n     * @param {Function} fn - Callback that will be invoked\n     *      when required DOM element appears.\n     *\n     * @example\n     *      Creating listener of the 'span' nodes appearance,\n     *      located inside of 'div' nodes, which are binded to 'cms_page_listing' component:\n     *\n     *      $.async('cms_page_listing:div -> span', function (node) {});\n     *\n     * @example Another syntaxes of the previous example.\n     *      $.async({\n     *          component: 'cms_page_listing',\n     *          ctx: 'div',\n     *          selector: 'span'\n     *       }, function (node) {});\n     *\n     * @example Listens for appearance of any child node inside of specified component.\n     *      $.async('> *', 'cms_page_lsiting', function (node) {});\n     *\n     * @example Listens for appearance of 'span' nodes inside of specific context.\n     *      $.async('span', document.getElementById('test'), function (node) {});\n     */\n    $.async = function (selector, ctx, fn) {\n        var args = _.toArray(arguments),\n            data = parseData.apply(null, _.initial(args));\n\n        data.fn = _.last(args);\n\n        if (data.component) {\n            waitComponent(data.component)\n                .then(setRootListener.bind(null, data));\n        } else {\n            domObserver.get(data.selector, data.fn, data.ctx);\n        }\n    };\n\n    /*eslint-enable no-unused-vars*/\n\n    _.extend($.async, {\n\n        /*eslint-disable no-unused-vars*/\n        /**\n         * Returns collection of elements found by provided selector data.\n         *\n         * @param {(String|Object)} selector - See 'async' definition.\n         * @param {(HTMLElement|Object|String)} [ctx] - See 'async' definition.\n         * @returns {Array} An array of DOM elements.\n         */\n        get: function (selector, ctx) {\n            var data        = parseData.apply(null, arguments),\n                component   = data.component,\n                nodes;\n\n            if (!component) {\n                return $(data.selector, data.ctx).toArray();\n            } else if (_.isString(component)) {\n                component = registry.get(component);\n            }\n\n            if (!component) {\n                return [];\n            }\n\n            nodes = boundedNodes.get(component);\n            nodes = $(nodes).filter(data.ctx).toArray();\n\n            return data.selector ?\n                $(data.selector, nodes).toArray() :\n                nodes;\n        },\n\n        /*eslint-enable no-unused-vars*/\n\n        /**\n         * Sets removal listener of the specified nodes.\n         *\n         * @param {(HTMLElement|Array|ArrayLike)} nodes - Nodes whose removal to track.\n         * @param {Function} fn - Callback that will be invoked when node is removed.\n         */\n        remove: function (nodes, fn) {\n            domObserver.remove(nodes, fn);\n        },\n\n        parseSelector: parseSelector\n    });\n\n    return $;\n});\n","Magento_Ui/js/lib/logger/console-output-handler.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    './levels-pool'\n], function (logLevels) {\n    'use strict';\n\n    var levels = logLevels.getLevels();\n\n    /**\n     * @param {LogFormatter} formatter\n     */\n    function ConsoleOutputHandler(formatter) {\n        /**\n         * @protected\n         * @type {LogFormatter}\n         */\n        this.formatter_ = formatter;\n    }\n\n    /**\n     * Display data of the provided entry to the console.\n     *\n     * @param {LogEntry} entry - Entry to be displayed.\n     */\n    ConsoleOutputHandler.prototype.show = function (entry) {\n        var displayString = this.formatter_.process(entry);\n\n        switch (entry.level) {\n            case levels.ERROR:\n                console.error(displayString);\n                break;\n\n            case levels.WARN:\n                console.warn(displayString);\n                break;\n\n            case levels.INFO:\n                console.info(displayString);\n                break;\n\n            case levels.DEBUG:\n                console.log(displayString);\n                break;\n        }\n    };\n\n    /**\n     * Displays the array of entries.\n     *\n     * @param {Array<LogEntry>} entries\n     */\n    ConsoleOutputHandler.prototype.dump = function (entries) {\n        entries.forEach(this.show, this);\n    };\n\n    return ConsoleOutputHandler;\n});\n","Magento_Ui/js/lib/logger/logger.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    './levels-pool'\n], function (logLevels) {\n    'use strict';\n\n    var levels = logLevels.getLevels();\n\n    /**\n     * @param {LogOutputHandler} outputHandler\n     * @param {LogEntryFactory} entryFactory\n     */\n    function Logger(outputHandler, entryFactory) {\n        /**\n         * An array of log entries.\n         *\n         * @protected\n         * @type {Array<LogEntry>}\n         */\n        this.entries_ = [];\n\n        /**\n         * Current display level.\n         *\n         * @protected\n         * @type {Number}\n         */\n        this.displayLevel_ = levels.ERROR;\n\n        /**\n         * An array of display criteria.\n         *\n         * @protected\n         * @type {Array<LogCriteria>}\n         */\n        this.displayCriteria_ = [];\n\n        /**\n         * @protected\n         * @type {LogEntryFactory}\n         */\n        this.entryFactory_ = entryFactory;\n\n        /**\n         * @protected\n         * @type {Array<LogOutputHandler>}\n         */\n        this.outputHandlers_ = [outputHandler];\n\n        this.addDisplayCriteria(this.matchesLevel_);\n    }\n\n    /**\n     * Swaps current display level with the provided one.\n     *\n     * @param {Number} level - Level's code.\n     */\n    Logger.prototype.setDisplayLevel = function (level) {\n        var levelName = logLevels.getNameByCode(level);\n\n        if (!levelName) {\n            throw new TypeError('The provided level is not defined in the levels list.');\n        }\n\n        this.displayLevel_ = level;\n    };\n\n    /**\n     * Sets up the criteria by which log entries will be filtered out from the output.\n     *\n     * @param {LogCriteria} criteria\n     */\n    Logger.prototype.addDisplayCriteria = function (criteria) {\n        this.displayCriteria_.push(criteria);\n    };\n\n    /**\n     * Removes previously defined criteria.\n     *\n     * @param {LogCriteria} criteria\n     */\n    Logger.prototype.removeDisplayCriteria = function (criteria) {\n        var index = this.displayCriteria_.indexOf(criteria);\n\n        if (~index) {\n            this.displayCriteria_.splice(index, 1);\n        }\n    };\n\n    /**\n     * @param {String} message\n     * @param {Object} [messageData]\n     * @returns {LogEntry}\n     */\n    Logger.prototype.error = function (message, messageData) {\n        return this.log_(message, levels.ERROR, messageData);\n    };\n\n    /**\n     * @param {String} message\n     * @param {Object} [messageData]\n     * @returns {LogEntry}\n     */\n    Logger.prototype.warn = function (message, messageData) {\n        return this.log_(message, levels.WARN, messageData);\n    };\n\n    /**\n     * @param {String} message\n     * @param {Object} [messageData]\n     * @returns {LogEntry}\n     */\n    Logger.prototype.info = function (message, messageData) {\n        return this.log_(message, levels.INFO, messageData);\n    };\n\n    /**\n     * @param {String} message\n     * @param {Object} [messageData]\n     * @returns {LogEntry}\n     */\n    Logger.prototype.debug = function (message, messageData) {\n        return this.log_(message, levels.DEBUG, messageData);\n    };\n\n    /**\n     * @protected\n     * @param {String} message\n     * @param {Number} level\n     * @param {Object} [messageData]\n     * @returns {LogEntry}\n     */\n    Logger.prototype.log_ = function (message, level, messageData) {\n        var entry = this.createEntry_(message, level, messageData);\n\n        this.entries_.push(entry);\n\n        if (this.matchesCriteria_(entry)) {\n            this.processOutput_(entry);\n        }\n\n        return entry;\n    };\n\n    /**\n     * @protected\n     * @param {String} message\n     * @param {Number} level\n     * @param {Object} [messageData]\n     * @returns {LogEntry}\n     */\n    Logger.prototype.createEntry_ = function (message, level, messageData) {\n        return this.entryFactory_.createEntry(message, level, messageData);\n    };\n\n    /**\n     * Returns an array of log entries that have been added to the logger.\n     *\n     * @param {LogCriteria} [criteria] - Optional filter criteria.\n     * @returns {Array<LogEntry>}\n     */\n    Logger.prototype.getEntries = function (criteria) {\n        if (criteria) {\n            return this.entries_.filter(criteria);\n        }\n\n        return this.entries_;\n    };\n\n    /**\n     * @param {LogCriteria} [criteria]\n     */\n    Logger.prototype.dump = function (criteria) {\n        var entries;\n\n        if (!criteria) {\n            criteria = this.matchesCriteria_;\n        }\n\n        entries = this.entries_.filter(criteria, this);\n\n        this.outputHandlers_.forEach(function (handler) {\n            handler.dump(entries);\n        });\n    };\n\n    /**\n     * @protected\n     * @param {LogEntry} entry\n     */\n    Logger.prototype.processOutput_ = function (entry) {\n        this.outputHandlers_.forEach(function (handler) {\n            handler.show(entry);\n        });\n    };\n\n    /**\n     * @protected\n     * @param {LogEntry} entry\n     * @returns {Boolean}\n     */\n    Logger.prototype.matchesCriteria_ = function (entry) {\n        return this.displayCriteria_.every(function (criteria) {\n            return criteria.call(this, entry);\n        }, this);\n    };\n\n    /**\n     * Checks that the level of provided entry passes the \"displayLevel_\" threshold.\n     *\n     * @protected\n     * @param {LogEntry} entry - Entry to be checked.\n     * @returns {Boolean}\n     */\n    Logger.prototype.matchesLevel_ = function (entry) {\n        return entry.level <= this.displayLevel_;\n    };\n\n    return Logger;\n});\n","Magento_Ui/js/lib/logger/console-logger.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    './logger',\n    './entry-factory',\n    './console-output-handler',\n    './formatter',\n    './message-pool',\n    './levels-pool',\n    'Magento_Ui/js/lib/core/storage/local',\n    'underscore',\n    './logger-utils'\n], function (Logger, entryFactory, ConsoleHandler, Formatter, messagePoll, levelsPoll, storage, _, LoggerUtils) {\n    'use strict';\n\n    var STORAGE_NAMESPACE = 'CONSOLE_LOGGER';\n\n    /**\n     * Singleton Logger's sub-class instance of which is configured to display its\n     * messages to the console. It also provides the support of predefined messages\n     * and persists its display level.\n     */\n    function ConsoleLogger() {\n        var formatter = new Formatter(),\n            consoleHandler = new ConsoleHandler(formatter),\n            savedLevel = storage.get(STORAGE_NAMESPACE),\n            utils = new LoggerUtils(this);\n\n        Logger.call(this, consoleHandler, entryFactory);\n\n        if (savedLevel) {\n            this.displayLevel_ = savedLevel;\n        }\n\n        this.utils = utils;\n        this.messages = messagePoll;\n        this.levels = levelsPoll.getLevels();\n    }\n\n    _.extend(ConsoleLogger, Logger);\n\n    ConsoleLogger.prototype = Object.create(Logger.prototype);\n    ConsoleLogger.prototype.constructor = ConsoleLogger;\n\n    /**\n     * Overrides parent method to save the provided display level.\n     *\n     * @override\n     */\n    ConsoleLogger.prototype.setDisplayLevel = function (level) {\n        Logger.prototype.setDisplayLevel.call(this, level);\n\n        storage.set(STORAGE_NAMESPACE, level);\n    };\n\n    /**\n     * Adds the support of predefined messages.\n     *\n     * @protected\n     * @override\n     */\n    ConsoleLogger.prototype.createEntry_ = function (message, level, data) {\n        var code;\n\n        if (messagePoll.hasMessage(message)) {\n            data = data || {};\n            code = message;\n            message = messagePoll.getMessage(code);\n\n            data.messageCode = code;\n        }\n\n        return Logger.prototype.createEntry_.call(this, message, level, data);\n    };\n\n    return new ConsoleLogger();\n});\n","Magento_Ui/js/lib/logger/entry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    './levels-pool'\n], function (logLevels) {\n    'use strict';\n\n    /**\n     * @param {String} message\n     * @param {Number} level\n     * @param {Object} [data]\n     */\n    function LogEntry(message, level, data) {\n        /**\n         * @readonly\n         * @type {Number}\n         */\n        this.timestamp = Date.now();\n\n        /**\n         * @readonly\n         * @type {Number}\n         */\n        this.level = level;\n\n        /**\n         * @readonly\n         * @type {String}\n         */\n        this.levelName = logLevels.getNameByCode(level);\n\n        /**\n         * @readonly\n         * @type {Object}\n         */\n        this.data = data;\n\n        /**\n         * @readonly\n         * @type {String}\n         */\n        this.message = message;\n    }\n\n    return LogEntry;\n});\n","Magento_Ui/js/lib/logger/levels-pool.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    var LEVELS,\n        CODE_MAP;\n\n    LEVELS = {\n        NONE: 0,\n        ERROR: 1,\n        WARN: 2,\n        INFO: 3,\n        DEBUG: 4,\n        ALL: 5\n    };\n\n    CODE_MAP = _.invert(LEVELS);\n\n    return {\n        /**\n         * Returns the list of available log levels.\n         *\n         * @returns {Object}\n         */\n        getLevels: function () {\n            return LEVELS;\n        },\n\n        /**\n         * Returns name of the log level that matches to the provided code.\n         *\n         * @returns {String}\n         */\n        getNameByCode: function (code) {\n            return CODE_MAP[code];\n        }\n    };\n});\n","Magento_Ui/js/lib/logger/formatter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'moment',\n    'mage/utils/template'\n], function (moment, mageTemplate) {\n    'use strict';\n\n    /**\n     * @param {String} dateFormat\n     * @param {String} template\n     */\n    function LogFormatter(dateFormat, template) {\n        /**\n         * @protected\n         * @type {String}\n         */\n        this.dateFormat_ = 'YYYY-MM-DD hh:mm:ss';\n\n        /**\n         * @protected\n         * @type {String}\n         */\n        this.template_ = '[${ $.date }] [${ $.entry.levelName }] ${ $.message }';\n\n        if (dateFormat) {\n            this.dateFormat_ = dateFormat;\n        }\n\n        if (template) {\n            this.template_ = template;\n        }\n    }\n\n    /**\n     * @param {LogEntry} entry\n     * @returns {String}\n     */\n    LogFormatter.prototype.process = function (entry) {\n        var message = mageTemplate.template(entry.message, entry.data),\n            date = moment(entry.timestamp).format(this.dateFormat_);\n\n        return mageTemplate.template(this.template_, {\n            date: date,\n            entry: entry,\n            message: message\n        });\n    };\n\n    return LogFormatter;\n});\n","Magento_Ui/js/lib/logger/entry-factory.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    './entry'\n], function (LogEntry) {\n    'use strict';\n\n    return {\n        /**\n         * @param {String} message\n         * @param {Number} level\n         * @param {Object} [messageData]\n         * @returns {LogEntry}\n         */\n        createEntry: function (message, level, messageData) {\n            return new LogEntry(message, level, messageData);\n        }\n    };\n});\n","Magento_Ui/js/lib/logger/message-pool.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    var MESSAGES = {\n        templateStartLoading:\n            'The \"${ $.template }\" template requested by  the \"${$.component}\" component started loading.',\n        templateLoadedFromServer:\n            'The \"${ $.template }\" template requested by the \"${$.component}\" component  was loaded from server.\"',\n        templateLoadedFromCache:\n            'The \"${ $.template }\" template  requested by the \"${$.component}\" component was loaded from cache.\"',\n        templateLoadingFail: 'Failed to load the \"${ $.template }\" template requested by \"${$.component}\".',\n        componentStartInitialization:\n            'Component \"${$.component}\" start initialization with instance name \"${$.componentName}\".',\n        componentStartLoading: ' Started loading the \"${$.component}\" component.',\n        componentFinishLoading: 'The \"${$.component}\" component was loaded.',\n        componentLoadingFail: 'Failed to load the \"${$.component}\" component.',\n        depsLoadingFail: 'Could not get the declared \"${$.deps}\" dependency for the \"${$.component}\" instance.',\n        depsStartRequesting: 'Requesting the \"${$.deps}\" dependency for the \"${$.component}\" instance.',\n        depsFinishRequesting: 'The \"${$.deps}\" dependency for the \"${$.component}\" instance was received.',\n        requestingComponent: 'Requesting the \"${$.component}\" component.',\n        requestingComponentIsLoaded: 'The requested \"${$.component}\" component was received.',\n        requestingComponentIsFailed: 'Could not get the requested \"${$.component}\" component.'\n    };\n\n    return {\n        /**\n         * Returns message that matches the provided code.\n         *\n         * @param {String} code - Message's identifier\n         * @returns {String}\n         */\n        getMessage: function (code) {\n            return MESSAGES[code];\n        },\n\n        /**\n         * Adds a new message to the poll.\n         *\n         * @param {String} code - Message's identifier.\n         * @param {String} message - Text of the message\n         */\n        addMessage: function (code, message) {\n            MESSAGES[code] = message;\n        },\n\n        /**\n         * Tells whether message with provide code exists in the poll.\n         *\n         * @param {String} code - Message's identifier.\n         * @returns {Boolean}\n         */\n        hasMessage: function (code) {\n            return MESSAGES.hasOwnProperty(code);\n        }\n    };\n});\n","Magento_Ui/js/lib/logger/logger-utils.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     * Utils methods for logger\n     * @param {Logger} logger\n     */\n    function LogUtils(logger) {\n        this.logger = logger;\n\n    }\n\n    /**\n     * Method for logging asynchronous operations\n     * @param {Promise} promise\n     * @param {Object} config\n     */\n    LogUtils.prototype.asyncLog = function (promise, config) {\n        var levels,\n            messages,\n            wait;\n\n        config = config || {};\n        levels = config.levels || this.createLevels();\n        messages = config.messages || this.createMessages();\n        wait = config.wait || 5000;\n\n        this.logger[levels.requested](messages.requested, config.data);\n        setTimeout(function () {\n            promise.state() === 'pending' ?\n                this.logger[levels.failed](messages.failed, config.data) :\n                this.logger[levels.loaded](messages.loaded, config.data);\n        }.bind(this), wait);\n    };\n\n    /**\n     * Method that creates object of messages\n     * @param {String} requested - log message that showing that request for class is started\n     * @param {String} loaded - log message that show when requested class is loaded\n     * @param {String} failed - log message that show when requested class is failed\n     * @returns {Object}\n     */\n    LogUtils.prototype.createMessages = function (requested, loaded, failed) {\n        return {\n            requested: requested || '',\n            loaded: loaded || '',\n            failed: failed || ''\n        };\n    };\n\n    /**\n     * Method that creates object of log levels\n     * @param {String} requested - log message that showing that request for class is started\n     * @param {String} loaded - log message that show when requested class is loaded\n     * @param {String} failed - log message that show when requested class is failed\n     * @returns {Object}\n     */\n    LogUtils.prototype.createLevels = function (requested, loaded, failed) {\n        return {\n            requested: requested || 'info',\n            loaded: loaded || 'info',\n            failed: failed || 'warn'\n        };\n    };\n\n    return LogUtils;\n});\n","Magento_Ui/js/lib/core/events.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'underscore'\n], function (ko, _) {\n    'use strict';\n\n    var eventsMap = new WeakMap();\n\n    /**\n     * Returns events map or a specific event\n     * data associated with a provided object.\n     *\n     * @param {Object} obj - Key in the events weakmap.\n     * @param {String} [name] - Name of the event.\n     * @returns {Map|Array|Boolean}\n     */\n    function getEvents(obj, name) {\n        var events = eventsMap.get(obj);\n\n        if (!events) {\n            return false;\n        }\n\n        return name ? events.get(name) : events;\n    }\n\n    /**\n     * Adds new event handler.\n     *\n     * @param {Object} obj - Key in the events weakmap.\n     * @param {String} ns - Callback namespace.\n     * @param {Function} callback - Event callback.\n     * @param {String} name - Name of the event.\n     */\n    function addHandler(obj, ns, callback, name) {\n        var events      = getEvents(obj),\n            observable,\n            data;\n\n        observable = !ko.isObservable(obj[name]) ?\n            ko.getObservable(obj, name) :\n            obj[name];\n\n        if (observable) {\n            observable.subscribe(callback);\n\n            return;\n        }\n\n        if (!events) {\n            events = new Map();\n\n            eventsMap.set(obj, events);\n        }\n\n        data = {\n            callback: callback,\n            ns: ns\n        };\n\n        events.has(name) ?\n            events.get(name).push(data) :\n            events.set(name, [data]);\n    }\n\n    /**\n     * Invokes provided callbacks with a specified arguments.\n     *\n     * @param {Array} handlers\n     * @param {Array} args\n     * @returns {Boolean}\n     */\n    function trigger(handlers, args) {\n        var bubble = true,\n            callback;\n\n        handlers.forEach(function (handler) {\n            callback = handler.callback;\n\n            if (callback.apply(null, args) === false) {\n                bubble = false;\n            }\n        });\n\n        return bubble;\n    }\n\n    return {\n\n        /**\n         * Calls callback when name event is triggered.\n         * @param  {String}   events\n         * @param  {Function} callback\n         * @param  {Function} ns\n         * @return {Object} reference to this\n         */\n        on: function (events, callback, ns) {\n            var iterator;\n\n            if (arguments.length < 2) {\n                ns = callback;\n            }\n\n            iterator = addHandler.bind(null, this, ns);\n\n            _.isObject(events) ?\n                _.each(events, iterator) :\n                iterator(callback, events);\n\n            return this;\n        },\n\n        /**\n         * Removed callback from listening to target event\n         * @param  {String} ns\n         * @return {Object} reference to this\n         */\n        off: function (ns) {\n            var storage = getEvents(this);\n\n            if (!storage) {\n                return this;\n            }\n\n            storage.forEach(function (handlers, name) {\n                handlers = handlers.filter(function (handler) {\n                    return !ns ? false : handler.ns !== ns;\n                });\n\n                handlers.length ?\n                    storage.set(name, handlers) :\n                    storage.delete(name);\n            });\n\n            return this;\n        },\n\n        /**\n         * Triggers event and executes all attached callbacks.\n         *\n         * @param {String} name - Name of the event to be triggered.\n         * @returns {Boolean}\n         */\n        trigger: function (name) {\n            var handlers,\n                args;\n\n            handlers = getEvents(this, name),\n            args = _.toArray(arguments).slice(1);\n\n            if (!handlers || !name) {\n                return true;\n            }\n\n            return trigger(handlers, args);\n        }\n    };\n});\n","Magento_Ui/js/lib/core/class.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    'mage/utils/wrapper'\n], function (_, utils, wrapper) {\n    'use strict';\n\n    var Class;\n\n    /**\n     * Returns property of an object if\n     * it's his own property.\n     *\n     * @param {Object} obj - Object whose property should be retrieved.\n     * @param {String} prop - Name of the property.\n     * @returns {*} Value of the property or false.\n     */\n    function getOwn(obj, prop) {\n        return _.isObject(obj) && obj.hasOwnProperty(prop) && obj[prop];\n    }\n\n    /**\n     * Creates constructor function which allows\n     * initialization without usage of a 'new' operator.\n     *\n     * @param {Object} protoProps - Prototypal properties of a new constructor.\n     * @param {Function} constructor\n     * @returns {Function} Created constructor.\n     */\n    function createConstructor(protoProps, constructor) {\n        var UiClass = constructor;\n\n        if (!UiClass) {\n\n            /**\n             * Default constructor function.\n             */\n            UiClass = function () {\n                var obj = this;\n\n                if (!_.isObject(obj) || Object.getPrototypeOf(obj) !== UiClass.prototype) {\n                    obj = Object.create(UiClass.prototype);\n                }\n\n                obj.initialize.apply(obj, arguments);\n\n                return obj;\n            };\n        }\n\n        UiClass.prototype = protoProps;\n        UiClass.prototype.constructor = UiClass;\n\n        return UiClass;\n    }\n\n    Class = createConstructor({\n\n        /**\n         * Entry point to the initialization of constructor's instance.\n         *\n         * @param {Object} [options={}]\n         * @returns {Class} Chainable.\n         */\n        initialize: function (options) {\n            this.initConfig(options);\n\n            return this;\n        },\n\n        /**\n         * Recursively extends data specified in constructors' 'defaults'\n         * property with provided options object. Evaluates resulting\n         * object using string templates (see: mage/utils/template.js).\n         *\n         * @param {Object} [options={}]\n         * @returns {Class} Chainable.\n         */\n        initConfig: function (options) {\n            var defaults    = this.constructor.defaults,\n                config      = utils.extend({}, defaults, options || {}),\n                ignored     = config.ignoreTmpls || {},\n                cached      = utils.omit(config, ignored);\n\n            config = utils.template(config, this, false, true);\n\n            _.each(cached, function (value, key) {\n                utils.nested(config, key, value);\n            });\n\n            return _.extend(this, config);\n        }\n    });\n\n    _.extend(Class, {\n        defaults: {\n            ignoreTmpls: {\n                templates: true\n            }\n        },\n\n        /**\n         * Creates new constructor based on a current prototype properties,\n         * extending them with properties specified in 'exender' object.\n         *\n         * @param {Object} [extender={}]\n         * @returns {Function} New constructor.\n         */\n        extend: function (extender) {\n            var parent      = this,\n                parentProto = parent.prototype,\n                childProto  = Object.create(parentProto),\n                child       = createConstructor(childProto, getOwn(extender, 'constructor')),\n                defaults;\n\n            extender = extender || {};\n            defaults = extender.defaults;\n\n            delete extender.defaults;\n\n            _.each(extender, function (method, name) {\n                childProto[name] = wrapper.wrapSuper(parentProto[name], method);\n            });\n\n            child.defaults = utils.extend({}, parent.defaults || {});\n\n            if (defaults) {\n                utils.extend(child.defaults, defaults);\n                extender.defaults = defaults;\n            }\n\n            return _.extend(child, {\n                __super__:  parentProto,\n                extend:     parent.extend\n            });\n        }\n    });\n\n    return Class;\n});\n","Magento_Ui/js/lib/core/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    'uiElement'\n], function (_, utils, registry, Element) {\n    'use strict';\n\n    /**\n     * Removes non plain object items from the specified array.\n     *\n     * @param {Array} container - Array whose value should be filtered.\n     * @returns {Array}\n     */\n    function compact(container) {\n        return _.values(container).filter(utils.isObject);\n    }\n\n    /**\n     * Defines index of an item in a specified container.\n     *\n     * @param {*} item - Item whose index should be defined.\n     * @param {Array} container - Container upon which to perform search.\n     * @returns {Number}\n     */\n    function _findIndex(item, container) {\n        var index = _.findKey(container, function (value) {\n            return value === item;\n        });\n\n        if (typeof index === 'undefined') {\n            index = _.findKey(container, function (value) {\n                return value && value.name === item;\n            });\n        }\n\n        return typeof index === 'undefined' ? -1 : index;\n    }\n\n    /**\n     * Inserts specified item into container at a specified position.\n     *\n     * @param {*} item - Item to be inserted into container.\n     * @param {Array} container - Container of items.\n     * @param {*} [position=-1] - Position at which item should be inserted.\n     *      Position can represent:\n     *          - specific index in container\n     *          - item which might already be present in container\n     *          - structure with one of these properties: after, before\n     * @returns {Boolean|*}\n     *      - true if element has changed its' position\n     *      - false if nothing has changed\n     *      - inserted value if it wasn't present in container\n     */\n    function _insertAt(item, container, position) {\n        var currentIndex = _findIndex(item, container),\n            newIndex,\n            target;\n\n        if (typeof position === 'undefined') {\n            position = -1;\n        } else if (typeof position === 'string') {\n            position = isNaN(+position) ? position : +position;\n        }\n\n        newIndex = position;\n\n        if (~currentIndex) {\n            target = container.splice(currentIndex, 1)[0];\n\n            if (typeof item === 'string') {\n                item = target;\n            }\n        }\n\n        if (typeof position !== 'number') {\n            target = position.after || position.before || position;\n\n            newIndex = _findIndex(target, container);\n\n            if (~newIndex && (position.after || newIndex >= currentIndex)) {\n                newIndex++;\n            }\n        }\n\n        if (newIndex < 0) {\n            newIndex += container.length + 1;\n        }\n\n        container[newIndex] ?\n            container.splice(newIndex, 0, item) :\n            container[newIndex] = item;\n\n        return !~currentIndex ? item : currentIndex !== newIndex;\n    }\n\n    return Element.extend({\n        defaults: {\n            template: 'ui/collection',\n            _elems: [],\n            ignoreTmpls: {\n                childDefaults: true\n            }\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Model} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe({\n                    elems: []\n                });\n\n            return this;\n        },\n\n        /**\n         * Called when another element was added to current component.\n         *\n         * @param {Object} elem - Instance of an element that was added.\n         * @returns {Collection} Chainable.\n         */\n        initElement: function (elem) {\n            elem.initContainer(this);\n\n            return this;\n        },\n\n        /**\n         * Returns instance of a child found by provided index.\n         *\n         * @param {String} index - Index of a child.\n         * @returns {Object}\n         */\n        getChild: function (index) {\n            return _.findWhere(this.elems(), {\n                index: index\n            });\n        },\n\n        /**\n         * Requests specified components to insert\n         * them into 'elems' array starting from provided position.\n         *\n         * @param {(String|Array)} elems - Name of the component to insert.\n         * @param {Number} [position=-1] - Position at which to insert elements.\n         * @returns {Collection} Chainable.\n         */\n        insertChild: function (elems, position) {\n            var container   = this._elems,\n                insert      = this._insert.bind(this),\n                update;\n\n            if (!Array.isArray(elems)) {\n                elems = [elems];\n            }\n\n            elems.map(function (item) {\n                return item.elem ?\n                    _insertAt(item.elem, container, item.position) :\n                    _insertAt(item, container, position);\n            }).forEach(function (item) {\n                if (item === true) {\n                    update = true;\n                } else if (_.isString(item)) {\n                    registry.get(item, insert);\n                } else if (utils.isObject(item)) {\n                    insert(item);\n                }\n            });\n\n            if (update) {\n                this._updateCollection();\n            }\n\n            return this;\n        },\n\n        /**\n         * Removes specified child from collection.\n         *\n         * @param {(Object|String)} elem - Child or index of a child to be removed.\n         * @param {Boolean} skipUpdate - skip collection update when element to be destroyed.\n         *\n         * @returns {Collection} Chainable.\n         */\n        removeChild: function (elem, skipUpdate) {\n            if (_.isString(elem)) {\n                elem = this.getChild(elem);\n            }\n\n            if (elem) {\n                utils.remove(this._elems, elem);\n\n                if (!skipUpdate) {\n                    this._updateCollection();\n                }\n            }\n\n            return this;\n        },\n\n        /**\n         * Destroys collection children with its' elements.\n         */\n        destroyChildren: function () {\n            this.elems.each(function (elem) {\n                elem.destroy(true);\n            });\n\n            this._updateCollection();\n        },\n\n        /**\n         * Clear data. Call method \"clear\"\n         * in child components\n         *\n         * @returns {Object} Chainable.\n         */\n        clear: function () {\n            var elems = this.elems();\n\n            _.each(elems, function (elem) {\n                if (_.isFunction(elem.clear)) {\n                    elem.clear();\n                }\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Checks if specified child exists in collection.\n         *\n         * @param {String} index - Index of a child.\n         * @returns {Boolean}\n         */\n        hasChild: function (index) {\n            return !!this.getChild(index);\n        },\n\n        /**\n         * Creates 'async' wrapper for the specified child\n         * using uiRegistry 'async' method and caches it\n         * in a '_requested' components  object.\n         *\n         * @param {String} index - Index of a child.\n         * @returns {Function} Async module wrapper.\n         */\n        requestChild: function (index) {\n            var name = this.formChildName(index);\n\n            return this.requestModule(name);\n        },\n\n        /**\n         * Creates complete child name based on a provided index.\n         *\n         * @param {String} index - Index of a child.\n         * @returns {String}\n         */\n        formChildName: function (index) {\n            return this.name + '.' + index;\n        },\n\n        /**\n         * Retrieves requested region.\n         * Creates region if it was not created yet\n         *\n         * @returns {ObservableArray}\n         */\n        getRegion: function (name) {\n            var regions = this.regions = this.regions || {};\n\n            if (!regions[name]) {\n                regions[name] = [];\n\n                this.observe.call(regions, name);\n            }\n\n            return regions[name];\n        },\n\n        /**\n         * Checks if the specified region has any elements\n         * associated with it.\n         *\n         * @param {String} name\n         * @returns {Boolean}\n         */\n        regionHasElements: function (name) {\n            var region = this.getRegion(name);\n\n            return region().length > 0;\n        },\n\n        /**\n         * Replaces specified regions' data with a provided one.\n         * Creates region if it was not created yet.\n         *\n         * @param {Array} items - New regions' data.\n         * @param {String} name - Name of the region.\n         * @returns {Collection} Chainable.\n         */\n        updateRegion: function (items, name) {\n            this.getRegion(name)(items);\n\n            return this;\n        },\n\n        /**\n         * Destroys collection along with its' elements.\n         */\n        destroy: function () {\n            this._super();\n\n            this.elems.each('destroy');\n        },\n\n        /**\n         * Inserts provided component into 'elems' array at a specified position.\n         * @private\n         *\n         * @param {Object} elem - Element to insert.\n         */\n        _insert: function (elem) {\n            var index = _.findKey(this._elems, function (value) {\n                return value === elem.name;\n            });\n\n            if (typeof index !== 'undefined') {\n                this._elems[index] = elem;\n            }\n\n            this._updateCollection()\n                .initElement(elem);\n        },\n\n        /**\n         * Synchronizes multiple elements arrays with a core '_elems' container.\n         * Performs elemets grouping by theirs 'displayArea' property.\n         * @private\n         *\n         * @returns {Collection} Chainable.\n         */\n        _updateCollection: function () {\n            var _elems = compact(this._elems),\n                grouped;\n\n            grouped = _elems.filter(function (elem) {\n                return elem.displayArea && _.isString(elem.displayArea);\n            });\n            grouped = _.groupBy(grouped, 'displayArea');\n\n            _.each(grouped, this.updateRegion, this);\n\n            _.each(this.regions, function (items) {\n                var hasObsoleteComponents = items().length && !_.intersection(_elems, items()).length;\n\n                if (hasObsoleteComponents) {\n                    items.removeAll();\n                }\n            });\n\n            this.elems(_elems);\n\n            return this;\n        },\n\n        /**\n         * Tries to call specified method of a current component,\n         * otherwise delegates attempt to its' children.\n         *\n         * @param {String} target - Name of the method.\n         * @param {...*} parameters - Arguments that will be passed to method.\n         * @returns {*} Result of the method calls.\n         */\n        delegate: function (target) {\n            var args = _.toArray(arguments);\n\n            target = this[target];\n\n            if (_.isFunction(target)) {\n                return target.apply(this, args.slice(1));\n            }\n\n            return this._delegate(args);\n        },\n\n        /**\n         * Calls 'delegate' method of all of it's children components.\n         * @private\n         *\n         * @param {Array} args - An array of arguments to pass to the next delegation call.\n         * @returns {Array} An array of delegation results.\n         */\n        _delegate: function (args) {\n            var result;\n\n            result = this.elems.map(function (elem) {\n                var target;\n\n                if (!_.isFunction(elem.delegate)) {\n                    target = elem[args[0]];\n\n                    if (_.isFunction(target)) {\n                        return target.apply(elem, args.slice(1));\n                    }\n                } else {\n                    return elem.delegate.apply(elem, args);\n                }\n            });\n\n            return _.flatten(result);\n        }\n    });\n});\n","Magento_Ui/js/lib/core/storage/local.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore',\n    'uiRegistry',\n    'mageUtils',\n    'uiEvents'\n], function (_, registry, utils, EventsBus) {\n    'use strict';\n\n    var root = 'appData',\n        localStorage,\n        hasSupport,\n        storage;\n\n    /**\n     * Flag which indicates whether localStorage is supported.\n     */\n    hasSupport = (function () {\n        var key = '_storageSupported';\n\n        try {\n            localStorage = window.localStorage;\n            localStorage.setItem(key, 'true');\n\n            if (localStorage.getItem(key) === 'true') {\n                localStorage.removeItem(key);\n\n                return true;\n            }\n\n            return false;\n        } catch (e) {\n            return false;\n        }\n    })();\n\n    if (!hasSupport) {\n        localStorage = {\n            _data: {},\n\n            /**\n             * Sets value of the specified item.\n             *\n             * @param {String} key - Key of the property.\n             * @param {*} value - Properties' value.\n             */\n            setItem: function (key, value) {\n                this._data[key] = value + '';\n            },\n\n            /**\n             * Retrieves specified item.\n             *\n             * @param {String} key - Key of the property to be retrieved.\n             */\n            getItem: function (key) {\n                return this._data[key];\n            },\n\n            /**\n             * Removes specified item.\n             *\n             * @param {String} key - Key of the property to be removed.\n             */\n            removeItem: function (key) {\n                delete this._data[key];\n            },\n\n            /**\n             * Removes all items.\n             */\n            clear: function () {\n                this._data = {};\n            }\n        };\n    }\n\n    /**\n     * Extracts and parses data stored in localStorage by the\n     * key specified in 'root' variable.\n     *\n     * @returns {Object}\n     */\n    function getRoot() {\n        var data = localStorage.getItem(root),\n            result = {};\n\n        if (!_.isNull(data) && typeof data != 'undefined') {\n            result = JSON.parse(data);\n        }\n\n        return result;\n    }\n\n    /**\n     * Writes provided data to the localStorage.\n     *\n     * @param {*} data - Data to be stored.\n     */\n    function setRoot(data) {\n        localStorage.setItem(root, JSON.stringify(data));\n    }\n\n    /**\n     * Provides methods to work with a localStorage\n     * as a single nested structure.\n     */\n    storage = _.extend({\n\n        /**\n         * Retrieves value of the specified property.\n         *\n         * @param {String} path - Path to the property.\n         *\n         * @example Retrieving data.\n         *      localStorage =>\n         *          'appData' => '\n         *              \"one\": {\"two\": \"three\"}\n         *          '\n         *      storage.get('one.two')\n         *      => \"three\"\n         *\n         *      storage.get('one')\n         *      => {\"two\": \"three\"}\n         */\n        get: function (path) {\n            var data = getRoot();\n\n            return utils.nested(data, path);\n        },\n\n        /**\n         * Sets specified data to the localStorage.\n         *\n         * @param {String} path - Path of the property.\n         * @param {*} value - Value of the property.\n         *\n         * @example Setting data.\n         *      storage.set('one.two', 'four');\n         *      => localStorage =>\n         *          'appData' => '\n         *              \"one\": {\"two\": \"four\"}\n         *          '\n         */\n        set: function (path, value) {\n            var data = getRoot();\n\n            utils.nested(data, path, value);\n\n            setRoot(data);\n        },\n\n        /**\n         * Removes specified data from the localStorage.\n         *\n         * @param {String} path - Path to the property that should be removed.\n         *\n         * @example Removing data.\n         *      storage.remove('one.two', 'four');\n         *      => localStorage =>\n         *          'appData' => '\n         *              \"one\": {}\n         *          '\n         */\n        remove: function (path) {\n            var data = getRoot();\n\n            utils.nestedRemove(data, path);\n\n            setRoot(data);\n        }\n    }, EventsBus);\n\n    registry.set('localStorage', storage);\n\n    return storage;\n});\n","Magento_Ui/js/lib/core/element/element.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    'underscore',\n    'mageUtils',\n    'uiRegistry',\n    'uiEvents',\n    'uiClass',\n    './links',\n    '../storage/local'\n], function (ko, _, utils, registry, Events, Class, links) {\n    'use strict';\n\n    var Element;\n\n    /**\n     * Creates observable property using knockouts'\n     * 'observableArray' or 'observable' methods,\n     * depending on a type of 'value' parameter.\n     *\n     * @param {Object} obj - Object to whom property belongs.\n     * @param {String} key - Key of the property.\n     * @param {*} value - Initial value.\n     */\n    function observable(obj, key, value) {\n        var method = Array.isArray(value) ? 'observableArray' : 'observable';\n\n        if (_.isFunction(obj[key]) && !ko.isObservable(obj[key])) {\n            return;\n        }\n\n        if (ko.isObservable(value)) {\n            value = value();\n        }\n\n        ko.isObservable(obj[key]) ?\n            obj[key](value) :\n            obj[key] = ko[method](value);\n    }\n\n    /**\n     * Creates observable property using 'track' method.\n     *\n     * @param {Object} obj - Object to whom property belongs.\n     * @param {String} key - Key of the property.\n     * @param {*} value - Initial value.\n     */\n    function accessor(obj, key, value) {\n        if (_.isFunction(obj[key]) || ko.isObservable(obj[key])) {\n            return;\n        }\n\n        obj[key] = value;\n\n        if (!ko.es5.isTracked(obj, key)) {\n            ko.track(obj, [key]);\n        }\n    }\n\n    Element = _.extend({\n        defaults: {\n            _requested: {},\n            containers: [],\n            exports: {},\n            imports: {},\n            links: {},\n            listens: {},\n            name: '',\n            ns: '${ $.name.split(\".\")[0] }',\n            provider: '',\n            registerNodes: true,\n            source: null,\n            statefull: {},\n            template: '',\n            tracks: {},\n            storageConfig: {\n                provider: 'localStorage',\n                namespace: '${ $.name }',\n                path: '${ $.storageConfig.provider }:${ $.storageConfig.namespace }'\n            },\n            maps: {\n                imports: {},\n                exports: {}\n            },\n            modules: {\n                storage: '${ $.storageConfig.provider }'\n            }\n        },\n\n        /**\n         * Initializes model instance.\n         *\n         * @returns {Element} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .initObservable()\n                .initModules()\n                .initStatefull()\n                .initLinks()\n                .initUnique();\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Element} Chainable.\n         */\n        initObservable: function () {\n            _.each(this.tracks, function (enabled, key) {\n                if (enabled) {\n                    this.track(key);\n                }\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Parses 'modules' object and creates\n         * async wrappers for specified components.\n         *\n         * @returns {Element} Chainable.\n         */\n        initModules: function () {\n            _.each(this.modules, function (name, property) {\n                if (name) {\n                    this[property] = this.requestModule(name);\n                }\n            }, this);\n\n            if (!_.isFunction(this.source)) {\n                this.source = registry.get(this.provider);\n            }\n\n            return this;\n        },\n\n        /**\n         * Called when current element was injected to another component.\n         *\n         * @param {Object} parent - Instance of a 'parent' component.\n         * @returns {Collection} Chainable.\n         */\n        initContainer: function (parent) {\n            this.containers.push(parent);\n\n            return this;\n        },\n\n        /**\n         * Initializes statefull properties\n         * based on the keys of 'statefull' object.\n         *\n         * @returns {Element} Chainable.\n         */\n        initStatefull: function () {\n            _.each(this.statefull, function (path, key) {\n                if (path) {\n                    this.setStatefull(key, path);\n                }\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Initializes links between properties.\n         *\n         * @returns {Element} Chainbale.\n         */\n        initLinks: function () {\n            return this.setListeners(this.listens)\n                       .setLinks(this.links, 'imports')\n                       .setLinks(this.links, 'exports')\n                       .setLinks(this.exports, 'exports')\n                       .setLinks(this.imports, 'imports');\n        },\n\n        /**\n         * Initializes listeners of the unique property.\n         *\n         * @returns {Element} Chainable.\n         */\n        initUnique: function () {\n            var update = this.onUniqueUpdate.bind(this),\n                uniqueNs = this.uniqueNs;\n\n            this.hasUnique = this.uniqueProp && uniqueNs;\n\n            if (this.hasUnique) {\n                this.source.on(uniqueNs, update, this.name);\n            }\n\n            return this;\n        },\n\n        /**\n         * Makes specified property to be stored automatically.\n         *\n         * @param {String} key - Name of the property\n         *      that will be stored.\n         * @param {String} [path=key] - Path to the property in storage.\n         * @returns {Element} Chainable.\n         */\n        setStatefull: function (key, path) {\n            var link = {};\n\n            path        = !_.isString(path) || !path ? key : path;\n            link[key]   = this.storageConfig.path + '.' + path;\n\n            this.setLinks(link, 'imports')\n                .setLinks(link, 'exports');\n\n            return this;\n        },\n\n        /**\n         * Updates property specified in uniqueNs\n         * if elements' unique property is set to 'true'.\n         *\n         * @returns {Element} Chainable.\n         */\n        setUnique: function () {\n            var property = this.uniqueProp;\n\n            if (this[property]()) {\n                this.source.set(this.uniqueNs, this.name);\n            }\n\n            return this;\n        },\n\n        /**\n         * Creates 'async' wrapper for the specified component\n         * using uiRegistry 'async' method and caches it\n         * in a '_requested' components  object.\n         *\n         * @param {String} name - Name of requested component.\n         * @returns {Function} Async module wrapper.\n         */\n        requestModule: function (name) {\n            var requested = this._requested;\n\n            if (!requested[name]) {\n                requested[name] = registry.async(name);\n            }\n\n            return requested[name];\n        },\n\n        /**\n         * Returns path to elements' template.\n         *\n         * @returns {String}\n         */\n        getTemplate: function () {\n            return this.template;\n        },\n\n        /**\n         * Checks if template was specified for an element.\n         *\n         * @returns {Boolean}\n         */\n        hasTemplate: function () {\n            return !!this.template;\n        },\n\n        /**\n         * Returns value of the nested property.\n         *\n         * @param {String} path - Path to the property.\n         * @returns {*} Value of the property.\n         */\n        get: function (path) {\n            return utils.nested(this, path);\n        },\n\n        /**\n         * Sets provided value as a value of the specified nested property.\n         * Triggers changes notifications, if value has mutated.\n         *\n         * @param {String} path - Path to property.\n         * @param {*} value - New value of the property.\n         * @returns {Element} Chainable.\n         */\n        set: function (path, value) {\n            var data = this.get(path),\n                diffs;\n\n            diffs = !_.isFunction(data) && !this.isTracked(path) ?\n                utils.compare(data, value, path) :\n                false;\n\n            utils.nested(this, path, value);\n\n            if (diffs) {\n                this._notifyChanges(diffs);\n            }\n\n            return this;\n        },\n\n        /**\n         * Removes nested property from the object.\n         *\n         * @param {String} path - Path to the property.\n         * @returns {Element} Chainable.\n         */\n        remove: function (path) {\n            var data = utils.nested(this, path),\n                diffs;\n\n            if (_.isUndefined(data) || _.isFunction(data)) {\n                return this;\n            }\n\n            diffs = utils.compare(data, undefined, path);\n\n            utils.nestedRemove(this, path);\n\n            this._notifyChanges(diffs);\n\n            return this;\n        },\n\n        /**\n         * Creates observable properties for the current object.\n         *\n         * If 'useTrack' flag is set to 'true' then each property will be\n         * created with a ES5 get/set accessor descriptors, instead of\n         * making them an observable functions.\n         * See 'knockout-es5' library for more information.\n         *\n         * @param {Boolean} [useAccessors=false] - Whether to create an\n         *      observable function or to use property accesessors.\n         * @param {(Object|String|Array)} properties - List of observable properties.\n         * @returns {Element} Chainable.\n         *\n         * @example Sample declaration and equivalent knockout methods.\n         *      this.key = 'value';\n         *      this.array = ['value'];\n         *\n         *      this.observe(['key', 'array']);\n         *      =>\n         *          this.key = ko.observable('value');\n         *          this.array = ko.observableArray(['value']);\n         *\n         * @example Another syntaxes of the previous example.\n         *      this.observe({\n         *          key: 'value',\n         *          array: ['value']\n         *      });\n         */\n        observe: function (useAccessors, properties) {\n            var model = this,\n                trackMethod;\n\n            if (typeof useAccessors !== 'boolean') {\n                properties   = useAccessors;\n                useAccessors = false;\n            }\n\n            trackMethod = useAccessors ? accessor : observable;\n\n            if (_.isString(properties)) {\n                properties = properties.split(' ');\n            }\n\n            if (Array.isArray(properties)) {\n                properties.forEach(function (key) {\n                    trackMethod(model, key, model[key]);\n                });\n            } else if (typeof properties === 'object') {\n                _.each(properties, function (value, key) {\n                    trackMethod(model, key, value);\n                });\n            }\n\n            return this;\n        },\n\n        /**\n         * Delegates call to 'observe' method but\n         * with a predefined 'useAccessors' flag.\n         *\n         * @param {(String|Array|Object)} properties - List of observable properties.\n         * @returns {Element} Chainable.\n         */\n        track: function (properties) {\n            this.observe(true, properties);\n\n            return this;\n        },\n\n        /**\n         * Checks if specified property is tracked.\n         *\n         * @param {String} property - Property to be checked.\n         * @returns {Boolean}\n         */\n        isTracked: function (property) {\n            return ko.es5.isTracked(this, property);\n        },\n\n        /**\n         * Invokes subscribers for the provided changes.\n         *\n         * @param {Object} diffs - Object with changes descriptions.\n         * @returns {Element} Chainable.\n         */\n        _notifyChanges: function (diffs) {\n            diffs.changes.forEach(function (change) {\n                this.trigger(change.path, change.value, change);\n            }, this);\n\n            _.each(diffs.containers, function (changes, name) {\n                var value = utils.nested(this, name);\n\n                this.trigger(name, value, changes);\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Extracts all stored data and sets it to element.\n         *\n         * @returns {Element} Chainable.\n         */\n        restore: function () {\n            var ns = this.storageConfig.namespace,\n                storage = this.storage();\n\n            if (storage) {\n                utils.extend(this, storage.get(ns));\n            }\n\n            return this;\n        },\n\n        /**\n         * Stores value of the specified property in components' storage module.\n         *\n         * @param {String} property\n         * @param {*} [data=this[property]]\n         * @returns {Element} Chainable.\n         */\n        store: function (property, data) {\n            var ns = this.storageConfig.namespace,\n                path = utils.fullPath(ns, property);\n\n            if (arguments.length < 2) {\n                data = this.get(property);\n            }\n\n            this.storage('set', path, data);\n\n            return this;\n        },\n\n        /**\n         * Extracts specified property from storage.\n         *\n         * @param {String} [property] - Name of the property\n         *      to be extracted. If not specified then all of the\n         *      stored will be returned.\n         * @returns {*}\n         */\n        getStored: function (property) {\n            var ns = this.storageConfig.namespace,\n                path = utils.fullPath(ns, property),\n                storage = this.storage(),\n                data;\n\n            if (storage) {\n                data = storage.get(path);\n            }\n\n            return data;\n        },\n\n        /**\n         * Removes stored property.\n         *\n         * @param {String} property - Property to be removed from storage.\n         * @returns {Element} Chainable.\n         */\n        removeStored: function (property) {\n            var ns = this.storageConfig.namespace,\n                path = utils.fullPath(ns, property);\n\n            this.storage('remove', path);\n\n            return this;\n        },\n\n        /**\n         * Destroys current instance along with all of its' children.\n         * @param {Boolean} skipUpdate - skip collection update when element to be destroyed.\n         */\n        destroy: function (skipUpdate) {\n            this._dropHandlers()\n                ._clearRefs(skipUpdate);\n        },\n\n        /**\n         * Removes events listeners.\n         * @private\n         *\n         * @returns {Element} Chainable.\n         */\n        _dropHandlers: function () {\n            this.off();\n\n            if (_.isFunction(this.source)) {\n                this.source().off(this.name);\n            } else if (this.source) {\n                this.source.off(this.name);\n            }\n\n            return this;\n        },\n\n        /**\n         * Removes all references to current instance and\n         * calls 'destroy' method on all of its' children.\n         * @private\n         * @param {Boolean} skipUpdate - skip collection update when element to be destroyed.\n         *\n         * @returns {Element} Chainable.\n         */\n        _clearRefs: function (skipUpdate) {\n            registry.remove(this.name);\n\n            this.containers.forEach(function (parent) {\n                parent.removeChild(this, skipUpdate);\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Overrides 'EventsBus.trigger' method to implement events bubbling.\n         *\n         * @param {...*} arguments - Any number of arguments that should be passed to the events' handler.\n         * @returns {Boolean} False if event bubbling was canceled.\n         */\n        bubble: function () {\n            var args = _.toArray(arguments),\n                bubble = this.trigger.apply(this, args),\n                result;\n\n            if (!bubble) {\n                return false;\n            }\n\n            this.containers.forEach(function (parent) {\n                result = parent.bubble.apply(parent, args);\n\n                if (result === false) {\n                    bubble = false;\n                }\n            });\n\n            return !!bubble;\n        },\n\n        /**\n         * Callback which fires when property under uniqueNs has changed.\n         */\n        onUniqueUpdate: function (name) {\n            var active = name === this.name,\n                property = this.uniqueProp;\n\n            this[property](active);\n        },\n\n        /**\n         * Clean data form data source.\n         *\n         * @returns {Element}\n         */\n        cleanData: function () {\n            if (this.source && this.source.componentType === 'dataSource') {\n                if (this.elems) {\n                    _.each(this.elems(), function (val) {\n                        val.cleanData();\n                    });\n                } else {\n                    this.source.remove(this.dataScope);\n                }\n            }\n\n            return this;\n        },\n\n        /**\n         * Fallback data.\n         */\n        cacheData: function () {\n            this.cachedComponent = utils.copy(this);\n        },\n\n        /**\n         * Update configuration in component.\n         *\n         * @param {*} oldValue\n         * @param {*} newValue\n         * @param {String} path - path to value.\n         * @returns {Element}\n         */\n        updateConfig: function (oldValue, newValue, path) {\n            var names = path.split('.'),\n                index = _.lastIndexOf(names, 'config') + 1;\n\n            names = names.splice(index, names.length - index).join('.');\n            this.set(names, newValue);\n\n            return this;\n        }\n    }, Events, links);\n\n    return Class.extend(Element);\n});\n","Magento_Ui/js/lib/core/element/links.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'underscore',\n    'mageUtils',\n    'uiRegistry'\n], function (ko, _, utils, registry) {\n    'use strict';\n\n    /**\n     * Parse provided data.\n     *\n     * @param {String} placeholder\n     * @param {String} data\n     * @param {String} direction\n     * @returns {Boolean|Object}\n     */\n    function parseData(placeholder, data, direction) {\n        if (typeof data !== 'string') {\n            return false;\n        }\n\n        data = data.split(':');\n\n        if (!data[0]) {\n            return false;\n        }\n\n        if (!data[1]) {\n            data[1] = data[0];\n            data[0] = placeholder;\n        }\n\n        return {\n            target: data[0],\n            property: data[1],\n            direction: direction\n        };\n    }\n\n    /**\n     * Check if value not empty.\n     *\n     * @param {*} value\n     * @returns {Boolean}\n     */\n    function notEmpty(value) {\n        return typeof value !== 'undefined' && value != null;\n    }\n\n    /**\n     * Update value for linked component.\n     *\n     * @param {Object} data\n     * @param {Object} owner\n     * @param {Object} target\n     * @param {*} value\n     */\n    function updateValue(data, owner, target, value) {\n        var component = target.component,\n            property = target.property,\n            linked = data.linked;\n\n        if (data.mute) {\n            return;\n        }\n\n        if (linked) {\n            linked.mute = true;\n        }\n\n        if (owner.component !== target.component) {\n            value = data.inversionValue ? !utils.copy(value) : utils.copy(value);\n        }\n\n        component.set(property, value, owner);\n\n        if (property === 'disabled' && value) {\n            component.set('validate', value, owner);\n        }\n\n        if (linked) {\n            linked.mute = false;\n        }\n    }\n\n    /**\n     * Get value form owner component property.\n     *\n     * @param {Object} owner\n     * @returns {*}\n     */\n    function getValue(owner) {\n        var component = owner.component,\n            property = owner.property;\n\n        return component.get(property);\n    }\n\n    /**\n     * Format provided params to object.\n     *\n     * @param {String} ownerComponent\n     * @param {String} targetComponent\n     * @param {String} ownerProp\n     * @param {String} targetProp\n     * @param {String} direction\n     * @returns {Object}\n     */\n    function form(ownerComponent, targetComponent, ownerProp, targetProp, direction) {\n        var result,\n            tmp;\n\n        result = {\n            owner: {\n                component: ownerComponent,\n                property: ownerProp\n            },\n            target: {\n                component: targetComponent,\n                property: targetProp\n            }\n        };\n\n        if (direction === 'exports') {\n            tmp = result.owner;\n            result.owner = result.target;\n            result.target = tmp;\n        }\n\n        return result;\n    }\n\n    /**\n     * Set data to linked property.\n     *\n     * @param {Object} map\n     * @param {Object} data\n     */\n    function setLinked(map, data) {\n        var match;\n\n        if (!map) {\n            return;\n        }\n\n        match = _.findWhere(map, {\n            linked: false,\n            target: data.target,\n            property: data.property\n        });\n\n        if (match) {\n            match.linked = data;\n            data.linked = match;\n        }\n    }\n\n    /**\n     * Set data by direction.\n     *\n     * @param {Object} maps\n     * @param {String} property\n     * @param {Object} data\n     */\n    function setData(maps, property, data) {\n        var direction   = data.direction,\n            map         = maps[direction];\n\n        data.linked = false;\n\n        (map[property] = map[property] || []).push(data);\n\n        direction = direction === 'imports' ? 'exports' : 'imports';\n\n        setLinked(maps[direction][property], data);\n    }\n\n    /**\n     * Set links for components.\n     *\n     * @param {String} target\n     * @param {String} owner\n     * @param {Object} data\n     * @param {String} property\n     * @param {Boolean} immediate\n     */\n    function setLink(target, owner, data, property, immediate) {\n        var direction = data.direction,\n            formated = form(target, owner, data.property, property, direction),\n            callback,\n            value;\n\n        owner = formated.owner;\n        target = formated.target;\n\n        callback = updateValue.bind(null, data, owner, target);\n\n        owner.component.on(owner.property, callback, target.component.name);\n\n        if (immediate) {\n            value = getValue(owner);\n\n            if (notEmpty(value)) {\n                updateValue(data, owner, target, value);\n            }\n        }\n    }\n\n    /**\n     * Transfer data between components.\n     *\n     * @param {Object} owner\n     * @param {Object} data\n     */\n    function transfer(owner, data) {\n        var args = _.toArray(arguments);\n\n        if (data.target.substr(0, 1) === '!') {\n            data.target = data.target.substr(1);\n            data.inversionValue = true;\n        }\n\n        if (owner.name === data.target) {\n            args.unshift(owner);\n\n            setLink.apply(null, args);\n        } else {\n            registry.get(data.target, function (target) {\n                args.unshift(target);\n\n                setLink.apply(null, args);\n            });\n        }\n    }\n\n    return {\n        /**\n         * Assign listeners.\n         *\n         * @param {Object} listeners\n         * @returns {Object} Chainable\n         */\n        setListeners: function (listeners) {\n            var owner = this,\n                data;\n\n            _.each(listeners, function (callbacks, sources) {\n                sources = sources.split(' ');\n                callbacks = callbacks.split(' ');\n\n                sources.forEach(function (target) {\n                    callbacks.forEach(function (callback) {//eslint-disable-line max-nested-callbacks\n                        data = parseData(owner.name, target, 'imports');\n\n                        if (data) {\n                            setData(owner.maps, callback, data);\n                            transfer(owner, data, callback);\n                        }\n                    });\n                });\n            });\n\n            return this;\n        },\n\n        /**\n         * Set links in provided direction.\n         *\n         * @param {Object} links\n         * @param {String} direction\n         * @returns {Object} Chainable\n         */\n        setLinks: function (links, direction) {\n            var owner = this,\n                property,\n                data;\n\n            for (property in links) {\n                if (links.hasOwnProperty(property)) {\n                    data = parseData(owner.name, links[property], direction);\n\n                    if (data) {//eslint-disable-line max-depth\n                        setData(owner.maps, property, data);\n                        transfer(owner, data, property, true);\n                    }\n                }\n            }\n\n            return this;\n        }\n    };\n});\n","Magento_Ui/js/lib/validation/validator.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    './rules'\n], function (_, rulesList) {\n    'use strict';\n\n    /**\n     * Validates provided value be the specified rule.\n     *\n     * @param {String} id - Rule identifier.\n     * @param {*} value - Value to be checked.\n     * @param {*} [params]\n     * @param {*} additionalParams - additional validation params set by method caller\n     * @returns {Object}\n     */\n    function validate(id, value, params, additionalParams) {\n        var rule,\n            message,\n            valid,\n            result = {\n                rule: id,\n                passed: true,\n                message: ''\n            };\n\n        if (_.isObject(params)) {\n            message = params.message || '';\n        }\n\n        if (!rulesList[id]) {\n            return result;\n        }\n\n        rule    = rulesList[id];\n        message = message || rule.message;\n        valid   = rule.handler(value, params, additionalParams);\n\n        if (!valid) {\n            params = Array.isArray(params) ?\n                params :\n                [params];\n\n            if (typeof message === 'function') {\n                message = message.call(rule);\n            }\n\n            message = params.reduce(function (msg, param, idx) {\n                return msg.replace(new RegExp('\\\\{' + idx + '\\\\}', 'g'), param);\n            }, message);\n\n            result.passed = false;\n            result.message = message;\n        }\n\n        return result;\n    }\n\n    /**\n     * Validates provided value by a specified set of rules.\n     *\n     * @param {(String|Object)} rules - One or many validation rules.\n     * @param {*} value - Value to be checked.\n     * @param {*} additionalParams - additional validation params set by method caller\n     * @returns {Object}\n     */\n    function validator(rules, value, additionalParams) {\n        var result;\n\n        if (typeof rules === 'object') {\n            result = {\n                passed: true\n            };\n\n            _.every(rules, function (ruleParams, id) {\n                if (ruleParams.validate || ruleParams !== false || additionalParams) {\n                    result = validate(id, value, ruleParams, additionalParams);\n\n                    return result.passed;\n                }\n\n                return true;\n            });\n\n            return result;\n        }\n\n        return validate.apply(null, arguments);\n    }\n\n    /**\n     * Adds new validation rule.\n     *\n     * @param {String} id - Rule identifier.\n     * @param {Function} handler - Validation function.\n     * @param {String} message - Error message.\n     */\n    validator.addRule = function (id, handler, message) {\n        rulesList[id] = {\n            handler: handler,\n            message: message\n        };\n    };\n\n    /**\n     * Returns rule object found by provided identifier.\n     *\n     * @param {String} id - Rule identifier.\n     * @returns {Object}\n     */\n    validator.getRule = function (id) {\n        return rulesList[id];\n    };\n\n    return validator;\n});\n","Magento_Ui/js/lib/validation/rules.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    './utils',\n    'moment',\n    'tinycolor',\n    'jquery/validate',\n    'mage/translate'\n], function ($, _, utils, moment, tinycolor) {\n    'use strict';\n\n    /**\n     * validate credit card number using mod10\n     * @param {String} s\n     * @return {Boolean}\n     */\n    function validateCreditCard(s) {\n        // remove non-numerics\n        var v = '0123456789',\n            w = '',\n            i, j, k, m, c, a, x;\n\n        for (i = 0; i < s.length; i++) {\n            x = s.charAt(i);\n\n            if (v.indexOf(x, 0) !== -1) {\n                w += x;\n            }\n        }\n        // validate number\n        j = w.length / 2;\n        k = Math.floor(j);\n        m = Math.ceil(j) - k;\n        c = 0;\n\n        for (i = 0; i < k; i++) {\n            a = w.charAt(i * 2 + m) * 2;\n            c += a > 9 ? Math.floor(a / 10 + a % 10) : a;\n        }\n\n        for (i = 0; i < k + m; i++) {\n            c += w.charAt(i * 2 + 1 - m) * 1;\n        }\n\n        return c % 10 === 0;\n    }\n\n    /**\n     * Collection of validation rules including rules from additional-methods.js\n     * @type {Object}\n     */\n    return _.mapObject({\n        'min_text_length': [\n            function (value, params) {\n                return _.isUndefined(value) || value.length === 0 || value.length >= +params;\n            },\n            $.mage.__('Please enter more or equal than {0} symbols.')\n        ],\n        'max_text_length': [\n            function (value, params) {\n                return !_.isUndefined(value) && value.length <= +params;\n            },\n            $.mage.__('Please enter less or equal than {0} symbols.')\n        ],\n        'max-words': [\n            function (value, params) {\n                return utils.isEmpty(value) || utils.stripHtml(value).match(/\\b\\w+\\b/g).length < params;\n            },\n            $.mage.__('Please enter {0} words or less.')\n        ],\n        'min-words': [\n            function (value, params) {\n                return utils.isEmpty(value) || utils.stripHtml(value).match(/\\b\\w+\\b/g).length >= params;\n            },\n            $.mage.__('Please enter at least {0} words.')\n        ],\n        'range-words': [\n            function (value, params) {\n                var match = utils.stripHtml(value).match(/\\b\\w+\\b/g) || [];\n\n                return utils.isEmpty(value) || match.length >= params[0] &&\n                    match.length <= params[1];\n            },\n            $.mage.__('Please enter between {0} and {1} words.')\n        ],\n        'letters-with-basic-punc': [\n            function (value) {\n                return utils.isEmpty(value) || /^[a-z\\-.,()\\u0027\\u0022\\s]+$/i.test(value);\n            },\n            $.mage.__('Letters or punctuation only please')\n        ],\n        'alphanumeric': [\n            function (value) {\n                return utils.isEmpty(value) || /^\\w+$/i.test(value);\n            },\n            $.mage.__('Letters, numbers, spaces or underscores only please')\n        ],\n        'letters-only': [\n            function (value) {\n                return utils.isEmpty(value) || /^[a-z]+$/i.test(value);\n            },\n            $.mage.__('Letters only please')\n        ],\n        'no-whitespace': [\n            function (value) {\n                return utils.isEmpty(value) || /^\\S+$/i.test(value);\n            },\n            $.mage.__('No white space please')\n        ],\n        'no-marginal-whitespace': [\n            function (value) {\n                return !/^\\s+|\\s+$/i.test(value);\n            },\n            $.mage.__('No marginal white space please')\n        ],\n        'zip-range': [\n            function (value) {\n                return utils.isEmpty(value) || /^90[2-5]-\\d{2}-\\d{4}$/.test(value);\n            },\n            $.mage.__('Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx')\n        ],\n        'integer': [\n            function (value) {\n                return utils.isEmpty(value) || /^-?\\d+$/.test(value);\n            },\n            $.mage.__('A positive or negative non-decimal number please')\n        ],\n        'vinUS': [\n            function (value) {\n                if (utils.isEmpty(value)) {\n                    return true;\n                }\n\n                if (value.length !== 17) {\n                    return false;\n                }\n                var i, n, d, f, cd, cdv,//eslint-disable-line vars-on-top\n                    LL = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],//eslint-disable-line max-len\n                    VL = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9],\n                    FL = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2],\n                    rs = 0;\n\n                for (i = 0; i < 17; i++) {\n                    f = FL[i];\n                    d = value.slice(i, i + 1);\n\n                    if (i === 8) {\n                        cdv = d;\n                    }\n\n                    if (!isNaN(d)) {\n                        d *= f;\n                    } else {\n                        for (n = 0; n < LL.length; n++) {//eslint-disable-line max-depth\n                            if (d.toUpperCase() === LL[n]) {//eslint-disable-line max-depth\n                                d = VL[n];\n                                d *= f;\n\n                                if (isNaN(cdv) && n === 8) {//eslint-disable-line max-depth\n                                    cdv = LL[n];\n                                }\n                                break;\n                            }\n                        }\n                    }\n                    rs += d;\n                }\n                cd = rs % 11;\n\n                if (cd === 10) {\n                    cd = 'X';\n                }\n\n                if (cd === cdv) {\n                    return true;\n                }\n\n                return false;\n            },\n            $.mage.__('The specified vehicle identification number (VIN) is invalid.')\n        ],\n        'dateITA': [\n            function (value) {\n                var check = false,\n                    re = /^\\d{1,2}\\/\\d{1,2}\\/\\d{4}$/,\n                    adata, gg, mm, aaaa, xdata;\n\n                if (re.test(value)) {\n                    adata = value.split('/');\n                    gg = parseInt(adata[0], 10);\n                    mm = parseInt(adata[1], 10);\n                    aaaa = parseInt(adata[2], 10);\n                    xdata = new Date(aaaa, mm - 1, gg);\n\n                    if (xdata.getFullYear() === aaaa &&\n                        xdata.getMonth() === mm - 1 &&\n                        xdata.getDate() === gg\n                    ) {\n                        check = true;\n                    } else {\n                        check = false;\n                    }\n                } else {\n                    check = false;\n                }\n\n                return check;\n            },\n            $.mage.__('Please enter a correct date')\n        ],\n        'dateNL': [\n            function (value) {\n                return /^\\d\\d?[\\.\\/-]\\d\\d?[\\.\\/-]\\d\\d\\d?\\d?$/.test(value);\n            },\n            $.mage.__('Vul hier een geldige datum in.')\n        ],\n        'time': [\n            function (value) {\n                return utils.isEmpty(value) || /^([01]\\d|2[0-3])(:[0-5]\\d){0,2}$/.test(value);\n            },\n            $.mage.__('Please enter a valid time, between 00:00 and 23:59')\n        ],\n        'time12h': [\n            function (value) {\n                return utils.isEmpty(value) || /^((0?[1-9]|1[012])(:[0-5]\\d){0,2}(\\s[AP]M))$/i.test(value);\n            },\n            $.mage.__('Please enter a valid time, between 00:00 am and 12:00 pm')\n        ],\n        'phoneUS': [\n            function (value) {\n                value = value.replace(/\\s+/g, '');\n\n                return utils.isEmpty(value) || value.length > 9 &&\n                    value.match(/^(1-?)?(\\([2-9]\\d{2}\\)|[2-9]\\d{2})-?[2-9]\\d{2}-?\\d{4}$/);\n            },\n            $.mage.__('Please specify a valid phone number')\n        ],\n        'phoneUK': [\n            function (value) {\n                return utils.isEmpty(value) || value.length > 9 &&\n                    value.match(/^(\\(?(0|\\+44)[1-9]{1}\\d{1,4}?\\)?\\s?\\d{3,4}\\s?\\d{3,4})$/);\n            },\n            $.mage.__('Please specify a valid phone number')\n        ],\n        'mobileUK': [\n            function (value) {\n                return utils.isEmpty(value) || value.length > 9 && value.match(/^((0|\\+44)7\\d{3}\\s?\\d{6})$/);\n            },\n            $.mage.__('Please specify a valid mobile number')\n        ],\n        'stripped-min-length': [\n            function (value, param) {\n                return _.isUndefined(value) || value.length === 0 || utils.stripHtml(value).length >= param;\n            },\n            $.mage.__('Please enter at least {0} characters')\n        ],\n        'email2': [\n            function (value) {\n                return utils.isEmpty(value) || /^((([a-z]|\\d|[!#\\$%&\\u0027\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&\\u0027\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\u0022)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\u0022)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)*(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$/i.test(value);//eslint-disable-line max-len\n            },\n            $.validator.messages.email\n        ],\n        'url2': [\n            function (value) {\n                return utils.isEmpty(value) || /^(https?|ftp):\\/\\/(((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\\u0027\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)*(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\\u0027\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\\u0027\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\\u0027\\(\\)\\*\\+,;=]|:|@)|[\\uE000-\\uF8FF]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\\u0027\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.test(value);//eslint-disable-line max-len\n            },\n            $.validator.messages.url\n        ],\n        'credit-card-types': [\n            function (value, param) {\n                var validTypes;\n\n                if (utils.isEmpty(value)) {\n                    return true;\n                }\n\n                if (/[^0-9-]+/.test(value)) {\n                    return false;\n                }\n                value = value.replace(/\\D/g, '');\n                validTypes = 0x0000;\n\n                if (param.mastercard) {\n                    validTypes |= 0x0001;\n                }\n\n                if (param.visa) {\n                    validTypes |= 0x0002;\n                }\n\n                if (param.amex) {\n                    validTypes |= 0x0004;\n                }\n\n                if (param.dinersclub) {\n                    validTypes |= 0x0008;\n                }\n\n                if (param.enroute) {\n                    validTypes |= 0x0010;\n                }\n\n                if (param.discover) {\n                    validTypes |= 0x0020;\n                }\n\n                if (param.jcb) {\n                    validTypes |= 0x0040;\n                }\n\n                if (param.unknown) {\n                    validTypes |= 0x0080;\n                }\n\n                if (param.all) {\n                    validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;\n                }\n\n                if (validTypes & 0x0001 && /^(51|52|53|54|55)/.test(value)) { //mastercard\n                    return value.length === 16;\n                }\n\n                if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa\n                    return value.length === 16;\n                }\n\n                if (validTypes & 0x0004 && /^(34|37)/.test(value)) { //amex\n                    return value.length === 15;\n                }\n\n                if (validTypes & 0x0008 && /^(300|301|302|303|304|305|36|38)/.test(value)) { //dinersclub\n                    return value.length === 14;\n                }\n\n                if (validTypes & 0x0010 && /^(2014|2149)/.test(value)) { //enroute\n                    return value.length === 15;\n                }\n\n                if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover\n                    return value.length === 16;\n                }\n\n                if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb\n                    return value.length === 16;\n                }\n\n                if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb\n                    return value.length === 15;\n                }\n\n                if (validTypes & 0x0080) { //unknown\n                    return true;\n                }\n\n                return false;\n            },\n            $.mage.__('Please enter a valid credit card number.')\n        ],\n        'ipv4': [\n            function (value) {\n                return utils.isEmpty(value) || /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i.test(value);//eslint-disable-line max-len\n            },\n            $.mage.__('Please enter a valid IP v4 address.')\n        ],\n        'ipv6': [\n            function (value) {\n                return utils.isEmpty(value) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(value);//eslint-disable-line max-len\n            },\n            $.mage.__('Please enter a valid IP v6 address.')\n        ],\n        'pattern': [\n            function (value, param) {\n                return utils.isEmpty(value) || new RegExp(param).test(value);\n            },\n            $.mage.__('Invalid format.')\n        ],\n        'validate-no-html-tags': [\n            function (value) {\n                return !/<(\\/)?\\w+/.test(value);\n            },\n            $.mage.__('HTML tags are not allowed.')\n        ],\n        'validate-select': [\n            function (value) {\n                return value !== 'none' && value != null && value.length !== 0;\n            },\n            $.mage.__('Please select an option.')\n        ],\n        'validate-no-empty': [\n            function (value) {\n                return !utils.isEmpty(value);\n            },\n            $.mage.__('Empty Value.')\n        ],\n        'validate-alphanum-with-spaces': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^[a-zA-Z0-9 ]+$/.test(value);\n            },\n            $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.')\n        ],\n        'validate-data': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^[A-Za-z]+[A-Za-z0-9_]+$/.test(value);\n            },\n            $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.')//eslint-disable-line max-len\n        ],\n        'validate-street': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) ||\n                    /^[ \\w]{3,}([A-Za-z]\\.)?([ \\w]*\\#\\d+)?(\\r\\n| )[ \\w]{3,}/.test(value);\n            },\n            $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9), spaces and \"#\" in this field.')\n        ],\n        'validate-phoneStrict': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^(\\()?\\d{3}(\\))?(-|\\s)?\\d{3}(-|\\s)\\d{4}$/.test(value);\n            },\n            $.mage.__('Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.')\n        ],\n        'validate-phoneLax': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) ||\n                    /^((\\d[\\-. ]?)?((\\(\\d{3}\\))|\\d{3}))?[\\-. ]?\\d{3}[\\-. ]?\\d{4}$/.test(value);\n            },\n            $.mage.__('Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.')\n        ],\n        'validate-fax': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^(\\()?\\d{3}(\\))?(-|\\s)?\\d{3}(-|\\s)\\d{4}$/.test(value);\n            },\n            $.mage.__('Please enter a valid fax number (Ex: 123-456-7890).')\n        ],\n        'validate-email': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^([a-z0-9,!\\#\\$%&'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z0-9,!\\#\\$%&'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*@([a-z0-9-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z0-9-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*\\.(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]){2,})$/i.test(value);//eslint-disable-line max-len\n            },\n            $.mage.__('Please enter a valid email address (Ex: johndoe@domain.com).')\n        ],\n        'validate-emailSender': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^[\\S ]+$/.test(value);\n            },\n            $.mage.__('Please enter a valid email address (Ex: johndoe@domain.com).')\n        ],\n        'validate-password': [\n            function (value) {\n                var pass;\n\n                if (value == null) {\n                    return false;\n                }\n\n                pass = value.trim();\n\n                if (!pass.length) {\n                    return true;\n                }\n\n                return !(pass.length > 0 && pass.length < 6);\n            },\n            $.mage.__('Please enter 6 or more characters. Leading and trailing spaces will be ignored.')\n        ],\n        'validate-admin-password': [\n            function (value) {\n                var pass;\n\n                if (value == null) {\n                    return false;\n                }\n\n                pass = value.trim();\n\n                if (pass.length === 0) {\n                    return true;\n                }\n\n                if (!/[a-z]/i.test(value) || !/[0-9]/.test(value)) {\n                    return false;\n                }\n\n                if (pass.length < 7) {\n                    return false;\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter 7 or more characters, using both numeric and alphabetic.')\n        ],\n        'validate-customer-password': [\n            function (v, elm) {\n                var validator = this,\n                    counter = 0,\n                    passwordMinLength = $(elm).data('password-min-length'),\n                    passwordMinCharacterSets = $(elm).data('password-min-character-sets'),\n                    pass = v.trim(),\n                    result = pass.length >= passwordMinLength;\n\n                if (result === false) {\n                    validator.passwordErrorMessage = $.mage.__('Minimum length of this field must be equal or greater than %1 symbols. Leading and trailing spaces will be ignored.').replace('%1', passwordMinLength);//eslint-disable-line max-len\n\n                    return result;\n                }\n\n                if (pass.match(/\\d+/)) {\n                    counter++;\n                }\n\n                if (pass.match(/[a-z]+/)) {\n                    counter++;\n                }\n\n                if (pass.match(/[A-Z]+/)) {\n                    counter++;\n                }\n\n                if (pass.match(/[^a-zA-Z0-9]+/)) {\n                    counter++;\n                }\n\n                if (counter < passwordMinCharacterSets) {\n                    result = false;\n                    validator.passwordErrorMessage = $.mage.__('Minimum of different classes of characters in password is %1. Classes of characters: Lower Case, Upper Case, Digits, Special Characters.').replace('%1', passwordMinCharacterSets);//eslint-disable-line max-len\n                }\n\n                return result;\n            }, function () {\n                return this.passwordErrorMessage;\n            }\n        ],\n        'validate-url': [\n            function (value) {\n                if (utils.isEmptyNoTrim(value)) {\n                    return true;\n                }\n                value = (value || '').replace(/^\\s+/, '').replace(/\\s+$/, '');\n\n                return (/^(http|https|ftp):\\/\\/(([A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))(\\.[A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))*)(:(\\d+))?(\\/[A-Z0-9~](([A-Z0-9_~-]|\\.)*[A-Z0-9~]|))*\\/?(.*)?$/i).test(value);//eslint-disable-line max-len\n\n            },\n            $.mage.__('Please enter a valid URL. Protocol is required (http://, https:// or ftp://).')\n        ],\n        'validate-clean-url': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^(http|https|ftp):\\/\\/(([A-Z0-9][A-Z0-9_-]*)(\\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\\d+))?\\/?/i.test(value) || /^(www)((\\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\\d+))?\\/?/i.test(value);//eslint-disable-line max-len\n\n            },\n            $.mage.__('Please enter a valid URL. For example http://www.example.com or www.example.com.')\n        ],\n        'validate-xml-identifier': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^[A-Z][A-Z0-9_\\/-]*$/i.test(value);\n\n            },\n            $.mage.__('Please enter a valid XML-identifier (Ex: something_1, block5, id-4).')\n        ],\n        'validate-ssn': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^\\d{3}-?\\d{2}-?\\d{4}$/.test(value);\n\n            },\n            $.mage.__('Please enter a valid social security number (Ex: 123-45-6789).')\n        ],\n        'validate-zip-us': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /(^\\d{5}$)|(^\\d{5}-\\d{4}$)/.test(value);\n\n            },\n            $.mage.__('Please enter a valid zip code (Ex: 90602 or 90602-1234).')\n        ],\n        'validate-date-au': [\n            function (value) {\n                var regex = /^(\\d{2})\\/(\\d{2})\\/(\\d{4})$/,\n                    d;\n\n                if (utils.isEmptyNoTrim(value)) {\n                    return true;\n                }\n\n                if (utils.isEmpty(value) || !regex.test(value)) {\n                    return false;\n                }\n                d = new Date(value.replace(regex, '$2/$1/$3'));\n\n                return parseInt(RegExp.$2, 10) === 1 + d.getMonth() &&\n                    parseInt(RegExp.$1, 10) === d.getDate() &&\n                    parseInt(RegExp.$3, 10) === d.getFullYear();\n\n            },\n            $.mage.__('Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.')\n        ],\n        'validate-currency-dollar': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^\\$?\\-?([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}\\d*(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$/.test(value);//eslint-disable-line max-len\n\n            },\n            $.mage.__('Please enter a valid $ amount. For example $100.00.')\n        ],\n        'validate-not-negative-number': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || !isNaN(utils.parseNumber(value))\n                    && value >= 0 && (/^\\s*-?\\d+([,.]\\d+)*\\s*%?\\s*$/).test(value);\n\n            },\n            $.mage.__('Please enter a number 0 or greater, without comma in this field.')\n        ],\n        // validate-not-negative-number should be replaced in all places with this one and then removed\n        'validate-zero-or-greater': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || !isNaN(utils.parseNumber(value))\n                    && value >= 0 && (/^\\s*-?\\d+([,.]\\d+)*\\s*%?\\s*$/).test(value);\n            },\n            $.mage.__('Please enter a number 0 or greater, without comma in this field.')\n        ],\n        'validate-greater-than-zero': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || !isNaN(utils.parseNumber(value))\n                    && value > 0 && (/^\\s*-?\\d+([,.]\\d+)*\\s*%?\\s*$/).test(value);\n            },\n            $.mage.__('Please enter a number greater than 0, without comma in this field.')\n        ],\n        'validate-css-length': [\n            function (value) {\n                if (value !== '') {\n                    return (/^[0-9]*\\.*[0-9]+(px|pc|pt|ex|em|mm|cm|in|%)?$/).test(value);\n                }\n\n                return true;\n            },\n            $.mage.__('Please input a valid CSS-length (Ex: 100px, 77pt, 20em, .5ex or 50%).')\n        ],\n        'validate-number': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) ||\n                    !isNaN(utils.parseNumber(value)) &&\n                    /^\\s*-?\\d*(?:[.,|'|\\s]\\d+)*(?:[.,|'|\\s]\\d{2})?-?\\s*$/.test(value);\n            },\n            $.mage.__('Please enter a valid number in this field.')\n        ],\n        'validate-integer': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || !isNaN(utils.parseNumber(value)) && /^\\s*-?\\d*\\s*$/.test(value);\n            },\n            $.mage.__('Please enter a valid integer in this field.')\n        ],\n        'validate-number-range': [\n            function (value, param) {\n                var numValue, dataAttrRange, result, range, m;\n\n                if (utils.isEmptyNoTrim(value)) {\n                    return true;\n                }\n\n                numValue = utils.parseNumber(value);\n\n                if (isNaN(numValue)) {\n                    return false;\n                }\n\n                dataAttrRange = /^(-?[\\d.,]+)?-(-?[\\d.,]+)?$/;\n                result = true;\n                range = param;\n\n                if (range) {\n                    m = dataAttrRange.exec(range);\n\n                    if (m) {\n                        result = result && utils.isBetween(numValue, m[1], m[2]);\n                    }\n                }\n\n                return result;\n            },\n            $.mage.__('The value is not within the specified range.')\n        ],\n        'validate-positive-percent-decimal': [\n            function (value) {\n                var numValue;\n\n                if (utils.isEmptyNoTrim(value) || !/^\\s*-?\\d*(\\.\\d*)?\\s*$/.test(value)) {\n                    return false;\n                }\n\n                numValue = utils.parseNumber(value);\n\n                if (isNaN(numValue)) {\n                    return false;\n                }\n\n                return utils.isBetween(numValue, 0.01, 100);\n            },\n            $.mage.__('Please enter a valid percentage discount value greater than 0.')\n        ],\n        'validate-digits': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || !/[^\\d]/.test(value);\n            },\n            $.mage.__('Please enter a valid number in this field.')\n        ],\n        'validate-digits-range': [\n            function (value, param) {\n                var numValue, dataAttrRange, result, range, m;\n\n                if (utils.isEmptyNoTrim(value)) {\n                    return true;\n                }\n\n                numValue = utils.parseNumber(value);\n\n                if (isNaN(numValue)) {\n                    return false;\n                }\n\n                dataAttrRange = /^(-?\\d+)?-(-?\\d+)?$/;\n                result = true;\n                range = param;\n\n                if (range) {\n                    m = dataAttrRange.exec(range);\n\n                    if (m) {\n                        result = result && utils.isBetween(numValue, m[1], m[2]);\n                    }\n                }\n\n                return result;\n            },\n            $.mage.__('The value is not within the specified range.')\n        ],\n        'validate-range': [\n            function (value) {\n                var minValue, maxValue, ranges;\n\n                if (utils.isEmptyNoTrim(value)) {\n                    return true;\n                } else if ($.validator.methods['validate-digits'] && $.validator.methods['validate-digits'](value)) {\n                    minValue = maxValue = utils.parseNumber(value);\n                } else {\n                    ranges = /^(-?\\d+)?-(-?\\d+)?$/.exec(value);\n\n                    if (ranges) {\n                        minValue = utils.parseNumber(ranges[1]);\n                        maxValue = utils.parseNumber(ranges[2]);\n\n                        if (minValue > maxValue) {//eslint-disable-line max-depth\n                            return false;\n                        }\n                    } else {\n                        return false;\n                    }\n                }\n            },\n            $.mage.__('The value is not within the specified range.')\n        ],\n        'validate-alpha': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^[a-zA-Z]+$/.test(value);\n            },\n            $.mage.__('Please use letters only (a-z or A-Z) in this field.')\n        ],\n        'validate-code': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^[a-z]+[a-z0-9_]+$/.test(value);\n            },\n            $.mage.__('Please use only lowercase letters (a-z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.')//eslint-disable-line max-len\n        ],\n        'validate-alphanum': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^[a-zA-Z0-9]+$/.test(value);\n            },\n            $.mage.__('Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.')//eslint-disable-line max-len\n        ],\n        'validate-not-number-first': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^[^0-9-\\.].*$/.test(value.trim());\n            },\n            $.mage.__('First character must be letter.')\n        ],\n        'validate-date': [\n            function (value, params, additionalParams) {\n                var test = moment(value, additionalParams.dateFormat);\n\n                return utils.isEmptyNoTrim(value) || test.isValid();\n            },\n            $.mage.__('Please enter a valid date.')\n        ],\n        'validate-date-range': [\n            function (value, params) {\n                var fromDate = $('input[name*=\"' + params + '\"]').val();\n\n                return moment.utc(value).unix() >= moment.utc(fromDate).unix() || isNaN(moment.utc(value).unix());\n            },\n            $.mage.__('Make sure the To Date is later than or the same as the From Date.')\n        ],\n        'validate-identifier': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^[a-z0-9][a-z0-9_\\/-]+(\\.[a-z0-9_-]+)?$/.test(value);\n            },\n            $.mage.__('Please enter a valid URL Key (Ex: \"example-page\", \"example-page.html\" or \"anotherlevel/example-page\").')//eslint-disable-line max-len\n        ],\n        'validate-trailing-hyphen': [\n            function (value) {\n                return utils.isEmptyNoTrim(value) || /^(?!-)(?!.*-$).+$/.test(value);\n            },\n            $.mage.__('Trailing hyphens are not allowed.')\n        ],\n        'validate-zip-international': [\n\n            /*function(v) {\n            // @TODO: Cleanup\n            return Validation.get('IsEmpty').test(v) || /(^[A-z0-9]{2,10}([\\s]{0,1}|[\\-]{0,1})[A-z0-9]{2,10}$)/.test(v);\n            }*/\n            function () {\n                return true;\n            },\n            $.mage.__('Please enter a valid zip code.')\n        ],\n        'validate-state': [\n            function (value) {\n                return value !== 0;\n            },\n            $.mage.__('Please select State/Province.')\n        ],\n        'less-than-equals-to': [\n            function (value, params) {\n                value = utils.parseNumber(value);\n\n                if (isNaN(parseFloat(params))) {\n                    params = $(params).val();\n                }\n\n                params = utils.parseNumber(params);\n\n                if (!isNaN(params) && !isNaN(value)) {\n                    this.lteToVal = params;\n\n                    return value <= params;\n                }\n\n                return true;\n            },\n            function () {\n                return $.mage.__('Please enter a value less than or equal to %s.').replace('%s', this.lteToVal);\n            }\n        ],\n        'greater-than-equals-to': [\n            function (value, params) {\n                value = utils.parseNumber(value);\n\n                if (isNaN(parseFloat(params))) {\n                    params = $(params).val();\n                }\n\n                params = utils.parseNumber(params);\n\n                if (!isNaN(params) && !isNaN(value)) {\n                    this.gteToVal = params;\n\n                    return value >= params;\n                }\n\n                return true;\n            },\n            function () {\n                return $.mage.__('Please enter a value greater than or equal to %s.').replace('%s', this.gteToVal);\n            }\n        ],\n        'validate-emails': [\n            function (value) {\n                var validRegexp, emails, i;\n\n                if (utils.isEmpty(value)) {\n                    return true;\n                }\n                validRegexp = /^[a-z0-9\\._-]{1,30}@([a-z0-9_-]{1,30}\\.){1,5}[a-z]{2,4}$/i;\n                emails = value.split(/[\\s\\n\\,]+/g);\n\n                for (i = 0; i < emails.length; i++) {\n                    if (!validRegexp.test(emails[i].strip())) {\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter valid email addresses, separated by commas. For example, johndoe@domain.com, johnsmith@domain.com.')//eslint-disable-line max-len\n        ],\n        'validate-cc-number': [\n\n            /**\n             * Validate credit card number based on mod 10.\n             *\n             * @param {String} value - credit card number\n             * @return {Boolean}\n             */\n            function (value) {\n                if (value) {\n                    return validateCreditCard(value);\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter a valid credit card number.')\n        ],\n        'validate-cc-ukss': [\n\n            /**\n             * Validate Switch/Solo/Maestro issue number and start date is filled.\n             *\n             * @param {String} value - input field value\n             * @return {*}\n             */\n            function (value) {\n                return value;\n            },\n            $.mage.__('Please enter issue number or start date for switch/solo card type.')\n        ],\n        'required-entry': [\n            function (value) {\n                return !utils.isEmpty(value);\n            },\n            $.mage.__('This is a required field.')\n        ],\n        'checked': [\n            function (value) {\n                return value;\n            },\n            $.mage.__('This is a required field.')\n        ],\n        'not-negative-amount': [\n            function (value) {\n                if (value.length) {\n                    return (/^\\s*\\d+([,.]\\d+)*\\s*%?\\s*$/).test(value);\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter positive number in this field.')\n        ],\n        'validate-per-page-value-list': [\n            function (value) {\n                var isValid = true,\n                    values = value.split(','),\n                    i;\n\n                if (utils.isEmpty(value)) {\n                    return isValid;\n                }\n\n                for (i = 0; i < values.length; i++) {\n                    if (!/^[0-9]+$/.test(values[i])) {\n                        isValid = false;\n                    }\n                }\n\n                return isValid;\n            },\n            $.mage.__('Please enter a valid value, ex: 10,20,30')\n        ],\n        'validate-new-password': [\n            function (value) {\n                if ($.validator.methods['validate-password'] && !$.validator.methods['validate-password'](value)) {\n                    return false;\n                }\n\n                if (utils.isEmpty(value) && value !== '') {\n                    return false;\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter 6 or more characters. Leading and trailing spaces will be ignored.')\n        ],\n        'validate-item-quantity': [\n            function (value, params) {\n                var validator = this,\n                    result = false,\n                    // obtain values for validation\n                    qty = utils.parseNumber(value),\n                    isMinAllowedValid = typeof params.minAllowed === 'undefined' ||\n                        qty >= utils.parseNumber(params.minAllowed),\n                    isMaxAllowedValid = typeof params.maxAllowed === 'undefined' ||\n                        qty <= utils.parseNumber(params.maxAllowed),\n                    isQtyIncrementsValid = typeof params.qtyIncrements === 'undefined' ||\n                        qty % utils.parseNumber(params.qtyIncrements) === 0;\n\n                result = qty > 0;\n\n                if (result === false) {\n                    validator.itemQtyErrorMessage = $.mage.__('Please enter a quantity greater than 0.');//eslint-disable-line max-len\n\n                    return result;\n                }\n\n                result = isMinAllowedValid;\n\n                if (result === false) {\n                    validator.itemQtyErrorMessage = $.mage.__('The fewest you may purchase is %1.').replace('%1', params.minAllowed);//eslint-disable-line max-len\n\n                    return result;\n                }\n\n                result = isMaxAllowedValid;\n\n                if (result === false) {\n                    validator.itemQtyErrorMessage = $.mage.__('The maximum you may purchase is %1.').replace('%1', params.maxAllowed);//eslint-disable-line max-len\n\n                    return result;\n                }\n\n                result = isQtyIncrementsValid;\n\n                if (result === false) {\n                    validator.itemQtyErrorMessage = $.mage.__('You can buy this product only in quantities of %1 at a time.').replace('%1', params.qtyIncrements);//eslint-disable-line max-len\n\n                    return result;\n                }\n\n                return result;\n            }, function () {\n                return this.itemQtyErrorMessage;\n            }\n        ],\n        'equalTo': [\n            function (value, param) {\n                return value === $(param).val();\n            },\n            $.validator.messages.equalTo\n        ],\n        'validate-file-type': [\n            function (name, types) {\n                var extension = name.split('.').pop().toLowerCase();\n\n                if (types && typeof types === 'string') {\n                    types = types.split(' ');\n                }\n\n                return !types || !types.length || ~types.indexOf(extension);\n            },\n            $.mage.__('We don\\'t recognize or support this file extension type.')\n        ],\n        'validate-max-size': [\n            function (size, maxSize) {\n                return maxSize === false || size < maxSize;\n            },\n            $.mage.__('File you are trying to upload exceeds maximum file size limit.')\n        ],\n        'validate-if-tag-script-exist': [\n            function (value) {\n                return !value || (/<script\\b[^>]*>([\\s\\S]*?)<\\/script>$/ig).test(value);\n            },\n            $.mage.__('Please use tag SCRIPT with SRC attribute or with proper content to include JavaScript to the document.')//eslint-disable-line max-len\n        ],\n        'date_range_min': [\n            function (value, minValue, params) {\n                return moment.utc(value, params.dateFormat).unix() >= minValue;\n            },\n            $.mage.__('The date is not within the specified range.')\n        ],\n        'date_range_max': [\n            function (value, maxValue, params) {\n                return moment.utc(value, params.dateFormat).unix() <= maxValue;\n            },\n            $.mage.__('The date is not within the specified range.')\n        ],\n        'validate-color': [\n            function (value) {\n                if (value === '') {\n                    return true;\n                }\n\n                return tinycolor(value).isValid();\n            },\n            $.mage.__('Wrong color format. Please specify color in HEX, RGBa, HSVa, HSLa or use color name.')\n        ],\n        'blacklist-url': [\n            function (value, param) {\n                return new RegExp(param).test(value);\n            },\n            $.mage.__('This link is not allowed.')\n        ],\n        'validate-dob': [\n            function (value, param, params) {\n                if (value === '') {\n                    return true;\n                }\n\n                return moment.utc(value, params.dateFormat).isSameOrBefore(moment.utc());\n            },\n            $.mage.__('The Date of Birth should not be greater than today.')\n        ],\n        'validate-no-utf8mb4-characters': [\n            function (value) {\n                var validator = this,\n                    message = $.mage.__('Please remove invalid characters: {0}.'),\n                    matches = value.match(/(?:[\\uD800-\\uDBFF][\\uDC00-\\uDFFF])/g),\n                    result = matches === null;\n\n                if (!result) {\n                    validator.charErrorMessage = message.replace('{0}', matches.join());\n                }\n\n                return result;\n            }, function () {\n                return this.charErrorMessage;\n            }\n        ]\n    }, function (data) {\n        return {\n            handler: data[0],\n            message: data[1]\n        };\n    });\n});\n","Magento_Ui/js/lib/validation/utils.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    var utils = {\n        /**\n         * Check if string is empty with trim.\n         *\n         * @param {String} value\n         * @return {Boolean}\n         */\n        isEmpty: function (value) {\n            return value === '' || value == null || value.length === 0 || /^\\s+$/.test(value);\n        },\n\n        /**\n         * Check if string is empty no trim.\n         *\n         * @param {String} value\n         * @return {Boolean}\n         */\n        isEmptyNoTrim: function (value) {\n            return value === '' || value == null || value.length === 0;\n        },\n\n        /**\n         * Checks if {value} is between numbers {from} and {to}.\n         *\n         * @param {String} value\n         * @param {String} from\n         * @param {String} to\n         * @return {Boolean}\n         */\n        isBetween: function (value, from, to) {\n            return (from === null || from === '' || value >= utils.parseNumber(from)) &&\n                   (to === null || to === '' || value <= utils.parseNumber(to));\n        },\n\n        /**\n         * Parse price string.\n         *\n         * @param {String} value\n         * @return {Number}\n         */\n        parseNumber: function (value) {\n            var isDot, isComa;\n\n            if (typeof value !== 'string') {\n                return parseFloat(value);\n            }\n            isDot = value.indexOf('.');\n            isComa = value.indexOf(',');\n\n            if (isDot !== -1 && isComa !== -1) {\n                if (isComa > isDot) {\n                    value = value.replace('.', '').replace(',', '.');\n                } else {\n                    value = value.replace(',', '');\n                }\n            } else if (isComa !== -1) {\n                value = value.replace(',', '.');\n            }\n\n            return parseFloat(value);\n        },\n\n        /**\n         * Removes HTML tags and space characters, numbers and punctuation.\n         *\n         * @param {String} value -  Value being stripped.\n         * @return {String}\n         */\n        stripHtml: function (value) {\n            return value.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' ')\n                .replace(/[0-9.(),;:!?%#$'\"_+=\\/-]*/g, '');\n        }\n    };\n\n    return utils;\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/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/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/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","Mageplaza_Smtp/js/action/send-address.js":"/**\n * Mageplaza\n *\n * NOTICE OF LICENSE\n *\n * This source file is subject to the Mageplaza.com license that is\n * available through the world-wide-web at this URL:\n * https://www.mageplaza.com/LICENSE.txt\n *\n * DISCLAIMER\n *\n * Do not edit or add to this file if you wish to upgrade this extension to newer\n * version in the future.\n *\n * @category    Mageplaza\n * @package     Mageplaza_Smtp\n * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)\n * @license     https://www.mageplaza.com/LICENSE.txt\n */\n\ndefine([\n    'mage/storage',\n    'Mageplaza_Smtp/js/model/resource-url-manager',\n    'Magento_Checkout/js/model/quote'\n], function (storage, resourceUrlManager, quote) {\n    'use strict';\n\n    return function (address, isOsc) {\n        return storage.post(\n            resourceUrlManager.getUrlForUpdateOrder(quote),\n            JSON.stringify({\n                address: address,\n                isOsc: isOsc\n            }),\n            false\n        );\n    };\n});\n","Mageplaza_Smtp/js/view/shipping-mixins.js":"/**\n * Mageplaza\n *\n * NOTICE OF LICENSE\n *\n * This source file is subject to the Mageplaza.com license that is\n * available through the world-wide-web at this URL:\n * https://www.mageplaza.com/LICENSE.txt\n *\n * DISCLAIMER\n *\n * Do not edit or add to this file if you wish to upgrade this extension to newer\n * version in the future.\n *\n * @category    Mageplaza\n * @package     Mageplaza_StoreLocator\n * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)\n * @license     https://www.mageplaza.com/LICENSE.txt\n */\n\ndefine(\n    [\n        'jquery',\n        'underscore',\n        'Magento_Ui/js/form/form',\n        'ko',\n        'Magento_Customer/js/model/customer',\n        'Magento_Customer/js/model/address-list',\n        'Magento_Checkout/js/model/address-converter',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Checkout/js/action/create-shipping-address',\n        'Magento_Checkout/js/action/select-shipping-address',\n        'Magento_Checkout/js/model/shipping-rates-validator',\n        'Magento_Checkout/js/model/shipping-address/form-popup-state',\n        'Magento_Checkout/js/model/shipping-service',\n        'Magento_Checkout/js/action/select-shipping-method',\n        'Magento_Checkout/js/model/shipping-rate-registry',\n        'Magento_Checkout/js/action/set-shipping-information',\n        'Magento_Checkout/js/model/step-navigator',\n        'Magento_Ui/js/modal/modal',\n        'Magento_Checkout/js/model/checkout-data-resolver',\n        'Magento_Checkout/js/checkout-data',\n        'uiRegistry',\n        'mage/translate',\n        'Magento_Checkout/js/model/shipping-rate-service',\n        'Mageplaza_Smtp/js/model/address-on-change'\n    ],\n    function (\n        $,\n        _,\n        Component,\n        ko,\n        customer,\n        addressList,\n        addressConverter,\n        quote,\n        createShippingAddress,\n        selectShippingAddress,\n        shippingRatesValidator,\n        formPopUpState,\n        shippingService,\n        selectShippingMethodAction,\n        rateRegistry,\n        setShippingInformationAction,\n        stepNavigator,\n        modal,\n        checkoutDataResolver,\n        checkoutData,\n        registry,\n        $t,\n        shippingRateService,\n        shippingAddressOnChange\n    ) {\n        'use strict';\n\n        var mixin = {\n\n            initialize: function () {\n                var fieldsetName = 'checkout.steps.shipping-step.shippingAddress.shipping-address-fieldset';\n\n                this._super();\n\n                shippingAddressOnChange.initFields(fieldsetName);\n            }\n        };\n\n        return function (target) {\n            return target.extend(mixin);\n        };\n    }\n);\n","Mageplaza_Smtp/js/view/billing-address-mixins.js":"/**\n * Mageplaza\n *\n * NOTICE OF LICENSE\n *\n * This source file is subject to the Mageplaza.com license that is\n * available through the world-wide-web at this URL:\n * https://www.mageplaza.com/LICENSE.txt\n *\n * DISCLAIMER\n *\n * Do not edit or add to this file if you wish to upgrade this extension to newer\n * version in the future.\n *\n * @category    Mageplaza\n * @package     Mageplaza_StoreLocator\n * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)\n * @license     https://www.mageplaza.com/LICENSE.txt\n */\n\ndefine(\n    [\n        'jquery',\n        'ko',\n        'underscore',\n        'Magento_Ui/js/form/form',\n        'Magento_Customer/js/model/customer',\n        'Magento_Customer/js/model/address-list',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Checkout/js/action/create-billing-address',\n        'Magento_Checkout/js/action/select-billing-address',\n        'Magento_Checkout/js/checkout-data',\n        'Magento_Checkout/js/model/checkout-data-resolver',\n        'Magento_Customer/js/customer-data',\n        'Magento_Checkout/js/action/set-billing-address',\n        'Magento_Ui/js/model/messageList',\n        'mage/translate',\n        'Magento_Checkout/js/model/billing-address-postcode-validator',\n        'Mageplaza_Smtp/js/model/address-on-change'\n    ],\n    function (\n        $,\n        ko,\n        _,\n        Component,\n        customer,\n        addressList,\n        quote,\n        createBillingAddress,\n        selectBillingAddress,\n        checkoutData,\n        checkoutDataResolver,\n        customerData,\n        setBillingAddressAction,\n        globalMessageList,\n        $t,\n        billingAddressPostcodeValidator,\n        billingAddressOnChange\n    ) {\n        'use strict';\n\n        var mixin = {\n            initialize: function () {\n                var fieldset;\n\n                this._super();\n\n                if (window.checkoutConfig.oscConfig) {\n                    fieldset = this.get('name') + '.billing-address-fieldset';\n                } else {\n                    fieldset = this.get('name') + '.form-fields';\n                }\n\n                billingAddressOnChange.initFields(fieldset);\n            },\n        };\n\n        return function (target) {\n            return target.extend(mixin);\n        };\n    }\n);\n","Mageplaza_Smtp/js/model/address-on-change.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    'ko',\n    'mage/translate',\n    'uiRegistry',\n    'Magento_Checkout/js/model/quote',\n    'Mageplaza_Smtp/js/action/send-address'\n], function (\n    $,\n    ko,\n    $t,\n    uiRegistry,\n    quote,\n    sendAddress\n) {\n    'use strict';\n\n    var elements         = ['firstname', 'lastname', 'company', 'street', 'country_id', 'region_id', 'city', 'postcode', 'telephone'],\n        observedElements = [];\n\n    return {\n        validateAddressTimeout: 0,\n        validateDelay: 1000,\n\n        /**\n         * Perform postponed binding for fieldset elements\n         *\n         * @param {String} formPath\n         */\n        initFields: function (formPath) {\n            var self = this;\n\n            $.each(elements, function (index, field) {\n                uiRegistry.async(formPath + '.' + field)(self.smtpBindHandler.bind(self));\n            });\n        },\n\n        /**\n         * @param {Object} element\n         * @param {Number} delay\n         */\n        smtpBindHandler: function (element, delay) {\n            var self = this;\n\n            delay = typeof delay === 'undefined' ? self.validateDelay : delay;\n\n            if (element.component.indexOf('/group') !== -1) {\n                $.each(element.elems(), function (index, elem) {\n                    uiRegistry.async(elem.name)(function () {\n                        self.smtpBindHandler(elem);\n                    });\n                });\n            } else if (element && element.hasOwnProperty('value')) {\n                element.on('value', function () {\n                    clearTimeout(self.validateAddressTimeout);\n                    self.validateAddressTimeout = setTimeout(function () {\n                        sendAddress(JSON.stringify(self.collectObservedData()), self.isOsc());\n                    }, delay);\n                });\n\n                observedElements.push(element);\n            }\n        },\n        /**\n         * Collect observed fields data to object\n         *\n         * @returns {*}\n         */\n        collectObservedData: function () {\n            var observedValues = {};\n\n            $.each(observedElements, function (index, field) {\n                var value = field.value();\n\n                if ($.type(value) === 'undefined') {\n                    value = '';\n                }\n                observedValues[field.dataScope] = value;\n            });\n\n            return observedValues;\n        },\n        isOsc: function () {\n            return !!window.checkoutConfig.oscConfig;\n        }\n    };\n});\n","Mageplaza_Smtp/js/model/resource-url-manager.js":"/**\n * Mageplaza\n *\n * NOTICE OF LICENSE\n *\n * This source file is subject to the Mageplaza.com license that is\n * available through the world-wide-web at this URL:\n * https://www.mageplaza.com/LICENSE.txt\n *\n * DISCLAIMER\n *\n * Do not edit or add to this file if you wish to upgrade this extension to newer\n * version in the future.\n *\n * @category    Mageplaza\n * @package     Mageplaza_Smtp\n * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)\n * @license     https://www.mageplaza.com/LICENSE.txt\n */\n\ndefine(\n    [\n        'jquery',\n        'Magento_Checkout/js/model/resource-url-manager'\n    ],\n    function ($, resourceUrlManager) {\n        \"use strict\";\n\n        return $.extend({\n            /** Get url for send the address to update order */\n            getUrlForUpdateOrder: function (quote) {\n                var params = {cartId: quote.getQuoteId()};\n                var urls   = {\n                    'default': '/carts/:cartId/update-order'\n                };\n\n                return this.getUrl(urls, params);\n            }\n        }, resourceUrlManager);\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: '.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                        let salableProducts = this.products;\n\n                        if ($widget.options.jsonConfig.canDisplayShowOutOfStockStatus) {\n                            salableProducts = $widget.options.jsonConfig.salable[item.id][this.id];\n                        }\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: salableProducts\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            $product.find(this.options.normalPriceLabelSelector).hide();\n\n            _.each(this.element.find('.' + 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                                $product.find(this.options.normalPriceLabelSelector).show();\n                            }\n                        }.bind(this));\n                    } else {\n                        $product.find(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(\n                    imagesToUpdate.map(({thumb, img, full, type, videoUrl}) => ({thumb, img, full, type, videoUrl})),\n                    initialImages.map(({thumb, img, full, type, videoUrl}) => ({thumb, img, full, type, videoUrl}))\n                );\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/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_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","Mageplaza_Blog/js/treeselectjs.umd.js":"// MIT License\n//\n// Copyright (c) 2022 Dzmitry Zhuraukou\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n//     The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n//     THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n(function(b,p){typeof exports==\"object\"&&typeof module<\"u\"?module.exports=p():typeof define==\"function\"&&define.amd?define(p):(b=typeof globalThis<\"u\"?globalThis:b||self,b.Treeselect=p())})(this,function(){var P,y,H,x,pe,Ut,G,oe,me,zt,fe,Yt,M,re,B,j,be,Kt,Ce,Xt,ge,Jt,ke,Zt,we,Qt,Ee,es,ve,ts,Le,ss,ye,is,xe,ls,Se,ns,_e,as,Ae,os,Te,rs,Ne,cs,Oe,hs,z,xt,F,V,_,Y,Ie,ds,Pe,us,Be,ps,Ve,ms,De,fs,He,bs,K,St,Ge,Cs,Me,gs,Fe,ks,X,_t,je,ws,qe,Es,Re,vs,$e,Ls,We,ys,Ue,xs,ze,Ss,Ye,_s,Ke,As,Xe,Ts,Je,Ns,J,At,Z,Tt,Ze,Os,u,m,q,Q,R,A,T,S,D,ee,Nt,te,Ot,Qe,Is,et,Ps,tt,Bs,st,Vs,it,Ds,lt,Hs,se,It,nt,Gs,at,Ms,ot,Fs,rt,js,ie,Pt,ct,qs,$,gt,le,Bt,W,kt,ht,Rs,ne,Vt,dt,$s,ut,Ws,pt,Us,mt,zs,ft,Ys;\"use strict\";var Hi=Object.defineProperty;var Gi=(b,p,f)=>p in b?Hi(b,p,{enumerable:!0,configurable:!0,writable:!0,value:f}):b[p]=f;var c=(b,p,f)=>(Gi(b,typeof p!=\"symbol\"?p+\"\":p,f),f),yt=(b,p,f)=>{if(!p.has(b))throw TypeError(\"Cannot \"+f)};var n=(b,p,f)=>(yt(b,p,\"read from private field\"),f?f.call(b):p.get(b)),r=(b,p,f)=>{if(p.has(b))throw TypeError(\"Cannot add the same private member more than once\");p instanceof WeakSet?p.add(b):p.set(b,f)},C=(b,p,f,U)=>(yt(b,p,\"write to private field\"),U?U.call(b,f):p.set(b,f),f);var o=(b,p,f)=>(yt(b,p,\"access private method\"),f);const b=\"\",p={arrowUp:'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 25 25\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 15l-6-6-6 6\"/></svg>',arrowDown:'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 25 25\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6 9l6 6 6-6\"/></svg>',arrowRight:'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 25 25\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 18l6-6-6-6\"/></svg>',attention:'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 25 25\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"></path><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"></line><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"></line></svg>',clear:'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 25 25\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"></circle><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"></line><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"></line></svg>',cross:'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 25 25\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line></svg>',check:'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 25 25\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg>',partialCheck:'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 25 25\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line></svg>'},f=(l,e)=>{if(e.innerHTML=\"\",typeof l==\"string\")e.innerHTML=l;else{const t=l.cloneNode(!0);e.appendChild(t)}},U=l=>{const e=l?{...l}:{};return Object.keys(p).forEach(t=>{e[t]||(e[t]=p[t])}),e},Ks=l=>l.reduce((e,{name:t},s)=>(e+=t,s<l.length-1&&(e+=\", \"),e),\"\");class Xs{constructor({value:e,showTags:t,tagsCountText:s,clearable:i,isAlwaysOpened:a,searchable:h,placeholder:d,disabled:w,isSingleSelect:g,id:k,ariaLabel:E,iconElements:v,inputCallback:L,searchCallback:N,openCallback:O,closeCallback:ae,keydownCallback:bt,focusCallback:vt,blurCallback:Lt,nameChangeCallback:Ct}){r(this,pe);r(this,G);r(this,me);r(this,fe);r(this,M);r(this,B);r(this,be);r(this,Ce);r(this,ge);r(this,ke);r(this,we);r(this,Ee);r(this,ve);r(this,Le);r(this,ye);r(this,xe);r(this,Se);r(this,_e);r(this,Ae);r(this,Te);r(this,Ne);r(this,Oe);r(this,z);c(this,\"value\");c(this,\"showTags\");c(this,\"tagsCountText\");c(this,\"clearable\");c(this,\"isAlwaysOpened\");c(this,\"searchable\");c(this,\"placeholder\");c(this,\"disabled\");c(this,\"isSingleSelect\");c(this,\"id\");c(this,\"ariaLabel\");c(this,\"iconElements\");c(this,\"isOpened\");c(this,\"searchText\");c(this,\"srcElement\");r(this,P,void 0);r(this,y,void 0);r(this,H,void 0);r(this,x,void 0);c(this,\"inputCallback\");c(this,\"searchCallback\");c(this,\"openCallback\");c(this,\"closeCallback\");c(this,\"keydownCallback\");c(this,\"focusCallback\");c(this,\"blurCallback\");c(this,\"nameChangeCallback\");this.value=e,this.showTags=t,this.tagsCountText=s,this.searchable=h,this.placeholder=d,this.clearable=i,this.isAlwaysOpened=a,this.disabled=w,this.isSingleSelect=g,this.id=k,this.ariaLabel=E,this.iconElements=v,this.isOpened=!1,this.searchText=\"\",C(this,P,o(this,ge,Jt).call(this)),C(this,y,o(this,ye,is).call(this)),C(this,H,o(this,_e,as).call(this)),C(this,x,null),this.inputCallback=L,this.searchCallback=N,this.openCallback=O,this.closeCallback=ae,this.keydownCallback=bt,this.focusCallback=vt,this.blurCallback=Lt,this.nameChangeCallback=Ct,this.srcElement=o(this,be,Kt).call(this,n(this,P),n(this,y),n(this,H)),o(this,pe,Ut).call(this)}focus(){setTimeout(()=>n(this,y).focus(),0)}blur(){this.isOpened&&o(this,B,j).call(this),this.clearSearch(),n(this,y).blur()}updateValue(e){this.value=e,o(this,G,oe).call(this),o(this,M,re).call(this)}removeItem(e){this.value=this.value.filter(t=>t.id!==e),o(this,z,xt).call(this),o(this,G,oe).call(this),o(this,M,re).call(this)}clear(){this.value=[],o(this,z,xt).call(this),o(this,G,oe).call(this),this.clearSearch()}openClose(){o(this,B,j).call(this)}clearSearch(){this.searchText=\"\",this.searchCallback(\"\"),o(this,M,re).call(this)}}P=new WeakMap,y=new WeakMap,H=new WeakMap,x=new WeakMap,pe=new WeakSet,Ut=function(){o(this,G,oe).call(this),o(this,M,re).call(this),o(this,me,zt).call(this)},G=new WeakSet,oe=function(){if(n(this,P).innerHTML=\"\",this.showTags){n(this,P).append(...o(this,ke,Zt).call(this));const e=Ks(this.value);this.nameChangeCallback(e)}else{const e=o(this,Le,ss).call(this);n(this,P).appendChild(e),this.nameChangeCallback(e.innerText)}n(this,P).appendChild(n(this,y))},me=new WeakSet,zt=function(){const e=[];n(this,H).innerHTML=\"\",this.clearable&&e.push(o(this,Ae,os).call(this)),this.isAlwaysOpened||e.push(o(this,Ne,cs).call(this,this.isOpened)),e.length&&n(this,H).append(...e)},fe=new WeakSet,Yt=function(){if(!this.isAlwaysOpened&&n(this,x)){const e=this.isOpened?this.iconElements.arrowUp:this.iconElements.arrowDown;f(e,n(this,x))}},M=new WeakSet,re=function(){var e;(e=this.value)!=null&&e.length?(n(this,y).removeAttribute(\"placeholder\"),this.srcElement.classList.remove(\"treeselect-input--value-not-selected\")):(n(this,y).setAttribute(\"placeholder\",this.placeholder),this.srcElement.classList.add(\"treeselect-input--value-not-selected\")),this.searchable?this.srcElement.classList.remove(\"treeselect-input--unsearchable\"):this.srcElement.classList.add(\"treeselect-input--unsearchable\"),this.isSingleSelect?this.srcElement.classList.add(\"treeselect-input--is-single-select\"):this.srcElement.classList.remove(\"treeselect-input--is-single-select\"),n(this,y).value=this.searchText},B=new WeakSet,j=function(){this.isOpened=!this.isOpened,o(this,fe,Yt).call(this),this.isOpened?this.openCallback():this.closeCallback()},be=new WeakSet,Kt=function(e,t,s){const i=document.createElement(\"div\");return i.classList.add(\"treeselect-input\"),i.setAttribute(\"tabindex\",\"-1\"),i.addEventListener(\"mousedown\",a=>o(this,Ce,Xt).call(this,a)),i.addEventListener(\"focus\",()=>this.focusCallback(),!0),i.addEventListener(\"blur\",()=>this.blurCallback(),!0),e.appendChild(t),i.append(e,s),i},Ce=new WeakSet,Xt=function(e){e.stopPropagation(),this.isOpened||o(this,B,j).call(this),this.focus()},ge=new WeakSet,Jt=function(){const e=document.createElement(\"div\");return e.classList.add(\"treeselect-input__tags\"),e},ke=new WeakSet,Zt=function(){return this.value.map(e=>{const t=document.createElement(\"div\");t.classList.add(\"treeselect-input__tags-element\"),t.setAttribute(\"tabindex\",\"-1\"),t.setAttribute(\"tag-id\",e.id.toString()),t.setAttribute(\"title\",e.name);const s=o(this,Ee,es).call(this,e.name),i=o(this,ve,ts).call(this);return t.addEventListener(\"mousedown\",a=>o(this,we,Qt).call(this,a,e.id)),t.append(s,i),t})},we=new WeakSet,Qt=function(e,t){e.preventDefault(),e.stopPropagation(),this.removeItem(t),this.focus()},Ee=new WeakSet,es=function(e){const t=document.createElement(\"span\");return t.classList.add(\"treeselect-input__tags-name\"),t.textContent=e,t},ve=new WeakSet,ts=function(){const e=document.createElement(\"span\");return e.classList.add(\"treeselect-input__tags-cross\"),f(this.iconElements.cross,e),e},Le=new WeakSet,ss=function(){const e=document.createElement(\"span\");if(e.classList.add(\"treeselect-input__tags-count\"),!this.value.length)return e.textContent=\"\",e.setAttribute(\"title\",\"\"),e;const t=this.value.length===1?this.value[0].name:`${this.value.length} ${this.tagsCountText}`;return e.textContent=t,e.setAttribute(\"title\",t),e},ye=new WeakSet,is=function(){const e=document.createElement(\"input\");return e.classList.add(\"treeselect-input__edit\"),this.id&&e.setAttribute(\"id\",this.id),(!this.searchable||this.disabled)&&e.setAttribute(\"readonly\",\"readonly\"),this.disabled&&e.setAttribute(\"tabindex\",\"-1\"),this.ariaLabel.length&&e.setAttribute(\"aria-label\",this.ariaLabel),e.addEventListener(\"keydown\",t=>o(this,xe,ls).call(this,t)),e.addEventListener(\"input\",t=>o(this,Se,ns).call(this,t,e)),e},xe=new WeakSet,ls=function(e){e.stopPropagation();const t=e.key;t===\"Backspace\"&&!this.searchText.length&&this.value.length&&!this.showTags&&this.clear(),t===\"Backspace\"&&!this.searchText.length&&this.value.length&&this.removeItem(this.value[this.value.length-1].id),e.code===\"Space\"&&(!this.searchText||!this.searchable)&&o(this,B,j).call(this),(t===\"Enter\"||t===\"ArrowDown\"||t===\"ArrowUp\")&&e.preventDefault(),this.keydownCallback(e),t!==\"Tab\"&&this.focus()},Se=new WeakSet,ns=function(e,t){e.stopPropagation();const s=this.searchText,i=t.value.trim();if(s.length===0&&i.length===0){t.value=\"\";return}if(this.searchable){const a=e.target.value;this.searchCallback(a),this.isOpened||o(this,B,j).call(this)}else t.value=\"\";this.searchText=t.value},_e=new WeakSet,as=function(){const e=document.createElement(\"div\");return e.classList.add(\"treeselect-input__operators\"),e},Ae=new WeakSet,os=function(){const e=document.createElement(\"span\");return e.classList.add(\"treeselect-input__clear\"),e.setAttribute(\"tabindex\",\"-1\"),f(this.iconElements.clear,e),e.addEventListener(\"mousedown\",t=>o(this,Te,rs).call(this,t)),e},Te=new WeakSet,rs=function(e){e.preventDefault(),e.stopPropagation(),(this.searchText.length||this.value.length)&&this.clear(),this.focus()},Ne=new WeakSet,cs=function(e){C(this,x,document.createElement(\"span\")),n(this,x).classList.add(\"treeselect-input__arrow\");const t=e?this.iconElements.arrowUp:this.iconElements.arrowDown;return f(t,n(this,x)),n(this,x).addEventListener(\"mousedown\",s=>o(this,Oe,hs).call(this,s)),n(this,x)},Oe=new WeakSet,hs=function(e){e.stopPropagation(),e.preventDefault(),this.focus(),o(this,B,j).call(this)},z=new WeakSet,xt=function(){this.inputCallback(this.value)};const Dt=(l,e,t,s)=>{ei(e);const i=e.filter(a=>!a.disabled&&l.some(h=>h===a.id));if(t&&i.length){i[0].checked=!0;return}i.forEach(a=>{a.checked=!0;const h=wt(a,e,s);a.checked=h})},wt=({id:l,checked:e},t,s)=>{const i=t.find(h=>h.id===l);if(!i)return!1;if(s)return i.checked=i.disabled?!1:!!e,i.checked;const a=Ht(!!e,i,t);return Gt(i,t),a},Ht=(l,e,t)=>{if(!e.isGroup)return e.checked=e.disabled?!1:!!l,e.isPartialChecked=!1,e.checked;const s=t.filter(d=>d.childOf===e.id);return!l||e.disabled||e.isPartialChecked?(e.checked=!1,e.isPartialChecked=!1,Et(e,s,t),e.checked):Mt(s,t)?Ft(s)?(e.checked=!1,e.isPartialChecked=!1,e.disabled=!0,e.checked):(e.checked=!1,e.isPartialChecked=!0,s.forEach(d=>{Ht(l,d,t)}),e.checked):(e.checked=!0,e.isPartialChecked=!1,Et(e,s,t),e.checked)},Gt=(l,e)=>{const t=e.find(s=>s.id===l.childOf);t&&(Js(t,e),Gt(t,e))},Js=(l,e)=>{const t=ce(l,e);if(Ft(t)){l.checked=!1,l.isPartialChecked=!1,l.disabled=!0;return}if(Zs(t)){l.checked=!0,l.isPartialChecked=!1;return}if(Qs(t)){l.checked=!1,l.isPartialChecked=!0;return}l.checked=!1,l.isPartialChecked=!1},Et=({checked:l,disabled:e},t,s)=>{t.forEach(i=>{i.disabled=!!e||!!i.disabled,i.checked=!!l&&!i.disabled,i.isPartialChecked=!1;const a=ce(i,s);Et({checked:l,disabled:e},a,s)})},Mt=(l,e)=>l.some(i=>i.disabled)?!0:l.some(i=>{if(i.isGroup){const a=ce(i,e);return Mt(a,e)}return!1}),Ft=l=>l.every(e=>!!e.disabled),Zs=l=>l.every(e=>!!e.checked),Qs=l=>l.some(e=>!!e.checked||!!e.isPartialChecked),ei=l=>{l.forEach(e=>{e.checked=!1,e.isPartialChecked=!1})},ti=(l,e,t)=>{const s={level:0,groupId:\"\"},i=jt(l,e,s.groupId,s.level);return ii(i,t)},jt=(l,e,t,s)=>l.reduce((i,a)=>{var g;const h=!!((g=a.children)!=null&&g.length),d=s>=e&&h,w=s>e;if(i.push({id:a.value,name:a.name,childOf:t,isGroup:h,checked:!1,isPartialChecked:!1,level:s,isClosed:d,hidden:w,disabled:a.disabled??!1}),h){const k=jt(a.children,e,a.value,s+1);i.push(...k)}return i},[]),ce=({id:l},e)=>e.filter(t=>t.childOf===l),si=l=>{const{ungroupedNodes:e,allGroupedNodes:t,allNodes:s}=l.reduce((a,h)=>(h.checked&&(a.allNodes.push(h),h.isGroup?a.allGroupedNodes.push(h):a.ungroupedNodes.push(h)),a),{ungroupedNodes:[],allGroupedNodes:[],allNodes:[]}),i=s.filter(a=>!t.some(({id:h})=>h===a.childOf));return{ungroupedNodes:e,groupedNodes:i,allNodes:s}},ii=(l,e)=>(l.filter(s=>!!s.disabled).forEach(({id:s})=>wt({id:s,checked:!1},l,e)),l),he=(l,{id:e,isClosed:t})=>{ce({id:e},l).forEach(i=>{i.hidden=t??!1,i.isGroup&&!i.isClosed&&he(l,{id:i.id,isClosed:t})})},li=l=>{l.filter(e=>e.isGroup&&!e.disabled&&(e.checked||e.isPartialChecked)).forEach(e=>{e.isClosed=!1,he(l,e)})},ni=(l,e)=>{const t=ai(l,e);l.forEach(s=>{t.some(({id:a})=>a===s.id)?(s.isGroup&&(s.isClosed=!1,he(l,s)),s.hidden=!1):s.hidden=!0})},ai=(l,e)=>l.reduce((t,s)=>{if(s.name.toLowerCase().includes(e.toLowerCase())){if(t.push(s),s.isGroup){const a=qt(s.id,l);t.push(...a)}if(s.childOf){const a=Rt(s.childOf,l);t.push(...a)}}return t},[]),qt=(l,e)=>e.reduce((t,s)=>(s.childOf===l&&(t.push(s),s.isGroup&&t.push(...qt(s.id,e))),t),[]),Rt=(l,e)=>e.reduce((t,s)=>(s.id===l&&(t.push(s),s.childOf&&t.push(...Rt(s.childOf,e))),t),[]),oi=l=>{const{duplications:e}=l.reduce((t,s)=>(t.allItems.some(i=>i.toString()===s.id.toString())&&t.duplications.push(s.id),t.allItems.push(s.id),t),{duplications:[],allItems:[]});e.length&&console.error(`Validation: You have duplicated values: ${e.join(\", \")}! You should use unique values.`)},ri=(l,e,t,s,i,a,h,d,w,g)=>{Dt(l,e,i,w),d&&h&&li(e),de(e,t,s,a,g)},de=(l,e,t,s,i)=>{l.forEach(a=>{const h=e.querySelector(`[input-id=\"${a.id}\"]`),d=I(h);h.checked=a.checked,ci(a,d,s),hi(a,d),di(a,d),ui(a,d,t),pi(a,d),fi(a,d,l,i),mi(a,h,t)}),bi(l,e)},ci=(l,e,t)=>{l.checked?e.classList.add(\"treeselect-list__item--checked\"):e.classList.remove(\"treeselect-list__item--checked\"),Array.isArray(t)&&t[0]===l.id&&!l.disabled?e.classList.add(\"treeselect-list__item--single-selected\"):e.classList.remove(\"treeselect-list__item--single-selected\")},hi=(l,e)=>{l.isPartialChecked?e.classList.add(\"treeselect-list__item--partial-checked\"):e.classList.remove(\"treeselect-list__item--partial-checked\")},di=(l,e)=>{l.disabled?e.classList.add(\"treeselect-list__item--disabled\"):e.classList.remove(\"treeselect-list__item--disabled\")},ui=(l,e,t)=>{if(l.isGroup){const s=e.querySelector(\".treeselect-list__item-icon\"),i=l.isClosed?t.arrowRight:t.arrowDown;f(i,s),l.isClosed?e.classList.add(\"treeselect-list__item--closed\"):e.classList.remove(\"treeselect-list__item--closed\")}},pi=(l,e)=>{l.hidden?e.classList.add(\"treeselect-list__item--hidden\"):e.classList.remove(\"treeselect-list__item--hidden\")},mi=(l,e,t)=>{const i=e.parentNode.querySelector(\".treeselect-list__item-checkbox-icon\");l.checked?f(t.check,i):l.isPartialChecked?f(t.partialCheck,i):i.innerHTML=\"\"},fi=(l,e,t,s)=>{const i=l.level===0,a=20,h=5;if(i){const d=t.some(k=>k.isGroup&&k.level===l.level),w=!l.isGroup&&d?`${a}px`:`${h}px`,g=l.isGroup?\"0\":w;s?e.style.paddingRight=g:e.style.paddingLeft=g}else{const d=l.isGroup?`${l.level*a}px`:`${l.level*a+a}px`;s?e.style.paddingRight=d:e.style.paddingLeft=d}e.setAttribute(\"level\",l.level.toString()),e.setAttribute(\"group\",l.isGroup.toString())},bi=(l,e)=>{const t=l.some(i=>!i.hidden),s=e.querySelector(\".treeselect-list__empty\");t?s.classList.add(\"treeselect-list__empty--hidden\"):s.classList.remove(\"treeselect-list__empty--hidden\")},I=l=>l.parentNode.parentNode,$t=(l,e)=>e.find(t=>t.id.toString()===l),Ci=l=>I(l).querySelector(\".treeselect-list__item-icon\"),gi=(l,e)=>{e&&Object.keys(e).forEach(t=>{const s=e[t];typeof s==\"string\"&&l.setAttribute(t,s)})};class ki{constructor({options:e,value:t,openLevel:s,listSlotHtmlComponent:i,emptyText:a,isSingleSelect:h,iconElements:d,showCount:w,disabledBranchNode:g,expandSelected:k,isIndependentNodes:E,rtl:v,inputCallback:L,arrowClickCallback:N,mouseupCallback:O}){r(this,Ie);r(this,Pe);r(this,Be);r(this,Ve);r(this,De);r(this,He);r(this,K);r(this,Ge);r(this,Me);r(this,Fe);r(this,X);r(this,je);r(this,qe);r(this,Re);r(this,$e);r(this,We);r(this,Ue);r(this,ze);r(this,Ye);r(this,Ke);r(this,Xe);r(this,Je);r(this,J);r(this,Z);r(this,Ze);c(this,\"options\");c(this,\"value\");c(this,\"openLevel\");c(this,\"listSlotHtmlComponent\");c(this,\"emptyText\");c(this,\"isSingleSelect\");c(this,\"showCount\");c(this,\"disabledBranchNode\");c(this,\"expandSelected\");c(this,\"isIndependentNodes\");c(this,\"rtl\");c(this,\"iconElements\");c(this,\"searchText\");c(this,\"flattedOptions\");c(this,\"flattedOptionsBeforeSearch\");c(this,\"selectedNodes\");c(this,\"srcElement\");c(this,\"inputCallback\");c(this,\"arrowClickCallback\");c(this,\"mouseupCallback\");r(this,F,null);r(this,V,!0);r(this,_,[]);r(this,Y,!0);this.options=e,this.value=t,this.openLevel=s??0,this.listSlotHtmlComponent=i??null,this.emptyText=a??\"No results found...\",this.isSingleSelect=h??!1,this.showCount=w??!1,this.disabledBranchNode=g??!1,this.expandSelected=k??!1,this.isIndependentNodes=E??!1,this.rtl=v??!1,this.iconElements=d,this.searchText=\"\",this.flattedOptions=ti(this.options,this.openLevel,this.isIndependentNodes),this.flattedOptionsBeforeSearch=this.flattedOptions,this.selectedNodes={nodes:[],groupedNodes:[],allNodes:[]},this.srcElement=o(this,Be,ps).call(this),this.inputCallback=L,this.arrowClickCallback=N,this.mouseupCallback=O,oi(this.flattedOptions)}updateValue(e){this.value=e,C(this,_,this.isSingleSelect?this.value:[]),ri(e,this.flattedOptions,this.srcElement,this.iconElements,this.isSingleSelect,n(this,_),this.expandSelected,n(this,Y),this.isIndependentNodes,this.rtl),C(this,Y,!1),o(this,Z,Tt).call(this)}updateSearchValue(e){if(e===this.searchText)return;const t=this.searchText===\"\"&&e!==\"\";this.searchText=e,t&&(this.flattedOptionsBeforeSearch=JSON.parse(JSON.stringify(this.flattedOptions))),this.searchText===\"\"&&(this.flattedOptions=this.flattedOptionsBeforeSearch.map(s=>{const i=this.flattedOptions.find(a=>a.id===s.id);return i.isClosed=s.isClosed,i.hidden=s.hidden,i}),this.flattedOptionsBeforeSearch=[]),this.searchText&&ni(this.flattedOptions,e),de(this.flattedOptions,this.srcElement,this.iconElements,n(this,_),this.rtl),this.focusFirstListElement()}callKeyAction(e){C(this,V,!1);const t=this.srcElement.querySelector(\".treeselect-list__item--focused\");if(t==null?void 0:t.classList.contains(\"treeselect-list__item--hidden\"))return;const i=e.key;i===\"Enter\"&&t&&t.dispatchEvent(new Event(\"mousedown\")),(i===\"ArrowLeft\"||i===\"ArrowRight\")&&o(this,Ie,ds).call(this,t,e),(i===\"ArrowDown\"||i===\"ArrowUp\")&&o(this,Pe,us).call(this,t,i)}focusFirstListElement(){const e=\"treeselect-list__item--focused\",t=this.srcElement.querySelector(`.${e}`),s=Array.from(this.srcElement.querySelectorAll(\".treeselect-list__item-checkbox\")).filter(a=>window.getComputedStyle(I(a)).display!==\"none\");if(!s.length)return;t&&t.classList.remove(e),I(s[0]).classList.add(e)}isLastFocusedElementExist(){return!!n(this,F)}}F=new WeakMap,V=new WeakMap,_=new WeakMap,Y=new WeakMap,Ie=new WeakSet,ds=function(e,t){if(!e)return;const s=t.key,a=e.querySelector(\".treeselect-list__item-checkbox\").getAttribute(\"input-id\"),h=$t(a,this.flattedOptions),d=e.querySelector(\".treeselect-list__item-icon\");s===\"ArrowLeft\"&&!h.isClosed&&h.isGroup&&(d.dispatchEvent(new Event(\"mousedown\")),t.preventDefault()),s===\"ArrowRight\"&&h.isClosed&&h.isGroup&&(d.dispatchEvent(new Event(\"mousedown\")),t.preventDefault())},Pe=new WeakSet,us=function(e,t){var i;const s=Array.from(this.srcElement.querySelectorAll(\".treeselect-list__item-checkbox\")).filter(a=>window.getComputedStyle(I(a)).display!==\"none\");if(s.length)if(!e)I(s[0]).classList.add(\"treeselect-list__item--focused\");else{const a=s.findIndex(O=>I(O).classList.contains(\"treeselect-list__item--focused\"));I(s[a]).classList.remove(\"treeselect-list__item--focused\");const d=t===\"ArrowDown\"?a+1:a-1,w=t===\"ArrowDown\"?0:s.length-1,g=s[d]??s[w],k=!s[d],E=I(g);E.classList.add(\"treeselect-list__item--focused\");const v=this.srcElement.getBoundingClientRect(),L=E.getBoundingClientRect();if(k&&t===\"ArrowDown\"){this.srcElement.scroll(0,0);return}if(k&&t===\"ArrowUp\"){this.srcElement.scroll(0,this.srcElement.scrollHeight);return}const N=((i=this.listSlotHtmlComponent)==null?void 0:i.clientHeight)??0;if(v.y+v.height<L.y+L.height+N){this.srcElement.scroll(0,this.srcElement.scrollTop+L.height);return}if(v.y>L.y){this.srcElement.scroll(0,this.srcElement.scrollTop-L.height);return}}},Be=new WeakSet,ps=function(){const e=o(this,Ve,ms).call(this),t=o(this,K,St).call(this,this.options);e.append(...t);const s=o(this,Me,gs).call(this);e.append(s);const i=o(this,Ge,Cs).call(this);return i&&e.append(i),e},Ve=new WeakSet,ms=function(){const e=document.createElement(\"div\");return e.classList.add(\"treeselect-list\"),this.isSingleSelect&&e.classList.add(\"treeselect-list--single-select\"),this.disabledBranchNode&&e.classList.add(\"treeselect-list--disabled-branch-node\"),e.addEventListener(\"mouseout\",t=>o(this,De,fs).call(this,t)),e.addEventListener(\"mousemove\",()=>o(this,He,bs).call(this)),e.addEventListener(\"mouseup\",()=>this.mouseupCallback(),!0),e},De=new WeakSet,fs=function(e){e.stopPropagation(),n(this,F)&&n(this,V)&&n(this,F).classList.add(\"treeselect-list__item--focused\")},He=new WeakSet,bs=function(){C(this,V,!0)},K=new WeakSet,St=function(e){return e.reduce((t,s)=>{var a;if((a=s.children)!=null&&a.length){const h=o(this,Fe,ks).call(this,s),d=o(this,K,St).call(this,s.children);return h.append(...d),t.push(h),t}const i=o(this,X,_t).call(this,s,!1);return t.push(i),t},[])},Ge=new WeakSet,Cs=function(){if(!this.listSlotHtmlComponent)return null;const e=document.createElement(\"div\");return e.classList.add(\"treeselect-list__slot\"),e.appendChild(this.listSlotHtmlComponent),e},Me=new WeakSet,gs=function(){const e=document.createElement(\"div\");e.classList.add(\"treeselect-list__empty\"),e.setAttribute(\"title\",this.emptyText);const t=document.createElement(\"span\");t.classList.add(\"treeselect-list__empty-icon\"),f(this.iconElements.attention,t);const s=document.createElement(\"span\");return s.classList.add(\"treeselect-list__empty-text\"),s.textContent=this.emptyText,e.append(t,s),e},Fe=new WeakSet,ks=function(e){const t=document.createElement(\"div\");t.setAttribute(\"group-container-id\",e.value.toString()),t.classList.add(\"treeselect-list__group-container\");const s=o(this,X,_t).call(this,e,!0);return t.appendChild(s),t},X=new WeakSet,_t=function(e,t){const s=o(this,je,ws).call(this,e);if(t){const h=o(this,We,ys).call(this);s.appendChild(h),s.classList.add(\"treeselect-list__item--group\")}const i=o(this,ze,Ss).call(this,e),a=o(this,Ye,_s).call(this,e,t);return s.append(i,a),s},je=new WeakSet,ws=function(e){const t=document.createElement(\"div\");return gi(t,e.htmlAttr),t.setAttribute(\"tabindex\",\"-1\"),t.setAttribute(\"title\",e.name),t.classList.add(\"treeselect-list__item\"),t.addEventListener(\"mouseover\",()=>o(this,qe,Es).call(this,t),!0),t.addEventListener(\"mouseout\",()=>o(this,Re,vs).call(this,t),!0),t.addEventListener(\"mousedown\",s=>o(this,$e,Ls).call(this,s,e)),t},qe=new WeakSet,Es=function(e){n(this,V)&&o(this,J,At).call(this,!0,e)},Re=new WeakSet,vs=function(e){n(this,V)&&(o(this,J,At).call(this,!1,e),C(this,F,e))},$e=new WeakSet,Ls=function(e,t){var a;if(e.preventDefault(),e.stopPropagation(),(a=this.flattedOptions.find(h=>h.id===t.value))==null?void 0:a.disabled)return;const i=e.target.querySelector(\".treeselect-list__item-checkbox\");i.checked=!i.checked,o(this,Xe,Ts).call(this,i,t)},We=new WeakSet,ys=function(){const e=document.createElement(\"span\");return e.setAttribute(\"tabindex\",\"-1\"),e.classList.add(\"treeselect-list__item-icon\"),f(this.iconElements.arrowDown,e),e.addEventListener(\"mousedown\",t=>o(this,Ue,xs).call(this,t)),e},Ue=new WeakSet,xs=function(e){e.preventDefault(),e.stopPropagation(),o(this,Je,Ns).call(this,e)},ze=new WeakSet,Ss=function(e){const t=document.createElement(\"div\");t.classList.add(\"treeselect-list__item-checkbox-container\");const s=document.createElement(\"span\");s.classList.add(\"treeselect-list__item-checkbox-icon\"),s.innerHTML=\"\";const i=document.createElement(\"input\");return i.setAttribute(\"tabindex\",\"-1\"),i.setAttribute(\"type\",\"checkbox\"),i.setAttribute(\"input-id\",e.value.toString()),i.classList.add(\"treeselect-list__item-checkbox\"),t.append(s,i),t},Ye=new WeakSet,_s=function(e,t){const s=document.createElement(\"label\");if(s.textContent=e.name,s.classList.add(\"treeselect-list__item-label\"),t&&this.showCount){const i=o(this,Ke,As).call(this,e);s.appendChild(i)}return s},Ke=new WeakSet,As=function(e){const t=document.createElement(\"span\"),s=this.flattedOptions.filter(i=>i.childOf===e.value);return t.textContent=`(${s.length})`,t.classList.add(\"treeselect-list__item-label-counter\"),t},Xe=new WeakSet,Ts=function(e,t){const s=this.flattedOptions.find(i=>i.id===t.value);if(s){if(s!=null&&s.isGroup&&this.disabledBranchNode){const i=Ci(e);i==null||i.dispatchEvent(new Event(\"mousedown\"));return}if(this.isSingleSelect){const[i]=n(this,_);if(s.id===i)return;C(this,_,[s.id]),Dt([s.id],this.flattedOptions,this.isSingleSelect,this.isIndependentNodes)}else{s.checked=e.checked;const i=wt(s,this.flattedOptions,this.isIndependentNodes);e.checked=i}de(this.flattedOptions,this.srcElement,this.iconElements,n(this,_),this.rtl),o(this,Ze,Os).call(this)}},Je=new WeakSet,Ns=function(e){var a,h;const t=(h=(a=e.target)==null?void 0:a.parentNode)==null?void 0:h.querySelector(\"[input-id]\"),s=(t==null?void 0:t.getAttribute(\"input-id\"))??null,i=$t(s,this.flattedOptions);i&&(i.isClosed=!i.isClosed,he(this.flattedOptions,i),de(this.flattedOptions,this.srcElement,this.iconElements,n(this,_),this.rtl),this.arrowClickCallback(i.id,i.isClosed))},J=new WeakSet,At=function(e,t){const s=\"treeselect-list__item--focused\";if(e){const i=Array.from(this.srcElement.querySelectorAll(`.${s}`));i.length&&i.forEach(a=>a.classList.remove(s)),t.classList.add(s)}else t.classList.remove(s)},Z=new WeakSet,Tt=function(){const{ungroupedNodes:e,groupedNodes:t,allNodes:s}=si(this.flattedOptions);this.selectedNodes={nodes:e,groupedNodes:t,allNodes:s}},Ze=new WeakSet,Os=function(){o(this,Z,Tt).call(this),this.inputCallback(this.selectedNodes),this.value=this.selectedNodes.nodes.map(e=>e.id)};const Wt=({parentHtmlContainer:l,staticList:e,appendToBody:t,isSingleSelect:s,value:i,direction:a})=>{l||console.error(\"Validation: parentHtmlContainer prop is required!\"),e&&t&&console.error(\"Validation: You should set staticList to false if you use appendToBody!\"),s&&Array.isArray(i)&&console.error(\"Validation: if you use isSingleSelect prop, you should pass a single value!\"),!s&&!Array.isArray(i)&&console.error(\"Validation: you should pass an array as a value!\"),a&&a!==\"auto\"&&a!==\"bottom\"&&a!==\"top\"&&console.error(\"Validation: you should pass (auto | top | bottom | undefined) as a value for the direction prop!\")},ue=l=>l.map(e=>e.id),wi=l=>l?Array.isArray(l)?l:[l]:[],Ei=(l,e)=>{if(e){const[t]=l;return t??null}return l};class vi{constructor({parentHtmlContainer:e,value:t,options:s,openLevel:i,appendToBody:a,alwaysOpen:h,showTags:d,tagsCountText:w,clearable:g,searchable:k,placeholder:E,grouped:v,isGroupedValue:L,listSlotHtmlComponent:N,disabled:O,emptyText:ae,staticList:bt,id:vt,ariaLabel:Lt,isSingleSelect:Ct,showCount:Li,disabledBranchNode:yi,direction:xi,expandSelected:Si,saveScrollPosition:_i,isIndependentNodes:Ai,rtl:Ti,iconElements:Ni,inputCallback:Oi,openCallback:Ii,closeCallback:Pi,nameChangeCallback:Bi,searchCallback:Vi,openCloseGroupCallback:Di}){r(this,ee);r(this,te);r(this,Qe);r(this,et);r(this,tt);r(this,st);r(this,it);r(this,lt);r(this,se);r(this,nt);r(this,at);r(this,ot);r(this,rt);r(this,ie);r(this,ct);r(this,$);r(this,le);r(this,W);r(this,ht);r(this,ne);r(this,dt);r(this,ut);r(this,pt);r(this,mt);r(this,ft);c(this,\"parentHtmlContainer\");c(this,\"value\");c(this,\"options\");c(this,\"openLevel\");c(this,\"appendToBody\");c(this,\"alwaysOpen\");c(this,\"showTags\");c(this,\"tagsCountText\");c(this,\"clearable\");c(this,\"searchable\");c(this,\"placeholder\");c(this,\"grouped\");c(this,\"isGroupedValue\");c(this,\"listSlotHtmlComponent\");c(this,\"disabled\");c(this,\"emptyText\");c(this,\"staticList\");c(this,\"id\");c(this,\"ariaLabel\");c(this,\"isSingleSelect\");c(this,\"showCount\");c(this,\"disabledBranchNode\");c(this,\"direction\");c(this,\"expandSelected\");c(this,\"saveScrollPosition\");c(this,\"isIndependentNodes\");c(this,\"rtl\");c(this,\"iconElements\");c(this,\"inputCallback\");c(this,\"openCallback\");c(this,\"closeCallback\");c(this,\"nameChangeCallback\");c(this,\"searchCallback\");c(this,\"openCloseGroupCallback\");c(this,\"ungroupedValue\");c(this,\"groupedValue\");c(this,\"allValue\");c(this,\"isListOpened\");c(this,\"selectedName\");c(this,\"srcElement\");r(this,u,null);r(this,m,null);r(this,q,null);r(this,Q,0);r(this,R,0);r(this,A,null);r(this,T,null);r(this,S,null);r(this,D,null);Wt({parentHtmlContainer:e,value:t,staticList:bt,appendToBody:a,isSingleSelect:Ct}),this.parentHtmlContainer=e,this.value=[],this.options=s??[],this.openLevel=i??0,this.appendToBody=a??!1,this.alwaysOpen=!!(h&&!O),this.showTags=d??!0,this.tagsCountText=w??\"elements selected\",this.clearable=g??!0,this.searchable=k??!0,this.placeholder=E??\"Search...\",this.grouped=v??!0,this.isGroupedValue=L??!1,this.listSlotHtmlComponent=N??null,this.disabled=O??!1,this.emptyText=ae??\"No results found...\",this.staticList=!!(bt&&!this.appendToBody),this.id=vt??\"\",this.ariaLabel=Lt??\"\",this.isSingleSelect=Ct??!1,this.showCount=Li??!1,this.disabledBranchNode=yi??!1,this.direction=xi??\"auto\",this.expandSelected=Si??!1,this.saveScrollPosition=_i??!0,this.isIndependentNodes=Ai??!1,this.rtl=Ti??!1,this.iconElements=U(Ni),this.inputCallback=Oi,this.openCallback=Ii,this.closeCallback=Pi,this.nameChangeCallback=Bi,this.searchCallback=Vi,this.openCloseGroupCallback=Di,this.ungroupedValue=[],this.groupedValue=[],this.allValue=[],this.isListOpened=!1,this.selectedName=\"\",this.srcElement=null,o(this,ee,Nt).call(this,t)}mount(){Wt({parentHtmlContainer:this.parentHtmlContainer,value:this.value,staticList:this.staticList,appendToBody:this.appendToBody,isSingleSelect:this.isSingleSelect}),this.iconElements=U(this.iconElements),o(this,ee,Nt).call(this,this.value)}updateValue(e){const t=wi(e),s=n(this,u);s&&(s.updateValue(t),o(this,se,It).call(this,s==null?void 0:s.selectedNodes))}destroy(){this.srcElement&&(o(this,ie,Pt).call(this),this.srcElement.innerHTML=\"\",this.srcElement=null,o(this,W,kt).call(this,!0))}focus(){n(this,m)&&n(this,m).focus()}toggleOpenClose(){n(this,m)&&(n(this,m).openClose(),n(this,m).focus())}scrollWindowHandler(){this.updateListPosition()}focusWindowHandler(e){var s,i,a;((s=this.srcElement)==null?void 0:s.contains(e.target))||((i=n(this,u))==null?void 0:i.srcElement.contains(e.target))||((a=n(this,m))==null||a.blur(),o(this,W,kt).call(this,!1),o(this,$,gt).call(this,!1))}blurWindowHandler(){var e;(e=n(this,m))==null||e.blur(),o(this,W,kt).call(this,!1),o(this,$,gt).call(this,!1)}updateListPosition(){var N;const e=this.srcElement,t=(N=n(this,u))==null?void 0:N.srcElement;if(!e||!t)return;const{height:s}=t.getBoundingClientRect(),{x:i,y:a,height:h,width:d}=e.getBoundingClientRect(),w=window.innerHeight,g=a,k=w-a-h;let E=g>k&&g>=s&&k<s;if(this.direction!==\"auto\"&&(E=this.direction===\"top\"),this.appendToBody){(t.style.top!==\"0px\"||t.style.left!==\"0px\")&&(t.style.top=\"0px\",t.style.left=\"0px\");const O=i+window.scrollX,ae=E?a+window.scrollY-s:a+window.scrollY+h;t.style.transform=`translate(${O}px,${ae}px)`,t.style.width=`${d}px`}const v=E?\"top\":\"bottom\";t.getAttribute(\"direction\")!==v&&(t.setAttribute(\"direction\",v),o(this,ct,qs).call(this,E,this.appendToBody))}}return u=new WeakMap,m=new WeakMap,q=new WeakMap,Q=new WeakMap,R=new WeakMap,A=new WeakMap,T=new WeakMap,S=new WeakMap,D=new WeakMap,ee=new WeakSet,Nt=function(e){var a;this.destroy();const{container:t,list:s,input:i}=o(this,Qe,Is).call(this);this.srcElement=t,C(this,u,s),C(this,m,i),C(this,A,this.scrollWindowHandler.bind(this)),C(this,T,this.scrollWindowHandler.bind(this)),C(this,S,this.focusWindowHandler.bind(this)),C(this,D,this.blurWindowHandler.bind(this)),this.alwaysOpen&&((a=n(this,m))==null||a.openClose()),this.disabled?this.srcElement.classList.add(\"treeselect--disabled\"):this.srcElement.classList.remove(\"treeselect--disabled\"),this.updateValue(e??this.value)},te=new WeakSet,Ot=function({groupedNodes:e,nodes:t,allNodes:s}){this.ungroupedValue=t?ue(t):[],this.groupedValue=e?ue(e):[],this.allValue=s?ue(s):[];let i=[];this.isIndependentNodes||this.isSingleSelect?i=this.allValue:this.isGroupedValue?i=this.groupedValue:i=this.ungroupedValue,this.value=Ei(i,this.isSingleSelect)},Qe=new WeakSet,Is=function(){const e=this.parentHtmlContainer;e.classList.add(\"treeselect\"),this.rtl&&e.setAttribute(\"dir\",\"rtl\");const t=new ki({value:[],options:this.options,openLevel:this.openLevel,listSlotHtmlComponent:this.listSlotHtmlComponent,emptyText:this.emptyText,isSingleSelect:this.isSingleSelect,showCount:this.showCount,disabledBranchNode:this.disabledBranchNode,expandSelected:this.expandSelected,isIndependentNodes:this.isIndependentNodes,rtl:this.rtl,iconElements:this.iconElements,inputCallback:i=>o(this,nt,Gs).call(this,i),arrowClickCallback:(i,a)=>o(this,at,Ms).call(this,i,a),mouseupCallback:()=>{var i;return(i=n(this,m))==null?void 0:i.focus()}}),s=new Xs({value:[],showTags:this.showTags,tagsCountText:this.tagsCountText,clearable:this.clearable,isAlwaysOpened:this.alwaysOpen,searchable:this.searchable,placeholder:this.placeholder,disabled:this.disabled,isSingleSelect:this.isSingleSelect,id:this.id,ariaLabel:this.ariaLabel,iconElements:this.iconElements,inputCallback:i=>o(this,et,Ps).call(this,i),searchCallback:i=>o(this,st,Vs).call(this,i),openCallback:()=>o(this,rt,js).call(this),closeCallback:()=>o(this,ie,Pt).call(this),keydownCallback:i=>o(this,tt,Bs).call(this,i),focusCallback:()=>o(this,it,Ds).call(this),blurCallback:()=>o(this,lt,Hs).call(this),nameChangeCallback:i=>o(this,ot,Fs).call(this,i)});return this.appendToBody&&C(this,q,new ResizeObserver(()=>this.updateListPosition())),e.append(s.srcElement),{container:e,list:t,input:s}},et=new WeakSet,Ps=function(e){var i,a;const t=ue(e);(i=n(this,u))==null||i.updateValue(t);const s=((a=n(this,u))==null?void 0:a.selectedNodes)??{};o(this,te,Ot).call(this,s),o(this,ne,Vt).call(this)},tt=new WeakSet,Bs=function(e){var t;this.isListOpened&&((t=n(this,u))==null||t.callKeyAction(e))},st=new WeakSet,Vs=function(e){n(this,R)&&clearTimeout(n(this,R)),C(this,R,window.setTimeout(()=>{var t;(t=n(this,u))==null||t.updateSearchValue(e),this.updateListPosition()},350)),o(this,mt,zs).call(this,e)},it=new WeakSet,Ds=function(){o(this,$,gt).call(this,!0),n(this,S)&&n(this,S)&&n(this,D)&&(document.addEventListener(\"mousedown\",n(this,S),!0),document.addEventListener(\"focus\",n(this,S),!0),window.addEventListener(\"blur\",n(this,D)))},lt=new WeakSet,Hs=function(){setTimeout(()=>{var s,i;const e=(s=n(this,m))==null?void 0:s.srcElement.contains(document.activeElement),t=(i=n(this,u))==null?void 0:i.srcElement.contains(document.activeElement);!e&&!t&&this.blurWindowHandler()},1)},se=new WeakSet,It=function(e){var s;if(!e)return;let t=[];this.isIndependentNodes||this.isSingleSelect?t=e.allNodes:this.grouped?t=e.groupedNodes:t=e.nodes,(s=n(this,m))==null||s.updateValue(t),o(this,te,Ot).call(this,e)},nt=new WeakSet,Gs=function(e){var t,s,i;o(this,se,It).call(this,e),this.isSingleSelect&&!this.alwaysOpen&&((t=n(this,m))==null||t.openClose(),(s=n(this,m))==null||s.clearSearch()),(i=n(this,m))==null||i.focus(),o(this,ne,Vt).call(this)},at=new WeakSet,Ms=function(e,t){var s;(s=n(this,m))==null||s.focus(),this.updateListPosition(),o(this,ft,Ys).call(this,e,t)},ot=new WeakSet,Fs=function(e){this.selectedName!==e&&(this.selectedName=e,o(this,dt,$s).call(this))},rt=new WeakSet,js=function(){var e;this.isListOpened=!0,n(this,A)&&n(this,T)&&(window.addEventListener(\"scroll\",n(this,A),!0),window.addEventListener(\"resize\",n(this,T))),!(!n(this,u)||!this.srcElement)&&(this.appendToBody?(document.body.appendChild(n(this,u).srcElement),(e=n(this,q))==null||e.observe(this.srcElement)):this.srcElement.appendChild(n(this,u).srcElement),this.updateListPosition(),o(this,le,Bt).call(this,!0),o(this,ht,Rs).call(this),o(this,ut,Ws).call(this))},ie=new WeakSet,Pt=function(){var t;this.alwaysOpen||(this.isListOpened=!1,n(this,A)&&n(this,T)&&(window.removeEventListener(\"scroll\",n(this,A),!0),window.removeEventListener(\"resize\",n(this,T))),!n(this,u)||!this.srcElement)||!(this.appendToBody?document.body.contains(n(this,u).srcElement):this.srcElement.contains(n(this,u).srcElement))||(C(this,Q,n(this,u).srcElement.scrollTop),this.appendToBody?(document.body.removeChild(n(this,u).srcElement),(t=n(this,q))==null||t.disconnect()):this.srcElement.removeChild(n(this,u).srcElement),o(this,le,Bt).call(this,!1),o(this,pt,Us).call(this))},ct=new WeakSet,qs=function(e,t){if(!n(this,u)||!n(this,m))return;const s=t?\"treeselect-list--top-to-body\":\"treeselect-list--top\",i=t?\"treeselect-list--bottom-to-body\":\"treeselect-list--bottom\";e?(n(this,u).srcElement.classList.add(s),n(this,u).srcElement.classList.remove(i),n(this,m).srcElement.classList.add(\"treeselect-input--top\"),n(this,m).srcElement.classList.remove(\"treeselect-input--bottom\")):(n(this,u).srcElement.classList.remove(s),n(this,u).srcElement.classList.add(i),n(this,m).srcElement.classList.remove(\"treeselect-input--top\"),n(this,m).srcElement.classList.add(\"treeselect-input--bottom\"))},$=new WeakSet,gt=function(e){!n(this,m)||!n(this,u)||(e?(n(this,m).srcElement.classList.add(\"treeselect-input--focused\"),n(this,u).srcElement.classList.add(\"treeselect-list--focused\")):(n(this,m).srcElement.classList.remove(\"treeselect-input--focused\"),n(this,u).srcElement.classList.remove(\"treeselect-list--focused\")))},le=new WeakSet,Bt=function(e){var t,s,i,a;e?(t=n(this,m))==null||t.srcElement.classList.add(\"treeselect-input--opened\"):(s=n(this,m))==null||s.srcElement.classList.remove(\"treeselect-input--opened\"),this.staticList?(i=n(this,u))==null||i.srcElement.classList.add(\"treeselect-list--static\"):(a=n(this,u))==null||a.srcElement.classList.remove(\"treeselect-list--static\")},W=new WeakSet,kt=function(e){!n(this,A)||!n(this,T)||!n(this,S)||!n(this,D)||((!this.alwaysOpen||e)&&(window.removeEventListener(\"scroll\",n(this,A),!0),window.removeEventListener(\"resize\",n(this,T))),document.removeEventListener(\"mousedown\",n(this,S),!0),document.removeEventListener(\"focus\",n(this,S),!0),window.removeEventListener(\"blur\",n(this,D)))},ht=new WeakSet,Rs=function(){var t,s,i;const e=(t=n(this,u))==null?void 0:t.isLastFocusedElementExist();this.saveScrollPosition&&e?(s=n(this,u))==null||s.srcElement.scroll(0,n(this,Q)):(i=n(this,u))==null||i.focusFirstListElement()},ne=new WeakSet,Vt=function(){var e;(e=this.srcElement)==null||e.dispatchEvent(new CustomEvent(\"input\",{detail:this.value})),this.inputCallback&&this.inputCallback(this.value)},dt=new WeakSet,$s=function(){var e;(e=this.srcElement)==null||e.dispatchEvent(new CustomEvent(\"name-change\",{detail:this.selectedName})),this.nameChangeCallback&&this.nameChangeCallback(this.selectedName)},ut=new WeakSet,Ws=function(){var e;this.alwaysOpen||((e=this.srcElement)==null||e.dispatchEvent(new CustomEvent(\"open\",{detail:this.value})),this.openCallback&&this.openCallback(this.value))},pt=new WeakSet,Us=function(){var e;this.alwaysOpen||((e=this.srcElement)==null||e.dispatchEvent(new CustomEvent(\"close\",{detail:this.value})),this.closeCallback&&this.closeCallback(this.value))},mt=new WeakSet,zs=function(e){var s;const t=(e==null?void 0:e.trim())??\"\";(s=this.srcElement)==null||s.dispatchEvent(new CustomEvent(\"search\",{detail:t})),this.searchCallback&&this.searchCallback(t)},ft=new WeakSet,Ys=function(e,t){var s;(s=this.srcElement)==null||s.dispatchEvent(new CustomEvent(\"open-close-group\",{detail:{groupId:e,isClosed:t}})),this.openCloseGroupCallback&&this.openCloseGroupCallback(e,t)},vi});","Mageplaza_Blog/js/postAction.js":"    /**\r\n     * Mageplaza\r\n     *\r\n     * NOTICE OF LICENSE\r\n     *\r\n     * This source file is subject to the Mageplaza.com license that is\r\n     * available through the world-wide-web at this URL:\r\n     * https://www.mageplaza.com/LICENSE.txt\r\n     *\r\n     * DISCLAIMER\r\n     *\r\n     * Do not edit or add to this file if you wish to upgrade this extension to newer\r\n     * version in the future.\r\n     *\r\n     * @category    Mageplaza\r\n     * @package     Mageplaza_Blog\r\n     * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)\r\n     * @license     https://www.mageplaza.com/LICENSE.txt\r\n     */\r\n    define([\r\n        'jquery',\r\n        \"mage/adminhtml/events\",\r\n        \"mage/adminhtml/wysiwyg/tiny_mce/setup\"\r\n    ], function ($) {\r\n        'use strict';\r\n\r\n        $.widget('mageplaza.mpBlogPostAction', {\r\n                options: {},\r\n                _create: function () {\r\n                    var self = this;\r\n\r\n                    $('button.mpblog-action-new').on('click', function () {\r\n                        self._AddNew();\r\n                    });\r\n                },\r\n                _AddNew: function () {\r\n                    var form      = $('#mp_blog_post_form'),\r\n                        formData  = new FormData(form[0]),\r\n                        htmlPopup = $('#mp-blog-new-post-popup'),\r\n                        url       = form.attr('action');\r\n                    $.ajax({\r\n                        url: url,\r\n                        type: \"post\",\r\n                        data: formData,\r\n                        cache: false,\r\n                        contentType: false,\r\n                        processData: false,\r\n                        showLoader: true,\r\n                        success: function (result) {\r\n                            htmlPopup.data('mageModal').closeModal();\r\n                            if (result.status === 1) {\r\n                                setTimeout(function () {\r\n                                    location.reload();\r\n                                }, 500);\r\n                            }\r\n                        }\r\n                    });\r\n                }\r\n            }\r\n        );\r\n\r\n        return $.mageplaza.mpBlogPostAction;\r\n    });\r\n","Mageplaza_Blog/js/comment.js":"/**\r\n * Mageplaza\r\n *\r\n * NOTICE OF LICENSE\r\n *\r\n * This source file is subject to the Mageplaza.com license that is\r\n * available through the world-wide-web at this URL:\r\n * https://www.mageplaza.com/LICENSE.txt\r\n *\r\n * DISCLAIMER\r\n *\r\n * Do not edit or add to this file if you wish to upgrade this extension to newer\r\n * version in the future.\r\n *\r\n * @category    Mageplaza\r\n * @package     Mageplaza_Blog\r\n * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)\r\n * @license     https://www.mageplaza.com/LICENSE.txt\r\n */\r\n\r\n\r\nrequire([\r\n    'jquery'\r\n], function ($) {\r\n    'use strict';\r\n\r\n    var cmtBox = $('.default-cmt__content__cmt-block__cmt-box__cmt-input'),\r\n        submitCmt = $('.default-cmt__content__cmt-block__cmt-box__cmt-btn__btn-submit'),\r\n        defaultCmt = $('ul.default-cmt__content__cmt-content:first'),\r\n        likeBtn = defaultCmt.find('.btn-like'),\r\n        replyBtn = defaultCmt.find('.btn-reply');\r\n\r\n    submitComment();\r\n    likeComment(likeBtn);\r\n    showReply(replyBtn);\r\n\r\n    $('li.default-cmt__content__cmt-content__cmt-row:first').css({'border-top': 'none'});\r\n    $('.default-cmt__cmt-login__btn-login').click(function () {\r\n        var socialPopup = $(\"[href$='social-login-popup']\");\r\n\r\n        if (socialPopup.length) {\r\n            socialPopup.first().trigger(\"click\");\r\n        } else {\r\n            window.location.href = loginUrl;\r\n        }\r\n    });\r\n\r\n    /**\r\n     * Check the guest name and email input is valid\r\n     *\r\n     * @returns {boolean}\r\n     */\r\n    function checkGuestFormValidate() {\r\n        if (isLogged == 'No') {\r\n            return $(\"#default-cmt__content__cmt-block__guest-form\").valid();\r\n        }\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * The comment submit button action\r\n     */\r\n    function submitComment() {\r\n        submitCmt.click(function () {\r\n            $(\".default-cmt__content__cmt-block__cmt-box\").find('.messages').hide();\r\n            if (checkGuestFormValidate()) {\r\n                var cmtText = cmtBox.val();\r\n\r\n                if (cmtText.trim().length) {\r\n                    $('.default-cmt_loading').show();\r\n                    $(this).prop('disabled', true);\r\n                    var ajaxRequest = ajaxCommentActions(cmtText, submitCmt);\r\n                    ajaxRequest.done(function () {\r\n                        cmtBox.val('');\r\n                        $('.default-cmt_loading').hide();\r\n                        $(this).prop('disabled', false);\r\n                    }.bind(this));\r\n                } else {\r\n                    $('.default-cmt__content__cmt-block__cmt-box__cmt-input').parent().append(messengerBox.cmt_warning);\r\n                }\r\n            }\r\n        });\r\n    }\r\n\r\n    //like action\r\n    function likeComment(btn) {\r\n        btn.each(function () {\r\n            var likeEl = $(this);\r\n\r\n            likeEl.click(function () {\r\n                var cmtId = $(this).attr('data-cmt-id'),\r\n                    cmtRowContainer = $(this).closest('.default-cmt__content__cmt-content__cmt-row');\r\n                if (isLogged === 'Yes') {\r\n                    var likeCount = $(this).find('span').text();\r\n                    if ($(this).attr('click') === '1') {\r\n                        if ($(this).hasClass('mpblog-liked')) {\r\n                            $(this).css('color', '#333333');\r\n                            likeCount--;\r\n                            $(this).find('span').text((likeCount === 0) ? \"\" : likeCount);\r\n                            $(this).removeClass('mpblog-liked')\r\n\r\n                        } else {\r\n                            likeCount++;\r\n                            $(this).find('span').text(likeCount);\r\n                            $(this).css('color', likedColor);\r\n                            $(this).addClass('mpblog-liked')\r\n                        }\r\n                        $.ajax({\r\n                            type: \"POST\",\r\n                            url: window.location.href,\r\n                            data: {cmtId: cmtId},\r\n                            success: function (response) {\r\n                                if (response.status === 'ok') {\r\n                                    $(likeEl).attr('click', '1');\r\n                                } else if (response.status === 'error' && response.hasOwnProperty(error)) {\r\n                                    defaultCmt.append(response.error);\r\n                                }\r\n                            }\r\n                        });\r\n                    }\r\n                    $(this).attr('click', '0');\r\n\r\n                } else {\r\n                    cmtRowContainer.append(messengerBox.login_warning);\r\n                    jQuery.fn.fadeOutAndRemove = function (speed) {\r\n                        $(this).fadeOut(speed, function () {\r\n                            $(this).remove();\r\n                        })\r\n                    };\r\n                    var removeNotification = function () {\r\n                        $('.message.error.message-error').fadeOutAndRemove('normal');\r\n                    };\r\n                    setTimeout(removeNotification, 3000);\r\n                }\r\n\r\n            });\r\n        });\r\n    }\r\n\r\n    //show reply\r\n    function showReply(btn) {\r\n        btn.each(function () {\r\n\r\n            $(this).click(function () {\r\n                var cmtId = (typeof $(this).closest('.default-cmt__content__cmt-content__cmt-row').parent().parent().parent().parent().attr('data-cmt-id') !== 'undefined') ? $(this).closest('.default-cmt__content__cmt-content__cmt-row').parent().parent().attr('data-cmt-id') : $(this).attr('data-cmt-id'),\r\n                    inputCmtID = $(this).attr('data-cmt-id'),\r\n                    cmtRowCmt = $(\"div\").find('#cmt-row');\r\n                var cmtRowContainer = $(this).closest('.default-cmt__content__cmt-content__cmt-row');\r\n                if ($(\"li.cmt-row-\" + cmtId).find(\"ul\").length) {\r\n                    var cmtRowContainer = $(\"#cmt-id-\" + cmtId + \" ul:last-child\");\r\n                }\r\n                var cmtRow = cmtRowContainer.find('.row__' + inputCmtID);\r\n                var cmtName = $(\".username__\" + inputCmtID).text();\r\n\r\n                if (isLogged === 'Yes') {\r\n                    if (cmtRowCmt.length) {\r\n                        cmtRowCmt.toggle();\r\n                        $(\"#cmt-row\").remove();\r\n                    }\r\n                    if (cmtRow.length) {\r\n                        cmtRow.toggle();\r\n                        $(\"#cmt-row\").remove();\r\n                    } else {\r\n                        cmtRowContainer.append('<div id=\"cmt-row\" class=\"cmt-row__reply-row row row__' + inputCmtID + ' col-md-12\">' +\r\n                            '<div class=\"reply-form__form-input form-group col-xs-8 col-md-6\">' +\r\n                            '<label for=\"reply_cmt' + inputCmtID + '\"></label>' +\r\n                            '<input type=\"text\" id=\"reply_cmt' + inputCmtID + '\" class=\"form-group__input form-control\" placeholder=\"Press enter to submit reply\" value=\"' + cmtName + ' \" autofocus onfocus=\"this.setSelectionRange(1000,1001);\"/>' +\r\n                            '</div>' +\r\n                            '</div>');\r\n                        var input = $('#reply_cmt' + inputCmtID);\r\n                        input.closest('.form-group').append(\r\n                            $('.default-cmt__content__cmt-block__cmt-box__cmt-btn .default-cmt_loading').clone()\r\n                        );\r\n                        input.focus();\r\n                        submitReply(input, cmtId, cmtRowContainer);\r\n                    }\r\n                } else {\r\n                    cmtRowContainer.append(messengerBox.login_warning);\r\n                    jQuery.fn.fadeOutAndRemove = function (speed) {\r\n                        $(this).fadeOut(speed, function () {\r\n                            $(this).remove();\r\n                        })\r\n                    };\r\n                    var removeNotification = function () {\r\n                        $('.message.error.message-error').fadeOutAndRemove('normal');\r\n                    };\r\n                    setTimeout(removeNotification, 3000);\r\n                }\r\n            });\r\n        });\r\n    }\r\n\r\n    //submit reply\r\n    function submitReply(input, replyId, parentComment) {\r\n        input.keypress(function (e) {\r\n            var text = input.val();\r\n            if (text !== '') {\r\n                if (e.keyCode === 13) {\r\n                    input.siblings('.default-cmt_loading').show();\r\n                    input.prop('disabled', true);\r\n                    var ajaxRequest = ajaxCommentActions(text, input, true, replyId, parentComment);\r\n                    ajaxRequest.done(function () {\r\n                        input.closest('.cmt-row__reply-row').hide();\r\n                        input.siblings('.default-cmt_loading').hide();\r\n                        input.prop('disabled', false);\r\n                        $(\"#cmt-row\").remove();\r\n                    });\r\n                }\r\n            }\r\n        });\r\n    }\r\n\r\n    //submit comment actions\r\n    function ajaxCommentActions(cmtText, inputEl, checkReply, cmtId, parentComment) {\r\n        var isReply = (typeof checkReply !== 'undefined') ? 1 : 0,\r\n            replyId = (typeof cmtId !== 'undefined') ? cmtId : 0,\r\n            displayReply = (typeof checkReply !== 'undefined');\r\n        var guestName = $('#default-cmt__content__cmt-block__guest-box__name-input').val();\r\n        var guestEmail = $('#default-cmt__content__cmt-block__guest-box__email-input').val();\r\n        return $.ajax({\r\n            type: 'POST',\r\n            url: window.location.href,\r\n            // async: false,\r\n            data: {cmt_text: cmtText, isReply: isReply, replyId: replyId, guestName: guestName, guestEmail: guestEmail},\r\n            success: function (response) {\r\n                switch (response.status) {\r\n                    case 'duplicated':\r\n                        $('.default-cmt__content__cmt-block__cmt-box__cmt-input').parent().append(messengerBox.exist_email_warning);\r\n                        break;\r\n                    case 3:\r\n                        $('.default-cmt__content__cmt-block').prepend(messengerBox.comment_approve);\r\n                        break;\r\n                    case 1:\r\n                        displayComment(response, displayReply);\r\n                        var cmtCount = defaultCmt.find('li').length;\r\n                        $('.mp-cmt-count').text(cmtCount);\r\n                        inputEl.val('');\r\n                        break;\r\n                    case 'error':\r\n                        if (checkReply !== 'undefined') {\r\n                            parentComment.append(response.error);\r\n                        } else {\r\n                            defaultCmt.append(response.error);\r\n                        }\r\n                        break;\r\n                }\r\n            }\r\n        });\r\n    }\r\n\r\n    // display comment\r\n    function displayComment(cmt, isReply) {\r\n        function htmlComment(text) {\r\n            var html = '';\r\n            var sub = text.split(\"\\n\");\r\n            for (var i = 0; i < sub.length; i++) {\r\n                html += '<p>' + sub[i] + '</p>';\r\n            }\r\n            return html;\r\n        }\r\n        var cmtRow = '<li style=\"width: 100%\" id=\"cmt-id-' + cmt.cmt_id + '\" class=\"default-cmt__content__cmt-content__cmt-row cmt-row-' + cmt.cmt_id + ' cmt-row col-m-12 '\r\n            + (isReply ? ('reply-row') : '') + '\" data-cmt-id=\"' + cmt.cmt_id + '\"' + (isReply ? ('data-reply-id=\"' + cmt.reply_cmt + '\"') : '')\r\n            + '> <div class=\"cmt-row__cmt-username\"> <span class=\"cmt-row__cmt-username username username__' + cmt.cmt_id + '\">' + cmt.user_cmt\r\n            + '</span> </div> <div class=\"cmt-row__cmt-content\"> <p>' + htmlComment(cmt.cmt_text)\r\n            + '</p> </div> <div class=\"cmt-row__cmt-interactions interactions\"> <div class=\"interactions__btn-actions\"> <a class=\"interactions__btn-actions action btn-like mpblog-like\" data-cmt-id=\"'\r\n            + cmt.cmt_id + '\" click=\"1\"><i class=\"fa fa-thumbs-up\" aria-hidden=\"true\" style=\"margin-right: 3px\"></i><span class=\"count-like__like-text\"></span></a> <a class=\"interactions__btn-actions action btn-reply\" data-cmt-id=\"'\r\n            + cmt.cmt_id + '\">' + reply + '</a>  </div> <div class=\"interactions__cmt-createdat\"> <span>' + cmt.created_at + '</span> </div> </div> </li>';\r\n\r\n        if (isReply) {\r\n            var replyCmtId = cmt.reply_cmt;\r\n            var replyCmt = defaultCmt.find('.default-cmt__content__cmt-content__cmt-row');\r\n\r\n            replyCmt.each(function () {\r\n                var cmtEl = $(this);\r\n                if (cmtEl.attr('data-cmt-id') === replyCmtId) {\r\n                    var replyList = cmtEl.find('ul.default-cmt__content__cmt-content:first');\r\n\r\n                    if (!replyList.length) {\r\n                        cmtRow = $('<ul class=\"default-cmt__content__cmt-content row\">' + cmtRow + '</ul>');\r\n                        cmtEl.append(cmtRow);\r\n\r\n                        likeComment(cmtRow.find('.btn-like'));\r\n                        showReply(cmtRow.find('.btn-reply'));\r\n                    } else {\r\n                        cmtRow = $(cmtRow);\r\n                        replyList.append(cmtRow);\r\n\r\n                        likeComment(cmtRow.find('.btn-like'));\r\n                        showReply(cmtRow.find('.btn-reply'));\r\n\r\n                    }\r\n\r\n                    return false;\r\n                }\r\n            });\r\n        } else {\r\n            cmtRow = $(cmtRow);\r\n            defaultCmt.append(cmtRow);\r\n\r\n            likeComment(cmtRow.find('.btn-like'));\r\n            showReply(cmtRow.find('.btn-reply'));\r\n        }\r\n    }\r\n});\r\n","Mageplaza_Blog/js/helpful-rate.js":"/**\r\n * Mageplaza\r\n *\r\n * NOTICE OF LICENSE\r\n *\r\n * This source file is subject to the Mageplaza.com license that is\r\n * available through the world-wide-web at this URL:\r\n * https://www.mageplaza.com/LICENSE.txt\r\n *\r\n * DISCLAIMER\r\n *\r\n * Do not edit or add to this file if you wish to upgrade this extension to newer\r\n * version in the future.\r\n *\r\n * @category    Mageplaza\r\n * @package     Mageplaza_Blog\r\n * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)\r\n * @license     https://www.mageplaza.com/LICENSE.txt\r\n */\r\ndefine([\r\n    'jquery'\r\n], function ($) {\r\n    'use strict';\r\n\r\n    $.widget('mageplaza.mpBlogHelpfulRate', {\r\n            options: {\r\n                url: '',\r\n                post_id: '',\r\n                mode: ''\r\n            },\r\n            _create: function () {\r\n                var post_id   = this.options.post_id,\r\n                    url       = this.options.url,\r\n                    self      = this,\r\n                    subPostId = {};\r\n\r\n                if (self.options.mode === 1) {\r\n                    $.ajax({\r\n                        url: url,\r\n                        type: \"post\",\r\n                        data: {\r\n                            post_id: post_id,\r\n                            action: '3',\r\n                            mode: self.options.mode\r\n                        },\r\n                        showLoader: false,\r\n                        success: function (response) {\r\n                            if (response.status === 0) {\r\n                                self.disableReview(response.action);\r\n                            }\r\n                        }\r\n                    });\r\n                } else if (JSON.parse(self.getCookie('mpblog_post_data'))) {\r\n                    subPostId = JSON.parse(self.getCookie('mpblog_post_data'));\r\n                    if (typeof subPostId[post_id] !== \"undefined\") {\r\n                        self.disableReview(subPostId[post_id].type);\r\n                    }\r\n                }\r\n\r\n                $('#mp-blog-review div').each(function () {\r\n                    var el = this;\r\n\r\n\r\n                    $(el).on('click', function () {\r\n                        var action         = 0,\r\n                            currentPostIds = {},\r\n                            likeId         = 0;\r\n\r\n                        if (JSON.parse(self.getCookie('mpblog_post_data'))) {\r\n                            currentPostIds = JSON.parse(self.getCookie('mpblog_post_data'));\r\n                        }\r\n\r\n                        if ($(this).hasClass('mp-blog-like')) {\r\n                            action = 1;\r\n                        }\r\n\r\n                        if (typeof currentPostIds[post_id] !== \"undefined\" && self.options.mode === 0) {\r\n                            likeId = currentPostIds[post_id].likeId;\r\n                            self.enableReview(currentPostIds[post_id].type);\r\n                            if (action === currentPostIds[post_id].type) {\r\n                                delete currentPostIds[post_id];\r\n                                document.cookie = 'mpblog_post_data = ' + JSON.stringify(currentPostIds);\r\n                            } else {\r\n                                currentPostIds[post_id].type = action;\r\n                                self.disableReview(action);\r\n                            }\r\n                        }\r\n                        $.ajax({\r\n                            url: url,\r\n                            type: \"post\",\r\n                            data: {\r\n                                post_id: post_id,\r\n                                action: action,\r\n                                mode: self.options.mode,\r\n                                likeId: likeId\r\n                            },\r\n                            showLoader: true,\r\n                            success: function (response) {\r\n                                var storedPostIds,\r\n                                    jsonStringIds;\r\n\r\n                                if (response['postLike']\r\n                                    && self.options.mode === 0 && typeof currentPostIds[post_id] === \"undefined\") {\r\n                                    storedPostIds   =\r\n                                        self.receiveCookiePostIds(post_id, action, response['postLike'], self);\r\n                                    jsonStringIds   = JSON.stringify(storedPostIds);\r\n                                    document.cookie = 'mpblog_post_data = ' + jsonStringIds;\r\n                                }\r\n\r\n                                if (response['status']) {\r\n                                    if (response[\"sumLike\"]) {\r\n                                        $('#mp-blog-review .mp-blog-like .mp-blog-view')\r\n                                        .text('(' + response[\"sumLike\"] + ')');\r\n                                    } else {\r\n                                        $('#mp-blog-review .mp-blog-like .mp-blog-view')\r\n                                        .text('');\r\n                                    }\r\n                                    if (response[\"sumDislike\"]) {\r\n                                        $('#mp-blog-review .mp-blog-dislike .mp-blog-view')\r\n                                        .text('(' + response[\"sumDislike\"] + ')');\r\n                                    } else {\r\n                                        $('#mp-blog-review .mp-blog-dislike .mp-blog-view')\r\n                                        .text('');\r\n                                    }\r\n                                }\r\n\r\n                                if (response['status']) {\r\n                                    self.enableAllReview();\r\n                                    if (response['postLike']) {\r\n                                        self.disableReview(action);\r\n                                    }\r\n                                }\r\n\r\n                                $('html, body').animate({\r\n                                    scrollTop: $('body').offset().top\r\n                                }, 500);\r\n                            }\r\n                        });\r\n\r\n                    });\r\n                });\r\n            },\r\n            disableReview: function (action) {\r\n                if ('' + action === '1') {\r\n                    $('.mp-blog-like').css('background-color', '#658259');\r\n\r\n                } else {\r\n                    $('.mp-blog-dislike').css('background-color', '#9a6464');\r\n                }\r\n            },\r\n            enableReview: function (action) {\r\n                if ('' + action === '1') {\r\n                    $('.mp-blog-like').css('background-color', '#6AA84F');\r\n\r\n                } else {\r\n                    $('.mp-blog-dislike').css('background-color', '#EC3A3C');\r\n                }\r\n            },\r\n            enableAllReview: function () {\r\n                $('.mp-blog-like').css('background-color', '#6AA84F');\r\n                $('.mp-blog-dislike').css('background-color', '#EC3A3C');\r\n\r\n            },\r\n            getCookie: function (name) {\r\n                var v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');\r\n\r\n                return v ? v[2] : null;\r\n            },\r\n            receiveCookiePostIds: function (postId, action, likeId, self) {\r\n                var postData        = {\r\n                        id: postId,\r\n                        type: action,\r\n                        likeId: likeId\r\n                    },\r\n                    receivedJsonStr = self.getCookie('mpblog_post_data'),\r\n                    postIds         = JSON.parse(receivedJsonStr);\r\n\r\n                if (postIds == null) {\r\n                    postIds = {};\r\n                }\r\n                if (typeof postIds[postId] !== \"undefined\") {\r\n\r\n                    return postIds;\r\n                }\r\n                postIds[postId] = postData;\r\n\r\n                return postIds;\r\n            }\r\n        }\r\n    );\r\n\r\n    return $.mageplaza.mpBlogHelpfulRate;\r\n});\r\n","Mageplaza_Blog/js/managePost.js":"/**\r\n * Mageplaza\r\n *\r\n * NOTICE OF LICENSE\r\n *\r\n * This source file is subject to the Mageplaza.com license that is\r\n * available through the world-wide-web at this URL:\r\n * https://www.mageplaza.com/LICENSE.txt\r\n *\r\n * DISCLAIMER\r\n *\r\n * Do not edit or add to this file if you wish to upgrade this extension to newer\r\n * version in the future.\r\n *\r\n * @category    Mageplaza\r\n * @package     Mageplaza_Blog\r\n * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)\r\n * @license     https://www.mageplaza.com/LICENSE.txt\r\n */\r\ndefine([\r\n    'jquery',\r\n    'mage/translate',\r\n    'underscore',\r\n    'Magento_Ui/js/modal/modal',\r\n    'uiRegistry',\r\n    'moment',\r\n    \"Mageplaza_Blog/js/get-editor\"\r\n], function ($, $t, _, modal, registry, moment, editor) {\r\n    'use strict';\r\n\r\n    $.widget('mageplaza.mpBlogManagePost', {\r\n            options: {\r\n                deleteUrl: '',\r\n                basePubUrl: '',\r\n                postDatas: {},\r\n                editorVersion: '',\r\n                magentoVersion: ''\r\n            },\r\n            _create: function () {\r\n                var self      = this,\r\n                    htmlPopup = $('#mp-blog-new-post-popup');\r\n\r\n                $('.mp-blog-new-post button').on('click', function () {\r\n                    self._AddNewPost(self, htmlPopup);\r\n                });\r\n\r\n                $('.mpblog-post-edit').on('click', function () {\r\n                    self._EditPost(self, this, htmlPopup);\r\n                });\r\n\r\n                $('.mpblog-post-duplicate').on('click', function () {\r\n                    self._DuplicatePost(self, this, htmlPopup);\r\n                });\r\n\r\n                $('.mpblog-post-delete').on('click', function () {\r\n                    self._DeletePost(self, this);\r\n                });\r\n            },\r\n            _AddNewPost: function (self, htmlPopup) {\r\n                var options = {\r\n                    'type': 'popup',\r\n                    'title': $t('Add New Post'),\r\n                    'responsive': true,\r\n                    'innerScroll': true,\r\n                    'buttons': []\r\n                };\r\n\r\n                self._resetForm('');\r\n                self._openPopup(options, htmlPopup, self);\r\n            },\r\n            _resetForm: function (postContent) {\r\n                var iframe = document.getElementById('post_content_ifr');\r\n\r\n                $('#mp_blog_post_form').trigger(\"reset\");\r\n                $('#short_description').empty();\r\n                $('#post_content').empty();\r\n                $('#post_id').removeAttr('value');\r\n\r\n                if (iframe){\r\n                    iframe.contentWindow.document.open();\r\n                    iframe.contentWindow.document.write(postContent);\r\n                    iframe.contentWindow.document.close();\r\n                }\r\n\r\n                $('.mp-field .mp-image-link').remove();\r\n                registry.get('customCategory').value('');\r\n                registry.get('customTag').value('');\r\n                registry.get('customTopic').value('');\r\n            },\r\n            _EditPost: function (self, click, htmlPopup) {\r\n                var postId   = $(click).parent().data('postid'),\r\n                    postData = self.options.postDatas[postId],\r\n                    pubUrl   = self.options.basePubUrl,\r\n                    options  = {\r\n                        'type': 'popup',\r\n                        'title': $t('Edit Post'),\r\n                        'responsive': true,\r\n                        'innerScroll': true,\r\n                        'buttons': []\r\n                    };\r\n                if (htmlPopup.find('#mp_blog_post_form [name=\"name\"]').length > 0) {\r\n                    self._resetForm(postData['post_content']);\r\n                }\r\n                self._openPopup(options, htmlPopup, self);\r\n                self._setPopupFormData(postData, pubUrl, htmlPopup);\r\n            },\r\n            _setPopupFormData: function(postData, pubUrl, htmlPopup){\r\n                _.each(postData, function (value, name) {\r\n                    var field = htmlPopup.find('#mp_blog_post_form [name=\"' + name + '\"]'),\r\n                        imageEL,\r\n                        deleteEL,\r\n                        date;\r\n                    if (field.is('[type=\"file\"]') && value) {\r\n                        imageEL = '<a class=\"mp-image-link\" href=\"' + pubUrl + 'mageplaza/blog/post/' + value\r\n                            + '\" onclick=\"imagePreview(\\'post_image_image\\'); return false;\" >' +\r\n                            '<img src=\"' + pubUrl + 'mageplaza/blog/post/' + value + '\" id=\"post_image_image\"' +\r\n                            ' title=\"' + value + '\" alt=\"' + value + '\" height=\"22\" width=\"22\"' +\r\n                            ' class=\"small-image-preview v-middle\">' +\r\n                            '</a>';\r\n                        field.parent().prepend(imageEL);\r\n                        deleteEL =  '<span class=\"delete-image\">'\r\n                            + '<input style=\"width: 8%\" type=\"checkbox\" name=\"image[delete]\"'\r\n                            + ' value=\"1\" class=\"checkbox\" id=\"post_image_delete\">'\r\n                            + '<label for=\"post_image_delete\"> Delete Image</label>'\r\n                            + '</span>';\r\n                        if (!field.parent().find('.delete-image').lenth) {\r\n                            field.parent().append(deleteEL);\r\n                        }\r\n                    } else if (field.is('[type=\"datetime-local\"]')) {\r\n                        date = moment(value).format(\"YYYY-MM-DDTkk:mm\");\r\n                        field.val(date);\r\n                    } else if (field.is('input') || field.is('select')) {\r\n                        field.val(value);\r\n                    } else if (field.is('textarea')) {\r\n                        field.html(value);\r\n                    }\r\n                    if (name === 'category_ids') {\r\n                        registry.get('customCategory').value(value);\r\n                    }\r\n                    if (name === 'tag_ids') {\r\n                        registry.get('customTag').value(value);\r\n                    }\r\n                    if (name === 'topic_ids') {\r\n                        registry.get('customTopic').value(value);\r\n                    }\r\n                });\r\n            },\r\n            _DuplicatePost: function (self, click, htmlPopup) {\r\n                var postId   = $(click).parent().data('postid'),\r\n                    postData = self.options.postDatas[postId],\r\n                    pubUrl   = self.options.basePubUrl,\r\n                    options  = {\r\n                        'type': 'popup',\r\n                        'title': $t('Duplicate Post'),\r\n                        'responsive': true,\r\n                        'innerScroll': true,\r\n                        'buttons': []\r\n                    };\r\n\r\n                if (htmlPopup.find('#mp_blog_post_form [name=\"name\"]').length > 0) {\r\n                    self._resetForm(postData['post_content']);\r\n                }\r\n                self._openPopup(options, htmlPopup, self);\r\n                self._setPopupFormData(postData, pubUrl, htmlPopup);\r\n                $('#post_id').removeAttr('value');\r\n                $('#image').parent().append('<input type=\"hidden\" name=\"image\" value=\"'+postData[\"image\"]+'\" />');\r\n            },\r\n            _DeletePost: function (self, widget) {\r\n                var url = self.options.deleteUrl,\r\n                    id = $(widget).parent().data('postid');\r\n\r\n                $.ajax({\r\n                    url: url,\r\n                    type: \"post\",\r\n                    data: {\r\n                        post_id: id\r\n                    },\r\n                    showLoader: true,\r\n                    success: function (result) {\r\n                        if (result['status'] === 1){\r\n                            $('.post-list-item[data-post-id=\"'+result['post_id']+'\"]').remove();\r\n                        }\r\n                    },\r\n                    complete: function () {\r\n\r\n                    }\r\n                });\r\n            },\r\n            _openPopup: function (options, htmlPopup, self) {\r\n                var popupModal,\r\n                    editorVersion = self.options.editorVersion,\r\n                    magentoVersion = self.options.magentoVersion;\r\n\r\n                popupModal = modal(options, htmlPopup);\r\n                popupModal.openModal();\r\n                $('#mp_blog_post_form').trigger('contentUpdated');\r\n\r\n                editor.config('post_content', editorVersion, magentoVersion);\r\n            }\r\n        }\r\n    );\r\n\r\n    return $.mageplaza.mpBlogManagePost;\r\n});\r\n"}
}});