Spamworldpro Mini Shell
Spamworldpro


Server : Apache
System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64
User : corals ( 1002)
PHP Version : 7.4.33
Disable Function : exec,passthru,shell_exec,system
Directory :  /home/corals/cartforge.co/pub/static/frontend/Smartwave/porto_rtl/en_US/js/bundle/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/corals/cartforge.co/pub/static/frontend/Smartwave/porto_rtl/en_US/js/bundle/bundle6.js
require.config({"config": {
        "jsbuild":{"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/knockout/bootstrap.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Loads all available knockout bindings, sets custom template engine, initializes knockout on page */\n\ndefine([\n    'ko',\n    './template/engine',\n    'knockoutjs/knockout-es5',\n    './bindings/bootstrap',\n    './extender/observable_array',\n    './extender/bound-nodes',\n    'domReady!'\n], function (ko, templateEngine) {\n    'use strict';\n\n    ko.uid = 0;\n\n    ko.setTemplateEngine(templateEngine);\n    ko.applyBindings();\n});\n","Magento_Ui/js/lib/knockout/extender/observable_array.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    /**\n     * Iterator function.\n     *\n     * @param {String} callback\n     * @param {Array} args\n     * @param {Object} elem\n     * @returns {*}\n     */\n    function iterator(callback, args, elem) {\n        callback = elem[callback];\n\n        if (_.isFunction(callback)) {\n            return callback.apply(elem, args);\n        }\n\n        return callback;\n    }\n\n    /**\n     * Wrapper function.\n     *\n     * @param {String} method\n     * @returns {Function}\n     */\n    function wrapper(method) {\n        return function (iteratee) {\n            var callback = iteratee,\n                elems = this(),\n                args = _.toArray(arguments);\n\n            if (_.isString(iteratee)) {\n                callback = iterator.bind(null, iteratee, args.slice(1));\n\n                args.unshift(callback);\n            }\n\n            args.unshift(elems);\n\n            return _[method].apply(_, args);\n        };\n    }\n\n    _.extend(ko.observableArray.fn, {\n        each: wrapper('each'),\n\n        map: wrapper('map'),\n\n        filter: wrapper('filter'),\n\n        some: wrapper('some'),\n\n        every: wrapper('every'),\n\n        groupBy: wrapper('groupBy'),\n\n        sortBy: wrapper('sortBy'),\n\n        /**\n         * Wrapper for underscore findWhere function.\n         *\n         * @param {Object} properties\n         * @return {Object}\n         */\n        findWhere: function (properties) {\n            return _.findWhere(this(), properties);\n        },\n\n        /**\n         * Wrapper for underscore contains function.\n         *\n         * @param {*} value\n         * @return {Boolean}\n         */\n        contains: function (value) {\n            return _.contains(this(), value);\n        },\n\n        /**\n         * Inverse contains call.\n         *\n         * @return {Boolean}\n         */\n        hasNo: function () {\n            return !this.contains.apply(this, arguments);\n        },\n\n        /**\n         * Getter for length property.\n         *\n         * @return {Number}\n         */\n        getLength: function () {\n            return this().length;\n        },\n\n        /**\n         * Create object with keys that gets from each object property.\n         *\n         * @return {Object}\n         */\n        indexBy: function (key) {\n            return _.indexBy(this(), key);\n        },\n\n        /**\n         * Returns a copy of the array with all instances of the values removed.\n         *\n         * @return {Array}\n         */\n        without: function () {\n            var args = Array.prototype.slice.call(arguments);\n\n            args.unshift(this());\n\n            return _.without.apply(_, args);\n        },\n\n        /**\n         * Returns the first element of an array.\n         *\n         * @return {*}\n         */\n        first: function () {\n            return _.first(this());\n        },\n\n        /**\n         * Returns the last element of an array\n         *\n         * @return {*}\n         */\n        last: function () {\n            return _.last(this());\n        },\n\n        /**\n         * Iterate and pick provided properties.\n         *\n         * @return {Array}\n         */\n        pluck: function () {\n            var args = Array.prototype.slice.call(arguments);\n\n            args.unshift(this());\n\n            return _.pluck.apply(_, args);\n        }\n    });\n});\n","Magento_Ui/js/lib/knockout/extender/bound-nodes.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/utils/wrapper',\n    'uiEvents'\n], function (ko, _, wrapper, Events) {\n    'use strict';\n\n    var nodesMap = new WeakMap();\n\n    /**\n     * Returns a array of nodes associated with a specified model.\n     *\n     * @param {Object} model\n     * @returns {Undefined|Array}\n     */\n    function getBounded(model) {\n        return nodesMap.get(model);\n    }\n\n    /**\n     * Removes specified node to models' associations list, if it's\n     * a root node (node is not a descendant of any previously added nodes).\n     * Triggers 'addNode' event.\n     *\n     * @param {Object} model\n     * @param {HTMLElement} node\n     */\n    function addBounded(model, node) {\n        var nodes = getBounded(model),\n            isRoot;\n\n        if (!nodes) {\n            nodesMap.set(model, [node]);\n\n            Events.trigger.call(model, 'addNode', node);\n\n            return;\n        }\n\n        isRoot = nodes.every(function (bounded) {\n            return !bounded.contains(node);\n        });\n\n        if (isRoot) {\n            nodes.push(node);\n\n            Events.trigger.call(model, 'addNode', node);\n        }\n    }\n\n    /**\n     * Removes specified node from models' associations list.\n     * Triggers 'removeNode' event.\n     *\n     * @param {Object} model\n     * @param {HTMLElement} node\n     */\n    function removeBounded(model, node) {\n        var nodes = getBounded(model),\n            index;\n\n        if (!nodes) {\n            return;\n        }\n\n        index = nodes.indexOf(node);\n\n        if (~index) {\n            nodes.splice(index, 0);\n\n            Events.trigger.call(model, 'removeNode', node);\n        }\n\n        if (!nodes.length) {\n            nodesMap.delete(model);\n        }\n    }\n\n    /**\n     * Returns node's first sibling of 'element' type within the common component scope\n     *\n     * @param {HTMLElement} node\n     * @param {*} data\n     * @returns {HTMLElement}\n     */\n    function getElement(node, data) {\n        var elem;\n\n        while (node.nextElementSibling) {\n            node = node.nextElementSibling;\n\n            if (node.nodeType === 1 && ko.dataFor(node) === data) {\n                elem = node;\n                break;\n            }\n        }\n\n        return elem;\n    }\n\n    wrapper.extend(ko, {\n\n        /**\n         * Extends knockouts' 'applyBindings'\n         * to track nodes associated with model.\n         *\n         * @param {Function} orig - Original 'applyBindings' method.\n         * @param {Object} ctx\n         * @param {HTMLElement} node - Original 'applyBindings' method.\n         */\n        applyBindings: function (orig, ctx, node) {\n            var result = orig(),\n                data = ctx && (ctx.$data || ctx);\n\n            if (node && node.nodeType === 8) {\n                node = getElement(node, data);\n            }\n\n            if (!node || node.nodeType !== 1) {\n                return result;\n            }\n\n            if (data && data.registerNodes) {\n                addBounded(data, node);\n            }\n\n            return result;\n        },\n\n        /**\n         * Extends knockouts' cleanNode\n         * to track nodes associated with model.\n         *\n         * @param {Function} orig - Original 'cleanNode' method.\n         * @param {HTMLElement} node - Original 'cleanNode' method.\n         */\n        cleanNode: function (orig, node) {\n            var result = orig(),\n                data;\n\n            if (node.nodeType !== 1) {\n                return result;\n            }\n\n            data = ko.dataFor(node);\n\n            if (data && data.registerNodes) {\n                removeBounded(data, node);\n            }\n\n            return result;\n        }\n    });\n\n    return {\n\n        /**\n         * Returns root nodes associated with a model. If callback is provided,\n         * will iterate through all of the present nodes triggering callback\n         * for each of it. Also it will subscribe to the 'addNode' event.\n         *\n         * @param {Object} model\n         * @param {Function} [callback]\n         * @returns {Array|Undefined}\n         */\n        get: function (model, callback) {\n            var nodes = getBounded(model) || [];\n\n            if (!_.isFunction(callback)) {\n                return nodes;\n            }\n\n            nodes.forEach(function (node) {\n                callback(node);\n            });\n\n            this.add.apply(this, arguments);\n        },\n\n        /**\n         * Subscribes to adding of nodes associated with a model.\n         *\n         * @param {Object} model\n         */\n        add: function (model) {\n            var args = _.toArray(arguments).slice(1);\n\n            args.unshift('addNode');\n\n            Events.on.apply(model, args);\n        },\n\n        /**\n         * Subscribes to removal of nodes associated with a model.\n         *\n         * @param {Object} model\n         */\n        remove: function (model) {\n            var args = _.toArray(arguments).slice(1);\n\n            args.unshift('removeNode');\n\n            Events.on.apply(model, args);\n        },\n\n        /**\n         * Removes subscriptions from the model.\n         *\n         * @param {Object} model\n         */\n        off: function (model) {\n            var args = _.toArray(arguments).slice(1);\n\n            Events.off.apply(model, args);\n        }\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/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/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/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/collapsible.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'ko',\n    'jquery',\n    'underscore',\n    '../template/renderer'\n], function (ko, $, _, renderer) {\n    'use strict';\n\n    var collapsible,\n        defaults;\n\n    defaults = {\n        closeOnOuter: true,\n        onTarget: false,\n        openClass: '_active',\n        as: '$collapsible'\n    };\n\n    collapsible = {\n\n        /**\n         * Sets 'opened' property to true.\n         */\n        open: function () {\n            this.opened(true);\n        },\n\n        /**\n         * Sets 'opened' property to false.\n         */\n        close: function () {\n            this.opened(false);\n        },\n\n        /**\n         * Toggles value of the 'opened' property.\n         */\n        toggle: function () {\n            this.opened(!this.opened());\n        }\n    };\n\n    /**\n     * Document click handler which in case if event target is not\n     * a descendant of provided container element, closes collapsible model.\n     *\n     * @param {HTMLElement} container\n     * @param {Object} model\n     * @param {EventObject} e\n     */\n    function onOuterClick(container, model, e) {\n        var target = e.target;\n\n        if (target !== container && !container.contains(target)) {\n            model.close();\n        }\n    }\n\n    /**\n     * Creates 'css' binding which toggles\n     * class specified in 'name' parameter.\n     *\n     * @param {Object} model\n     * @param {String} name\n     * @returns {Object}\n     */\n    function getClassBinding(model, name) {\n        var binding = {};\n\n        binding[name] = model.opened;\n\n        return {\n            css: binding\n        };\n    }\n\n    /**\n     * Prepares configuration for the binding based\n     * on a default properties and provided options.\n     *\n     * @param {Object} [options={}]\n     * @returns {Object} Complete instance configuration.\n     */\n    function buildConfig(options) {\n        if (typeof options !== 'object') {\n            options = {};\n        }\n\n        return _.extend({}, defaults, options);\n    }\n\n    ko.bindingHandlers.collapsible = {\n\n        /**\n         * Initializes 'collapsible' binding.\n         */\n        init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n            var $collapsible = Object.create(collapsible),\n                config = buildConfig(valueAccessor()),\n                outerClick,\n                bindings;\n\n            _.bindAll($collapsible, 'open', 'close', 'toggle');\n\n            $collapsible.opened = ko.observable(!!config.opened);\n\n            bindingCtx[config.as] = $collapsible;\n\n            if (config.closeOnOuter) {\n                outerClick = onOuterClick.bind(null, element, $collapsible);\n\n                $(document).on('click', outerClick);\n\n                ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n                    $(document).off('click', outerClick);\n                });\n            }\n\n            if (config.openClass) {\n                bindings = getClassBinding($collapsible, config.openClass);\n\n                ko.applyBindingsToNode(element, bindings, bindingCtx);\n            }\n\n            if (config.onTarget) {\n                $(element).on('click', $collapsible.toggle);\n            }\n\n            if (viewModel && _.isFunction(viewModel.on)) {\n                viewModel.on({\n                    close:          $collapsible.close,\n                    open:           $collapsible.open,\n                    toggleOpened:   $collapsible.toggle\n                });\n            }\n        }\n    };\n\n    ko.bindingHandlers.closeCollapsible = {\n\n        /**\n         * Creates listener for the click event on provided DOM element,\n         * which closes associated with it collapsible model.\n         */\n        init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n            var name = valueAccessor() || defaults.as,\n                $collapsible = bindingCtx[name];\n\n            if ($collapsible) {\n                $(element).on('click', $collapsible.close);\n            }\n        }\n    };\n\n    ko.bindingHandlers.openCollapsible = {\n\n        /**\n         * Creates listener for the click event on provided DOM element,\n         * which opens associated with it collapsible model.\n         */\n        init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n            var name = valueAccessor() || defaults.as,\n                $collapsible = bindingCtx[name];\n\n            if ($collapsible) {\n                $(element).on('click', $collapsible.open);\n            }\n        }\n    };\n\n    ko.bindingHandlers.toggleCollapsible = {\n\n        /**\n         * Creates listener for the click event on provided DOM element,\n         * which toggles associated with it collapsible model.\n         */\n        init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n            var name = valueAccessor() || defaults.as,\n                $collapsible = bindingCtx[name];\n\n            if ($collapsible) {\n                $(element).on('click', $collapsible.toggle);\n            }\n        }\n    };\n\n    renderer\n        .addAttribute('collapsible')\n        .addAttribute('openCollapsible')\n        .addAttribute('closeCollapsible')\n        .addAttribute('toggleCollapsible');\n});\n","Magento_Ui/js/lib/knockout/bindings/i18n.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'ko',\n    'module',\n    '../template/renderer',\n    'mage/translate'\n], function ($, ko, module, renderer) {\n    'use strict';\n\n    var locations = {\n            'legend': 'Caption for the fieldset element',\n            'label': 'Label for an input element.',\n            'button': 'Push button',\n            'a': 'Link label',\n            'b': 'Bold text',\n            'strong': 'Strong emphasized text',\n            'i': 'Italic text',\n            'em': 'Emphasized text',\n            'u': 'Underlined text',\n            'sup': 'Superscript text',\n            'sub': 'Subscript text',\n            'span': 'Span element',\n            'small': 'Smaller text',\n            'big': 'Bigger text',\n            'address': 'Contact information',\n            'blockquote': 'Long quotation',\n            'q': 'Short quotation',\n            'cite': 'Citation',\n            'caption': 'Table caption',\n            'abbr': 'Abbreviated phrase',\n            'acronym': 'An acronym',\n            'var': 'Variable part of a text',\n            'dfn': 'Term',\n            'strike': 'Strikethrough text',\n            'del': 'Deleted text',\n            'ins': 'Inserted text',\n            'h1': 'Heading level 1',\n            'h2': 'Heading level 2',\n            'h3': 'Heading level 3',\n            'h4': 'Heading level 4',\n            'h5': 'Heading level 5',\n            'h6': 'Heading level 6',\n            'center': 'Centered text',\n            'select': 'List options',\n            'img': 'Image',\n            'input': 'Form element'\n        },\n\n        /**\n         * Generates [data-translate] attribute's value\n         * @param {Object} translationData\n         * @param {String} location\n         */\n        composeTranslateAttr = function (translationData, location) {\n            var obj = [{\n                'shown': translationData.shown,\n                'translated': translationData.translated,\n                'original': translationData.original,\n                'location': locations[location] || 'Text'\n            }];\n\n            return JSON.stringify(obj);\n        },\n\n        /**\n         * Sets text for the element\n         * @param {Object} el\n         * @param {String} text\n         */\n        setText = function (el, text) {\n            $(el).text(text);\n        },\n\n        /**\n         * Sets [data-translate] attribute for the element\n         * @param {Object} el - The element which is binded\n         * @param {String} original - The original value of the element\n         */\n        setTranslateProp = function (el, original) {\n            var location = $(el).prop('tagName').toLowerCase(),\n                translated = $.mage.__(original),\n                translationData = {\n                    shown: translated,\n                    translated: translated,\n                    original: original\n                },\n                translateAttr = composeTranslateAttr(translationData, location);\n\n            $(el).attr('data-translate', translateAttr);\n\n            setText(el, translationData.shown);\n        },\n\n        /**\n         * Checks if node represents ko virtual node (nodeType === 8, nodeName === '#comment').\n         *\n         * @param {HTMLElement} node\n         * @returns {Boolean}\n         */\n        isVirtualElement = function (node) {\n            return node.nodeType === 8;\n        },\n\n        /**\n        * Checks if it's real DOM element\n        * in case of virtual element, returns span wrapper\n        * @param {Object} el\n        * @param {bool} isUpdate\n        * @return {Object} el\n        */\n        getRealElement = function (el, isUpdate) {\n            if (isVirtualElement(el)) {\n                if (isUpdate) {\n                    return $(el).next('span');\n                }\n\n                return $('<span></span>').insertAfter(el);\n            }\n\n            return el;\n        },\n\n        /**\n         * execute i18n binding\n         * @param {Object} element\n         * @param {Function} valueAccessor\n         * @param {bool} isUpdate\n         */\n        execute = function (element, valueAccessor, isUpdate) {\n            var original = ko.unwrap(valueAccessor() || ''),\n                el = getRealElement(element, isUpdate),\n                inlineTranslation = (module.config() || {}).inlineTranslation;\n\n            if (inlineTranslation) {\n                setTranslateProp(el, original);\n            } else {\n                setText(el, $.mage.__(original));\n            }\n        };\n\n    /**\n     * i18n binding\n     * @property {Function}  init\n     * @property {Function}  update\n     */\n    ko.bindingHandlers.i18n = {\n\n        /**\n         * init i18n binding\n         * @param {Object} element\n         * @param {Function} valueAccessor\n         */\n        init: function (element, valueAccessor) {\n            execute(element, valueAccessor);\n        },\n\n        /**\n         * update i18n binding\n         * @param {Object} element\n         * @param {Function} valueAccessor\n         */\n        update: function (element, valueAccessor) {\n            execute(element, valueAccessor, true);\n        }\n    };\n\n    ko.virtualElements.allowedBindings.i18n = true;\n\n    renderer\n        .addNode('translate', {\n            binding: 'i18n'\n        })\n        .addAttribute('translate', {\n            binding: 'i18n'\n        });\n});\n","Magento_Ui/js/lib/knockout/bindings/resizable.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'ko',\n    'jquery',\n    'Magento_Ui/js/lib/view/utils/async',\n    'uiRegistry',\n    'underscore',\n    '../template/renderer'\n], function (ko, $, async, registry, _, renderer) {\n    'use strict';\n\n    var sizeOptions = [\n            'minHeight',\n            'maxHeight',\n            'minWidth',\n            'maxWidth'\n        ],\n\n        handles = {\n            height: '.ui-resizable-s, .ui-resizable-n',\n            width: '.ui-resizable-w, .ui-resizable-e'\n        };\n\n    /**\n     * Recalcs visibility of handles, width and height of resizable based on content\n     * @param {HTMLElement} element\n     */\n    function adjustSize(element) {\n        var maxHeight,\n            maxWidth;\n\n        element = $(element);\n        maxHeight = element.resizable('option').maxHeight;\n        maxWidth = element.resizable('option').maxWidth;\n\n        if (maxHeight && element.height() > maxHeight) {\n            element.height(maxHeight + 1);\n            $(handles.height).hide();\n        } else {\n            $(handles.height).show();\n        }\n\n        if (maxWidth && element.width() > maxWidth) {\n            element.width(maxWidth + 1);\n            $(handles.width).hide();\n        } else {\n            $(handles.width).show();\n        }\n    }\n\n    /**\n     * Recalcs allowed min, max width and height based on configured selectors\n     * @param {Object} sizeConstraints\n     * @param {String} componentName\n     * @param {HTMLElement} element\n     * @param {Boolean} hasWidthUpdate\n     */\n    function recalcAllowedSize(sizeConstraints, componentName, element, hasWidthUpdate) {\n        var size;\n\n        element = $(element);\n\n        if (!element.data('resizable')) {\n            return;\n        }\n\n        if (!hasWidthUpdate) {\n            element.css('width', 'auto');\n        }\n\n        _.each(sizeConstraints, function (selector, key) {\n            async.async({\n                component: componentName,\n                selector: selector\n            }, function (elem) {\n                size = key.indexOf('Height') !== -1 ? $(elem).outerHeight(true) : $(elem).outerWidth(true);\n\n                if (element.data('resizable')) {\n                    element.resizable('option', key, size + 1);\n                }\n            });\n        }, this);\n\n        adjustSize(element);\n    }\n\n    /**\n     * Preprocess config to separate options,\n     * which must be processed further before applying\n     *\n     * @param {Object} config\n     * @param {Object} viewModel\n     * @param {*} element\n     * @return {Object} config\n     */\n    function processConfig(config, viewModel, element) {\n        var sizeConstraint,\n            sizeConstraints = {},\n            recalc,\n            hasWidthUpdate;\n\n        if (_.isEmpty(config)) {\n            return {};\n        }\n        _.each(sizeOptions, function (key) {\n            sizeConstraint = config[key];\n\n            if (sizeConstraint && !_.isNumber(sizeConstraint)) {\n                sizeConstraints[key] = sizeConstraint;\n                delete config[key];\n            }\n        });\n        hasWidthUpdate =  _.some(sizeConstraints, function (value, key) {\n            return key.indexOf('Width') !== -1;\n        });\n\n        recalc = recalcAllowedSize.bind(null, sizeConstraints, viewModel.name, element, hasWidthUpdate);\n        config.start = recalc;\n        $(window).on('resize.resizable', recalc);\n        registry.get(viewModel.provider).on('reloaded', recalc);\n\n        return config;\n    }\n\n    ko.bindingHandlers.resizable = {\n\n        /**\n         * Binding init callback.\n         *\n         * @param {*} element\n         * @param {Function} valueAccessor\n         * @param {Function} allBindings\n         * @param {Object} viewModel\n         */\n        init: function (element, valueAccessor, allBindings, viewModel) {\n            var config = processConfig(valueAccessor(), viewModel, element);\n\n            require(['jquery-ui-modules/resizable'], function () {\n                if ($.fn.resizable) {\n                    $(element).resizable(config);\n                }\n            });\n        }\n    };\n\n    renderer.addAttribute('resizable');\n});\n","Magento_Ui/js/lib/knockout/bindings/mage-init.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'underscore',\n    'mage/apply/main'\n], function (ko, _, mage) {\n    'use strict';\n\n    ko.bindingHandlers.mageInit = {\n        /**\n         * Initializes components assigned to HTML elements.\n         *\n         * @param {HTMLElement} el\n         * @param {Function} valueAccessor\n         */\n        init: function (el, valueAccessor) {\n            var data = valueAccessor();\n\n            _.each(data, function (config, component) {\n                mage.applyFor(el, config, component);\n            });\n        }\n    };\n});\n","Magento_Ui/js/lib/knockout/bindings/staticChecked.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'ko',\n    '../template/renderer'\n], function (ko, renderer) {\n    'use strict';\n\n    ko.bindingHandlers.staticChecked = {\n        'after': ['value', 'attr'],\n\n        /**\n         * Implements same functionality as a standard 'checked' binding,\n         * but with a difference that it wont' change values array if\n         * value of DOM element changes.\n         */\n        init: function (element, valueAccessor, allBindings) {\n            var isCheckbox = element.type === 'checkbox',\n                isRadio = element.type === 'radio',\n                isValueArray,\n                oldElemValue,\n                useCheckedValue,\n                checkedValue,\n                updateModel,\n                updateView;\n\n            if (!isCheckbox && !isRadio) {\n                return;\n            }\n\n            checkedValue = ko.pureComputed(function () {\n                if (allBindings.has('checkedValue')) {\n                    return ko.utils.unwrapObservable(allBindings.get('checkedValue'));\n                } else if (allBindings.has('value')) {\n                    return ko.utils.unwrapObservable(allBindings.get('value'));\n                }\n\n                return element.value;\n            });\n\n            isValueArray = isCheckbox && ko.utils.unwrapObservable(valueAccessor()) instanceof Array;\n            oldElemValue = isValueArray ? checkedValue() : undefined;\n            useCheckedValue = isRadio || isValueArray;\n\n            /**\n             * Updates values array if it's necessary.\n             */\n            updateModel = function () {\n                var isChecked = element.checked,\n                    elemValue = useCheckedValue ? checkedValue() : isChecked,\n                    modelValue;\n\n                if (ko.computedContext.isInitial()) {\n                    return;\n                }\n\n                if (isRadio && !isChecked) {\n                    return;\n                }\n\n                modelValue = ko.dependencyDetection.ignore(valueAccessor);\n\n                if (isValueArray) {\n                    if (oldElemValue !== elemValue) {\n                        oldElemValue = elemValue;\n                    } else {\n                        ko.utils.addOrRemoveItem(modelValue, elemValue, isChecked);\n                    }\n                } else {\n                    ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'checked', elemValue, true);\n                }\n            };\n\n            /**\n             * Updates checkbox state.\n             */\n            updateView = function () {\n                var modelValue = ko.utils.unwrapObservable(valueAccessor());\n\n                if (isValueArray) {\n                    element.checked = ko.utils.arrayIndexOf(modelValue, checkedValue()) >= 0;\n                } else if (isCheckbox) {\n                    element.checked = modelValue;\n                } else {\n                    element.checked = checkedValue() === modelValue;\n                }\n            };\n\n            ko.computed(updateModel, null, {\n                disposeWhenNodeIsRemoved: element\n            });\n\n            ko.utils.registerEventHandler(element, 'click', updateModel);\n\n            ko.computed(updateView, null, {\n                disposeWhenNodeIsRemoved: element\n            });\n        }\n    };\n\n    ko.expressionRewriting._twoWayBindings.staticChecked = true;\n\n    renderer.addAttribute('staticChecked');\n});\n","Magento_Ui/js/lib/knockout/bindings/after-render.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'ko',\n    '../template/renderer'\n], function (ko, renderer) {\n    'use strict';\n\n    ko.bindingHandlers.afterRender = {\n\n        /**\n         * Binding init callback.\n         */\n        init: function (element, valueAccessor, allBindings, viewModel) {\n            var callback = valueAccessor();\n\n            if (typeof callback === 'function') {\n                callback.call(viewModel, element, viewModel);\n            }\n        }\n    };\n\n    renderer.addAttribute('afterRender');\n});\n","Magento_Ui/js/lib/knockout/bindings/fadeVisible.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'ko'\n], function ($, ko) {\n    'use strict';\n\n    ko.bindingHandlers.fadeVisible = {\n        /**\n         * Initially set the element to be instantly visible/hidden depending on the value.\n         *\n         * @param {HTMLElement} element\n         * @param {Function} valueAccessor\n         */\n        init: function (element, valueAccessor) {\n            var value = valueAccessor();\n\n            // Use \"unwrapObservable\" so we can handle values that may or may not be observable\n            $(element).toggle(ko.unwrap(value));\n        },\n\n        /**\n         * Whenever the value subsequently changes, slowly fade the element in or out.\n         *\n         * @param {HTMLElement} element\n         * @param {Function} valueAccessor\n         */\n        update: function (element, valueAccessor) {\n            var value = valueAccessor();\n\n            ko.unwrap(value) ? $(element).fadeIn() : $(element).fadeOut();\n        }\n    };\n});\n","Magento_Ui/js/lib/knockout/bindings/bootstrap.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(function (require) {\n    'use strict';\n\n    var renderer = require('../template/renderer');\n\n    renderer.addAttribute('repeat', renderer.handlers.wrapAttribute);\n\n    renderer.addAttribute('outerfasteach', {\n        binding: 'fastForEach',\n        handler: renderer.handlers.wrapAttribute\n    });\n\n    renderer\n        .addNode('repeat')\n        .addNode('fastForEach');\n\n    return {\n        resizable:      require('./resizable'),\n        i18n:           require('./i18n'),\n        scope:          require('./scope'),\n        range:          require('./range'),\n        mageInit:       require('./mage-init'),\n        keyboard:       require('./keyboard'),\n        optgroup:       require('./optgroup'),\n        afterRender:     require('./after-render'),\n        autoselect:     require('./autoselect'),\n        datepicker:     require('./datepicker'),\n        outerClick:     require('./outer_click'),\n        fadeVisible:    require('./fadeVisible'),\n        collapsible:    require('./collapsible'),\n        staticChecked:  require('./staticChecked'),\n        simpleChecked:  require('./simple-checked'),\n        bindHtml:       require('./bind-html'),\n        tooltip:        require('./tooltip'),\n        repeat:         require('knockoutjs/knockout-repeat'),\n        fastForEach:    require('knockoutjs/knockout-fast-foreach'),\n        colorPicker:    require('./color-picker')\n    };\n});\n","Magento_Ui/js/lib/knockout/bindings/outer_click.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Creates outerClick binding and registers in to ko.bindingHandlers object */\ndefine([\n    'ko',\n    'jquery',\n    'underscore',\n    '../template/renderer'\n], function (ko, $, _, renderer) {\n    'use strict';\n\n    var defaults = {\n        onlyIfVisible: true\n    };\n\n    /**\n     * Checks if element sis visible.\n     *\n     * @param {Element} el\n     * @returns {Boolean}\n     */\n    function isVisible(el) {\n        var style = window.getComputedStyle(el),\n            visibility = {\n                display: 'none',\n                visibility: 'hidden',\n                opacity: '0'\n            },\n            visible = true;\n\n        _.each(visibility, function (val, key) {\n            if (style[key] === val) {\n                visible = false;\n            }\n        });\n\n        return visible;\n    }\n\n    /**\n     * Document click handler which in case if event target is not\n     * a descendant of provided container element,\n     * invokes specified in configuration callback.\n     *\n     * @param {HTMLElement} container\n     * @param {Object} config\n     * @param {EventObject} e\n     */\n    function onOuterClick(container, config, e) {\n        var target = e.target,\n            callback = config.callback;\n\n        if (container === target || container.contains(target)) {\n            return;\n        }\n\n        if (config.onlyIfVisible) {\n            if (!_.isNull(container.offsetParent) && isVisible(container)) {\n                callback();\n            }\n        } else {\n            callback();\n        }\n    }\n\n    /**\n     * Prepares configuration for the binding based\n     * on a default properties and provided options.\n     *\n     * @param {(Object|Function)} [options={}]\n     * @returns {Object}\n     */\n    function buildConfig(options) {\n        var config = {};\n\n        if (_.isFunction(options)) {\n            options = {\n                callback: options\n            };\n        } else if (!_.isObject(options)) {\n            options = {};\n        }\n\n        return _.extend(config, defaults, options);\n    }\n\n    ko.bindingHandlers.outerClick = {\n\n        /**\n         * Initializes outer click binding.\n         */\n        init: function (element, valueAccessor) {\n            var config = buildConfig(valueAccessor()),\n                outerClick = onOuterClick.bind(null, element, config),\n                isTouchDevice = typeof document.ontouchstart !== 'undefined';\n\n            if (isTouchDevice) {\n                $(document).on('touchstart', outerClick);\n\n                ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n                    $(document).off('touchstart', outerClick);\n                });\n            } else {\n                $(document).on('click', outerClick);\n\n                ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n                    $(document).off('click', outerClick);\n                });\n            }\n        }\n    };\n\n    renderer.addAttribute('outerClick');\n});\n","Magento_Ui/js/lib/knockout/bindings/keyboard.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'ko',\n    '../template/renderer'\n], function (ko, renderer) {\n    'use strict';\n\n    ko.bindingHandlers.keyboard = {\n\n        /**\n         * Attaches keypress handlers to element\n         * @param {HTMLElement} el - Element, that binding is applied to\n         * @param {Function} valueAccessor - Function that returns value, passed to binding\n         * @param  {Object} allBindings - all bindings object\n         * @param  {Object} viewModel - reference to viewmodel\n         */\n        init: function (el, valueAccessor, allBindings, viewModel) {\n            var map = valueAccessor();\n\n            ko.utils.registerEventHandler(el, 'keyup', function (e) {\n                var callback = map[e.keyCode];\n\n                if (callback) {\n                    return callback.call(viewModel, e);\n                }\n            });\n        }\n    };\n\n    renderer.addAttribute('keyboard');\n});\n","Magento_Ui/js/lib/knockout/bindings/range.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'jquery',\n    'underscore',\n    '../template/renderer'\n], function (ko, $, _, renderer) {\n    'use strict';\n\n    var isTouchDevice = !_.isUndefined(document.ontouchstart),\n        sliderFn = 'slider',\n        sliderModule = 'jquery-ui-modules/slider';\n\n    if (isTouchDevice) {\n        sliderFn = 'touchSlider';\n        sliderModule = 'mage/touch-slider';\n    }\n\n    ko.bindingHandlers.range = {\n\n        /**\n         * Initializes binding and a slider update.\n         *\n         * @param {HTMLElement} element\n         * @param {Function} valueAccessor\n         */\n        init: function (element, valueAccessor) {\n            var config  = valueAccessor(),\n                value   = config.value;\n\n            _.extend(config, {\n                value: value(),\n\n                /**\n                 * Callback which is being called when sliders' value changes.\n                 *\n                 * @param {Event} event\n                 * @param {Object} ui\n                 */\n                slide: function (event, ui) {\n                    value(ui.value);\n                }\n            });\n\n            require([sliderModule], function () {\n                $(element)[sliderFn](config);\n            });\n        },\n\n        /**\n         * Updates sliders' plugin configuration.\n         *\n         * @param {HTMLElement} element\n         * @param {Function} valueAccessor\n         */\n        update: function (element, valueAccessor) {\n            var config = valueAccessor();\n\n            config.value = ko.unwrap(config.value);\n\n            require([sliderModule], function () {\n                $(element)[sliderFn]('option', config);\n            });\n        }\n    };\n\n    renderer.addAttribute('range');\n});\n","Magento_Ui/js/lib/knockout/bindings/scope.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Creates scope binding and registers in to ko.bindingHandlers object */\ndefine([\n    'ko',\n    'uiRegistry',\n    'mage/translate',\n    '../template/renderer',\n    'jquery',\n    '../../logger/console-logger'\n], function (ko, registry, $t, renderer, $, consoleLogger) {\n    'use strict';\n\n    /**\n     * Creates child context with passed component param as $data. Extends context with $t helper.\n     * Applies bindings to descendant nodes.\n     * @param {HTMLElement} el - element to apply bindings to.\n     * @param {ko.bindingContext} bindingContext - instance of ko.bindingContext, passed to binding initially.\n     * @param {Promise} promise - instance of jQuery promise\n     * @param {Object} component - component instance to attach to new context\n     */\n    function applyComponents(el, bindingContext, promise, component) {\n        promise.resolve();\n        component = bindingContext.createChildContext(component);\n\n        ko.utils.extend(component, {\n            $t: $t\n        });\n\n        ko.utils.arrayForEach(ko.virtualElements.childNodes(el), ko.cleanNode);\n\n        ko.applyBindingsToDescendants(component, el);\n    }\n\n    ko.bindingHandlers.scope = {\n\n        /**\n         * Scope binding's init method.\n         * @returns {Object} - Knockout declaration for it to let binding control descendants.\n         */\n        init: function () {\n            return {\n                controlsDescendantBindings: true\n            };\n        },\n\n        /**\n         * Reads params passed to binding, parses component declarations.\n         * Fetches for those found and attaches them to the new context.\n         * @param {HTMLElement} el - Element to apply bindings to.\n         * @param {Function} valueAccessor - Function that returns value, passed to binding.\n         * @param {Object} allBindings - Object, which represents all bindings applied to element.\n         * @param {Object} viewModel - Object, which represents view model binded to el.\n         * @param {ko.bindingContext} bindingContext - Instance of ko.bindingContext, passed to binding initially.\n         */\n        update: function (el, valueAccessor, allBindings, viewModel, bindingContext) {\n            var component = valueAccessor(),\n                promise = $.Deferred(),\n                apply = applyComponents.bind(this, el, bindingContext, promise),\n                loggerUtils = consoleLogger.utils;\n\n            if (typeof component === 'string') {\n                loggerUtils.asyncLog(\n                    promise,\n                    {\n                        data: {\n                            component: component\n                        },\n                        messages: loggerUtils.createMessages(\n                            'requestingComponent',\n                            'requestingComponentIsLoaded',\n                            'requestingComponentIsFailed'\n                        )\n                    }\n                );\n\n                registry.get(component, apply);\n            } else if (typeof component === 'function') {\n                component(apply);\n            }\n        }\n    };\n\n    ko.virtualElements.allowedBindings.scope = true;\n\n    renderer\n        .addNode('scope')\n        .addAttribute('scope', {\n            name: 'ko-scope'\n        });\n});\n","Magento_Ui/js/lib/knockout/bindings/datepicker.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Creates datepicker binding and registers in to ko.bindingHandlers object */\ndefine([\n    'ko',\n    'underscore',\n    'jquery',\n    'mage/translate'\n], function (ko, _, $, $t) {\n    'use strict';\n\n    var defaults = {\n        dateFormat: 'mm\\/dd\\/yyyy',\n        showsTime: false,\n        timeFormat: null,\n        buttonImage: null,\n        buttonImageOnly: null,\n        buttonText: $t('Select Date')\n    };\n\n    ko.bindingHandlers.datepicker = {\n        /**\n         * Initializes calendar widget on element and stores it's value to observable property.\n         * Datepicker binding takes either observable property or object\n         *  { storage: {ko.observable}, options: {Object} }.\n         * For more info about options take a look at \"mage/calendar\" and jquery.ui.datepicker widget.\n         * @param {HTMLElement} el - Element, that binding is applied to\n         * @param {Function} valueAccessor - Function that returns value, passed to binding\n         * @param {object} allBindings\n         * @param {object} viewModel\n         * @param {object} bindingContext\n         */\n        init: function (el, valueAccessor, allBindings, viewModel, bindingContext) {\n            var config = valueAccessor(),\n                observable,\n                options = {};\n\n            _.extend(options, defaults);\n\n            if (typeof config === 'object') {\n                observable = config.storage;\n                _.extend(options, config.options);\n            } else {\n                observable = config;\n            }\n\n            require(['mage/calendar'], function () {\n                $(el).calendar(options);\n\n                ko.utils.registerEventHandler(el, 'change', function () {\n                    observable(this.value);\n                });\n            });\n\n            if (bindingContext.$data) {\n                bindingContext.$data.value.subscribe(function (newVal) {\n                    if (!newVal) {\n                        $(el).val('');\n                    }\n                }, this);\n            }\n\n\n        },\n\n        /**\n         * Update calendar widget on element and stores it's value to observable property.\n         * Datepicker binding takes either observable property or object\n         *  { storage: {ko.observable}, options: {Object} }.\n         * @param {HTMLElement} element - Element, that binding is applied to\n         * @param {Function} valueAccessor - Function that returns value, passed to binding\n         */\n        update: function (element, valueAccessor) {\n            var config = valueAccessor(),\n                $element = $(element),\n                observable,\n                options = {},\n                newVal;\n\n            _.extend(options, defaults);\n\n            if (typeof config === 'object') {\n                observable = config.storage;\n                _.extend(options, config.options);\n            } else {\n                observable = config;\n            }\n\n            require(['moment', 'mage/utils/misc', 'mage/calendar'], function (moment, utils) {\n                if (_.isEmpty(observable())) {\n                    newVal = null;\n                } else {\n                    newVal = moment(\n                        observable(),\n                        utils.convertToMomentFormat(\n                            options.dateFormat + (options.showsTime ? ' ' + options.timeFormat : '')\n                        )\n                    ).toDate();\n                }\n\n                if (!options.timeOnly) {\n                    $element.datepicker('setDate', newVal);\n                    $element.trigger('blur');\n                }\n            });\n        }\n    };\n});\n","Magento_Ui/js/lib/knockout/bindings/bind-html.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'ko',\n    'underscore',\n    'mage/apply/main',\n    '../template/renderer'\n], function (ko, _, mage, renderer) {\n    'use strict';\n\n    /**\n     * Set html to node element.\n     *\n     * @param {HTMLElement} el - Element to apply bindings to.\n     * @param {Function} html - Observable html content.\n     */\n    function setHtml(el, html) {\n        ko.utils.emptyDomNode(el);\n        html = ko.utils.unwrapObservable(html);\n\n        if (!_.isNull(html) && !_.isUndefined(html)) {\n            if (!_.isString(html)) {\n                html = html.toString();\n            }\n\n            el.innerHTML = html;\n        }\n    }\n\n    /**\n     * Apply bindings and call magento attributes parser.\n     *\n     * @param {HTMLElement} el - Element to apply bindings to.\n     * @param {ko.bindingContext} ctx - Instance of ko.bindingContext, passed to binding initially.\n     */\n    function applyComponents(el, ctx) {\n        ko.utils.arrayForEach(el.childNodes, ko.cleanNode);\n        ko.applyBindingsToDescendants(ctx, el);\n        mage.apply();\n    }\n\n    ko.bindingHandlers.bindHtml = {\n        /**\n         * Scope binding's init method.\n         *\n         * @returns {Object} - Knockout declaration for it to let binding control descendants.\n         */\n        init: function () {\n            return {\n                controlsDescendantBindings: true\n            };\n        },\n\n        /**\n         * Reads params passed to binding.\n         * Set html to node element, apply bindings and call magento attributes parser.\n         *\n         * @param {HTMLElement} el - Element to apply bindings to.\n         * @param {Function} valueAccessor - Function that returns value, passed to binding.\n         * @param {Object} allBindings - Object, which represents all bindings applied to element.\n         * @param {Object} viewModel - Object, which represents view model binded to el.\n         * @param {ko.bindingContext} bindingContext - Instance of ko.bindingContext, passed to binding initially.\n         */\n        update: function (el, valueAccessor, allBindings, viewModel, bindingContext) {\n            setHtml(el, valueAccessor());\n            applyComponents(el, bindingContext);\n        }\n    };\n\n    renderer.addAttribute('bindHtml');\n});\n","Magento_Ui/js/lib/knockout/bindings/color-picker.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'ko',\n    'jquery',\n    '../template/renderer',\n    'spectrum',\n    'tinycolor'\n], function (ko, $, renderer, spectrum, tinycolor) {\n    'use strict';\n\n    /**\n     * Change color picker status to be enabled or disabled\n     *\n     * @param {HTMLElement} element - Element to apply colorpicker enable/disable status to.\n     * @param {Object} viewModel - Object, which represents view model binded to el.\n     */\n    function changeColorPickerStateBasedOnViewModel(element, viewModel) {\n        $(element).spectrum(viewModel.disabled() ? 'disable' : 'enable');\n    }\n\n    ko.bindingHandlers.colorPicker = {\n        /**\n         * Binding init callback.\n         *\n         * @param {*} element\n         * @param {Function} valueAccessor\n         * @param {Function} allBindings\n         * @param {Object} viewModel\n         */\n        init: function (element, valueAccessor, allBindings, viewModel) {\n            var config = valueAccessor(),\n\n                /** change value */\n                changeValue = function (value) {\n                    if (value == null) {\n                        value = '';\n                    }\n                    config.value(value.toString());\n                };\n\n            config.change = changeValue;\n\n            config.hide = changeValue;\n\n            /** show value */\n            config.show = function () {\n                if (!viewModel.focused()) {\n                    viewModel.focused(true);\n                }\n\n                return true;\n            };\n\n            $(element).spectrum(config);\n\n            changeColorPickerStateBasedOnViewModel(element, viewModel);\n        },\n\n        /**\n         * Reads params passed to binding, parses component declarations.\n         * Fetches for those found and attaches them to the new context.\n         *\n         * @param {HTMLElement} element - Element to apply bindings to.\n         * @param {Function} valueAccessor - Function that returns value, passed to binding.\n         * @param {Object} allBindings - Object, which represents all bindings applied to element.\n         * @param {Object} viewModel - Object, which represents view model binded to element.\n         */\n        update: function (element, valueAccessor, allBindings, viewModel) {\n            var config = valueAccessor();\n\n            /** Initialise value as empty if it is undefined when color picker input is reset **/\n            if (config.value() === undefined) {\n                config.value('');\n            }\n\n            if (tinycolor(config.value()).isValid() || config.value() === '') {\n                $(element).spectrum('set', config.value());\n\n                if (config.value() !== '') {\n                    config.value($(element).spectrum('get').toString());\n                }\n            }\n\n            changeColorPickerStateBasedOnViewModel(element, viewModel);\n        }\n    };\n\n    renderer.addAttribute('colorPicker');\n});\n","Magento_Ui/js/lib/knockout/template/renderer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'underscore',\n    './loader'\n], function ($, _, loader) {\n    'use strict';\n\n    var colonReg       = /\\\\:/g,\n        renderedTemplatePromises = {},\n        attributes     = {},\n        elements       = {},\n        globals        = [],\n        renderer,\n        preset;\n\n    renderer = {\n\n        /**\n         * Loads template by provided path and\n         * than converts it's content to html.\n         *\n         * @param {String} tmplPath - Path to the template.\n         * @returns {jQueryPromise}\n         * @alias getRendered\n         */\n        render: function (tmplPath) {\n            var cachedPromise = renderedTemplatePromises[tmplPath];\n\n            if (!cachedPromise) {\n                cachedPromise = renderedTemplatePromises[tmplPath] = loader\n                    .loadTemplate(tmplPath)\n                    .then(renderer.parseTemplate);\n            }\n\n            return cachedPromise;\n        },\n\n        /**\n         * @ignore\n         */\n        getRendered: function (tmplPath) {\n            return renderer.render(tmplPath);\n        },\n\n        /**\n         * Parses provided string as html content\n         * and returns an array of DOM elements.\n         *\n         * @param {String} html - String to be processed.\n         * @returns {Array}\n         */\n        parseTemplate: function (html) {\n            var fragment = document.createDocumentFragment();\n\n            $(fragment).append(html);\n\n            return renderer.normalize(fragment);\n        },\n\n        /**\n         * Processes custom attributes and nodes of provided DOM element.\n         *\n         * @param {HTMLElement} content - Element to be processed.\n         * @returns {Array} An array of content's child nodes.\n         */\n        normalize: function (content) {\n            globals.forEach(function (handler) {\n                handler(content);\n            });\n\n            return _.toArray(content.childNodes);\n        },\n\n        /**\n         * Adds new global content handler.\n         *\n         * @param {Function} handler - Function which will be invoked for\n         *      an every content passed to 'normalize' method.\n         * @returns {Renderer} Chainable.\n         */\n        addGlobal: function (handler) {\n            if (!_.contains(globals, handler)) {\n                globals.push(handler);\n            }\n\n            return this;\n        },\n\n        /**\n         * Removes specified global content handler.\n         *\n         * @param {Function} handler - Handler to be removed.\n         * @returns {Renderer} Chainable.\n         */\n        removeGlobal: function (handler) {\n            var index = globals.indexOf(handler);\n\n            if (~index) {\n                globals.splice(index, 1);\n            }\n\n            return this;\n        },\n\n        /**\n         * Adds new custom attribute handler.\n         *\n         * @param {String} id - Attribute identifier.\n         * @param {(Object|Function)} [config={}]\n         * @returns {Renderer} Chainable.\n         */\n        addAttribute: function (id, config) {\n            var data = {\n                name: id,\n                binding: id,\n                handler: renderer.handlers.attribute\n            };\n\n            if (_.isFunction(config)) {\n                data.handler = config;\n            } else if (_.isObject(config)) {\n                _.extend(data, config);\n            }\n\n            data.id = id;\n            attributes[id] = data;\n\n            return this;\n        },\n\n        /**\n         * Removes specified attribute handler.\n         *\n         * @param {String} id - Attribute identifier.\n         * @returns {Renderer} Chainable.\n         */\n        removeAttribute: function (id) {\n            delete attributes[id];\n\n            return this;\n        },\n\n        /**\n         * Adds new custom node handler.\n         *\n         * @param {String} id - Node identifier.\n         * @param {(Object|Function)} [config={}]\n         * @returns {Renderer} Chainable.\n         */\n        addNode: function (id, config) {\n            var data = {\n                name: id,\n                binding: id,\n                handler: renderer.handlers.node\n            };\n\n            if (_.isFunction(config)) {\n                data.handler = config;\n            } else if (_.isObject(config)) {\n                _.extend(data, config);\n            }\n\n            data.id = id;\n            elements[id] = data;\n\n            return this;\n        },\n\n        /**\n         * Removes specified custom node handler.\n         *\n         * @param {String} id - Node identifier.\n         * @returns {Renderer} Chainable.\n         */\n        removeNode: function (id) {\n            delete elements[id];\n\n            return this;\n        },\n\n        /**\n         * Checks if provided DOM element is a custom node.\n         *\n         * @param {HTMLElement} node - Node to be checked.\n         * @returns {Boolean}\n         */\n        isCustomNode: function (node) {\n            return _.some(elements, function (elem) {\n                return elem.name.toUpperCase() === node.tagName;\n            });\n        },\n\n        /**\n         * Processes custom attributes of a content's child nodes.\n         *\n         * @param {HTMLElement} content - DOM element to be processed.\n         */\n        processAttributes: function (content) {\n            var repeat;\n\n            repeat = _.some(attributes, function (attr) {\n                var attrName = attr.name,\n                    nodes    = content.querySelectorAll('[' + attrName + ']'),\n                    handler  = attr.handler;\n\n                return _.toArray(nodes).some(function (node) {\n                    var data = node.getAttribute(attrName);\n\n                    return handler(node, data, attr) === true;\n                });\n            });\n\n            if (repeat) {\n                renderer.processAttributes(content);\n            }\n        },\n\n        /**\n         * Processes custom nodes of a provided content.\n         *\n         * @param {HTMLElement} content - DOM element to be processed.\n         */\n        processNodes: function (content) {\n            var repeat;\n\n            repeat = _.some(elements, function (element) {\n                var nodes   = content.querySelectorAll(element.name),\n                    handler = element.handler;\n\n                return _.toArray(nodes).some(function (node) {\n                    var data = node.getAttribute('args');\n\n                    return handler(node, data, element) === true;\n                });\n            });\n\n            if (repeat) {\n                renderer.processNodes(content);\n            }\n        },\n\n        /**\n         * Wraps provided string in curly braces if it's necessary.\n         *\n         * @param {String} args - String to be wrapped.\n         * @returns {String} Wrapped string.\n         */\n        wrapArgs: function (args) {\n            if (~args.indexOf('\\\\:')) {\n                args = args.replace(colonReg, ':');\n            } else if (~args.indexOf(':') && !~args.indexOf('}')) {\n                args = '{' + args + '}';\n            }\n\n            return args;\n        },\n\n        /**\n         * Wraps child nodes of provided DOM element\n         * with knockout's comment tag.\n         *\n         * @param {HTMLElement} node - Node whose children should be wrapped.\n         * @param {String} binding - Name of the binding for the opener comment tag.\n         * @param {String} data - Data associated with a binding.\n         *\n         * @example\n         *      <div id=\"example\"><span/></div>\n         *      wrapChildren(document.getElementById('example'), 'foreach', 'data');\n         *      =>\n         *      <div id=\"example\">\n         *      <!-- ko foreach: data -->\n         *          <span></span>\n         *      <!-- /ko -->\n         *      </div>\n         */\n        wrapChildren: function (node, binding, data) {\n            var tag = this.createComment(binding, data),\n                $node = $(node);\n\n            $node.prepend(tag.open);\n            $node.append(tag.close);\n        },\n\n        /**\n         * Wraps specified node with knockout's comment tag.\n         *\n         * @param {HTMLElement} node - Node to be wrapped.\n         * @param {String} binding - Name of the binding for the opener comment tag.\n         * @param {String} data - Data associated with a binding.\n         *\n         * @example\n         *      <div id=\"example\"></div>\n         *      wrapNode(document.getElementById('example'), 'foreach', 'data');\n         *      =>\n         *      <!-- ko foreach: data -->\n         *          <div id=\"example\"></div>\n         *      <!-- /ko -->\n         */\n        wrapNode: function (node, binding, data) {\n            var tag = this.createComment(binding, data),\n                $node = $(node);\n\n            $node.before(tag.open);\n            $node.after(tag.close);\n        },\n\n        /**\n         * Creates knockouts' comment tag for the provided binding.\n         *\n         * @param {String} binding - Name of the binding.\n         * @param {String} data - Data associated with a binding.\n         * @returns {Object} Object with an open and close comment elements.\n         */\n        createComment: function (binding, data) {\n            return {\n                open: document.createComment(' ko ' + binding + ': ' + data + ' '),\n                close: document.createComment(' /ko ')\n            };\n        }\n    };\n\n    renderer.handlers = {\n\n        /**\n         * Basic node handler. Replaces custom nodes\n         * with a corresponding knockout's comment tag.\n         *\n         * @param {HTMLElement} node - Node to be processed.\n         * @param {String} data\n         * @param {Object} element\n         * @returns {Boolean} True\n         *\n         * @example Sample syntaxes conversions.\n         *      <with args=\"model\">\n         *          <span/>\n         *      </with>\n         *      =>\n         *      <!-- ko with: model-->\n         *          <span/>\n         *      <!-- /ko -->\n         */\n        node: function (node, data, element) {\n            data = renderer.wrapArgs(data);\n\n            renderer.wrapNode(node, element.binding, data);\n            $(node).replaceWith(node.childNodes);\n\n            return true;\n        },\n\n        /**\n         * Base attribute handler. Replaces custom attributes with\n         * a corresponding knockouts' data binding.\n         *\n         * @param {HTMLElement} node - Node to be processed.\n         * @param {String} data - Data associated with a binding.\n         * @param {Object} attr - Attribute definition.\n         *\n         * @example Sample syntaxes conversions.\n         *      <div text=\"label\"></div>\n         *      =>\n         *      <div data-bind=\"text: label\"></div>\n         */\n        attribute: function (node, data, attr) {\n            data = renderer.wrapArgs(data);\n\n            renderer.bindings.add(node, attr.binding, data);\n            node.removeAttribute(attr.name);\n        },\n\n        /**\n         * Wraps provided node with a knockouts' comment tag.\n         *\n         * @param {HTMLElement} node - Node that will be wrapped.\n         * @param {String} data - Data associated with a binding.\n         * @param {Object} attr - Attribute definition.\n         *\n         * @example\n         *      <div outereach=\"data\" class=\"test\"></div>\n         *      =>\n         *      <!-- ko foreach: data -->\n         *          <div class=\"test\"></div>\n         *      <!-- /ko -->\n         */\n        wrapAttribute: function (node, data, attr) {\n            data = renderer.wrapArgs(data);\n\n            renderer.wrapNode(node, attr.binding, data);\n            node.removeAttribute(attr.name);\n        }\n    };\n\n    renderer.bindings = {\n\n        /**\n         * Appends binding string to the current\n         * 'data-bind' attribute of provided node.\n         *\n         * @param {HTMLElement} node - DOM element whose 'data-bind' attribute will be extended.\n         * @param {String} name - Name of a binding.\n         * @param {String} data - Data associated with the binding.\n         */\n        add: function (node, name, data) {\n            var bindings = this.get(node);\n\n            if (bindings) {\n                bindings += ', ';\n            }\n\n            bindings += name;\n\n            if (data) {\n                bindings += ': ' + data;\n            }\n\n            this.set(node, bindings);\n        },\n\n        /**\n         * Extracts value of a 'data-bind' attribute from provided node.\n         *\n         * @param {HTMLElement} node - Node whose attribute to be extracted.\n         * @returns {String}\n         */\n        get: function (node) {\n            return node.getAttribute('data-bind') || '';\n        },\n\n        /**\n         * Sets 'data-bind' attribute of the specified node\n         * to the provided value.\n         *\n         * @param {HTMLElement} node - Node whose attribute will be altered.\n         * @param {String} bindings - New value of 'data-bind' attribute.\n         */\n        set: function (node, bindings) {\n            node.setAttribute('data-bind', bindings);\n        }\n    };\n\n    renderer\n        .addGlobal(renderer.processAttributes)\n        .addGlobal(renderer.processNodes);\n\n    /**\n     * Collection of default binding conversions.\n     */\n    preset = {\n        nodes: _.object([\n            'if',\n            'text',\n            'with',\n            'scope',\n            'ifnot',\n            'foreach',\n            'component'\n        ], Array.prototype),\n        attributes: _.object([\n            'css',\n            'attr',\n            'html',\n            'with',\n            'text',\n            'click',\n            'event',\n            'submit',\n            'enable',\n            'disable',\n            'options',\n            'visible',\n            'template',\n            'hasFocus',\n            'textInput',\n            'component',\n            'uniqueName',\n            'optionsText',\n            'optionsValue',\n            'checkedValue',\n            'selectedOptions'\n        ], Array.prototype)\n    };\n\n    _.extend(preset.attributes, {\n        if: renderer.handlers.wrapAttribute,\n        ifnot: renderer.handlers.wrapAttribute,\n        innerif: {\n            binding: 'if'\n        },\n        innerifnot: {\n            binding: 'ifnot'\n        },\n        outereach: {\n            binding: 'foreach',\n            handler: renderer.handlers.wrapAttribute\n        },\n        foreach: {\n            name: 'each'\n        },\n        value: {\n            name: 'ko-value'\n        },\n        style: {\n            name: 'ko-style'\n        },\n        checked: {\n            name: 'ko-checked'\n        },\n        disabled: {\n            name: 'ko-disabled',\n            binding: 'disable'\n        },\n        focused: {\n            name: 'ko-focused',\n            binding: 'hasFocus'\n        },\n\n        /**\n         * Custom 'render' attribute handler function. Wraps child elements\n         * of a node with knockout's 'ko template:' comment tag.\n         *\n         * @param {HTMLElement} node - Element to be processed.\n         * @param {String} data - Data specified in 'render' attribute of a node.\n         */\n        render: function (node, data) {\n            data = data || 'getTemplate()';\n            data = renderer.wrapArgs(data);\n\n            renderer.wrapChildren(node, 'template', data);\n            node.removeAttribute('render');\n        }\n    });\n\n    _.extend(preset.nodes, {\n        foreach: {\n            name: 'each'\n        },\n\n        /**\n         * Custom 'render' node handler function.\n         * Replaces node with knockout's 'ko template:' comment tag.\n         *\n         * @param {HTMLElement} node - Element to be processed.\n         * @param {String} data - Data specified in 'args' attribute of a node.\n         */\n        render: function (node, data) {\n            data = data || 'getTemplate()';\n            data = renderer.wrapArgs(data);\n\n            renderer.wrapNode(node, 'template', data);\n            $(node).replaceWith(node.childNodes);\n        }\n    });\n\n    _.each(preset.attributes, function (data, id) {\n        renderer.addAttribute(id, data);\n    });\n\n    _.each(preset.nodes, function (data, id) {\n        renderer.addNode(id, data);\n    });\n\n    return renderer;\n});\n","Magento_Ui/js/lib/knockout/template/observable_source.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * Is being used by knockout template engine to store template to.\n */\ndefine([\n    'ko',\n    'uiClass'\n], function (ko, Class) {\n    'use strict';\n\n    return Class.extend({\n\n        /**\n         * Initializes templateName, _data, nodes properties.\n         *\n         * @param  {template} template - identifier of template\n         */\n        initialize: function (template) {\n            this.templateName = template;\n            this._data = {};\n            this.nodes = ko.observable([]);\n        },\n\n        /**\n         * Data setter. If only one arguments passed, returns corresponding value.\n         * Else, writes into it.\n         * @param  {String} key - key to write to or to read from\n         * @param  {*} value\n         * @return {*} - if 1 arg provided, Returns _data[key] property\n         */\n        data: function (key, value) {\n            if (arguments.length === 1) {\n                return this._data[key];\n            }\n\n            this._data[key] = value;\n        }\n    });\n});\n","Magento_Ui/js/lib/knockout/template/loader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery'\n], function ($) {\n    'use strict';\n\n    var licenseRegExp   = /<!--[\\s\\S]*?-->/,\n        defaultPlugin   = 'text',\n        defaultExt      = 'html';\n\n    /**\n     * Checks of provided string contains a file extension.\n     *\n     * @param {String} str - String to be checked.\n     * @returns {Boolean}\n     */\n    function hasFileExtension(str) {\n        return !!~str.indexOf('.') && !!str.split('.').pop();\n    }\n\n    /**\n     * Checks if provided string contains a requirejs's plugin reference.\n     *\n     * @param {String} str - String to be checked.\n     * @returns {Boolean}\n     */\n    function hasPlugin(str) {\n        return !!~str.indexOf('!');\n    }\n\n    /**\n     * Checks if provided string is a full path to the file.\n     *\n     * @param {String} str - String to be checked.\n     * @returns {Boolean}\n     */\n    function isFullPath(str) {\n        return !!~str.indexOf('://');\n    }\n\n    /**\n     * Removes license comment from the provided string.\n     *\n     * @param {String} content - String to be processed.\n     * @returns {String}\n     */\n    function removeLicense(content) {\n        return content.replace(licenseRegExp, function (match) {\n            return ~match.indexOf('/**') ? '' : match;\n        });\n    }\n\n    return {\n\n        /**\n         * Attempts to extract template by provided path from\n         * a DOM element and falls back to a file loading if\n         * none of the DOM nodes was found.\n         *\n         * @param {String} path - Path to the template or a DOM selector.\n         * @returns {jQueryPromise}\n         */\n        loadTemplate: function (path) {\n            var content = this.loadFromNode(path),\n                defer;\n\n            if (content) {\n                defer = $.Deferred();\n\n                defer.resolve(content);\n\n                return defer.promise();\n            }\n\n            return this.loadFromFile(path);\n        },\n\n        /**\n         * Loads template from external file by provided\n         * path, which will be preliminary formatted.\n         *\n         * @param {String} path - Path to the template.\n         * @returns {jQueryPromise}\n         */\n        loadFromFile: function (path) {\n            var loading = $.Deferred();\n\n            path = this.formatPath(path);\n\n            require([path], function (template) {\n                template = removeLicense(template);\n                loading.resolve(template);\n            }, function (err) {\n                loading.reject(err);\n            });\n\n            return loading.promise();\n        },\n\n        /**\n         * Attempts to extract content of a node found by provided selector.\n         *\n         * @param {String} selector - Node's selector (not necessary valid).\n         * @returns {String|Boolean} If specified node doesn't exists\n         *      'false' will be returned, otherwise returns node's content.\n         */\n        loadFromNode: function (selector) {\n            var node;\n\n            try {\n                node =\n                    document.getElementById(selector) ||\n                    document.querySelector(selector);\n\n                return node ? node.innerHTML : false;\n            } catch (e) {\n                return false;\n            }\n        },\n\n        /**\n         * Adds requirejs's plugin and file extension to\n         * to the provided string if it's necessary.\n         *\n         * @param {String} path - Path to be processed.\n         * @returns {String} Formatted path.\n         */\n        formatPath: function (path) {\n            var result = path;\n\n            if (!hasPlugin(path)) {\n                result = defaultPlugin + '!' + result;\n            }\n\n            if (isFullPath(path)) {\n                return result;\n            }\n\n            if (!hasFileExtension(path)) {\n                result += '.' + defaultExt;\n            }\n\n            return result.replace(/^([^\\/]+)/g, '$1/template');\n        }\n    };\n});\n","Magento_Ui/js/lib/knockout/template/engine.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'ko',\n    'underscore',\n    './observable_source',\n    './renderer',\n    '../../logger/console-logger'\n], function ($, ko, _, Source, renderer, consoleLogger) {\n    'use strict';\n\n    var RemoteTemplateEngine,\n        NativeTemplateEngine = ko.nativeTemplateEngine,\n        sources = {};\n\n    /**\n     * Remote template engine class. Is used to be able to load remote templates via knockout template binding.\n     */\n    RemoteTemplateEngine = function () {\n        // Instance reference for closure.\n        var engine = this,\n        // Decorate the builtin Knockout \"template\" binding to track synchronous template renders.\n        origUpdate = ko.bindingHandlers.template.update;\n\n        /**\n         * Counter to track the number of currently running render tasks (both synchronous and asynchronous).\n         * @type {Number}\n         * @private\n         */\n        this._rendersOutstanding = 0;\n\n        /**\n         * Use a jQuery object as an event bus (but any event emitter with on/off/emit methods could work)\n         * @type {jQuery}\n         * @private\n         */\n        this._events = $(this);\n\n        /**\n         * Rendered templates\n         * @type {Object}\n         * @private\n         */\n        this._templatesRendered = {};\n\n        /*eslint-disable no-unused-vars*/\n        /**\n         * Decorate update method\n         *\n         * @param {HTMLElement} element\n         * @param {Function} valueAccessor\n         * @param {Object} allBindings\n         * @param {Object} viewModel\n         * @param {ko.bindingContext} bindingContext\n         * @returns {*}\n         */\n        ko.bindingHandlers.template.update = function (element, valueAccessor, allBindings, viewModel, bindingContext) {\n            /*eslint-enable no-unused-vars*/\n            var options = ko.utils.peekObservable(valueAccessor()),\n                templateName,\n                isSync,\n                updated;\n\n            if (typeof options === 'object') {\n                if (options.templateEngine && options.templateEngine !== engine) {\n                    return origUpdate.apply(this, arguments);\n                }\n\n                if (!options.name) {\n                    consoleLogger.error('Could not find template name', options);\n                }\n                templateName = options.name;\n            } else if (typeof options === 'string') {\n                templateName = options;\n            } else {\n                consoleLogger.error('Could not build a template binding', options);\n            }\n            engine._trackRender(templateName);\n            isSync = engine._hasTemplateLoaded(templateName);\n            updated = origUpdate.apply(this, arguments);\n\n            if (isSync) {\n                engine._releaseRender(templateName, 'sync');\n            }\n\n            return updated;\n        };\n    };\n\n    /**\n     * Creates unique template identifier based on template name and it's extenders (optional)\n     * @param  {String} templateName\n     * @return {String} - unique template identifier\n     */\n    function createTemplateIdentifier(templateName) {\n        return templateName;\n    }\n\n    RemoteTemplateEngine.prototype = new NativeTemplateEngine;\n    RemoteTemplateEngine.prototype.constructor = RemoteTemplateEngine;\n\n    /**\n     * When an asynchronous render task begins, increment the internal counter for tracking when renders are complete.\n     * @private\n     */\n    RemoteTemplateEngine.prototype._trackRender = function (templateName) {\n        var rendersForTemplate = this._templatesRendered[templateName] !== undefined ?\n            this._templatesRendered[templateName] : 0;\n\n        this._rendersOutstanding++;\n        this._templatesRendered[templateName] = rendersForTemplate + 1;\n        this._resolveRenderWaits();\n    };\n\n    /**\n     * When an asynchronous render task ends, decrement the internal counter for tracking when renders are complete.\n     * @private\n     */\n    RemoteTemplateEngine.prototype._releaseRender = function (templateName) {\n        var rendersForTemplate = this._templatesRendered[templateName];\n\n        this._rendersOutstanding--;\n        this._templatesRendered[templateName] = rendersForTemplate - 1;\n        this._resolveRenderWaits();\n    };\n\n    /**\n     * Check to see if renders are complete and trigger events for listeners.\n     * @private\n     */\n    RemoteTemplateEngine.prototype._resolveRenderWaits = function () {\n        if (this._rendersOutstanding === 0) {\n            this._events.triggerHandler('finishrender');\n        }\n    };\n\n    /**\n     * Get a promise for the end of the current run of renders, both sync and async.\n     * @return {jQueryPromise} - promise that resolves when render completes\n     */\n    RemoteTemplateEngine.prototype.waitForFinishRender = function () {\n        var defer = $.Deferred();\n\n        this._events.one('finishrender', defer.resolve);\n\n        return defer.promise();\n    };\n\n    /**\n     * Returns true if this template has already been asynchronously loaded and will be synchronously rendered.\n     * @param {String} templateName\n     * @returns {Boolean}\n     * @private\n     */\n    RemoteTemplateEngine.prototype._hasTemplateLoaded = function (templateName) {\n        // Sources object will have cached template once makeTemplateSource has run\n        return sources.hasOwnProperty(templateName);\n    };\n\n    /**\n     * Overrided method of native knockout template engine.\n     * Caches template after it's unique name and renders in once.\n     * If template name is not typeof string, delegates work to knockout.templateSources.anonymousTemplate.\n     * @param  {*} template\n     * @param  {HTMLElement} templateDocument - document\n     * @param  {Object} options - options, passed to template binding\n     * @param  {ko.bindingContext} bindingContext\n     * @returns {TemplateSource} Object with methods 'nodes' and 'data'.\n     */\n    RemoteTemplateEngine.prototype.makeTemplateSource = function (template, templateDocument, options, bindingContext) {\n        var engine = this,\n            source,\n            templateId;\n\n        if (typeof template === 'string') {\n            templateId = createTemplateIdentifier(template);\n            source = sources[templateId];\n\n            if (!source) {\n                source = new Source(template);\n                source.requestedBy = bindingContext.$data.name;\n                sources[templateId] = source;\n\n                consoleLogger.info('templateStartLoading', {\n                    template: templateId,\n                    component: bindingContext.$data.name\n                });\n\n                renderer.render(template).then(function (rendered) {\n                    consoleLogger.info('templateLoadedFromServer', {\n                        template: templateId,\n                        component: bindingContext.$data.name\n                    });\n                    source.nodes(rendered);\n                    engine._releaseRender(templateId, 'async');\n                }).fail(function () {\n                    consoleLogger.error('templateLoadingFail', {\n                        template: templateId,\n                        component: bindingContext.$data.name\n                    });\n                });\n            }\n\n            if (source.requestedBy !== bindingContext.$data.name) {\n                consoleLogger.info('templateLoadedFromCache', {\n                    template: templateId,\n                    component: bindingContext.$data.name\n                });\n            }\n\n            return source;\n        } else if (template.nodeType === 1 || template.nodeType === 8) {\n            source = new ko.templateSources.anonymousTemplate(template);\n\n            return source;\n        }\n\n        throw new Error('Unknown template type: ' + template);\n    };\n\n    /**\n     * Overrided method of native knockout template engine.\n     * Should return array of html elements.\n     * @param  {TemplateSource} templateSource - object with methods 'nodes' and 'data'.\n     * @return {Array} - array of html elements\n     */\n    RemoteTemplateEngine.prototype.renderTemplateSource = function (templateSource) {\n        var nodes = templateSource.nodes();\n\n        return ko.utils.cloneNodes(nodes);\n    };\n\n    /**\n     * Overrided method of native knockout template engine.\n     * Created in order to invoke makeTemplateSource method with custom set of params.\n     * @param  {*} template - template identifier\n     * @param  {ko.bindingContext} bindingContext\n     * @param  {Object} options - options, passed to template binding\n     * @param  {HTMLElement} templateDocument - document\n     * @return {Array} - array of html elements\n     */\n    RemoteTemplateEngine.prototype.renderTemplate = function (template, bindingContext, options, templateDocument) {\n        var templateSource = this.makeTemplateSource(template, templateDocument, options, bindingContext);\n\n        return this.renderTemplateSource(templateSource);\n    };\n\n    return new RemoteTemplateEngine;\n});\n","Magento_Ui/js/modal/confirm.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'underscore',\n    'mage/translate',\n    'jquery-ui-modules/widget',\n    'Magento_Ui/js/modal/modal'\n], function ($, _, $t) {\n    'use strict';\n\n    $.widget('mage.confirm', $.mage.modal, {\n        options: {\n            modalClass: 'confirm',\n            title: '',\n            focus: '.action-accept',\n            actions: {\n\n                /**\n                 * Callback always - called on all actions.\n                 */\n                always: function () {},\n\n                /**\n                 * Callback confirm.\n                 */\n                confirm: function () {},\n\n                /**\n                 * Callback cancel.\n                 */\n                cancel: function () {}\n            },\n            buttons: [{\n                text: $t('Cancel'),\n                class: 'action-secondary action-dismiss',\n\n                /**\n                 * Click handler.\n                 */\n                click: function (event) {\n                    this.closeModal(event);\n                }\n            }, {\n                text: $t('OK'),\n                class: 'action-primary action-accept',\n\n                /**\n                 * Click handler.\n                 */\n                click: function (event) {\n                    this.closeModal(event, true);\n                }\n            }]\n        },\n\n        /**\n         * Create widget.\n         */\n        _create: function () {\n            this._super();\n            this.modal.find(this.options.modalCloseBtn).off().on('click', _.bind(this.closeModal, this));\n            this.openModal();\n        },\n\n        /**\n         * Remove modal window.\n         */\n        _remove: function () {\n            this.modal.remove();\n        },\n\n        /**\n         * Open modal window.\n         */\n        openModal: function () {\n            return this._super();\n        },\n\n        /**\n         * Close modal window.\n         */\n        closeModal: function (event, result) {\n            result = result || false;\n\n            if (result) {\n                this.options.actions.confirm(event);\n            } else {\n                this.options.actions.cancel(event);\n            }\n            this.options.actions.always(event);\n            this.element.on('confirmclosed', _.bind(this._remove, this));\n\n            return this._super();\n        }\n    });\n\n    return function (config) {\n        return $('<div></div>').html(config.content).confirm(config);\n    };\n});\n","Magento_Ui/js/modal/modalToggle.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/modal'\n], function ($) {\n    'use strict';\n\n    return function (config, el) {\n        var widget,\n            content;\n\n        if (config.contentSelector) {\n            content = $(config.contentSelector);\n        } else if (config.content) {\n            content = $('<div></div>').html(config.content);\n        } else {\n            content = $('<div></div>');\n        }\n\n        widget = content.modal(config);\n\n        $(el).on(config.toggleEvent, function () {\n            var state = widget.data('mage-modal').options.isOpen;\n\n            if (state) {\n                widget.modal('closeModal');\n            } else {\n                widget.modal('openModal');\n            }\n\n            return false;\n        });\n\n        return widget;\n    };\n});\n","Magento_Ui/js/modal/prompt.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'underscore',\n    'mage/template',\n    'text!ui/template/modal/modal-prompt-content.html',\n    'jquery-ui-modules/widget',\n    'Magento_Ui/js/modal/modal',\n    'mage/translate'\n], function ($, _, template, promptContentTmpl) {\n    'use strict';\n\n    $.widget('mage.prompt', $.mage.modal, {\n        options: {\n            modalClass: 'prompt',\n            promptContentTmpl: promptContentTmpl,\n            promptField: '[data-role=\"promptField\"]',\n            attributesForm: {},\n            attributesField: {},\n            value: '',\n            validation: false,\n            validationRules: [],\n            keyEventHandlers: {\n\n                /**\n                 * Enter key press handler,\n                 * submit result and close modal window\n                 * @param {Object} event - event\n                 */\n                enterKey: function (event) {\n                    if (this.options.isOpen && this.modal.find(document.activeElement).length ||\n                        this.options.isOpen && this.modal[0] === document.activeElement) {\n                        this.closeModal(true);\n                        event.preventDefault();\n                    }\n                },\n\n                /**\n                 * Tab key press handler,\n                 * set focus to elements\n                 */\n                tabKey: function () {\n                    if (document.activeElement === this.modal[0]) {\n                        this._setFocus('start');\n                    }\n                },\n\n                /**\n                 * Escape key press handler,\n                 * cancel and close modal window\n                 * @param {Object} event - event\n                 */\n                escapeKey: function (event) {\n                    if (this.options.isOpen && this.modal.find(document.activeElement).length ||\n                        this.options.isOpen && this.modal[0] === document.activeElement) {\n                        this.closeModal();\n                        event.preventDefault();\n                    }\n                }\n            },\n            actions: {\n\n                /**\n                 * Callback always - called on all actions.\n                 */\n                always: function () {},\n\n                /**\n                 * Callback confirm.\n                 */\n                confirm: function () {},\n\n                /**\n                 * Callback cancel.\n                 */\n                cancel: function () {}\n            },\n            buttons: [{\n                text: $.mage.__('Cancel'),\n                class: 'action-secondary action-dismiss',\n\n                /**\n                 * Click handler.\n                 */\n                click: function () {\n                    this.closeModal();\n                }\n            }, {\n                text: $.mage.__('OK'),\n                class: 'action-primary action-accept',\n\n                /**\n                 * Click handler.\n                 */\n                click: function () {\n                    this.closeModal(true);\n                }\n            }]\n        },\n\n        /**\n         * Create widget.\n         */\n        _create: function () {\n            this.options.focus = this.options.promptField;\n            this.options.validation = this.options.validation && this.options.validationRules.length;\n            this.options.outerClickHandler = this.options.outerClickHandler || _.bind(this.closeModal, this, false);\n            this._super();\n            this.modal.find(this.options.modalContent).append(this.getFormTemplate());\n            this.modal.find(this.options.modalCloseBtn).off().on('click',  _.bind(this.closeModal, this, false));\n\n            if (this.options.validation) {\n                this.setValidationClasses();\n            }\n\n            this.openModal();\n        },\n\n        /**\n         * Form template getter.\n         *\n         * @returns {Object} Form template.\n         */\n        getFormTemplate: function () {\n            var formTemplate,\n                formAttr = '',\n                inputAttr = '',\n                attributeName;\n\n            for (attributeName in this.options.attributesForm) {\n                if (this.options.attributesForm.hasOwnProperty(attributeName)) {\n                    formAttr = formAttr + ' ' + attributeName + '=\"' +\n                        this.options.attributesForm[attributeName] + '\"';\n                }\n            }\n\n            for (attributeName in this.options.attributesField) {\n                if (this.options.attributesField.hasOwnProperty(attributeName)) {\n                    inputAttr = inputAttr + ' ' + attributeName + '=\"' +\n                        this.options.attributesField[attributeName] + '\"';\n                }\n            }\n\n            formTemplate = $(template(this.options.promptContentTmpl, {\n                data: this.options,\n                formAttr: formAttr,\n                inputAttr: inputAttr\n            }));\n\n            return formTemplate;\n        },\n\n        /**\n         * Remove widget\n         */\n        _remove: function () {\n            this.modal.remove();\n        },\n\n        /**\n         * Validate prompt field\n         */\n        validate: function () {\n            return $.validator.validateSingleElement(this.options.promptField);\n        },\n\n        /**\n         * Add validation classes to prompt field\n         */\n        setValidationClasses: function () {\n            this.modal.find(this.options.promptField).attr('class', $.proxy(function (i, val) {\n                return val + ' ' + this.options.validationRules.join(' ');\n            }, this));\n        },\n\n        /**\n         * Open modal window\n         */\n        openModal: function () {\n            this._super();\n            this.modal.find(this.options.promptField).val(this.options.value);\n        },\n\n        /**\n         * Close modal window\n         */\n        closeModal: function (result) {\n            var value;\n\n            if (result) {\n                if (this.options.validation && !this.validate()) {\n                    return false;\n                }\n\n                value = this.modal.find(this.options.promptField).val();\n                this.options.actions.confirm.call(this, value);\n            } else {\n                this.options.actions.cancel.call(this, result);\n            }\n\n            this.options.actions.always();\n            this.element.on('promptclosed', _.bind(this._remove, this));\n\n            return this._super();\n        }\n    });\n\n    return function (config) {\n        return $('<div class=\"prompt-message\"></div>').html(config.content).prompt(config);\n    };\n});\n","Magento_Ui/js/modal/modal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'underscore',\n    'mage/template',\n    'text!ui/template/modal/modal-popup.html',\n    'text!ui/template/modal/modal-slide.html',\n    'text!ui/template/modal/modal-custom.html',\n    'Magento_Ui/js/lib/key-codes',\n    'jquery-ui-modules/widget',\n    'jquery-ui-modules/core',\n    'mage/translate',\n    'jquery/z-index'\n], function ($, _, template, popupTpl, slideTpl, customTpl, keyCodes) {\n    'use strict';\n\n    /**\n     * Detect browser transition end event.\n     * @return {String|undefined} - transition event.\n     */\n    var transitionEvent = (function () {\n        var transition,\n            elementStyle = document.createElement('div').style,\n            transitions = {\n                'transition': 'transitionend',\n                'OTransition': 'oTransitionEnd',\n                'MozTransition': 'transitionend',\n                'WebkitTransition': 'webkitTransitionEnd'\n            };\n\n        for (transition in transitions) {\n            if (elementStyle[transition] !== undefined && transitions.hasOwnProperty(transition)) {\n                return transitions[transition];\n            }\n        }\n    })();\n\n    /**\n     * Modal Window Widget\n     */\n    $.widget('mage.modal', {\n        options: {\n            id: null,\n            type: 'popup',\n            title: '',\n            subTitle: '',\n            modalClass: '',\n            focus: '[data-role=\"closeBtn\"]',\n            autoOpen: false,\n            clickableOverlay: true,\n            popupTpl: popupTpl,\n            slideTpl: slideTpl,\n            customTpl: customTpl,\n            modalVisibleClass: '_show',\n            parentModalClass: '_has-modal',\n            innerScrollClass: '_inner-scroll',\n            responsive: false,\n            innerScroll: false,\n            modalTitle: '[data-role=\"title\"]',\n            modalSubTitle: '[data-role=\"subTitle\"]',\n            modalBlock: '[data-role=\"modal\"]',\n            modalCloseBtn: '[data-role=\"closeBtn\"]',\n            modalContent: '[data-role=\"content\"]',\n            modalAction: '[data-role=\"action\"]',\n            focusableScope: '[data-role=\"focusable-scope\"]',\n            focusableStart: '[data-role=\"focusable-start\"]',\n            focusableEnd: '[data-role=\"focusable-end\"]',\n            appendTo: 'body',\n            wrapperClass: 'modals-wrapper',\n            overlayClass: 'modals-overlay',\n            responsiveClass: 'modal-slide',\n            trigger: '',\n            modalLeftMargin: 45,\n            closeText: $.mage.__('Close'),\n            buttons: [{\n                text: $.mage.__('Ok'),\n                class: '',\n                attr: {},\n\n                /**\n                 * Default action on button click\n                 */\n                click: function (event) {\n                    this.closeModal(event);\n                }\n            }],\n            keyEventHandlers: {\n\n                /**\n                 * Tab key press handler,\n                 * set focus to elements\n                 */\n                tabKey: function () {\n                    if (document.activeElement === this.modal[0]) {\n                        this._setFocus('start');\n                    }\n                },\n\n                /**\n                 * Escape key press handler,\n                 * close modal window\n                 * @param {Object} event - event\n                 */\n                escapeKey: function (event) {\n                    if (this.options.isOpen && this.modal.find(document.activeElement).length ||\n                        this.options.isOpen && this.modal[0] === document.activeElement) {\n                        this.closeModal(event);\n                    }\n                }\n            }\n        },\n\n        /**\n         * Creates modal widget.\n         */\n        _create: function () {\n            _.bindAll(\n                this,\n                'keyEventSwitcher',\n                '_tabSwitcher',\n                'closeModal'\n            );\n\n            this.options.id = this.uuid;\n            this.options.transitionEvent = transitionEvent;\n            this._createWrapper();\n            this._renderModal();\n            this._createButtons();\n\n            if (this.options.trigger) {\n                $(document).on('click', this.options.trigger, _.bind(this.toggleModal, this));\n            }\n            this._on(this.modal.find(this.options.modalCloseBtn), {\n                'click': this.options.modalCloseBtnHandler ? this.options.modalCloseBtnHandler : this.closeModal\n            });\n            this._on(this.element, {\n                'openModal': this.openModal,\n                'closeModal': this.closeModal\n            });\n            this.options.autoOpen ? this.openModal() : false;\n        },\n\n        /**\n         * Returns element from modal node.\n         * @return {Object} - element.\n         */\n        _getElem: function (elem) {\n            return this.modal.find(elem);\n        },\n\n        /**\n         * Gets visible modal count.\n         * * @return {Number} - visible modal count.\n         */\n        _getVisibleCount: function () {\n            var modals = this.modalWrapper.find(this.options.modalBlock);\n\n            return modals.filter('.' + this.options.modalVisibleClass).length;\n        },\n\n        /**\n         * Gets count of visible modal by slide type.\n         * * @return {Number} - visible modal count.\n         */\n        _getVisibleSlideCount: function () {\n            var elems = this.modalWrapper.find('[data-type=\"slide\"]');\n\n            return elems.filter('.' + this.options.modalVisibleClass).length;\n        },\n\n        /**\n         * Listener key events.\n         * Call handler function if it exists\n         */\n        keyEventSwitcher: function (event) {\n            var key = keyCodes[event.keyCode];\n\n            if (this.options.keyEventHandlers.hasOwnProperty(key)) {\n                this.options.keyEventHandlers[key].apply(this, arguments);\n            }\n        },\n\n        /**\n         * Set title for modal.\n         *\n         * @param {String} title\n         */\n        setTitle: function (title) {\n            var $title = this.modal.find(this.options.modalTitle),\n                $subTitle = this.modal.find(this.options.modalSubTitle);\n\n            $title.text(title);\n            $title.append($subTitle);\n        },\n\n        /**\n         * Set sub title for modal.\n         *\n         * @param {String} subTitle\n         */\n        setSubTitle: function (subTitle) {\n            this.options.subTitle = subTitle;\n            this.modal.find(this.options.modalSubTitle).html(subTitle);\n        },\n\n        /**\n         * Toggle modal.\n         * * @return {Element} - current element.\n         */\n        toggleModal: function () {\n            if (this.options.isOpen === true) {\n                this.closeModal();\n            } else {\n                this.openModal();\n            }\n        },\n\n        /**\n         * Open modal.\n         * * @return {Element} - current element.\n         */\n        openModal: function () {\n            this.options.isOpen = true;\n            this.focussedElement = document.activeElement;\n            this._createOverlay();\n            this._setActive();\n            this._setKeyListener();\n            this.modal.one(this.options.transitionEvent, _.bind(this._setFocus, this, 'end', 'opened'));\n            this.modal.one(this.options.transitionEvent, _.bind(this._trigger, this, 'opened'));\n            this.modal.addClass(this.options.modalVisibleClass);\n\n            if (!this.options.transitionEvent) {\n                this._trigger('opened');\n            }\n\n            return this.element;\n        },\n\n        /**\n         * Set focus to element.\n         * @param {String} position - can be \"start\" and \"end\"\n         *      positions.\n         *      If position is \"end\" - sets focus to first\n         *      focusable element in modal window scope.\n         *      If position is \"start\" - sets focus to last\n         *      focusable element in modal window scope\n         *\n         *  @param {String} type - can be \"opened\" or false\n         *      If type is \"opened\" - looks to \"this.options.focus\"\n         *      property and sets focus\n         */\n        _setFocus: function (position, type) {\n            var focusableElements,\n                infelicity;\n\n            if (type === 'opened' && this.options.focus) {\n                this.modal.find($(this.options.focus)).trigger('focus');\n            } else if (type === 'opened' && !this.options.focus) {\n                this.modal.find(this.options.focusableScope).trigger('focus');\n            } else if (position === 'end') {\n                this.modal.find(this.options.modalCloseBtn).trigger('focus');\n            } else if (position === 'start') {\n                infelicity = 2; //Constant for find last focusable element\n                focusableElements = this.modal.find(':focusable');\n                focusableElements.eq(focusableElements.length - infelicity).trigger('focus');\n            }\n        },\n\n        /**\n         * Set events listener when modal is opened.\n         */\n        _setKeyListener: function () {\n            this.modal.find(this.options.focusableStart).on('focusin', this._tabSwitcher);\n            this.modal.find(this.options.focusableEnd).on('focusin', this._tabSwitcher);\n            this.modal.on('keydown', this.keyEventSwitcher);\n        },\n\n        /**\n         * Remove events listener when modal is closed.\n         */\n        _removeKeyListener: function () {\n            this.modal.find(this.options.focusableStart).off('focusin', this._tabSwitcher);\n            this.modal.find(this.options.focusableEnd).off('focusin', this._tabSwitcher);\n            this.modal.off('keydown', this.keyEventSwitcher);\n        },\n\n        /**\n         * Switcher for focus event.\n         * @param {Object} e - event\n         */\n        _tabSwitcher: function (e) {\n            var target = $(e.target);\n\n            if (target.is(this.options.focusableStart)) {\n                this._setFocus('start');\n            } else if (target.is(this.options.focusableEnd)) {\n                this._setFocus('end');\n            }\n        },\n\n        /**\n         * Close modal.\n         * * @return {Element} - current element.\n         */\n        closeModal: function () {\n            var that = this;\n\n            this._removeKeyListener();\n            this.options.isOpen = false;\n            this.modal.one(this.options.transitionEvent, function () {\n                that._close();\n            });\n            this.modal.removeClass(this.options.modalVisibleClass);\n\n            if (!this.options.transitionEvent) {\n                that._close();\n            }\n\n            return this.element;\n        },\n\n        /**\n         * Helper for closeModal function.\n         */\n        _close: function () {\n            var trigger = _.bind(this._trigger, this, 'closed', this.modal);\n\n            $(this.focussedElement).trigger('focus');\n            this._destroyOverlay();\n            this._unsetActive();\n            _.defer(trigger, this);\n        },\n\n        /**\n         * Set z-index and margin for modal and overlay.\n         */\n        _setActive: function () {\n            var zIndex = this.modal.zIndex(),\n                baseIndex = zIndex + this._getVisibleCount();\n\n            if (this.modal.data('active')) {\n                return;\n            }\n\n            this.modal.data('active', true);\n\n            this.overlay.zIndex(++baseIndex);\n            this.prevOverlayIndex = this.overlay.zIndex();\n            this.modal.zIndex(this.overlay.zIndex() + 1);\n\n            if (this._getVisibleSlideCount()) {\n                this.modal.css('marginLeft', this.options.modalLeftMargin * this._getVisibleSlideCount());\n            }\n        },\n\n        /**\n         * Unset styles for modal and set z-index for previous modal.\n         */\n        _unsetActive: function () {\n            this.modal.removeAttr('style');\n            this.modal.data('active', false);\n\n            if (this.overlay) {\n                this.overlay.zIndex(this.prevOverlayIndex - 1);\n            }\n        },\n\n        /**\n         * Creates wrapper to hold all modals.\n         */\n        _createWrapper: function () {\n            this.modalWrapper = $(this.options.appendTo).find('.' + this.options.wrapperClass);\n\n            if (!this.modalWrapper.length) {\n                this.modalWrapper = $('<div></div>')\n                    .addClass(this.options.wrapperClass)\n                    .appendTo(this.options.appendTo);\n            }\n        },\n\n        /**\n         * Compile template and append to wrapper.\n         */\n        _renderModal: function () {\n            $(template(\n                this.options[this.options.type + 'Tpl'],\n                {\n                    data: this.options\n                })).appendTo(this.modalWrapper);\n            this.modal = this.modalWrapper.find(this.options.modalBlock).last();\n            this.element.appendTo(this._getElem(this.options.modalContent));\n\n            if (this.element.is(':hidden')) {\n                this.element.show();\n            }\n        },\n\n        /**\n         * Creates buttons pane.\n         */\n        _createButtons: function () {\n            this.buttons = this._getElem(this.options.modalAction);\n            _.each(this.options.buttons, function (btn, key) {\n                var button = this.buttons[key];\n\n                if (btn.attr) {\n                    $(button).attr(btn.attr);\n                }\n\n                if (btn.class) {\n                    $(button).addClass(btn.class);\n                }\n\n                if (!btn.click) {\n                    btn.click = this.closeModal;\n                }\n                $(button).on('click', _.bind(btn.click, this));\n            }, this);\n        },\n\n        /**\n         * Creates overlay, append it to wrapper, set previous click event on overlay.\n         */\n        _createOverlay: function () {\n            var events,\n                outerClickHandler = this.options.outerClickHandler || this.closeModal;\n\n            this.overlay = $('.' + this.options.overlayClass);\n\n            if (!this.overlay.length) {\n                $(this.options.appendTo).addClass(this.options.parentModalClass);\n                this.overlay = $('<div></div>')\n                    .addClass(this.options.overlayClass)\n                    .appendTo(this.modalWrapper);\n            }\n            events = $._data(this.overlay.get(0), 'events');\n            events ? this.prevOverlayHandler = events.click[0].handler : false;\n            this.options.clickableOverlay ? this.overlay.off().on('click', outerClickHandler) : false;\n        },\n\n        /**\n         * Destroy overlay.\n         */\n        _destroyOverlay: function () {\n            if (this._getVisibleCount()) {\n                this.overlay.off().on('click', this.prevOverlayHandler);\n            } else {\n                $(this.options.appendTo).removeClass(this.options.parentModalClass);\n                this.overlay.remove();\n                this.overlay = null;\n            }\n        }\n    });\n\n    return $.mage.modal;\n});\n","Magento_Ui/js/modal/alert.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'underscore',\n    'jquery-ui-modules/widget',\n    'Magento_Ui/js/modal/confirm',\n    'mage/translate'\n], function ($, _) {\n    'use strict';\n\n    $.widget('mage.alert', $.mage.confirm, {\n        options: {\n            modalClass: 'confirm',\n            title: $.mage.__('Attention'),\n            actions: {\n\n                /**\n                 * Callback always - called on all actions.\n                 */\n                always: function () {}\n            },\n            buttons: [{\n                text: $.mage.__('OK'),\n                class: 'action-primary action-accept',\n\n                /**\n                 * Click handler.\n                 */\n                click: function () {\n                    this.closeModal(true);\n                }\n            }]\n        },\n\n        /**\n         * Close modal window.\n         */\n        closeModal: function () {\n            this.options.actions.always();\n            this.element.on('alertclosed', _.bind(this._remove, this));\n\n            return this._super();\n        }\n    });\n\n    return function (config) {\n        return $('<div></div>').html(config.content).alert(config);\n    };\n});\n","Magento_Ui/js/modal/modal-component.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Ui/js/lib/view/utils/async',\n    'uiCollection',\n    'uiRegistry',\n    'underscore',\n    './modal'\n], function ($, Collection, registry, _) {\n    'use strict';\n\n    return Collection.extend({\n        defaults: {\n            template: 'ui/modal/modal-component',\n            title: '',\n            subTitle: '',\n            options: {\n                modalClass: '',\n                title: '',\n                subTitle: '',\n                buttons: [],\n                keyEventHandlers: {}\n            },\n            valid: true,\n            links: {\n                title: 'options.title',\n                subTitle: 'options.subTitle'\n            },\n            listens: {\n                state: 'onState',\n                title: 'setTitle',\n                'options.subTitle': 'setSubTitle'\n            },\n            modalClass: 'modal-component',\n            onCancel: 'closeModal'\n        },\n\n        /**\n         * Initializes component.\n         *\n         * @returns {Object} Chainable.\n         */\n        initialize: function () {\n            this._super();\n            _.bindAll(this,\n                'initModal',\n                'openModal',\n                'closeModal',\n                'toggleModal',\n                'setPrevValues',\n                'validate');\n            this.initializeContent();\n\n            return this;\n        },\n\n        /**\n         * Initializes modal configuration\n         *\n         * @returns {Object} Chainable.\n         */\n        initConfig: function () {\n            return this._super()\n                .initSelector()\n                .initModalEvents();\n        },\n\n        /**\n         * Configure modal selector\n         *\n         * @returns {Object} Chainable.\n         */\n        initSelector: function () {\n            var modalClass = this.name.replace(/\\./g, '_');\n\n            this.contentSelector = '.' + this.modalClass;\n            this.options.modalClass = this.options.modalClass + ' ' + modalClass;\n            this.rootSelector = '.' + modalClass;\n\n            return this;\n        },\n\n        /**\n         * Configure modal keyboard handlers\n         * and outer click\n         *\n         * @returns {Object} Chainable.\n         */\n        initModalEvents: function () {\n            this.options.keyEventHandlers.escapeKey = this.options.outerClickHandler = this[this.onCancel].bind(this);\n\n            return this;\n        },\n\n        /**\n         * Initialize modal's content components\n         */\n        initializeContent: function () {\n            $.async({\n                component: this.name\n            }, this.initModal);\n        },\n\n        /**\n         * Init toolbar section so other components will be able to place something in it\n         */\n        initToolbarSection: function () {\n            this.set('toolbarSection', this.modal.data('mage-modal').modal.find('header').get(0));\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super();\n            this.observe(['state', 'focused']);\n\n            return this;\n        },\n\n        /**\n         * Wrap content in a modal of certain type\n         *\n         * @param {HTMLElement} element\n         * @returns {Object} Chainable.\n         */\n        initModal: function (element) {\n            if (!this.modal) {\n                this.overrideModalButtonCallback();\n                this.options.modalCloseBtnHandler = this[this.onCancel].bind(this);\n                this.modal = $(element).modal(this.options);\n                this.initToolbarSection();\n\n                if (this.waitCbk) {\n                    this.waitCbk();\n                    this.waitCbk = null;\n                }\n            }\n\n            return this;\n        },\n\n        /**\n         * Open modal\n         */\n        openModal: function () {\n            if (this.modal) {\n                this.state(true);\n            } else {\n                this.waitCbk = this.openModal;\n            }\n        },\n\n        /**\n         * Close modal\n         */\n        closeModal: function () {\n            if (this.modal) {\n                this.state(false);\n            } else {\n                this.waitCbk = this.closeModal;\n            }\n        },\n\n        /**\n         * Toggle modal\n         */\n        toggleModal: function () {\n            if (this.modal) {\n                this.state(!this.state());\n            } else {\n                this.waitCbk = this.toggleModal;\n            }\n        },\n\n        /**\n         * Sets title for modal\n         *\n         * @param {String} title\n         */\n        setTitle: function (title) {\n            if (this.title !== title) {\n                this.title = title;\n            }\n\n            if (this.modal) {\n                this.modal.modal('setTitle', title);\n            }\n        },\n\n        /**\n         * Sets subTitle for modal\n         *\n         * @param {String} subTitle\n         */\n        setSubTitle: function (subTitle) {\n            if (this.subTitle !== subTitle) {\n                this.subTitle = subTitle;\n            }\n\n            if (this.modal) {\n                this.modal.modal('setSubTitle', subTitle);\n            }\n        },\n\n        /**\n         * Wrap content in a modal of certain type\n         *\n         * @param {Boolean} state\n         */\n        onState: function (state) {\n            if (state) {\n                this.modal.modal('openModal');\n                this.applyData();\n            } else {\n                this.modal.modal('closeModal');\n            }\n        },\n\n        /**\n         * Validate everything validatable in modal\n         */\n        validate: function (elem) {\n            if (typeof elem === 'undefined') {\n                return;\n            }\n\n            if (typeof elem.validate === 'function') {\n                this.valid &= elem.validate().valid;\n            } else if (elem.elems) {\n                elem.elems().forEach(this.validate, this);\n            }\n        },\n\n        /**\n         * Reset data from provider\n         */\n        resetData: function () {\n            this.elems().forEach(this.resetValue, this);\n        },\n\n        /**\n         * Update 'applied' property with data from modal content\n         */\n        applyData: function () {\n            var applied = {};\n\n            this.elems().forEach(this.gatherValues.bind(this, applied), this);\n            this.applied = applied;\n        },\n\n        /**\n         * Gather values from modal content\n         *\n         * @param {Array} applied\n         * @param {HTMLElement} elem\n         */\n        gatherValues: function (applied, elem) {\n            if (typeof elem.value === 'function') {\n                applied[elem.name] = elem.value();\n            } else if (elem.elems) {\n                elem.elems().forEach(this.gatherValues.bind(this, applied), this);\n            }\n        },\n\n        /**\n         * Set to previous values from modal content\n         *\n         * @param {HTMLElement} elem\n         */\n        setPrevValues: function (elem) {\n            if (typeof elem.value === 'function') {\n                this.modal.focus();\n                elem.value(this.applied[elem.name]);\n            } else if (elem.elems) {\n                elem.elems().forEach(this.setPrevValues, this);\n            }\n        },\n\n        /**\n         * Triggers some method in every modal child elem, if this method is defined\n         *\n         * @param {Object} action - action configuration,\n         * must contain actionName and targetName and\n         * can contain params\n         */\n        triggerAction: function (action) {\n            var targetName = action.targetName,\n                params = action.params || [],\n                actionName = action.actionName,\n                target;\n\n            target = registry.async(targetName);\n\n            if (target && typeof target === 'function' && actionName) {\n                params.unshift(actionName);\n                target.apply(target, params);\n            }\n        },\n\n        /**\n         * Override modal buttons callback placeholders with real callbacks\n         */\n        overrideModalButtonCallback: function () {\n            var buttons = this.options.buttons;\n\n            if (buttons && buttons.length) {\n                buttons.forEach(function (button) {\n                    button.click = this.getButtonClickHandler(button.actions);\n                }, this);\n            }\n        },\n\n        /**\n         * Generate button click handler based on button's 'actions' configuration\n         */\n        getButtonClickHandler: function (actionsConfig) {\n            var actions = actionsConfig.map(\n                function (actionConfig) {\n                    if (_.isObject(actionConfig)) {\n                        return this.triggerAction.bind(this, actionConfig);\n                    }\n\n                    return this[actionConfig] ? this[actionConfig].bind(this) : function () {};\n                }, this);\n\n            return function () {\n                actions.forEach(\n                    function (action) {\n                        action();\n                    }\n                );\n            };\n        },\n\n        /**\n         * Cancels changes in modal:\n         * returning elems values to the previous state,\n         * and close modal\n         */\n        actionCancel: function () {\n            this.elems().forEach(this.setPrevValues, this);\n            this.closeModal();\n        },\n\n        /**\n         * Accept changes in modal by not preventing them.\n         * Can be extended by exporting 'gatherValues' result somewhere\n         */\n        actionDone: function () {\n            this.valid = true;\n            this.elems().forEach(this.validate, this);\n\n            if (this.valid) {\n                this.closeModal();\n            }\n        }\n    });\n});\n","Magento_Ui/js/grid/massactions.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiRegistry',\n    'mageUtils',\n    'Magento_Ui/js/lib/collapsible',\n    'Magento_Ui/js/modal/confirm',\n    'Magento_Ui/js/modal/alert',\n    'mage/translate'\n], function (_, registry, utils, Collapsible, confirm, alert, $t) {\n    'use strict';\n\n    return Collapsible.extend({\n        defaults: {\n            template: 'ui/grid/actions',\n            stickyTmpl: 'ui/grid/sticky/actions',\n            selectProvider: 'ns = ${ $.ns }, index = ids',\n            actions: [],\n            noItemsMsg: $t('You haven\\'t selected any items!'),\n            modules: {\n                selections: '${ $.selectProvider }'\n            }\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Massactions} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe('actions');\n\n            return this;\n        },\n\n        /**\n         * Applies specified action.\n         *\n         * @param {String} actionIndex - Actions' identifier.\n         * @returns {Massactions} Chainable.\n         */\n        applyAction: function (actionIndex) {\n            var data = this.getSelections(),\n                action,\n                callback;\n\n            if (!data.total) {\n                alert({\n                    content: this.noItemsMsg\n                });\n\n                return this;\n            }\n\n            action   = this.getAction(actionIndex);\n            callback = this._getCallback(action, data);\n\n            action.confirm ?\n                this._confirm(action, callback) :\n                callback();\n\n            return this;\n        },\n\n        /**\n         * Retrieves selections data from the selections provider.\n         *\n         * @returns {Object|Undefined}\n         */\n        getSelections: function () {\n            var provider = this.selections(),\n                selections = provider && provider.getSelections();\n\n            return selections;\n        },\n\n        /**\n         * Retrieves action object associated with a specified index.\n         *\n         * @param {String} actionIndex - Actions' identifier.\n         * @returns {Object} Action object.\n         */\n        getAction: function (actionIndex) {\n            return _.findWhere(this.actions(), {\n                type: actionIndex\n            });\n        },\n\n        /**\n         * Adds new action. If action with a specified identifier\n         * already exists, than the original one will be overrided.\n         *\n         * @param {Object} action - Action object.\n         * @returns {Massactions} Chainable.\n         */\n        addAction: function (action) {\n            var actions = this.actions(),\n                index = _.findIndex(actions, {\n                    type: action.type\n                });\n\n            ~index ?\n                actions[index] = action :\n                actions.push(action);\n\n            this.actions(actions);\n\n            return this;\n        },\n\n        /**\n         * Creates action callback based on its' data. If action doesn't spicify\n         * a callback function than the default one will be used.\n         *\n         * @private\n         * @param {Object} action - Actions' object.\n         * @param {Object} selections - Selections data.\n         * @returns {Function} Callback function.\n         */\n        _getCallback: function (action, selections) {\n            var callback = action.callback,\n                args     = [action, selections];\n\n            if (utils.isObject(callback)) {\n                args.unshift(callback.target);\n\n                callback = registry.async(callback.provider);\n            } else if (typeof callback != 'function') {\n                callback = this.defaultCallback.bind(this);\n            }\n\n            return function () {\n                callback.apply(null, args);\n            };\n        },\n\n        /**\n         * Default action callback. Sends selections data\n         * via POST request.\n         *\n         * @param {Object} action - Action data.\n         * @param {Object} data - Selections data.\n         */\n        defaultCallback: function (action, data) {\n            var itemsType = data.excludeMode ? 'excluded' : 'selected',\n                selections = {};\n\n            selections[itemsType] = data[itemsType];\n\n            if (!selections[itemsType].length) {\n                selections[itemsType] = false;\n            }\n\n            _.extend(selections, data.params || {});\n\n            utils.submit({\n                url: action.url,\n                data: selections\n            });\n        },\n\n        /**\n         * Shows actions' confirmation window.\n         *\n         * @param {Object} action - Actions' data.\n         * @param {Function} callback - Callback that will be\n         *      invoked if action is confirmed.\n         */\n        _confirm: function (action, callback) {\n            var confirmData = action.confirm,\n                data = this.getSelections(),\n                total = data.total ? data.total : 0,\n                confirmMessage = confirmData.message + (data.showTotalRecords || data.showTotalRecords === undefined ?\n                    ' (' + total + ' record' + (total > 1 ? 's' : '') + ')'\n                    : '');\n\n            confirm({\n                title: confirmData.title,\n                content: confirmMessage,\n                actions: {\n                    confirm: callback\n                }\n            });\n        }\n    });\n});\n","Magento_Ui/js/grid/data-storage.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    'mageUtils',\n    'uiClass'\n], function ($, _, utils, Class) {\n    'use strict';\n\n    return Class.extend({\n        defaults: {\n            cacheRequests: true,\n            cachedRequestDelay: 50,\n            indexField: 'entity_id',\n            requestConfig: {\n                url: '${ $.updateUrl }',\n                method: 'GET',\n                dataType: 'json'\n            },\n            dataScope: '',\n            data: {}\n        },\n\n        /**\n         * Initializes dataStorage configuration.\n         *\n         * @returns {DataStorage} Chainable.\n         */\n        initConfig: function () {\n            var scope;\n\n            this._super();\n\n            scope = this.dataScope;\n\n            if (typeof scope === 'string') {\n                this.dataScope = scope ? [scope] : [];\n            }\n\n            this._requests = [];\n\n            return this;\n        },\n\n        /**\n         * Extracts data which matches specified set of identifiers.\n         *\n         * @param {Array} ids - Records identifiers.\n         * @returns {Array|Boolean}\n         */\n        getByIds: function (ids) {\n            var result = [],\n                hasData;\n\n            hasData = ids.every(function (id) {\n                var item = this.data[id];\n\n                return item ? result.push(item) : false;\n            }, this);\n\n            return hasData ? result : false;\n        },\n\n        /**\n         * Extracts identifiers of provided records.\n         * If no records were provided then full list of\n         * current data id's will be returned.\n         *\n         * @param {Object|Array} [data=this.data]\n         * @returns {Array}\n         */\n        getIds: function (data) {\n            data = data || this.data;\n\n            return _.pluck(data, this.indexField);\n        },\n\n        /**\n         * Extracts data which matches specified parameters.\n         *\n         * @param {Object} params - Request parameters.\n         * @param {Object} [options={}]\n         * @returns {jQueryPromise}\n         */\n        getData: function (params, options) {\n            var cachedRequest;\n\n            if (this.hasScopeChanged(params)) {\n                this.clearRequests();\n            } else {\n                cachedRequest = this.getRequest(params);\n            }\n\n            options = options || {};\n\n            return !options.refresh && cachedRequest ?\n                this.getRequestData(cachedRequest) :\n                this.requestData(params);\n        },\n\n        /**\n         * Tells whether one of the parameters defined in the \"dataScope\" has\n         * changed since the last request.\n         *\n         * @param {Object} params - Request parameters.\n         * @returns {Boolean}\n         */\n        hasScopeChanged: function (params) {\n            var lastRequest = _.last(this._requests),\n                keys,\n                diff;\n\n            if (!lastRequest) {\n                return false;\n            }\n\n            diff = utils.compare(lastRequest.params, params);\n\n            keys = _.pluck(diff.changes, 'path');\n            keys = keys.concat(Object.keys(diff.containers));\n\n            return _.intersection(this.dataScope, keys).length > 0;\n        },\n\n        /**\n         * Extends records of current data object\n         * with the provided records collection.\n         *\n         * @param {Array} data - An array of records.\n         * @returns {DataStorage} Chainable.\n         */\n        updateData: function (data) {\n            var records = _.indexBy(data || [], this.indexField);\n\n            _.extend(this.data, records);\n\n            return this;\n        },\n\n        /**\n         * Sends request to the server with provided parameters.\n         *\n         * @param {Object} params - Request parameters.\n         * @returns {jQueryPromise}\n         */\n        requestData: function (params) {\n            var query = utils.copy(params),\n                handler = this.onRequestComplete.bind(this, query),\n                request;\n\n            this.requestConfig.data = query;\n            request = $.ajax(this.requestConfig).done(handler);\n\n            return request;\n        },\n\n        /**\n         * Returns request's instance which\n         * contains provided parameters.\n         *\n         * @param {Object} params - Request parameters.\n         * @returns {Object} Instance of request.\n         */\n        getRequest: function (params) {\n            return _.find(this._requests, function (request) {\n                return _.isEqual(params, request.params);\n            }, this);\n        },\n\n        /**\n         * Forms data object associated with provided request.\n         *\n         * @param {Object} request - Request object.\n         * @returns {jQueryPromise}\n         */\n        getRequestData: function (request) {\n            var defer = $.Deferred(),\n                resolve = defer.resolve.bind(defer),\n                delay = this.cachedRequestDelay,\n                result;\n\n            if (request.showTotalRecords === undefined) {\n                request.showTotalRecords = true;\n            }\n\n            result = {\n                items: this.getByIds(request.ids),\n                totalRecords: request.totalRecords,\n                showTotalRecords: request.showTotalRecords,\n                errorMessage: request.errorMessage\n            };\n\n            delay ?\n                _.delay(resolve, delay, result) :\n                resolve(result);\n\n            return defer.promise();\n        },\n\n        /**\n         * Caches requests object with provided parameters\n         * and data object associated with it.\n         *\n         * @param {Object} data - Data associated with request.\n         * @param {Object} params - Request parameters.\n         * @returns {DataStorage} Chainable.\n         */\n        cacheRequest: function (data, params) {\n            var cached = this.getRequest(params);\n\n            if (cached) {\n                this.removeRequest(cached);\n            }\n\n            if (data.showTotalRecords === undefined) {\n                data.showTotalRecords = true;\n            }\n\n            this._requests.push({\n                ids: this.getIds(data.items),\n                params: params,\n                totalRecords: data.totalRecords,\n                showTotalRecords: data.showTotalRecords,\n                errorMessage: data.errorMessage\n            });\n\n            return this;\n        },\n\n        /**\n         * Clears all cached requests.\n         *\n         * @returns {DataStorage} Chainable.\n         */\n        clearRequests: function () {\n            this._requests.splice(0);\n\n            return this;\n        },\n\n        /**\n         * Removes provided request object from cached requests list.\n         *\n         * @param {Object} request - Request object.\n         * @returns {DataStorage} Chainable.\n         */\n        removeRequest: function (request) {\n            var requests = this._requests,\n                index = requests.indexOf(request);\n\n            if (~index) {\n                requests.splice(index, 1);\n            }\n\n            return this;\n        },\n\n        /**\n         * Checks if request with a specified parameters was cached.\n         *\n         * @param {Object} params - Parameters of the request.\n         * @returns {Boolean}\n         */\n        wasRequested: function (params) {\n            return !!this.getRequest(params);\n        },\n\n        /**\n         * Handles successful data request.\n         *\n         * @param {Object} params - Request parameters.\n         * @param {Object} data - Response data.\n         */\n        onRequestComplete: function (params, data) {\n            this.updateData(data.items);\n\n            if (this.cacheRequests) {\n                this.cacheRequest(data, params);\n            }\n        }\n    });\n});\n","Magento_Ui/js/grid/dnd.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    'Magento_Ui/js/lib/view/utils/async',\n    'underscore',\n    'uiRegistry',\n    'uiClass'\n], function (ko, $, _, registry, Class) {\n    'use strict';\n\n    var isTouchDevice = typeof document.ontouchstart !== 'undefined',\n        transformProp;\n\n    /**\n     * Defines supported css 'transform' property.\n     *\n     * @returns {String|Undefined}\n     */\n    transformProp = (function () {\n        var style = document.body.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    /**\n     * Returns first touch data if it's available.\n     *\n     * @param {(MouseEvent|TouchEvent)} e - Event object.\n     * @returns {Object}\n     */\n    function getTouch(e) {\n        return e.touches ? e.touches[0] : e;\n    }\n\n    /**\n     * Moves specified DOM element to the x and y coordinates.\n     *\n     * @param {HTMLElement} elem - Element to be relocated.\n     * @param {Number} x - X coordinate.\n     * @param {Number} y - Y coordinate.\n     */\n    function locate(elem, x, y) {\n        var value = 'translate(' + x + 'px,' + y + 'px)';\n\n        elem.style[transformProp] = value;\n    }\n\n    /*eslint-disable no-extra-parens*/\n    /**\n     * Checks if specified coordinate is inside of the provided area.\n     *\n     * @param {Number} x - X coordinate.\n     * @param {Number} y - Y coordinate.\n     * @param {Object} area - Object which represents area.\n     * @returns {Boolean}\n     */\n    function isInside(x, y, area) {\n        return (\n            area &&\n            x >= area.left && x <= area.right &&\n            y >= area.top && y <= area.bottom\n        );\n    }\n\n    /*eslint-enable no-extra-parens*/\n\n    /**\n     * Calculates distance between two points.\n     *\n     * @param {Number} x1 - X coordinate of a first point.\n     * @param {Number} y1 - Y coordinate of a first point.\n     * @param {Number} x2 - X coordinate of a second point.\n     * @param {Number} y2 - Y coordinate of a second point.\n     * @returns {Number} Distance between points.\n     */\n    function distance(x1, y1, x2, y2) {\n        var dx = x2 - x1,\n            dy = y2 - y1;\n\n        dx *= dx;\n        dy *= dy;\n\n        return Math.sqrt(dx + dy);\n    }\n\n    /**\n     * Returns viewModel associated with a provided DOM element.\n     *\n     * @param {HTMLElement} elem\n     * @returns {Object|Array}\n     */\n    function getModel(elem) {\n        return ko.dataFor(elem);\n    }\n\n    /**\n     * Checks whether cols are identical\n     *\n     * @param {HTMLElement} c1\n     * @param {HTMLElement} c2\n     * @returns {Boolean}\n     */\n    function compareCols(c1, c2) {\n        return c1.cellIndex === c2.cellIndex;\n    }\n\n    return Class.extend({\n        defaults: {\n            rootSelector: '${ $.columnsProvider }:.admin__data-grid-wrap',\n            tableSelector: '${ $.rootSelector } -> table.data-grid',\n            mainTableSelector: '[data-role=\"grid\"]',\n            columnSelector: '${ $.tableSelector } thead tr th',\n            noSelectClass: '_no-select',\n            hiddenClass: '_hidden',\n            fixedX: false,\n            fixedY: true,\n            minDistance: 2,\n            columns: []\n        },\n\n        /**\n         * Initializes Dnd component.\n         *\n         * @returns {Dnd} Chainable.\n         */\n        initialize: function () {\n            _.bindAll(\n                this,\n                'initTable',\n                'initColumn',\n                'removeColumn',\n                'onMouseMove',\n                'onMouseUp',\n                'onMouseDown'\n            );\n\n            this.$body = $('body');\n\n            this._super()\n                .initListeners();\n\n            $.async(this.tableSelector, this.initTable);\n            $.async(this.columnSelector, this.initColumn);\n\n            return this;\n        },\n\n        /**\n         * Binds necessary events listeners.\n         *\n         * @returns {Dnd} Chainbale.\n         */\n        initListeners: function () {\n            if (isTouchDevice) {\n                $(document).on({\n                    touchmove: this.onMouseMove,\n                    touchend: this.onMouseUp,\n                    touchleave: this.onMouseUp\n                });\n            } else {\n                $(document).on({\n                    mousemove: this.onMouseMove,\n                    mouseup: this.onMouseUp\n                });\n            }\n\n            return this;\n        },\n\n        /**\n         * Defines specified table element as a main container.\n         *\n         * @param {HTMLTableElement} table\n         * @returns {Dnd} Chainable.\n         */\n        initTable: function (table) {\n            this.table =  $(table).is(this.mainTableSelector) ?  table : this.table;\n\n            $(table).addClass('data-grid-draggable');\n\n            return this;\n        },\n\n        /**\n         * Sets specified column as a draggable element.\n         *\n         * @param {HTMLTableHeaderCellElement} column - Columns header element.\n         * @returns {Dnd} Chainable.\n         */\n        initColumn: function (column) {\n            var model = getModel(column),\n                eventName;\n\n            if (!model || !model.draggable) {\n                return this;\n            }\n\n            if (!ko.es5.isTracked(model, 'dragover')) {\n                model.track('dragover');\n            }\n\n            this.columns.push(column);\n\n            $(column).bindings({\n                css: {\n                    '_dragover-left': ko.computed(function () {\n                        return model.dragover === 'right';\n                    }),\n                    '_dragover-right': ko.computed(function () {\n                        return model.dragover === 'left';\n                    })\n                }\n            });\n\n            eventName = isTouchDevice ?\n                'touchstart' :\n                'mousedown';\n\n            $(column).on(eventName, this.onMouseDown);\n            $.async.remove(column, this.removeColumn);\n\n            return this;\n        },\n\n        /**\n         * Removes specified column element from the columns array.\n         *\n         * @param {HTMLTableHeaderCellElement} column - Columns header element.\n         * @returns {Dnd} Chainable.\n         */\n        removeColumn: function (column) {\n            var columns = this.columns,\n                index = columns.indexOf(column);\n\n            if (~index) {\n                columns.splice(index, 1);\n            }\n\n            return this;\n        },\n\n        /**\n         * Returns index of column.\n         *\n         * @param {HTMLTableHeaderCellElement} elem\n         * @returns {Number}\n         */\n        _getColumnIndex: function (elem) {\n            return _.toArray(elem.parentNode.cells).indexOf(elem);\n        },\n\n        /**\n         * Calculates coordinates of draggable elements.\n         *\n         * @returns {Dnd} Chainbale.\n         */\n        _cacheCoords: function () {\n            var container   = this.table.getBoundingClientRect(),\n                bodyRect    = document.body.getBoundingClientRect(),\n                grabbed     = this.grabbed,\n                dragElem    = grabbed.elem,\n                cells       = _.toArray(dragElem.parentNode.cells),\n                rect;\n\n            this.coords = this.columns.map(function (column) {\n                var data,\n                    colIndex = _.findIndex(cells, function (cell) {\n                        return compareCols(cell, column);\n                    });\n\n                rect = column.getBoundingClientRect();\n\n                data = {\n                    index: colIndex,\n                    target: column,\n                    orig: rect,\n                    left: rect.left - bodyRect.left,\n                    right: rect.right - bodyRect.left,\n                    top: rect.top - bodyRect.top,\n                    bottom: container.bottom - bodyRect.top\n                };\n\n                if (column === dragElem) {\n                    this.dragArea = data;\n\n                    grabbed.shiftX = rect.left - grabbed.x;\n                    grabbed.shiftY = rect.top - grabbed.y;\n                }\n\n                return data;\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Creates clone of a target table with only specified column visible.\n         *\n         * @param {HTMLTableHeaderCellElement} elem - Dragging column.\n         * @returns {Dnd} Chainbale.\n         */\n        _cloneTable: function (elem) {\n            var clone       = this.table.cloneNode(true),\n                columnIndex = this._getColumnIndex(elem),\n                headRow     = clone.tHead.firstElementChild,\n                headCells   = _.toArray(headRow.cells),\n                tableBody   = clone.tBodies[0],\n                bodyRows    = _.toArray(tableBody.children),\n                origTrs     = this.table.tBodies[0].children;\n\n            clone.style.width = elem.offsetWidth + 'px';\n\n            headCells.forEach(function (th, index) {\n                if (index !== columnIndex) {\n                    headRow.removeChild(th);\n                }\n            });\n\n            headRow.cells[0].style.height = elem.offsetHeight + 'px';\n\n            bodyRows.forEach(function (row, rowIndex) {\n                var cells = row.cells,\n                    cell;\n\n                if (cells.length !== headCells.length) {\n                    tableBody.removeChild(row);\n\n                    return;\n                }\n\n                cell = row.cells[columnIndex].cloneNode(true);\n\n                while (row.firstElementChild) {\n                    row.removeChild(row.firstElementChild);\n                }\n\n                cell.style.height = origTrs[rowIndex].cells[columnIndex].offsetHeight + 'px';\n\n                row.appendChild(cell);\n            });\n\n            this.dragTable = clone;\n\n            $(clone)\n                .addClass('_dragging-copy')\n                .appendTo('body');\n\n            return this;\n        },\n\n        /**\n         * Matches provided coordinates to available areas.\n         *\n         * @param {Number} x - X coordinate of a mouse pointer.\n         * @param {Number} y - Y coordinate of a mouse pointer.\n         * @returns {Object|Undefined} Matched area.\n         */\n        _getDropArea: function (x, y) {\n            return _.find(this.coords, function (area) {\n                return isInside(x, y, area);\n            });\n        },\n\n        /**\n         * Updates state of hovered areas.\n         *\n         * @param {Number} x - X coordinate of a mouse pointer.\n         * @param {Number} y - Y coordinate of a mouse pointer.\n         */\n        _updateAreas: function (x, y) {\n            var leavedArea = this.dropArea,\n                area = this.dropArea = this._getDropArea(x, y);\n\n            if (leavedArea) {\n                this.dragleave(leavedArea);\n            }\n\n            if (area && !compareCols(area.target, this.dragArea.target)) {\n                this.dragenter(area);\n            }\n        },\n\n        /**\n         * Grab action handler.\n         *\n         * @param {Number} x - X coordinate of a grabbed point.\n         * @param {Number} y - Y coordinate of a grabbed point.\n         * @param {HTMLElement} elem - Grabbed element.\n         */\n        grab: function (x, y, elem) {\n            this.initDrag = true;\n\n            this.grabbed = {\n                x: x,\n                y: y,\n                elem: elem\n            };\n\n            this.$body.addClass(this.noSelectClass);\n        },\n\n        /**\n         * Dragstart action handler.\n         *\n         * @param {HTMLTableHeaderCellElement} elem - Element which is dragging.\n         */\n        dragstart: function (elem) {\n            this.initDrag = false;\n            this.dropArea = false;\n            this.dragging = true;\n\n            getModel(elem).dragging(true);\n\n            this._cacheCoords()\n                ._cloneTable(elem);\n        },\n\n        /**\n         * Drag action handler. Locates draggable\n         * grid at a specified coordinates.\n         *\n         * @param {Number} x - X coordinate.\n         * @param {Number} y - Y coordinate.\n         */\n        drag: function (x, y) {\n            var grabbed  = this.grabbed,\n                dragArea = this.dragArea,\n                posX     = x + grabbed.shiftX,\n                posY     = y + grabbed.shiftY;\n\n            if (this.fixedX) {\n                x    = dragArea.left;\n                posX = dragArea.orig.left;\n            }\n\n            if (this.fixedY) {\n                y    = dragArea.top;\n                posY = dragArea.orig.top;\n            }\n\n            locate(this.dragTable, posX, posY);\n\n            if (!isInside(x, y, this.dropArea)) {\n                this._updateAreas(x, y);\n            }\n        },\n\n        /**\n         * Dragenter action handler.\n         *\n         * @param {Object} dropArea\n         */\n        dragenter: function (dropArea) {\n            var direction = this.dragArea.index < dropArea.index ?\n                'left' :\n                'right';\n\n            getModel(dropArea.target).dragover = direction;\n        },\n\n        /**\n         * Dragleave action handler.\n         *\n         * @param {Object} dropArea\n         */\n        dragleave: function (dropArea) {\n            getModel(dropArea.target).dragover = false;\n        },\n\n        /**\n         * Dragend action handler.\n         *\n         * @param {Object} dragArea\n         */\n        dragend: function (dragArea) {\n            var dropArea = this.dropArea,\n                dragElem = dragArea.target;\n\n            this.dragging = false;\n\n            document.body.removeChild(this.dragTable);\n\n            getModel(dragElem).dragging(false);\n\n            if (dropArea && !compareCols(dropArea.target, dragElem)) {\n                this.drop(dropArea, dragArea);\n            }\n        },\n\n        /**\n         * Drop action handler.\n         *\n         * @param {Object} dropArea\n         * @param {Object} dragArea\n         */\n        drop: function (dropArea, dragArea) {\n            var dropModel = getModel(dropArea.target),\n                dragModel = getModel(dragArea.target);\n\n            getModel(this.table).insertChild(dragModel, dropModel);\n            dropModel.dragover = false;\n        },\n\n        /**\n         * Documents' 'mousemove' event handler.\n         *\n         * @param {(MouseEvent|TouchEvent)} e - Event object.\n         */\n        onMouseMove: function (e) {\n            var grab    = this.grabbed,\n                touch   = getTouch(e),\n                x       = touch.pageX,\n                y       = touch.pageY;\n\n            if (this.initDrag || this.dragging) {\n                e.preventDefault();\n            }\n\n            if (this.initDrag && distance(x, y, grab.x, grab.y) >= this.minDistance) {\n                this.dragstart(grab.elem);\n            }\n\n            if (this.dragging) {\n                this.drag(x, y);\n            }\n        },\n\n        /**\n         * Documents' 'mouseup' event handler.\n         */\n        onMouseUp: function () {\n            if (this.initDrag || this.dragging) {\n                this.initDrag = false;\n                this.$body.removeClass(this.noSelectClass);\n            }\n\n            if (this.dragging) {\n                this.dragend(this.dragArea);\n            }\n        },\n\n        /**\n         * Columns' 'mousedown' event handler.\n         *\n         * @param {(MouseEvent|TouchEvent)} e - Event object.\n         */\n        onMouseDown: function (e) {\n            var touch = getTouch(e);\n\n            this.grab(touch.pageX, touch.pageY, e.currentTarget);\n        }\n    });\n});\n","Magento_Ui/js/grid/sortBy.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'uiElement'\n], function (Element) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            template: 'ui/grid/sortBy',\n            options: [],\n            applied: {},\n            sorting: 'asc',\n            columnsProvider: 'ns = ${ $.ns }, componentType = columns',\n            selectedOption: '',\n            isVisible: true,\n            listens: {\n                'selectedOption': 'applyChanges'\n            },\n            statefull: {\n                selectedOption: true,\n                applied: true\n            },\n            exports: {\n                applied: '${ $.provider }:params.sorting'\n            },\n            imports: {\n                preparedOptions: '${ $.columnsProvider }:elems'\n            },\n            modules: {\n                columns: '${ $.columnsProvider }'\n            }\n        },\n\n        /**\n         * @inheritdoc\n         */\n        initObservable: function () {\n            return this._super()\n                .observe([\n                    'applied',\n                    'selectedOption',\n                    'isVisible'\n                ]);\n        },\n\n        /**\n         * Prepared sort order options\n         */\n        preparedOptions: function (columns) {\n            if (columns && columns.length > 0) {\n                columns.map(function (column) {\n                    if (column.sortable === true) {\n                        this.options.push({\n                            value: column.index,\n                            label: column.label\n                        });\n                        this.isVisible(true);\n                    } else {\n                        this.isVisible(false);\n                    }\n                }.bind(this));\n            }\n        },\n\n        /**\n         * Apply changes\n         */\n        applyChanges: function () {\n            this.applied({\n                field: this.selectedOption(),\n                direction: this.sorting\n            });\n        }\n    });\n});\n","Magento_Ui/js/grid/url-filter-applier.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'underscore',\n    'jquery'\n], function (Component, _, $) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            listingNamespace: null,\n            bookmarkProvider: 'componentType = bookmark, ns = ${ $.listingNamespace }',\n            filterProvider: 'componentType = filters, ns = ${ $.listingNamespace }',\n            filterKey: 'filters',\n            searchString: location.search,\n            modules: {\n                bookmarks: '${ $.bookmarkProvider }',\n                filterComponent: '${ $.filterProvider }'\n            }\n        },\n\n        /**\n         * Init component\n         *\n         * @return {exports}\n         */\n        initialize: function () {\n            this._super();\n            this.apply();\n\n            return this;\n        },\n\n        /**\n         * Apply filter\n         */\n        apply: function () {\n            var urlFilter = this.getFilterParam(this.searchString),\n                applied,\n                filters;\n\n            if (_.isUndefined(this.filterComponent())) {\n                setTimeout(function () {\n                    this.apply();\n                }.bind(this), 100);\n\n                return;\n            }\n\n            if (!_.isUndefined(this.bookmarks())) {\n                if (!_.size(this.bookmarks().getViewData(this.bookmarks().defaultIndex))) {\n                    setTimeout(function () {\n                        this.apply();\n                    }.bind(this), 500);\n\n                    return;\n                }\n            }\n\n            if (Object.keys(urlFilter).length) {\n                applied = this.filterComponent().get('applied');\n                filters = $.extend({}, applied, urlFilter);\n                this.filterComponent().set('applied', filters);\n            }\n        },\n\n        /**\n         * Get filter param from url\n         *\n         * @returns {Object}\n         */\n        getFilterParam: function (url) {\n            var searchString = decodeURI(url),\n                itemArray;\n\n            return _.chain(searchString.slice(1).split('&'))\n                .map(function (item) {\n\n                    if (item && item.search(this.filterKey) !== -1) {\n                        itemArray = item.split('=');\n\n                        if (itemArray[1].search('\\\\[') === 0) {\n                            itemArray[1] = itemArray[1].replace(/[\\[\\]]/g, '').split(',');\n                        }\n\n                        itemArray[0] = itemArray[0].replace(this.filterKey, '')\n                                .replace(/[\\[\\]]/g, '');\n\n                        return itemArray;\n                    }\n                }.bind(this))\n                .compact()\n                .object()\n                .value();\n        }\n    });\n});\n","Magento_Ui/js/grid/masonry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'Magento_Ui/js/grid/listing',\n    'Magento_Ui/js/lib/view/utils/raf',\n    'jquery',\n    'ko',\n    'underscore'\n], function (Listing, raf, $, ko, _) {\n    'use strict';\n\n    return Listing.extend({\n        defaults: {\n            template: 'ui/grid/masonry',\n            imports: {\n                rows: '${ $.provider }:data.items',\n                errorMessage: '${ $.provider }:data.errorMessage'\n            },\n            listens: {\n                rows: 'initComponent'\n            },\n\n            /**\n             * Images container id\n             * @param string\n             */\n            containerId: null,\n\n            /**\n             * Minimum aspect ratio for each image\n             * @param int\n             */\n            minRatio: null,\n\n            /**\n             * Container width\n             * @param int\n             */\n            containerWidth: window.innerWidth,\n\n            /**\n             * Margin between images\n             * @param int\n             */\n            imageMargin: 20,\n\n            /**\n             * Maximum image height value\n             * @param int\n             */\n            maxImageHeight: 240,\n\n            /**\n             * The value is minimum image width to height ratio when container width is less than the key\n             * @param {Object}\n             */\n            containerWidthToMinRatio: {\n                640: 3,\n                1280: 5,\n                1920: 8\n            },\n\n            /**\n             * Default minimal image width to height ratio.\n             * Applied when container width is greater than max width in the containerWidthToMinRatio matrix.\n             * @param int\n             */\n            defaultMinRatio: 10,\n\n            /**\n             * Layout update FPS during window resizing\n             */\n            refreshFPS: 60\n        },\n\n        /**\n         * Init observable variables\n         * @return {Object}\n         */\n        initObservable: function () {\n            this._super()\n                .observe([\n                    'rows',\n                    'errorMessage'\n                ]);\n\n            return this;\n        },\n\n        /**\n         * Init component handler\n         * @param {Object} rows\n         * @return {Object}\n         */\n        initComponent: function (rows) {\n            if (!rows.length) {\n                return;\n            }\n            this.imageMargin = parseInt(this.imageMargin, 10);\n            this.container = $('[data-id=\"' + this.containerId + '\"]')[0];\n\n            this.setLayoutStyles();\n            this.setEventListener();\n\n            return this;\n        },\n\n        /**\n         * Set event listener to track resize event\n         */\n        setEventListener: function () {\n            window.addEventListener('resize', function () {\n                this.updateStyles();\n            }.bind(this));\n        },\n\n        /**\n         * Updates styles for component.\n         */\n        updateStyles: function () {\n            raf(function () {\n                this.containerWidth = window.innerWidth;\n                this.setLayoutStyles();\n            }.bind(this), this.refreshFPS);\n        },\n\n        /**\n         * Set layout styles inside the container\n         */\n        setLayoutStyles: function () {\n            var containerWidth = parseInt(this.container.clientWidth, 10),\n                rowImages = [],\n                ratio = 0,\n                rowHeight = 0,\n                calcHeight = 0,\n                isLastRow = false,\n                rowNumber = 1;\n\n            this.setMinRatio();\n\n            this.rows().forEach(function (image, index) {\n                ratio += parseFloat((image.width / image.height).toFixed(2));\n                rowImages.push(image);\n\n                if (ratio < this.minRatio && index + 1 !== this.rows().length) {\n                    // Row has more space for images and the image is not the last one - proceed to the next iteration\n                    return;\n                }\n\n                ratio = Math.max(ratio, this.minRatio);\n                calcHeight = (containerWidth - this.imageMargin * rowImages.length) / ratio;\n                rowHeight = calcHeight < this.maxImageHeight ? calcHeight : this.maxImageHeight;\n                isLastRow = index + 1 === this.rows().length;\n\n                this.assignImagesToRow(rowImages, rowNumber, rowHeight, isLastRow);\n\n                rowImages = [];\n                ratio = 0;\n                rowNumber++;\n\n            }.bind(this));\n        },\n\n        /**\n         * Apply styles, css classes and add properties for images in the row\n         *\n         * @param {Object[]} images\n         * @param {Number} rowNumber\n         * @param {Number} rowHeight\n         * @param {Boolean} isLastRow\n         */\n        assignImagesToRow: function (images, rowNumber, rowHeight, isLastRow) {\n            var imageWidth;\n\n            images.forEach(function (img) {\n                imageWidth = rowHeight * (img.width / img.height).toFixed(2);\n                this.setImageStyles(img, imageWidth, rowHeight);\n                this.setImageClass(img, {\n                    bottom: isLastRow\n                });\n                img.rowNumber = rowNumber;\n            }.bind(this));\n\n            images[0].firstInRow = true;\n            images[images.length - 1].lastInRow = true;\n        },\n\n        /**\n         * Wait for container to initialize\n         */\n        waitForContainer: function (callback) {\n            if (typeof this.container === 'undefined') {\n                setTimeout(function () {\n                    this.waitForContainer(callback);\n                }.bind(this), 500);\n            } else {\n                setTimeout(callback, 0);\n            }\n        },\n\n        /**\n         * Set layout styles when container element is loaded.\n         */\n        setLayoutStylesWhenLoaded: function () {\n            this.waitForContainer(function () {\n                this.setLayoutStyles();\n            }.bind(this));\n        },\n\n        /**\n         * Set styles for every image in layout\n         *\n         * @param {Object} img\n         * @param {Number} width\n         * @param {Number} height\n         */\n        setImageStyles: function (img, width, height) {\n            if (!img.styles) {\n                img.styles = ko.observable();\n            }\n            img.styles({\n                width: parseInt(width, 10) + 'px',\n                height: parseInt(height, 10) + 'px'\n            });\n        },\n\n        /**\n         * Set css classes to and an image\n         *\n         * @param {Object} image\n         * @param {Object} classes\n         */\n        setImageClass: function (image, classes) {\n            if (!image.css) {\n                image.css = ko.observable(classes);\n            }\n            image.css(classes);\n        },\n\n        /**\n         * Set min ratio for images in layout\n         */\n        setMinRatio: function () {\n            var minRatio = _.find(\n                this.containerWidthToMinRatio,\n\n                /**\n                 * Find the minimal ratio for container width in the matrix\n                 *\n                 * @param {Number} ratio\n                 * @param {Number} width\n                 * @returns {Boolean}\n                 */\n                function (ratio, width) {\n                    return this.containerWidth <= width;\n                },\n                this\n            );\n\n            this.minRatio = minRatio ? minRatio : this.defaultMinRatio;\n        },\n\n        /**\n         * Checks if grid has data.\n         *\n         * @returns {Boolean}\n         */\n        hasData: function () {\n            return !!this.rows() && !!this.rows().length;\n        },\n\n        /**\n         * Returns error message returned by the data provider\n         *\n         * @returns {String|null}\n         */\n        getErrorMessageUnsanitizedHtml: function () {\n            return this.errorMessage();\n        }\n    });\n});\n","Magento_Ui/js/grid/resize.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    'ko',\n    'underscore',\n    'mageUtils',\n    'uiRegistry',\n    'Magento_Ui/js/lib/knockout/extender/bound-nodes',\n    'uiElement'\n], function ($, ko, _, utils, registry, boundedNodes, Element) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            rootSelector: '${ $.columnsProvider }:.admin__data-grid-wrap',\n            tableSelector: '${ $.rootSelector } -> table.data-grid',\n            mainTableSelector: '[data-role=\"grid\"]',\n            columnSelector: '${ $.tableSelector } thead tr th',\n            fieldSelector: '${ $.tableSelector } tbody tr td',\n\n            imports: {\n                storageColumnsData: '${ $.storageConfig.path }.storageColumnsData'\n            },\n            storageColumnsData: {},\n            columnsElements: {},\n            tableWidth: 0,\n            sumColumnsWidth: 0,\n            showLines: 4,\n            resizableElementClass: 'shadow-div',\n            resizingColumnClass: '_resizing',\n            fixedLayoutClass: '_layout-fixed',\n            inResizeClass: '_in-resize',\n            visibleClass: '_resize-visible',\n            cellContentElement: 'div.data-grid-cell-content',\n            minColumnWidth: 40,\n            layoutFixedPolyfillIterator: 0,\n            windowResize: false,\n            resizable: false,\n            resizeConfig: {\n                maxRowsHeight: [],\n                curResizeElem: {},\n                depResizeElem: {},\n                previousWidth: null\n            }\n        },\n\n        /**\n         * Initialize application -\n         * binding functions context,\n         * set handlers for table elements\n         *\n         * @returns {Object} Chainable\n         */\n        initialize: function () {\n            _.bindAll(\n                this,\n                'initTable',\n                'initColumn',\n                'mousedownHandler',\n                'mousemoveHandler',\n                'mouseupHandler',\n                'refreshLastColumn',\n                'refreshMaxRowHeight',\n                'preprocessingWidth',\n                '_eventProxy',\n                'checkAfterResize'\n            );\n\n            this._super();\n            this.observe(['maxRowsHeight']);\n            this.maxRowsHeight([]);\n\n            $.async(this.tableSelector, this.initTable);\n            $.async(this.columnSelector, this.initColumn);\n\n            return this;\n        },\n\n        /**\n         * Set table element and adds handler to mousedown on headers\n         *\n         * @returns {Object} Chainable\n         */\n        initTable: function (table) {\n            if ($(table).is(this.mainTableSelector)) {\n                this.table = table;\n                this.tableWidth = $(table).outerWidth();\n                $(window).on('resize', this.checkAfterResize);\n            }\n\n            //TODO - Must be deleted when Firefox fixed problem with table-layout: fixed\n            //ticket to Firefox: https://bugs.webkit.org/show_bug.cgi?id=90068\n            if (navigator.userAgent.search(/Firefox/) > -1) {\n                this._layoutFixedPolyfill();\n            }\n\n            $(table).addClass(this.fixedLayoutClass);\n\n            return this;\n        },\n\n        /**\n         * Window resize handler,\n         * check changes on table width and\n         * set new width to variable\n         * after window resize start preprocessingWidth method\n         */\n        checkAfterResize: function () {\n            var tableWidth,\n                self = this;\n\n            setTimeout(function () {\n                tableWidth = $(self.table).outerWidth();\n\n                if (self.tableWidth !== tableWidth) {\n                    self.tableWidth = tableWidth;\n                } else {\n                    self.preprocessingWidth();\n                }\n            }, 300);\n        },\n\n        /**\n         * Check conditions to set minimal width\n         */\n        checkSumColumnsWidth: function () {\n            var table = $(this.table),\n                elems = table.find('th:not([style*=\"width: auto\"]):visible'),\n                elemsWidthMin = table.find('th[style*=\"width: ' + (this.minColumnWidth - 1) + 'px\"]:visible'),\n                elemsWidthAuto = table.find('th[style*=\"width: auto\"]:visible'),\n                model;\n\n            this.sumColumnsWidth = 0;\n            _.each(elems, function (elem) {\n                model = ko.dataFor(elem);\n                model.width && model.width !== 'auto' ? this.sumColumnsWidth += model.width : false;\n            }, this);\n\n            if (\n                    this.sumColumnsWidth + elemsWidthAuto.length *\n                    this.minColumnWidth + elemsWidthMin.length *\n                    this.minColumnWidth > this.tableWidth\n            ) {\n                return true;\n            }\n\n            return false;\n        },\n\n        /**\n         * Set minimal width to element with \"auto\" width\n         */\n        setWidthToColumnsWidthAuto: function () {\n            var elemsWidthAuto = $(this.table).find('th[style*=\"width: auto\"]:visible');\n\n            _.each(elemsWidthAuto, function (elem) {\n                $(elem).outerWidth(this.minColumnWidth - 1);\n            }, this);\n        },\n\n        /**\n         * Check conditions to set auto width\n         */\n        hasMinimal: function () {\n            var table = $(this.table),\n                elemsWidthMin = table.find('th[style*=\"width: ' + (this.minColumnWidth - 1) + 'px\"]:visible'),\n                elemsWidthAuto = table.find('th[style*=\"width: auto\"]:visible');\n\n            if (\n                    elemsWidthAuto && this.sumColumnsWidth + elemsWidthAuto.length *\n                    this.minColumnWidth + elemsWidthMin.length * this.minColumnWidth + 5 < this.tableWidth\n            ) {\n                return true;\n            }\n\n            return false;\n        },\n\n        /**\n         * Set \"auto\" width to element with minimal width\n         */\n        setAuto: function () {\n            var elemsWidthAuto = $(this.table).find('th[style*=\"width: ' + (this.minColumnWidth - 1) + 'px\"]:visible');\n\n            _.each(elemsWidthAuto, function (elem) {\n                $(elem).outerWidth('auto');\n            }, this);\n        },\n\n        /**\n         * Check columns width and preprocessing\n         */\n        preprocessingWidth: function () {\n            if (this.checkSumColumnsWidth()) {\n                this.setWidthToColumnsWidthAuto();\n            } else if (this.hasMinimal()) {\n                this.setAuto();\n            }\n        },\n\n        /**\n         * Init columns elements,\n         * set width to current column element,\n         * add resizable element to columns header,\n         * check and add no-resize class to last column,\n         * stop parents events,\n         * add handler to visibility column\n         *\n         * @param {Object} column - columns header element (th)\n         */\n        initColumn: function (column) {\n            var model = ko.dataFor(column),\n                ctxIndex = this.getCtxIndex(ko.contextFor(column));\n\n            model.width = this.getDefaultWidth(column);\n\n            if (!this.hasColumn(model, ctxIndex, false)) {\n                this.columnsElements[model.index] = this.columnsElements[model.index] || {};\n                this.columnsElements[model.index][ctxIndex] = column;\n                this.initResizableElement(column);\n                this.setStopPropagationHandler(column);\n                $(column).outerWidth(model.width);\n            }\n\n            this.refreshLastColumn(column);\n            this.preprocessingWidth();\n\n            model.on('visible', this.refreshLastColumn.bind(this, column));\n            model.on('visible', this.preprocessingWidth.bind(this));\n        },\n\n        /**\n         * Hack for mozilla firefox\n         */\n        _layoutFixedPolyfill: function () {\n            var self = this;\n\n            setTimeout(function () {\n                if (self.layoutFixedPolyfillIterator < 20) {\n                    $(window).trigger('resize');\n                    self.layoutFixedPolyfillIterator++;\n                    self._layoutFixedPolyfill();\n                } else {\n                    return false;\n                }\n            }, 500);\n        },\n\n        /**\n         * Check element is resizable or not\n         * and append resizable element to DOM\n         *\n         * @param {Object} column - columns header element (th)\n         * @returns {Boolean}\n         */\n        initResizableElement: function (column) {\n            var model = ko.dataFor(column),\n                templateDragElement = '<div class=\"' + this.resizableElementClass + '\"></div>';\n\n            if (_.isUndefined(model.resizeEnabled) || model.resizeEnabled) {\n                $(column).append(templateDragElement);\n\n                return true;\n            }\n\n            return false;\n        },\n\n        /**\n         * Check event target and if need stop parents event,\n         *\n         * @param {Object} column - columns header element (th)\n         * @returns {Boolean}\n         */\n        setStopPropagationHandler: function (column) {\n            var events,\n                click,\n                mousedown;\n\n            $(column).on('click', this._eventProxy);\n            $(column).on('mousedown', this._eventProxy);\n\n            events = $._data(column, 'events');\n\n            click = events.click;\n            mousedown = events.mousedown;\n            click.unshift(click.pop());\n            mousedown.unshift(mousedown.pop());\n\n            return this;\n        },\n\n        /**\n         * Check event target and stop event if need\n         *\n         * @param {Object} event\n         */\n        _eventProxy: function (event) {\n            if ($(event.target).is('.' + this.resizableElementClass)) {\n\n                if (event.type === 'click') {\n                    event.stopImmediatePropagation();\n                } else if (event.type === 'mousedown') {\n                    this.mousedownHandler(event);\n                }\n            }\n        },\n\n        /**\n         * Check visible columns and set disable class to resizable elements,\n         *\n         * @param {Object} column - columns header element (th)\n         */\n        refreshLastColumn: function (column) {\n            var i = 0,\n                columns = $(column).parent().children().not(':hidden'),\n                length = columns.length;\n\n            $('.' + this.visibleClass).removeClass(this.visibleClass);\n\n            $(column).parent().children().not(':hidden').last().addClass(this.visibleClass);\n\n            for (i; i < length; i++) {\n\n                if (!columns.eq(i).find('.' + this.resizableElementClass).length && i) {\n                    columns.eq(i - 1).addClass(this.visibleClass);\n                }\n            }\n\n        },\n\n        /**\n         * Refresh max height to row elements,\n         *\n         * @param {Object} elem - (td)\n         */\n        refreshMaxRowHeight: function (elem) {\n            var rowsH = this.maxRowsHeight(),\n                curEL = $(elem).find('div'),\n                height,\n                obj = this.hasRow($(elem).parent()[0], true);\n\n            curEL.css('white-space', 'nowrap');\n            height = curEL.height() * this.showLines;\n            curEL.css('white-space', 'normal');\n\n            if (obj) {\n                if (obj.maxHeight < height) {\n                    rowsH[_.indexOf(rowsH, obj)].maxHeight = height;\n                } else {\n                    return false;\n                }\n            } else {\n                rowsH.push({\n                    elem: $(elem).parent()[0],\n                    maxHeight: height\n                });\n            }\n\n            $(elem).parent().children().find(this.cellContentElement).css('max-height', height + 'px');\n            this.maxRowsHeight(rowsH);\n        },\n\n        /**\n         * Set resize class to elements when resizable\n         */\n        _setResizeClass: function () {\n            var rowElements = $(this.table).find('tr');\n\n            rowElements\n                .find('td:eq(' + this.resizeConfig.curResizeElem.ctx.$index() + ')')\n                .addClass(this.resizingColumnClass);\n            rowElements\n                .find('td:eq(' + this.resizeConfig.depResizeElem.ctx.$index() + ')')\n                .addClass(this.resizingColumnClass);\n        },\n\n        /**\n         * Remove resize class to elements when resizable\n         */\n        _removeResizeClass: function () {\n            var rowElements = $(this.table).find('tr');\n\n            rowElements\n                .find('td:eq(' + this.resizeConfig.curResizeElem.ctx.$index() + ')')\n                .removeClass(this.resizingColumnClass);\n            rowElements\n                .find('td:eq(' + this.resizeConfig.depResizeElem.ctx.$index() + ')')\n                .removeClass(this.resizingColumnClass);\n        },\n\n        /**\n         * Check conditions to resize\n         *\n         * @returns {Boolean}\n         */\n        _canResize: function (column) {\n            if (\n                $(column).hasClass(this.visibleClass) ||\n                !$(this.resizeConfig.depResizeElem.elems[0]).find('.' + this.resizableElementClass).length\n            ) {\n                return false;\n            }\n\n            return true;\n        },\n\n        /**\n         * Mouse down event handler,\n         * find current and dep column to resize\n         *\n         * @param {Object} event\n         */\n        mousedownHandler: function (event) {\n            var target = event.target,\n                column = $(target).parent()[0],\n                cfg = this.resizeConfig,\n                body = $('body');\n\n            event.stopImmediatePropagation();\n            cfg.curResizeElem.model = ko.dataFor(column);\n            cfg.curResizeElem.ctx = ko.contextFor(column);\n            cfg.curResizeElem.elems = this.hasColumn(cfg.curResizeElem.model, false, true);\n            cfg.curResizeElem.position = event.pageX;\n            cfg.depResizeElem.elems = this.getNextElements(cfg.curResizeElem.elems[0]);\n            cfg.depResizeElem.model = ko.dataFor(cfg.depResizeElem.elems[0]);\n            cfg.depResizeElem.ctx = ko.contextFor(cfg.depResizeElem.elems[0]);\n\n            this._setResizeClass();\n\n            if (!this._canResize(column)) {\n                return false;\n            }\n\n            event.stopPropagation();\n            this.resizable = true;\n            cfg.curResizeElem.model.width = $(cfg.curResizeElem.elems[0]).outerWidth();\n            cfg.depResizeElem.model.width = $(cfg.depResizeElem.elems[0]).outerWidth();\n            body.addClass(this.inResizeClass);\n            body.on('mousemove', this.mousemoveHandler);\n            $(window).on('mouseup', this.mouseupHandler);\n        },\n\n        /**\n         * Mouse move event handler,\n         * change columns width\n         *\n         * @param {Object} event\n         */\n        mousemoveHandler: function (event) {\n            var cfg = this.resizeConfig,\n                width = event.pageX - cfg.curResizeElem.position,\n                self = this;\n\n            event.stopPropagation();\n            event.preventDefault();\n\n            if (\n                this.resizable &&\n                this.minColumnWidth < cfg.curResizeElem.model.width + width &&\n                this.minColumnWidth < cfg.depResizeElem.model.width - width &&\n                cfg.previousWidth !== width\n            ) {\n                cfg.curResizeElem.model.width += width;\n                cfg.depResizeElem.model.width -= width;\n\n                cfg.curResizeElem.elems.forEach(function (el) {\n                    $(el).outerWidth(cfg.curResizeElem.model.width);\n                });\n                cfg.depResizeElem.elems.forEach(function (el) {\n                    $(el).outerWidth(cfg.depResizeElem.model.width);\n                });\n\n                cfg.previousWidth = width;\n                cfg.curResizeElem.position = event.pageX;\n            } else if (width <= -(cfg.curResizeElem.model.width - this.minColumnWidth)) {\n\n                cfg.curResizeElem.elems.forEach(function (el) {\n                    $(el).outerWidth(self.minColumnWidth);\n                });\n                cfg.depResizeElem.elems.forEach(function (el) {\n                    $(el).outerWidth(\n                    cfg.depResizeElem.model.width +\n                    cfg.curResizeElem.model.width -\n                    self.minColumnWidth);\n                });\n\n            } else if (width >= cfg.depResizeElem.model.width - this.minColumnWidth) {\n\n                cfg.depResizeElem.elems.forEach(function (el) {\n                    $(el).outerWidth(self.minColumnWidth);\n                });\n                cfg.curResizeElem.elems.forEach(function (el) {\n                    $(el).outerWidth(\n                        cfg.curResizeElem.model.width +\n                        cfg.depResizeElem.model.width -\n                        self.minColumnWidth\n                    );\n                });\n            }\n        },\n\n        /**\n         * Mouse up event handler,\n         * change columns width\n         *\n         * @param {Object} event\n         */\n        mouseupHandler: function (event) {\n            var cfg = this.resizeConfig,\n                body = $('body');\n\n            event.stopPropagation();\n            event.preventDefault();\n\n            this._removeResizeClass();\n            this.storageColumnsData[cfg.curResizeElem.model.index] = cfg.curResizeElem.model.width;\n            this.storageColumnsData[cfg.depResizeElem.model.index] = cfg.depResizeElem.model.width;\n            this.resizable = false;\n\n            this.store('storageColumnsData');\n\n            body.removeClass(this.inResizeClass);\n            body.off('mousemove', this.mousemoveHandler);\n            $(window).off('mouseup', this.mouseupHandler);\n        },\n\n        /**\n         * Find dependency element\n         *\n         * @param {Object} element - current element\n         * @returns {Object} next element data\n         */\n        getNextElements: function (element) {\n            var nextElem = $(element).next()[0],\n                nextElemModel = ko.dataFor(nextElem),\n                nextElemData = this.hasColumn(nextElemModel, false, true);\n\n            if (nextElemData) {\n                if (nextElemModel.visible) {\n                    return nextElemData;\n                }\n\n                return this.getNextElements(nextElem);\n            }\n        },\n\n        /**\n         * Get default width\n         *\n         * @param {Object} column - (th) element\n         * @return {String} width for current column\n         */\n        getDefaultWidth: function (column) {\n            var model = ko.dataFor(column);\n\n            if (this.storageColumnsData[model.index]) {\n                return this.storageColumnsData[model.index];\n            }\n\n            if (model.resizeDefaultWidth) {\n                return parseInt(model.resizeDefaultWidth, 10);\n            }\n\n            return 'auto';\n        },\n\n        /**\n         * Check column is render or not\n         *\n         * @param {Object} model - cur column model\n         * @param {String|Boolean} ctxIndex - index of context, or false, if want to get cols from all ctx\n         * @param {Boolean} returned - need return column object or not\n         * @return {Boolean} if returned param is false, returned boolean value, else return current object data\n         */\n        hasColumn: function (model, ctxIndex, returned) {\n            var colElem = this.columnsElements[model.index] || {},\n                getFromAllCtx = ctxIndex === false;\n\n            if (colElem && (getFromAllCtx || colElem.hasOwnProperty(ctxIndex))) {\n\n                if (returned) {\n                    return getFromAllCtx ?\n                        _.values(colElem) :\n                        colElem[ctxIndex];\n                }\n\n                return true;\n            }\n\n            return false;\n        },\n\n        /**\n         * Check row is render or not\n         *\n         * @param {Object} elem - cur column element\n         * @param {Boolean} returned - need return column object or not\n         * @return {Boolean|Object} if returned param is false, returned boolean value, else return current object data\n         */\n        hasRow: function (elem, returned) {\n            var i = 0,\n                el = this.maxRowsHeight(),\n                length = el.length;\n\n            for (i; i < length; i++) {\n                if (this.maxRowsHeight()[i].elem === elem) {\n                    if (returned) {//eslint-disable-line max-depth\n                        return this.maxRowsHeight()[i];\n                    }\n\n                    return true;\n                }\n            }\n\n            return false;\n        },\n\n        /**\n         * Generate index that will identify context\n         *\n         * @param {Object} ctx\n         * @return {String}\n         */\n        getCtxIndex: function (ctx) {\n            return ctx ? ctx.$parents.reduce(function (pv, cv) {\n                return (pv.index || pv) + (cv || {}).index;\n            }) : ctx;\n        }\n    });\n});\n","Magento_Ui/js/grid/listing.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    'Magento_Ui/js/lib/spinner',\n    'rjsResolver',\n    'uiLayout',\n    'uiCollection'\n], function (ko, _, loader, resolver, layout, Collection) {\n    'use strict';\n\n    return Collection.extend({\n        defaults: {\n            template: 'ui/grid/listing',\n            listTemplate: 'ui/list/listing',\n            stickyTmpl: 'ui/grid/sticky/listing',\n            viewSwitcherTmpl: 'ui/grid/view-switcher',\n            positions: false,\n            displayMode: 'grid',\n            displayModes: {\n                grid: {\n                    value: 'grid',\n                    label: 'Grid',\n                    template: '${ $.template }'\n                },\n                list: {\n                    value: 'list',\n                    label: 'List',\n                    template: '${ $.listTemplate }'\n                }\n            },\n            dndConfig: {\n                name: '${ $.name }_dnd',\n                component: 'Magento_Ui/js/grid/dnd',\n                columnsProvider: '${ $.name }',\n                enabled: true\n            },\n            editorConfig: {\n                name: '${ $.name }_editor',\n                component: 'Magento_Ui/js/grid/editing/editor',\n                columnsProvider: '${ $.name }',\n                dataProvider: '${ $.provider }',\n                enabled: false\n            },\n            resizeConfig: {\n                name: '${ $.name }_resize',\n                columnsProvider: '${ $.name }',\n                component: 'Magento_Ui/js/grid/resize',\n                enabled: false\n            },\n            imports: {\n                rows: '${ $.provider }:data.items'\n            },\n            listens: {\n                elems: 'updatePositions updateVisible',\n                '${ $.provider }:reload': 'onBeforeReload',\n                '${ $.provider }:reloaded': 'onDataReloaded'\n            },\n            modules: {\n                dnd: '${ $.dndConfig.name }',\n                resize: '${ $.resizeConfig.name }'\n            },\n            tracks: {\n                displayMode: true\n            },\n            statefull: {\n                displayMode: true\n            }\n        },\n\n        /**\n         * Initializes Listing component.\n         *\n         * @returns {Listing} Chainable.\n         */\n        initialize: function () {\n            _.bindAll(this, 'updateVisible');\n\n            this._super()\n                .initDnd()\n                .initEditor()\n                .initResize();\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Listing} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track({\n                    rows: [],\n                    visibleColumns: []\n                });\n\n            return this;\n        },\n\n        /**\n         * Creates drag&drop widget instance.\n         *\n         * @returns {Listing} Chainable.\n         */\n        initDnd: function () {\n            if (this.dndConfig.enabled) {\n                layout([this.dndConfig]);\n            }\n\n            return this;\n        },\n\n        /**\n         * Initializes resize component.\n         *\n         * @returns {Listing} Chainable.\n         */\n        initResize: function () {\n            if (this.resizeConfig.enabled) {\n                layout([this.resizeConfig]);\n            }\n\n            return this;\n        },\n\n        /**\n         * Creates inline editing component.\n         *\n         * @returns {Listing} Chainable.\n         */\n        initEditor: function () {\n            if (this.editorConfig.enabled) {\n                layout([this.editorConfig]);\n            }\n\n            return this;\n        },\n\n        /**\n         * Called when another element was added to current component.\n         *\n         * @returns {Listing} Chainable.\n         */\n        initElement: function (element) {\n            var currentCount = this.elems().length,\n                totalCount = this.initChildCount;\n\n            if (totalCount === currentCount) {\n                this.initPositions();\n            }\n\n            element.on('visible', this.updateVisible);\n\n            return this._super();\n        },\n\n        /**\n         * Defines initial order of child elements.\n         *\n         * @returns {Listing} Chainable.\n         */\n        initPositions: function () {\n            this.on('positions', this.applyPositions.bind(this));\n\n            this.setStatefull('positions');\n\n            return this;\n        },\n\n        /**\n         * Updates current state of child positions.\n         *\n         * @returns {Listing} Chainable.\n         */\n        updatePositions: function () {\n            var positions = {};\n\n            this.elems.each(function (elem, index) {\n                positions[elem.index] = index;\n            });\n\n            this.set('positions', positions);\n\n            return this;\n        },\n\n        /**\n         * Resorts child elements array according to provided positions.\n         *\n         * @param {Object} positions - Object where key represents child\n         *      index and value is its' position.\n         * @returns {Listing} Chainable.\n         */\n        applyPositions: function (positions) {\n            var sorting;\n\n            sorting = this.elems.map(function (elem) {\n                return {\n                    elem: elem,\n                    position: positions[elem.index]\n                };\n            });\n\n            this.insertChild(sorting);\n\n            return this;\n        },\n\n        /**\n         * Returns reference to 'visibleColumns' array.\n         *\n         * @returns {Array}\n         */\n        getVisible: function () {\n            var observable = ko.getObservable(this, 'visibleColumns');\n\n            return observable || this.visibleColumns;\n        },\n\n        /**\n         * Returns path to the template\n         * defined for a current display mode.\n         *\n         * @returns {String} Path to the template.\n         */\n        getTemplate: function () {\n            var mode = this.displayModes[this.displayMode];\n\n            return mode.template;\n        },\n\n        /**\n         * Returns an array of available display modes.\n         *\n         * @returns {Array<Object>}\n         */\n        getDisplayModes: function () {\n            var modes = this.displayModes;\n\n            return _.values(modes);\n        },\n\n        /**\n         * Sets display mode to provided value.\n         *\n         * @param {String} index\n         * @returns {Listing} Chainable\n         */\n        setDisplayMode: function (index) {\n            this.displayMode = index;\n\n            return this;\n        },\n\n        /**\n         * Returns total number of displayed columns in grid.\n         *\n         * @returns {Number}\n         */\n        countVisible: function () {\n            return this.visibleColumns.length;\n        },\n\n        /**\n         * Updates array of visible columns.\n         *\n         * @returns {Listing} Chainable.\n         */\n        updateVisible: function () {\n            this.visibleColumns = this.elems.filter('visible');\n\n            return this;\n        },\n\n        /**\n         * Checks if grid has data.\n         *\n         * @returns {Boolean}\n         */\n        hasData: function () {\n            return !!this.rows && !!this.rows.length;\n        },\n\n        /**\n         * Hides loader.\n         */\n        hideLoader: function () {\n            loader.get(this.name).hide();\n        },\n\n        /**\n         * Shows loader.\n         */\n        showLoader: function () {\n            loader.get(this.name).show();\n        },\n\n        /**\n         * Handler of the data providers' 'reload' event.\n         */\n        onBeforeReload: function () {\n            this.showLoader();\n        },\n\n        /**\n         * Handler of the data providers' 'reloaded' event.\n         */\n        onDataReloaded: function () {\n            resolver(this.hideLoader, this);\n        }\n    });\n});\n","Magento_Ui/js/grid/export.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    'uiElement'\n], function ($, _, Element) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            template: 'ui/grid/exportButton',\n            selectProvider: 'ns = ${ $.ns }, index = ids',\n            checked: '',\n            additionalParams: [],\n            modules: {\n                selections: '${ $.selectProvider }'\n            }\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super()\n                .initChecked();\n        },\n\n        /** @inheritdoc */\n        initConfig: function () {\n            this._super();\n\n            _.each(this.additionalParams, function (value, key) {\n                key = 'additionalParams.' + key;\n                this.imports[key] = value;\n            }, this);\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super()\n                .observe('checked');\n\n            return this;\n        },\n\n        /**\n         * Checks first option if checked not defined.\n         *\n         * @returns {Object}\n         */\n        initChecked: function () {\n            if (!this.checked()) {\n                this.checked(\n                    this.options[0].value\n                );\n            }\n\n            return this;\n        },\n\n        /**\n         * Compose params object that will be added to request.\n         *\n         * @returns {Object}\n         */\n        getParams: function () {\n            var selections = this.selections(),\n                data = selections ? selections.getSelections() : null,\n                itemsType,\n                result = {};\n\n            if (data) {\n                itemsType = data.excludeMode ? 'excluded' : 'selected';\n                result.filters = data.params.filters;\n                result.search = data.params.search;\n                result.namespace = data.params.namespace;\n                result[itemsType] = data[itemsType];\n                _.each(this.additionalParams, function (param, key) {\n                    result[key] = param;\n                });\n\n                if (!result[itemsType].length) {\n                    result[itemsType] = false;\n                }\n            }\n\n            return result;\n        },\n\n        /**\n         * Find checked option.\n         *\n         * @returns {Object}\n         */\n        getActiveOption: function () {\n            return _.findWhere(this.options, {\n                value: this.checked()\n            });\n        },\n\n        /**\n         * Build option url.\n         *\n         * @param {Object} option\n         * @returns {String}\n         */\n        buildOptionUrl: function (option) {\n            var params = this.getParams();\n\n            if (!params) {\n                return 'javascript:void(0);';\n            }\n\n            return option.url + '?' + $.param(params);\n            //TODO: MAGETWO-40250\n        },\n\n        /**\n         * Redirect to built option url.\n         */\n        applyOption: function () {\n            var option = this.getActiveOption(),\n                url = this.buildOptionUrl(option);\n\n            location.href = url;\n\n        }\n    });\n});\n","Magento_Ui/js/grid/provider.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'underscore',\n    'mageUtils',\n    'rjsResolver',\n    'uiLayout',\n    'Magento_Ui/js/modal/alert',\n    'mage/translate',\n    'uiElement',\n    'uiRegistry',\n    'Magento_Ui/js/grid/data-storage'\n], function ($, _, utils, resolver, layout, alert, $t, Element, registry) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            firstLoad: true,\n            lastError: false,\n            storageConfig: {\n                component: 'Magento_Ui/js/grid/data-storage',\n                provider: '${ $.storageConfig.name }',\n                name: '${ $.name }_storage',\n                updateUrl: '${ $.update_url }'\n            },\n            listens: {\n                params: 'onParamsChange',\n                requestConfig: 'updateRequestConfig'\n            },\n            ignoreTmpls: {\n                data: true\n            },\n            triggerDataReload: false\n        },\n\n        /**\n         * Initializes provider component.\n         *\n         * @returns {Provider} Chainable.\n         */\n        initialize: function () {\n            utils.limit(this, 'onParamsChange', 5);\n            _.bindAll(this, 'onReload');\n\n            this._super()\n                .initStorage()\n                .clearData();\n\n            // Load data when there will\n            // be no more pending assets.\n            resolver(this.reload, this);\n\n            return this;\n        },\n\n        /**\n         * Initializes storage component.\n         *\n         * @returns {Provider} Chainable.\n         */\n        initStorage: function () {\n            layout([this.storageConfig]);\n\n            return this;\n        },\n\n        /**\n         * Clears provider's data properties.\n         *\n         * @returns {Provider} Chainable.\n         */\n        clearData: function () {\n            this.setData({\n                items: [],\n                totalRecords: 0,\n                showTotalRecords: true\n            });\n\n            return this;\n        },\n\n        /**\n         * Overrides current data with a provided one.\n         *\n         * @param {Object} data - New data object.\n         * @returns {Provider} Chainable.\n         */\n        setData: function (data) {\n            data = this.processData(data);\n\n            this.set('data', data);\n\n            return this;\n        },\n\n        /**\n         * Processes data before applying it.\n         *\n         * @param {Object} data - Data to be processed.\n         * @returns {Object}\n         */\n        processData: function (data) {\n            var items = data.items;\n\n            _.each(items, function (record, index) {\n                record._rowIndex = index;\n            });\n\n            return data;\n        },\n\n        /**\n         * Reloads data with current parameters.\n         *\n         * @returns {Promise} Reload promise object.\n         */\n        reload: function (options) {\n            var request = this.storage().getData(this.params, options);\n\n            this.trigger('reload');\n\n            request\n                .done(this.onReload)\n                .fail(this.onError.bind(this));\n\n            return request;\n        },\n\n        /**\n         * Handles changes of 'params' object.\n         */\n        onParamsChange: function () {\n            // It's necessary to make a reload only\n            // after the initial loading has been made.\n            if (!this.firstLoad) {\n                this.reload();\n            } else {\n                this.triggerDataReload = true;\n            }\n        },\n\n        /**\n         * Handles reload error.\n         */\n        onError: function (xhr) {\n            if (xhr.statusText === 'abort') {\n                return;\n            }\n\n            this.set('lastError', true);\n\n            this.firstLoad = false;\n            this.triggerDataReload = false;\n\n            alert({\n                content: $t('Something went wrong.')\n            });\n        },\n\n        /**\n         * Handles successful data reload.\n         *\n         * @param {Object} data - Retrieved data object.\n         */\n        onReload: function (data) {\n            this.firstLoad = false;\n            this.set('lastError', false);\n            this.setData(data)\n                .trigger('reloaded');\n\n            if (this.triggerDataReload) {\n                this.triggerDataReload = false;\n                this.reload();\n            }\n        },\n\n        /**\n         * Updates storage's request configuration\n         *\n         * @param {Object} requestConfig\n         */\n        updateRequestConfig: function (requestConfig) {\n            registry.get(this.storageConfig.provider, function (storage) {\n                _.extend(storage.requestConfig, requestConfig);\n            });\n        }\n    });\n});\n","Magento_Ui/js/grid/toolbar.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'Magento_Ui/js/lib/view/utils/async',\n    'Magento_Ui/js/lib/view/utils/raf',\n    'rjsResolver',\n    'uiCollection'\n], function (_, $, raf, resolver, Collection) {\n    'use strict';\n\n    var transformProp;\n\n    /**\n     * Defines supported css 'transform' property.\n     *\n     * @returns {String|Undefined}\n     */\n    transformProp = (function () {\n        var style = document.documentElement.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    /**\n     * Moves specified DOM element to the x and y coordinates.\n     *\n     * @param {HTMLElement} elem - Element to be relocated.\n     * @param {Number} x - X coordinate.\n     * @param {Number} y - Y coordinate.\n     */\n    function locate(elem, x, y) {\n        var value = 'translate(' + x + 'px,' + y + 'px)';\n\n        elem.style[transformProp] = value;\n    }\n\n    return Collection.extend({\n        defaults: {\n            template: 'ui/grid/toolbar',\n            stickyTmpl: 'ui/grid/sticky/sticky',\n            tableSelector: 'table',\n            columnsProvider: 'ns = ${ $.ns }, componentType = columns',\n            refreshFPS: 15,\n            sticky: false,\n            visible: false,\n            _resized: true,\n            _scrolled: true,\n            _tableScrolled: true,\n            _requiredNodes: {\n                '$stickyToolbar': true,\n                '$stickyTable': true,\n                '$table': true,\n                '$sticky': true\n            },\n            stickyClass: {\n                'sticky-header': true\n            }\n        },\n\n        /**\n         * Initializes sticky toolbar component.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        initialize: function () {\n            this._super();\n\n            if (this.sticky) {\n                this.waitDOMElements()\n                    .then(this.run.bind(this));\n            }\n\n            return this;\n        },\n\n        /**\n         * Establishes DOM elements wait process.\n         *\n         * @returns {jQueryPromise} Promise which will be resolved\n         *      when all of the required DOM elements are defined.\n         */\n        waitDOMElements: function () {\n            var _domPromise = $.Deferred();\n\n            _.bindAll(this, 'setStickyTable', 'setTableNode');\n\n            $.async({\n                ctx: ':not([data-role=\"sticky-el-root\"])',\n                component: this.columnsProvider,\n                selector: this.tableSelector\n            }, this.setTableNode);\n\n            $.async({\n                ctx: '[data-role=\"sticky-el-root\"]',\n                component: this.columnsProvider,\n                selector: this.tableSelector\n            }, this.setStickyTable);\n\n            this._domPromise = _domPromise;\n\n            return _domPromise.promise();\n        },\n\n        /**\n         * Defines left caption element.\n         *\n         * @param {HTMLElement} node\n         */\n        setLeftCap: function (node) {\n            this.$leftCap = node;\n        },\n\n        /**\n         * Defines right caption element.\n         *\n         * @param {HTMLElement} node\n         */\n        setRightCap: function (node) {\n            this.$rightCap = node;\n        },\n\n        /**\n         * Defines original table element.\n         *\n         * @param {HTMLTableElement} node\n         */\n        setTableNode: function (node) {\n            this.$cols = node.tHead.children[0].cells;\n            this.$tableContainer = node.parentNode;\n\n            this.setNode('$table', node);\n        },\n\n        /**\n         * Defines sticky table element.\n         *\n         * @param {HTMLTableElement} node\n         */\n        setStickyTable: function (node) {\n            this.$stickyCols = node.tHead.children[0].cells;\n\n            this.setNode('$stickyTable', node);\n        },\n\n        /**\n         * Defines sticky toolbar node.\n         *\n         * @param {HTMLElement} node\n         */\n        setStickyToolbarNode: function (node) {\n            this.setNode('$stickyToolbar', node);\n        },\n\n        /**\n         * Defines sticky element container.\n         *\n         * @param {HTMLElement} node\n         */\n        setStickyNode: function (node) {\n            this.setNode('$sticky', node);\n        },\n\n        /**\n         * Defines toolbar element container.\n         *\n         * @param {HTMLElement} node\n         */\n        setToolbarNode: function (node) {\n            this.$toolbar = node;\n        },\n\n        /**\n         * Sets provided node as a value of 'key' property and\n         * performs check for required DOM elements.\n         *\n         * @param {String} key - Properties key.\n         * @param {HTMLElement} node - DOM element.\n         */\n        setNode: function (key, node) {\n            var nodes = this._requiredNodes,\n                promise = this._domPromise,\n                defined;\n\n            this[key] = node;\n\n            defined = _.every(nodes, function (enabled, name) {\n                return enabled ? this[name] : true;\n            }, this);\n\n            if (defined) {\n                resolver(promise.resolve, promise);\n            }\n        },\n\n        /**\n         * Starts refresh process of the sticky element\n         * and assigns DOM elements events handlers.\n         */\n        run: function () {\n            _.bindAll(\n                this,\n                'refresh',\n                '_onWindowResize',\n                '_onWindowScroll',\n                '_onTableScroll'\n            );\n\n            $(window).on({\n                scroll: this._onWindowScroll,\n                resize: this._onWindowResize\n            });\n\n            $(this.$tableContainer).on('scroll', this._onTableScroll);\n\n            this.refresh();\n            this.checkTableWidth();\n        },\n\n        /**\n         * Refreshes state of the sticky element and\n         * invokes DOM elements events handlers\n         * if corresponding event has been triggered.\n         */\n        refresh: function () {\n            if (!raf(this.refresh, this.refreshFPS)) {\n                return;\n            }\n\n            if (this._scrolled) {\n                this.onWindowScroll();\n            }\n\n            if (this._tableScrolled) {\n                this.onTableScroll();\n            }\n\n            if (this._resized) {\n                this.onWindowResize();\n            }\n\n            if (this.visible) {\n                this.checkTableWidth();\n            }\n        },\n\n        /**\n         * Shows sticky toolbar.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        show: function () {\n            this.visible = true;\n            //Check admin grid button has addedr not\n            if ($('.page-main-actions').length === 0) {\n                this.$sticky.style.top = 0;\n            }\n            this.$sticky.style.display = '';\n            this.$toolbar.style.visibility = 'hidden';\n\n            return this;\n        },\n\n        /**\n         * Hides sticky toolbar.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        hide: function () {\n            this.visible = false;\n\n            this.$sticky.style.display = 'none';\n            this.$toolbar.style.visibility = '';\n\n            return this;\n        },\n\n        /**\n         * Checks if sticky toolbar covers original elements.\n         *\n         * @returns {Boolean}\n         */\n        isCovered: function () {\n            var stickyTop = this._stickyTableTop + this._wScrollTop;\n\n            return stickyTop > this._tableTop;\n        },\n\n        /**\n         * Updates offset of the sticky table element.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        updateStickyTableOffset: function () {\n            var style,\n                top;\n\n            if (this.visible) {\n                top = this.$stickyTable.getBoundingClientRect().top;\n            } else {\n                style = this.$sticky.style;\n\n                style.visibility = 'hidden';\n                style.display = '';\n\n                top = this.$stickyTable.getBoundingClientRect().top;\n\n                style.display = 'none';\n                style.visibility = '';\n            }\n\n            this._stickyTableTop = top;\n\n            return this;\n        },\n\n        /**\n         * Updates offset of the original table element.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        updateTableOffset: function () {\n            var box = this.$table.getBoundingClientRect(),\n                top = box.top + this._wScrollTop;\n\n            if (this._tableTop !== top) {\n                this._tableTop = top;\n\n                this.onTableTopChange(top);\n            }\n\n            return this;\n        },\n\n        /**\n         * Checks if width of the table or it's columns has changed.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        checkTableWidth: function () {\n            var cols        = this.$cols,\n                total       = cols.length,\n                rightBorder = cols[total - 2].offsetLeft,\n                tableWidth  = this.$table.offsetWidth;\n\n            if (this._tableWidth !== tableWidth) {\n                this._tableWidth = tableWidth;\n\n                this.onTableWidthChange(tableWidth);\n            }\n\n            if (this._rightBorder !== rightBorder) {\n                this._rightBorder = rightBorder;\n\n                this.onColumnsWidthChange();\n            }\n\n            return this;\n        },\n\n        /**\n         * Updates width of the sticky table.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        updateTableWidth: function () {\n            this.$stickyTable.style.width = this._tableWidth + 'px';\n\n            if (this._tableWidth < this._toolbarWidth) {\n                this.checkToolbarSize();\n            }\n\n            return this;\n        },\n\n        /**\n         * Updates width of the sticky columns.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        updateColumnsWidth: function () {\n            var cols        = this.$cols,\n                index       = cols.length,\n                stickyCols  = this.$stickyCols;\n\n            while (index--) {\n                stickyCols[index].width = cols[index].offsetWidth;\n            }\n\n            return this;\n        },\n\n        /**\n         * Upadates size of the sticky toolbar element\n         * and invokes corresponding 'change' event handlers.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        checkToolbarSize: function () {\n            var width = this.$tableContainer.offsetWidth;\n\n            if (this._toolbarWidth !== width) {\n                this._toolbarWidth = width;\n\n                this.onToolbarWidthChange(width);\n            }\n\n            return this;\n        },\n\n        /**\n         * Toggles sticky toolbar visibility if it's necessary.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        updateVisibility: function () {\n            if (this.visible !== this.isCovered()) {\n                this.visible ? this.hide() : this.show();\n            }\n\n            return this;\n        },\n\n        /**\n         * Updates position of the left cover area.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        updateLeftCap: function () {\n            locate(this.$leftCap, -this._wScrollLeft, 0);\n\n            return this;\n        },\n\n        /**\n         * Updates position of the right cover area.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        updateRightCap: function () {\n            var left = this._toolbarWidth - this._wScrollLeft;\n\n            locate(this.$rightCap, left, 0);\n\n            return this;\n        },\n\n        /**\n         * Updates position of the sticky table.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        updateTableScroll: function () {\n            var container = this.$tableContainer,\n                left = container.scrollLeft + this._wScrollLeft;\n\n            locate(this.$stickyTable, -left, 0);\n\n            return this;\n        },\n\n        /**\n         * Updates width of the toolbar element.\n         *\n         * @returns {Sticky} Chainable.\n         */\n        updateToolbarWidth: function () {\n            this.$stickyToolbar.style.width = this._toolbarWidth + 'px';\n\n            return this;\n        },\n\n        /**\n         * Handles changes of the toolbar element's width.\n         */\n        onToolbarWidthChange: function () {\n            this.updateToolbarWidth()\n                .updateRightCap();\n        },\n\n        /**\n         * Handles changes of the table top position.\n         */\n        onTableTopChange: function () {\n            this.updateStickyTableOffset();\n        },\n\n        /**\n         * Handles change of the table width.\n         */\n        onTableWidthChange: function () {\n            this.updateTableWidth();\n        },\n\n        /**\n         * Handles change of the table columns width.\n         */\n        onColumnsWidthChange: function () {\n            this.updateColumnsWidth();\n        },\n\n        /**\n         * Handles changes of the window's size.\n         */\n        onWindowResize: function () {\n            this.checkToolbarSize();\n\n            this._resized = false;\n        },\n\n        /**\n         * Handles changes of the original table scroll position.\n         */\n        onTableScroll: function () {\n            this.updateTableScroll();\n\n            this._tableScrolled = false;\n        },\n\n        /**\n         * Handles changes of window's scroll position.\n         */\n        onWindowScroll: function () {\n            var scrollTop = window.pageYOffset,\n                scrollLeft = window.pageXOffset;\n\n            if (this._wScrollTop !== scrollTop) {\n                this._wScrollTop = scrollTop;\n\n                this.onWindowScrollTop(scrollTop);\n            }\n\n            if (this._wScrollLeft !== scrollLeft) {\n                this._wScrollLeft = scrollLeft;\n\n                this.onWindowScrollLeft(scrollLeft);\n            }\n\n            this._scrolled = false;\n        },\n\n        /**\n         * Handles changes of windows' top scroll position.\n         */\n        onWindowScrollTop: function () {\n            this.updateTableOffset()\n                .updateVisibility();\n        },\n\n        /**\n         * Handles changes of windows' left scroll position.\n         */\n        onWindowScrollLeft: function () {\n            this.updateRightCap()\n                .updateLeftCap()\n                .updateTableScroll();\n        },\n\n        /**\n         * Original window 'scroll' event handler.\n         * Sets 'scrolled' flag to 'true'.\n         *\n         * @private\n         */\n        _onWindowScroll: function () {\n            this._scrolled = true;\n        },\n\n        /**\n         * Original window 'resize' event handler.\n         * Sets 'resized' flag to 'true'.\n         *\n         * @private\n         */\n        _onWindowResize: function () {\n            this._resized = true;\n        },\n\n        /**\n         * Original table 'scroll' event handler.\n         * Sets '_tableScrolled' flag to 'true'.\n         *\n         * @private\n         */\n        _onTableScroll: function () {\n            this._tableScrolled = true;\n        }\n    });\n});\n","Magento_Ui/js/grid/tree-massactions.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    'Magento_Ui/js/grid/massactions'\n], function (ko, _, Massactions) {\n    'use strict';\n\n    return Massactions.extend({\n        defaults: {\n            template: 'ui/grid/tree-massactions',\n            submenuTemplate: 'ui/grid/submenu',\n            listens: {\n                opened: 'hideSubmenus'\n            }\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Massactions} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .recursiveObserveActions(this.actions());\n\n            return this;\n        },\n\n        /**\n         * Recursive initializes observable actions.\n         *\n         * @param {Array} actions - Action objects.\n         * @param {String} [prefix] - An optional string that will be prepended\n         *      to the \"type\" field of all child actions.\n         * @returns {Massactions} Chainable.\n         */\n        recursiveObserveActions: function (actions, prefix) {\n            _.each(actions, function (action) {\n                if (prefix) {\n                    action.type = prefix + '.' + action.type;\n                }\n\n                if (action.actions) {\n                    action.visible = ko.observable(false);\n                    action.parent = actions;\n                    this.recursiveObserveActions(action.actions, action.type);\n                }\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Applies specified action.\n         *\n         * @param {String} actionIndex - Actions' identifier.\n         * @returns {Massactions} Chainable.\n         */\n        applyAction: function (actionIndex) {\n            var action = this.getAction(actionIndex),\n                visibility;\n\n            if (action.visible) {\n                visibility = action.visible();\n\n                this.hideSubmenus(action.parent);\n                action.visible(!visibility);\n\n                return this;\n            }\n\n            return this._super(actionIndex);\n        },\n\n        /**\n         * Retrieves action object associated with a specified index.\n         *\n         * @param {String} actionIndex - Actions' identifier.\n         * @param {Array} actions - Action objects.\n         * @returns {Object} Action object.\n         */\n        getAction: function (actionIndex, actions) {\n            var currentActions = actions || this.actions(),\n                result = false;\n\n            _.find(currentActions, function (action) {\n                if (action.type === actionIndex) {\n                    result = action;\n\n                    return true;\n                }\n\n                if (action.actions) {\n                    result = this.getAction(actionIndex, action.actions);\n\n                    return result;\n                }\n            }, this);\n\n            return result;\n        },\n\n        /**\n         * Recursive hide all sub folders in given array.\n         *\n         * @param {Array} actions - Action objects.\n         * @returns {Massactions} Chainable.\n         */\n        hideSubmenus: function (actions) {\n            var currentActions = actions || this.actions();\n\n            _.each(currentActions, function (action) {\n                if (action.visible && action.visible()) {\n                    action.visible(false);\n                }\n\n                if (action.actions) {\n                    this.hideSubmenus(action.actions);\n                }\n            }, this);\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/grid/editing/record.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    'uiLayout',\n    'uiCollection'\n], function (_, utils, layout, Collection) {\n    'use strict';\n\n    return Collection.extend({\n        defaults: {\n            active: true,\n            hasChanges: false,\n            fields: [],\n            errorsCount: 0,\n            fieldTmpl: 'ui/grid/editing/field',\n            rowTmpl: 'ui/grid/editing/row',\n            templates: {\n                fields: {\n                    base: {\n                        parent: '${ $.$data.record.name }',\n                        name: '${ $.$data.column.index }',\n                        provider: '${ $.$data.record.name }',\n                        dataScope: 'data.${ $.$data.column.index }',\n                        imports: {\n                            disabled: '${ $.$data.record.parentName }:fields.${ $.$data.column.index }.disabled'\n                        },\n                        isEditor: true\n                    },\n                    text: {\n                        component: 'Magento_Ui/js/form/element/abstract',\n                        template: 'ui/form/element/input'\n                    },\n                    date: {\n                        component: 'Magento_Ui/js/form/element/date',\n                        template: 'ui/form/element/date',\n                        dateFormat: 'MMM d, y h:mm:ss a'\n                    },\n                    select: {\n                        component: 'Magento_Ui/js/form/element/select',\n                        template: 'ui/form/element/select',\n                        options: '${ JSON.stringify($.$data.column.options) }'\n                    }\n                }\n            },\n            ignoreTmpls: {\n                data: true\n            },\n            listens: {\n                elems: 'updateFields',\n                data: 'updateState'\n            },\n            imports: {\n                onColumnsUpdate: '${ $.columnsProvider }:elems'\n            },\n            modules: {\n                columns: '${ $.columnsProvider }',\n                editor: '${ $.editorProvider }'\n            }\n        },\n\n        /**\n         * Initializes record component.\n         *\n         * @returns {Record} Chainable.\n         */\n        initialize: function () {\n            _.bindAll(this, 'countErrors');\n            utils.limit(this, 'updateState', 10);\n\n            return this._super();\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Record} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track('errorsCount hasChanges')\n                .observe('active fields');\n\n            return this;\n        },\n\n        /**\n         * Adds listeners on a field.\n         *\n         * @returns {Record} Chainable.\n         */\n        initElement: function (field) {\n            field.on('error', this.countErrors);\n\n            return this._super();\n        },\n\n        /**\n         * Creates new instance of a field.\n         *\n         * @param {Column} column - Column instance which contains field definition.\n         * @returns {Record} Chainable.\n         */\n        initField: function (column) {\n            var field = this.buildField(column);\n\n            layout([field]);\n\n            return this;\n        },\n\n        /**\n         * Builds fields' configuration described in a provided column.\n         *\n         * @param {Column} column - Column instance which contains field definition.\n         * @returns {Object} Complete fields' configuration.\n         */\n        buildField: function (column) {\n            var fields = this.templates.fields,\n                field  = column.editor;\n\n            if (_.isObject(field) && field.editorType) {\n                field = utils.extend({}, fields[field.editorType], field);\n            } else if (_.isString(field)) {\n                field = fields[field];\n            }\n\n            field = utils.extend({}, fields.base, field);\n\n            return utils.template(field, {\n                record: this,\n                column: column\n            }, true, true);\n        },\n\n        /**\n         * Creates fields for the specified columns.\n         *\n         * @param {Array} columns - An array of column instances.\n         * @returns {Record} Chainable.\n         */\n        createFields: function (columns) {\n            columns.forEach(function (column) {\n                if (column.editor && !this.hasChild(column.index)) {\n                    this.initField(column);\n                }\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Returns instance of a column found by provided index.\n         *\n         * @param {String} index - Index of a column (e.g. 'title').\n         * @returns {Column}\n         */\n        getColumn: function (index) {\n            return this.columns().getChild(index);\n        },\n\n        /**\n         * Returns records' current data object.\n         *\n         * @returns {Object}\n         */\n        getData: function () {\n            return this.filterData(this.data);\n        },\n\n        /**\n         * Returns saved records' data. Data will be processed\n         * with a 'filterData' and 'normalizeData' methods.\n         *\n         * @returns {Object} Saved records' data.\n         */\n        getSavedData: function () {\n            var editor      = this.editor(),\n                savedData   = editor.getRowData(this.index);\n\n            savedData = this.filterData(savedData);\n\n            return this.normalizeData(savedData);\n        },\n\n        /**\n         * Replaces current records' data with the provided one.\n         *\n         * @param {Object} data - New records data.\n         * @param {Boolean} [partial=false] - Flag that defines whether\n         *      to completely replace current data or to extend it.\n         * @returns {Record} Chainable.\n         */\n        setData: function (data, partial) {\n            var currentData = partial ? this.data : {};\n\n            data = this.normalizeData(data);\n            data = utils.extend({}, currentData, data);\n\n            this.set('data', data)\n                .updateState();\n\n            return this;\n        },\n\n        /**\n         * Filters provided object extracting from it values\n         * that can be matched with an existing fields.\n         *\n         * @param {Object} data - Object to be processed.\n         * @returns {Object}\n         */\n        filterData: function (data) {\n            var fields = _.pluck(this.elems(), 'index');\n\n            _.each(this.preserveFields, function (enabled, field) {\n                if (enabled && !_.contains(fields, field)) {\n                    fields.push(field);\n                }\n            });\n\n            return _.pick(data, fields);\n        },\n\n        /**\n         * Parses values of a provided object with\n         * a 'normalizeData' method of a corresponding field.\n         *\n         * @param {Object} data - Data to be processed.\n         * @returns {Object}\n         */\n        normalizeData: function (data) {\n            var index;\n\n            this.elems.each(function (elem) {\n                index = elem.index;\n\n                if (data.hasOwnProperty(index)) {\n                    data[index] = elem.normalizeData(data[index]);\n                }\n            });\n\n            return data;\n        },\n\n        /**\n         * Clears values of all fields.\n         *\n         * @returns {Record} Chainable.\n         */\n        clear: function () {\n            this.elems.each('clear');\n\n            return this;\n        },\n\n        /**\n         * Validates all of the available fields.\n         *\n         * @returns {Array} An array with validation results.\n         */\n        validate: function () {\n            return this.elems.map('validate');\n        },\n\n        /**\n         * Checks if all fields are valid.\n         *\n         * @returns {Boolean}\n         */\n        isValid: function () {\n            return _.every(this.validate(), 'valid');\n        },\n\n        /**\n         * Counts total errors amount across all fields.\n         *\n         * @returns {Number}\n         */\n        countErrors: function () {\n            var errorsCount = this.elems.filter('error').length;\n\n            this.errorsCount = errorsCount;\n\n            return errorsCount;\n        },\n\n        /**\n         * Returns difference between current data and its'\n         * initial state, retrieved from the records collection.\n         *\n         * @returns {Object} Object with changes descriptions.\n         */\n        checkChanges: function () {\n            var savedData   = this.getSavedData(),\n                data        = this.normalizeData(this.getData());\n\n            return utils.compare(savedData, data);\n        },\n\n        /**\n         * Updates 'fields' array filling it with available editors\n         * or with column instances if associated field is not present.\n         *\n         * @returns {Record} Chainable.\n         */\n        updateFields: function () {\n            var fields;\n\n            fields = this.columns().elems.map(function (column) {\n                return this.getChild(column.index) || column;\n            }, this);\n\n            this.fields(fields);\n\n            return this;\n        },\n\n        /**\n         * Updates state of a 'hasChanges' property.\n         *\n         * @returns {Record} Chainable.\n         */\n        updateState: function () {\n            var diff = this.checkChanges(),\n                changed = {};\n\n            this.hasChanges = !diff.equal;\n            changed[this.index] = this.data;\n            this.editor().set('changed', [changed]);\n\n            return this;\n        },\n\n        /**\n         * Checks if provided column is an actions column.\n         *\n         * @param {Column} column - Column to be checked.\n         * @returns {Boolean}\n         */\n        isActionsColumn: function (column) {\n            return column.dataType === 'actions';\n        },\n\n        /**\n         * Listener of columns provider child array changes.\n         *\n         * @param {Array} columns - Modified child elements array.\n         */\n        onColumnsUpdate: function (columns) {\n            this.createFields(columns)\n                .updateFields();\n        }\n    });\n});\n","Magento_Ui/js/grid/editing/client.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    'mageUtils',\n    'uiClass'\n], function ($, _, utils, Class) {\n    'use strict';\n\n    return Class.extend({\n        defaults: {\n            validateBeforeSave: true,\n            requestConfig: {\n                dataType: 'json',\n                type: 'POST'\n            }\n        },\n\n        /**\n         * Initializes client instance.\n         *\n         * @returns {Client} Chainable.\n         */\n        initialize: function () {\n            _.bindAll(this, 'onSuccess', 'onError');\n\n            return this._super();\n        },\n\n        /**\n         * Sends XMLHttpRequest with a provided configuration.\n         *\n         * @param {Object} config - Configuration of request.\n         * @returns {jQueryPromise}\n         */\n        send: function (config) {\n            var deffer  = $.Deferred();\n\n            config = utils.extend({}, this.requestConfig, config);\n\n            $.ajax(config)\n                .done(_.partial(this.onSuccess, deffer))\n                .fail(_.partial(this.onError, deffer));\n\n            return deffer.promise();\n        },\n\n        /**\n         * Proxy save method which might invoke\n         * data validation prior to its' saving.\n         *\n         * @param {Object} data - Data to be processed.\n         * @returns {jQueryPromise}\n         */\n        save: function (data) {\n            var save = this._save.bind(this, data);\n\n            return this.validateBeforeSave ?\n                this.validate(data).pipe(save) :\n                save();\n        },\n\n        /**\n         * Sends request to validate provided data.\n         *\n         * @param {Object} data - Data to be validated.\n         * @returns {jQueryPromise}\n         */\n        validate: function (data) {\n            return this.send({\n                url: this.validateUrl,\n                data: data\n            });\n        },\n\n        /**\n         * Sends request to save provided data.\n         *\n         * @private\n         * @param {Object} data - Data to be validated.\n         * @returns {jQueryPromise}\n         */\n        _save: function (data) {\n            return this.send({\n                url: this.saveUrl,\n                data: data\n            });\n        },\n\n        /**\n         * Creates error object with a provided message.\n         *\n         * @param {String} msg - Errors' message.\n         * @returns {Object}\n         */\n        createError: function (msg) {\n            return {\n                type: 'error',\n                message: msg\n            };\n        },\n\n        /**\n         * Handles ajax error callback.\n         *\n         * @param {jQueryPromise} promise - Promise to be rejected.\n         * @param {jQueryXHR} xhr - See 'jquery' ajax error callback.\n         * @param {String} status - See 'jquery' ajax error callback.\n         * @param {(String|Object)} err - See 'jquery' ajax error callback.\n         */\n        onError: function (promise, xhr, status, err) {\n            var msg;\n\n            msg = xhr.status !== 200 ?\n                xhr.status + ' (' + xhr.statusText + ')' :\n                err;\n\n            promise.reject(this.createError(msg));\n        },\n\n        /**\n         * Handles ajax success callback.\n         *\n         * @param {jQueryPromise} promise - Promise to be resolved.\n         * @param {*} data - See 'jquery' ajax success callback.\n         */\n        onSuccess: function (promise, data) {\n            var errors;\n\n            if (data.error) {\n                errors = _.map(data.messages, this.createError, this);\n\n                promise.reject(errors);\n            } else {\n                promise.resolve(data);\n            }\n        }\n    });\n});\n","Magento_Ui/js/grid/editing/editor-view.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    'Magento_Ui/js/lib/view/utils/async',\n    'underscore',\n    'uiRegistry',\n    'uiClass'\n], function (ko, $, _, registry, Class) {\n    'use strict';\n\n    return Class.extend({\n        defaults: {\n            rootSelector: '${ $.columnsProvider }:.admin__data-grid-wrap',\n            tableSelector: '${ $.rootSelector } -> table',\n            rowSelector: '${ $.tableSelector } tbody tr.data-row',\n            headerButtonsTmpl:\n                '<!-- ko template: headerButtonsTmpl --><!-- /ko -->',\n            bulkTmpl:\n                '<!-- ko scope: bulk -->' +\n                    '<!-- ko template: getTemplate() --><!-- /ko -->' +\n                '<!-- /ko -->',\n            rowTmpl:\n                '<!-- ko with: _editor -->' +\n                    '<!-- ko if: isActive($row()._rowIndex, true) -->' +\n                        '<!-- ko with: getRecord($row()._rowIndex, true) -->' +\n                            '<!-- ko template: rowTmpl --><!-- /ko -->' +\n                        '<!-- /ko -->' +\n                        '<!-- ko if: isSingleEditing && singleEditingButtons -->' +\n                            '<!-- ko template: rowButtonsTmpl --><!-- /ko -->' +\n                        '<!-- /ko -->' +\n                    '<!-- /ko -->' +\n               '<!-- /ko -->'\n        },\n\n        /**\n         * Initializes view component.\n         *\n         * @returns {View} Chainable.\n         */\n        initialize: function () {\n            _.bindAll(\n                this,\n                'initRoot',\n                'initTable',\n                'initRow',\n                'rowBindings',\n                'tableBindings'\n            );\n\n            this._super();\n\n            this.model = registry.get(this.model);\n\n            $.async(this.rootSelector, this.initRoot);\n            $.async(this.tableSelector, this.initTable);\n            $.async(this.rowSelector, this.initRow);\n\n            return this;\n        },\n\n        /**\n         * Initializes columns root container.\n         *\n         * @param {HTMLElement} node\n         * @returns {View} Chainable.\n         */\n        initRoot: function (node) {\n            $(this.headerButtonsTmpl)\n                .insertBefore(node)\n                .applyBindings(this.model);\n\n            return this;\n        },\n\n        /**\n         * Initializes table element.\n         *\n         * @param {HTMLTableElement} table\n         * @returns {View} Chainable.\n         */\n        initTable: function (table) {\n            $(table).bindings(this.tableBindings);\n\n            this.initBulk(table);\n\n            return this;\n        },\n\n        /**\n         * Initializes bulk editor element\n         * for the provided table.\n         *\n         * @param {HTMLTableElement} table\n         * @returns {View} Chainable.\n         */\n        initBulk: function (table) {\n            var tableBody = $('tbody', table)[0];\n\n            $(this.bulkTmpl)\n                .prependTo(tableBody)\n                .applyBindings(this.model);\n\n            return this;\n        },\n\n        /**\n         * Initializes table row.\n         *\n         * @param {HTMLTableRowElement} row\n         * @returns {View} Chainable.\n         */\n        initRow: function (row) {\n            var $editingRow;\n\n            $(row).extendCtx({\n                    _editor: this.model\n                }).bindings(this.rowBindings);\n\n            $editingRow = $(this.rowTmpl)\n                .insertBefore(row)\n                .applyBindings(row);\n\n            ko.utils.domNodeDisposal.addDisposeCallback(row, this.removeEditingRow.bind(this, $editingRow));\n\n            return this;\n        },\n\n        /**\n         * Returns row bindings.\n         *\n         * @param {Object} ctx - Current context of a row.\n         * @returns {Object}\n         */\n        rowBindings: function (ctx) {\n            var model = this.model;\n\n            return {\n                visible: ko.computed(function () {\n                    var record = ctx.$row(),\n                        index = record && record._rowIndex;\n\n                    return !model.isActive(index, true);\n                })\n            };\n        },\n\n        /**\n         * Returns table bindings.\n         *\n         * @returns {Object}\n         */\n        tableBindings: function () {\n            var model = this.model;\n\n            return {\n                css: {\n                    '_in-edit': ko.computed(function () {\n                        return model.hasActive() && !model.permanentlyActive;\n                    })\n                }\n            };\n        },\n\n        /**\n         * Removes specified array of nodes.\n         *\n         * @param {ArrayLike} row\n         */\n        removeEditingRow: function (row) {\n            _.toArray(row).forEach(ko.removeNode);\n        }\n    });\n});\n","Magento_Ui/js/grid/editing/editor.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    'uiLayout',\n    'mage/translate',\n    'uiCollection'\n], function (_, utils, layout, $t, Collection) {\n    'use strict';\n\n    return Collection.extend({\n        defaults: {\n            rowButtonsTmpl: 'ui/grid/editing/row-buttons',\n            headerButtonsTmpl: 'ui/grid/editing/header-buttons',\n            successMsg: $t('You have successfully saved your edits.'),\n            errorsCount: 0,\n            bulkEnabled: true,\n            multiEditingButtons: true,\n            singleEditingButtons: true,\n            isMultiEditing: false,\n            isSingleEditing: false,\n            permanentlyActive: false,\n            rowsData: [],\n            fields: {},\n\n            templates: {\n                record: {\n                    parent: '${ $.$data.editor.name }',\n                    name: '${ $.$data.recordId }',\n                    component: 'Magento_Ui/js/grid/editing/record',\n                    columnsProvider: '${ $.$data.editor.columnsProvider }',\n                    editorProvider: '${ $.$data.editor.name }',\n                    preserveFields: {\n                        '${ $.$data.editor.indexField }': true\n                    }\n                }\n            },\n            bulkConfig: {\n                component: 'Magento_Ui/js/grid/editing/bulk',\n                name: '${ $.name }_bulk',\n                editorProvider: '${ $.name }',\n                columnsProvider: '${ $.columnsProvider }'\n            },\n            clientConfig: {\n                component: 'Magento_Ui/js/grid/editing/client',\n                name: '${ $.name }_client'\n            },\n            viewConfig: {\n                component: 'Magento_Ui/js/grid/editing/editor-view',\n                name: '${ $.name }_view',\n                model: '${ $.name }',\n                columnsProvider: '${ $.columnsProvider }'\n            },\n            imports: {\n                rowsData: '${ $.dataProvider }:data.items'\n            },\n            listens: {\n                '${ $.dataProvider }:reloaded': 'cancel',\n                '${ $.selectProvider }:selected': 'onSelectionsChange'\n            },\n            modules: {\n                source: '${ $.dataProvider }',\n                client: '${ $.clientConfig.name }',\n                columns: '${ $.columnsProvider }',\n                bulk: '${ $.bulkConfig.name }',\n                selections: '${ $.selectProvider }'\n            }\n        },\n\n        /**\n         * Initializes editor component.\n         *\n         * @returns {Editor} Chainable.\n         */\n        initialize: function () {\n            _.bindAll(this, 'updateState', 'countErrors', 'onDataSaved', 'onSaveError');\n\n            this._super()\n                .initBulk()\n                .initClient()\n                .initView();\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Editor} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track([\n                    'errorsCount',\n                    'isMultiEditing',\n                    'isSingleEditing',\n                    'isSingleColumnEditing',\n                    'changed'\n                ])\n                .observe({\n                    canSave: true,\n                    activeRecords: [],\n                    messages: []\n                });\n\n            return this;\n        },\n\n        /**\n         * Initializes bulk editing component.\n         *\n         * @returns {Editor} Chainable.\n         */\n        initBulk: function () {\n            if (this.bulkEnabled) {\n                layout([this.bulkConfig]);\n            }\n\n            return this;\n        },\n\n        /**\n         * Initializes editors' view component.\n         *\n         * @returns {Editor} Chainable.\n         */\n        initView: function () {\n            layout([this.viewConfig]);\n\n            return this;\n        },\n\n        /**\n         * Initializes client component.\n         *\n         * @returns {Editor} Chainable.\n         */\n        initClient: function () {\n            layout([this.clientConfig]);\n\n            return this;\n        },\n\n        /**\n         * Creates instance of a new record.\n         *\n         * @param {(Number|String)} id - See 'getId' method.\n         * @param {Boolean} [isIndex=false] - See 'getId' method.\n         * @returns {Editor} Chainable.\n         */\n        initRecord: function (id, isIndex) {\n            var record = this.buildRecord(id, isIndex);\n\n            layout([record]);\n\n            return this;\n        },\n\n        /**\n         * Adds listeners on a new record.\n         *\n         * @param {Record} record\n         * @returns {Editor} Chainable.\n         */\n        initElement: function (record) {\n            record.on({\n                'active': this.updateState,\n                'errorsCount': this.countErrors\n            });\n\n            this.updateState();\n\n            return this._super();\n        },\n\n        /**\n         * Creates configuration for a new record associated with a row data.\n         *\n         * @param {(Number|String)} id - See 'getId' method.\n         * @param {Boolean} [isIndex=false] - See 'getId' method.\n         * @returns {Object} Record configuration.\n         */\n        buildRecord: function (id, isIndex) {\n            var recordId = this.getId(id, isIndex),\n                recordTmpl = this.templates.record,\n                record;\n\n            if (this.getRecord(recordId)) {\n                return this;\n            }\n\n            record = utils.template(recordTmpl, {\n                editor: this,\n                recordId: id\n            });\n\n            record.recordId = id;\n            record.data     = this.getRowData(id);\n\n            return record;\n        },\n\n        /**\n         * Starts editing of a specified record. If records'\n         * instance doesn't exist, than it will be created.\n         *\n         * @param {(Number|String)} id - See 'getId' method.\n         * @param {Boolean} [isIndex=false] - See 'getId' method.\n         * @returns {Editor} Chainable.\n         */\n        edit: function (id, isIndex) {\n            var recordId = this.getId(id, isIndex),\n                record   = this.getRecord(recordId);\n\n            record ?\n                record.active(true) :\n                this.initRecord(recordId);\n\n            return this;\n        },\n\n        /**\n         * Drops list of selections while activating only the specified record.\n         *\n         * @param {(Number|String)} id - See 'getId' method.\n         * @param {Boolean} [isIndex=false] - See 'getId' method.\n         * @returns {Editor} Chainable.\n         */\n        startEdit: function (id, isIndex) {\n            var recordId = this.getId(id, isIndex);\n\n            this.selections()\n                .deselectAll()\n                .select(recordId);\n\n            return this.edit(recordId);\n        },\n\n        /**\n         * Hides records and resets theirs data.\n         *\n         * @returns {Editor} Chainable.\n         */\n        cancel: function () {\n            this.reset()\n                .hide()\n                .clearMessages()\n                .bulk('clear');\n\n            return this;\n        },\n\n        /**\n         * Hides records.\n         *\n         * @returns {Editor} Chainable.\n         */\n        hide: function () {\n            this.activeRecords.each('active', false);\n\n            return this;\n        },\n\n        /**\n         * Resets active records.\n         *\n         * @returns {Editor} Chainable.\n         */\n        reset: function () {\n            this.elems.each(function (record) {\n                this.resetRecord(record.recordId);\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Validates and saves data of active records.\n         *\n         * @returns {Editor} Chainable.\n         */\n        save: function () {\n            var data;\n\n            if (!this.isValid()) {\n                return this;\n            }\n\n            data = {\n                items: this.getData()\n            };\n\n            this.clearMessages()\n                .columns('showLoader');\n\n            this.client()\n                .save(data)\n                .done(this.onDataSaved)\n                .fail(this.onSaveError);\n\n            return this;\n        },\n\n        /**\n         * Validates all active records.\n         *\n         * @returns {Array} An array of records and theirs validation results.\n         */\n        validate: function () {\n            return this.activeRecords.map(function (record) {\n                return {\n                    target: record,\n                    valid: record.isValid()\n                };\n            });\n        },\n\n        /**\n         * Checks if all active records are valid.\n         *\n         * @returns {Boolean}\n         */\n        isValid: function () {\n            return _.every(this.validate(), 'valid');\n        },\n\n        /**\n         * Returns active records data, indexed by a theirs ids.\n         *\n         * @returns {Object} Collection of records data.\n         */\n        getData: function () {\n            var data = this.activeRecords.map(function (record) {\n                var elemKey,\n                    recordData = record.getData();\n\n                for (elemKey in recordData) {\n                    if (_.isUndefined(recordData[elemKey])) {\n                        recordData[elemKey] = null;\n                    }\n                }\n\n                return recordData;\n            });\n\n            return _.indexBy(data, this.indexField);\n        },\n\n        /**\n         * Sets provided data to all active records.\n         *\n         * @param {Object} data - See 'setData' method of a 'Record'.\n         * @param {Boolean} partial - See 'setData' method of a 'Record'.\n         * @returns {Editor} Chainable.\n         */\n        setData: function (data, partial) {\n            this.activeRecords.each('setData', data, partial);\n\n            return this;\n        },\n\n        /**\n         * Resets specific records' data\n         * to the data present in associated row.\n         *\n         * @param {(Number|String)} id - See 'getId' method.\n         * @param {Boolean} [isIndex=false] - See 'getId' method.\n         * @returns {Editor} Chainable.\n         */\n        resetRecord: function (id, isIndex) {\n            var record  = this.getRecord(id, isIndex),\n                data    = this.getRowData(id, isIndex);\n\n            if (record && data) {\n                record.setData(data);\n            }\n\n            return this;\n        },\n\n        /**\n         * Returns instance of a specified record.\n         *\n         * @param {(Number|String)} id - See 'getId' method.\n         * @param {Boolean} [isIndex=false] - See 'getId' method.\n         * @returns {Record}\n         */\n        getRecord: function (id, isIndex) {\n            return this.elems.findWhere({\n                recordId: this.getId(id, isIndex)\n            });\n        },\n\n        /**\n         * Creates record name based on a provided id.\n         *\n         * @param {(Number|String)} id - See 'getId' method.\n         * @param {Boolean} [isIndex=false] - See 'getId' method.\n         * @returns {String}\n         */\n        formRecordName: function (id, isIndex) {\n            id = this.getId(id, isIndex);\n\n            return this.name + '.' + id;\n        },\n\n        /**\n         * Disables editing of specified fields.\n         *\n         * @param {Array} fields - An array of fields indexes to be disabled.\n         * @returns {Editor} Chainable.\n         */\n        disableFields: function (fields) {\n            var columns = this.columns().elems(),\n                data    = utils.copy(this.fields);\n\n            columns.forEach(function (column) {\n                var index = column.index,\n                    field = data[index] = data[index] || {};\n\n                field.disabled = _.contains(fields, index);\n            });\n\n            this.set('fields', data);\n\n            return this;\n        },\n\n        /**\n         * Converts index of a row into the record id.\n         *\n         * @param {(Number|String)} id - Records' identifier or its' index in the rows array.\n         * @param {Boolean} [isIndex=false] - Flag that indicates if first\n         *      parameter is an index or identifier.\n         * @returns {String} Records' id.\n         */\n        getId: function (id, isIndex) {\n            var rowsData = this.rowsData,\n                record;\n\n            if (isIndex === true) {\n                record  = rowsData[id];\n                id      = record ? record[this.indexField] : false;\n            }\n\n            return id;\n        },\n\n        /**\n         * Returns data of a specified row.\n         *\n         * @param {(Number|String)} id - See 'getId' method.\n         * @param {Boolean} [isIndex=false] - See 'getId' method.\n         * @returns {Object}\n         */\n        getRowData: function (id, isIndex) {\n            id = this.getId(id, isIndex);\n\n            return _.find(this.rowsData, function (row) {\n                return row[this.indexField] === id;\n            }, this);\n        },\n\n        /**\n         * Checks if specified record is active.\n         *\n         * @param {(Number|String)} id - See 'getId' method.\n         * @param {Boolean} [isIndex=false] - See'getId' method.\n         * @returns {Boolean}\n         */\n        isActive: function (id, isIndex) {\n            var record = this.getRecord(id, isIndex);\n\n            return _.contains(this.activeRecords(), record);\n        },\n\n        /**\n         * Checks if editor has active records.\n         *\n         * @returns {Boolean}\n         */\n        hasActive: function () {\n            return !!this.activeRecords().length || this.permanentlyActive;\n        },\n\n        /**\n         * Counts number of active records.\n         *\n         * @returns {Number}\n         */\n        countActive: function () {\n            return this.activeRecords().length;\n        },\n\n        /**\n         * Counts number of invalid fields across all active records.\n         *\n         * @returns {Number}\n         */\n        countErrors: function () {\n            var errorsCount = 0;\n\n            this.activeRecords.each(function (record) {\n                errorsCount += record.errorsCount;\n            });\n\n            this.errorsCount = errorsCount;\n\n            return errorsCount;\n        },\n\n        /**\n         * Translatable error message text.\n         *\n         * @returns {String}\n         */\n        countErrorsMessage: function () {\n            return $t('There are {placeholder} messages requires your attention.')\n                .replace('{placeholder}', this.countErrors());\n        },\n\n        /**\n         * Checks if editor has any errors.\n         *\n         * @returns {Boolean}\n         */\n        hasErrors: function () {\n            return !!this.countErrors();\n        },\n\n        /**\n         * Handles changes of the records 'active' property.\n         *\n         * @returns {Editor} Chainable.\n         */\n        updateState: function () {\n            var active      = this.elems.filter('active'),\n                activeCount = active.length,\n                columns     = this.columns().elems;\n\n            columns.each('disableAction', !!activeCount);\n\n            this.isMultiEditing = activeCount > 1;\n            this.isSingleEditing = activeCount === 1;\n\n            this.activeRecords(active);\n\n            return this;\n        },\n\n        /**\n         * Returns list of selections from a current page.\n         *\n         * @returns {Array}\n         */\n        getSelections: function () {\n            return this.selections().getPageSelections();\n        },\n\n        /**\n         * Starts editing of selected records. If record\n         * is not in the selections list, then it will get hidden.\n         *\n         * @returns {Editor} Chainable.\n         */\n        editSelected: function () {\n            var selections = this.getSelections();\n\n            this.elems.each(function (record) {\n                if (!_.contains(selections, record.recordId)) {\n                    record.active(false);\n                }\n            });\n\n            selections.forEach(function (id) {\n                this.edit(id);\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Checks if there is any additional messages.\n         *\n         * @returns {Boolean}\n         */\n        hasMessages: function () {\n            return this.messages().length;\n        },\n\n        /**\n         * Adds new additional message or a set of messages.\n         *\n         * @param {(Object|Array)} message - Messages to be added.\n         * @returns {Editor} Chainable.\n         */\n        addMessage: function (message) {\n            var messages = this.messages();\n\n            Array.isArray(message) ?\n                messages.push.apply(messages, message) :\n                messages.push(message);\n\n            this.messages(messages);\n\n            return this;\n        },\n\n        /**\n         * Removes all additional messages.\n         *\n         * @returns {Editor} Chainable.\n         */\n        clearMessages: function () {\n            this.messages.removeAll();\n\n            return this;\n        },\n\n        /**\n         * Listener of the selections data changes.\n         */\n        onSelectionsChange: function () {\n            if (this.hasActive()) {\n                this.editSelected();\n            }\n        },\n\n        /**\n         * Handles successful save request.\n         */\n        onDataSaved: function () {\n            var msg = {\n                type: 'success',\n                message: this.successMsg\n            };\n\n            this.addMessage(msg)\n                .source('reload', {\n                    refresh: true\n                });\n        },\n\n        /**\n         * Handles failed save request.\n         *\n         * @param {(Array|Object)} errors - List of errors or a single error object.\n         */\n        onSaveError: function (errors) {\n            this.addMessage(errors)\n                .columns('hideLoader');\n        }\n    });\n});\n","Magento_Ui/js/grid/editing/bulk.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    './record'\n], function (_, utils, Record) {\n    'use strict';\n\n    /**\n     * Removes empty properties from the provided object.\n     *\n     * @param {Object} data - Object to be processed.\n     * @returns {Object}\n     */\n    function removeEmpty(data) {\n        data = utils.flatten(data);\n        data = _.omit(data, utils.isEmpty);\n\n        return utils.unflatten(data);\n    }\n\n    return Record.extend({\n        defaults: {\n            template: 'ui/grid/editing/bulk',\n            active: false,\n            templates: {\n                fields: {\n                    select: {\n                        caption: ' '\n                    }\n                }\n            },\n            imports: {\n                active: '${ $.editorProvider }:isMultiEditing'\n            },\n            listens: {\n                data: 'updateState',\n                active: 'updateState'\n            }\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Bulk} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track({\n                    hasData: false\n                });\n\n            return this;\n        },\n\n        /**\n         * Extends original method to disable possible\n         * 'required-entry' validation rule.\n         *\n         * @returns {Object} Columns' field definition.\n         */\n        buildField: function () {\n            var field = this._super(),\n                rules = field.validation;\n\n            if (rules) {\n                delete rules['required-entry'];\n            }\n\n            return field;\n        },\n\n        /**\n         * Applies current data to all active records.\n         *\n         * @returns {Bulk} Chainable.\n         */\n        apply: function () {\n            if (this.isValid()) {\n                this.applyData()\n                    .clear();\n            }\n\n            return this;\n        },\n\n        /**\n         * Sets available data to all active records.\n         *\n         * @param {Object} [data] -  If not specified, then current fields data will be used.\n         * @returns {Bulk} Chainable.\n         */\n        applyData: function (data) {\n            data = data || this.getData();\n\n            this.editor('setData', data, true);\n\n            return this;\n        },\n\n        /**\n         * Returns data of all non-empty fields.\n         *\n         * @returns {Object} Fields data without empty values.\n         */\n        getData: function () {\n            return removeEmpty(this._super());\n        },\n\n        /**\n         * Updates own 'hasData' property and defines\n         * whether regular rows editing can be resumed.\n         *\n         * @returns {Bulk} Chainable.\n         */\n        updateState: function () {\n            var fields  = _.keys(this.getData()),\n                hasData = !!fields.length;\n\n            this.hasData = hasData;\n\n            if (!this.active()) {\n                fields = [];\n            }\n\n            this.editor('disableFields', fields);\n            this.editor('canSave', !fields.length);\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/grid/paging/sizes.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    'uiElement'\n], function (ko, _, utils, Element) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            template: 'ui/grid/paging/sizes',\n            minSize: 1,\n            maxSize: 999,\n            statefull: {\n                options: true,\n                value: true\n            },\n            listens: {\n                value: 'onValueChange',\n                options: 'onSizesChange'\n            }\n        },\n\n        /**\n         * Initializes sizes component.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .updateArray();\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track([\n                    'value',\n                    'editing',\n                    'customVisible',\n                    'customValue'\n                ])\n                .track({\n                    optionsArray: []\n                });\n\n            this._value = ko.pureComputed({\n                read: ko.getObservable(this, 'value'),\n\n                /**\n                 * Validates input field prior to updating 'value' property.\n                 */\n                write: function (value) {\n                    value = this.normalize(value);\n\n                    this.value = value;\n                    this._value.notifySubscribers(value);\n                },\n\n                owner: this\n            });\n\n            return this;\n        },\n\n        /**\n         * Starts editing of the specified size.\n         *\n         * @param {Number} value - Value of the size.\n         * @returns {Sizes} Chainable.\n         */\n        edit: function (value) {\n            this.editing = value;\n\n            return this;\n        },\n\n        /**\n         * Discards changes made to the currently editable size.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        discardEditing: function () {\n            var value = this.editing;\n\n            if (value) {\n                this.updateSize(value, value);\n            }\n\n            return this;\n        },\n\n        /**\n         * Invokes 'discardEditing' and 'discardCustom' actions.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        discardAll: function () {\n            this.discardEditing()\n                .discardCustom();\n\n            return this;\n        },\n\n        /**\n         * Returns value of the first size.\n         *\n         * @returns {Number}\n         */\n        getFirst: function () {\n            return this.optionsArray[0].value;\n        },\n\n        /**\n         * Returns size which matches specified value.\n         *\n         * @param {Number} value - Value of the item.\n         * @returns {Object|Undefined}\n         */\n        getSize: function (value) {\n            return this.options[value];\n        },\n\n        /**\n         * Sets current size to the specified value.\n         *\n         * @param {Number} value - Value of the size.\n         * @returns {Sizes} Chainable.\n         */\n        setSize: function (value) {\n            this.value = value;\n\n            return this;\n        },\n\n        /**\n         * Adds a new value to sizes list.\n         *\n         * @param {Number} value - Value to be added.\n         * @returns {Sizes} Chainable.\n         */\n        addSize: function (value) {\n            var size;\n\n            if (!this.hasSize(value)) {\n                size = this.createSize(value);\n\n                this.set('options.' + value, size);\n            }\n\n            return this;\n        },\n\n        /**\n         * Removes provided value from the sizes list.\n         *\n         * @param {Number} value - Value to be removed.\n         * @returns {Sizes} Chainable.\n         */\n        removeSize: function (value) {\n            if (!this.hasSize(value)) {\n                return this;\n            }\n\n            this.remove('options.' + value);\n\n            if (this.isSelected(value)) {\n                this.setSize(this.getFirst());\n            }\n\n            return this;\n        },\n\n        /**\n         * Updates existing value to the provided one. If new value\n         * is not specified, then sizes' '_value' property will be taken.\n         *\n         * @param {Number} value - Existing value that should be updated.\n         * @param {(Number|String)} [newValue=size._value] - New size value.\n         * @returns {Sizes} Chainable.\n         */\n        updateSize: function (value, newValue) {\n            var size = this.getSize(value);\n\n            if (!size) {\n                return this;\n            }\n\n            newValue = newValue || size._value;\n\n            if (isNaN(+newValue)) {\n                this.discardEditing();\n\n                return this;\n            }\n\n            newValue = this.normalize(newValue);\n\n            this.remove('options.' + value)\n                .addSize(newValue);\n\n            if (this.isSelected(value)) {\n                this.setSize(newValue);\n            }\n\n            return this;\n        },\n\n        /**\n         * Creates new editable size instance with the provided value.\n         *\n         * @param {Number} value - Value of the size.\n         * @returns {Object}\n         */\n        createSize: function (value) {\n            return {\n                value: value,\n                label: value,\n                _value: value,\n                editable: true\n            };\n        },\n\n        /**\n         * Checks if provided value exists in the sizes list.\n         *\n         * @param {Number} value - Value to be checked.\n         * @returns {Boolean}\n         */\n        hasSize: function (value) {\n            return !!this.getSize(value);\n        },\n\n        /**\n         * Hides and clears custom field.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        discardCustom: function () {\n            this.hideCustom()\n                .clearCustom();\n\n            return this;\n        },\n\n        /**\n         * Shows custom field.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        showCustom: function () {\n            this.customVisible = true;\n\n            return this;\n        },\n\n        /**\n         * Hides custom field.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        hideCustom: function () {\n            this.customVisible = false;\n\n            return this;\n        },\n\n        /**\n         * Empties value of the custom field.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        clearCustom: function () {\n            this.customValue = '';\n\n            return this;\n        },\n\n        /**\n         * Adds a new size specified in the custom field.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        applyCustom: function () {\n            var value = this.customValue;\n\n            value = this.normalize(value);\n\n            this.addSize(value)\n                .setSize(value)\n                .discardCustom();\n\n            return this;\n        },\n\n        /**\n         * Checks if custom field is visible.\n         *\n         * @returns {Boolean}\n         */\n        isCustomVisible: function () {\n            return this.customVisible;\n        },\n\n        /**\n         * Converts provided value to a number and puts\n         * it in range between 'minSize' and 'maxSize' properties.\n         *\n         * @param {(Number|String)} value - Value to be normalized.\n         * @returns {Number}\n         */\n        normalize: function (value) {\n            value = +value;\n\n            if (isNaN(value)) {\n                return this.getFirst();\n            }\n\n            return utils.inRange(Math.round(value), this.minSize, this.maxSize);\n        },\n\n        /**\n         * Updates the array of options.\n         *\n         * @returns {Sizes} Chainable.\n         */\n        updateArray: function () {\n            var array = _.values(this.options);\n\n            this.optionsArray = _.sortBy(array, 'value');\n\n            return this;\n        },\n\n        /**\n         * Checks if provided value is in editing state.\n         *\n         * @param {Number} value - Value to be checked.\n         * @returns {Boolean}\n         */\n        isEditing: function (value) {\n            return this.editing === value;\n        },\n\n        /**\n         * Checks if provided value is selected.\n         *\n         * @param {Number} value - Value to be checked.\n         * @returns {Boolean}\n         */\n        isSelected: function (value) {\n            return this.value === value;\n        },\n\n        /**\n         * Listener of the 'value' property changes.\n         */\n        onValueChange: function () {\n            this.discardAll()\n                .trigger('close');\n        },\n\n        /**\n         * Listener of the 'options' object changes.\n         */\n        onSizesChange: function () {\n            this.editing = false;\n\n            this.updateArray();\n        }\n    });\n});\n","Magento_Ui/js/grid/paging/paging.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    'uiLayout',\n    'uiElement'\n], function (ko, _, utils, layout, Element) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            template: 'ui/grid/paging/paging',\n            totalTmpl: 'ui/grid/paging-total',\n            totalRecords: 0,\n            showTotalRecords: true,\n            pages: 1,\n            current: 1,\n            selectProvider: 'ns = ${ $.ns }, index = ids',\n\n            sizesConfig: {\n                component: 'Magento_Ui/js/grid/paging/sizes',\n                name: '${ $.name }_sizes',\n                storageConfig: {\n                    provider: '${ $.storageConfig.provider }',\n                    namespace: '${ $.storageConfig.namespace }'\n                }\n            },\n\n            imports: {\n                totalSelected: '${ $.selectProvider }:totalSelected',\n                totalRecords: '${ $.provider }:data.totalRecords',\n                showTotalRecords: '${ $.provider }:data.showTotalRecords',\n                filters: '${ $.provider }:params.filters',\n                keywordUpdated: '${ $.provider }:params.keywordUpdated'\n            },\n\n            exports: {\n                pageSize: '${ $.provider }:params.paging.pageSize',\n                current: '${ $.provider }:params.paging.current'\n            },\n\n            links: {\n                options: '${ $.sizesConfig.name }:options',\n                pageSize: '${ $.sizesConfig.name }:value'\n            },\n\n            statefull: {\n                pageSize: true,\n                current: true\n            },\n\n            listens: {\n                'pages': 'onPagesChange',\n                'pageSize': 'onPageSizeChange',\n                'totalRecords': 'updateCounter',\n                'showTotalRecords': 'updateShowTotalRecords',\n                '${ $.provider }:params.filters': 'goFirst',\n                '${ $.provider }:params.search': 'onSearchUpdate'\n            },\n\n            modules: {\n                sizes: '${ $.sizesConfig.name }'\n            }\n        },\n\n        /**\n         * Initializes paging component.\n         *\n         * @returns {Paging} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .initSizes()\n                .updateCounter();\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Paging} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track([\n                    'totalSelected',\n                    'totalRecords',\n                    'showTotalRecords',\n                    'pageSize',\n                    'pages',\n                    'current'\n                ]);\n\n            this._current = ko.pureComputed({\n                read: ko.getObservable(this, 'current'),\n\n                /**\n                 * Validates page change according to user's input.\n                 * Sets current observable to result of validation.\n                 * Calls reload method then.\n                 */\n                write: function (value) {\n                    this.setPage(value)\n                        ._current.notifySubscribers(this.current);\n                },\n\n                owner: this\n            });\n\n            return this;\n        },\n\n        /**\n         * Initializes sizes component.\n         *\n         * @returns {Paging} Chainable.\n         */\n        initSizes: function () {\n            layout([this.sizesConfig]);\n\n            return this;\n        },\n\n        /**\n         * Gets first item index on current page.\n         *\n         * @returns {Number}\n         */\n        getFirstItemIndex: function () {\n            return this.pageSize * (this.current - 1) + 1;\n        },\n\n        /**\n         * Gets last item index on current page.\n         *\n         * @returns {Number}\n         */\n        getLastItemIndex: function () {\n            var lastItem = this.getFirstItemIndex() + this.pageSize - 1;\n\n            return this.totalRecords < lastItem ? this.totalRecords : lastItem;\n        },\n\n        /**\n         * Sets cursor to the provied value.\n         *\n         * @param {(Number|String)} value - New value of the cursor.\n         * @returns {Paging} Chainable.\n         */\n        setPage: function (value) {\n            this.current = this.normalize(value);\n\n            return this;\n        },\n\n        /**\n         * Increments current page value.\n         *\n         * @returns {Paging} Chainable.\n         */\n        next: function () {\n            this.setPage(this.current + 1);\n\n            return this;\n        },\n\n        /**\n         * Decrements current page value.\n         *\n         * @returns {Paging} Chainable.\n         */\n        prev: function () {\n            this.setPage(this.current - 1);\n\n            return this;\n        },\n\n        /**\n         * Goes to the first page.\n         *\n         * @returns {Paging} Chainable.\n         */\n        goFirst: function () {\n            if (!_.isUndefined(this.filters)) {\n                this.current = 1;\n            }\n\n            return this;\n        },\n\n        /**\n         * Goes to the last page.\n         *\n         * @returns {Paging} Chainable.\n         */\n        goLast: function () {\n            this.current = this.pages;\n\n            return this;\n        },\n\n        /**\n         * Checks if current page is the first one.\n         *\n         * @returns {Boolean}\n         */\n        isFirst: function () {\n            return this.current === 1;\n        },\n\n        /**\n         * Checks if current page is the last one.\n         *\n         * @returns {Boolean}\n         */\n        isLast: function () {\n            return this.current === this.pages;\n        },\n\n        /**\n         * Updates number of pages.\n         */\n        updateCounter: function () {\n            this.pages = Math.ceil(this.totalRecords / this.pageSize) || 1;\n\n            return this;\n        },\n\n        /**\n         * Updates show total records flag.\n         */\n        updateShowTotalRecords: function () {\n            if (this.showTotalRecords === undefined) {\n                this.showTotalRecords = true;\n            }\n            return this;\n        },\n\n        /**\n         * Calculates new page cursor based on the\n         * previous and current page size values.\n         */\n        updateCursor: function () {\n            var cursor = this.current - 1,\n                size = this.pageSize,\n                oldSize = _.isUndefined(this.previousSize) ? this.pageSize : this.previousSize,\n                delta = cursor * (oldSize - size) / size;\n\n            delta = size > oldSize ?\n                Math.ceil(delta) :\n                Math.floor(delta);\n\n            cursor += delta + 1;\n\n            this.previousSize = size;\n\n            this.setPage(cursor);\n\n            return this;\n        },\n\n        /**\n         * Converts provided value to a number and puts\n         * it in range between 1 and total amount of pages.\n         *\n         * @param {(Number|String)} value - Value to be normalized.\n         * @returns {Number}\n         */\n        normalize: function (value) {\n            value = +value;\n\n            if (isNaN(value)) {\n                return 1;\n            }\n\n            return utils.inRange(Math.round(value), 1, this.pages);\n        },\n\n        /**\n         * Handles changes of the page size.\n         */\n        onPageSizeChange: function () {\n            this.updateCounter()\n                .updateCursor();\n        },\n\n        /**\n         * Handles changes of the pages amount.\n         */\n        onPagesChange: function () {\n            this.updateCursor();\n        },\n\n        /**\n         * Resent the pagination to Page 1 on search keyword update\n         */\n        onSearchUpdate: function () {\n            if (!_.isUndefined(this.keywordUpdated) && this.keywordUpdated) {\n                this.goFirst();\n            }\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/grid/sticky/sticky.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    'underscore',\n    'uiComponent',\n    'Magento_Ui/js/lib/view/utils/raf'\n], function ($, _, Component, raf) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            listingSelector: '${ $.listingProvider }::not([data-role = \"sticky-el-root\"])',\n            toolbarSelector: '${ $.toolbarProvider }::not([data-role = \"sticky-el-root\"])',\n            bulkRowSelector: '[data-role = \"data-grid-bulk-row\"]',\n            bulkRowHeaderSelector: '.data-grid-info-panel:visible',\n            tableSelector: 'table',\n            columnSelector: 'thead tr th',\n            rowSelector: 'tbody tr',\n            toolbarCollapsiblesSelector: '[data-role=\"toolbar-menu-item\"]',\n            toolbarCollapsiblesActiveClass: '_active',\n            template: 'ui/grid/sticky/sticky',\n            stickyContainerSelector: '.sticky-header',\n            stickyElementSelector: '[data-role = \"sticky-el-root\"]',\n            leftDataGridCapSelector: '.data-grid-cap-left',\n            rightDataGridCapSelector: '.data-grid-cap-right',\n            visible: false,\n            enableToolbar: true,\n            enableHeader: true,\n            modules: {\n                toolbar: '${ $.toolbarProvider }',\n                listing: '${ $.listingProvider }'\n            },\n            otherStickyElsSize: 77,\n            containerNode: null,\n            listingNode: null,\n            toolbarNode: null,\n            stickyListingNode: null,\n            stickyToolbarNode: null,\n            storedOriginalToolbarElements: [],\n            cache: {},\n            flags: {},\n            dirtyFlag: 'dirty'\n        },\n\n        /**\n         * Initializes Sticky component.\n         *\n         * @returns {Object} Chainable.\n         */\n        initialize: function () {\n            this._super();\n            _.bindAll(this,\n                'adjustStickyElems',\n                'initListingNode',\n                'initToolbarNode',\n                'initContainerNode',\n                'initColumns',\n                'initStickyListingNode',\n                'initStickyToolbarNode',\n                'initLeftDataGridCap',\n                'initRightDataGridCap'\n            );\n\n            $.async(this.listingSelector,\n                this.initListingNode);\n            $.async(this.toolbarSelector,\n                this.initToolbarNode);\n\n            $.async(this.stickyContainerSelector,\n                this,\n                this.initContainerNode);\n\n            return this;\n        },\n\n        /**\n         * Init observables\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track('visible');\n\n            return this;\n        },\n\n        /**\n         * Init original listing node\n         *\n         * @param {HTMLElement} node\n         */\n        initListingNode: function (node) {\n            if ($(node).is(this.stickyElementSelector)) {\n                return;\n            }\n            this.listingNode = $(node);\n            $.async(this.columnSelector, node, this.initColumns);\n        },\n\n        /**\n         * Init original toolbar node\n         *\n         * @param {HTMLElement} node\n         */\n        initToolbarNode: function (node) {\n            if ($(node).is(this.stickyElementSelector)) {\n                return;\n            }\n            this.toolbarNode = $(node);\n        },\n\n        /**\n         * Init sticky listing node\n         *\n         * @param {HTMLElement} node\n         */\n        initStickyListingNode: function (node) {\n            this.stickyListingNode = $(node);\n            this.checkPos();\n            this.initListeners();\n        },\n\n        /**\n         * Init sticky toolbar node\n         *\n         * @param {HTMLElement} node\n         */\n        initStickyToolbarNode: function (node) {\n            this.stickyToolbarNode = $(node);\n        },\n\n        /**\n         * Init sticky header container node\n         *\n         * @param {HTMLElement} node\n         */\n        initContainerNode: function (node) {\n            this.containerNode = $(node);\n\n            $.async(this.leftDataGridCapSelector,\n                node,\n                this.initLeftDataGridCap);\n            $.async(this.rightDataGridCapSelector,\n                node,\n                this.initRightDataGridCap);\n\n            $.async(this.stickyElementSelector,\n                this.listing(),\n                this.initStickyListingNode);\n            $.async(this.stickyElementSelector,\n                this.toolbar(),\n                this.initStickyToolbarNode);\n        },\n\n        /**\n         * Init columns (each time when amount of columns is changed)\n         *\n         */\n        initColumns: function () {\n            this.columns = this.listingNode.find(this.columnSelector);\n        },\n\n        /**\n         * Init left DataGridCap\n         *\n         * @param {HTMLElement} node\n         */\n        initLeftDataGridCap: function (node) {\n            this.leftDataGridCap = $(node);\n        },\n\n        /**\n         * Init right DataGridCap\n         *\n         * @param {HTMLElement} node\n         */\n        initRightDataGridCap: function (node) {\n            this.rightDataGridCap = $(node);\n        },\n\n        /**\n         * Init listeners\n         *\n         * @returns {Object} Chainable.\n         */\n        initListeners: function () {\n            this.adjustStickyElems();\n            this.initOnResize()\n                .initOnScroll()\n                .initOnListingScroll();\n\n            return this;\n        },\n\n        /**\n         * Start to listen to window scroll event\n         *\n         * @returns {Object} Chainable.\n         */\n        initOnScroll: function () {\n            this.lastHorizontalScrollPos = $(window).scrollLeft();\n            document.addEventListener('scroll', function () {\n                this.flags.scrolled = true;\n            }.bind(this));\n\n            return this;\n        },\n\n        /**\n         * Start to listen to original listing scroll event\n         *\n         * @returns {Object} Chainable.\n         */\n        initOnListingScroll: function () {\n            $(this.listingNode).on('scroll', function (e) {\n                this.flags.listingScrolled = true;\n                this.flags.listingScrolledValue = $(e.target).scrollLeft();\n            }.bind(this));\n\n            return this;\n        },\n\n        /**\n         * Start to listen to window resize event\n         *\n         * @returns {Object} Chainable.\n         */\n        initOnResize: function () {\n            $(window).on('resize', function () {\n                this.flags.resized = true;\n            }.bind(this));\n\n            return this;\n        },\n\n        /**\n         * Adjust sticky header elements according to flags of the events that have happened in the endless RAF loop\n         */\n        adjustStickyElems: function () {\n            if (this.flags.resized ||\n                this.flags.scrolled) {\n                this.checkPos();\n            }\n\n            if (this.visible) {\n                this.checkTableElemsWidth();\n\n                if (this.flags.originalWidthChanged) {\n                    this.adjustContainerElemsWidth();\n                }\n\n                if (this.flags.resized) {\n                    this.onResize();\n                }\n\n                if (this.flags.scrolled) {\n                    this.onWindowScroll();\n                }\n\n                if (this.flags.listingScrolled) {\n                    this.onListingScroll(this.flags.listingScrolledValue);\n                }\n            }\n            _.each(this.flags, function (val, key) {\n                if (val === this.dirtyFlag) {\n                    this.flags[key] = false;\n                } else if (val) {\n                    this.flags[key] = this.dirtyFlag;\n                }\n            }, this);\n\n            raf(this.adjustStickyElems);\n        },\n\n        /**\n         * Handles window scroll\n         */\n        onWindowScroll: function () {\n            var scrolled = $(window).scrollLeft(),\n                horizontal = this.lastHorizontalScrollPos !== scrolled;\n\n            if (horizontal) {\n                this.adjustOffset()\n                    .adjustDataGridCapPositions();\n                this.lastHorizontalScrollPos = scrolled;\n            } else {\n                this.checkPos();\n            }\n        },\n\n        /**\n         * Handles original listing scroll\n         *\n         * @param {Number} scrolled\n         */\n        onListingScroll: function (scrolled) {\n            this.adjustOffset(scrolled);\n        },\n\n        /**\n         * Handles window resize\n         */\n        onResize: function () {\n            this.checkPos();\n            this.adjustContainerElemsWidth()\n                .adjustDataGridCapPositions();\n        },\n\n        /**\n         * Check if original table or columns change it dimensions and sets appropriate flag\n         */\n        checkTableElemsWidth: function () {\n            var newWidth = this.getTableWidth();\n\n            if (this.cache.tableWidth !== newWidth) {\n                this.cache.tableWidth = newWidth;\n                this.flags.originalWidthChanged = true;\n            } else if (this.cache.colChecksum !== this.getColsChecksum()) {\n                this.cache.colChecksum = this.getColsChecksum();\n                this.flags.originalWidthChanged = true;\n            }\n        },\n\n        /**\n         * Get the checksum of original columns width\n         *\n         * @returns {Number}.\n         */\n        getColsChecksum: function () {\n            return _.reduce(this.columns,\n            function (pv, cv) {\n                return ($(pv).width() || pv) + '' + $(cv).width();\n            });\n        },\n\n        /**\n         * Get the width of the sticky table wrapper\n         *\n         * @returns {Number}.\n         */\n        getListingWidth: function () {\n            return this.listingNode.width();\n        },\n\n        /**\n         * Get the width of the original table\n         *\n         * @returns {Number}.\n         */\n        getTableWidth: function () {\n            return this.listingNode.find(this.tableSelector).width();\n        },\n\n        /**\n         * Get the top elem: header or toolbar\n         *\n         * @returns {HTMLElement}.\n         */\n        getTopElement: function () {\n            return this.toolbarNode || this.listingNode;\n        },\n\n        /**\n         * Get the height of the other sticky elem (Page header)\n         *\n         * @returns {Number}.\n         */\n        getOtherStickyElementsSize: function () {\n            return this.otherStickyElsSize;\n        },\n\n        /**\n         * Get original bulk row height, if is visible\n         *\n         * @returns {Number}.\n         */\n        getBulkRowHeight: function () {\n            return this.listingNode.find(this.bulkRowSelector).filter(':visible').height();\n        },\n\n        /**\n         * Get top Y coord of the sticky header\n         *\n         * @returns {Number}.\n         */\n        getListingTopYCoord: function () {\n            var bulkRowHeight = this.getBulkRowHeight();\n\n            return this.listingNode.find('tbody').offset().top -\n                this.containerNode.height() -\n                $(window).scrollTop() +\n                bulkRowHeight;\n        },\n\n        /**\n         * Check if sticky header must be visible\n         *\n         * @returns {Boolean}.\n         */\n        getMustBeSticky: function () {\n            var stickyTopCondition = this.getListingTopYCoord() - this.getOtherStickyElementsSize(),\n                stickyBottomCondition = this.listingNode.offset().top +\n                    this.listingNode.height() -\n                    $(window).scrollTop() +\n                    this.getBulkRowHeight() -\n                    this.getOtherStickyElementsSize();\n\n            return stickyTopCondition < 0 && stickyBottomCondition > 0;\n        },\n\n        /**\n         * Resize sticky header and cols\n         *\n         * @returns {Object} Chainable.\n         */\n        adjustContainerElemsWidth: function () {\n            this.resizeContainer()\n                .resizeCols()\n                .resizeBulk();\n\n            return this;\n        },\n\n        /**\n         * Resize sticky header\n         *\n         * @returns {Object} Chainable.\n         */\n        resizeContainer: function () {\n            var listingWidth = this.getListingWidth();\n\n            this.stickyListingNode.innerWidth(listingWidth);\n            this.stickyListingNode.find(this.tableSelector).innerWidth(this.getTableWidth());\n\n            if (this.stickyToolbarNode) {\n                this.stickyToolbarNode.innerWidth(listingWidth);\n            }\n\n            return this;\n        },\n\n        /**\n         * Resize sticky cols\n         *\n         * @returns {Object} Chainable.\n         */\n        resizeCols: function () {\n            var cols = this.listingNode.find(this.columnSelector);\n\n            this.stickyListingNode.find(this.columnSelector).each(function (ind) {\n                var originalColWidth =  $(cols[ind]).width();\n\n                $(this).width(originalColWidth);\n            });\n\n            return this;\n        },\n\n        /**\n         * Resize bulk row header\n         *\n         * @returns {Object} Chainable.\n         */\n        resizeBulk: function () {\n            var bulk = this.containerNode.find(this.bulkRowHeaderSelector)[0];\n\n            if (bulk) {\n                $(bulk).innerWidth(this.getListingWidth());\n            }\n\n            return this;\n        },\n\n        /**\n         * Reset viewport to the top of listing\n         */\n        resetToTop: function () {\n            var posOfTopEl = this.getTopElement().offset().top - this.getOtherStickyElementsSize() || 0;\n\n            $(window).scrollTop(posOfTopEl);\n        },\n\n        /**\n         * Adjust sticky header offset\n         *\n         * @param {Number} val\n         * @returns {Object} Chainable.\n         */\n        adjustOffset: function (val) {\n            val = val || this.listingNode.scrollLeft();\n            this.stickyListingNode.offset({\n                left: this.listingNode.offset().left - val\n            });\n\n            return this;\n        },\n\n        /**\n         * Adjust both DataGridCap position\n         *\n         * @returns {Object} Chainable.\n         */\n        adjustDataGridCapPositions: function () {\n            this.adjustLeftDataGridCapPos()\n                .adjustRightDataGridCapPos();\n\n            return this;\n        },\n\n        /**\n         * Adjust left DataGridCap position\n         *\n         * @returns {Object} Chainable.\n         */\n        adjustLeftDataGridCapPos: function () {\n            this.leftDataGridCap.offset({\n                left: this.listingNode.offset().left - this.leftDataGridCap.width()\n            });\n\n            return this;\n        },\n\n        /**\n         * Adjust right DataGridCap position\n         *\n         * @returns {Object} Chainable.\n         */\n        adjustRightDataGridCapPos: function () {\n            this.rightDataGridCap.offset({\n                left: this.listingNode.offset().left + this.listingNode.width()\n            });\n\n            return this;\n        },\n\n        /**\n         * Hides the oiginal toolbar opened dropdowns/collapsibles etc\n         */\n        collapseOriginalElements: function () {\n            this.toolbarNode\n                .find(this.toolbarCollapsiblesSelector)\n                .css('visibility', 'hidden');\n            $(this.listingNode.find(this.bulkRowSelector)[0]).css('visibility', 'hidden');\n        },\n\n        /**\n         * Restores the oiginal toolbar opened dropdowns/collapsibles etc\n         */\n        restoreOriginalElements: function () {\n            this.toolbarNode\n                .find(this.toolbarCollapsiblesSelector)\n                .css('visibility', 'visible');\n            $(this.listingNode.find(this.bulkRowSelector)[0]).css('visibility', 'visible');\n        },\n\n        /**\n         * Toggle the visibility of sticky header\n         *\n         * @returns {Object} Chainable.\n         */\n        toggleContainerVisibility: function () {\n            this.visible = !this.visible;\n\n            return this;\n        },\n\n        /**\n         * Checks position of the listing to know if need to show/hide sticky header\n         *\n         * @returns {Boolean} whether the visibility of the sticky header was toggled.\n         */\n        checkPos: function () {\n            var isSticky = this.visible,\n                mustBeSticky = this.getMustBeSticky(),\n                needChange = isSticky !== mustBeSticky;\n\n            if (needChange) {\n                if (mustBeSticky) {\n                    this.collapseOriginalElements();\n                    this.toggleContainerVisibility();\n                    this.adjustContainerElemsWidth()\n                        .adjustOffset()\n                        .adjustDataGridCapPositions();\n\n                } else {\n                    this.toggleContainerVisibility();\n                    this.restoreOriginalElements();\n                }\n            }\n\n            return needChange;\n        }\n    });\n});\n","Magento_Ui/js/grid/filters/chips.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiCollection'\n], function (_, Collection) {\n    'use strict';\n\n    return Collection.extend({\n        defaults: {\n            template: 'ui/grid/filters/chips',\n            componentType: 'filtersChips'\n        },\n\n        /**\n         * Defines if some of components' children has available previews.\n         *\n         * @returns {Boolean}\n         */\n        hasPreviews: function () {\n            return this.elems().some(function (elem) {\n                return !!elem.previews.length;\n            });\n        },\n\n        /**\n         * Calls clear method on all of its' children.\n         *\n         * @returns {Chips} Chainable.\n         */\n        clear: function () {\n            _.invoke(this.elems(), 'clear');\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/grid/filters/filters.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    'uiLayout',\n    'uiCollection',\n    'mage/translate',\n    'jquery'\n], function (_, utils, layout, Collection, $t, $) {\n    'use strict';\n\n    /**\n     * Extracts and formats preview of an element.\n     *\n     * @param {Object} elem - Element whose preview should be extracted.\n     * @returns {Object} Formatted data.\n     */\n    function extractPreview(elem) {\n        return {\n            label: elem.label,\n            preview: elem.getPreview(),\n            elem: elem\n        };\n    }\n\n    /**\n     * Removes empty properties from the provided object.\n     *\n     * @param {Object} data - Object to be processed.\n     * @returns {Object}\n     */\n    function removeEmpty(data) {\n        var result = utils.mapRecursive(data, utils.removeEmptyValues.bind(utils));\n\n        return utils.mapRecursive(result, function (value) {\n            return _.isString(value) ? value.trim() : value;\n        });\n    }\n\n    return Collection.extend({\n        defaults: {\n            template: 'ui/grid/filters/filters',\n            stickyTmpl: 'ui/grid/sticky/filters',\n            _processed: [],\n            columnsProvider: 'ns = ${ $.ns }, componentType = columns',\n            bookmarksProvider: 'ns = ${ $.ns }, componentType = bookmark',\n            applied: {\n                placeholder: true\n            },\n            filters: {\n                placeholder: true\n            },\n            templates: {\n                filters: {\n                    base: {\n                        parent: '${ $.$data.filters.name }',\n                        name: '${ $.$data.column.index }',\n                        provider: '${ $.$data.filters.name }',\n                        dataScope: '${ $.$data.column.index }',\n                        label: '${ $.$data.column.label }',\n                        imports: {\n                            visible: '${ $.$data.column.name }:visible'\n                        }\n                    },\n                    text: {\n                        component: 'Magento_Ui/js/form/element/abstract',\n                        template: 'ui/grid/filters/field'\n                    },\n                    select: {\n                        component: 'Magento_Ui/js/form/element/select',\n                        template: 'ui/grid/filters/field',\n                        options: '${ JSON.stringify($.$data.column.options) }',\n                        caption: ' '\n                    },\n                    dateRange: {\n                        component: 'Magento_Ui/js/grid/filters/range',\n                        rangeType: 'date'\n                    },\n                    datetimeRange: {\n                        component: 'Magento_Ui/js/grid/filters/range',\n                        rangeType: 'datetime'\n                    },\n                    textRange: {\n                        component: 'Magento_Ui/js/grid/filters/range',\n                        rangeType: 'text'\n                    }\n                }\n            },\n            chipsConfig: {\n                name: '${ $.name }_chips',\n                provider: '${ $.chipsConfig.name }',\n                component: 'Magento_Ui/js/grid/filters/chips'\n            },\n            listens: {\n                active: 'updatePreviews',\n                applied: 'cancel updateActive'\n            },\n            statefull: {\n                applied: true\n            },\n            exports: {\n                applied: '${ $.provider }:params.filters'\n            },\n            imports: {\n                onColumnsUpdate: '${ $.columnsProvider }:elems',\n                onBackendError: '${ $.provider }:lastError',\n                bookmarksActiveIndex: '${ $.bookmarksProvider }:activeIndex'\n            },\n            modules: {\n                columns: '${ $.columnsProvider }',\n                chips: '${ $.chipsConfig.provider }'\n            }\n        },\n\n        /**\n         * Initializes filters component.\n         *\n         * @returns {Filters} Chainable.\n         */\n        initialize: function (config) {\n            if (typeof config.options !== 'undefined' && config.options.dateFormat) {\n                this.constructor.defaults.templates.filters.dateRange.dateFormat = config.options.dateFormat;\n            }\n            _.bindAll(this, 'updateActive');\n\n            this._super()\n                .initChips()\n                .cancel();\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Filters} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track({\n                    active: [],\n                    previews: []\n                });\n\n            return this;\n        },\n\n        /**\n         * Initializes chips component.\n         *\n         * @returns {Filters} Chainable.\n         */\n        initChips: function () {\n            layout([this.chipsConfig]);\n\n            this.chips('insertChild', this.name);\n\n            return this;\n        },\n\n        /**\n         * Called when another element was added to filters collection.\n         *\n         * @returns {Filters} Chainable.\n         */\n        initElement: function (elem) {\n            this._super();\n\n            elem.on('elems', this.updateActive);\n\n            this.updateActive();\n\n            return this;\n        },\n\n        /**\n         * Clears filters data.\n         *\n         * @param {Object} [filter] - If provided, then only specified\n         *      filter will be cleared. Otherwise, clears all data.\n         * @returns {Filters} Chainable.\n         */\n        clear: function (filter) {\n            filter ?\n                filter.clear() :\n                _.invoke(this.active, 'clear');\n\n            this.apply();\n\n            return this;\n        },\n\n        /**\n         * Sets filters data to the applied state.\n         *\n         * @returns {Filters} Chainable.\n         */\n        apply: function () {\n            if (typeof $('body').notification === 'function') {\n                $('body').notification('clear');\n            }\n            this.set('applied', removeEmpty(this.filters));\n            return this;\n        },\n\n        /**\n         * Resets filters to the last applied state.\n         *\n         * @returns {Filters} Chainable.\n         */\n        cancel: function () {\n            this.set('filters', utils.copy(this.applied));\n\n            return this;\n        },\n\n        /**\n         * Sets provided data to filter components (without applying it).\n         *\n         * @param {Object} data - Filters data.\n         * @param {Boolean} [partial=false] - Flag that defines whether\n         *      to completely replace current filters data or to extend it.\n         * @returns {Filters} Chainable.\n         */\n        setData: function (data, partial) {\n            var filters = partial ? this.filters : {};\n\n            data = utils.extend({}, filters, data);\n\n            this.set('filters', data);\n\n            return this;\n        },\n\n        /**\n         * Creates instance of a filter associated with the provided column.\n         *\n         * @param {Column} column - Column component for which to create a filter.\n         * @returns {Filters} Chainable.\n         */\n        addFilter: function (column) {\n            var index       = column.index,\n                processed   = this._processed,\n                filter;\n\n            if (!column.filter || _.contains(processed, index)) {\n                return this;\n            }\n\n            filter = this.buildFilter(column);\n\n            processed.push(index);\n\n            layout([filter]);\n\n            return this;\n        },\n\n        /**\n         * Creates filter component configuration associated with the provided column.\n         *\n         * @param {Column} column - Column component with a basic filter declaration.\n         * @returns {Object} Filters' configuration.\n         */\n        buildFilter: function (column) {\n            var filters = this.templates.filters,\n                filter  = column.filter,\n                type    = filters[filter.filterType];\n\n            if (_.isObject(filter) && type) {\n                filter = utils.extend({}, type, filter);\n            } else if (_.isString(filter)) {\n                filter = filters[filter];\n            }\n\n            filter = utils.extend({}, filters.base, filter);\n            //Accepting labels as is.\n            filter.__disableTmpl = {\n                label: 1,\n                options: 1\n            };\n\n            filter = utils.template(filter, {\n                filters: this,\n                column: column\n            }, true, true);\n\n            filter.__disableTmpl = {\n                label: true\n            };\n\n            return filter;\n        },\n\n        /**\n         * Returns an array of range filters.\n         *\n         * @returns {Array}\n         */\n        getRanges: function () {\n            return this.elems.filter(function (filter) {\n                return filter.isRange;\n            });\n        },\n\n        /**\n         * Returns an array of non-range filters.\n         *\n         * @returns {Array}\n         */\n        getPlain: function () {\n            return this.elems.filter(function (filter) {\n                return !filter.isRange;\n            });\n        },\n\n        /**\n         * Tells wether specified filter should be visible.\n         *\n         * @param {Object} filter\n         * @returns {Boolean}\n         */\n        isFilterVisible: function (filter) {\n            return filter.visible() || this.isFilterActive(filter);\n        },\n\n        /**\n         * Checks if specified filter is active.\n         *\n         * @param {Object} filter\n         * @returns {Boolean}\n         */\n        isFilterActive: function (filter) {\n            return _.contains(this.active, filter);\n        },\n\n        /**\n         * Checks if collection has visible filters.\n         *\n         * @returns {Boolean}\n         */\n        hasVisible: function () {\n            return this.elems.some(this.isFilterVisible, this);\n        },\n\n        /**\n         * Finds filters with a not empty data\n         * and sets them to the 'active' filters array.\n         *\n         * @returns {Filters} Chainable.\n         */\n        updateActive: function () {\n            var applied = _.keys(this.applied);\n\n            this.active = this.elems.filter(function (elem) {\n                return _.contains(applied, elem.index);\n            });\n\n            return this;\n        },\n\n        /**\n         * Returns number of applied filters.\n         *\n         * @returns {Number}\n         */\n        countActive: function () {\n            return this.active.length;\n        },\n\n        /**\n         * Extract previews of a specified filters.\n         *\n         * @param {Array} filters - Filters to be processed.\n         * @returns {Filters} Chainable.\n         */\n        updatePreviews: function (filters) {\n            var previews = filters.map(extractPreview);\n\n            this.previews = _.compact(previews);\n\n            return this;\n        },\n\n        /**\n         * Listener of the columns provider children array changes.\n         *\n         * @param {Array} columns - Current columns list.\n         */\n        onColumnsUpdate: function (columns) {\n            columns.forEach(this.addFilter, this);\n        },\n\n        /**\n         * Provider ajax error listener.\n         *\n         * @param {bool} isError - Selected index of the filter.\n         */\n        onBackendError: function (isError) {\n            var defaultMessage = 'Something went wrong with processing the default view and we have restored the ' +\n                    'filter to its original state.',\n                customMessage  = 'Something went wrong with processing current custom view and filters have been ' +\n                    'reset to its original state. Please edit filters then click apply.';\n\n            if (isError) {\n                this.clear();\n\n                $('body').notification('clear')\n                    .notification('add', {\n                        error: true,\n                        message: $.mage.__(this.bookmarksActiveIndex !== 'default' ? customMessage : defaultMessage),\n\n                        /**\n                         * @param {String} message\n                         */\n                        insertMethod: function (message) {\n                            var $wrapper = $('<div></div>').html(message);\n\n                            $('.page-main-actions').after($wrapper);\n                        }\n                    });\n            }\n        }\n    });\n});\n","Magento_Ui/js/grid/filters/range.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiLayout',\n    'mageUtils',\n    'Magento_Ui/js/form/components/group',\n    'mage/translate'\n], function (_, layout, utils, Group, $t) {\n    'use strict';\n\n    return Group.extend({\n        defaults: {\n            template: 'ui/grid/filters/elements/group',\n            isRange: true,\n            templates: {\n                base: {\n                    parent: '${ $.$data.group.name }',\n                    provider: '${ $.$data.group.provider }',\n                    template: 'ui/grid/filters/field'\n                },\n                date: {\n                    component: 'Magento_Ui/js/form/element/date',\n                    dateFormat: 'MM/dd/YYYY',\n                    shiftedValue: 'filter'\n                },\n                datetime: {\n                    component: 'Magento_Ui/js/form/element/date',\n                    dateFormat: 'MM/dd/YYYY',\n                    shiftedValue: 'filter',\n                    options: {\n                        showsTime: true\n                    }\n                },\n                text: {\n                    component: 'Magento_Ui/js/form/element/abstract'\n                },\n                ranges: {\n                    from: {\n                        label: $t('from'),\n                        dataScope: 'from'\n                    },\n                    to: {\n                        label: $t('to'),\n                        dataScope: 'to'\n                    }\n                }\n            }\n        },\n\n        /**\n         * Initializes range component.\n         *\n         * @returns {Range} Chainable.\n         */\n        initialize: function (config) {\n            if (config.dateFormat) {\n                this.constructor.defaults.templates.date.pickerDefaultDateFormat = config.dateFormat;\n            }\n            this._super()\n                .initChildren();\n\n            return this;\n        },\n\n        /**\n         * Creates instances of child components.\n         *\n         * @returns {Range} Chainable.\n         */\n        initChildren: function () {\n            var children = this.buildChildren();\n\n            layout(children);\n\n            return this;\n        },\n\n        /**\n         * Creates configuration for the child components.\n         *\n         * @returns {Object}\n         */\n        buildChildren: function () {\n            var templates   = this.templates,\n                typeTmpl    = templates[this.rangeType],\n                tmpl        = utils.extend({}, templates.base, typeTmpl),\n                children    = {};\n\n            _.each(templates.ranges, function (range, key) {\n                children[key] = utils.extend({}, tmpl, range);\n            });\n\n            return utils.template(children, {\n                group: this\n            }, true, true);\n        },\n\n        /**\n         * Clears childrens data.\n         *\n         * @returns {Range} Chainable.\n         */\n        clear: function () {\n            this.elems.each('clear');\n\n            return this;\n        },\n\n        /**\n         * Checks if some children has data.\n         *\n         * @returns {Boolean}\n         */\n        hasData: function () {\n            return this.elems.some('hasData');\n        }\n    });\n});\n","Magento_Ui/js/grid/filters/elements/ui-select.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Ui/js/form/element/ui-select',\n    'jquery',\n    'underscore'\n], function (Select, $, _) {\n    'use strict';\n\n    return Select.extend({\n        defaults: {\n            bookmarkProvider: 'ns = ${ $.ns }, index = bookmarks',\n            filterChipsProvider: 'componentType = filters, ns = ${ $.ns }',\n            validationUrl: false,\n            loadedOption: [],\n            validationLoading: true,\n            imports: {\n                applied: '${ $.filterChipsProvider }:applied',\n                activeIndex: '${ $.bookmarkProvider }:activeIndex'\n            },\n            modules: {\n                filterChips: '${ $.filterChipsProvider }'\n            },\n            listens: {\n                activeIndex: 'validateInitialValue',\n                applied: 'validateInitialValue'\n            }\n\n        },\n\n        /**\n         * Initializes UiSelect component.\n         *\n         * @returns {UiSelect} Chainable.\n         */\n        initialize: function () {\n            this._super();\n\n            this.validateInitialValue();\n\n            return this;\n        },\n\n        /**\n         * Validate initial value actually exists\n         */\n        validateInitialValue: function () {\n            if (_.isEmpty(this.value())) {\n                this.validationLoading(false);\n\n                return;\n            }\n\n            $.ajax({\n                url: this.validationUrl,\n                type: 'GET',\n                dataType: 'json',\n                context: this,\n                data: {\n                    ids: this.value()\n                },\n\n                /** @param {Object} response */\n                success: function (response) {\n                    if (!_.isEmpty(response)) {\n                        this.options([]);\n                        this.success({\n                            options: response\n                        });\n                    }\n                    this.filterChips().updateActive();\n                },\n\n                /** set empty array if error occurs */\n                error: function () {\n                    this.options([]);\n                },\n\n                /** stop loader */\n                complete: function () {\n                    this.validationLoading(false);\n                    this.setCaption();\n                }\n            });\n        }\n    });\n});\n","Magento_Ui/js/grid/search/search.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiLayout',\n    'mage/translate',\n    'mageUtils',\n    'uiElement',\n    'jquery'\n], function (_, layout, $t, utils, Element, $) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            template: 'ui/grid/search/search',\n            placeholder: $t('Search by keyword'),\n            label: $t('Keyword'),\n            value: '',\n            keywordUpdated: false,\n            previews: [],\n            chipsProvider: 'componentType = filtersChips, ns = ${ $.ns }',\n            statefull: {\n                value: true\n            },\n            tracks: {\n                value: true,\n                previews: true,\n                inputValue: true,\n                focused: true,\n                keywordUpdated: true\n            },\n            imports: {\n                inputValue: 'value',\n                updatePreview: 'value',\n                focused: false\n            },\n            exports: {\n                value: '${ $.provider }:params.search',\n                keywordUpdated: '${ $.provider }:params.keywordUpdated'\n            },\n            modules: {\n                chips: '${ $.chipsProvider }'\n            }\n        },\n\n        /**\n         * Initializes search component.\n         *\n         * @returns {Search} Chainable.\n         */\n        initialize: function () {\n            var urlParams = window.location.href.slice(window.location.href.search('[\\&\\?](search=)')).split('&'),\n                searchTerm = [];\n\n            this._super()\n                .initChips();\n\n            if (urlParams[0]) {\n                searchTerm = urlParams[0].split('=');\n\n                if (searchTerm[1]) {\n                    this.apply(decodeURIComponent(searchTerm[1]));\n                }\n            }\n\n            return this;\n        },\n\n        /**\n         * Initializes chips component.\n         *\n         * @returns {Search} Chainbale.\n         */\n        initChips: function () {\n            this.chips('insertChild', this, 0);\n\n            return this;\n        },\n\n        /**\n         * Clears search.\n         *\n         * @returns {Search} Chainable.\n         */\n        clear: function () {\n            this.value = '';\n\n            return this;\n        },\n\n        /**\n         * Click To ScrollTop.\n         */\n        scrollTo: function ($data) {\n            $('html, body').animate({\n                scrollTop: 0\n            }, 'slow', function () {\n                $data.focused = false;\n                $data.focused = true;\n            });\n        },\n\n        /**\n         * Resets input value to the last applied state.\n         *\n         * @returns {Search} Chainable.\n         */\n        cancel: function () {\n            this.inputValue = this.value;\n\n            return this;\n        },\n\n        /**\n         * Applies search query.\n         *\n         * @param {String} [value=inputValue] - If not specified, then\n         *      value of the input field will be used.\n         * @returns {Search} Chainable.\n         */\n        apply: function (value) {\n            value = value || this.inputValue;\n\n            this.keywordUpdated = this.value !== value;\n            this.value = this.inputValue = value.trim();\n\n            return this;\n        },\n\n        /**\n         * Updates preview data.\n         *\n         * @returns {Search} Chainable.\n         */\n        updatePreview: function () {\n            var preview = [];\n\n            if (this.value) {\n                preview.push({\n                    elem: this,\n                    label: this.label,\n                    preview: this.value\n                });\n            }\n\n            this.previews = preview;\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/date.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'mageUtils',\n    'moment',\n    './column',\n    'underscore',\n    'moment-timezone-with-data'\n], function (utils, moment, Column, _) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            dateFormat: 'MMM d, YYYY h:mm:ss A',\n            calendarConfig: []\n        },\n\n        /**\n         * Overrides base method to normalize date format\n         *\n         * @returns {DateColumn} Chainable\n         */\n        initConfig: function () {\n            this._super();\n\n            this.dateFormat = utils.normalizeDate(this.dateFormat ? this.dateFormat : this.options.dateFormat);\n\n            return this;\n        },\n\n        /**\n         * Formats incoming date based on the 'dateFormat' property.\n         *\n         * @returns {String} Formatted date.\n         */\n        getLabel: function (value, format) {\n            var date;\n\n            if (this.storeLocale !== undefined) {\n                moment.locale(this.storeLocale, utils.extend({}, this.calendarConfig));\n            }\n\n            date = moment.utc(this._super());\n\n            if (!_.isUndefined(this.timezone) && moment.tz.zone(this.timezone) !== null) {\n                date = date.tz(this.timezone);\n            }\n\n            date = date.isValid() && value[this.index] ?\n                date.format(format || this.dateFormat) :\n                '';\n\n            return date;\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/column.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiRegistry',\n    'mageUtils',\n    'uiElement'\n], function (_, registry, utils, Element) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            headerTmpl: 'ui/grid/columns/text',\n            bodyTmpl: 'ui/grid/cells/text',\n            disableAction: false,\n            controlVisibility: true,\n            sortable: true,\n            sorting: false,\n            visible: true,\n            draggable: true,\n            fieldClass: {},\n            ignoreTmpls: {\n                fieldAction: true\n            },\n            statefull: {\n                visible: true,\n                sorting: true\n            },\n            imports: {\n                exportSorting: 'sorting'\n            },\n            listens: {\n                '${ $.provider }:params.sorting.field': 'onSortChange'\n            },\n            modules: {\n                source: '${ $.provider }'\n            }\n        },\n\n        /**\n         * Initializes column component.\n         *\n         * @returns {Column} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .initFieldClass();\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Column} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track([\n                    'visible',\n                    'sorting',\n                    'disableAction'\n                ])\n                .observe([\n                    'dragging'\n                ]);\n\n            return this;\n        },\n\n        /**\n         * Extends list of field classes.\n         *\n         * @returns {Column} Chainable.\n         */\n        initFieldClass: function () {\n            _.extend(this.fieldClass, {\n                _dragging: this.dragging\n            });\n\n            return this;\n        },\n\n        /**\n         * Applies specified stored state of a column or one of its' properties.\n         *\n         * @param {String} state - Defines what state should be used: saved or default.\n         * @param {String} [property] - Defines what columns' property should be applied.\n         *      If not specified, then all columns stored properties will be used.\n         * @returns {Column} Chainable.\n         */\n        applyState: function (state, property) {\n            var namespace = this.storageConfig.root;\n\n            if (property) {\n                namespace += '.' + property;\n            }\n\n            this.storage('applyStateOf', state, namespace);\n\n            return this;\n        },\n\n        /**\n         * Sets columns' sorting. If column is currently sorted,\n         * than its' direction will be toggled.\n         *\n         * @param {*} [enable=true] - If false, than sorting will\n         *      be removed from a column.\n         * @returns {Column} Chainable.\n         */\n        sort: function (enable) {\n            if (!this.sortable) {\n                return this;\n            }\n\n            enable !== false ?\n                this.toggleSorting() :\n                this.sorting = false;\n\n            return this;\n        },\n\n        /**\n         * Sets descending columns' sorting.\n         *\n         * @returns {Column} Chainable.\n         */\n        sortDescending: function () {\n            if (this.sortable) {\n                this.sorting = 'desc';\n            }\n\n            return this;\n        },\n\n        /**\n         * Sets ascending columns' sorting.\n         *\n         * @returns {Column} Chainable.\n         */\n        sortAscending: function () {\n            if (this.sortable) {\n                this.sorting = 'asc';\n            }\n\n            return this;\n        },\n\n        /**\n         * Toggles sorting direction.\n         *\n         * @returns {Column} Chainable.\n         */\n        toggleSorting: function () {\n            this.sorting === 'asc' ?\n                this.sortDescending() :\n                this.sortAscending();\n\n            return this;\n        },\n\n        /**\n         * Checks if column is sorted.\n         *\n         * @returns {Boolean}\n         */\n        isSorted: function () {\n            return !!this.sorting;\n        },\n\n        /**\n         * Exports sorting data to the dataProvider if\n         * sorting of a column is enabled.\n         */\n        exportSorting: function () {\n            if (!this.sorting) {\n                return;\n            }\n\n            this.source('set', 'params.sorting', {\n                field: this.index,\n                direction: this.sorting\n            });\n        },\n\n        /**\n         * Checks if column has an assigned action that will\n         * be performed when clicking on one of its' fields.\n         *\n         * @returns {Boolean}\n         */\n        hasFieldAction: function () {\n            return !!this.fieldAction || !!this.fieldActions;\n        },\n\n        /**\n         * Applies action described in a 'fieldAction' property\n         * or actions described in 'fieldActions' property.\n         *\n         * @param {Number} rowIndex - Index of a row which initiates action.\n         * @returns {Column} Chainable.\n         *\n         * @example Example of fieldAction definition, which is equivalent to\n         *      referencing to external component named 'listing.multiselect'\n         *      and calling its' method 'toggleSelect' with params [rowIndex, true] =>\n         *\n         *      {\n         *          provider: 'listing.multiselect',\n         *          target: 'toggleSelect',\n         *          params: ['${ $.$data.rowIndex }', true]\n         *      }\n         */\n        applyFieldAction: function (rowIndex) {\n            if (!this.hasFieldAction() || this.disableAction) {\n                return this;\n            }\n\n            if (this.fieldActions) {\n                this.fieldActions.forEach(this.applySingleAction.bind(this, rowIndex), this);\n            } else {\n                this.applySingleAction(rowIndex);\n            }\n\n            return this;\n        },\n\n        /**\n         * Applies single action\n         *\n         * @param {Number} rowIndex - Index of a row which initiates action.\n         * @param {Object} action - Action (fieldAction) to be applied\n         *\n         */\n        applySingleAction: function (rowIndex, action) {\n            var callback;\n\n            action = action || this.fieldAction;\n            action = utils.template(action, {\n                column: this,\n                rowIndex: rowIndex\n            }, true);\n\n            callback = this._getFieldCallback(action);\n\n            if (_.isFunction(callback)) {\n                callback();\n            }\n        },\n\n        /**\n         * Returns field action handler if it was specified.\n         *\n         * @param {Object} record - Record object with which action is associated.\n         * @returns {Function|Undefined}\n         */\n        getFieldHandler: function (record) {\n            if (this.hasFieldAction()) {\n                return this.applyFieldAction.bind(this, record._rowIndex);\n            }\n        },\n\n        /**\n         * Creates action callback based on its' data.\n         *\n         * @param {Object} action - Actions' object.\n         * @returns {Function|Boolean} Callback function or false\n         *      value if it was impossible create a callback.\n         */\n        _getFieldCallback: function (action) {\n            var args     = action.params || [],\n                callback = action.target;\n\n            if (action.provider && action.target) {\n                args.unshift(action.target);\n\n                callback = registry.async(action.provider);\n            }\n\n            if (!_.isFunction(callback)) {\n                return false;\n            }\n\n            return function () {\n                callback.apply(callback, args);\n            };\n        },\n\n        /**\n         * Ment to preprocess data associated with a current columns' field.\n         *\n         * @param {Object} record - Data to be preprocessed.\n         * @returns {String}\n         */\n        getLabel: function (record) {\n            return record[this.index];\n        },\n\n        /**\n         * UnsanitizedHtml version of getLabel.\n         *\n         * @param {Object} record - Data to be preprocessed.\n         * @returns {String}\n         */\n        getLabelUnsanitizedHtml: function (record) {\n            return this.getLabel(record);\n        },\n\n        /**\n         * Returns list of classes that should be applied to a field.\n         *\n         * @returns {Object}\n         */\n        getFieldClass: function () {\n            return this.fieldClass;\n        },\n\n        /**\n         * Returns path to the columns' header template.\n         *\n         * @returns {String}\n         */\n        getHeader: function () {\n            return this.headerTmpl;\n        },\n\n        /**\n         * Returns path to the columns' body template.\n         *\n         * @returns {String}\n         */\n        getBody: function () {\n            return this.bodyTmpl;\n        },\n\n        /**\n         * Listener of the providers' sorting state changes.\n         *\n         * @param {Srting} field - Field by which current sorting is performed.\n         */\n        onSortChange: function (field) {\n            if (field !== this.index) {\n                this.sort(false);\n            }\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/actions.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    './column',\n    'Magento_Ui/js/modal/confirm',\n    'mage/dataPost'\n], function (_, utils, registry, Column, confirm, dataPost) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            bodyTmpl: 'ui/grid/cells/actions',\n            sortable: false,\n            draggable: false,\n            actions: [],\n            rows: [],\n            rowsProvider: '${ $.parentName }',\n            fieldClass: {\n                'data-grid-actions-cell': true\n            },\n            templates: {\n                actions: {}\n            },\n            imports: {\n                rows: '${ $.rowsProvider }:rows'\n            },\n            listens: {\n                rows: 'updateActions'\n            }\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {ActionsColumn} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .track('actions');\n\n            return this;\n        },\n\n        /**\n         * Returns specific action of a specified row\n         * or all action objects associated with it.\n         *\n         * @param {Number} rowIndex - Index of a row.\n         * @param {String} [actionIndex] - Action identifier.\n         * @returns {Array|Object}\n         */\n        getAction: function (rowIndex, actionIndex) {\n            var rowActions = this.actions[rowIndex];\n\n            return rowActions && actionIndex ?\n                rowActions[actionIndex] :\n                rowActions;\n        },\n\n        /**\n         * Returns visible actions for a specified row.\n         *\n         * @param {Number} rowIndex - Index of a row.\n         * @returns {Array} Visible actions.\n         */\n        getVisibleActions: function (rowIndex) {\n            var rowActions = this.getAction(rowIndex);\n\n            return _.filter(rowActions, this.isActionVisible, this);\n        },\n\n        /**\n         * Adds new action. If an action with the specified identifier\n         * already exists, then the original will be overridden.\n         *\n         * @param {String} index - Actions' identifier.\n         * @param {Object} action - Actions' data.\n         * @returns {ActionsColumn} Chainable.\n         */\n        addAction: function (index, action) {\n            var actionTmpls = this.templates.actions;\n\n            actionTmpls[index] = action;\n\n            this.updateActions();\n\n            return this;\n        },\n\n        /**\n         * Recreates actions for each row.\n         *\n         * @returns {ActionsColumn} Chainable.\n         */\n        updateActions: function () {\n            this.actions = this.rows.map(this._formatActions, this);\n\n            return this;\n        },\n\n        /**\n         * Processes actions, setting additional information to them and\n         * evaluating their properties as string templates.\n         *\n         * @private\n         * @param {Object} row - Row object.\n         * @param {Number} rowIndex - Index of a row.\n         * @returns {Array}\n         */\n        _formatActions: function (row, rowIndex) {\n            var rowActions      = row[this.index] || {},\n                recordId        = row[this.indexField],\n                customActions   = this.templates.actions;\n\n            /**\n             * Actions iterator.\n             */\n            function iterate(action, index) {\n                action = utils.extend({\n                    index: index,\n                    rowIndex: rowIndex,\n                    recordId: recordId\n                }, action);\n\n                return utils.template(action, row, true);\n            }\n\n            rowActions      = _.mapObject(rowActions, iterate);\n            customActions   = _.map(customActions, iterate);\n\n            customActions.forEach(function (action) {\n                rowActions[action.index] = action;\n            });\n\n            return rowActions;\n        },\n\n        /**\n         * Applies specified action.\n         *\n         * @param {String} actionIndex - Actions' identifier.\n         * @param {Number} rowIndex - Index of a row.\n         * @returns {ActionsColumn} Chainable.\n         */\n        applyAction: function (actionIndex, rowIndex) {\n            var action = this.getAction(rowIndex, actionIndex),\n                callback = this._getCallback(action);\n\n            action.confirm ?\n                this._confirm(action, callback) :\n                callback();\n\n            return this;\n        },\n\n        /**\n         * Creates handler for the provided action if it's required.\n         *\n         * @param {Object} action - Action object.\n         * @returns {Function|Undefined}\n         */\n        getActionHandler: function (action) {\n            var index = action.index,\n                rowIndex = action.rowIndex;\n\n            if (this.isHandlerRequired(index, rowIndex)) {\n                return this.applyAction.bind(this, index, rowIndex);\n            }\n        },\n\n        /**\n         * Returns target of action if it's been set.\n         *\n         * @param {Object} action - Action object.\n         * @returns {String}\n         */\n        getTarget: function (action) {\n            if (action.target) {\n                return action.target;\n            }\n\n            return '_self';\n        },\n\n        /**\n         * Checks if specified action requires a handler function.\n         *\n         * @param {String} actionIndex - Actions' identifier.\n         * @param {Number} rowIndex - Index of a row.\n         * @returns {Boolean}\n         */\n        isHandlerRequired: function (actionIndex, rowIndex) {\n            var action = this.getAction(rowIndex, actionIndex);\n\n            return _.isObject(action.callback) || action.confirm || !action.href;\n        },\n\n        /**\n         * Creates action callback based on it's data. If the action doesn't specify\n         * a callback function than the default one will be used.\n         *\n         * @private\n         * @param {Object} action - Action's object.\n         * @returns {Function} Callback function.\n         */\n        _getCallback: function (action) {\n            var args = [action.index, action.recordId, action],\n                callback = action.callback;\n\n            if (utils.isObject(callback)) {\n                args.unshift(callback.target);\n\n                callback = registry.async(callback.provider);\n            } else if (_.isArray(callback)) {\n                return this._getCallbacks(action);\n            } else if (!_.isFunction(callback)) {\n                callback = this.defaultCallback.bind(this);\n            }\n\n            return function () {\n                callback.apply(callback, args);\n            };\n        },\n\n        /**\n         * Creates action callback for multiple actions.\n         *\n         * @private\n         * @param {Object} action - Action's object.\n         * @returns {Function} Callback function.\n         */\n        _getCallbacks: function (action) {\n            var callback = action.callback,\n                callbacks = [],\n                tmpCallback;\n\n            _.each(callback, function (cb) {\n                tmpCallback = {\n                    action: registry.async(cb.provider),\n                    args: _.compact([cb.target, cb.params])\n                };\n                callbacks.push(tmpCallback);\n            });\n\n            return function () {\n                _.each(callbacks, function (cb) {\n                    cb.action.apply(cb.action, cb.args);\n                });\n            };\n        },\n\n        /**\n         * Default action callback. Redirects to\n         * the specified in action's data url.\n         *\n         * @param {String} actionIndex - Action's identifier.\n         * @param {(Number|String)} recordId - Id of the record associated\n         *      with a specified action.\n         * @param {Object} action - Action's data.\n         */\n        defaultCallback: function (actionIndex, recordId, action) {\n            if (action.post) {\n                dataPost().postData({\n                    action: action.href,\n                    data: {}\n                });\n            } else {\n                window.location.href = action.href;\n            }\n        },\n\n        /**\n         * Shows actions' confirmation window.\n         *\n         * @param {Object} action - Action's data.\n         * @param {Function} callback - Callback that will be\n         *      invoked if action is confirmed.\n         */\n        _confirm: function (action, callback) {\n            var confirmData = action.confirm;\n\n            confirm({\n                title: confirmData.title,\n                content: confirmData.message,\n                actions: {\n                    confirm: callback\n                }\n            });\n        },\n\n        /**\n         * Checks if row has only one visible action.\n         *\n         * @param {Number} rowIndex - Row index.\n         * @returns {Boolean}\n         */\n        isSingle: function (rowIndex) {\n            return this.getVisibleActions(rowIndex).length === 1;\n        },\n\n        /**\n         * Checks if row has more than one visible action.\n         *\n         * @param {Number} rowIndex - Row index.\n         * @returns {Boolean}\n         */\n        isMultiple: function (rowIndex) {\n            return this.getVisibleActions(rowIndex).length > 1;\n        },\n\n        /**\n         * Checks if action should be displayed.\n         *\n         * @param {Object} action - Action object.\n         * @returns {Boolean}\n         */\n        isActionVisible: function (action) {\n            return action.hidden !== true;\n        },\n\n        /**\n         * Overrides base method, because this component\n         * can't have global field action.\n         *\n         * @returns {Boolean} False.\n         */\n        hasFieldAction: function () {\n            return false;\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/thumbnail.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    './column',\n    'jquery',\n    'mage/template',\n    'text!Magento_Ui/templates/grid/cells/thumbnail/preview.html',\n    'underscore',\n    'Magento_Ui/js/modal/modal',\n    'mage/translate'\n], function (Column, $, mageTemplate, thumbnailPreviewTemplate, _) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            bodyTmpl: 'ui/grid/cells/thumbnail',\n            fieldClass: {\n                'data-grid-thumbnail-cell': true\n            }\n        },\n\n        /**\n         * Get image source data per row.\n         *\n         * @param {Object} row\n         * @returns {String}\n         */\n        getSrc: function (row) {\n            return row[this.index + '_src'];\n        },\n\n        /**\n         * Get original image source data per row.\n         *\n         * @param {Object} row\n         * @returns {String}\n         */\n        getOrigSrc: function (row) {\n            return row[this.index + '_orig_src'];\n        },\n\n        /**\n         * Get link data per row.\n         *\n         * @param {Object} row\n         * @returns {String}\n         */\n        getLink: function (row) {\n            return row[this.index + '_link'];\n        },\n\n        /**\n         * Get alternative text data per row.\n         *\n         * @param {Object} row\n         * @returns {String}\n         */\n        getAlt: function (row) {\n            return _.escape(row[this.index + '_alt']);\n        },\n\n        /**\n         * Check if preview available.\n         *\n         * @returns {Boolean}\n         */\n        isPreviewAvailable: function () {\n            return this['has_preview'] || false;\n        },\n\n        /**\n         * Build preview.\n         *\n         * @param {Object} row\n         */\n        preview: function (row) {\n            var modalHtml = mageTemplate(\n                    thumbnailPreviewTemplate,\n                    {\n                        src: this.getOrigSrc(row), alt: this.getAlt(row), link: this.getLink(row),\n                        linkText: $.mage.__('Go to Details Page')\n                    }\n                ),\n                previewPopup = $('<div></div>').html(modalHtml);\n\n            previewPopup.modal({\n                title: this.getAlt(row),\n                innerScroll: true,\n                modalClass: '_image-box',\n                buttons: []\n            }).trigger('openModal');\n        },\n\n        /**\n         * Get field handler per row.\n         *\n         * @param {Object} row\n         * @returns {Function}\n         */\n        getFieldHandler: function (row) {\n            if (this.isPreviewAvailable()) {\n                return this.preview.bind(this, row);\n            }\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/image.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'Magento_Ui/js/grid/columns/column'\n], function (Column) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            bodyTmpl: 'ui/grid/columns/image',\n            modules: {\n                masonry: '${ $.parentName }',\n                previewComponent: '${ $.parentName }.preview'\n            },\n            previewRowId: null,\n            previewHeight: 0,\n            fields: {\n                id: 'id',\n                url: 'url'\n            }\n        },\n\n        /**\n         * Init observable variables\n         * @return {Object}\n         */\n        initObservable: function () {\n            this._super()\n                .observe([\n                    'previewRowId',\n                    'previewHeight'\n                ]);\n\n            return this;\n        },\n\n        /**\n         * Updates styles when image loaded.\n         *\n         * @param {Object} record\n         */\n        updateStyles: function (record) {\n            !record.lastInRow || this.masonry().updateStyles();\n        },\n\n        /**\n         * Returns url to given record.\n         *\n         * @param {Object} record - Data to be preprocessed.\n         * @returns {String}\n         */\n        getUrl: function (record) {\n            return record[this.fields.url];\n        },\n\n        /**\n         * Returns id to given record.\n         *\n         * @param {Object} record - Data to be preprocessed.\n         * @returns {Number}\n         */\n        getId: function (record) {\n            return record[this.fields.id];\n        },\n\n        /**\n         * Returns container styles to given record.\n         *\n         * @param {Object} record - Data to be preprocessed.\n         * @returns {Object}\n         */\n        getStyles: function (record) {\n            var styles = record.styles();\n\n            styles['margin-bottom'] = this.previewRowId() === record.rowNumber ? this.previewHeight : 0;\n            record.styles(styles);\n\n            return record.styles;\n        },\n\n        /**\n         * Returns class list to given record.\n         *\n         * @param {Object} record - Data to be preprocessed.\n         * @returns {Object}\n         */\n        getClasses: function (record) {\n            return record.css || {};\n        },\n\n        /**\n         * Get is active record\n         *\n         * @param {Object} record - Data to be preprocessed.\n         *\n         * @returns {Boolean}\n         */\n        getIsActive: function (record) {\n            return this.previewComponent().visibleRecord() === record._rowIndex || false;\n        },\n\n        /**\n         * Expand image preview\n         */\n        expandPreview: function (record) {\n            this.previewComponent().show(record);\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/link.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    './column',\n    'mageUtils'\n], function (Column, utils) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            link: 'link',\n            bodyTmpl: 'ui/grid/cells/link'\n        },\n\n        /**\n         * Returns link to given record.\n         *\n         * @param {Object} record - Data to be preprocessed.\n         * @returns {String}\n         */\n        getLink: function (record) {\n            return utils.nested(record, this.link);\n        },\n\n        /**\n         * Check if link parameter exist in record.\n         * @param {Object} record - Data to be preprocessed.\n         * @returns {Boolean}\n         */\n        isLink: function (record) {\n            return !!utils.nested(record, this.link);\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/onoff.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    'mage/translate',\n    './multiselect',\n    'uiRegistry'\n], function (_, $t, Column, registry) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            headerTmpl: 'ui/grid/columns/onoff',\n            bodyTmpl: 'ui/grid/cells/onoff',\n            fieldClass: {\n                'admin__scope-old': true,\n                'data-grid-onoff-cell': true,\n                'data-grid-checkbox-cell': false\n            },\n            imports: {\n                selectedData: '${ $.provider }:data.selectedData'\n            },\n            listens: {\n                '${ $.provider }:reloaded': 'setDefaultSelections'\n            }\n        },\n\n        /**\n         * @param {Number} id\n         * @returns {*}\n         */\n        getLabel: function (id) {\n            return this.selected.indexOf(id) !== -1 ? $t('On') : $t('Off');\n        },\n\n        /**\n         * Sets the ids for preselected elements\n         * @returns void\n         */\n        setDefaultSelections: function () {\n            var positionCacheValid = registry.get('position_cache_valid'),\n                selectedFromCache = registry.get('selected_cache'),\n                key,\n                i;\n\n            if (positionCacheValid && this.selected().length === 0) {\n                // Check selected data\n                selectedFromCache = JSON.parse(selectedFromCache);\n\n                for (i = 0; i < selectedFromCache.length; i++) {\n                    this.selected.push(selectedFromCache[i]);\n                }\n\n                registry.set('position_cache_valid', true);\n                registry.set('selected_cache', JSON.stringify(this.selected()));\n\n                return;\n            }\n\n            if (positionCacheValid && this.selected().length > 0) {\n                registry.set('position_cache_valid', true);\n                registry.set('selected_cache', JSON.stringify(this.selected()));\n\n                return;\n            }\n\n            if (this.selectedData.length === 0) {\n                registry.set('position_cache_valid', true);\n                registry.set('selected_cache', JSON.stringify([]));\n\n                return;\n            }\n\n            // Check selected data\n            for (key in this.selectedData) {\n                if (this.selectedData.hasOwnProperty(key) && this.selected().indexOf(key) === -1) {\n                    this.selected.push(key);\n                }\n            }\n            // Uncheck unselected data\n            for (i = 0; i < this.selected().length; i++) {\n                key = this.selected()[i];\n                this.selectedData.hasOwnProperty(key) || this.selected.splice(this.selected().indexOf(key), 1);\n                this.selectedData.hasOwnProperty(key) || i--;\n            }\n            registry.set('position_cache_valid', true);\n            registry.set('selected_cache', JSON.stringify(this.selected()));\n        },\n\n        /**\n         * Show/hide action in the massaction menu\n         * @param {Number} actionId\n         * @returns {Boolean}\n         */\n        isActionRelevant: function (actionId) {\n            var relevant = true;\n\n            switch (actionId) {\n                case 'selectPage':\n                    relevant = !this.isPageSelected(true);\n                    break;\n\n                case 'deselectPage':\n                    relevant =  this.isPageSelected();\n                    break;\n            }\n\n            return relevant;\n        },\n\n        /**\n         * Updates values of the 'allSelected'\n         * and 'indetermine' properties.\n         *\n         * @returns {Object} Chainable.\n         */\n        updateState: function () {\n            var positionCacheValid = registry.get('position_cache_valid'),\n                totalRecords    = this.totalRecords(),\n                selected        = this.selected().length,\n                excluded        = this.excluded().length,\n                totalSelected   = this.totalSelected(),\n                allSelected;\n\n            if (positionCacheValid && this.selected().length > 0) {\n                registry.set('position_cache_valid', true);\n                registry.set('selected_cache', JSON.stringify(this.selected()));\n            }\n\n            // When filters are enabled then totalRecords is unknown\n            if (this.getFiltering()) {\n                if (this.getFiltering().search !== '') {\n                    totalRecords = -1;\n                }\n            }\n\n            allSelected = totalRecords && totalSelected === totalRecords;\n\n            if (this.excludeMode()) {\n                if (excluded === totalRecords) {\n                    this.deselectAll();\n                }\n            } else if (totalRecords && selected === totalRecords) {\n                this.selectAll();\n            }\n\n            this.allSelected(allSelected);\n            this.indetermine(totalSelected && !allSelected);\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/overlay.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'Magento_Ui/js/grid/columns/column'\n], function (Column) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            bodyTmpl: 'ui/grid/columns/overlay'\n        },\n\n        /**\n         * If overlay should be visible\n         *\n         * @param {Object} row\n         * @returns {Boolean}\n         */\n        isVisible: function (row) {\n            return !!row[this.index];\n        },\n\n        /**\n         * Get overlay label\n         *\n         * @param {Object} row\n         * @returns {String}\n         */\n        getLabel: function (row) {\n            return row[this.index];\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/select.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    './column'\n], function (_, Column) {\n    'use strict';\n\n    return Column.extend({\n        /**\n         * Retrieves label associated with a provided value.\n         *\n         * @returns {String}\n         */\n        getLabel: function () {\n            var options = this.options || [],\n                values = this._super(),\n                label = [];\n\n            if (_.isString(values)) {\n                values = values.split(',');\n            }\n\n            if (!_.isArray(values)) {\n                values = [values];\n            }\n\n            values = values.map(function (value) {\n                return value + '';\n            });\n\n            options = this.flatOptions(options);\n\n            options.forEach(function (item) {\n                if (_.contains(values, item.value + '')) {\n                    label.push(item.label);\n                }\n            });\n\n            return label.join(', ');\n        },\n\n        /**\n         * Transformation tree options structure to liner array.\n         *\n         * @param {Array} options\n         * @returns {Array}\n         */\n        flatOptions: function (options) {\n            var self = this;\n\n            if (!_.isArray(options)) {\n                options = _.values(options);\n            }\n\n            return options.reduce(function (opts, option) {\n                if (_.isArray(option.value)) {\n                    opts = opts.concat(self.flatOptions(option.value));\n                } else {\n                    opts.push(option);\n                }\n\n                return opts;\n            }, []);\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/multiselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mage/translate',\n    './column'\n], function (_, $t, Column) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            headerTmpl: 'ui/grid/columns/multiselect',\n            bodyTmpl: 'ui/grid/cells/multiselect',\n            controlVisibility: false,\n            sortable: false,\n            draggable: false,\n            menuVisible: false,\n            excludeMode: false,\n            allSelected: false,\n            indetermine: false,\n            preserveSelectionsOnFilter: false,\n            disabled: [],\n            selected: [],\n            excluded: [],\n            fieldClass: {\n                'data-grid-checkbox-cell': true\n            },\n            actions: [{\n                value: 'selectAll',\n                label: $t('Select All')\n            }, {\n                value: 'deselectAll',\n                label: $t('Deselect All')\n            }, {\n                value: 'selectPage',\n                label: $t('Select All on This Page')\n            }, {\n                value: 'deselectPage',\n                label: $t('Deselect All on This Page')\n            }],\n\n            imports: {\n                totalRecords: '${ $.provider }:data.totalRecords',\n                showTotalRecords: '${ $.provider }:data.showTotalRecords',\n                rows: '${ $.provider }:data.items'\n            },\n\n            listens: {\n                '${ $.provider }:params.filters': 'onFilter',\n                '${ $.provider }:params.search': 'onSearch',\n                selected: 'onSelectedChange',\n                rows: 'onRowsChange'\n            },\n\n            modules: {\n                source: '${ $.provider }'\n            }\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Multiselect} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe([\n                    'disabled',\n                    'selected',\n                    'excluded',\n                    'excludeMode',\n                    'totalSelected',\n                    'allSelected',\n                    'indetermine',\n                    'totalRecords',\n                    'showTotalRecords',\n                    'rows'\n                ]);\n\n            return this;\n        },\n\n        /**\n         * Selects specified record.\n         *\n         * @param {*} id - See definition of 'getId' method.\n         * @param {Boolean} [isIndex=false] - See definition of 'getId' method.\n         * @returns {Multiselect} Chainable.\n         */\n        select: function (id, isIndex) {\n            this._setSelection(id, isIndex, true);\n\n            return this;\n        },\n\n        /**\n         * Deselects specified record.\n         *\n         * @param {*} id - See definition of 'getId' method.\n         * @param {Boolean} [isIndex=false] - See definition of 'getId' method.\n         * @returns {Multiselect} Chainable.\n         */\n        deselect: function (id, isIndex) {\n            this._setSelection(id, isIndex, false);\n\n            return this;\n        },\n\n        /**\n         * Toggles selection of a specified record.\n         *\n         * @param {*} id - See definition of 'getId' method.\n         * @param {Boolean} [isIndex=false] - See definition of 'getId' method.\n         * @returns {Multiselect} Chainable.\n         */\n        toggleSelect: function (id, isIndex) {\n            this._setSelection(id, isIndex, !this.isSelected(id, isIndex));\n\n            return this;\n        },\n\n        /**\n         * Checks if specified record is selected.\n         *\n         * @param {*} id - See definition of 'getId' method.\n         * @param {Boolean} [isIndex=false] - See definition of 'getId' method.\n         * @returns {Boolean}\n         */\n        isSelected: function (id, isIndex) {\n            id = this.getId(id, isIndex);\n\n            return this.selected.contains(id);\n        },\n\n        /**\n         * Selects/deselects specified record base on a 'select' parameter value.\n         *\n         * @param {*} id - See definition of 'getId' method.\n         * @param {Boolean} [isIndex=false] - See definition of 'getId' method.\n         * @param {Boolean} select - Whether to select/deselect record.\n         * @returns {Multiselect} Chainable.\n         */\n        _setSelection: function (id, isIndex, select) {\n            var selected = this.selected;\n\n            id = this.getId(id, isIndex);\n\n            if (!select && this.isSelected(id)) {\n                selected.remove(id);\n            } else if (select) {\n                selected.push(id);\n            }\n\n            return this;\n        },\n\n        /**\n         * Selects all records, even those that\n         * are not visible on the page.\n         *\n         * @returns {Multiselect} Chainable.\n         */\n        selectAll: function () {\n            this.excludeMode(true);\n\n            this.clearExcluded()\n                .selectPage();\n\n            return this;\n        },\n\n        /**\n         * Deselects all records.\n         *\n         * @returns {Multiselect} Chainable.\n         */\n        deselectAll: function () {\n            this.excludeMode(false);\n\n            this.clearExcluded();\n            this.selected.removeAll();\n\n            return this;\n        },\n\n        /**\n         * Selects or deselects all records.\n         *\n         * @returns {Multiselect} Chainable.\n         */\n        toggleSelectAll: function () {\n            this.allSelected() ?\n                this.deselectAll() :\n                this.selectAll();\n\n            return this;\n        },\n\n        /**\n         * Selects all records on the current page.\n         *\n         * @returns {Multiselect} Chainable.\n         */\n        selectPage: function () {\n            var selected = _.union(this.selected(), this.getIds());\n\n            selected = _.difference(selected, this.disabled());\n\n            this.selected(selected);\n\n            return this;\n        },\n\n        /**\n         * Deselects all records on the current page.\n         *\n         * @returns {Multiselect} Chainable.\n         */\n        deselectPage: function () {\n            var pageIds = this.getIds();\n\n            this.selected.remove(function (value) {\n                return !!~pageIds.indexOf(value);\n            });\n\n            return this;\n        },\n\n        /**\n        * Selects or deselects all records on the current page.\n        *\n        * @returns {Multiselect} Chainable.\n        */\n        togglePage: function () {\n            return this.isPageSelected() && !this.excluded().length ? this.deselectPage() : this.selectPage();\n        },\n\n        /**\n         * Clears the array of not selected records.\n         *\n         * @returns {Multiselect} Chainable.\n         */\n        clearExcluded: function () {\n            this.excluded.removeAll();\n\n            return this;\n        },\n\n        /**\n         * Retrieve all id's from available records.\n         *\n         * @param {Boolean} [exclude] - Whether to exclude not selected ids' from result.\n         * @returns {Array} An array of ids'.\n         */\n        getIds: function (exclude) {\n            var items = this.rows(),\n                ids = _.pluck(items, this.indexField);\n\n            return exclude ?\n                _.difference(ids, this.excluded()) :\n                ids;\n        },\n\n        /**\n         * Returns identifier of a record.\n         *\n         * @param {*} id - Id of a record or its' index in a rows array.\n         * @param {Boolean} [isIndex=false] - Flag that specifies with what\n         *      kind of identifier we are dealing with.\n         * @returns {*}\n         */\n        getId: function (id, isIndex) {\n            var record = this.rows()[id];\n\n            if (isIndex && record) {\n                id = record[this.indexField];\n            }\n\n            return id;\n        },\n\n        /**\n         * Recalculates list of the excluded records.\n         * Changes value of `excluded`.\n         *\n         * @param {Array} selected - List of the currently selected records.\n         * @returns {Multiselect} Chainable.\n         */\n        updateExcluded: function (selected) {\n            var excluded = this.excluded(),\n                fromPage = _.difference(this.getIds(), selected);\n\n            excluded = _.union(excluded, fromPage);\n            excluded = _.difference(excluded, selected);\n\n            this.excluded(excluded);\n\n            return this;\n        },\n\n        /**\n         * Calculates number of selected records and\n         * updates 'totalSelected' property.\n         *\n         * @returns {Multiselect} Chainable.\n         */\n        countSelected: function () {\n            var total = this.totalRecords(),\n                excluded = this.excluded().length,\n                selected = this.selected().length;\n\n            if (this.excludeMode()) {\n                selected = total - excluded;\n            }\n\n            this.totalSelected(selected);\n\n            return this;\n        },\n\n        /**\n         * Returns selected items on a current page.\n         *\n         * @returns {Array}\n         */\n        getPageSelections: function () {\n            var ids = this.getIds();\n\n            return this.selected.filter(function (id) {\n                return _.contains(ids, id);\n            });\n        },\n\n        /**\n         * Returns selections data.\n         *\n         * @returns {Object}\n         */\n        getSelections: function () {\n            return {\n                excluded: this.excluded(),\n                selected: this.selected(),\n                total: this.totalSelected(),\n                showTotalRecords: this.showTotalRecords(),\n                excludeMode: this.excludeMode(),\n                params: this.getFiltering()\n            };\n        },\n\n        /**\n         * Extracts filtering data from data provider.\n         *\n         * @returns {Object} Current filters state.\n         */\n        getFiltering: function () {\n            var source = this.source(),\n                keys = ['filters', 'search', 'namespace'];\n\n            if (!source) {\n                return {};\n            }\n\n            return _.pick(source.get('params'), keys);\n        },\n\n        /**\n         * Defines if provided select/deselect actions is relevant.\n         * E.g. there is no need in a 'select page' action if only one\n         * page is available.\n         *\n         * @param {String} actionId - Id of the action to be checked.\n         * @returns {Boolean}\n         */\n        isActionRelevant: function (actionId) {\n            var pageIds         = this.getIds().length,\n                multiplePages   = pageIds < this.totalRecords(),\n                relevant        = true;\n\n            switch (actionId) {\n                case 'selectPage':\n                    relevant = multiplePages && !this.isPageSelected(true);\n                    break;\n\n                case 'deselectPage':\n                    relevant =  multiplePages && this.isPageSelected();\n                    break;\n\n                case 'selectAll':\n                    relevant = !this.allSelected();\n                    break;\n\n                case 'deselectAll':\n                    relevant = this.totalSelected() > 0;\n            }\n\n            return relevant;\n        },\n\n        /**\n         * Checks if current page has selected records.\n         *\n         * @param {Boolean} [all=false] - If set to 'true' checks that every\n         *      record on the page is selected. Otherwise checks that\n         *      page has some selected records.\n         * @returns {Boolean}\n         */\n        isPageSelected: function (all) {\n            var pageIds = this.getIds(),\n                selected = this.selected(),\n                excluded = this.excluded(),\n                iterator = all ? 'every' : 'some';\n\n            if (this.allSelected()) {\n                return true;\n            }\n\n            if (this.excludeMode()) {\n                return pageIds[iterator](function (id) {\n                    return !~excluded.indexOf(id);\n                });\n            }\n\n            return pageIds[iterator](function (id) {\n                return !!~selected.indexOf(id);\n            });\n        },\n\n        /**\n         * Updates values of the 'allSelected'\n         * and 'indetermine' properties.\n         *\n         * @returns {Multiselect} Chainable.\n         */\n        updateState: function () {\n            var selected        = this.selected().length,\n                excluded        = this.excluded().length,\n                totalSelected   = this.totalSelected(),\n                totalRecords    = this.totalRecords(),\n                allSelected     = totalRecords && totalSelected === totalRecords;\n\n            if (this.excludeMode()) {\n                if (excluded === totalRecords && !this.preserveSelectionsOnFilter) {\n                    this.deselectAll();\n                }\n            } else if (totalRecords && selected === totalRecords && !this.preserveSelectionsOnFilter) {\n                this.selectAll();\n            }\n\n            this.allSelected(allSelected);\n            this.indetermine(totalSelected && !allSelected);\n\n            return this;\n        },\n\n        /**\n         * Overrides base method, because this component\n         * can't have global field action.\n         *\n         * @returns {Boolean} False.\n         */\n        hasFieldAction: function () {\n            return false;\n        },\n\n        /**\n         * Callback method to handle changes of selected items.\n         *\n         * @param {Array} selected - An array of currently selected items.\n         */\n        onSelectedChange: function (selected) {\n            this.updateExcluded(selected)\n                .countSelected()\n                .updateState();\n        },\n\n        /**\n         * Is invoked when rows has changed. Recalculates selected items\n         * based on \"selectMode\" property.\n         */\n        onRowsChange: function () {\n            var newSelections;\n\n            if (this.excludeMode()) {\n                newSelections = _.union(this.getIds(true), this.selected());\n\n                this.selected(newSelections);\n            }\n        },\n\n        /**\n         * Is invoked when filtration is applied or removed\n         */\n        onFilter: function () {\n            if (!this.preserveSelectionsOnFilter) {\n                this.deselectAll();\n            }\n        },\n\n        /**\n         * Is invoked when search is applied or removed\n         */\n        onSearch: function () {\n            this.onFilter();\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/expandable.js":"/**\n * Copyright \u00a9 2016 Magento. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    './column',\n    'underscore'\n], function (Column, _) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            bodyTmpl: 'ui/grid/cells/expandable',\n            tooltipTmpl: 'ui/grid/cells/expandable/content',\n            visibeItemsLimit: 5,\n            tooltipTitle: ''\n        },\n\n        /**\n         * Gets label from full options array.\n         *\n         * @param {Object} record - Record object.\n         * @returns {String}\n         */\n        getFullLabel: function (record) {\n            return this.getLabelsArray(record).join(', ');\n        },\n\n        /**\n         * Gets label from options array limited by 'visibeItemsLimit'.\n         *\n         * @param {Object} record - Record object.\n         * @returns {String}\n         */\n        getShortLabel: function (record) {\n            return this.getLabelsArray(record).slice(0, this.visibeItemsLimit).join(', ');\n        },\n\n        /**\n         * Extracts array of labels associated with provided values and sort it alphabetically.\n         *\n         * @param {Object} record - Record object.\n         * @returns {Array}\n         */\n        getLabelsArray: function (record) {\n            var values = this.getLabel(record),\n                options = this.options || [],\n                labels = [];\n\n            if (_.isString(values)) {\n                values = values.split(',');\n            }\n\n            if (!Array.isArray(values)) {\n                values = [values];\n            }\n\n            values = values.map(function (value) {\n                return value + '';\n            });\n\n            options = this.flatOptions(options);\n\n            options.forEach(function (item) {\n                if (_.contains(values, item.value + '')) {\n                    labels.push(item.label);\n                }\n            });\n\n            return labels.sort(\n                function (labelFirst, labelSecond) {\n                    return labelFirst.toLowerCase().localeCompare(labelSecond.toLowerCase());\n                }\n            );\n        },\n\n        /**\n         * Transformation tree options structure to liner array.\n         *\n         * @param {Array} options\n         * @returns {Array}\n         */\n        flatOptions: function (options) {\n            var self = this;\n\n            return options.reduce(function (opts, option) {\n                if (_.isArray(option.value)) {\n                    opts = opts.concat(self.flatOptions(option.value));\n                } else {\n                    opts.push(option);\n                }\n\n                return opts;\n            }, []);\n        },\n\n        /**\n         * Checks if amount of options is more than limit value.\n         *\n         * @param {Object} record - Data to be preprocessed.\n         * @returns {Boolean}\n         */\n        isExpandable: function (record) {\n            return this.getLabel(record).length > this.visibeItemsLimit;\n        }\n    });\n});\n","Magento_Ui/js/grid/columns/image-preview.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* eslint-disable no-undef */\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Ui/js/grid/columns/column',\n    'Magento_Ui/js/lib/key-codes'\n], function ($, _, Column, keyCodes) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            bodyTmpl: 'ui/grid/columns/image-preview',\n            previewImageSelector: '[data-image-preview]',\n            visibleRecord: null,\n            height: 0,\n            displayedRecord: {},\n            lastOpenedImage: false,\n            fields: {\n                previewUrl: 'preview_url',\n                title: 'title'\n            },\n            modules: {\n                masonry: '${ $.parentName }',\n                thumbnailComponent: '${ $.parentName }.thumbnail_url'\n            },\n            statefull: {\n                sorting: true,\n                lastOpenedImage: true\n            },\n            listens: {\n                '${ $.provider }:params.filters': 'hide',\n                '${ $.provider }:params.search': 'hide',\n                '${ $.provider }:params.paging': 'hide',\n                '${ $.provider }:data.items': 'updateDisplayedRecord'\n            },\n            exports: {\n                height: '${ $.parentName }.thumbnail_url:previewHeight'\n            }\n        },\n\n        /**\n         * Initialize image preview component\n         *\n         * @returns {Object}\n         */\n        initialize: function () {\n            this._super();\n            $(document).on('keydown', this.handleKeyDown.bind(this));\n\n            this.lastOpenedImage.subscribe(function (newValue) {\n\n                if (newValue === false && _.isNull(this.visibleRecord())) {\n                    return;\n                }\n\n                if (newValue === this.visibleRecord()) {\n                    return;\n                }\n\n                if (newValue === false) {\n                    this.hide();\n\n                    return;\n                }\n\n                this.show(this.masonry().rows()[newValue]);\n            }.bind(this));\n\n            return this;\n        },\n\n        /**\n         * Init observable variables\n         * @return {Object}\n         */\n        initObservable: function () {\n            this._super()\n                .observe([\n                    'visibleRecord',\n                    'height',\n                    'displayedRecord',\n                    'lastOpenedImage'\n                ]);\n\n            return this;\n        },\n\n        /**\n         * Next image preview\n         *\n         * @param {Object} record\n         */\n        next: function (record) {\n            var recordToShow;\n\n            if (record._rowIndex + 1 === this.masonry().rows().length) {\n                return;\n            }\n\n            recordToShow = this.getRecord(record._rowIndex + 1);\n            recordToShow.rowNumber = record.lastInRow ? record.rowNumber + 1 : record.rowNumber;\n            this.show(recordToShow);\n        },\n\n        /**\n         * Previous image preview\n         *\n         * @param {Object} record\n         */\n        prev: function (record) {\n            var recordToShow;\n\n            if (record._rowIndex === 0) {\n                return;\n            }\n            recordToShow = this.getRecord(record._rowIndex - 1);\n\n            recordToShow.rowNumber = record.firstInRow ? record.rowNumber - 1 : record.rowNumber;\n            this.show(recordToShow);\n        },\n\n        /**\n         * Get record\n         *\n         * @param {Integer} recordIndex\n         *\n         * @return {Object}\n         */\n        getRecord: function (recordIndex) {\n            return this.masonry().rows()[recordIndex];\n        },\n\n        /**\n         * Set selected row id\n         *\n         * @param {Number} rowId\n         * @private\n         */\n        _selectRow: function (rowId) {\n            this.thumbnailComponent().previewRowId(rowId);\n        },\n\n        /**\n         * Show image preview\n         *\n         * @param {Object} record\n         */\n        show: function (record) {\n            if (record._rowIndex === this.visibleRecord()) {\n                this.hide();\n\n                return;\n            }\n\n            this.hide();\n            this.displayedRecord(record);\n            this._selectRow(record.rowNumber || null);\n            this.visibleRecord(record._rowIndex);\n\n            this.lastOpenedImage(record._rowIndex);\n            this.updateImageData();\n        },\n\n        /**\n         * Update image data when image preview is opened\n         */\n        updateImageData: function () {\n            var img = $(this.previewImageSelector + ' img'), self;\n\n            if (!img.get(0)) {\n                setTimeout(function () {\n                    this.updateImageData();\n                }.bind(this), 100);\n            } else if (img.get(0).complete) {\n                this.updateHeight();\n                this.scrollToPreview();\n            } else {\n                self = this;\n\n                img.on('load', function () {\n                    self.updateHeight();\n                    self.scrollToPreview();\n                });\n            }\n        },\n\n        /**\n         * Update preview displayed record data from the new items data if the preview is expanded\n         *\n         * @param {Array} items\n         */\n        updateDisplayedRecord: function (items) {\n            if (!_.isNull(this.visibleRecord())) {\n                this.displayedRecord(items[this.visibleRecord()]);\n            }\n        },\n\n        /**\n         * Update image preview section height\n         */\n        updateHeight: function () {\n            this.height($(this.previewImageSelector).height() + 'px');\n        },\n\n        /**\n         * Close image preview\n         */\n        hide: function () {\n            this.lastOpenedImage(false);\n            this.visibleRecord(null);\n            this.height(0);\n            this._selectRow(null);\n        },\n\n        /**\n         * Returns visibility for given record.\n         *\n         * @param {Object} record\n         * @return {*|bool}\n         */\n        isVisible: function (record) {\n            if (this.lastOpenedImage() === record._rowIndex &&\n                this.visibleRecord() === null\n            ) {\n                this.show(record);\n            }\n\n            return this.visibleRecord() === record._rowIndex || false;\n        },\n\n        /**\n         * Returns preview image url for a given record.\n         *\n         * @param {Object} record\n         * @return {String}\n         */\n        getUrl: function (record) {\n            return record[this.fields.previewUrl];\n        },\n\n        /**\n         * Returns image title for a given record.\n         *\n         * @param {Object} record\n         * @return {String}\n         */\n        getTitle: function (record) {\n            return record[this.fields.title];\n        },\n\n        /**\n         * Get styles for preview\n         *\n         * @returns {Object}\n         */\n        getStyles: function () {\n            return {\n                'margin-top': '-' + this.height()\n            };\n        },\n\n        /**\n         * Scroll to preview window\n         */\n        scrollToPreview: function () {\n            $(this.previewImageSelector).get(0).scrollIntoView({\n                behavior: 'smooth',\n                block: 'center',\n                inline: 'nearest'\n            });\n        },\n\n        /**\n         * Handle keyboard navigation for image preview\n         *\n         * @param {Object} e\n         */\n        handleKeyDown: function (e) {\n            var key = keyCodes[e.keyCode];\n\n            if (this.visibleRecord() !== null && document.activeElement.tagName !== 'INPUT') {\n                if (key === 'pageLeftKey') {\n                    this.prev(this.displayedRecord());\n                } else if (key === 'pageRightKey') {\n                    this.next(this.displayedRecord());\n                }\n            }\n        }\n    });\n});\n","Magento_Ui/js/grid/cells/sanitizedHtml.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Ui/js/grid/columns/column',\n    'escaper'\n], function (Column, escaper) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            allowedTags: ['div', 'span', 'b', 'strong', 'i', 'em', 'u', 'a']\n        },\n\n        /**\n         * Name column.\n         *\n         * @param {String} label\n         * @returns {String}\n         */\n        getSafeHtml: function (label) {\n            return escaper.escapeHtml(label, this.allowedTags);\n        },\n\n        /**\n         * UnsanitizedHtml version of getSafeHtml.\n         *\n         * @param {String} label\n         * @returns {String}\n         */\n        getSafeUnsanitizedHtml: function (label) {\n            return this.getSafeHtml(label);\n        }\n    });\n});\n","Magento_Ui/js/grid/controls/columns.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    'mage/translate',\n    'uiCollection'\n], function (_, utils, $t, Collection) {\n    'use strict';\n\n    return Collection.extend({\n        defaults: {\n            template: 'ui/grid/controls/columns',\n            minVisible: 1,\n            maxVisible: 30,\n            viewportSize: 18,\n            displayArea: 'dataGridActions',\n            columnsProvider: 'ns = ${ $.ns }, componentType = columns',\n            imports: {\n                addColumns: '${ $.columnsProvider }:elems'\n            },\n            templates: {\n                headerMsg: $t('${ $.visible } out of ${ $.total } visible')\n            }\n        },\n\n        /**\n         * Resets columns visibility to theirs default state.\n         *\n         * @returns {Columns} Chainable.\n         */\n        reset: function () {\n            this.elems.each('applyState', 'default', 'visible');\n\n            return this;\n        },\n\n        /**\n         * Applies last saved state of columns visibility.\n         *\n         * @returns {Columns} Chainable.\n         */\n        cancel: function () {\n            this.elems.each('applyState', '', 'visible');\n\n            return this;\n        },\n\n        /**\n         * Adds columns whose visibility can be controlled to the component.\n         *\n         * @param {Array} columns - Elements array that will be added to component.\n         * @returns {Columns} Chainable.\n         */\n        addColumns: function (columns) {\n            columns = _.where(columns, {\n                controlVisibility: true\n            });\n\n            this.insertChild(columns);\n\n            return this;\n        },\n\n        /**\n         * Defines whether child elements array length\n         * is greater than the 'viewportSize' property.\n         *\n         * @returns {Boolean}\n         */\n        hasOverflow: function () {\n            return this.elems().length > this.viewportSize;\n        },\n\n        /**\n         * Helper, checks\n         *  - if less than one item choosen\n         *  - if more then viewportMaxSize choosen\n         *\n         * @param {Object} elem\n         * @returns {Boolean}\n         */\n        isDisabled: function (elem) {\n            var visible = this.countVisible();\n\n            return elem.visible ?\n                    visible === this.minVisible :\n                    visible === this.maxVisible;\n        },\n\n        /**\n         * Counts number of visible columns.\n         *\n         * @returns {Number}\n         */\n        countVisible: function () {\n            return this.elems.filter('visible').length;\n        },\n\n        /**\n         * Compile header message from headerMessage setting.\n         *\n         * @returns {String}\n         */\n        getHeaderMessage: function () {\n            return utils.template(this.templates.headerMsg, {\n                visible: this.countVisible(),\n                total: this.elems().length\n            });\n        }\n    });\n});\n","Magento_Ui/js/grid/controls/button/split.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery'\n], function ($) {\n    'use strict';\n\n    return function (data, element) {\n\n        $(element).on('click.splitDefault', '.action-default', function () {\n            $(this).siblings('.dropdown-menu').find('.item-default').trigger('click');\n        });\n    };\n});\n","Magento_Ui/js/grid/controls/bookmarks/storage.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    'mageUtils',\n    'Magento_Ui/js/lib/core/storage/local',\n    'uiClass'\n], function ($, utils, storage, Class) {\n    'use strict';\n\n    /**\n     * Removes ns prefix for path.\n     *\n     * @param {String} ns\n     * @param {String} path\n     * @returns {String}\n     */\n    function removeNs(ns, path) {\n        return path.replace(ns + '.', '');\n    }\n\n    return Class.extend({\n        defaults: {\n            ajaxSettings: {\n                method: 'POST',\n                data: {\n                    namespace: '${ $.namespace }'\n                }\n            }\n        },\n\n        /**\n         * Delegates call to the localStorage adapter.\n         */\n        get: function () {\n            return {};\n        },\n\n        /**\n         * Sends request to store specified data.\n         *\n         * @param {String} path - Path by which data should be stored.\n         * @param {*} value - Value to be sent.\n         */\n        set: function (path, value) {\n            var property = removeNs(this.namespace, path),\n                data = {},\n                config;\n\n            utils.nested(data, property, value);\n\n            config = utils.extend({\n                url: this.saveUrl,\n                data: {\n                    data: JSON.stringify(data)\n                }\n            }, this.ajaxSettings);\n\n            $.ajax(config);\n        },\n\n        /**\n         * Sends request to remove specified data.\n         *\n         * @param {String} path - Path to the property to be removed.\n         */\n        remove: function (path) {\n            var property = removeNs(this.namespace, path),\n                config;\n\n            config = utils.extend({\n                url: this.deleteUrl,\n                data: {\n                    data: property\n                }\n            }, this.ajaxSettings);\n\n            $.ajax(config);\n        }\n    });\n});\n","Magento_Ui/js/grid/controls/bookmarks/bookmarks.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    'mage/translate',\n    'rjsResolver',\n    'uiLayout',\n    'uiCollection'\n], function (_, utils, $t, resolver, layout, Collection) {\n    'use strict';\n\n    /**\n     * Removes 'current' namespace from a 'path' string.\n     *\n     * @param {String} path\n     * @returns {String} Path without namespace.\n     */\n    function removeStateNs(path) {\n        path = typeof path == 'string' ? path.split('.') : [];\n\n        if (path[0] === 'current') {\n            path.shift();\n        }\n\n        return path.join('.');\n    }\n\n    return Collection.extend({\n        defaults: {\n            template: 'ui/grid/controls/bookmarks/bookmarks',\n            viewTmpl: 'ui/grid/controls/bookmarks/view',\n            newViewLabel: $t('New View'),\n            defaultIndex: 'default',\n            activeIndex: 'default',\n            viewsArray: [],\n            storageConfig: {\n                provider: '${ $.storageConfig.name }',\n                name: '${ $.name }_storage',\n                component: 'Magento_Ui/js/grid/controls/bookmarks/storage'\n            },\n            views: {\n                default: {\n                    label: $t('Default View'),\n                    index: 'default',\n                    editable: false\n                }\n            },\n            tracks: {\n                editing: true,\n                viewsArray: true,\n                activeView: true,\n                hasChanges: true,\n                customLabel: true,\n                customVisible: true\n            },\n            listens: {\n                activeIndex: 'onActiveIndexChange',\n                activeView: 'checkState',\n                current: 'onStateChange'\n            }\n        },\n\n        /**\n         * Initializes bookmarks component.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        initialize: function () {\n            utils.limit(this, 'checkState', 5);\n            utils.limit(this, 'saveState', 2000);\n\n            this._super()\n                .restore()\n                .initStorage()\n                .initViews();\n\n            return this;\n        },\n\n        /**\n         * Creates custom storage instance.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        initStorage: function () {\n            layout([this.storageConfig]);\n\n            return this;\n        },\n\n        /**\n         * Defines default data if it wasn't gathered previously.\n         *\n         * @private\n         * @returns {Bookmarks} Chainbale.\n         */\n        initDefaultView: function () {\n            var data = this.getViewData(this.defaultIndex);\n\n            if (!_.size(data) && (this.current.columns && this.current.positions)) {\n                    this.setViewData(this.defaultIndex, this.current)\n                        .saveView(this.defaultIndex);\n                    this.defaultDefined = true;\n            }\n\n            return this;\n        },\n\n        /**\n         * Creates instances of a previously saved views.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        initViews: function () {\n            _.each(this.views, function (config) {\n                this.addView(config);\n            }, this);\n\n            this.activeView = this.getActiveView();\n\n            return this;\n        },\n\n        /**\n         * Creates complete configuration for a view.\n         *\n         * @param {Object} [config] - Additional configuration object.\n         * @returns {Object}\n         */\n        buildView: function (config) {\n            var view = {\n                label: this.newViewLabel,\n                index: '_' + Date.now(),\n                editable: true\n            };\n\n            utils.extend(view, config || {});\n\n            view.data   = view.data || utils.copy(this.current);\n            view.value  = view.label;\n\n            this.observe.call(view, true, 'label value');\n\n            return view;\n        },\n\n        /**\n         * Creates instance of a view with a provided configuration.\n         *\n         * @param {Object} [config] - View configuration.\n         * @param {Boolean} [saveView=false] - Whether to save created view automatically or not.\n         * @param {Boolean} [applyView=false] - Whether to apply created view automatically or not.\n         * @returns {View} Created view.\n         */\n        addView: function (config, saveView, applyView) {\n            var view    = this.buildView(config),\n                index   = view.index;\n\n            this.views[index] = view;\n\n            if (saveView) {\n                this.saveView(index);\n            }\n\n            if (applyView) {\n                this.applyView(index);\n            }\n\n            this.updateArray();\n\n            return view;\n        },\n\n        /**\n         * Removes specified view.\n         *\n         * @param {String} index - Index of a view to be removed.\n         * @returns {Bookmarks} Chainable.\n         */\n        removeView: function (index) {\n            var viewPath = this.getViewPath(index);\n\n            if (this.isViewActive(index)) {\n                this.applyView(this.defaultIndex);\n            }\n\n            this.endEdit(index)\n                .remove(viewPath)\n                .removeStored(viewPath)\n                .updateArray();\n\n            return this;\n        },\n\n        /**\n         * Saves data of a specified view.\n         *\n         * @param {String} index - Index of a view to be saved.\n         * @returns {Bookmarks} Chainable.\n         */\n        saveView: function (index) {\n            var viewPath = this.getViewPath(index);\n\n            this.updateViewLabel(index)\n                .endEdit(index)\n                .store(viewPath)\n                .checkState();\n\n            return this;\n        },\n\n        /**\n         * Sets specified view as active\n         * and applies its' state.\n         *\n         * @param {String} index - Index of a view to be applied.\n         * @returns {Bookmarks} Chainable.\n         */\n        applyView: function (index) {\n            this.applyStateOf(index)\n                .set('activeIndex', index);\n\n            return this;\n        },\n\n        /**\n         * Updates data of a specified view if it's\n         * currently active and saves its' data.\n         *\n         * @param {String} index - Index of a view.\n         * @returns {Bookmarks} Chainable.\n         */\n        updateAndSave: function (index) {\n            if (this.isViewActive(index)) {\n                this.updateActiveView(index);\n            }\n\n            this.saveView(index);\n\n            return this;\n        },\n\n        /**\n         * Returns instance of a specified view.\n         *\n         * @param {String} index - Index of a view to be retrieved.\n         * @returns {View}\n         */\n        getView: function (index) {\n            return this.views[index];\n        },\n\n        /**\n         * Returns instance of an active view.\n         *\n         * @returns {View}\n         */\n        getActiveView: function () {\n            return this.views[this.activeIndex];\n        },\n\n        /**\n         * Checks if specified view is active.\n         *\n         * @param {String} index - Index of a view to be checked.\n         * @returns {Boolean}\n         */\n        isViewActive: function (index) {\n            return this.activeView === this.getView(index);\n        },\n\n        /**\n         * Sets current state as a data of an active view.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        updateActiveView: function () {\n            this.setViewData(this.activeIndex, this.current);\n\n            return this;\n        },\n\n        /**\n         * Replaces label a view with a provided one.\n         * If new label is not specified, then views'\n         * 'value' property will be taken.\n         *\n         * @param {String} index - Index of a view.\n         * @param {String} [label=view.value] - New labels' value.\n         * @returns {Bookmarks} Chainable.\n         */\n        updateViewLabel: function (index, label) {\n            var view    = this.getView(index),\n                current = view.label;\n\n            label = (label || view.value).trim() || current;\n            label = this.uniqueLabel(label, current);\n\n            view.label = view.value = label;\n\n            return this;\n        },\n\n        /**\n         * Retrieves data of a specified view.\n         *\n         * @param {String} index - Index of a view whose data should be retrieved.\n         * @param {String} [property] - If not specified then whole views' data will be retrieved.\n         * @returns {Object} Views' data.\n         */\n        getViewData: function (index, property) {\n            var view = this.getView(index),\n                data = view.data;\n\n            if (property) {\n                data = utils.nested(data, property);\n            }\n\n            return utils.copy(data);\n        },\n\n        /**\n         * Sets data to the specified view.\n         *\n         * @param {String} index - Index of a view whose data will be replaced.\n         * @param {Object} data - New view data.\n         * @returns {Bookmarks} Chainable.\n         */\n        setViewData: function (index, data) {\n            var path = this.getViewPath(index) + '.data';\n\n            this.set(path, utils.copy(data));\n\n            return this;\n        },\n\n        /**\n         * Starts editing of a specified view.\n         *\n         * @param {String} index - Index of a view.\n         * @returns {Bookmarks} Chainable.\n         */\n        editView: function (index) {\n            this.editing = index;\n\n            return this;\n        },\n\n        /**\n         * Ends editing of specified view\n         * and restores its' label.\n         *\n         * @param {String} index - Index of a view.\n         * @returns {Bookmarks} Chainable.\n         */\n        endEdit: function (index) {\n            var view;\n\n            if (!this.isEditing(index)) {\n                return this;\n            }\n\n            index   = index || this.editing;\n            view    = this.getView(index);\n\n            view.value = view.label;\n\n            this.editing = false;\n\n            return this;\n        },\n\n        /**\n         * Checks if specified view is in editing state.\n         *\n         * @param {String} index - Index of a view to be checked.\n         * @returns {Boolean}\n         */\n        isEditing: function (index) {\n            return this.editing === index;\n        },\n\n        /**\n         * Generates label unique among present views, based\n         * on the incoming label pattern.\n         *\n         * @param {String} [label=this.newViewLabel] - Label pattern.\n         * @param {String} [exclude]\n         * @returns {String}\n         */\n        uniqueLabel: function (label, exclude) {\n            var labels      = _.pluck(this.views, 'label'),\n                hasParenth  = _.last(label) === ')',\n                index       = 2,\n                result,\n                suffix;\n\n            labels = _.without(labels, exclude);\n            result = label = label || this.newViewLabel;\n\n            for (index = 2; _.contains(labels, result); index++) {\n                suffix = '(' + index + ')';\n\n                if (!hasParenth) {\n                    suffix = ' ' + suffix;\n                }\n\n                result = label + suffix;\n            }\n\n            return result;\n        },\n\n        /**\n         * Applies state of a specified view, without\n         * making it active.\n         *\n         * @param {String} [state=this.activeIndex]\n         * @param {String} [property]\n         * @returns {Bookmarks} Chainable.\n         */\n        applyStateOf: function (state, property) {\n            var index    = state || this.activeIndex,\n                dataPath = removeStateNs(property),\n                viewData = this.getViewData(index, dataPath);\n\n            dataPath = dataPath ?\n                'current.' + dataPath :\n                'current';\n\n            this.set(dataPath, viewData);\n\n            return this;\n        },\n\n        /**\n         * Saves current state.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        saveState: function () {\n            this.store('current');\n            return this;\n        },\n\n        /**\n         * Applies state of an active view.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        resetState: function () {\n            this.applyStateOf(this.activeIndex);\n\n            return this;\n        },\n\n        /**\n         * Checks if current state is different\n         * from the state of an active view.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        checkState: function () {\n            var viewData = this.getViewData(this.activeIndex),\n                diff     = utils.compare(viewData, this.current);\n\n            this.hasChanges = !diff.equal;\n\n            return this;\n        },\n\n        /**\n         * Returns path to the view instance,\n         * based on a provided index.\n         *\n         * @param {String} index - Index of a view.\n         * @returns {String}\n         */\n        getViewPath: function (index) {\n            return 'views.' + index;\n        },\n\n        /**\n         * Updates the array of views.\n         *\n         * @returns {Bookmarks} Chainable\n         */\n        updateArray: function () {\n            this.viewsArray = _.values(this.views);\n\n            return this;\n        },\n\n        /**\n         * Shows custom view field and creates unique label for it.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        showCustom: function () {\n            this.customLabel    = this.uniqueLabel();\n            this.customVisible  = true;\n\n            return this;\n        },\n\n        /**\n         * Hides custom view field.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        hideCustom: function () {\n            this.customVisible = false;\n\n            return this;\n        },\n\n        /**\n         * Checks if custom view field is visible.\n         *\n         * @returns {Boolean}\n         */\n        isCustomVisible: function () {\n            return this.customVisible;\n        },\n\n        /**\n         * Creates new view instance with a label specified\n         * in a custom view field.\n         *\n         * @returns {Bookmarks} Chainable.\n         */\n        applyCustom: function () {\n            var label = this.customLabel.trim();\n\n            this.hideCustom()\n                .addView({\n                    label: this.uniqueLabel(label)\n                }, true, true);\n\n            return this;\n        },\n\n        /**\n         * Listener of the activeIndex property.\n         */\n        onActiveIndexChange: function () {\n            this.activeView = this.getActiveView();\n            this.updateActiveView();\n            this.store('activeIndex');\n        },\n\n        /**\n         * Listener of the activeIndex property.\n         */\n        onStateChange: function () {\n            this.checkState();\n            this.saveState();\n\n            if (!this.defaultDefined) {\n                resolver(this.initDefaultView, this);\n            }\n        }\n    });\n});\n","Magento_Ui/js/core/app.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    './renderer/types',\n    './renderer/layout',\n    '../lib/knockout/bootstrap'\n], function (types, layout) {\n    'use strict';\n\n    return function (data, merge) {\n        types.set(data.types);\n        layout(data.components, undefined, true, merge);\n    };\n});\n","Magento_Ui/js/core/renderer/types.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'mageUtils'\n], function (_, utils) {\n    'use strict';\n\n    var store = {};\n\n    /**\n     * Flatten a nested data.\n     *\n     * @param {Object} data\n     * @returns {Object}\n     */\n    function flatten(data) {\n        var extender = data.extends || [],\n            result = {};\n\n        extender = utils.stringToArray(extender);\n\n        extender.push(data);\n\n        extender.forEach(function (item) {\n            if (_.isString(item)) {\n                item = store[item] || {};\n            }\n\n            utils.extend(result, item);\n        });\n\n        delete result.extends;\n\n        return result;\n    }\n\n    return {\n        /**\n         * Set types to store object.\n         *\n         * @param {Object} types\n         */\n        set: function (types) {\n            types = types || {};\n\n            utils.extend(store, types);\n\n            _.each(types, function (data, type) {\n                store[type] = flatten(data);\n            });\n        },\n\n        /**\n         * Get type from store object.\n         *\n         * @param {String} type\n         * @returns {*|{}}\n         */\n        get: function (type) {\n            return store[type] || {};\n        }\n    };\n});\n","Magento_Ui/js/core/renderer/layout.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'jquery',\n    'mageUtils',\n    'uiRegistry',\n    './types',\n    '../../lib/logger/console-logger'\n], function (_, $, utils, registry, types, consoleLogger) {\n    'use strict';\n\n    var templates = registry.create(),\n        layout = {},\n        cachedConfig = {};\n\n    /**\n     * Build name from parent name and node name\n     *\n     * @param {Object} parent\n     * @param {Object} node\n     * @param {String} [name]\n     * @returns {String}\n     */\n    function getNodeName(parent, node, name) {\n        var parentName = parent && parent.name;\n\n        if (typeof name !== 'string') {\n            name = node.name || name;\n        }\n\n        return utils.fullPath(parentName, name);\n    }\n\n    /**\n     * Get node type from node or parent.\n     *\n     * @param {Object} parent\n     * @param {Object} node\n     * @returns {String}\n     */\n    function getNodeType(parent, node) {\n        return node.type || parent && parent.childType;\n    }\n\n    /**\n     * Get data scope based on parent data scope and node data scope.\n     *\n     * @param {Object} parent\n     * @param {Object} node\n     * @returns {String}\n     */\n    function getDataScope(parent, node) {\n        var dataScope = node.dataScope,\n            parentScope = parent && parent.dataScope;\n\n        return !utils.isEmpty(parentScope) ?\n            !utils.isEmpty(dataScope) ?\n                parentScope + '.' + dataScope :\n                parentScope :\n            dataScope || '';\n    }\n\n    /**\n     * Load node dependencies on other instances.\n     *\n     * @param {Object} node\n     * @returns {jQueryPromise}\n     */\n    function loadDeps(node) {\n        var loaded = $.Deferred(),\n            loggerUtils = consoleLogger.utils;\n\n        if (node.deps) {\n            consoleLogger.utils.asyncLog(\n                loaded,\n                {\n                    data: {\n                        component: node.name,\n                        deps: node.deps\n                    },\n                    messages: loggerUtils.createMessages(\n                        'depsStartRequesting',\n                        'depsFinishRequesting',\n                        'depsLoadingFail'\n                    )\n                }\n            );\n        }\n\n        registry.get(node.deps, function (deps) {\n            node.provider = node.extendProvider ? deps && deps.name : node.provider;\n            loaded.resolve(node);\n        });\n\n        return loaded.promise();\n    }\n\n    /**\n     * Load node component file via requirejs.\n     *\n     * @param {Object} node\n     * @returns {jQueryPromise}\n     */\n    function loadSource(node) {\n        var loaded = $.Deferred(),\n            source = node.component;\n\n        consoleLogger.info('componentStartLoading', {\n            component: node.component\n        });\n\n        require([source], function (constr) {\n            consoleLogger.info('componentFinishLoading', {\n                component: node.component\n            });\n            loaded.resolve(node, constr);\n        }, function () {\n            consoleLogger.error('componentLoadingFail', {\n                component: node.component\n            });\n        });\n\n        return loaded.promise();\n    }\n\n    /**\n     * Create a new component instance and set it to the registry.\n     *\n     * @param {Object} node\n     * @param {Function} Constr\n     */\n    function initComponent(node, Constr) {\n        var component = new Constr(_.omit(node, 'children'));\n\n        consoleLogger.info('componentStartInitialization', {\n            component: node.component,\n            componentName: node.name\n        });\n\n        registry.set(node.name, component);\n    }\n\n    /**\n     * Application entry point.\n     *\n     * @param {Object} nodes\n     * @param {Object} parent\n     * @param {Boolean} cached\n     * @param {Boolean} merge\n     * @returns {Boolean|undefined}\n     */\n    function run(nodes, parent, cached, merge) {\n        if (_.isBoolean(merge) && merge) {\n            layout.merge(nodes);\n\n            return false;\n        }\n\n        if (cached) {\n            cachedConfig[_.keys(nodes)[0]] = JSON.parse(JSON.stringify(nodes));\n        }\n\n        _.each(nodes || [], layout.iterator.bind(layout, parent));\n    }\n\n    _.extend(layout, {\n        /**\n         * Determines if node ready to be added or process it.\n         *\n         * @param {Object} parent\n         * @param {Object|String} node\n         */\n        iterator: function (parent, node) {\n            var action = _.isString(node) ?\n                this.addChild :\n                this.process;\n\n            action.apply(this, arguments);\n        },\n\n        /**\n         * Prepare component.\n         *\n         * @param {Object} parent\n         * @param {Object} node\n         * @param {String} name\n         * @returns {Object}\n         */\n        process: function (parent, node, name) {\n            if (!parent && node.parent) {\n                return this.waitParent(node, name);\n            }\n\n            if (node.nodeTemplate) {\n                return this.waitTemplate.apply(this, arguments);\n            }\n\n            node = this.build.apply(this, arguments);\n\n            if (!registry.has(node.name)) {\n                this.addChild(parent, node)\n                    .manipulate(node)\n                    .initComponent(node);\n            }\n\n            if (node) {\n                run(node.children, node);\n            }\n\n            return this;\n        },\n\n        /**\n         * Detailed processing of component config.\n         *\n         * @param {Object} parent\n         * @param {Object} node\n         * @param {String} name\n         * @returns {Boolean|Object}\n         */\n        build: function (parent, node, name) {\n            var defaults    = parent && parent.childDefaults || {},\n                children    = this.filterDisabledChildren(node.children),\n                type        = getNodeType(parent, node),\n                dataScope   = getDataScope(parent, node),\n                component,\n                extendDeps  = true,\n                nodeName;\n\n            node.children = false;\n            node.extendProvider = true;\n\n            if (node.config && node.config.provider || node.provider) {\n                node.extendProvider = false;\n            }\n\n            if (node.config && node.config.deps || node.deps) {\n                extendDeps = false;\n            }\n\n            node = utils.extend({\n            }, types.get(type), defaults, node);\n\n            nodeName = getNodeName(parent, node, name);\n\n            if (registry.has(nodeName)) {\n                component = registry.get(nodeName);\n                component.children = children;\n\n                return component;\n            }\n\n            if (extendDeps && parent && parent.deps && type) {\n                node.deps = parent.deps;\n            }\n\n            _.extend(node, node.config || {}, {\n                index: node.name || name,\n                name: nodeName,\n                dataScope: dataScope,\n                parentName: utils.getPart(nodeName, -2),\n                parentScope: utils.getPart(dataScope, -2)\n            });\n\n            node.children = children;\n            node.componentType = node.type;\n\n            delete node.type;\n            delete node.config;\n\n            if (children) {\n                node.initChildCount = _.size(children);\n            }\n\n            if (node.isTemplate) {\n                node.isTemplate = false;\n\n                templates.set(node.name, node);\n                registry.get(node.parentName, function (parentComp) {\n                    parentComp.childTemplate = node;\n                });\n\n                return false;\n            }\n\n            if (node.componentDisabled === true) {\n                return false;\n            }\n\n            return node;\n        },\n\n        /**\n         * Filter out all disabled components.\n         *\n         * @param {Object} children\n         * @returns {*}\n         */\n        filterDisabledChildren: function (children) {\n            var cIds;\n\n            //cleanup children config.componentDisabled = true\n            if (children && typeof children === 'object') {\n                cIds = Object.keys(children);\n\n                if (cIds) {\n                    _.each(cIds, function (cId) {\n                        if (typeof children[cId] === 'object' &&\n                            children[cId].hasOwnProperty('config') &&\n                            typeof children[cId].config === 'object' &&\n                            children[cId].config.hasOwnProperty('componentDisabled') &&\n                            children[cId].config.componentDisabled === true) {\n                            delete children[cId];\n                        }\n                    });\n                }\n            }\n\n            return children;\n        },\n\n        /**\n         * Init component.\n         *\n         * @param {Object} node\n         * @returns {Object}\n         */\n        initComponent: function (node) {\n            if (!node.component) {\n                return this;\n            }\n\n            loadDeps(node)\n                .then(loadSource)\n                .done(initComponent);\n\n            return this;\n        }\n    });\n\n    _.extend(layout, {\n        /**\n         * Loading component marked as isTemplate.\n         *\n         * @param {Object} parent\n         * @param {Object} node\n         * @returns {Object}\n         */\n        waitTemplate: function (parent, node) {\n            var args = _.toArray(arguments);\n\n            templates.get(node.nodeTemplate, function () {\n                this.applyTemplate.apply(this, args);\n            }.bind(this));\n\n            return this;\n        },\n\n        /**\n         * Waiting for parent component and process provided component.\n         *\n         * @param {Object} node\n         * @param {String} name\n         * @returns {Object}\n         */\n        waitParent: function (node, name) {\n            var process = this.process.bind(this);\n\n            registry.get(node.parent, function (parent) {\n                process(parent, node, name);\n            });\n\n            return this;\n        },\n\n        /**\n         * Processing component marked as isTemplate.\n         *\n         * @param {Object} parent\n         * @param {Object} node\n         * @param {String} name\n         */\n        applyTemplate: function (parent, node, name) {\n            var template = templates.get(node.nodeTemplate);\n\n            node = utils.extend({}, template, node);\n\n            delete node.nodeTemplate;\n\n            this.process(parent, node, name);\n        }\n    });\n\n    _.extend(layout, {\n        /**\n         * Determines inserting strategy.\n         *\n         * @param {Object} node\n         * @returns {Object}\n         */\n        manipulate: function (node) {\n            var name = node.name;\n\n            if (node.appendTo) {\n                this.insert(name, node.appendTo, -1);\n            }\n\n            if (node.prependTo) {\n                this.insert(name, node.prependTo, 0);\n            }\n\n            if (node.insertTo) {\n                this.insertTo(name, node.insertTo);\n            }\n\n            return this;\n        },\n\n        /**\n         * Insert component to provide target and position.\n         *\n         * @param {Object|String} item\n         * @param {Object} target\n         * @param {Number} position\n         * @returns {Object}\n         */\n        insert: function (item, target, position) {\n            registry.get(target, function (container) {\n                container.insertChild(item, position);\n            });\n\n            return this;\n        },\n\n        /**\n         * Insert component into multiple targets.\n         *\n         * @param {Object} item\n         * @param {Array} targets\n         * @returns {Object}\n         */\n        insertTo: function (item, targets) {\n            _.each(targets, function (info, target) {\n                this.insert(item, target, info.position);\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Add provided child to parent.\n         *\n         * @param {Object} parent\n         * @param {Object|String} child\n         * @returns {Object}\n         */\n        addChild: function (parent, child) {\n            var name;\n\n            if (parent && parent.component) {\n                name = child.name || child;\n\n                this.insert(name, parent.name, child.sortOrder);\n            }\n\n            return this;\n        },\n\n        /**\n         * Merge components configuration with cached configuration.\n         *\n         * @param {Array} components\n         */\n        merge: function (components) {\n            var cachedKey = _.keys(components)[0],\n                compared = utils.compare(cachedConfig[cachedKey], components),\n                remove = this.filterComponents(this.getByProperty(compared.changes, 'type', 'remove'), true),\n                update = this.getByProperty(compared.changes, 'type', 'update'),\n                dataSources = this.getDataSources(components),\n                names, index, name, component;\n\n            _.each(dataSources, function (val, key) {\n                name = key.replace(/\\.children|\\.config/g, '');\n                component = registry.get(name);\n\n                component.cacheData();\n                component.updateConfig(\n                    true,\n                    this.getFullConfig(key, components),\n                    this.getFullConfig(key, cachedConfig[cachedKey])\n                );\n            }, this);\n\n            _.each(remove, function (val) {\n                component = registry.get(val.path);\n\n                if (component) {\n                    component.destroy();\n                }\n            });\n\n            update = _.compact(_.filter(update, function (val) {\n                return !_.isEqual(val.oldValue, val.value);\n            }));\n\n            _.each(update, function (val) {\n                names = val.path.split('.');\n                index = Math.max(_.lastIndexOf(names, 'config'), _.lastIndexOf(names, 'children') + 2);\n                name = _.without(names.splice(0, index), 'children', 'config').join('.');\n                component = registry.get(name);\n\n                if (val.name === 'sortOrder' && component) {\n                    registry.get(component.parentName).insertChild(component, val.value);\n                } else if (component) {\n                    component.updateConfig(\n                        val.oldValue,\n                        val.value,\n                        val.path\n                    );\n                }\n            }, this);\n\n            run(components, undefined, true);\n        },\n\n        /**\n         * Recursive dataSource assignment.\n         *\n         * @param {Object} config\n         * @param {String} parentPath\n         * @returns {Object}\n         */\n        getDataSources: function (config, parentPath) {\n            var dataSources = {},\n                key, obj;\n\n            /* eslint-disable no-loop-func, max-depth */\n            for (key in config) {\n                if (config.hasOwnProperty(key)) {\n                    if (\n                        key === 'type' &&\n                        config[key] === 'dataSource' &&\n                        config.hasOwnProperty('config')\n                    ) {\n                        dataSources[parentPath + '.config'] = config.config;\n                    } else if (_.isObject(config[key])) {\n                        obj = this.getDataSources(config[key], utils.fullPath(parentPath, key));\n\n                        _.each(obj, function (value, path) {\n                            dataSources[path] = value;\n                        });\n                    }\n                }\n            }\n\n            /* eslint-enable no-loop-func, max-depth */\n\n            return dataSources;\n        },\n\n        /**\n         * Configuration getter.\n         *\n         * @param {String} path\n         * @param {Object} config\n         * @returns {Boolean|Object}\n         */\n        getFullConfig: function (path, config) {\n            var index;\n\n            path = path.split('.');\n            index = _.lastIndexOf(path, 'config');\n\n            if (!~index) {\n                return false;\n            }\n            path = path.splice(0, index);\n\n            _.each(path, function (val) {\n                config = config[val];\n            });\n\n            return config.config;\n        },\n\n        /**\n         * Filter data by property and value.\n         *\n         * @param {Object} data\n         * @param {String} prop\n         * @param {*} propValue\n         */\n        getByProperty: function (data, prop, propValue) {\n            return _.filter(data, function (value) {\n                return value[prop] === propValue;\n            });\n        },\n\n        /**\n         * Filter components.\n         *\n         * @param {Array} data\n         * @param {Boolean} splitPath\n         * @param {Number} index\n         * @param {String} separator\n         * @param {String} keyName\n         * @returns {Array}\n         */\n        filterComponents: function (data, splitPath, index, separator, keyName) {\n            var result = [],\n                names, length;\n\n            index = -2;\n            separator = '.' || separator;\n            keyName = 'children' || keyName;\n\n            _.each(data, function (val) {\n                names = val.path.split(separator);\n                length  = names.length;\n\n                if (names[length + index] === keyName) {\n                    val.path = splitPath ? _.without(names, keyName).join(separator) : val.path;\n                    result.push(val);\n                }\n            });\n\n            return result;\n        }\n    });\n\n    return run;\n});\n","Magento_Ui/js/timeline/timeline-view.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    'Magento_Ui/js/lib/view/utils/async',\n    'underscore',\n    'Magento_Ui/js/lib/view/utils/raf',\n    'uiRegistry',\n    'uiClass'\n], function (ko, $, _, raf, registry, Class) {\n    'use strict';\n\n    var hasClassList = (function () {\n        var list = document.createElement('_').classList;\n\n        return !!list && !list.toggle('_test', false);\n    })();\n\n    /**\n     * Polyfill of the 'classList.toggle' method.\n     *\n     * @param {HTMLElement} elem\n     */\n    function toggleClass(elem) {\n        var classList   = elem.classList,\n            args        = Array.prototype.slice.call(arguments, 1),\n            $elem;\n\n        if (hasClassList) {\n            classList.toggle.apply(classList, args);\n        } else {\n            $elem = $(elem);\n            $elem.toggleClass.apply($elem, args);\n        }\n    }\n\n    return Class.extend({\n        defaults: {\n            selectors: {\n                content: '.timeline-content',\n                timeUnit: '.timeline-unit',\n                item: '.timeline-item:not([data-role=no-data-msg])',\n                event: '.timeline-event'\n            }\n        },\n\n        /**\n         * Initializes TimelineView component.\n         *\n         * @returns {TimelineView} Chainable.\n         */\n        initialize: function () {\n            _.bindAll(\n                this,\n                'refresh',\n                'initContent',\n                'initItem',\n                'initTimeUnit',\n                'getItemBindings',\n                'updateItemsPosition',\n                'onScaleChange',\n                'onEventElementRender',\n                'onWindowResize',\n                'onContentScroll',\n                'onDataReloaded',\n                'onToStartClick',\n                'onToEndClick'\n            );\n\n            this._super()\n                .initModel()\n                .waitContent();\n\n            return this;\n        },\n\n        /**\n         * Applies listeners for the model properties changes.\n         *\n         * @returns {TimelineView} Chainable.\n         */\n        initModel: function () {\n            var model = registry.get(this.model);\n\n            model.on('scale', this.onScaleChange);\n            model.source.on('reloaded', this.onDataReloaded);\n\n            this.model = model;\n\n            return this;\n        },\n\n        /**\n         * Applies DOM watcher for the\n         * content element rendering.\n         *\n         * @returns {TimelineView} Chainable.\n         */\n        waitContent: function () {\n            $.async({\n                selector: this.selectors.content,\n                component: this.model\n            }, this.initContent);\n\n            return this;\n        },\n\n        /**\n         * Initializes timelines' content element.\n         *\n         * @param {HTMLElement} content\n         * @returns {TimelineView} Chainable.\n         */\n        initContent: function (content) {\n            this.$content = content;\n\n            $(content).on('scroll', this.onContentScroll);\n            $(window).on('resize', this.onWindowResize);\n\n            $.async(this.selectors.item, content, this.initItem);\n            $.async(this.selectors.event, content, this.onEventElementRender);\n            $.async(this.selectors.timeUnit, content, this.initTimeUnit);\n\n            this.refresh();\n\n            return this;\n        },\n\n        /**\n         * Initializes timeline item element,\n         * e.g. establishes event listeners and applies data bindings.\n         *\n         * @param {HTMLElement} elem\n         * @returns {TimelineView} Chainable.\n         */\n        initItem: function (elem) {\n            $(elem)\n                .bindings(this.getItemBindings)\n                .on('click', '._toend', this.onToEndClick)\n                .on('click', '._tostart', this.onToStartClick);\n\n            return this;\n        },\n\n        /**\n         * Initializes timeline unit element.\n         *\n         * @param {HTMLElement} elem\n         * @returns {TimelineView} Chainable.\n         */\n        initTimeUnit: function (elem) {\n            $(elem).bindings(this.getTimeUnitBindings());\n\n            return this;\n        },\n\n        /**\n         * Updates items positions in a\n         * loop if state of a view has changed.\n         */\n        refresh: function () {\n            raf(this.refresh);\n\n            if (this._update) {\n                this._update = false;\n\n                this.updateItemsPosition();\n            }\n        },\n\n        /**\n         * Returns object width additional bindings\n         * for a timeline unit element.\n         *\n         * @returns {Object}\n         */\n        getTimeUnitBindings: function () {\n            return {\n                style: {\n                    width: ko.computed(function () {\n                        return this.getTimeUnitWidth() + '%';\n                    }.bind(this))\n                }\n            };\n        },\n\n        /**\n         * Returns object with additional\n         * bindings for a timeline item element.\n         *\n         * @param {Object} ctx\n         * @returns {Object}\n         */\n        getItemBindings: function (ctx) {\n            return {\n                style: {\n                    width: ko.computed(function () {\n                        return this.getItemWidth(ctx.$row()) + '%';\n                    }.bind(this)),\n\n                    'margin-left': ko.computed(function () {\n                        return this.getItemMargin(ctx.$row()) + '%';\n                    }.bind(this))\n                }\n            };\n        },\n\n        /**\n         * Calculates width in percents of a timeline unit element.\n         *\n         * @returns {Number}\n         */\n        getTimeUnitWidth: function () {\n            return 100 / this.model.scale;\n        },\n\n        /**\n         * Calculates width of a record in percents.\n         *\n         * @param {Object} record\n         * @returns {String}\n         */\n        getItemWidth: function (record) {\n            var days = 0;\n\n            if (record) {\n                days = this.model.getDaysLength(record);\n            }\n\n            return this.getTimeUnitWidth()  * days;\n        },\n\n        /**\n         * Calculates left margin value for provided record.\n         *\n         * @param {Object} record\n         * @returns {String}\n         */\n        getItemMargin: function (record) {\n            var offset = 0;\n\n            if (record) {\n                offset = this.model.getStartDelta(record);\n            }\n\n            return this.getTimeUnitWidth() * offset;\n        },\n\n        /**\n         * Returns collection of currently available\n         * timeline item elements.\n         *\n         * @returns {Array<HTMLElement>}\n         */\n        getItems: function () {\n            var items = this.$content.querySelectorAll(this.selectors.item);\n\n            return _.toArray(items);\n        },\n\n        /**\n         * Updates positions of timeline elements.\n         *\n         * @returns {TimelineView} Chainable.\n         */\n        updateItemsPosition: function () {\n            this.getItems()\n                .forEach(this.updatePositionFor, this);\n\n            return this;\n        },\n\n        /**\n         * Updates position of provided timeline element.\n         *\n         * @param {HTMLElement} $elem\n         * @returns {TimelineView} Chainable.\n         */\n        updatePositionFor: function ($elem) {\n            var $event      = $elem.querySelector(this.selectors.event),\n                leftEdge    = this.getLeftEdgeFor($elem),\n                rightEdge   = this.getRightEdgeFor($elem);\n\n            if ($event) {\n                $event.style.left = Math.max(-leftEdge, 0) + 'px';\n                $event.style.right = Math.max(rightEdge, 0) + 'px';\n            }\n\n            toggleClass($elem, '_scroll-start', leftEdge < 0);\n            toggleClass($elem, '_scroll-end', rightEdge > 0);\n\n            return this;\n        },\n\n        /**\n         * Scrolls content area to the start of provided element.\n         *\n         * @param {HTMLElement} elem\n         * @returns {TimelineView}\n         */\n        toStartOf: function (elem) {\n            var leftEdge = this.getLeftEdgeFor(elem);\n\n            this.$content.scrollLeft += leftEdge;\n\n            return this;\n        },\n\n        /**\n         * Scrolls content area to the end of provided element.\n         *\n         * @param {HTMLElement} elem\n         * @returns {TimelineView}\n         */\n        toEndOf: function (elem) {\n            var rightEdge = this.getRightEdgeFor(elem);\n\n            this.$content.scrollLeft += rightEdge + 1;\n\n            return this;\n        },\n\n        /**\n         * Calculates location of the left edge of an element\n         * relative to the contents' left edge.\n         *\n         * @param {HTMLElement} elem\n         * @returns {Number}\n         */\n        getLeftEdgeFor: function (elem) {\n            var leftOffset = elem.getBoundingClientRect().left;\n\n            return leftOffset - this.$content.getBoundingClientRect().left;\n        },\n\n        /**\n         * Calculates location of the right edge of an element\n         * relative to the contents' right edge.\n         *\n         * @param {HTMLElement} elem\n         * @returns {Number}\n         */\n        getRightEdgeFor: function (elem) {\n            var elemWidth   = elem.offsetWidth,\n                leftEdge    = this.getLeftEdgeFor(elem);\n\n            return leftEdge + elemWidth - this.$content.offsetWidth;\n        },\n\n        /**\n         * 'To Start' button 'click' event handler.\n         *\n         * @param {jQueryEvent} event\n         */\n        onToStartClick: function (event) {\n            var elem = event.originalEvent.currentTarget;\n\n            event.stopPropagation();\n\n            this.toStartOf(elem);\n        },\n\n        /**\n         * 'To End' button 'click' event handler.\n         *\n         * @param {jQueryEvent} event\n         */\n        onToEndClick: function (event) {\n            var elem = event.originalEvent.currentTarget;\n\n            event.stopPropagation();\n\n            this.toEndOf(elem);\n        },\n\n        /**\n         * Handler of the scale value 'change' event.\n         */\n        onScaleChange: function () {\n            this._update = true;\n        },\n\n        /**\n         * Callback function which is invoked\n         * when event element was rendered.\n         */\n        onEventElementRender: function () {\n            this._update = true;\n        },\n\n        /**\n         * Window 'resize' event handler.\n         */\n        onWindowResize: function () {\n            this._update = true;\n        },\n\n        /**\n         * Content container 'scroll' event handler.\n         */\n        onContentScroll: function () {\n            this._update = true;\n        },\n\n        /**\n         * Data 'reload' event handler.\n         */\n        onDataReloaded: function () {\n            this._update = true;\n        }\n    });\n});\n","Magento_Ui/js/timeline/timeline.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    'moment',\n    'uiLayout',\n    'Magento_Ui/js/grid/listing'\n], function (_, moment, layout, Listing) {\n    'use strict';\n\n    var ONE_DAY = 86400000;\n\n    return Listing.extend({\n        defaults: {\n            recordTmpl: 'ui/timeline/record',\n            dateFormat: 'YYYY-MM-DD HH:mm:ss',\n            headerFormat: 'ddd MM/DD',\n            detailsFormat: 'DD/MM/YYYY HH:mm:ss',\n            scale: 7,\n            scaleStep: 1,\n            minScale: 7,\n            maxScale: 28,\n            minDays: 28,\n            displayMode: 'timeline',\n            displayModes: {\n                timeline: {\n                    label: 'Timeline',\n                    value: 'timeline',\n                    template: 'ui/timeline/timeline'\n                }\n            },\n            viewConfig: {\n                component: 'Magento_Ui/js/timeline/timeline-view',\n                name: '${ $.name }_view',\n                model: '${ $.name }'\n            },\n            tracks: {\n                scale: true\n            },\n            statefull: {\n                scale: true\n            },\n            range: {}\n        },\n\n        /**\n         * Initializes Timeline component.\n         *\n         * @returns {Timeline} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .initView()\n                .updateRange();\n\n            return this;\n        },\n\n        /**\n         * Initializes components configuration.\n         *\n         * @returns {Timeline} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n\n            this.maxScale = Math.min(this.minDays, this.maxScale);\n            this.minScale = Math.min(this.maxScale, this.minScale);\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties.\n         *\n         * @returns {Timeline} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe.call(this.range, true, 'hasToday');\n\n            return this;\n        },\n\n        /**\n         * Initializes TimelineView component.\n         *\n         * @returns {Timeline} Chainable.\n         */\n        initView: function () {\n            layout([this.viewConfig]);\n\n            return this;\n        },\n\n        /**\n         * Checks if provided event record is active,\n         * i.e. it has already started.\n         *\n         * @param {Object} record\n         * @returns {Boolean}\n         */\n        isActive: function (record) {\n            return Number(record.status) === 1;\n        },\n\n        /**\n         * Checks if provided event record is upcoming,\n         * i.e. it will start later on.\n         *\n         * @param {Object} record\n         * @returns {Boolean}\n         */\n        isUpcoming: function (record) {\n            return Number(record.status) === 2;\n        },\n\n        /**\n         * Checks if provided event record is permanent,\n         * i.e. it has no ending time.\n         *\n         * @param {Object} record\n         * @returns {Boolean}\n         */\n        isPermanent: function (record) {\n            return !this.getEndDate(record);\n        },\n\n        /**\n         * Checks if provided date indicates current day.\n         *\n         * @param {(Number|Moment)} date\n         * @returns {Boolenan}\n         */\n        isToday: function (date) {\n            return moment().isSame(date, 'day');\n        },\n\n        /**\n         * Checks if range object contains todays date.\n         *\n         * @returns {Boolean}\n         */\n        hasToday: function () {\n            return this.range.hasToday;\n        },\n\n        /**\n         * Returns start date of provided record.\n         *\n         * @param {Object} record\n         * @returns {String}\n         */\n        getStartDate: function (record) {\n            return record['start_time'];\n        },\n\n        /**\n         * Returns end date of provided record.\n         *\n         * @param {Object} record\n         * @returns {String}\n         */\n        getEndDate: function (record) {\n            return record['end_time'];\n        },\n\n        /**\n         * Returns difference in days between records' start date\n         * and a first day of a range.\n         *\n         * @param {Object} record\n         * @returns {Number}\n         */\n        getStartDelta: function (record) {\n            var start    = this.createDate(this.getStartDate(record)),\n                firstDay = this.range.firstDay;\n\n            return start.diff(firstDay, 'days', true);\n        },\n\n        /**\n         * Calculates the amount of days that provided event lasts.\n         *\n         * @param {Object} record\n         * @returns {Number}\n         */\n        getDaysLength: function (record) {\n            var start   = this.createDate(this.getStartDate(record)),\n                end     = this.createDate(this.getEndDate(record));\n\n            if (!end.isValid()) {\n                end = this.range.lastDay.endOf('day');\n            }\n\n            return end.diff(start, 'days', true);\n        },\n\n        /**\n         * Creates new date object based on provided date string value.\n         *\n         * @param {String} dateStr\n         * @returns {Moment}\n         */\n        createDate: function (dateStr) {\n            return moment(dateStr, this.dateFormat);\n        },\n\n        /**\n         * Converts days to weeks.\n         *\n         * @param {Number} days\n         * @returns {Number}\n         */\n        daysToWeeks: function (days) {\n            var weeks = days / 7;\n\n            if (weeks % 1) {\n                weeks = weeks.toFixed(1);\n            }\n\n            return weeks;\n        },\n\n        /**\n         * Updates data of a range object,\n         * e.g. total days, first day and last day, etc.\n         *\n         * @returns {Object} Range instance.\n         */\n        updateRange: function () {\n            var firstDay    = this._getFirstDay(),\n                lastDay     = this._getLastDay(),\n                totalDays   = lastDay.diff(firstDay, 'days'),\n                days        = [],\n                i           = -1;\n\n            if (totalDays < this.minDays) {\n                totalDays += this.minDays - totalDays - 1;\n            }\n\n            while (++i <= totalDays) {\n                days.push(+firstDay + ONE_DAY * i);\n            }\n\n            return _.extend(this.range, {\n                days:       days,\n                totalDays:  totalDays,\n                firstDay:   firstDay,\n                lastDay:    moment(_.last(days)),\n                hasToday:   this.isToday(firstDay)\n            });\n        },\n\n        /**\n         *\n         * @private\n         * @param {String} key\n         * @returns {Array<Moment>}\n         */\n        _getDates: function (key) {\n            var dates = [];\n\n            this.rows.forEach(function (record) {\n                if (record[key]) {\n                    dates.push(this.createDate(record[key]));\n                }\n            }, this);\n\n            return dates;\n        },\n\n        /**\n         * Returns date which is closest to the current day.\n         *\n         * @private\n         * @returns {Moment}\n         */\n        _getFirstDay: function () {\n            var dates = this._getDates('start_time'),\n                first = moment.min(dates).subtract(1, 'day'),\n                today = moment();\n\n            if (!first.isValid() || first < today) {\n                first = today;\n            }\n\n            return first.startOf('day');\n        },\n\n        /**\n         * Returns the most distant date\n         * specified in available records.\n         *\n         * @private\n         * @returns {Moment}\n         */\n        _getLastDay: function () {\n            var startDates  = this._getDates('start_time'),\n                endDates    = this._getDates('end_time'),\n                last        = moment.max(startDates.concat(endDates));\n\n            return last.add(1, 'day').startOf('day');\n        },\n\n        /**\n         * TODO: remove after integration with date binding.\n         *\n         * @param {Number} timestamp\n         * @returns {String}\n         */\n        formatHeader: function (timestamp) {\n            return moment(timestamp).format(this.headerFormat);\n        },\n\n        /**\n         * TODO: remove after integration with date binding.\n         *\n         * @param {String} date\n         * @returns {String}\n         */\n        formatDetails: function (date) {\n            return moment(date).format(this.detailsFormat);\n        }\n    });\n});\n","Magento_Ui/js/form/button-adapter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'uiClass',\n    'jquery',\n    'underscore',\n    'uiRegistry'\n], function (Class, $, _, registry) {\n    'use strict';\n\n    return Class.extend({\n\n        /**\n         * Initialize actions and adapter.\n         *\n         * @param {Object} config\n         * @param {Element} elem\n         * @returns {Object}\n         */\n        initialize: function (config, elem) {\n            return this._super()\n                .initActions()\n                .initAdapter(elem);\n        },\n\n        /**\n         * Creates callback from declared actions.\n         *\n         * @returns {Object}\n         */\n        initActions: function () {\n            var callbacks = [];\n\n            _.each(this.actions, function (action) {\n                callbacks.push({\n                    action: registry.async(action.targetName),\n                    args: _.union([action.actionName], action.params)\n                });\n            });\n\n            /**\n             * Callback function.\n             */\n            this.callback = function () {\n                _.each(callbacks, function (callback) {\n                    callback.action.apply(callback.action, callback.args);\n                });\n            };\n\n            return this;\n        },\n\n        /**\n         * Attach callback handler on button.\n         *\n         * @param {Element} elem\n         */\n        initAdapter: function (elem) {\n            $(elem).on('click', this.callback);\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/form/client.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'mageUtils',\n    'uiClass'\n], function ($, _, utils, Class) {\n    'use strict';\n\n    /**\n     * Before save validate request.\n     *\n     * @param {Object} data\n     * @param {String} url\n     * @param {String} selectorPrefix\n     * @param {String} messagesClass\n     * @returns {*}\n     */\n    function beforeSave(data, url, selectorPrefix, messagesClass) {\n        var save = $.Deferred();\n\n        data = utils.serialize(utils.filterFormData(data));\n        data['form_key'] = window.FORM_KEY;\n\n        if (!url || url === 'undefined') {\n            return save.resolve();\n        }\n\n        $('body').trigger('processStart');\n\n        $.ajax({\n            url: url,\n            data: data,\n\n            /**\n             * Success callback.\n             * @param {Object} resp\n             * @returns {Boolean}\n             */\n            success: function (resp) {\n                if (!resp.error) {\n                    save.resolve();\n\n                    return true;\n                }\n\n                $('body').notification('clear');\n                $.each(resp.messages || [resp.message] || [], function (key, message) {\n                    $('body').notification('add', {\n                        error: resp.error,\n                        message: message,\n\n                        /**\n                         * Insert method.\n                         *\n                         * @param {String} msg\n                         */\n                        insertMethod: function (msg) {\n                            var $wrapper = $('<div></div>').addClass(messagesClass).html(msg);\n\n                            $('.page-main-actions', selectorPrefix).after($wrapper);\n                            $('html, body').animate({\n                                scrollTop: $('.page-main-actions', selectorPrefix).offset().top\n                            });\n                        }\n                    });\n                });\n            },\n\n            /**\n             * Complete callback.\n             */\n            complete: function () {\n                $('body').trigger('processStop');\n            }\n        });\n\n        return save.promise();\n    }\n\n    return Class.extend({\n\n        /**\n         * Assembles data and submits it using 'utils.submit' method\n         */\n        save: function (data, options) {\n            var url = this.urls.beforeSave,\n                save = this._save.bind(this, data, options);\n\n            beforeSave(data, url, this.selectorPrefix, this.messagesClass).then(save);\n\n            return this;\n        },\n\n        /**\n         * Save data.\n         *\n         * @param {Object} data\n         * @param {Object} options\n         * @returns {Object}\n         * @private\n         */\n        _save: function (data, options) {\n            var url = this.urls.save;\n\n            $('body').trigger('processStart');\n            options = options || {};\n\n            if (!options.redirect) {\n                url += 'back/edit';\n            }\n\n            if (options.ajaxSave) {\n                utils.ajaxSubmit({\n                    url: url,\n                    data: data\n                }, options);\n\n                $('body').trigger('processStop');\n\n                return this;\n            }\n\n            utils.submit({\n                url: url,\n                data: data\n            }, options.attributes);\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/form/form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'Magento_Ui/js/lib/spinner',\n    'rjsResolver',\n    './adapter',\n    'uiCollection',\n    'mageUtils',\n    'jquery',\n    'Magento_Ui/js/core/app',\n    'mage/validation'\n], function (_, loader, resolver, adapter, Collection, utils, $, app) {\n    'use strict';\n\n    /**\n     * Format params\n     *\n     * @param {Object} params\n     * @returns {Array}\n     */\n    function prepareParams(params) {\n        var result = '?';\n\n        _.each(params, function (value, key) {\n            result += key + '=' + value + '&';\n        });\n\n        return result.slice(0, -1);\n    }\n\n    /**\n     * Collect form data.\n     *\n     * @param {Array} items\n     * @returns {Object}\n     */\n    function collectData(items) {\n        var result = {},\n            name;\n\n        items = Array.prototype.slice.call(items);\n\n        items.forEach(function (item) {\n            switch (item.type) {\n                case 'checkbox':\n                    result[item.name] = +!!item.checked;\n                    break;\n\n                case 'radio':\n                    if (item.checked) {\n                        result[item.name] = item.value;\n                    }\n                    break;\n\n                case 'select-multiple':\n                    name = item.name.substring(0, item.name.length - 2); //remove [] from the name ending\n                    result[name] = _.pluck(item.selectedOptions, 'value');\n                    break;\n\n                default:\n                    result[item.name] = item.value;\n            }\n        });\n\n        return result;\n    }\n\n    /**\n     * Makes ajax request\n     *\n     * @param {Object} params\n     * @param {Object} data\n     * @param {String} url\n     * @returns {*}\n     */\n    function makeRequest(params, data, url) {\n        var save = $.Deferred();\n\n        data = utils.serialize(data);\n        data['form_key'] = window.FORM_KEY;\n\n        if (!url) {\n            save.resolve();\n        }\n\n        $('body').trigger('processStart');\n\n        $.ajax({\n            url: url + prepareParams(params),\n            data: data,\n            dataType: 'json',\n\n            /**\n             * Success callback.\n             * @param {Object} resp\n             * @returns {Boolean}\n             */\n            success: function (resp) {\n                if (resp.ajaxExpired) {\n                    window.location.href = resp.ajaxRedirect;\n                }\n\n                if (!resp.error) {\n                    save.resolve(resp);\n\n                    return true;\n                }\n\n                $('body').notification('clear');\n                $.each(resp.messages, function (key, message) {\n                    $('body').notification('add', {\n                        error: resp.error,\n                        message: message,\n\n                        /**\n                         * Inserts message on page\n                         * @param {String} msg\n                         */\n                        insertMethod: function (msg) {\n                            $('.page-main-actions').after(msg);\n                        }\n                    });\n                });\n            },\n\n            /**\n             * Complete callback.\n             */\n            complete: function () {\n                $('body').trigger('processStop');\n            }\n        });\n\n        return save.promise();\n    }\n\n    /**\n     * Check if fields is valid.\n     *\n     * @param {Array}items\n     * @returns {Boolean}\n     */\n    function isValidFields(items) {\n        var result = true;\n\n        _.each(items, function (item) {\n            if (!$.validator.validateSingleElement(item)) {\n                result = false;\n            }\n        });\n\n        return result;\n    }\n\n    return Collection.extend({\n        defaults: {\n            additionalFields: [],\n            additionalInvalid: false,\n            selectorPrefix: '.page-content',\n            messagesClass: 'messages',\n            errorClass: '.admin__field._error',\n            eventPrefix: '.${ $.index }',\n            ajaxSave: false,\n            ajaxSaveType: 'default',\n            imports: {\n                reloadUrl: '${ $.provider}:reloadUrl'\n            },\n            listens: {\n                selectorPrefix: 'destroyAdapter initAdapter',\n                '${ $.name }.${ $.reloadItem }': 'params.set reload'\n            },\n            exports: {\n                selectorPrefix: '${ $.provider }:client.selectorPrefix',\n                messagesClass: '${ $.provider }:client.messagesClass'\n            }\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super()\n                .initAdapter();\n\n            resolver(this.hideLoader, this);\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            return this._super()\n                .observe([\n                    'responseData',\n                    'responseStatus'\n                ]);\n        },\n\n        /** @inheritdoc */\n        initConfig: function () {\n            this._super();\n\n            this.selector = '[data-form-part=' + this.namespace + ']';\n\n            return this;\n        },\n\n        /**\n         * Initialize adapter handlers.\n         *\n         * @returns {Object}\n         */\n        initAdapter: function () {\n            adapter.on({\n                'reset': this.reset.bind(this),\n                'save': this.save.bind(this, true, {}),\n                'saveAndContinue': this.save.bind(this, false, {})\n            }, this.selectorPrefix, this.eventPrefix);\n\n            return this;\n        },\n\n        /**\n         * Destroy adapter handlers.\n         *\n         * @returns {Object}\n         */\n        destroyAdapter: function () {\n            adapter.off([\n                'reset',\n                'save',\n                'saveAndContinue'\n            ], this.eventPrefix);\n\n            return this;\n        },\n\n        /**\n         * Hide loader.\n         *\n         * @returns {Object}\n         */\n        hideLoader: function () {\n            loader.get(this.name).hide();\n\n            return this;\n        },\n\n        /**\n         * Validate and save form.\n         *\n         * @param {String} redirect\n         * @param {Object} data\n         */\n        save: function (redirect, data) {\n            this.validate();\n\n            if (!this.additionalInvalid && !this.source.get('params.invalid')) {\n                this.setAdditionalData(data)\n                    .submit(redirect);\n            } else {\n                this.focusInvalid();\n            }\n        },\n\n        /**\n         * Tries to set focus on first invalid form field.\n         *\n         * @returns {Object}\n         */\n        focusInvalid: function () {\n            var invalidField = _.find(this.delegate('checkInvalid'));\n\n            if (!_.isUndefined(invalidField) && _.isFunction(invalidField.focused)) {\n                invalidField.focused(true);\n            }\n\n            return this;\n        },\n\n        /**\n         * Set additional data to source before form submit and after validation.\n         *\n         * @param {Object} data\n         * @returns {Object}\n         */\n        setAdditionalData: function (data) {\n            _.each(data, function (value, name) {\n                this.source.set('data.' + name, value);\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Submits form\n         *\n         * @param {String} redirect\n         */\n        submit: function (redirect) {\n            var additional = collectData(this.additionalFields),\n                source = this.source;\n\n            _.each(additional, function (value, name) {\n                source.set('data.' + name, value);\n            });\n\n            source.save({\n                redirect: redirect,\n                ajaxSave: this.ajaxSave,\n                ajaxSaveType: this.ajaxSaveType,\n                response: {\n                    data: this.responseData,\n                    status: this.responseStatus\n                },\n                attributes: {\n                    id: this.namespace\n                }\n            });\n        },\n\n        /**\n         * Validates each element and returns true, if all elements are valid.\n         */\n        validate: function () {\n            this.additionalFields = document.querySelectorAll(this.selector);\n            this.source.set('params.invalid', false);\n            this.source.trigger('data.validate');\n            this.set('additionalInvalid', !isValidFields(this.additionalFields));\n        },\n\n        /**\n         * Trigger reset form data.\n         */\n        reset: function () {\n            this.source.trigger('data.reset');\n            $('[data-bind*=datepicker]').val('');\n        },\n\n        /**\n         * Trigger overload form data.\n         */\n        overload: function () {\n            this.source.trigger('data.overload');\n        },\n\n        /**\n         * Updates data from server.\n         */\n        reload: function () {\n            makeRequest(this.params, this.data, this.reloadUrl).then(function (data) {\n                app(data, true);\n            });\n        }\n    });\n});\n","Magento_Ui/js/form/provider.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiElement',\n    './client',\n    'mageUtils'\n], function (_, Element, Client, utils) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            clientConfig: {\n                urls: {\n                    save: '${ $.submit_url }',\n                    beforeSave: '${ $.validate_url }'\n                }\n            },\n            ignoreTmpls: {\n                data: true\n            }\n        },\n\n        /**\n         * Initializes provider component.\n         *\n         * @returns {Provider} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .initClient();\n\n            return this;\n        },\n\n        /**\n         * Initializes client component.\n         *\n         * @returns {Provider} Chainable.\n         */\n        initClient: function () {\n            this.client = new Client(this.clientConfig);\n\n            return this;\n        },\n\n        /**\n         * Saves currently available data.\n         *\n         * @param {Object} [options] - Addtitional request options.\n         * @returns {Provider} Chainable.\n         */\n        save: function (options) {\n            var data = this.get('data');\n\n            this.client.save(data, options);\n\n            return this;\n        },\n\n        /**\n         * Update data that stored in provider.\n         *\n         * @param {Boolean} isProvider\n         * @param {Object} newData\n         * @param {Object} oldData\n         *\n         * @returns {Provider}\n         */\n        updateConfig: function (isProvider, newData, oldData) {\n            if (isProvider === true) {\n                this.setData(oldData, newData, this);\n            }\n\n            return this;\n        },\n\n        /**\n         *  Set data to provider based on current data.\n         *\n         * @param {Object} oldData\n         * @param {Object} newData\n         * @param {Provider} current\n         * @param {String} parentPath\n         */\n        setData: function (oldData, newData, current, parentPath) {\n            _.each(newData, function (val, key) {\n                if (_.isObject(val) || _.isArray(val)) {\n                    this.setData(oldData[key], val, current[key], utils.fullPath(parentPath, key));\n                } else if (val != oldData[key] && oldData[key] == current[key]) {//eslint-disable-line eqeqeq\n                    this.set(utils.fullPath(parentPath, key), val);\n                }\n            }, this);\n        }\n    });\n});\n","Magento_Ui/js/form/adapter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Ui/js/form/adapter/buttons'\n], function ($, _, buttons) {\n    'use strict';\n\n    var selectorPrefix = '',\n        eventPrefix;\n\n    /**\n     * Initialize listener.\n     *\n     * @param {Function} callback\n     * @param {String} action\n     */\n    function initListener(callback, action) {\n        var selector    = selectorPrefix ? selectorPrefix + ' ' + buttons[action] : buttons[action],\n            elem        = $(selector)[0];\n\n        if (!elem) {\n            return;\n        }\n\n        if (elem.onclick) {\n            elem.onclick = null;\n        }\n\n        $(elem).on('click' + eventPrefix, callback);\n    }\n\n    /**\n     * Destroy listener.\n     *\n     * @param {String} action\n     */\n    function destroyListener(action) {\n        var selector    = selectorPrefix ? selectorPrefix + ' ' + buttons[action] : buttons[action],\n            elem        = $(selector)[0];\n\n        if (!elem) {\n            return;\n        }\n\n        if (elem.onclick) {\n            elem.onclick = null;\n        }\n\n        $(elem).off('click' + eventPrefix);\n    }\n\n    return {\n\n        /**\n         * Attaches events handlers.\n         *\n         * @param {Object} handlers\n         * @param {String} selectorPref\n         * @param {String} eventPref\n         */\n        on: function (handlers, selectorPref, eventPref) {\n            selectorPrefix = selectorPrefix || selectorPref;\n            eventPrefix = eventPref;\n            _.each(handlers, initListener);\n            selectorPrefix = '';\n        },\n\n        /**\n         * Removes events handlers.\n         *\n         * @param {Object} handlers\n         * @param {String} eventPref\n         */\n        off: function (handlers, eventPref) {\n            eventPrefix = eventPref;\n            _.each(handlers, destroyListener);\n        }\n    };\n});\n","Magento_Ui/js/form/switcher.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiRegistry',\n    'uiClass'\n], function (_, registry, Class) {\n    'use strict';\n\n    return Class.extend({\n        defaults: {\n            rules: []\n        },\n\n        /**\n         * Initializes instance of a DataSwitcher.\n         *\n         * @returns {DataSwitcher} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .initRules();\n\n            return this;\n        },\n\n        /**\n         *\n         * @returns {DataSwitcher} Chainable.\n         */\n        initRules: function () {\n            this.rules.forEach(this.initRule, this);\n\n            return this;\n        },\n\n        /**\n         *\n         * @param {Object} rule - Rule definition.\n         * @returns {DataSwitcher} Chainable.\n         */\n        initRule: function (rule) {\n            var handler = this.onValueChange.bind(this, rule);\n\n            if (!rule.target) {\n                rule.target = this.target;\n            }\n\n            if (!rule.property) {\n                rule.property = this.property;\n            }\n\n            registry.get(rule.target, function (target) {\n                this.applyRule(rule, target.get(rule.property));\n                target.on(rule.property, handler);\n            }.bind(this));\n\n            return this;\n        },\n\n        /**\n         *\n         * @param {Object} rule - Rule definition.\n         * @returns {DataSwitcher} Chainable.\n         */\n        addRule: function (rule) {\n            this.rules.push(rule);\n            this.initRule(rule);\n\n            return this;\n        },\n\n        /**\n         *\n         * @param {Object} rule - Rule object.\n         * @param {*} value - Current value associated with a rule.\n         */\n        applyRule: function (rule, value) {\n            var actions = rule.actions;\n\n            //TODO Refactor this logic in scope of MAGETWO-48585\n            /* eslint-disable eqeqeq */\n            if (rule.value != value) {\n                return;\n            } else if (rule.strict) {\n                return;\n            }\n\n            /* eslint-enable eqeqeq */\n            actions.forEach(this.applyAction, this);\n        },\n\n        /**\n         *\n         * @param {Object} action - Action object.\n         */\n        applyAction: function (action) {\n            registry.get(action.target, function (target) {\n                var callback = target[action.callback];\n\n                callback.apply(target, action.params || []);\n            });\n        },\n\n        /**\n         *\n         * @param {Object} rule - Rules object.\n         * @param {*} value - Current value associated with a rule.\n         */\n        onValueChange: function (rule, value) {\n            this.applyRule(rule, value);\n        }\n    });\n});\n","Magento_Ui/js/form/adapter/buttons.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine(function () {\n    'use strict';\n\n    return {\n        'reset': '#reset',\n        'save': '#save',\n        'saveAndContinue': '#save_and_continue'\n    };\n});\n","Magento_Ui/js/form/components/multiline.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    './group'\n], function (Group) {\n    'use strict';\n\n    return Group.extend({\n        defaults: {\n            links: {\n                value: '${ $.provider }:${ $.dataScope }'\n            }\n        },\n\n        /**\n         * Initialize Multiline component.\n         *\n         * @returns {Object}\n         */\n        initialize: function () {\n            return this._super()\n                ._prepareValue();\n        },\n\n        /**\n         * {@inheritdoc}\n         */\n        initObservable: function () {\n            this._super()\n                .observe('value');\n\n            return this;\n        },\n\n        /**\n         * Prepare value for Multiline options.\n         *\n         * @returns {Object} Chainable.\n         * @private\n         */\n        _prepareValue: function () {\n            var value = this.value();\n\n            if (typeof value === 'string') {\n                this.value(value.split('\\n'));\n            }\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/form/components/fieldset.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Ui/js/lib/collapsible',\n    'underscore'\n], function (Collapsible, _) {\n    'use strict';\n\n    return Collapsible.extend({\n        defaults: {\n            template: 'ui/form/fieldset',\n            collapsible: false,\n            changed: false,\n            loading: false,\n            error: false,\n            opened: false,\n            level: 0,\n            visible: true,\n            initializeFieldsetDataByDefault: false, /* Data in some fieldsets should be initialized before open */\n            disabled: false,\n            listens: {\n                'opened': 'onVisibilityChange'\n            },\n            additionalClasses: {}\n        },\n\n        /**\n         * Extends instance with defaults. Invokes parent initialize method.\n         * Calls initListeners and pushParams methods.\n         */\n        initialize: function () {\n            _.bindAll(this, 'onChildrenUpdate', 'onChildrenError', 'onContentLoading');\n\n            return this._super()\n                ._setClasses();\n        },\n\n        /**\n         * Initializes components' configuration.\n         *\n         * @returns {Fieldset} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n            this._wasOpened = this.opened || !this.collapsible;\n\n            return this;\n        },\n\n        /**\n         * Calls initObservable of parent class.\n         * Defines observable properties of instance.\n         *\n         * @returns {Object} Reference to instance\n         */\n        initObservable: function () {\n            this._super()\n                .observe('changed loading error visible');\n\n            return this;\n        },\n\n        /**\n         * Calls parent's initElement method.\n         * Assigns callbacks on various events of incoming element.\n         *\n         * @param  {Object} elem\n         * @return {Object} - reference to instance\n         */\n        initElement: function (elem) {\n            elem.initContainer(this);\n\n            elem.on({\n                'update': this.onChildrenUpdate,\n                'loading': this.onContentLoading,\n                'error': this.onChildrenError\n            });\n\n            if (this.disabled) {\n                try {\n                    elem.disabled(true);\n                }\n                catch (e) {\n\n                }\n            }\n\n            return this;\n        },\n\n        /**\n         * Is being invoked on children update.\n         * Sets changed property to one incoming.\n         *\n         * @param  {Boolean} hasChanged\n         */\n        onChildrenUpdate: function (hasChanged) {\n            if (!hasChanged) {\n                hasChanged = _.some(this.delegate('hasChanged'));\n            }\n\n            this.bubble('update', hasChanged);\n            this.changed(hasChanged);\n        },\n\n        /**\n         * Extends 'additionalClasses' object.\n         *\n         * @returns {Group} Chainable.\n         */\n        _setClasses: function () {\n            var additional = this.additionalClasses,\n                classes;\n\n            if (_.isString(additional)) {\n                additional = this.additionalClasses.split(' ');\n                classes = this.additionalClasses = {};\n\n                additional.forEach(function (name) {\n                    classes[name] = true;\n                }, this);\n            }\n\n            _.extend(this.additionalClasses, {\n                'admin__collapsible-block-wrapper': this.collapsible,\n                _show: this.opened,\n                _hide: !this.opened,\n                _disabled: this.disabled\n            });\n\n            return this;\n        },\n\n        /**\n         * Handler of the \"opened\" property changes.\n         *\n         * @param {Boolean} isOpened\n         */\n        onVisibilityChange: function (isOpened) {\n            if (!this._wasOpened) {\n                this._wasOpened = isOpened;\n            }\n        },\n\n        /**\n         * Is being invoked on children validation error.\n         * Sets error property to one incoming.\n         *\n         * @param {String} message - error message.\n         */\n        onChildrenError: function (message) {\n            var hasErrors = false;\n\n            if (!message) {\n                hasErrors = this._isChildrenHasErrors(hasErrors, this);\n            }\n\n            this.error(hasErrors || message);\n\n            if (hasErrors || message) {\n                this.open();\n            }\n        },\n\n        /**\n         * Returns errors of children if exist\n         *\n         * @param {Boolean} hasErrors\n         * @param {*} container\n         * @return {Boolean}\n         * @private\n         */\n        _isChildrenHasErrors: function (hasErrors, container) {\n            var self = this;\n\n            if (hasErrors === false && container.hasOwnProperty('elems')) {\n                hasErrors = container.elems.some('error');\n\n                if (hasErrors === false && container.hasOwnProperty('_elems')) {\n                    container._elems.forEach(function (child) {\n\n                        if (hasErrors === false) {\n                            hasErrors = self._isChildrenHasErrors(hasErrors, child);\n                        }\n                    });\n                }\n            }\n\n            return hasErrors;\n        },\n\n        /**\n         * Callback that sets loading property to true.\n         */\n        onContentLoading: function (isLoading) {\n            this.loading(isLoading);\n        }\n    });\n});\n","Magento_Ui/js/form/components/group.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiCollection'\n], function (_, Collection) {\n    'use strict';\n\n    return Collection.extend({\n        defaults: {\n            visible: true,\n            label: '',\n            showLabel: true,\n            required: false,\n            template: 'ui/group/group',\n            fieldTemplate: 'ui/form/field',\n            breakLine: true,\n            validateWholeGroup: false,\n            additionalClasses: {}\n        },\n\n        /**\n         * Extends this with defaults and config.\n         * Then calls initObservable, iniListenes and extractData methods.\n         */\n        initialize: function () {\n            this._super()\n                ._setClasses();\n\n            return this;\n        },\n\n        /**\n         * Calls initObservable of parent class.\n         * Defines observable properties of instance.\n         *\n         * @return {Object} - reference to instance\n         */\n        initObservable: function () {\n            this._super()\n                .observe('visible')\n                .observe({\n                    required: !!+this.required\n                });\n\n            return this;\n        },\n\n        /**\n         * Extends 'additionalClasses' object.\n         *\n         * @returns {Group} Chainable.\n         */\n        _setClasses: function () {\n            var additional = this.additionalClasses,\n                classes;\n\n            if (_.isString(additional)) {\n                additional = this.additionalClasses.split(' ');\n                classes = this.additionalClasses = {};\n\n                additional.forEach(function (name) {\n                    classes[name] = true;\n                }, this);\n            }\n\n            _.extend(this.additionalClasses, {\n                'admin__control-grouped': !this.breakLine,\n                'admin__control-fields': this.breakLine,\n                required:   this.required,\n                _error:     this.error,\n                _disabled:  this.disabled\n            });\n\n            return this;\n        },\n\n        /**\n         * Defines if group has only one element.\n         * @return {Boolean}\n         */\n        isSingle: function () {\n            return this.elems.getLength() === 1;\n        },\n\n        /**\n         * Defines if group has multiple elements.\n         * @return {Boolean}\n         */\n        isMultiple: function () {\n            return this.elems.getLength() > 1;\n        },\n\n        /**\n         * Returns an array of child components previews.\n         *\n         * @returns {Array}\n         */\n        getPreview: function () {\n            return this.elems.map('getPreview');\n        }\n    });\n});\n","Magento_Ui/js/form/components/tab_group.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'Magento_Ui/js/lib/collapsible'\n], function (_, Collapsible) {\n    'use strict';\n\n    return Collapsible.extend({\n        defaults: {\n            listens: {\n                '${ $.provider }:data.validate': 'onValidate'\n            },\n            collapsible: false,\n            opened: true\n        },\n\n        /**\n         * Invokes initElement method of parent class, calls 'initActivation' method\n         * passing element to it.\n         * @param {Object} elem\n         * @returns {Object} - reference to instance\n         */\n        initElement: function (elem) {\n            this._super()\n                .initActivation(elem);\n\n            return this;\n        },\n\n        /**\n         * Activates element if one is first or if one has 'active' propert\n         * set to true.\n         *\n         * @param  {Object} elem\n         * @returns {Object} - reference to instance\n         */\n        initActivation: function (elem) {\n            var elems   = this.elems(),\n                isFirst = !elems.indexOf(elem);\n\n            if (isFirst || elem.active()) {\n                elem.activate();\n            }\n\n            return this;\n        },\n\n        /**\n         * Delegates 'validate' method on element, then reads 'invalid' property\n         * of params storage, and if defined, activates element, sets\n         * 'allValid' property of instance to false and sets invalid's\n         * 'focused' property to true.\n         *\n         * @param {Object} elem\n         */\n        validate: function (elem) {\n            var result  = elem.delegate('validate'),\n                invalid;\n\n            invalid = _.find(result, function (item) {\n                return typeof item !== 'undefined' && !item.valid;\n            });\n\n            if (invalid) {\n                elem.activate();\n                invalid.target.focused(true);\n            }\n\n            return invalid;\n        },\n\n        /**\n         * Sets 'allValid' property of instance to true, then calls 'validate' method\n         * of instance for each element.\n         */\n        onValidate: function () {\n            this.elems.sortBy(function (elem) {\n                return !elem.active();\n            }).some(this.validate, this);\n        }\n    });\n});\n","Magento_Ui/js/form/components/collection.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    'uiRegistry',\n    'uiComponent',\n    'uiLayout',\n    'Magento_Ui/js/modal/confirm'\n], function (_, utils, registry, Component, layout, confirm) {\n    'use strict';\n\n    var childTemplate = {\n        parent: '${ $.$data.name }',\n        name: '${ $.$data.childIndex }',\n        dataScope: '${ $.name }',\n        nodeTemplate: '${ $.$data.name }.${ $.$data.itemTemplate }'\n    };\n\n    return Component.extend({\n        defaults: {\n            lastIndex: 0,\n            template: 'ui/form/components/collection'\n        },\n\n        /**\n         * Extends instance with default config, calls initialize of parent\n         * class, calls initChildren method.\n         */\n        initialize: function () {\n            this._super()\n                .initChildren();\n\n            return this;\n        },\n\n        /**\n         * Activates the incoming child and triggers the update event.\n         *\n         * @param {Object} elem - Incoming child.\n         */\n        initElement: function (elem) {\n            this._super();\n\n            elem.activate();\n\n            this.bubble('update');\n\n            return this;\n        },\n\n        /**\n         * Loops over corresponding data in data storage,\n         * creates child for each and pushes it's identifier to initialItems array.\n         *\n         * @returns {Collection} Chainable.\n         */\n        initChildren: function () {\n            var children = this.source.get(this.dataScope),\n                initial = this.initialItems = [];\n\n            _.each(children, function (item, index) {\n                initial.push(index);\n                this.addChild(index);\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Creates new item of collection, based on incoming 'index'.\n         * If not passed creates one with 'new_' prefix.\n         *\n         * @param {String|Object} [index] - Index of a child.\n         * @returns {Collection} Chainable.\n         */\n        addChild: function (index) {\n            this.childIndex = !_.isString(index) ?\n                'new_' + this.lastIndex++ :\n                index;\n\n            layout([utils.template(childTemplate, this)]);\n\n            return this;\n        },\n\n        /**\n         * Returns true if current set of items differ from initial one,\n         * or if some child has been changed.\n         *\n         * @returns {Boolean}\n         */\n        hasChanged: function () {\n            var initial = this.initialItems,\n                current = this.elems.pluck('index'),\n                changed = !utils.equalArrays(initial, current);\n\n            return changed || this.elems.some(function (elem) {\n                return _.some(elem.delegate('hasChanged'));\n            });\n        },\n\n        /**\n         * Initiates validation of its' children components.\n         *\n         * @returns {Array} An array of validation results.\n         */\n        validate: function () {\n            var elems;\n\n            this.allValid = true;\n\n            elems = this.elems.sortBy(function (elem) {\n                return !elem.active();\n            });\n\n            elems = elems.map(this._validate, this);\n\n            return _.flatten(elems);\n        },\n\n        /**\n         * Iterator function for components validation.\n         * Activates first invalid child component.\n         *\n         * @param {Object} elem - Element to run validation on.\n         * @returns {Array} An array of validation results.\n         */\n        _validate: function (elem) {\n            var result = elem.delegate('validate'),\n                invalid;\n\n            invalid = _.some(result, function (item) {\n                return !item.valid;\n            });\n\n            if (this.allValid && invalid) {\n                this.allValid = false;\n\n                elem.activate();\n            }\n\n            return result;\n        },\n\n        /**\n         * Creates function that removes element\n         * from collection using '_removeChild' method.\n         * @param  {Object} elem - Element that should be removed.\n         * @deprecated Not used anymore\n         */\n        removeAddress: function (elem) {\n            var self = this;\n\n            confirm({\n                content: this.removeMessage,\n                actions: {\n                    /** @inheritdoc */\n                    confirm: function () {\n                        self._removeAddress(elem);\n                    }\n                }\n            });\n        },\n\n        /**\n         * Removes element from both collection and data storage,\n         * activates first element if removed one was active,\n         * triggers 'update' event.\n         *\n         * @param {Object} elem - Element to remove.\n         */\n        _removeAddress: function (elem) {\n            var isActive = elem.active(),\n                first;\n\n            elem.destroy();\n\n            first = this.elems.first();\n\n            if (first && isActive) {\n                first.activate();\n            }\n\n            this.bubble('update');\n        }\n    });\n});\n","Magento_Ui/js/form/components/button.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'uiElement',\n    'uiRegistry',\n    'uiLayout',\n    'mageUtils',\n    'underscore'\n], function (Element, registry, layout, utils, _) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            buttonClasses: {},\n            additionalClasses: {},\n            displayArea: 'outsideGroup',\n            displayAsLink: false,\n            elementTmpl: 'ui/form/element/button',\n            template: 'ui/form/components/button/simple',\n            visible: true,\n            disabled: false,\n            title: '',\n            buttonTextId: '',\n            ariLabelledby: ''\n        },\n\n        /**\n         * Initializes component.\n         *\n         * @returns {Object} Chainable.\n         */\n        initialize: function () {\n            return this._super()\n                ._setClasses()\n                ._setButtonClasses();\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            return this._super()\n                .observe([\n                    'visible',\n                    'disabled',\n                    'title',\n                    'childError'\n                ]);\n        },\n\n        /**\n         * Performs configured actions\n         */\n        action: function () {\n            this.actions.forEach(this.applyAction, this);\n        },\n\n        /**\n         * Apply action on target component,\n         * but previously create this component from template if it is not existed\n         *\n         * @param {Object} action - action configuration\n         */\n        applyAction: function (action) {\n            var targetName = action.targetName,\n                params = utils.copy(action.params) || [],\n                actionName = action.actionName,\n                target;\n\n            if (!registry.has(targetName)) {\n                this.getFromTemplate(targetName);\n            }\n            target = registry.async(targetName);\n\n            if (target && typeof target === 'function' && actionName) {\n                params.unshift(actionName);\n                target.apply(target, params);\n            }\n        },\n\n        /**\n         * Create target component from template\n         *\n         * @param {Object} targetName - name of component,\n         * that supposed to be a template and need to be initialized\n         */\n        getFromTemplate: function (targetName) {\n            var parentName = targetName.split('.'),\n                index = parentName.pop(),\n                child;\n\n            parentName = parentName.join('.');\n            child = utils.template({\n                parent: parentName,\n                name: index,\n                nodeTemplate: targetName\n            });\n            layout([child]);\n        },\n\n        /**\n         * Extends 'additionalClasses' object.\n         *\n         * @returns {Object} Chainable.\n         */\n        _setClasses: function () {\n            if (typeof this.additionalClasses === 'string') {\n                if (this.additionalClasses === '') {\n                    this.additionalClasses = {};\n\n                    return this;\n                }\n\n                this.additionalClasses = this.additionalClasses\n                    .trim()\n                    .split(' ')\n                    .reduce(function (classes, name) {\n                        classes[name] = true;\n\n                        return classes;\n                    }, {}\n                );\n            }\n\n            return this;\n        },\n\n        /**\n         * Extends 'buttonClasses' object.\n         *\n         * @returns {Object} Chainable.\n         */\n        _setButtonClasses: function () {\n            var additional = this.buttonClasses;\n\n            if (_.isString(additional)) {\n                this.buttonClasses = {};\n\n                if (additional.trim().length) {\n                    additional = additional.trim().split(' ');\n\n                    additional.forEach(function (name) {\n                        if (name.length) {\n                            this.buttonClasses[name] = true;\n                        }\n                    }, this);\n                }\n            }\n\n            _.extend(this.buttonClasses, {\n                'action-basic': !this.displayAsLink,\n                'action-additional': this.displayAsLink\n            });\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/form/components/insert-form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    './insert',\n    'mageUtils',\n    'jquery'\n], function (Insert, utils, $) {\n    'use strict';\n\n    /**\n     * Get page actions element.\n     *\n     * @param {String} elem\n     * @param {String} actionsClass\n     * @returns {String}\n     */\n    function getPageActions(elem, actionsClass) {\n        var el = document.createElement('div');\n\n        el.innerHTML = elem;\n\n        return el.getElementsByClassName(actionsClass)[0];\n    }\n\n    /**\n     * Return element without page actions toolbar\n     *\n     * @param {String} elem\n     * @param {String} actionsClass\n     * @returns {String}\n     */\n    function removePageActions(elem, actionsClass) {\n        var el = document.createElement('div'),\n            actions;\n\n        el.innerHTML = elem;\n        actions = el.getElementsByClassName(actionsClass)[0];\n\n        if (actions) {\n            el.removeChild(actions);\n        }\n\n        return el.innerHTML;\n    }\n\n    return Insert.extend({\n        defaults: {\n            externalFormName: '${ $.ns }.${ $.ns }',\n            pageActionsClass: 'page-actions',\n            actionsContainerClass: 'page-main-actions',\n            exports: {\n                prefix: '${ $.externalFormName }:selectorPrefix'\n            },\n            imports: {\n                toolbarSection: '${ $.toolbarContainer }:toolbarSection',\n                prefix: '${ $.toolbarContainer }:rootSelector',\n                messagesClass: '${ $.externalFormName }:messagesClass'\n            },\n            settings: {\n                ajax: {\n                    ajaxSave: true,\n                    exports: {\n                        ajaxSave: '${ $.externalFormName }:ajaxSave'\n                    },\n                    imports: {\n                        responseStatus: '${ $.externalFormName }:responseStatus',\n                        responseData: '${ $.externalFormName }:responseData'\n                    }\n                }\n            },\n            modules: {\n                externalForm: '${ $.externalFormName }'\n            }\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            return this._super()\n                .observe('responseStatus');\n        },\n\n        /** @inheritdoc */\n        initConfig: function (config) {\n            var defaults = this.constructor.defaults;\n\n            utils.extend(defaults, defaults.settings[config.formSubmitType] || {});\n\n            return this._super();\n        },\n\n        /** @inheritdoc*/\n        destroyInserted: function () {\n            if (this.isRendered && this.externalForm()) {\n                this.externalForm().delegate('destroy');\n                this.removeActions();\n                this.responseStatus(undefined);\n                this.responseData = {};\n            }\n\n            return this._super();\n        },\n\n        /** @inheritdoc */\n        onRender: function (data) {\n            var actions = getPageActions(data, this.pageActionsClass);\n\n            if (!data.length) {\n                return this;\n            }\n            data = removePageActions(data, this.pageActionsClass);\n            this.renderActions(actions);\n            this._super(data);\n        },\n\n        /**\n         * Insert actions in toolbar.\n         *\n         * @param {String} actions\n         */\n        renderActions: function (actions) {\n            var $container = $('<div></div>');\n\n            $container\n                .addClass(this.actionsContainerClass)\n                .append(actions);\n\n            this.formHeader = $container;\n\n            $(this.toolbarSection).append(this.formHeader);\n        },\n\n        /**\n         * Remove actions toolbar.\n         */\n        removeActions: function () {\n            $(this.formHeader).siblings('.' + this.messagesClass).remove();\n            $(this.formHeader).remove();\n            this.formHeader = $();\n        },\n\n        /**\n         * Reset external form data.\n         */\n        resetForm: function () {\n            if (this.externalSource()) {\n                this.externalSource().trigger('data.reset');\n                this.responseStatus(undefined);\n            }\n        }\n    });\n});\n","Magento_Ui/js/form/components/html.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'underscore',\n    'uiComponent'\n], function ($, _, Component) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            content:        '',\n            showSpinner:    false,\n            loading:        false,\n            visible:        true,\n            template:       'ui/content/content',\n            additionalClasses: {},\n            ignoreTmpls: {\n                content: true\n            }\n        },\n\n        /**\n         * Extends instance with default config, calls 'initialize' method of\n         *     parent, calls 'initAjaxConfig'\n         */\n        initialize: function () {\n            _.bindAll(this, 'onContainerToggle', 'onDataLoaded');\n\n            this._super()\n                ._setClasses()\n                .initAjaxConfig();\n\n            return this;\n        },\n\n        /**\n         * Calls 'initObservable' method of parent, initializes observable\n         * properties of instance\n         *\n         * @return {Object} - reference to instance\n         */\n        initObservable: function () {\n            this._super()\n                .observe('content loading visible');\n\n            return this;\n        },\n\n        /**\n         * Extends 'additionalClasses' object.\n         *\n         * @returns {Group} Chainable.\n         */\n        _setClasses: function () {\n            var additional = this.additionalClasses,\n                classes;\n\n            if (_.isString(additional)) {\n                additional = this.additionalClasses.split(' ');\n                classes = this.additionalClasses = {};\n\n                additional.forEach(function (name) {\n                    classes[name] = true;\n                }, this);\n            }\n\n            _.extend(this.additionalClasses, {\n                'admin__scope-old': !!additional\n            });\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initContainer: function (parent) {\n            this._super();\n\n            parent.on('active', this.onContainerToggle);\n\n            return this;\n        },\n\n        /**\n         * Initializes default ajax config on instance\n         *\n         * @return {Object} - reference to instance\n         */\n        initAjaxConfig: function () {\n            this.ajaxConfig = {\n                url: this.url,\n                data: {\n                    FORM_KEY: window.FORM_KEY\n                },\n                success:    this.onDataLoaded\n            };\n\n            return this;\n        },\n\n        /**\n         * Calls 'loadData' if both 'active' variable and 'shouldLoad'\n         * property are truthy\n         *\n         * @param  {Boolean} active\n         */\n        onContainerToggle: function (active) {\n            if (active && this.shouldLoad()) {\n                this.loadData();\n            }\n        },\n\n        /**\n         * Defines if instance has 'content' property defined.\n         *\n         * @return {Boolean} [description]\n         */\n        hasData: function () {\n            return !!this.content();\n        },\n\n        /**\n         * Defines if instance should load external data\n         *\n         * @return {Boolean}\n         */\n        shouldLoad: function () {\n            return this.url && !this.hasData() && !this.loading();\n        },\n\n        /**\n         * Sets loading property to true, makes ajax call\n         *\n         * @return {Object} - reference to instance\n         */\n        loadData: function () {\n            this.loading(true);\n\n            $.ajax(this.ajaxConfig);\n\n            return this;\n        },\n\n        /**\n         * Ajax's request success handler. Calls 'updateContent' passing 'data'\n         * to it, then sets 'loading' property to false.\n         *\n         * @param  {String} data\n         */\n        onDataLoaded: function (data) {\n            this.updateContent(data)\n                .loading(false);\n        },\n\n        /**\n         * Sets incoming data 'content' property's value\n         *\n         * @param  {String} content\n         * @return {Object} - reference to instance\n         */\n        updateContent: function (content) {\n            this.content(content);\n\n            return this;\n        },\n\n        /**\n         * Content getter\n         *\n         * @returns {String}\n         */\n        getContentUnsanitizedHtml: function () {\n            return this.content();\n        }\n    });\n});\n","Magento_Ui/js/form/components/area.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    './tab'\n], function (_, Tab) {\n    'use strict';\n\n    return Tab.extend({\n        defaults: {\n            uniqueNs:   'params.activeArea',\n            template:   'ui/area',\n            changed:    false,\n            loading:    false\n        },\n\n        /**\n         * Extends instance with defaults. Invokes parent initialize method.\n         * Calls initListeners and pushParams methods.\n         */\n        initialize: function () {\n            _.bindAll(this, 'onChildrenUpdate', 'onContentLoading');\n\n            return this._super();\n        },\n\n        /**\n         * Calls initObservable of parent class.\n         * Defines observable properties of instance.\n         * @return {Object} - reference to instance\n         */\n        initObservable: function () {\n            this._super()\n                .observe('changed loading');\n\n            return this;\n        },\n\n        /**\n         * Calls parent's initElement method.\n         * Assigns callbacks on various events of incoming element.\n         * @param  {Object} elem\n         * @return {Object} - reference to instance\n         */\n        initElement: function (elem) {\n            this._super();\n\n            elem.on({\n                'update':   this.onChildrenUpdate,\n                'loading':  this.onContentLoading\n            });\n\n            return this;\n        },\n\n        /**\n         * Is being invoked on children update.\n         * Sets changed property to one incoming.\n         * Invokes setActive method if settings\n         * contain makeVisible property set to true.\n         *\n         * @param  {Boolean} hasChanged\n         */\n        onChildrenUpdate: function (hasChanged) {\n            if (!hasChanged) {\n                hasChanged = _.some(this.delegate('hasChanged'));\n            }\n\n            this.changed(hasChanged);\n        },\n\n        /**\n         * Callback that sets loading property to true.\n         */\n        onContentLoading: function (isLoading) {\n            this.loading(isLoading);\n        }\n    });\n});\n","Magento_Ui/js/form/components/tab.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'uiCollection'\n], function (Collection) {\n    'use strict';\n\n    return Collection.extend({\n        defaults: {\n            uniqueProp:     'active',\n            active:         false,\n            wasActivated:   false\n        },\n\n        /**\n         * Extends instance with defaults. Invokes parent initialize method.\n         * Calls initListeners and pushParams methods.\n         */\n        initialize: function () {\n            this._super()\n                .setUnique();\n        },\n\n        /**\n         * Calls initObservable of parent class.\n         * Defines observable properties of instance.\n         * @return {Object} - reference to instance\n         */\n        initObservable: function () {\n            this._super()\n                .observe('active wasActivated');\n\n            return this;\n        },\n\n        /**\n         * Sets active property to true, then invokes pushParams method.\n         */\n        activate: function () {\n            this.active(true);\n            this.wasActivated(true);\n\n            this.setUnique();\n\n            return true;\n        }\n    });\n});\n","Magento_Ui/js/form/components/collection/item.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    '../tab'\n], function (_, utils, Tab) {\n    'use strict';\n\n    var previewConfig = {\n        separator: ' ',\n        prefix: ''\n    };\n\n    /**\n     * Parses incoming data and returns result merged with default preview config\n     *\n     * @param  {Object|String} data\n     * @return {Object}\n     */\n    function parsePreview(data) {\n        if (typeof data == 'string') {\n            data = {\n                items: data\n            };\n        }\n\n        data.items = utils.stringToArray(data.items);\n\n        return _.defaults(data, previewConfig);\n    }\n\n    return Tab.extend({\n        defaults: {\n            label: '',\n            uniqueNs: 'activeCollectionItem',\n            previewTpl: 'ui/form/components/collection/preview'\n        },\n\n        /**\n         * Extends instance with default config, calls initializes of parent class\n         */\n        initialize: function () {\n            _.bindAll(this, 'buildPreview', 'hasPreview');\n\n            return this._super();\n        },\n\n        /**\n         * Calls initProperties of parent class, initializes properties\n         * of instance.\n         *\n         * @return {Object} - reference to instance\n         */\n        initConfig: function () {\n            this._super();\n\n            this.displayed = [];\n\n            return this;\n        },\n\n        /**\n         * Calls initObservable of parent class, initializes observable\n         * properties of instance.\n         *\n         * @return {Object} - reference to instance\n         */\n        initObservable: function () {\n            this._super()\n                .observe({\n                    noPreview: true,\n                    indexed: {}\n                });\n\n            return this;\n        },\n\n        /**\n         * Is being called when child element has been initialized,\n         *     calls initElement of parent class, binds to element's update event,\n         *     calls insertToArea and insertToIndexed methods passing element to it\n         *\n         * @param  {Object} elem\n         */\n        initElement: function (elem) {\n            this._super()\n                .insertToIndexed(elem);\n\n            return this;\n        },\n\n        /**\n         * Adds element to observable indexed object of instance\n         *\n         * @param  {Object} elem\n         * @return {Object} - reference to instance\n         */\n        insertToIndexed: function (elem) {\n            var indexed = this.indexed();\n\n            indexed[elem.index] = elem;\n\n            this.indexed(indexed);\n\n            return this;\n        },\n\n        /**\n         * Destroys current instance along with all of its' children.\n         * Overrides base method to clear data when this method is called.\n         */\n        destroy: function () {\n            this._super();\n            this._clearData();\n        },\n\n        /**\n         * Clears all data associated with component.\n         * @private\n         *\n         * @returns {Item} Chainable.\n         */\n        _clearData: function () {\n            this.source.remove(this.dataScope);\n\n            return this;\n        },\n\n        /**\n         * Formats incoming previews array via parsePreview function.\n         *\n         * @param  {Array} previews\n         * @return {Array} - formatted previews\n         */\n        formatPreviews: function (previews) {\n            return previews.map(parsePreview);\n        },\n\n        /**\n         * Creates string view of previews\n         *\n         * @param  {Object} data\n         * @return {Strict} - formatted preview string\n         */\n        buildPreview: function (data) {\n            var preview = this.getPreview(data.items),\n                prefix = data.prefix;\n\n            return prefix + preview.join(data.separator);\n        },\n\n        /**\n         * Defines if instance has preview for incoming data\n         *\n         * @param  {Object}  data\n         * @return {Boolean}\n         */\n        hasPreview: function (data) {\n            return !!this.getPreview(data.items).length;\n        },\n\n        /**\n         * Creates an array of previews for elements specified in incoming\n         * items array, calls updatePreview afterwards.\n         *\n         * @param  {Array} items - An array of element's indexes.\n         * @returns {Array} An array of previews.\n         */\n        getPreview: function (items) {\n            var elems = this.indexed(),\n                displayed = this.displayed,\n                preview;\n\n            items = items.map(function (index) {\n                var elem = elems[index];\n\n                preview = elem && elem.visible() ? elem.getPreview() : '';\n\n                preview = Array.isArray(preview) ?\n                    _.compact(preview).join(', ') :\n                    preview;\n\n                utils.toggle(displayed, index, !!preview);\n\n                return preview;\n            });\n\n            this.noPreview(!displayed.length);\n\n            return _.compact(items);\n        }\n    });\n});\n","Magento_Ui/js/form/element/date.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'moment',\n    'mageUtils',\n    './abstract',\n    'moment-timezone-with-data'\n], function (moment, utils, Abstract) {\n    'use strict';\n\n    return Abstract.extend({\n        defaults: {\n            options: {},\n\n            storeTimeZone: 'UTC',\n\n            validationParams: {\n                dateFormat: '${ $.outputDateFormat }'\n            },\n\n            /**\n             * Format of date that comes from the\n             * server (ICU Date Format).\n             *\n             * Used only in date picker mode\n             * (this.options.showsTime == false).\n             *\n             * @type {String}\n             */\n            inputDateFormat: 'y-MM-dd',\n\n            /**\n             * Format of date that should be sent to the\n             * server (ICU Date Format).\n             *\n             * Used only in date picker mode\n             * (this.options.showsTime == false).\n             *\n             * @type {String}\n             */\n            outputDateFormat: 'MM/dd/y',\n\n            /**\n             * Date/time format that is used to display date in\n             * the input field.\n             *\n             * @type {String}\n             */\n            pickerDateTimeFormat: '',\n\n            pickerDefaultDateFormat: 'MM/dd/y', // ICU Date Format\n            pickerDefaultTimeFormat: 'h:mm a', // ICU Time Format\n\n            elementTmpl: 'ui/form/element/date',\n\n            /**\n             * Format needed by moment timezone for conversion\n             */\n            timezoneFormat: 'YYYY-MM-DD HH:mm',\n\n            listens: {\n                'value': 'onValueChange',\n                'shiftedValue': 'onShiftedValueChange'\n            },\n\n            /**\n             * Date/time value shifted to corresponding timezone\n             * according to this.storeTimeZone property. This value\n             * will be sent to the server.\n             *\n             * @type {String}\n             */\n            shiftedValue: ''\n        },\n\n        /**\n         * Initializes regular properties of instance.\n         *\n         * @returns {Object} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n\n            if (!this.options.dateFormat) {\n                this.options.dateFormat = this.pickerDefaultDateFormat;\n            }\n\n            if (!this.options.timeFormat) {\n                this.options.timeFormat = this.pickerDefaultTimeFormat;\n            }\n\n            this.prepareDateTimeFormats();\n\n            return this;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        initObservable: function () {\n            return this._super().observe(['shiftedValue']);\n        },\n\n        /**\n         * @inheritdoc\n         */\n        getPreview: function () {\n            return this.shiftedValue();\n        },\n\n        /**\n         * Prepares and sets date/time value that will be displayed\n         * in the input field.\n         *\n         * @param {String} value\n         */\n        onValueChange: function (value) {\n            var shiftedValue;\n\n            if (value) {\n                if (this.options.showsTime && !this.options.timeOnly) {\n                    shiftedValue = moment.tz(value, 'UTC').tz(this.storeTimeZone);\n                } else {\n                    shiftedValue = moment(value, this.outputDateFormat, true);\n                }\n\n                if (!shiftedValue.isValid()) {\n                    shiftedValue = moment(value, this.inputDateFormat);\n                }\n                shiftedValue = shiftedValue.format(this.pickerDateTimeFormat);\n            } else {\n                shiftedValue = '';\n            }\n\n            if (shiftedValue !== this.shiftedValue()) {\n                this.shiftedValue(shiftedValue);\n            }\n        },\n\n        /**\n         * Prepares and sets date/time value that will be sent\n         * to the server.\n         *\n         * @param {String} shiftedValue\n         */\n        onShiftedValueChange: function (shiftedValue) {\n            var value,\n                formattedValue,\n                momentValue;\n\n            if (shiftedValue) {\n                momentValue = moment(shiftedValue, this.pickerDateTimeFormat);\n\n                if (this.options.showsTime && !this.options.timeOnly) {\n                    formattedValue = moment(momentValue).format(this.timezoneFormat);\n                    value = moment.tz(formattedValue, this.storeTimeZone).tz('UTC').toISOString();\n                } else {\n                    value = momentValue.format(this.outputDateFormat);\n                }\n            } else {\n                value = '';\n            }\n\n            if (value !== this.value()) {\n                this.value(value);\n            }\n        },\n\n        /**\n         * Prepares and converts all date/time formats to be compatible\n         * with moment.js library.\n         */\n        prepareDateTimeFormats: function () {\n            if (this.options.timeOnly) {\n                this.pickerDateTimeFormat = this.options.timeFormat;\n            } else {\n                this.pickerDateTimeFormat = this.options.dateFormat;\n\n                if (this.options.showsTime) {\n                    this.pickerDateTimeFormat += ' ' + this.options.timeFormat;\n                }\n            }\n\n            this.pickerDateTimeFormat = utils.convertToMomentFormat(this.pickerDateTimeFormat);\n\n            if (this.options.dateFormat) {\n                this.outputDateFormat = this.options.dateFormat;\n            }\n\n            this.inputDateFormat = this.options.timeOnly ?\n                utils.convertToMomentFormat(this.pickerDefaultTimeFormat) :\n                utils.convertToMomentFormat(this.inputDateFormat);\n            this.outputDateFormat = this.options.timeOnly ?\n                utils.convertToMomentFormat(this.options.timeFormat) :\n                utils.convertToMomentFormat(this.outputDateFormat);\n\n            this.validationParams.dateFormat = this.outputDateFormat;\n        }\n    });\n});\n","Magento_Ui/js/form/element/country.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiRegistry',\n    './select'\n], function (_, registry, Select) {\n    'use strict';\n\n    return Select.extend({\n        defaults: {\n            imports: {\n                update: '${ $.parentName }.website_id:value'\n            }\n        },\n\n        /**\n         * Filters 'initialOptions' property by 'field' and 'value' passed,\n         * calls 'setOptions' passing the result to it\n         *\n         * @param {*} value\n         * @param {String} field\n         */\n        filter: function (value, field) {\n            var result, defaultCountry, defaultValue;\n\n            if (!field) { //validate field, if we are on update\n                field = this.filterBy.field;\n            }\n\n            this._super(value, field);\n            result = _.filter(this.initialOptions, function (item) {\n\n                if (item[field]) {\n                    return ~item[field].indexOf(value);\n                }\n\n                return false;\n            });\n\n            this.setOptions(result);\n            this.reset();\n\n            if (!this.value()) {\n                defaultCountry = _.filter(result, function (item) {\n                    return item['is_default'] && _.contains(item['is_default'], value);\n                });\n\n                if (defaultCountry.length) {\n                    defaultValue = defaultCountry.shift();\n                    this.value(defaultValue.value);\n                }\n            }\n        }\n    });\n});\n\n","Magento_Ui/js/form/element/url-input.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiLayout',\n    'mage/translate',\n    'Magento_Ui/js/form/element/abstract'\n], function (_, layout, $t, Abstract) {\n    'use strict';\n\n    return Abstract.extend({\n        defaults: {\n            linkedElement: {},\n            settingTemplate: 'ui/form/element/urlInput/setting',\n            typeSelectorTemplate: 'ui/form/element/urlInput/typeSelector',\n            options: [],\n            linkedElementInstances: {},\n            //checkbox\n            isDisplayAdditionalSettings: true,\n            settingValue: false,\n            settingLabel: $t('Open in new tab'),\n            tracks: {\n                linkedElement: true\n            },\n            baseLinkSetting: {\n                namePrefix: '${$.name}.',\n                dataScopePrefix: '${$.dataScope}.',\n                provider: '${$.provider}'\n            },\n            urlTypes: {},\n            listens: {\n                settingValue: 'checked',\n                disabled: 'hideLinkedElement',\n                linkType: 'createChildUrlInputComponent'\n            },\n            links: {\n                linkType: '${$.provider}:${$.dataScope}.type',\n                settingValue: '${$.provider}:${$.dataScope}.setting'\n            }\n        },\n\n        /** @inheritdoc */\n        initConfig: function (config) {\n            var processedLinkTypes = {},\n                baseLinkType = this.constructor.defaults.baseLinkSetting;\n\n            _.each(config.urlTypes, function (linkSettingsArray, linkName) {\n                //add link name by link type\n                linkSettingsArray.name = baseLinkType.namePrefix + linkName;\n                linkSettingsArray.dataScope = baseLinkType.dataScopePrefix + linkName;\n                linkSettingsArray.type = linkName;\n                linkSettingsArray.disabled = config.disabled;\n                linkSettingsArray.visible = config.visible;\n                processedLinkTypes[linkName] = {};\n                _.extend(processedLinkTypes[linkName], baseLinkType, linkSettingsArray);\n            });\n            _.extend(this.constructor.defaults.urlTypes, processedLinkTypes);\n\n            this._super();\n        },\n\n        /**\n         * Initializes observable properties of instance\n         *\n         * @returns {Abstract} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe('componentTemplate options value linkType settingValue checked isDisplayAdditionalSettings')\n                .setOptions();\n\n            return this;\n        },\n\n        /**\n         * Set options to select based on link types configuration\n         *\n         * @return {Object}\n         */\n        setOptions: function () {\n            var result = [];\n\n            _.each(this.urlTypes, function (option, key) {\n                result.push({\n                    value: key,\n                    label: option.label,\n                    sortOrder: option.sortOrder || 0\n                });\n            });\n\n            //sort options by sortOrder\n            result.sort(function (a, b) {\n                return a.sortOrder > b.sortOrder ? 1 : -1;\n            });\n\n            this.options(result);\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        setPreview: function (visible) {\n            this.linkedElement().visible(visible);\n        },\n\n        /**\n         * Initializes observable properties of instance\n         *\n         * @param {Boolean} disabled\n         */\n        hideLinkedElement: function (disabled) {\n            this.linkedElement().disabled(disabled);\n        },\n\n        /** @inheritdoc */\n        destroy: function () {\n            _.each(this.linkedElementInstances, function (value) {\n                value().destroy();\n            });\n            this._super();\n        },\n\n        /**\n         * Create child component by value\n         *\n         * @param {String} value\n         * @return void\n         */\n        createChildUrlInputComponent: function (value) {\n            var elementConfig;\n\n            if (!_.isEmpty(value) && _.isUndefined(this.linkedElementInstances[value])) {\n                elementConfig = this.urlTypes[value];\n                layout([elementConfig]);\n                this.linkedElementInstances[value] = this.requestModule(elementConfig.name);\n            }\n            this.linkedElement = this.linkedElementInstances[value];\n\n        },\n\n        /**\n         * Returns linked element to display related field in template\n         * @return String\n         */\n        getLinkedElementName: function () {\n            return this.linkedElement;\n        },\n\n        /**\n         * Add ability to choose check box by clicking on label\n         */\n        checkboxClick: function () {\n            if (!this.disabled()) {\n                this.settingValue(!this.settingValue());\n            }\n        }\n    });\n});\n","Magento_Ui/js/form/element/color-picker-palette.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @api\n */\ndefine([], function () {\n    'use strict';\n\n    return [\n        [\n            'rgb(0,0,0)', 'rgb(52,52,52)', 'rgb(83,83,83)', 'rgb(135,135,135)', 'rgb(193,193,193)',\n            'rgb(234,234,234)', 'rgb(240,240,240)', 'rgb(255,255,255)'\n        ],\n        [\n            'rgb(252,0,9)', 'rgb(253,135,10)', 'rgb(255,255,13)', 'rgb(35,255,9)', 'rgb(33,255,255)',\n            'rgb(0,0,254)', 'rgb(132,0,254)', 'rgb(251,0,255)'\n        ],\n        [\n            'rgb(240,192,194)', 'rgb(251,223,194)', 'rgb(255,241,193)', 'rgb(210,230,201)',\n            'rgb(199,217,220)', 'rgb(197,219,240)', 'rgb(208,200,227)', 'rgb(229,199,212)'\n        ],\n        [\n            'rgb(228,133,135)', 'rgb(246,193,139)', 'rgb(254,225,136)', 'rgb(168,208,152)',\n            'rgb(146,184,190)', 'rgb(143,184,227)', 'rgb(165,148,204)', 'rgb(202,147,175)'\n        ],\n        [\n            'rgb(214,78,83)', 'rgb(243,163,88)', 'rgb(254,211,83)', 'rgb(130,187,106)',\n            'rgb(99,149,159)', 'rgb(93,150,211)', 'rgb(123,100,182)', 'rgb(180,100,142)'\n        ],\n        [\n            'rgb(190,0,5)', 'rgb(222,126,44)', 'rgb(236,183,39)', 'rgb(89,155,61)', 'rgb(55,110,123)',\n            'rgb(49,112,185)', 'rgb(83,55,150)', 'rgb(147,55,101)'\n        ],\n        [\n            'rgb(133,0,3)', 'rgb(163,74,10)', 'rgb(177,127,7)', 'rgb(45,101,23)', 'rgb(18,62,74)',\n            'rgb(14,62,129)', 'rgb(40,15,97)', 'rgb(95,16,55)'\n        ],\n        [\n            'rgb(81,0,1)', 'rgb(100,48,7)', 'rgb(107,78,3)', 'rgb(31,63,16)',\n            'rgb(13,39,46)', 'rgb(10,40,79)', 'rgb(24,12,59)', 'rgb(59,10,36)'\n        ]\n    ];\n});\n","Magento_Ui/js/form/element/region.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiRegistry',\n    './select',\n    'Magento_Checkout/js/model/default-post-code-resolver'\n], function (_, registry, Select, defaultPostCodeResolver) {\n    'use strict';\n\n    return Select.extend({\n        defaults: {\n            skipValidation: false,\n            imports: {\n                countryOptions: '${ $.parentName }.country_id:indexedOptions',\n                update: '${ $.parentName }.country_id:value'\n            }\n        },\n\n        /**\n         * {@inheritdoc}\n         */\n        initialize: function () {\n            var option;\n\n            this._super();\n\n            option = _.find(this.countryOptions, function (row) {\n                return row['is_default'] === true;\n            });\n            this.hideRegion(option);\n\n            return this;\n        },\n\n        /**\n         * Method called every time country selector's value gets changed.\n         * Updates all validations and requirements for certain country.\n         * @param {String} value - Selected country ID.\n         */\n        update: function (value) {\n            var isRegionRequired,\n                option;\n\n            if (!value) {\n                return;\n            }\n\n            option = _.isObject(this.countryOptions) && this.countryOptions[value];\n\n            if (!option) {\n                return;\n            }\n\n            this.hideRegion(option);\n\n            defaultPostCodeResolver.setUseDefaultPostCode(!option['is_zipcode_optional']);\n\n            isRegionRequired = !this.skipValidation && !!option['is_region_required'];\n\n            if (!isRegionRequired) {\n                this.error(false);\n            }\n\n            this.required(isRegionRequired);\n            this.validation['required-entry'] = isRegionRequired;\n\n            registry.get(this.customName, function (input) {\n                input.required(isRegionRequired);\n                input.validation['required-entry'] = isRegionRequired;\n                input.validation['validate-not-number-first'] = !this.options().length;\n            }.bind(this));\n        },\n\n        /**\n         * Hide select and corresponding text input field if region must not be shown for selected country.\n         *\n         * @private\n         * @param {Object}option\n         */\n        hideRegion: function (option) {\n            if (!option || option['is_region_visible'] !== false) {\n                return;\n            }\n\n            this.setVisible(false);\n\n            if (this.customEntry) {\n                this.toggleInput(false);\n            }\n        }\n    });\n});\n","Magento_Ui/js/form/element/textarea.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    './abstract'\n], function (Abstract) {\n    'use strict';\n\n    return Abstract.extend({\n        defaults: {\n            cols: 15,\n            rows: 2,\n            elementTmpl: 'ui/form/element/textarea'\n        }\n    });\n});\n","Magento_Ui/js/form/element/text.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'uiElement',\n    'mageUtils'\n], function (Element, utils) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            visible: true,\n            label: '',\n            error: '',\n            uid: utils.uniqueid(),\n            disabled: false,\n            links: {\n                value: '${ $.provider }:${ $.dataScope }'\n            }\n        },\n\n        /**\n         * Has service\n         *\n         * @returns {Boolean} false.\n         */\n        hasService: function () {\n            return false;\n        },\n\n        /**\n         * Has addons\n         *\n         * @returns {Boolean} false.\n         */\n        hasAddons: function () {\n            return false;\n        },\n\n        /**\n         * Calls 'initObservable' of parent\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe('disabled visible value');\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/form/element/wysiwyg.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'wysiwygAdapter',\n    'Magento_Ui/js/lib/view/utils/async',\n    'underscore',\n    'ko',\n    './abstract',\n    'mage/adminhtml/events',\n    'Magento_Variable/variables'\n], function (wysiwyg, $, _, ko, Abstract, varienGlobalEvents) {\n    'use strict';\n\n    return Abstract.extend({\n        currentWysiwyg: undefined,\n        defaults: {\n            elementSelector: 'textarea',\n            suffixRegExpPattern: '${ $.wysiwygUniqueSuffix }',\n            $wysiwygEditorButton: '',\n            links: {\n                value: '${ $.provider }:${ $.dataScope }'\n            },\n            template: 'ui/form/field',\n            elementTmpl: 'ui/form/element/wysiwyg',\n            content:        '',\n            showSpinner:    false,\n            loading:        false,\n            listens: {\n                disabled: 'setDisabled'\n            }\n        },\n\n        /**\n         *\n         * @returns {} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .initNodeListener();\n\n            $.async({\n                component: this,\n                selector: 'button'\n            }, function (element) {\n                this.$wysiwygEditorButton = this.$wysiwygEditorButton ?\n                    this.$wysiwygEditorButton.add($(element)) : $(element);\n            }.bind(this));\n\n            // disable editor completely after initialization is field is disabled\n            varienGlobalEvents.attachEventHandler('wysiwygEditorInitialized', function () {\n                if (!_.isUndefined(window.tinyMceEditors)) {\n                    this.currentWysiwyg = window.tinyMceEditors[this.wysiwygId];\n                }\n\n                if (this.disabled()) {\n                    this.setDisabled(true);\n                }\n            }.bind(this));\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initConfig: function (config) {\n            var pattern = config.suffixRegExpPattern || this.constructor.defaults.suffixRegExpPattern;\n\n            pattern = pattern.replace(/\\$/g, '\\\\$&');\n            config.content = config.content.replace(new RegExp(pattern, 'g'), this.getUniqueSuffix(config));\n            this._super();\n\n            return this;\n        },\n\n        /**\n         * Build unique id based on name, underscore separated.\n         *\n         * @param {Object} config\n         */\n        getUniqueSuffix: function (config) {\n            return config.name.replace(/(\\.|-)/g, '_');\n        },\n\n        /**\n         * @inheritdoc\n         */\n        destroy: function () {\n            this._super();\n            wysiwyg.removeEvents(this.wysiwygId);\n        },\n\n        /**\n         *\n         * @returns {exports}\n         */\n        initObservable: function () {\n            this._super()\n                .observe(['value', 'content']);\n\n            return this;\n        },\n\n        /**\n         *\n         * @returns {} Chainable.\n         */\n        initNodeListener: function () {\n            $.async({\n                component: this,\n                selector: this.elementSelector\n            }, this.setElementNode.bind(this));\n\n            return this;\n        },\n\n        /**\n         *\n         * @param {HTMLElement} node\n         */\n        setElementNode: function (node) {\n            $(node).bindings({\n                value: this.value\n            });\n        },\n\n        /**\n         * Set disabled property to wysiwyg component\n         *\n         * @param {Boolean} disabled\n         */\n        setDisabled: function (disabled) {\n            if (this.$wysiwygEditorButton && disabled) {\n                this.$wysiwygEditorButton.prop('disabled', 'disabled');\n            } else if (this.$wysiwygEditorButton) {\n                this.$wysiwygEditorButton.prop('disabled', false);\n            }\n\n            /* eslint-disable no-undef */\n            if (!_.isUndefined(this.currentWysiwyg) && this.currentWysiwyg.activeEditor()) {\n                this.currentWysiwyg.setEnabledStatus(!disabled);\n                this.currentWysiwyg.getPluginButtons().prop('disabled', disabled);\n            }\n        },\n\n        /**\n         * Content getter\n         *\n         * @returns {String}\n         */\n        getContentUnsanitizedHtml: function () {\n            return this.content();\n        }\n    });\n});\n","Magento_Ui/js/form/element/image-uploader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global Base64 */\ndefine([\n    'jquery',\n    'underscore',\n    'mageUtils',\n    'Magento_Ui/js/modal/alert',\n    'Magento_Ui/js/lib/validation/validator',\n    'Magento_Ui/js/form/element/file-uploader',\n    'mage/adminhtml/browser'\n], function ($, _, utils, uiAlert, validator, Element, browser) {\n    'use strict';\n\n    return Element.extend({\n        /**\n         * {@inheritDoc}\n         */\n        initialize: function () {\n            this._super();\n\n            // Listen for file deletions from the media browser\n            $(window).on('fileDeleted.mediabrowser', this.onDeleteFile.bind(this));\n        },\n\n        /**\n         * Assign uid for media gallery\n         *\n         * @return {ImageUploader} Chainable.\n         */\n        initConfig: function () {\n            var mediaGalleryUid = utils.uniqueid();\n\n            this._super();\n\n            _.extend(this, {\n                mediaGalleryUid: mediaGalleryUid\n            });\n\n            return this;\n        },\n\n        /**\n         * Add file event callback triggered from media gallery\n         *\n         * @param {ImageUploader} imageUploader - UI Class\n         * @param {Event} e\n         */\n        addFileFromMediaGallery: function (imageUploader, e) {\n            var $buttonEl = $(e.target),\n                fileSize = $buttonEl.data('size'),\n                fileMimeType = $buttonEl.data('mime-type'),\n                filePathname = $buttonEl.val(),\n                fileBasename = filePathname.split('/').pop();\n\n            this.addFile({\n                type: fileMimeType,\n                name: fileBasename,\n                size: fileSize,\n                url: filePathname\n            });\n        },\n\n        /**\n         * Open the media browser dialog\n         *\n         * @param {ImageUploader} imageUploader - UI Class\n         * @param {Event} e\n         */\n        openMediaBrowserDialog: function (imageUploader, e) {\n            var $buttonEl = $(e.target),\n                openDialogUrl = this.mediaGallery.openDialogUrl +\n                'target_element_id/' + $buttonEl.attr('id') +\n                '/store/' + this.mediaGallery.storeId +\n                '/type/image/?isAjax=true';\n\n            if (this.mediaGallery.initialOpenSubpath) {\n                openDialogUrl += '&current_tree_path=' + Base64.idEncode(this.mediaGallery.initialOpenSubpath);\n            }\n\n            browser.openDialog(\n                openDialogUrl,\n                null,\n                null,\n                this.mediaGallery.openDialogTitle,\n                {\n                    targetElementId: $buttonEl.attr('id')\n                }\n            );\n        },\n\n        /**\n         * @param {jQuery.event} e\n         * @param {Object} data\n         * @returns {Object} Chainables\n         */\n        onDeleteFile: function (e, data) {\n            var fileId = this.getFileId(),\n                deletedFileIds = data.ids;\n\n            if (fileId && $.inArray(fileId, deletedFileIds) > -1) {\n                this.clear();\n            }\n\n            return this;\n        },\n\n        /**\n         * {@inheritDoc}\n         */\n        clear: function () {\n            this.value([]);\n\n            return this;\n        },\n\n        /**\n         * Gets the ID of the file used if set\n         *\n         * @return {String|Null} ID\n         */\n        getFileId: function () {\n            return this.hasData() ? this.value()[0].id : null;\n        },\n\n        /**\n         * Trigger native browser file upload UI via clicking on 'Upload' button\n         *\n         * @param {ImageUploader} imageUploader - UI Class\n         * @param {Event} e\n         */\n        triggerImageUpload: function (imageUploader, e) {\n            $(e.target).closest('.file-uploader').find('input[type=\"file\"]').trigger('click');\n        },\n\n        /**\n         * Get list of file extensions allowed in comma delimited format\n         *\n         * @return {String}\n         */\n        getAllowedFileExtensionsInCommaDelimitedFormat: function () {\n            var allowedExtensions = this.allowedExtensions.toUpperCase().split(' ');\n\n            // if jpg and jpeg in allowed extensions, remove jpeg from list\n            if (allowedExtensions.indexOf('JPG') !== -1 && allowedExtensions.indexOf('JPEG') !== -1) {\n                allowedExtensions.splice(allowedExtensions.indexOf('JPEG'), 1);\n            }\n\n            return allowedExtensions.join(', ');\n        }\n    });\n});\n","Magento_Ui/js/form/element/single-checkbox-use-config.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Ui/js/form/element/single-checkbox'\n], function (Component) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            isUseDefault: false,\n            isUseConfig: false,\n            listens: {\n                'isUseConfig': 'toggleElement',\n                'isUseDefault': 'toggleElement'\n            }\n        },\n\n        /**\n         * @inheritdoc\n         */\n        initObservable: function () {\n\n            return this\n                ._super()\n                .observe('isUseConfig');\n        },\n\n        /**\n         * Toggle element\n         */\n        toggleElement: function () {\n            this.disabled(this.isUseDefault() || this.isUseConfig());\n\n            if (this.source) {\n                this.source.set('data.use_default.' + this.index, Number(this.isUseDefault()));\n            }\n        }\n    });\n});\n","Magento_Ui/js/form/element/checkbox-set.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    './abstract'\n], function (_, utils, Abstract) {\n    'use strict';\n\n    return Abstract.extend({\n        defaults: {\n            template: 'ui/form/element/checkbox-set',\n            multiple: false,\n            multipleScopeValue: null\n        },\n\n        /**\n         * @inheritdoc\n         */\n        initConfig: function () {\n            this._super();\n\n            this.value = this.normalizeData(this.value);\n\n            return this;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        initLinks: function () {\n            var scope = this.source.get(this.dataScope);\n\n            this.multipleScopeValue = this.multiple && _.isArray(scope) ? utils.copy(scope) : undefined;\n\n            return this._super();\n        },\n\n        /**\n         * @inheritdoc\n         */\n        reset: function () {\n            this.value(utils.copy(this.initialValue));\n            this.error(false);\n\n            return this;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        clear: function () {\n            var value = this.multiple ? [] : '';\n\n            this.value(value);\n            this.error(false);\n\n            return this;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        normalizeData: function (value) {\n            if (!this.multiple) {\n                return this._super();\n            }\n\n            return _.isArray(value) ? utils.copy(value) : [];\n        },\n\n        /**\n         * @inheritdoc\n         */\n        setInitialValue: function () {\n            this._super();\n\n            this.initialValue = utils.copy(this.initialValue);\n\n            return this;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        getInitialValue: function () {\n            var values = [this.multipleScopeValue, this.default, this.value.peek(), []],\n                value;\n\n            if (!this.multiple) {\n                return this._super();\n            }\n\n            values.some(function (v) {\n                return _.isArray(v) && (value = utils.copy(v));\n            });\n\n            return value;\n        },\n\n        /**\n         * Returns labels which matches current value.\n         *\n         * @returns {String|Array}\n         */\n        getPreview: function () {\n            var option;\n\n            if (!this.multiple) {\n                option = this.getOption(this.value());\n\n                return option ? option.label : '';\n            }\n\n            return this.value.map(function (value) {\n                return this.getOption(value).label;\n            }, this);\n        },\n\n        /**\n         * Returns option object associated with provided value.\n         *\n         * @param {String} value\n         * @returns {Object}\n         */\n        getOption: function (value) {\n            return _.findWhere(this.options, {\n                value: value\n            });\n        },\n\n        /**\n         * @inheritdoc\n         */\n        hasChanged: function () {\n            var value = this.value(),\n                initial = this.initialValue;\n\n            return this.multiple ?\n                !utils.equalArrays(value, initial) :\n                this._super();\n        }\n    });\n});\n","Magento_Ui/js/form/element/media.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'mageUtils',\n    './abstract'\n], function (utils, Abstract) {\n    'use strict';\n\n    return Abstract.extend({\n        defaults: {\n            links: {\n                value: ''\n            }\n        },\n\n        /**\n         * Initializes file component.\n         *\n         * @returns {Media} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .initFormId();\n\n            return this;\n        },\n\n        /**\n         * Defines form ID with which file input will be associated.\n         *\n         * @returns {Media} Chainable.\n         */\n        initFormId: function () {\n            var namespace;\n\n            if (this.formId) {\n                return this;\n            }\n\n            namespace   = this.name.split('.');\n            this.formId = namespace[0];\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/form/element/single-checkbox-toggle-notice.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Ui/js/form/element/single-checkbox'\n], function (SingleCheckbox) {\n    'use strict';\n\n    return SingleCheckbox.extend({\n        defaults: {\n            notices: [],\n            tracks: {\n                notice: true\n            }\n        },\n\n        /**\n         * Choose notice on initialization\n         *\n         * @returns {*|void|Element}\n         */\n        initialize: function () {\n            this._super()\n                .chooseNotice();\n\n            return this;\n        },\n\n        /**\n         * Choose notice function\n         *\n         * @returns void\n         */\n        chooseNotice: function () {\n            var checkedNoticeNumber = Number(this.checked());\n\n            this.notice = this.notices[checkedNoticeNumber];\n        },\n\n        /**\n         * Choose notice on update\n         *\n         * @returns void\n         */\n        onUpdate: function () {\n            this._super();\n            this.chooseNotice();\n        }\n    });\n});\n","Magento_Ui/js/form/element/single-checkbox.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_Ui/js/form/element/abstract',\n    'underscore',\n    'mage/translate'\n], function (AbstractField, _, $t) {\n    'use strict';\n\n    return AbstractField.extend({\n        defaults: {\n            template: 'ui/form/components/single/field',\n            checked: false,\n            initialChecked: false,\n            multiple: false,\n            prefer: 'checkbox', // 'radio' | 'checkbox' | 'toggle'\n            valueMap: {},\n\n            templates: {\n                radio: 'ui/form/components/single/radio',\n                checkbox: 'ui/form/components/single/checkbox',\n                toggle: 'ui/form/components/single/switcher'\n            },\n\n            listens: {\n                'checked': 'onCheckedChanged',\n                'value': 'onExtendedValueChanged'\n            }\n        },\n\n        /**\n         * @inheritdoc\n         */\n        initConfig: function (config) {\n            this._super();\n\n            if (!config.elementTmpl) {\n                if (!this.prefer && !this.multiple) {\n                    this.elementTmpl = this.templates.radio;\n                } else if (this.prefer === 'radio') {\n                    this.elementTmpl = this.templates.radio;\n                } else if (this.prefer === 'checkbox') {\n                    this.elementTmpl = this.templates.checkbox;\n                } else if (this.prefer === 'toggle') {\n                    this.elementTmpl = this.templates.toggle;\n                } else {\n                    this.elementTmpl = this.templates.checkbox;\n                }\n            }\n\n            if (this.prefer === 'toggle' && _.isEmpty(this.toggleLabels)) {\n                this.toggleLabels = {\n                    'on': $t('Yes'),\n                    'off': $t('No')\n                };\n            }\n\n            if (typeof this.default === 'undefined' || this.default === null) {\n                this.default = '';\n            }\n\n            if (typeof this.value === 'undefined' || this.value === null) {\n                this.value = _.isEmpty(this.valueMap) || this.default !== '' ? this.default : this.valueMap.false;\n                this.initialValue = this.value;\n            } else {\n                this.initialValue = this.value;\n            }\n\n            if (this.multiple && !_.isArray(this.value)) {\n                this.value = []; // needed for correct observable assignment\n            }\n\n            this.initialChecked = this.checked;\n\n            return this;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        initObservable: function () {\n            return this\n                ._super()\n                .observe('checked');\n        },\n\n        /**\n         * Get true/false key from valueMap by value.\n         *\n         * @param {*} value\n         * @returns {Boolean|undefined}\n         */\n        getReverseValueMap: function getReverseValueMap(value) {\n            var bool = false;\n\n            _.some(this.valueMap, function (iValue, iBool) {\n                if (iValue === value) {\n                    bool = iBool === 'true';\n\n                    return true;\n                }\n            });\n\n            return bool;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        setInitialValue: function () {\n            if (_.isEmpty(this.valueMap)) {\n                this.on('value', this.onUpdate.bind(this));\n            } else {\n                this._super();\n                this.checked(this.getReverseValueMap(this.value()));\n            }\n\n            return this;\n        },\n\n        /**\n         * Handle dataScope changes for checkbox / radio button.\n         *\n         * @param {*} newExportedValue\n         */\n        onExtendedValueChanged: function (newExportedValue) {\n            var isMappedUsed = !_.isEmpty(this.valueMap),\n                oldChecked = this.checked.peek(),\n                oldValue = this.initialValue,\n                newChecked;\n\n            if (this.multiple) {\n                newChecked = newExportedValue.indexOf(oldValue) !== -1;\n            } else if (isMappedUsed) {\n                newChecked = this.getReverseValueMap(newExportedValue);\n            } else if (typeof newExportedValue === 'boolean') {\n                newChecked = newExportedValue;\n            } else {\n                newChecked = newExportedValue === oldValue;\n            }\n\n            if (newChecked !== oldChecked) {\n                this.checked(newChecked);\n            }\n        },\n\n        /**\n         * Handle checked state changes for checkbox / radio button.\n         *\n         * @param {Boolean} newChecked\n         */\n        onCheckedChanged: function (newChecked) {\n            var isMappedUsed = !_.isEmpty(this.valueMap),\n                oldValue = this.initialValue,\n                newValue;\n\n            if (isMappedUsed) {\n                newValue = this.valueMap[newChecked];\n            } else {\n                newValue = oldValue;\n            }\n\n            if (!this.multiple && newChecked) {\n                this.value(newValue);\n            } else if (!this.multiple && !newChecked) {\n                if (typeof newValue === 'boolean') {\n                    this.value(newChecked);\n                } else if (newValue === this.value.peek()) {\n                    this.value('');\n                }\n\n                if (isMappedUsed) {\n                    this.value(newValue);\n                }\n            } else if (this.multiple && newChecked && this.value.indexOf(newValue) === -1) {\n                this.value.push(newValue);\n            } else if (this.multiple && !newChecked && this.value.indexOf(newValue) !== -1) {\n                this.value.splice(this.value.indexOf(newValue), 1);\n            }\n        },\n\n        /**\n         * @inheritdoc\n         */\n        onUpdate: function () {\n            if (this.hasUnique) {\n                this.setUnique();\n            }\n\n            return this._super();\n        },\n\n        /**\n         * @inheritdoc\n         */\n        reset: function () {\n            if (this.multiple && this.initialChecked) {\n                this.value.push(this.initialValue);\n            } else if (this.multiple && !this.initialChecked) {\n                this.value.splice(this.value.indexOf(this.initialValue), 1);\n            } else {\n                this.value(this.initialValue);\n            }\n\n            this.error(false);\n\n            return this;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        clear: function () {\n            if (this.multiple) {\n                this.value([]);\n            } else {\n                this.value('');\n            }\n\n            this.error(false);\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/form/element/website.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'uiRegistry',\n    './select'\n], function (_, registry, Select) {\n    'use strict';\n\n    return Select.extend({\n        defaults: {\n            customerId: null,\n            isGlobalScope: 0\n        },\n\n        /**\n         * Website component constructor.\n         * @returns {exports}\n         */\n        initialize: function () {\n            this._super();\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/form/element/select.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    'uiRegistry',\n    './abstract',\n    'uiLayout'\n], function (_, utils, registry, Abstract, layout) {\n    'use strict';\n\n    var inputNode = {\n        parent: '${ $.$data.parentName }',\n        component: 'Magento_Ui/js/form/element/abstract',\n        template: '${ $.$data.template }',\n        provider: '${ $.$data.provider }',\n        name: '${ $.$data.index }_input',\n        dataScope: '${ $.$data.customEntry }',\n        customScope: '${ $.$data.customScope }',\n        sortOrder: {\n            after: '${ $.$data.name }'\n        },\n        displayArea: 'body',\n        label: '${ $.$data.label }'\n    };\n\n    /**\n     * Parses incoming options, considers options with undefined value property\n     *     as caption\n     *\n     * @param  {Array} nodes\n     * @return {Object}\n     */\n    function parseOptions(nodes, captionValue) {\n        var caption,\n            value;\n\n        nodes = _.map(nodes, function (node) {\n            value = node.value;\n\n            if (value === null || value === captionValue) {\n                if (_.isUndefined(caption)) {\n                    caption = node.label;\n                }\n            } else {\n                return node;\n            }\n        });\n\n        return {\n            options: _.compact(nodes),\n            caption: _.isString(caption) ? caption : false\n        };\n    }\n\n    /**\n     * Recursively loops over data to find non-undefined, non-array value\n     *\n     * @param  {Array} data\n     * @return {*} - first non-undefined value in array\n     */\n    function findFirst(data) {\n        var value;\n\n        data.some(function (node) {\n            value = node.value;\n\n            if (Array.isArray(value)) {\n                value = findFirst(value);\n            }\n\n            return !_.isUndefined(value);\n        });\n\n        return value;\n    }\n\n    /**\n     * Recursively set to object item like value and item.value like key.\n     *\n     * @param {Array} data\n     * @param {Object} result\n     * @returns {Object}\n     */\n    function indexOptions(data, result) {\n        var value;\n\n        result = result || {};\n\n        data.forEach(function (item) {\n            value = item.value;\n\n            if (Array.isArray(value)) {\n                indexOptions(value, result);\n            } else {\n                result[value] = item;\n            }\n        });\n\n        return result;\n    }\n\n    return Abstract.extend({\n        defaults: {\n            customName: '${ $.parentName }.${ $.index }_input',\n            elementTmpl: 'ui/form/element/select',\n            caption: '',\n            options: []\n        },\n\n        /**\n         * Extends instance with defaults, extends config with formatted values\n         *     and options, and invokes initialize method of AbstractElement class.\n         *     If instance's 'customEntry' property is set to true, calls 'initInput'\n         */\n        initialize: function () {\n            this._super();\n\n            if (this.customEntry) {\n                registry.get(this.name, this.initInput.bind(this));\n            }\n\n            if (this.filterBy) {\n                this.initFilter();\n            }\n\n            return this;\n        },\n\n        /**\n         * Calls 'initObservable' of parent, initializes 'options' and 'initialOptions'\n         *     properties, calls 'setOptions' passing options to it\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super();\n\n            this.initialOptions = this.options;\n\n            this.observe('options caption')\n                .setOptions(this.options());\n\n            return this;\n        },\n\n        /**\n         * Set link for filter.\n         *\n         * @returns {Object} Chainable\n         */\n        initFilter: function () {\n            var filter = this.filterBy;\n\n            this.filter(this.default, filter.field);\n            this.setLinks({\n                filter: filter.target\n            }, 'imports');\n\n            return this;\n        },\n\n        /**\n         * Creates input from template, renders it via renderer.\n         *\n         * @returns {Object} Chainable.\n         */\n        initInput: function () {\n            layout([utils.template(inputNode, this)]);\n\n            return this;\n        },\n\n        /**\n         * Matches specified value with existing options\n         * or, if value is not specified, returns value of the first option.\n         *\n         * @returns {*}\n         */\n        normalizeData: function () {\n            var value = this._super(),\n                option;\n\n            if (value !== '') {\n                option = this.getOption(value);\n\n                return option && option.value;\n            }\n\n            if (!this.caption()) {\n                return findFirst(this.options);\n            }\n        },\n\n        /**\n         * Filters 'initialOptions' property by 'field' and 'value' passed,\n         * calls 'setOptions' passing the result to it\n         *\n         * @param {*} value\n         * @param {String} field\n         */\n        filter: function (value, field) {\n            var source = this.initialOptions,\n                result;\n\n            field = field || this.filterBy.field;\n\n            result = _.filter(source, function (item) {\n                return item[field] === value || item.value === '';\n            });\n\n            this.setOptions(result);\n        },\n\n        /**\n         * Change visibility for input.\n         *\n         * @param {Boolean} isVisible\n         */\n        toggleInput: function (isVisible) {\n            registry.get(this.customName, function (input) {\n                input.setVisible(isVisible);\n            });\n        },\n\n        /**\n         * Sets 'data' to 'options' observable array, if instance has\n         * 'customEntry' property set to true, calls 'setHidden' method\n         *  passing !options.length as a parameter\n         *\n         * @param {Array} data\n         * @returns {Object} Chainable\n         */\n        setOptions: function (data) {\n            var captionValue = this.captionValue || '',\n                result = parseOptions(data, captionValue),\n                isVisible;\n\n            this.indexedOptions = indexOptions(result.options);\n\n            this.options(result.options);\n\n            if (!this.caption()) {\n                this.caption(result.caption);\n            }\n\n            if (this.customEntry) {\n                isVisible = !!result.options.length;\n\n                this.setVisible(isVisible);\n                this.toggleInput(!isVisible);\n            }\n\n            return this;\n        },\n\n        /**\n         * Processes preview for option by it's value, and sets the result\n         * to 'preview' observable\n         *\n         * @returns {Object} Chainable.\n         */\n        getPreview: function () {\n            var value = this.value(),\n                option = this.indexedOptions[value],\n                preview = option ? option.label : '';\n\n            this.preview(preview);\n\n            return preview;\n        },\n\n        /**\n         * Get option from indexedOptions list.\n         *\n         * @param {Number} value\n         * @returns {Object} Chainable\n         */\n        getOption: function (value) {\n            return this.indexedOptions[value];\n        },\n\n        /**\n         * Select first available option\n         *\n         * @returns {Object} Chainable.\n         */\n        clear: function () {\n            var value = this.caption() ? '' : findFirst(this.options);\n\n            this.value(value);\n\n            return this;\n        },\n\n        /**\n         * Initializes observable properties of instance\n         *\n         * @returns {Object} Chainable.\n         */\n        setInitialValue: function () {\n            if (_.isUndefined(this.value()) && !this.default) {\n                this.clear();\n            }\n\n            return this._super();\n        }\n    });\n});\n","Magento_Ui/js/form/element/multiselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    './select'\n], function (_, utils, Select) {\n    'use strict';\n\n    return Select.extend({\n        defaults: {\n            size: 5,\n            elementTmpl: 'ui/form/element/multiselect',\n            listens: {\n                value: 'setDifferedFromDefault setPrepareToSendData'\n            }\n        },\n\n        /**\n         * @inheritdoc\n         */\n        setInitialValue: function () {\n            this._super();\n\n            this.initialValue = utils.copy(this.initialValue);\n\n            return this;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        normalizeData: function (value) {\n            if (utils.isEmpty(value)) {\n                value = [];\n            }\n\n            return _.isString(value) ? value.split(',') : value;\n        },\n\n        /**\n         * Sets the prepared data to dataSource\n         * by path, where key is component link to dataSource with\n         * suffix \"-prepared-for-send\"\n         *\n         * @param {Array} data - current component value\n         */\n        setPrepareToSendData: function (data) {\n            if (_.isUndefined(data) || !data.length) {\n                data = '';\n            }\n\n            this.source.set(this.dataScope + '-prepared-for-send', data);\n        },\n\n        /**\n         * @inheritdoc\n         */\n        getInitialValue: function () {\n            var values = [\n                    this.normalizeData(this.source.get(this.dataScope)),\n                    this.normalizeData(this.default)\n                ],\n                value;\n\n            values.some(function (v) {\n                return _.isArray(v) && (value = utils.copy(v)) && !_.isEmpty(v);\n            });\n\n            return value;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        hasChanged: function () {\n            var value = this.value(),\n                initial = this.initialValue;\n\n            return !utils.equalArrays(value, initial);\n        },\n\n        /**\n         * @inheritdoc\n         */\n        reset: function () {\n            this.value(utils.copy(this.initialValue));\n            this.error(false);\n\n            return this;\n        },\n\n        /**\n         * @inheritdoc\n         */\n        clear: function () {\n            this.value([]);\n            this.error(false);\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/form/element/post-code.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    './abstract'\n], function (_, Abstract) {\n    'use strict';\n\n    return Abstract.extend({\n        defaults: {\n            imports: {\n                countryOptions: '${ $.parentName }.country_id:indexedOptions',\n                update: '${ $.parentName }.country_id:value'\n            }\n        },\n\n        /**\n         * Initializes observable properties of instance\n         *\n         * @returns {Abstract} Chainable.\n         */\n        initObservable: function () {\n            this._super();\n\n            /**\n             * equalityComparer function\n             *\n             * @returns boolean.\n             */\n            this.value.equalityComparer = function (oldValue, newValue) {\n                return !oldValue && !newValue || oldValue === newValue;\n            };\n\n            return this;\n        },\n\n        /**\n         * Method called every time country selector's value gets changed.\n         * Updates all validations and requirements for certain country.\n         * @param {String} value - Selected country ID.\n         */\n        update: function (value) {\n            var isZipCodeOptional,\n                option;\n\n            if (!value) {\n                return;\n            }\n\n            option = _.isObject(this.countryOptions) && this.countryOptions[value];\n\n            if (!option) {\n                return;\n            }\n\n            isZipCodeOptional = !!option['is_zipcode_optional'];\n\n            if (isZipCodeOptional) {\n                this.error(false);\n            }\n\n            this.validation['required-entry'] = !isZipCodeOptional;\n            this.required(!isZipCodeOptional);\n        }\n    });\n});\n","Magento_Ui/js/form/element/boolean.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    './abstract'\n], function (Abstract) {\n    'use strict';\n\n    return Abstract.extend({\n        defaults: {\n            checked: false,\n            links: {\n                checked: 'value'\n            }\n        },\n\n        /**\n         * @returns {*|void|Element}\n         */\n        initObservable: function () {\n            return this._super()\n                    .observe('checked');\n        },\n\n        /**\n         * Converts provided value to boolean.\n         *\n         * @returns {Boolean}\n         */\n        normalizeData: function () {\n            return !!+this._super();\n        },\n\n        /**\n         * Calls 'onUpdate' method of parent, if value is defined and instance's\n         *     'unique' property set to true, calls 'setUnique' method\n         *\n         * @return {Object} - reference to instance\n         */\n        onUpdate: function () {\n            if (this.hasUnique) {\n                this.setUnique();\n            }\n\n            return this._super();\n        }\n    });\n});\n","Magento_Ui/js/form/element/abstract.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'mageUtils',\n    'uiLayout',\n    'uiElement',\n    'Magento_Ui/js/lib/validation/validator'\n], function (_, utils, layout, Element, validator) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            visible: true,\n            preview: '',\n            focused: false,\n            required: false,\n            disabled: false,\n            valueChangedByUser: false,\n            elementTmpl: 'ui/form/element/input',\n            tooltipTpl: 'ui/form/element/helper/tooltip',\n            fallbackResetTpl: 'ui/form/element/helper/fallback-reset',\n            'input_type': 'input',\n            placeholder: false,\n            description: '',\n            labelVisible: true,\n            label: '',\n            error: '',\n            warn: '',\n            notice: '',\n            customScope: '',\n            default: '',\n            isDifferedFromDefault: false,\n            showFallbackReset: false,\n            additionalClasses: {},\n            isUseDefault: '',\n            serviceDisabled: false,\n            valueUpdate: false, // ko binding valueUpdate\n\n            switcherConfig: {\n                component: 'Magento_Ui/js/form/switcher',\n                name: '${ $.name }_switcher',\n                target: '${ $.name }',\n                property: 'value'\n            },\n            listens: {\n                visible: 'setPreview',\n                value: 'setDifferedFromDefault',\n                '${ $.provider }:data.reset': 'reset',\n                '${ $.provider }:data.overload': 'overload',\n                '${ $.provider }:${ $.customScope ? $.customScope + \".\" : \"\"}data.validate': 'validate',\n                'isUseDefault': 'toggleUseDefault'\n            },\n            ignoreTmpls: {\n                value: true\n            },\n\n            links: {\n                value: '${ $.provider }:${ $.dataScope }'\n            }\n        },\n\n        /**\n         * Invokes initialize method of parent class,\n         * contains initialization logic\n         */\n        initialize: function () {\n            _.bindAll(this, 'reset');\n\n            this._super()\n                .setInitialValue()\n                ._setClasses()\n                .initSwitcher();\n\n            return this;\n        },\n\n        /**\n         * Checks if component has error.\n         *\n         * @returns {Object}\n         */\n        checkInvalid: function () {\n            return this.error() && this.error().length ? this : null;\n        },\n\n        /**\n         * Initializes observable properties of instance\n         *\n         * @returns {Abstract} Chainable.\n         */\n        initObservable: function () {\n            var rules = this.validation = this.validation || {};\n\n            this._super();\n\n            this.observe('error disabled focused preview visible value warn notice isDifferedFromDefault')\n                .observe('isUseDefault serviceDisabled')\n                .observe({\n                    'required': !!rules['required-entry']\n                });\n\n            return this;\n        },\n\n        /**\n         * Initializes regular properties of instance.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        initConfig: function () {\n            var uid = utils.uniqueid(),\n                name,\n                valueUpdate,\n                scope;\n\n            this._super();\n\n            scope = this.dataScope.split('.');\n            name = scope.length > 1 ? scope.slice(1) : scope;\n\n            valueUpdate = this.showFallbackReset ? 'afterkeydown' : this.valueUpdate;\n\n            _.extend(this, {\n                uid: uid,\n                noticeId: 'notice-' + uid,\n                errorId: 'error-' + uid,\n                tooltipId: 'tooltip-' + uid,\n                inputName: utils.serializeName(name.join('.')),\n                valueUpdate: valueUpdate\n            });\n\n            return this;\n        },\n\n        /**\n         * Initializes switcher element instance.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        initSwitcher: function () {\n            if (this.switcherConfig.enabled) {\n                layout([this.switcherConfig]);\n            }\n\n            return this;\n        },\n\n        /**\n         * Sets initial value of the element and subscribes to it's changes.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        setInitialValue: function () {\n            this.initialValue = this.getInitialValue();\n\n            if (this.value.peek() !== this.initialValue) {\n                this.value(this.initialValue);\n            }\n\n            this.on('value', this.onUpdate.bind(this));\n            this.isUseDefault(this.disabled());\n\n            return this;\n        },\n\n        /**\n         * Extends 'additionalClasses' object.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        _setClasses: function () {\n            var additional = this.additionalClasses;\n\n            if (_.isString(additional)) {\n                this.additionalClasses = {};\n\n                if (additional.trim().length) {\n                    additional = additional.trim().split(' ');\n\n                    additional.forEach(function (name) {\n                        if (name.length) {\n                            this.additionalClasses[name] = true;\n                        }\n                    }, this);\n                }\n            }\n\n            _.extend(this.additionalClasses, {\n                _required: this.required,\n                _error: this.error,\n                _warn: this.warn,\n                _disabled: this.disabled\n            });\n\n            return this;\n        },\n\n        /**\n         * Gets initial value of element\n         *\n         * @returns {*} Elements' value.\n         */\n        getInitialValue: function () {\n            var values = [this.value(), this.default],\n                value;\n\n            values.some(function (v) {\n                if (v !== null && v !== undefined) {\n                    value = v;\n\n                    return true;\n                }\n\n                return false;\n            });\n\n            return this.normalizeData(value);\n        },\n\n        /**\n         * Sets 'value' as 'hidden' property's value, triggers 'toggle' event,\n         * sets instance's hidden identifier in params storage based on\n         * 'value'.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        setVisible: function (isVisible) {\n            this.visible(isVisible);\n\n            return this;\n        },\n\n        /**\n         * Show element.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        show: function () {\n            this.visible(true);\n\n            return this;\n        },\n\n        /**\n         * Hide element.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        hide: function () {\n            this.visible(false);\n\n            return this;\n        },\n\n        /**\n         * Disable element.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        disable: function () {\n            this.disabled(true);\n\n            return this;\n        },\n\n        /**\n         * Enable element.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        enable: function () {\n            this.disabled(false);\n\n            return this;\n        },\n\n        /**\n         *\n         * @param {(String|Object)} rule\n         * @param {(Object|Boolean)} [options]\n         * @returns {Abstract} Chainable.\n         */\n        setValidation: function (rule, options) {\n            var rules = utils.copy(this.validation),\n                changed;\n\n            if (_.isObject(rule)) {\n                _.extend(this.validation, rule);\n            } else {\n                this.validation[rule] = options;\n            }\n\n            changed = !utils.compare(rules, this.validation).equal;\n\n            if (changed) {\n                this.required(!!rules['required-entry']);\n                this.validate();\n            }\n\n            return this;\n        },\n\n        /**\n         * Returns unwrapped preview observable.\n         *\n         * @returns {String} Value of the preview observable.\n         */\n        getPreview: function () {\n            return this.value();\n        },\n\n        /**\n         * Checks if element has addons\n         *\n         * @returns {Boolean}\n         */\n        hasAddons: function () {\n            return this.addbefore || this.addafter;\n        },\n\n        /**\n         * Checks if element has service setting\n         *\n         * @returns {Boolean}\n         */\n        hasService: function () {\n            return this.service && this.service.template;\n        },\n\n        /**\n         * Defines if value has changed.\n         *\n         * @returns {Boolean}\n         */\n        hasChanged: function () {\n            var notEqual = this.value() !== this.initialValue;\n\n            return !this.visible() ? false : notEqual;\n        },\n\n        /**\n         * Checks if 'value' is not empty.\n         *\n         * @returns {Boolean}\n         */\n        hasData: function () {\n            return !utils.isEmpty(this.value());\n        },\n\n        /**\n         * Sets value observable to initialValue property.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        reset: function () {\n            this.value(this.initialValue);\n            this.error(false);\n\n            return this;\n        },\n\n        /**\n         * Sets current state as initial.\n         */\n        overload: function () {\n            this.setInitialValue();\n            this.bubble('update', this.hasChanged());\n        },\n\n        /**\n         * Clears 'value' property.\n         *\n         * @returns {Abstract} Chainable.\n         */\n        clear: function () {\n            this.value('');\n\n            return this;\n        },\n\n        /**\n         * Converts values like 'null' or 'undefined' to an empty string.\n         *\n         * @param {*} value - Value to be processed.\n         * @returns {*}\n         */\n        normalizeData: function (value) {\n            return utils.isEmpty(value) ? '' : value;\n        },\n\n        /**\n         * Validates itself by it's validation rules using validator object.\n         * If validation of a rule did not pass, writes it's message to\n         * 'error' observable property.\n         *\n         * @returns {Object} Validate information.\n         */\n        validate: function () {\n            var value = this.value(),\n                result = validator(this.validation, value, this.validationParams),\n                message = !this.disabled() && this.visible() ? result.message : '',\n                isValid = this.disabled() || !this.visible() || result.passed;\n\n            this.error(message);\n            this.error.valueHasMutated();\n            this.bubble('error', message);\n\n            //TODO: Implement proper result propagation for form\n            if (this.source && !isValid) {\n                this.source.set('params.invalid', true);\n            }\n\n            return {\n                valid: isValid,\n                target: this\n            };\n        },\n\n        /**\n         * Callback that fires when 'value' property is updated.\n         */\n        onUpdate: function () {\n            this.bubble('update', this.hasChanged());\n\n            this.validate();\n        },\n\n        /**\n         * Restore value to default\n         */\n        restoreToDefault: function () {\n            this.value(this.default);\n            this.focused(true);\n        },\n\n        /**\n         * Update whether value differs from default value\n         */\n        setDifferedFromDefault: function () {\n            var value = typeof this.value() != 'undefined' && this.value() !== null ? this.value() : '',\n                defaultValue = typeof this.default != 'undefined' && this.default !== null ? this.default : '';\n\n            this.isDifferedFromDefault(value !== defaultValue);\n        },\n\n        /**\n         * @param {Boolean} state\n         */\n        toggleUseDefault: function (state) {\n            this.disabled(state);\n\n            if (this.source && this.hasService()) {\n                this.source.set('data.use_default.' + this.index, Number(state));\n            }\n        },\n\n        /**\n         *  Callback when value is changed by user\n         */\n        userChanges: function () {\n            this.valueChangedByUser = true;\n        },\n\n        /**\n         * Returns correct id for 'aria-describedby' accessibility attribute\n         *\n         * @returns {Boolean|String}\n         */\n        getDescriptionId: function () {\n            var id = false;\n\n            if (this.error()) {\n                id = this.errorId;\n            } else if (this.notice()) {\n                id = this.noticeId;\n            }\n\n            return id;\n        }\n    });\n});\n","Magento_Ui/js/form/element/color-picker.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'mage/translate',\n    'Magento_Ui/js/form/element/abstract',\n    'Magento_Ui/js/form/element/color-picker-palette'\n], function ($t, Abstract, palette) {\n    'use strict';\n\n    return Abstract.extend({\n\n        defaults: {\n            colorPickerConfig: {\n                chooseText: $t('Apply'),\n                cancelText: $t('Cancel'),\n                maxSelectionSize: 8,\n                clickoutFiresChange: true,\n                allowEmpty: true,\n                localStorageKey: 'magento.spectrum',\n                palette: palette\n            }\n        },\n\n        /**\n         * Invokes initialize method of parent class,\n         * contains initialization logic\n         */\n        initialize: function () {\n            this._super();\n\n            this.colorPickerConfig.value = this.value;\n\n            return this;\n        }\n    });\n});\n","Magento_Ui/js/view/messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'ko',\n    'jquery',\n    'uiComponent',\n    '../model/messageList',\n    'jquery-ui-modules/effect-blind'\n], function (ko, $, Component, globalMessages) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Ui/messages',\n            selector: '[data-role=checkout-messages]',\n            isHidden: false,\n            hideTimeout: 5000,\n            hideSpeed: 500,\n            listens: {\n                isHidden: 'onHiddenChange'\n            }\n        },\n\n        /** @inheritdoc */\n        initialize: function (config, messageContainer) {\n            this._super()\n                .initObservable();\n\n            this.messageContainer = messageContainer || config.messageContainer || globalMessages;\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super()\n                .observe('isHidden');\n\n            return this;\n        },\n\n        /**\n         * Checks visibility.\n         *\n         * @return {Boolean}\n         */\n        isVisible: function () {\n            return this.isHidden(this.messageContainer.hasMessages());\n        },\n\n        /**\n         * Remove all messages.\n         */\n        removeAll: function () {\n            this.messageContainer.clear();\n        },\n\n        /**\n         * @param {Boolean} isHidden\n         */\n        onHiddenChange: function (isHidden) {\n            // Hide message block if needed\n            if (isHidden) {\n                setTimeout(function () {\n                    $(this.selector).hide('slow');\n\n                    //commented because effect-blind.js(1.13.1) is having show & hide issue\n                    // $(this.selector).hide('blind', {}, this.hideSpeed);\n                }.bind(this), this.hideTimeout);\n            }\n        }\n    });\n});\n","Magento_Ui/js/model/messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'ko',\n    'uiClass'\n], function (ko, Class) {\n    'use strict';\n\n    return Class.extend({\n        /** @inheritdoc */\n        initialize: function () {\n            this._super()\n                .initObservable();\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this.errorMessages = ko.observableArray([]);\n            this.successMessages = ko.observableArray([]);\n\n            return this;\n        },\n\n        /**\n         * Add  message to list.\n         * @param {Object} messageObj\n         * @param {Object} type\n         * @returns {Boolean}\n         */\n        add: function (messageObj, type) {\n            var expr = /([%])\\w+/g,\n                message;\n\n            if (!messageObj.hasOwnProperty('parameters')) {\n                this.clear();\n                type.push(messageObj.message);\n\n                return true;\n            }\n            message = messageObj.message.replace(expr, function (varName) {\n                varName = varName.substr(1);\n\n                if (!isNaN(varName)) {\n                    varName--;\n                }\n\n                if (messageObj.parameters.hasOwnProperty(varName)) {\n                    return messageObj.parameters[varName];\n                }\n\n                return messageObj.parameters.shift();\n            });\n            this.clear();\n            type.push(message);\n\n            return true;\n        },\n\n        /**\n         * Add success message.\n         *\n         * @param {Object} message\n         * @return {*|Boolean}\n         */\n        addSuccessMessage: function (message) {\n            return this.add(message, this.successMessages);\n        },\n\n        /**\n         * Add error message.\n         *\n         * @param {Object} message\n         * @return {*|Boolean}\n         */\n        addErrorMessage: function (message) {\n            return this.add(message, this.errorMessages);\n        },\n\n        /**\n         * Get error messages.\n         *\n         * @return {Array}\n         */\n        getErrorMessages: function () {\n            return this.errorMessages;\n        },\n\n        /**\n         * Get success messages.\n         *\n         * @return {Array}\n         */\n        getSuccessMessages: function () {\n            return this.successMessages;\n        },\n\n        /**\n         * Checks if an instance has stored messages.\n         *\n         * @return {Boolean}\n         */\n        hasMessages: function () {\n            return this.errorMessages().length > 0 || this.successMessages().length > 0;\n        },\n\n        /**\n         * Removes stored messages.\n         */\n        clear: function () {\n            this.errorMessages.removeAll();\n            this.successMessages.removeAll();\n        }\n    });\n});\n","Magento_Ui/js/model/messageList.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    './messages'\n], function (Messages) {\n    'use strict';\n\n    return new Messages();\n});\n","Magento_Tax/js/price/adjustment.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Ui/js/grid/columns/column',\n    'mage/translate'\n], function (Element, $t) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            bodyTmpl: 'Magento_Tax/price/adjustment',\n            taxPriceType: 'final_price',\n            taxPriceCssClass: 'price-including-tax',\n            bothPrices: 3,\n            inclTax: 2,\n            exclTax: 1,\n            modules: {\n                price: '${ $.parentName }'\n            },\n            listens: {\n                price: 'initializePriceAttributes'\n            }\n        },\n\n        /**\n         * {@inheritdoc}\n         */\n        initialize: function () {\n            this._super()\n                .initializePriceAttributes();\n\n            return this;\n        },\n\n        /**\n         * Update parent price.\n         *\n         * @returns {Object} Chainable.\n         */\n        initializePriceAttributes: function () {\n            if (this.displayBothPrices && this.price()) {\n                this.price().priceWrapperCssClasses = this.taxPriceCssClass;\n                this.price().priceWrapperAttr = {\n                    'data-label': $t('Incl. Tax')\n                };\n            }\n\n            return this;\n        },\n\n        /**\n         * Get price tax adjustment.\n         *\n         * @param {Object} row\n         * @return {HTMLElement} tax html\n         */\n        getTax: function (row) {\n            return row['price_info']['extension_attributes']['tax_adjustments']['formatted_prices'][this.taxPriceType];\n        },\n\n        /**\n         * UnsanitizedHtml version of getTax.\n         *\n         * @param {Object} row\n         * @return {HTMLElement} tax html\n         */\n        getTaxUnsanitizedHtml: function (row) {\n            return this.getTax(row);\n        },\n\n        /**\n         * Set price tax type.\n         *\n         * @param {String} priceType\n         * @return {Object}\n         */\n        setPriceType: function (priceType) {\n            this.taxPriceType = priceType;\n\n            return this;\n        },\n\n        /**\n         * Return whether display setting is to display\n         * both price including tax and price excluding tax.\n         *\n         * @return {Boolean}\n         */\n        displayBothPrices: function () {\n            return +this.source.data.displayTaxes === this.bothPrices;\n        },\n\n        /**\n         * Return whether display setting is to display price including tax.\n         *\n         * @return {Boolean}\n         */\n        displayPriceIncludeTax: function () {\n            return +this.source.data.displayTaxes === this.inclTax;\n        },\n\n        /**\n         * Return whether display setting is to display price excluding tax.\n         *\n         * @return {Boolean}\n         */\n        displayPriceExclTax: function () {\n            return +this.source.data.displayTaxes === this.exclTax;\n        }\n    });\n});\n","Magento_Tax/js/view/checkout/cart/totals/grand-total.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'Magento_Tax/js/view/checkout/summary/grand-total'\n], function (Component) {\n    'use strict';\n\n    return Component.extend({\n        /**\n         * @override\n         */\n        isDisplayed: function () {\n            return true;\n        }\n    });\n});\n","Magento_Tax/js/view/checkout/cart/totals/shipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'Magento_Tax/js/view/checkout/summary/shipping',\n    'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n    'use strict';\n\n    return Component.extend({\n        /**\n         * @override\n         */\n        isCalculated: function () {\n            return !!quote.shippingMethod();\n        },\n\n        /**\n         * @override\n         */\n        getShippingMethodTitle: function () {\n            return '(' + this._super() + ')';\n        }\n    });\n});\n","Magento_Tax/js/view/checkout/cart/totals/tax.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'Magento_Tax/js/view/checkout/summary/tax',\n    'Magento_Checkout/js/model/totals'\n], function (Component, totals) {\n    'use strict';\n\n    var isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed,\n        isZeroTaxDisplayed = window.checkoutConfig.isZeroTaxDisplayed;\n\n    return Component.extend({\n        /**\n         * @override\n         */\n        ifShowValue: function () {\n            if (parseInt(this.getPureValue()) === 0) { //eslint-disable-line radix\n                return isZeroTaxDisplayed;\n            }\n\n            return true;\n        },\n\n        /**\n         * @override\n         */\n        ifShowDetails: function () {\n            return this.getPureValue() > 0 && isFullTaxSummaryDisplayed;\n        },\n\n        /**\n         * @override\n         */\n        isCalculated: function () {\n            return this.totals() && totals.getSegment('tax') !== null;\n        }\n    });\n});\n","Magento_Tax/js/view/checkout/minicart/subtotal/totals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'ko',\n    'uiComponent',\n    'Magento_Customer/js/customer-data'\n], function (ko, Component, customerData) {\n    'use strict';\n\n    return Component.extend({\n        displaySubtotal: ko.observable(true),\n\n        /**\n         * @override\n         */\n        initialize: function () {\n            this._super();\n            this.cart = customerData.get('cart');\n        }\n    });\n});\n","Magento_Tax/js/view/checkout/summary/subtotal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'Magento_Checkout/js/view/summary/abstract-total',\n    'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n    'use strict';\n\n    var displaySubtotalMode = window.checkoutConfig.reviewTotalsDisplayMode;\n\n    return Component.extend({\n        defaults: {\n            displaySubtotalMode: displaySubtotalMode,\n            template: 'Magento_Tax/checkout/summary/subtotal'\n        },\n        totals: quote.getTotals(),\n\n        /**\n         * @return {*|String}\n         */\n        getValue: function () {\n            var price = 0;\n\n            if (this.totals()) {\n                price = this.totals().subtotal;\n            }\n\n            return this.getFormattedPrice(price);\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isBothPricesDisplayed: function () {\n            return this.displaySubtotalMode == 'both'; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isIncludingTaxDisplayed: function () {\n            return this.displaySubtotalMode == 'including'; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @return {*|String}\n         */\n        getValueInclTax: function () {\n            var price = 0;\n\n            if (this.totals()) {\n                price = this.totals()['subtotal_incl_tax'];\n            }\n\n            return this.getFormattedPrice(price);\n        }\n    });\n});\n","Magento_Tax/js/view/checkout/summary/grand-total.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'Magento_Checkout/js/view/summary/abstract-total',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Catalog/js/price-utils',\n    'Magento_Checkout/js/model/totals'\n], function (Component, quote, priceUtils, totals) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            isFullTaxSummaryDisplayed: window.checkoutConfig.isFullTaxSummaryDisplayed || false,\n            template: 'Magento_Tax/checkout/summary/grand-total'\n        },\n        totals: quote.getTotals(),\n        isTaxDisplayedInGrandTotal: window.checkoutConfig.includeTaxInGrandTotal || false,\n\n        /**\n         * @return {*}\n         */\n        isDisplayed: function () {\n            return this.isFullMode();\n        },\n\n        /**\n         * @return {*|String}\n         */\n        getValue: function () {\n            var price = 0;\n\n            if (this.totals()) {\n                price = totals.getSegment('grand_total').value;\n            }\n\n            return this.getFormattedPrice(price);\n        },\n\n        /**\n         * @return {*|String}\n         */\n        getBaseValue: function () {\n            var price = 0;\n\n            if (this.totals()) {\n                price = this.totals()['base_grand_total'];\n            }\n\n            return priceUtils.formatPriceLocale(price, quote.getBasePriceFormat());\n        },\n\n        /**\n         * @return {*}\n         */\n        getGrandTotalExclTax: function () {\n            var total = this.totals(),\n                amount;\n\n            if (!total) {\n                return 0;\n            }\n\n            amount = total['grand_total'] - total['tax_amount'];\n\n            if (amount < 0) {\n                amount = 0;\n            }\n\n            return this.getFormattedPrice(amount);\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isBaseGrandTotalDisplayNeeded: function () {\n            var total = this.totals();\n\n            if (!total) {\n                return false;\n            }\n\n            return total['base_currency_code'] != total['quote_currency_code']; //eslint-disable-line eqeqeq\n        }\n    });\n});\n","Magento_Tax/js/view/checkout/summary/shipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'jquery',\n    'Magento_Checkout/js/view/summary/shipping',\n    'Magento_Checkout/js/model/quote'\n], function ($, Component, quote) {\n    'use strict';\n\n    var displayMode = window.checkoutConfig.reviewShippingDisplayMode;\n\n    return Component.extend({\n        defaults: {\n            displayMode: displayMode,\n            template: 'Magento_Tax/checkout/summary/shipping'\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isBothPricesDisplayed: function () {\n            return this.displayMode == 'both'; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isIncludingDisplayed: function () {\n            return this.displayMode == 'including'; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isExcludingDisplayed: function () {\n            return this.displayMode == 'excluding'; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @return {*|Boolean}\n         */\n        isCalculated: function () {\n            return this.totals() && this.isFullMode() && quote.shippingMethod() != null;\n        },\n\n        /**\n         * @return {*}\n         */\n        getIncludingValue: function () {\n            var price;\n\n            if (!this.isCalculated()) {\n                return this.notCalculatedMessage;\n            }\n            price = this.totals()['shipping_incl_tax'];\n\n            return this.getFormattedPrice(price);\n        },\n\n        /**\n         * @return {*}\n         */\n        getExcludingValue: function () {\n            var price;\n\n            if (!this.isCalculated()) {\n                return this.notCalculatedMessage;\n            }\n            price = this.totals()['shipping_amount'];\n\n            return this.getFormattedPrice(price);\n        }\n    });\n});\n","Magento_Tax/js/view/checkout/summary/tax.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'ko',\n    'Magento_Checkout/js/view/summary/abstract-total',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/totals',\n    'mage/translate',\n    'underscore'\n], function (ko, Component, quote, totals, $t, _) {\n    'use strict';\n\n    var isTaxDisplayedInGrandTotal = window.checkoutConfig.includeTaxInGrandTotal,\n        isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed,\n        isZeroTaxDisplayed = window.checkoutConfig.isZeroTaxDisplayed,\n        taxAmount = 0,\n        rates = 0;\n\n    return Component.extend({\n        defaults: {\n            isTaxDisplayedInGrandTotal: isTaxDisplayedInGrandTotal,\n            notCalculatedMessage: $t('Not yet calculated'),\n            template: 'Magento_Tax/checkout/summary/tax'\n        },\n        totals: quote.getTotals(),\n        isFullTaxSummaryDisplayed: isFullTaxSummaryDisplayed,\n\n        /**\n         * @return {Boolean}\n         */\n        ifShowValue: function () {\n            if (this.isFullMode() && this.getPureValue() == 0) { //eslint-disable-line eqeqeq\n                return isZeroTaxDisplayed;\n            }\n\n            return true;\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        ifShowDetails: function () {\n            if (!this.isFullMode()) {\n                return false;\n            }\n\n            return this.getPureValue() > 0 && isFullTaxSummaryDisplayed;\n        },\n\n        /**\n         * @return {Number}\n         */\n        getPureValue: function () {\n            var amount = 0,\n                taxTotal;\n\n            if (this.totals()) {\n                taxTotal = totals.getSegment('tax');\n\n                if (taxTotal) {\n                    amount = taxTotal.value;\n                }\n            }\n\n            return amount;\n        },\n\n        /**\n         * @return {*|Boolean}\n         */\n        isCalculated: function () {\n            return this.totals() && this.isFullMode() && totals.getSegment('tax') != null;\n        },\n\n        /**\n         * @return {*}\n         */\n        getValue: function () {\n            var amount;\n\n            if (!this.isCalculated()) {\n                return this.notCalculatedMessage;\n            }\n            amount = totals.getSegment('tax').value;\n\n            return this.getFormattedPrice(amount);\n        },\n\n        /**\n         * @param {*} amount\n         * @return {*|String}\n         */\n        formatPrice: function (amount) {\n            return this.getFormattedPrice(amount);\n        },\n\n        /**\n         * @param {*} parent\n         * @param {*} percentage\n         * @return {*|String}\n         */\n        getTaxAmount: function (parent, percentage) {\n            var totalPercentage = 0;\n\n            taxAmount = parent.amount;\n            rates = parent.rates;\n            _.each(rates, function (rate) {\n                totalPercentage += parseFloat(rate.percent);\n            });\n\n            return this.getFormattedPrice(this.getPercentAmount(taxAmount, totalPercentage, percentage));\n        },\n\n        /**\n         * @param {*} amount\n         * @param {*} totalPercentage\n         * @param {*} percentage\n         * @return {*|String}\n         */\n        getPercentAmount: function (amount, totalPercentage, percentage) {\n            return parseFloat(amount * percentage / totalPercentage);\n        },\n\n        /**\n         * @return {Array}\n         */\n        getDetails: function () {\n            var taxSegment = totals.getSegment('tax');\n\n            if (taxSegment && taxSegment['extension_attributes']) {\n                return taxSegment['extension_attributes']['tax_grandtotal_details'];\n            }\n\n            return [];\n        }\n    });\n});\n","Magento_Tax/js/view/checkout/summary/item/details/subtotal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'Magento_Checkout/js/view/summary/item/details/subtotal'\n], function (subtotal) {\n    'use strict';\n\n    var displayPriceMode = window.checkoutConfig.reviewItemPriceDisplayMode || 'including';\n\n    return subtotal.extend({\n        defaults: {\n            displayPriceMode: displayPriceMode,\n            template: 'Magento_Tax/checkout/summary/item/details/subtotal'\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isPriceInclTaxDisplayed: function () {\n            return displayPriceMode == 'both' || displayPriceMode == 'including'; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isPriceExclTaxDisplayed: function () {\n            return displayPriceMode == 'both' || displayPriceMode == 'excluding'; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @param {Object} quoteItem\n         * @return {*|String}\n         */\n        getValueInclTax: function (quoteItem) {\n            return this.getFormattedPrice(quoteItem['row_total_incl_tax']);\n        },\n\n        /**\n         * @param {Object} quoteItem\n         * @return {*|String}\n         */\n        getValueExclTax: function (quoteItem) {\n            return this.getFormattedPrice(quoteItem['row_total']);\n        }\n\n    });\n});\n","Magento_Tax/js/view/checkout/shipping_method/price.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Catalog/js/price-utils'\n], function (Component, quote, priceUtils) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Tax/checkout/shipping_method/price'\n        },\n        isDisplayShippingPriceExclTax: window.checkoutConfig.isDisplayShippingPriceExclTax,\n        isDisplayShippingBothPrices: window.checkoutConfig.isDisplayShippingBothPrices,\n\n        /**\n         * @param {Object} item\n         * @return {Boolean}\n         */\n        isPriceEqual: function (item) {\n            return item['price_excl_tax'] != item['price_incl_tax']; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @param {*} price\n         * @return {*|String}\n         */\n        getFormattedPrice: function (price) {\n            //todo add format data\n            return priceUtils.formatPriceLocale(price, quote.getPriceFormat());\n        }\n    });\n});\n","Magento_Payment/js/transparent.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'jquery',\n    'mage/template',\n    'Magento_Ui/js/modal/alert',\n    'jquery-ui-modules/widget',\n    'Magento_Payment/js/model/credit-card-validation/validator',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function ($, mageTemplate, alert, ui, validator, fullScreenLoader) {\n    'use strict';\n\n    $.widget('mage.transparent', {\n        options: {\n            context: null,\n            placeOrderSelector: '[data-role=\"review-save\"]',\n            paymentFormSelector: '#co-payment-form',\n            updateSelectorPrefix: '#checkout-',\n            updateSelectorSuffix: '-load',\n            hiddenFormTmpl:\n                '<form target=\"<%= data.target %>\" action=\"<%= data.action %>\" method=\"POST\" ' +\n                'hidden enctype=\"application/x-www-form-urlencoded\" class=\"no-display\">' +\n                    '<% _.each(data.inputs, function(val, key){ %>' +\n                    '<input value=\"<%= val %>\" name=\"<%= key %>\" type=\"hidden\">' +\n                    '<% }); %>' +\n                '</form>',\n            reviewAgreementForm: '#checkout-agreements',\n            cgiUrl: null,\n            orderSaveUrl: null,\n            controller: null,\n            gateway: null,\n            dateDelim: null,\n            cardFieldsMap: null,\n            expireYearLength: 2\n        },\n\n        /**\n         * {Function}\n         * @private\n         */\n        _create: function () {\n            this.hiddenFormTmpl = mageTemplate(this.options.hiddenFormTmpl);\n\n            if (this.options.context) {\n                this.options.context.setPlaceOrderHandler($.proxy(this._orderSave, this));\n                this.options.context.setValidateHandler($.proxy(this._validateHandler, this));\n            } else {\n                $(this.options.placeOrderSelector)\n                    .off('click')\n                    .on('click', $.proxy(this._placeOrderHandler, this));\n            }\n\n            this.element.validation();\n            $('[data-container=\"' + this.options.gateway + '-cc-number\"]').on('focusout', function () {\n                $(this).valid();\n            });\n        },\n\n        /**\n         * handler for credit card validation\n         * @return {Boolean}\n         * @private\n         */\n        _validateHandler: function () {\n            return this.element.validation && this.element.validation('isValid');\n        },\n\n        /**\n         * handler for Place Order button to call gateway for credit card validation\n         * @return {Boolean}\n         * @private\n         */\n        _placeOrderHandler: function () {\n            if (this._validateHandler()) {\n                this._orderSave();\n            }\n\n            return false;\n        },\n\n        /**\n         * Save order and generate post data for gateway call\n         * @private\n         */\n        _orderSave: function () {\n            var postData = $(this.options.paymentFormSelector).serialize();\n\n            if ($(this.options.reviewAgreementForm).length) {\n                postData += '&' + $(this.options.reviewAgreementForm).serialize();\n            }\n            postData += '&controller=' + this.options.controller;\n            postData += '&cc_type=' + this.element.find(\n                '[data-container=\"' + this.options.gateway + '-cc-type\"]'\n            ).val();\n\n            return $.ajax({\n                url: this.options.orderSaveUrl,\n                type: 'post',\n                context: this,\n                data: postData,\n                dataType: 'json',\n\n                /**\n                 * {Function}\n                 */\n                beforeSend: function () {\n                    fullScreenLoader.startLoader();\n                },\n\n                /**\n                 * {Function}\n                 */\n                success: function (response) {\n                    var preparedData,\n                        msg,\n\n                        /**\n                         * {Function}\n                         */\n                        alertActionHandler = function () {\n                            // default action\n                        };\n\n                    if (response.success && response[this.options.gateway]) {\n                        preparedData = this._preparePaymentData(\n                            response[this.options.gateway].fields,\n                            this.options.cardFieldsMap\n                        );\n                        this._postPaymentToGateway(preparedData);\n                    } else {\n                        fullScreenLoader.stopLoader(true);\n\n                        msg = response['error_messages'];\n\n                        if (this.options.context) {\n                            this.options.context.clearTimeout().fail();\n                            alertActionHandler = this.options.context.alertActionHandler;\n                        }\n\n                        if (typeof msg === 'object') {\n                            msg = msg.join('\\n');\n                        }\n\n                        if (msg) {\n                            alert(\n                                {\n                                    content: msg,\n                                    actions: {\n\n                                        /**\n                                         * {Function}\n                                         */\n                                        always: alertActionHandler\n                                    }\n                                }\n                            );\n                        }\n                    }\n                }.bind(this)\n            });\n        },\n\n        /**\n         * Post data to gateway for credit card validation\n         * @param {Object} data\n         * @private\n         */\n        _postPaymentToGateway: function (data) {\n            var tmpl,\n                iframeSelector = '[data-container=\"' + this.options.gateway + '-transparent-iframe\"]';\n\n            tmpl = this.hiddenFormTmpl({\n                data: {\n                    target: $(iframeSelector).attr('name'),\n                    action: this.options.cgiUrl,\n                    inputs: data\n                }\n            });\n            $(tmpl).appendTo($(iframeSelector)).trigger('submit');\n        },\n\n        /**\n         * Add credit card fields to post data for gateway\n         * @param {Object} data\n         * @param {Object} ccfields\n         * @private\n         */\n        _preparePaymentData: function (data, ccfields) {\n            var preparedata;\n\n            if (this.element.find('[data-container=\"' + this.options.gateway + '-cc-cvv\"]').length) {\n                data[ccfields.cccvv] = this.element.find(\n                    '[data-container=\"' + this.options.gateway + '-cc-cvv\"]'\n                ).val();\n            }\n            preparedata = this._prepareExpDate();\n            data[ccfields.ccexpdate] = preparedata.month + this.options.dateDelim + preparedata.year;\n            data[ccfields.ccnum] = this.element.find(\n                '[data-container=\"' + this.options.gateway + '-cc-number\"]'\n            ).val();\n\n            return data;\n        },\n\n        /**\n         * Grab Month and Year into one\n         * @returns {Object}\n         * @private\n         */\n        _prepareExpDate: function () {\n            var year = this.element.find('[data-container=\"' + this.options.gateway + '-cc-year\"]').val(),\n                month = parseInt(\n                    this.element.find('[data-container=\"' + this.options.gateway + '-cc-month\"]').val(),\n                    10\n                );\n\n            if (year.length > this.options.expireYearLength) {\n                year = year.substring(year.length - this.options.expireYearLength);\n            }\n\n            if (month < 10) {\n                month = '0' + month;\n            }\n\n            return {\n                month: month, year: year\n            };\n        }\n    });\n\n    return $.mage.transparent;\n});\n","Magento_Payment/js/cc-type.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.creditCardType', {\n        options: {\n            typeCodes: ['SS', 'SM', 'SO'] // Type codes for Switch/Maestro/Solo credit cards.\n        },\n\n        /**\n         * Bind change handler to select element and trigger the event to show/hide\n         * the Switch/Maestro or Solo credit card type container for those credit card types.\n         * @private\n         */\n        _create: function () {\n            this.element.on('change', $.proxy(this._toggleCardType, this)).trigger('change');\n        },\n\n        /**\n         * Toggle the Switch/Maestro and Solo credit card type container depending on which\n         * credit card type is selected.\n         * @private\n         */\n        _toggleCardType: function () {\n            $(this.options.creditCardTypeContainer)\n                .toggle($.inArray(this.element.val(), this.options.typeCodes) !== -1);\n        }\n    });\n\n    return $.mage.creditCardType;\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-data.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([], function () {\n    'use strict';\n\n    return {\n        creditCard: null,\n        creditCardNumber: null,\n        expirationMonth: null,\n        expirationYear: null,\n        cvvCode: null\n    };\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-number-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'mageUtils',\n    'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator',\n    'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/credit-card-type'\n], function (utils, luhn10, creditCardTypes) {\n    'use strict';\n\n    /**\n     * @param {*} card\n     * @param {*} isPotentiallyValid\n     * @param {*} isValid\n     * @return {Object}\n     */\n    function resultWrapper(card, isPotentiallyValid, isValid) {\n        return {\n            card: card,\n            isValid: isValid,\n            isPotentiallyValid: isPotentiallyValid\n        };\n    }\n\n    return function (value) {\n        var potentialTypes,\n            cardType,\n            valid,\n            i,\n            maxLength;\n\n        if (utils.isEmpty(value)) {\n            return resultWrapper(null, false, false);\n        }\n\n        value = value.replace(/\\s+/g, '');\n\n        if (!/^\\d*$/.test(value)) {\n            return resultWrapper(null, false, false);\n        }\n\n        potentialTypes = creditCardTypes.getCardTypes(value);\n\n        if (potentialTypes.length === 0) {\n            return resultWrapper(null, false, false);\n        } else if (potentialTypes.length !== 1) {\n            return resultWrapper(null, true, false);\n        }\n\n        cardType = potentialTypes[0];\n\n        if (cardType.type === 'unionpay') {  // UnionPay is not Luhn 10 compliant\n            valid = true;\n        } else {\n            valid = luhn10(value);\n        }\n\n        for (i = 0; i < cardType.lengths.length; i++) {\n            if (cardType.lengths[i] === value.length) {\n                return resultWrapper(cardType, valid, valid);\n            }\n        }\n\n        maxLength = Math.max.apply(null, cardType.lengths);\n\n        if (value.length < maxLength) {\n            return resultWrapper(cardType, true, false);\n        }\n\n        return resultWrapper(cardType, false, false);\n    };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'mageUtils',\n    'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/parse-date',\n    'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator',\n    'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator'\n], function (utils, parseDate, expirationMonth, expirationYear) {\n    'use strict';\n\n    /**\n     * @param {*} isValid\n     * @param {*} isPotentiallyValid\n     * @param {*} month\n     * @param {*} year\n     * @return {Object}\n     */\n    function resultWrapper(isValid, isPotentiallyValid, month, year) {\n        return {\n            isValid: isValid,\n            isPotentiallyValid: isPotentiallyValid,\n            month: month,\n            year: year\n        };\n    }\n\n    return function (value) {\n        var date,\n            monthValid,\n            yearValid;\n\n        if (utils.isEmpty(value)) {\n            return resultWrapper(false, false, null, null);\n        }\n\n        value = value.replace(/^(\\d\\d) (\\d\\d(\\d\\d)?)$/, '$1/$2');\n        date = parseDate(value);\n        monthValid = expirationMonth(date.month);\n        yearValid = expirationYear(date.year);\n\n        if (monthValid.isValid && yearValid.isValid) {\n            return resultWrapper(true, true, date.month, date.year);\n        }\n\n        if (monthValid.isPotentiallyValid && yearValid.isPotentiallyValid) {\n            return resultWrapper(false, true, null, null);\n        }\n\n        return resultWrapper(false, false, null, null);\n    };\n});\n","Magento_Payment/js/model/credit-card-validation/validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'jquery',\n    'Magento_Payment/js/model/credit-card-validation/cvv-validator',\n    'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator',\n    'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator',\n    'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator',\n    'Magento_Payment/js/model/credit-card-validation/credit-card-data',\n    'mage/translate'\n], function ($, cvvValidator, creditCardNumberValidator, yearValidator, monthValidator, creditCardData) {\n    'use strict';\n\n    $('.payment-method-content input[type=\"number\"]').on('keyup', function () {\n        if ($(this).val() < 0) {\n            $(this).val($(this).val().replace(/^-/, ''));\n        }\n    });\n\n    $.each({\n        'validate-card-type': [\n            function (number, item, allowedTypes) {\n                var cardInfo,\n                    i,\n                    l;\n\n                if (!creditCardNumberValidator(number).isValid) {\n                    return false;\n                }\n\n                cardInfo = creditCardNumberValidator(number).card;\n\n                for (i = 0, l = allowedTypes.length; i < l; i++) {\n                    if (cardInfo.title == allowedTypes[i].type) { //eslint-disable-line eqeqeq\n                        return true;\n                    }\n                }\n\n                return false;\n            },\n            $.mage.__('Please enter a valid credit card type number.')\n        ],\n        'validate-card-number': [\n\n            /**\n             * Validate credit card number based on mod 10\n             *\n             * @param {*} number - credit card number\n             * @return {Boolean}\n             */\n            function (number) {\n                return creditCardNumberValidator(number).isValid;\n            },\n            $.mage.__('Please enter a valid credit card number.')\n        ],\n        'validate-card-date': [\n\n            /**\n             * Validate credit card expiration month\n             *\n             * @param {String} date - month\n             * @return {Boolean}\n             */\n            function (date) {\n                return monthValidator(date).isValid;\n            },\n            $.mage.__('Incorrect credit card expiration month.')\n        ],\n        'validate-card-cvv': [\n\n            /**\n             * Validate cvv\n             *\n             * @param {String} cvv - card verification value\n             * @return {Boolean}\n             */\n            function (cvv) {\n                var maxLength = creditCardData.creditCard ? creditCardData.creditCard.code.size : 3;\n\n                return cvvValidator(cvv, maxLength).isValid;\n            },\n            $.mage.__('Please enter a valid credit card verification number.')\n        ],\n        'validate-card-year': [\n\n            /**\n             * Validate credit card expiration year\n             *\n             * @param {String} date - year\n             * @return {Boolean}\n             */\n            function (date) {\n                return yearValidator(date).isValid;\n            },\n            $.mage.__('Incorrect credit card expiration year.')\n        ]\n\n    }, function (i, rule) {\n        rule.unshift(i);\n        $.validator.addMethod.apply($.validator, rule);\n    });\n});\n","Magento_Payment/js/model/credit-card-validation/cvv-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([], function () {\n    'use strict';\n\n    /**\n     * @param {*} isValid\n     * @param {*} isPotentiallyValid\n     * @return {Object}\n     */\n    function resultWrapper(isValid, isPotentiallyValid) {\n        return {\n            isValid: isValid,\n            isPotentiallyValid: isPotentiallyValid\n        };\n    }\n\n    /**\n     * CVV number validation.\n     * Validate digit count for CVV code.\n     *\n     * @param {*} value\n     * @param {Number} maxLength\n     * @return {Object}\n     */\n    return function (value, maxLength) {\n        var DEFAULT_LENGTH = 3;\n\n        maxLength = maxLength || DEFAULT_LENGTH;\n\n        if (!/^\\d*$/.test(value)) {\n            return resultWrapper(false, false);\n        }\n\n        if (value.length === maxLength) {\n            return resultWrapper(true, true);\n        }\n\n        if (value.length < maxLength) {\n            return resultWrapper(false, true);\n        }\n\n        if (value.length > maxLength) {\n            return resultWrapper(false, false);\n        }\n    };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    /**\n     * @param {*} isValid\n     * @param {*} isPotentiallyValid\n     * @return {Object}\n     */\n    function resultWrapper(isValid, isPotentiallyValid) {\n        return {\n            isValid: isValid,\n            isPotentiallyValid: isPotentiallyValid\n        };\n    }\n\n    return function (value) {\n        var currentYear = new Date().getFullYear(),\n            len = value.length,\n            valid,\n            expMaxLifetime = 19;\n\n        if (value.replace(/\\s/g, '') === '') {\n            return resultWrapper(false, true);\n        }\n\n        if (!/^\\d*$/.test(value)) {\n            return resultWrapper(false, false);\n        }\n\n        if (len !== 4) {\n            return resultWrapper(false, true);\n        }\n\n        value = parseInt(value, 10);\n        valid = value >= currentYear && value <= currentYear + expMaxLifetime;\n\n        return resultWrapper(valid, valid);\n    };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator/parse-date.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return function (value) {\n        var month, len;\n\n        if (value.match('/')) {\n            value = value.split(/\\s*\\/\\s*/g);\n\n            return {\n                month: value[0],\n                year: value.slice(1).join()\n            };\n        }\n\n        len = value[0] === '0' || value.length > 5 || value.length === 4 || value.length === 3 ? 2 : 1;\n        month = value.substr(0, len);\n\n        return {\n            month: month,\n            year: value.substr(month.length, 4)\n        };\n    };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    /**\n     * @param {*} isValid\n     * @param {*} isPotentiallyValid\n     * @return {Object}\n     */\n    function resultWrapper(isValid, isPotentiallyValid) {\n        return {\n            isValid: isValid,\n            isPotentiallyValid: isPotentiallyValid\n        };\n    }\n\n    return function (value) {\n        var month,\n            monthValid;\n\n        if (value.replace(/\\s/g, '') === '' || value === '0') {\n            return resultWrapper(false, true);\n        }\n\n        if (!/^\\d*$/.test(value)) {\n            return resultWrapper(false, false);\n        }\n\n        if (isNaN(value)) {\n            return resultWrapper(false, false);\n        }\n\n        month = parseInt(value, 10);\n        monthValid = month > 0 && month < 13;\n\n        return resultWrapper(monthValid, monthValid);\n    };\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'jquery',\n    'mageUtils'\n], function ($, utils) {\n    'use strict';\n\n    var types = [\n        {\n            title: 'Visa',\n            type: 'VI',\n            pattern: '^4\\\\d*$',\n            gaps: [4, 8, 12],\n            lengths: [16],\n            code: {\n                name: 'CVV',\n                size: 3\n            }\n        },\n        {\n            title: 'MasterCard',\n            type: 'MC',\n            pattern: '^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$',\n            gaps: [4, 8, 12],\n            lengths: [16],\n            code: {\n                name: 'CVC',\n                size: 3\n            }\n        },\n        {\n            title: 'American Express',\n            type: 'AE',\n            pattern: '^3([47]\\\\d*)?$',\n            isAmex: true,\n            gaps: [4, 10],\n            lengths: [15],\n            code: {\n                name: 'CID',\n                size: 4\n            }\n        },\n        {\n            title: 'Diners',\n            type: 'DN',\n            pattern: '^(3(0[0-5]|095|6|[8-9]))\\\\d*$',\n            gaps: [4, 10],\n            lengths: [14, 16, 17, 18, 19],\n            code: {\n                name: 'CVV',\n                size: 3\n            }\n        },\n        {\n            title: 'Discover',\n            type: 'DI',\n            pattern: '^(6011(0|[2-4]|74|7[7-9]|8[6-9]|9)|6(4[4-9]|5))\\\\d*$',\n            gaps: [4, 8, 12],\n            lengths: [16, 17, 18, 19],\n            code: {\n                name: 'CID',\n                size: 3\n            }\n        },\n        {\n            title: 'JCB',\n            type: 'JCB',\n            pattern: '^35(2[8-9]|[3-8])\\\\d*$',\n            gaps: [4, 8, 12],\n            lengths: [16, 17, 18, 19],\n            code: {\n                name: 'CVV',\n                size: 3\n            }\n        },\n        {\n            title: 'UnionPay',\n            type: 'UN',\n            pattern: '^(622(1(2[6-9]|[3-9])|[3-8]|9([[0-1]|2[0-5]))|62[4-6]|628([2-8]))\\\\d*?$',\n            gaps: [4, 8, 12],\n            lengths: [16, 17, 18, 19],\n            code: {\n                name: 'CVN',\n                size: 3\n            }\n        },\n        {\n            title: 'Maestro International',\n            type: 'MI',\n            pattern: '^(5(0|[6-9])|63|67(?!59|6770|6774))\\\\d*$',\n            gaps: [4, 8, 12],\n            lengths: [12, 13, 14, 15, 16, 17, 18, 19],\n            code: {\n                name: 'CVC',\n                size: 3\n            }\n        },\n        {\n            title: 'Maestro Domestic',\n            type: 'MD',\n            pattern: '^6759(?!24|38|40|6[3-9]|70|76)|676770|676774\\\\d*$',\n            gaps: [4, 8, 12],\n            lengths: [12, 13, 14, 15, 16, 17, 18, 19],\n            code: {\n                name: 'CVC',\n                size: 3\n            }\n        },\n        {\n            title: 'Hipercard',\n            type: 'HC',\n            pattern: '^((606282)|(637095)|(637568)|(637599)|(637609)|(637612))\\\\d*$',\n            gaps: [4, 8, 12],\n            lengths: [13, 16],\n            code: {\n                name: 'CVC',\n                size: 3\n            }\n        },\n        {\n            title: 'Elo',\n            type: 'ELO',\n            pattern: '^((509091)|(636368)|(636297)|(504175)|(438935)|(40117[8-9])|(45763[1-2])|' +\n                '(457393)|(431274)|(50990[0-2])|(5099[7-9][0-9])|(50996[4-9])|(509[1-8][0-9][0-9])|' +\n                '(5090(0[0-2]|0[4-9]|1[2-9]|[24589][0-9]|3[1-9]|6[0-46-9]|7[0-24-9]))|' +\n                '(5067(0[0-24-8]|1[0-24-9]|2[014-9]|3[0-379]|4[0-9]|5[0-3]|6[0-5]|7[0-8]))|' +\n                '(6504(0[5-9]|1[0-9]|2[0-9]|3[0-9]))|' +\n                '(6504(8[5-9]|9[0-9])|6505(0[0-9]|1[0-9]|2[0-9]|3[0-8]))|' +\n                '(6505(4[1-9]|5[0-9]|6[0-9]|7[0-9]|8[0-9]|9[0-8]))|' +\n                '(6507(0[0-9]|1[0-8]))|(65072[0-7])|(6509(0[1-9]|1[0-9]|20))|' +\n                '(6516(5[2-9]|6[0-9]|7[0-9]))|(6550(0[0-9]|1[0-9]))|' +\n                '(6550(2[1-9]|3[0-9]|4[0-9]|5[0-8])))\\\\d*$',\n            gaps: [4, 8, 12],\n            lengths: [16],\n            code: {\n                name: 'CVC',\n                size: 3\n            }\n        },\n        {\n            title: 'Aura',\n            type: 'AU',\n            pattern: '^5078\\\\d*$',\n            gaps: [4, 8, 12],\n            lengths: [19],\n            code: {\n                name: 'CVC',\n                size: 3\n            }\n        }\n    ];\n\n    return {\n        /**\n         * @param {*} cardNumber\n         * @return {Array}\n         */\n        getCardTypes: function (cardNumber) {\n            var i, value,\n                result = [];\n\n            if (utils.isEmpty(cardNumber)) {\n                return result;\n            }\n\n            if (cardNumber === '') {\n                return $.extend(true, {}, types);\n            }\n\n            for (i = 0; i < types.length; i++) {\n                value = types[i];\n\n                if (new RegExp(value.pattern).test(cardNumber)) {\n                    result.push($.extend(true, {}, value));\n                }\n            }\n\n            return result;\n        }\n    };\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    /**\n     * Luhn algorithm verification\n     */\n    return function (a, b, c, d, e) {\n        for (d = +a[b = a.length - 1], e = 0; b--;) {\n            c = +a[b];\n            d += ++e % 2 ? 2 * c % 10 + (c > 4) : c;\n        }\n\n        return !(d % 10);\n    };\n});\n","Magento_Payment/js/view/payment/iframe.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'jquery',\n    'Magento_Payment/js/view/payment/cc-form',\n    'Magento_Ui/js/model/messageList',\n    'mage/translate',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Checkout/js/action/set-payment-information',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Ui/js/modal/alert'\n], function (\n    $,\n    Component,\n    messageList,\n    $t,\n    fullScreenLoader,\n    setPaymentInformationAction,\n    additionalValidators,\n    alert\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Payment/payment/iframe',\n            timeoutId: null,\n            timeoutMessage: 'Sorry, but something went wrong.'\n        },\n\n        /**\n         * @returns {String}\n         */\n        getSource: function () {\n            return window.checkoutConfig.payment.iframe.source[this.getCode()];\n        },\n\n        /**\n         * @returns {String}\n         */\n        getControllerName: function () {\n            return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];\n        },\n\n        /**\n         * @returns {String}\n         */\n        getPlaceOrderUrl: function () {\n            return window.checkoutConfig.payment.iframe.placeOrderUrl[this.getCode()];\n        },\n\n        /**\n         * @returns {String}\n         */\n        getCgiUrl: function () {\n            return window.checkoutConfig.payment.iframe.cgiUrl[this.getCode()];\n        },\n\n        /**\n         * @returns {String}\n         */\n        getSaveOrderUrl: function () {\n            return window.checkoutConfig.payment.iframe.saveOrderUrl[this.getCode()];\n        },\n\n        /**\n         * @returns {String}\n         */\n        getDateDelim: function () {\n            return window.checkoutConfig.payment.iframe.dateDelim[this.getCode()];\n        },\n\n        /**\n         * @returns {String}\n         */\n        getCardFieldsMap: function () {\n            return window.checkoutConfig.payment.iframe.cardFieldsMap[this.getCode()];\n        },\n\n        /**\n         * @returns {String}\n         */\n        getExpireYearLength: function () {\n            return window.checkoutConfig.payment.iframe.expireYearLength[this.getCode()];\n        },\n\n        /**\n         * @param {Object} parent\n         * @returns {Function}\n         */\n        originalPlaceOrder: function (parent) {\n            return parent.placeOrder.bind(parent);\n        },\n\n        /**\n         * @returns {Number}\n         */\n        getTimeoutTime: function () {\n            return window.checkoutConfig.payment.iframe.timeoutTime[this.getCode()];\n        },\n\n        /**\n         * @returns {String}\n         */\n        getTimeoutMessage: function () {\n            return $t(this.timeoutMessage);\n        },\n\n        /**\n         * @override\n         */\n        placeOrder: function () {\n            var self = this;\n\n            if (this.validateHandler() &&\n                additionalValidators.validate() &&\n                this.isPlaceOrderActionAllowed() === true\n            ) {\n                fullScreenLoader.startLoader();\n\n                this.isPlaceOrderActionAllowed(false);\n\n                $.when(\n                    this.setPaymentInformation()\n                ).done(\n                    this.done.bind(this)\n                ).fail(\n                    this.fail.bind(this)\n                ).always(\n                    function () {\n                        self.isPlaceOrderActionAllowed(true);\n                    }\n                );\n\n                this.initTimeoutHandler();\n            }\n        },\n\n        /**\n         * {Function}\n         */\n        setPaymentInformation: function () {\n            return setPaymentInformationAction(\n                this.messageContainer,\n                {\n                    method: this.getCode()\n                }\n            );\n        },\n\n        /**\n         * {Function}\n         */\n        initTimeoutHandler: function () {\n            this.timeoutId = setTimeout(\n                this.timeoutHandler.bind(this),\n                this.getTimeoutTime()\n            );\n\n            $(window).off('clearTimeout')\n                .on('clearTimeout', this.clearTimeout.bind(this));\n        },\n\n        /**\n         * {Function}\n         */\n        clearTimeout: function () {\n            clearTimeout(this.timeoutId);\n            this.fail();\n\n            return this;\n        },\n\n        /**\n         * {Function}\n         */\n        timeoutHandler: function () {\n            this.clearTimeout();\n\n            alert(\n                {\n                    content: this.getTimeoutMessage(),\n                    actions: {\n\n                        /**\n                         * {Function}\n                         */\n                        always: this.alertActionHandler.bind(this)\n                    }\n                }\n            );\n\n            this.fail();\n        },\n\n        /**\n         * {Function}\n         */\n        alertActionHandler: function () {\n            fullScreenLoader.startLoader();\n            window.location.reload();\n        },\n\n        /**\n         * {Function}\n         */\n        fail: function () {\n            fullScreenLoader.stopLoader();\n\n            return this;\n        },\n\n        /**\n         * {Function}\n         */\n        done: function () {\n            this.placeOrderHandler().fail(function () {\n                fullScreenLoader.stopLoader();\n            });\n\n            return this;\n        }\n    });\n});\n","Magento_Payment/js/view/payment/cc-form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'underscore',\n    'Magento_Checkout/js/view/payment/default',\n    'Magento_Payment/js/model/credit-card-validation/credit-card-data',\n    'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator',\n    'mage/translate'\n], function (_, Component, creditCardData, cardNumberValidator, $t) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            creditCardType: '',\n            creditCardExpYear: '',\n            creditCardExpMonth: '',\n            creditCardNumber: '',\n            creditCardSsStartMonth: '',\n            creditCardSsStartYear: '',\n            creditCardSsIssue: '',\n            creditCardVerificationNumber: '',\n            selectedCardType: null\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super()\n                .observe([\n                    'creditCardType',\n                    'creditCardExpYear',\n                    'creditCardExpMonth',\n                    'creditCardNumber',\n                    'creditCardVerificationNumber',\n                    'creditCardSsStartMonth',\n                    'creditCardSsStartYear',\n                    'creditCardSsIssue',\n                    'selectedCardType'\n                ]);\n\n            return this;\n        },\n\n        /**\n         * Init component\n         */\n        initialize: function () {\n            var self = this;\n\n            this._super();\n\n            //Set credit card number to credit card data object\n            this.creditCardNumber.subscribe(function (value) {\n                var result;\n\n                self.selectedCardType(null);\n\n                if (value === '' || value === null) {\n                    return false;\n                }\n                result = cardNumberValidator(value);\n\n                if (!result.isPotentiallyValid && !result.isValid) {\n                    return false;\n                }\n\n                if (result.card !== null) {\n                    self.selectedCardType(result.card.type);\n                    creditCardData.creditCard = result.card;\n                }\n\n                if (result.isValid) {\n                    creditCardData.creditCardNumber = value;\n                    self.creditCardType(result.card.type);\n                }\n            });\n\n            //Set expiration year to credit card data object\n            this.creditCardExpYear.subscribe(function (value) {\n                creditCardData.expirationYear = value;\n            });\n\n            //Set expiration month to credit card data object\n            this.creditCardExpMonth.subscribe(function (value) {\n                creditCardData.expirationMonth = value;\n            });\n\n            //Set cvv code to credit card data object\n            this.creditCardVerificationNumber.subscribe(function (value) {\n                creditCardData.cvvCode = value;\n            });\n        },\n\n        /**\n         * Get code\n         * @returns {String}\n         */\n        getCode: function () {\n            return 'cc';\n        },\n\n        /**\n         * Get data\n         * @returns {Object}\n         */\n        getData: function () {\n            return {\n                'method': this.item.method,\n                'additional_data': {\n                    'cc_cid': this.creditCardVerificationNumber(),\n                    'cc_ss_start_month': this.creditCardSsStartMonth(),\n                    'cc_ss_start_year': this.creditCardSsStartYear(),\n                    'cc_ss_issue': this.creditCardSsIssue(),\n                    'cc_type': this.creditCardType(),\n                    'cc_exp_year': this.creditCardExpYear(),\n                    'cc_exp_month': this.creditCardExpMonth(),\n                    'cc_number': this.creditCardNumber()\n                }\n            };\n        },\n\n        /**\n         * Get list of available credit card types\n         * @returns {Object}\n         */\n        getCcAvailableTypes: function () {\n            return window.checkoutConfig.payment.ccform.availableTypes[this.getCode()];\n        },\n\n        /**\n         * Get payment icons\n         * @param {String} type\n         * @returns {Boolean}\n         */\n        getIcons: function (type) {\n            return window.checkoutConfig.payment.ccform.icons.hasOwnProperty(type) ?\n                window.checkoutConfig.payment.ccform.icons[type]\n                : false;\n        },\n\n        /**\n         * Get list of months\n         * @returns {Object}\n         */\n        getCcMonths: function () {\n            return window.checkoutConfig.payment.ccform.months[this.getCode()];\n        },\n\n        /**\n         * Get list of years\n         * @returns {Object}\n         */\n        getCcYears: function () {\n            return window.checkoutConfig.payment.ccform.years[this.getCode()];\n        },\n\n        /**\n         * Check if current payment has verification\n         * @returns {Boolean}\n         */\n        hasVerification: function () {\n            return window.checkoutConfig.payment.ccform.hasVerification[this.getCode()];\n        },\n\n        /**\n         * @deprecated\n         * @returns {Boolean}\n         */\n        hasSsCardType: function () {\n            return window.checkoutConfig.payment.ccform.hasSsCardType[this.getCode()];\n        },\n\n        /**\n         * Get image url for CVV\n         * @returns {String}\n         */\n        getCvvImageUrl: function () {\n            return window.checkoutConfig.payment.ccform.cvvImageUrl[this.getCode()];\n        },\n\n        /**\n         * Get image for CVV\n         * @returns {String}\n         */\n        getCvvImageHtml: function () {\n            return '<img src=\"' + this.getCvvImageUrl() +\n                '\" alt=\"' + $t('Card Verification Number Visual Reference') +\n                '\" title=\"' + $t('Card Verification Number Visual Reference') +\n                '\" />';\n        },\n\n        /**\n         * Get unsanitized html for image for CVV\n         * @returns {String}\n         */\n        getCvvImageUnsanitizedHtml: function () {\n            return this.getCvvImageHtml();\n        },\n\n        /**\n         * @deprecated\n         * @returns {Object}\n         */\n        getSsStartYears: function () {\n            return window.checkoutConfig.payment.ccform.ssStartYears[this.getCode()];\n        },\n\n        /**\n         * Get list of available credit card types values\n         * @returns {Object}\n         */\n        getCcAvailableTypesValues: function () {\n            return _.map(this.getCcAvailableTypes(), function (value, key) {\n                return {\n                    'value': key,\n                    'type': value\n                };\n            });\n        },\n\n        /**\n         * Get list of available month values\n         * @returns {Object}\n         */\n        getCcMonthsValues: function () {\n            return _.map(this.getCcMonths(), function (value, key) {\n                return {\n                    'value': key,\n                    'month': value\n                };\n            });\n        },\n\n        /**\n         * Get list of available year values\n         * @returns {Object}\n         */\n        getCcYearsValues: function () {\n            return _.map(this.getCcYears(), function (value, key) {\n                return {\n                    'value': key,\n                    'year': value\n                };\n            });\n        },\n\n        /**\n         * @deprecated\n         * @returns {Object}\n         */\n        getSsStartYearsValues: function () {\n            return _.map(this.getSsStartYears(), function (value, key) {\n                return {\n                    'value': key,\n                    'year': value\n                };\n            });\n        },\n\n        /**\n         * Is legend available to display\n         * @returns {Boolean}\n         */\n        isShowLegend: function () {\n            return false;\n        },\n\n        /**\n         * Get available credit card type by code\n         * @param {String} code\n         * @returns {String}\n         */\n        getCcTypeTitleByCode: function (code) {\n            var title = '',\n                keyValue = 'value',\n                keyType = 'type';\n\n            _.each(this.getCcAvailableTypesValues(), function (value) {\n                if (value[keyValue] === code) {\n                    title = value[keyType];\n                }\n            });\n\n            return title;\n        },\n\n        /**\n         * Prepare credit card number to output\n         * @param {String} number\n         * @returns {String}\n         */\n        formatDisplayCcNumber: function (number) {\n            return 'xxxx-' + number.substr(-4);\n        },\n\n        /**\n         * Get credit card details\n         * @returns {Array}\n         */\n        getInfo: function () {\n            return [\n                {\n                    'name': 'Credit Card Type', value: this.getCcTypeTitleByCode(this.creditCardType())\n                },\n                {\n                    'name': 'Credit Card Number', value: this.formatDisplayCcNumber(this.creditCardNumber())\n                }\n            ];\n        }\n    });\n});\n","Magento_Payment/js/view/payment/payments.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n    'use strict';\n\n    rendererList.push(\n        {\n            type: 'free',\n            component: 'Magento_Payment/js/view/payment/method-renderer/free-method'\n        }\n    );\n\n    /** Add view logic here if needed */\n    return Component.extend({});\n});\n","Magento_Payment/js/view/payment/method-renderer/free-method.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n    'Magento_Checkout/js/view/payment/default',\n    'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Payment/payment/free'\n        },\n\n        /** Returns is method available */\n        isAvailable: function () {\n            return quote.totals()['grand_total'] <= 0;\n        }\n    });\n});\n","Magento_Msrp/js/msrp.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_Catalog/js/price-utils',\n    'underscore',\n    'jquery-ui-modules/widget',\n    'mage/dropdown',\n    'mage/template'\n], function ($, priceUtils, _) {\n    'use strict';\n\n    $.widget('mage.addToCart', {\n        options: {\n            showAddToCart: true,\n            submitUrl: '',\n            cartButtonId: '',\n            singleOpenDropDown: true,\n            dialog: {}, // Options for mage/dropdown\n            dialogDelay: 500, // Delay in ms after resize dropdown shown again\n            origin: '', //Required, type of popup: 'msrp', 'tier' or 'info' popup\n\n            // Selectors\n            cartForm: '.form.map.checkout',\n            msrpLabelId: '#map-popup-msrp',\n            msrpPriceElement: '#map-popup-msrp .price-wrapper',\n            priceLabelId: '#map-popup-price',\n            priceElement: '#map-popup-price .price',\n            mapInfoLinks: '.map-show-info',\n            displayPriceElement: '.old-price.map-old-price .price-wrapper',\n            fallbackPriceElement: '.normal-price.map-fallback-price .price-wrapper',\n            displayPriceContainer: '.old-price.map-old-price',\n            fallbackPriceContainer: '.normal-price.map-fallback-price',\n            popUpAttr: '[data-role=msrp-popup-template]',\n            popupCartButtonId: '#map-popup-button',\n            paypalCheckoutButons: '[data-action=checkout-form-submit]',\n            popupId: '',\n            realPrice: '',\n            isSaleable: '',\n            msrpPrice: '',\n            helpLinkId: '',\n            addToCartButton: '',\n\n            // Text options\n            productName: '',\n            addToCartUrl: ''\n        },\n\n        openDropDown: null,\n        triggerClass: 'dropdown-active',\n\n        popUpOptions: {\n            appendTo: 'body',\n            dialogContentClass: 'active',\n            closeOnMouseLeave: false,\n            autoPosition: true,\n            closeOnClickOutside: false,\n            'dialogClass': 'popup map-popup-wrapper',\n            position: {\n                my: 'left top',\n                collision: 'fit none',\n                at: 'left bottom',\n                within: 'body'\n            },\n            shadowHinter: 'popup popup-pointer'\n        },\n        popupOpened: false,\n        wasOpened: false,\n\n        /**\n         * Creates widget instance\n         *\n         * @private\n         */\n        _create: function () {\n            if (this.options.origin === 'msrp') {\n                this.initMsrpPopup();\n            } else if (this.options.origin === 'info') {\n                this.initInfoPopup();\n            } else if (this.options.origin === 'tier') {\n                this.initTierPopup();\n            }\n            $(this.options.cartButtonId).on('click', this._addToCartSubmit.bind(this));\n            $(document).on('updateMsrpPriceBlock', this.onUpdateMsrpPrice.bind(this));\n            $(this.options.cartForm).on('submit', this._onSubmitForm.bind(this));\n        },\n\n        /**\n         * Init msrp popup\n         *\n         * @private\n         */\n        initMsrpPopup: function () {\n            var popupDOM = $(this.options.popUpAttr)[0],\n                $msrpPopup = $(popupDOM.innerHTML.trim());\n\n            $msrpPopup.find(this.options.productIdInput).val(this.options.productId);\n            $('body').append($msrpPopup);\n            $msrpPopup.trigger('contentUpdated');\n\n            $msrpPopup.find('button')\n                .on('click',\n                    this.handleMsrpAddToCart.bind(this))\n                .filter(this.options.popupCartButtonId)\n                .text($(this.options.addToCartButton).text());\n\n            $msrpPopup.find(this.options.paypalCheckoutButons).on('click',\n                this.handleMsrpPaypalCheckout.bind(this));\n\n            $(this.options.popupId).on('click',\n                this.openPopup.bind(this));\n\n            this.$popup = $msrpPopup;\n        },\n\n        /**\n         * Init info popup\n         *\n         * @private\n         */\n        initInfoPopup: function () {\n            var infoPopupDOM = $('[data-role=msrp-info-template]')[0],\n                $infoPopup = $(infoPopupDOM.innerHTML.trim());\n\n            $('body').append($infoPopup);\n\n            $(this.options.helpLinkId).on('click', function (e) {\n                this.popUpOptions.position.of = $(e.target);\n                $infoPopup.dropdownDialog(this.popUpOptions).dropdownDialog('open');\n                this._toggle($infoPopup);\n            }.bind(this));\n\n            this.$popup = $infoPopup;\n        },\n\n        /**\n         * Init tier price popup\n         * @private\n         */\n        initTierPopup: function () {\n            var popupDOM = $(this.options.popUpAttr)[0],\n                $tierPopup = $(popupDOM.innerHTML.trim());\n\n            $('body').append($tierPopup);\n            $tierPopup.find(this.options.productIdInput).val(this.options.productId);\n            this.popUpOptions.position.of = $(this.options.helpLinkId);\n\n            $tierPopup.find('button').on('click',\n                this.handleTierAddToCart.bind(this))\n                .filter(this.options.popupCartButtonId)\n                .text($(this.options.addToCartButton).text());\n\n            $tierPopup.find(this.options.paypalCheckoutButons).on('click',\n                this.handleTierPaypalCheckout.bind(this));\n\n            $(this.options.attr).on('click', function (e) {\n                this.$popup = $tierPopup;\n                this.tierOptions = $(e.target).data('tier-price');\n                this.openPopup(e);\n            }.bind(this));\n        },\n\n        /**\n         * handle 'AddToCart' click on Msrp popup\n         * @param {Object} ev\n         *\n         * @private\n         */\n        handleMsrpAddToCart: function (ev) {\n            ev.preventDefault();\n\n            if (this.options.addToCartButton) {\n                $(this.options.addToCartButton).trigger('click');\n                this.closePopup(this.$popup);\n            }\n        },\n\n        /**\n         * handle 'paypal checkout buttons' click on Msrp popup\n         *\n         * @private\n         */\n        handleMsrpPaypalCheckout: function () {\n            this.closePopup(this.$popup);\n        },\n\n        /**\n         * handle 'AddToCart' click on Tier popup\n         *\n         * @param {Object} ev\n         * @private\n         */\n        handleTierAddToCart: function (ev) {\n            ev.preventDefault();\n\n            if (this.options.addToCartButton &&\n                this.options.inputQty && !isNaN(this.tierOptions.qty)\n            ) {\n                $(this.options.inputQty).val(this.tierOptions.qty);\n                $(this.options.addToCartButton).trigger('click');\n                this.closePopup(this.$popup);\n            }\n        },\n\n        /**\n         * handle 'paypal checkout buttons' click on Tier popup\n         *\n         * @private\n         */\n        handleTierPaypalCheckout: function () {\n            if (this.options.inputQty && !isNaN(this.tierOptions.qty)\n            ) {\n                $(this.options.inputQty).val(this.tierOptions.qty);\n                this.closePopup(this.$popup);\n            }\n        },\n\n        /**\n         * Open and set up popup\n         *\n         * @param {Object} event\n         */\n        openPopup: function (event) {\n            var options = this.tierOptions || this.options;\n\n            this.popUpOptions.position.of = $(event.target);\n\n            if (!this.wasOpened) {\n                this.$popup.find(this.options.msrpLabelId).html(options.msrpPrice);\n                this.$popup.find(this.options.priceLabelId).html(options.realPrice);\n                this.wasOpened = true;\n            }\n            this.$popup.dropdownDialog(this.popUpOptions).dropdownDialog('open');\n            this._toggle(this.$popup);\n\n            if (!this.options.isSaleable) {\n                this.$popup.find('form').hide();\n            }\n        },\n\n        /**\n         * Toggle MAP popup visibility\n         *\n         * @param {HTMLElement} $elem\n         * @private\n         */\n        _toggle: function ($elem) {\n            $(document).on('mouseup.msrp touchend.msrp', function (e) {\n                if (!$elem.is(e.target) && $elem.has(e.target).length === 0) {\n                    this.closePopup($elem);\n                }\n            }.bind(this));\n            $(window).on('resize', function () {\n                this.closePopup($elem);\n            }.bind(this));\n        },\n\n        /**\n         * Close MAP information popup\n         *\n         * @param {HTMLElement} $elem\n         */\n        closePopup: function ($elem) {\n            $elem.dropdownDialog('close');\n            $(document).off('mouseup.msrp touchend.msrp');\n        },\n\n        /**\n         * Handler for addToCart action\n         *\n         * @param {Object} e\n         */\n        _addToCartSubmit: function (e) {\n            this.element.trigger('addToCart', this.element);\n\n            if (this.element.data('stop-processing')) {\n                return false;\n            }\n\n            if (this.options.addToCartButton) {\n                $(this.options.addToCartButton).trigger('click');\n\n                return false;\n            }\n\n            if (this.options.addToCartUrl) {\n                $('.mage-dropdown-dialog > .ui-dialog-content').dropdownDialog('close');\n            }\n\n            e.preventDefault();\n            $(this.options.cartForm).trigger('submit');\n        },\n\n        /**\n         * Call on event updatePrice. Proxy to updateMsrpPrice method.\n         *\n         * @param {Event} event\n         * @param {mixed} priceIndex\n         * @param {Object} prices\n         * @param {Object|undefined} $priceBox\n         */\n        onUpdateMsrpPrice: function onUpdateMsrpPrice(event, priceIndex, prices, $priceBox) {\n\n            var defaultMsrp,\n                defaultPrice,\n                msrpPrice,\n                finalPrice;\n\n            defaultMsrp = _.chain(prices).map(function (price) {\n                return price.msrpPrice.amount;\n            }).reject(function (p) {\n                return p === null;\n            }).max().value();\n\n            defaultPrice = _.chain(prices).map(function (p) {\n                return p.finalPrice.amount;\n            }).min().value();\n\n            if (typeof priceIndex !== 'undefined') {\n                msrpPrice = prices[priceIndex].msrpPrice.amount;\n                finalPrice = prices[priceIndex].finalPrice.amount;\n\n                if (msrpPrice === null || msrpPrice <= finalPrice) {\n                    this.updateNonMsrpPrice(priceUtils.formatPriceLocale(finalPrice), $priceBox);\n                } else {\n                    this.updateMsrpPrice(\n                        priceUtils.formatPriceLocale(finalPrice),\n                        priceUtils.formatPriceLocale(msrpPrice),\n                        false,\n                        $priceBox);\n                }\n            } else {\n                this.updateMsrpPrice(\n                    priceUtils.formatPriceLocale(defaultPrice),\n                    priceUtils.formatPriceLocale(defaultMsrp),\n                    true,\n                    $priceBox);\n            }\n        },\n\n        /**\n         * Update prices for configurable product with MSRP enabled\n         *\n         * @param {String} finalPrice\n         * @param {String} msrpPrice\n         * @param {Boolean} useDefaultPrice\n         * @param {Object|undefined} $priceBox\n         */\n        updateMsrpPrice: function (finalPrice, msrpPrice, useDefaultPrice, $priceBox) {\n            var options = this.tierOptions || this.options;\n\n            $(this.options.fallbackPriceContainer, $priceBox).hide();\n            $(this.options.displayPriceContainer, $priceBox).show();\n            $(this.options.mapInfoLinks, $priceBox).show();\n\n            if (useDefaultPrice || !this.wasOpened) {\n                if (this.$popup) {\n                    this.$popup.find(this.options.msrpLabelId).html(options.msrpPrice);\n                    this.$popup.find(this.options.priceLabelId).html(options.realPrice);\n                }\n\n                $(this.options.displayPriceElement, $priceBox).html(msrpPrice);\n                this.wasOpened = true;\n            }\n\n            if (!useDefaultPrice) {\n                this.$popup.find(this.options.msrpPriceElement).html(msrpPrice);\n                this.$popup.find(this.options.priceElement).html(finalPrice);\n                $(this.options.displayPriceElement, $priceBox).html(msrpPrice);\n            }\n        },\n\n        /**\n         * Display non MAP price for irrelevant products\n         *\n         * @param {String} price\n         * @param {Object|undefined} $priceBox\n         */\n        updateNonMsrpPrice: function (price, $priceBox) {\n            $(this.options.fallbackPriceElement, $priceBox).html(price);\n            $(this.options.displayPriceContainer, $priceBox).hide();\n            $(this.options.mapInfoLinks, $priceBox).hide();\n            $(this.options.fallbackPriceContainer, $priceBox).show();\n        },\n\n        /**\n         * Handler for submit form\n         *\n         * @private\n         */\n        _onSubmitForm: function () {\n            if ($(this.options.cartForm).valid()) {\n                $(this.options.cartButtonId).prop('disabled', true);\n            }\n        }\n\n    });\n\n    return $.mage.addToCart;\n});\n","Magento_Msrp/js/view/checkout/minicart/subtotal/totals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n    'Magento_Tax/js/view/checkout/minicart/subtotal/totals',\n    'underscore'\n], function (Component, _) {\n    'use strict';\n\n    return Component.extend({\n\n        /**\n         * @override\n         */\n        initialize: function () {\n            this._super();\n            this.displaySubtotal(this.isMsrpApplied(this.cart().items));\n            this.cart.subscribe(function (updatedCart) {\n\n                this.displaySubtotal(this.isMsrpApplied(updatedCart.items));\n            }, this);\n        },\n\n        /**\n         * Determine if subtotal should be hidden.\n         * @param {Array} cartItems\n         * @return {Boolean}\n         */\n        isMsrpApplied: function (cartItems) {\n            return !_.find(cartItems, function (item) {\n                if (_.has(item, 'canApplyMsrp')) {\n                    return item.canApplyMsrp;\n                }\n\n                return false;\n            });\n        }\n    });\n});\n","Magento_Msrp/js/product/list/columns/msrp-price.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Catalog/js/product/list/columns/price-box',\n    'Magento_Catalog/js/product/addtocart-button',\n    'mage/dropdown'\n], function ($, _, PriceBox) {\n    'use strict';\n\n    return PriceBox.extend({\n        defaults: {\n            priceBoxSelector: '[data-role=msrp-price-box]',\n            popupTmpl: 'Magento_Msrp/product/item/popup',\n            popupTriggerSelector: '[data-role=msrp-popup-trigger]',\n            popupSelector: '[data-role=msrp-popup]',\n            popupOptions: {\n                appendTo: 'body',\n                dialogContentClass: 'active',\n                closeOnMouseLeave: false,\n                autoPosition: true,\n                dialogClass: 'popup map-popup-wrapper',\n                position: {\n                    my: 'left top',\n                    collision: 'fit none',\n                    at: 'left bottom',\n                    within: 'body'\n                },\n                shadowHinter: 'popup popup-pointer'\n            }\n        },\n\n        /**\n         * Create and open popup with Msrp information.\n         *\n         * @param {Object} data - element data\n         * @param {DOMElement} elem - element\n         * @param {Event} event - event object\n         */\n        openPopup: function (data, elem, event) {\n            var $elem = $(elem),\n                $popup = $elem.find(this.popupSelector),\n                $trigger = $elem.find(this.popupTriggerSelector);\n\n            event.stopPropagation();\n\n            this.popupOptions.position.of = $trigger;\n            this.popupOptions.triggerTarget = $trigger;\n\n            $popup.dropdownDialog(this.popupOptions)\n                  .dropdownDialog('open');\n        },\n\n        /**\n         * Set listeners.\n         *\n         * @param {DOMElement} elem - DOM element\n         * @param {Object} data - element data\n         */\n        initListeners: function (elem, data) {\n            var $trigger = $(elem).find(this.popupTriggerSelector);\n\n            $trigger.on('click', this.openPopup.bind(this, data, elem));\n        },\n\n        /**\n         * Check whether we can apply msrp, or should use standard price.\n         *\n         * @param {Object} row\n         * @returns {Bool}\n         */\n        isMsrpApplicable: function (row) {\n            return this.getPrice(row)['is_applicable'];\n        },\n\n        /**\n         * Retrieve msrp formatted price\n         *\n         * @param {Object} row\n         * @returns {String}\n         */\n        getPrice: function (row) {\n            return row['price_info']['extension_attributes'].msrp;\n        },\n\n        /**\n         * UnsanitizedHtml version of getPrice.\n         *\n         * @param {Object} row\n         * @returns {String}\n         */\n        getPriceUnsanitizedHtml: function (row) {\n            return this.getPrice(row);\n        },\n\n        /**\n         * Get msrp_price property of a price.\n         *\n         * @param {Object} row\n         * @return {HTMLElement} final price html\n         */\n        getMsrpPriceUnsanitizedHtml: function (row) {\n            return this.getPrice(row)['msrp_price'];\n        },\n\n        /**\n         * Returns path to the columns' body template.\n         *\n         * @returns {String}\n         */\n        getBody: function () {\n            return this.bodyTmpl;\n        },\n\n        /**\n         * Check if popup with actual price must be shown.\n         *\n         * @returns {Boolean}\n         */\n        isShowPriceOnGesture: function (row) {\n            return this.getPrice(row)['is_shown_price_on_gesture'];\n        },\n\n        /**\n         * Get msrp price supporting text.\n         *\n         * @returns {String}\n         */\n        getMsrpPriceMessage: function (row) {\n            return this.getPrice(row)['msrp_message'];\n        },\n\n        /**\n         * UnsanitizedHtml version of getMsrpPriceMessage.\n         *\n         * @returns {String}\n         */\n        getMsrpPriceMessageUnsanitizedHtml: function (row) {\n            return this.getMsrpPriceMessage(row);\n        },\n\n        /**\n         * Get msrp price supporting text, when actual price is hidden.\n         *\n         * @returns {String}\n         */\n        getExplanationMessage: function (row) {\n            return this.getPrice(row)['explanation_message'];\n        },\n\n        /**\n         * UnsanitizedHtml version of getExplanationMessage.\n         *\n         * @returns {String}\n         */\n        getExplanationMessageUnsanitizedHtml: function (row) {\n            return this.getExplanationMessage(row);\n        }\n    });\n});\n","Magento_GroupedProduct/js/product-ids-resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_Catalog/js/product/view/product-ids',\n    'Magento_Catalog/js/product/view/product-info'\n], function ($, productIds, productInfo) {\n    'use strict';\n\n    /**\n     * Returns id's of products in form.\n     *\n     * @param {Object} config\n     * @param {HTMLElement} element\n     * @return {Array}\n     */\n    return function (config, element) {\n        $(element).find('div[data-product-id]').each(function () {\n            productIds.push($(this).data('productId').toString());\n            productInfo.push(\n                {\n                    'id': $(this).data('productId').toString()\n                }\n            );\n        });\n\n        return productIds();\n    };\n});\n","Magento_Variable/js/grid/columns/radioselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'mage/translate',\n    'Magento_Ui/js/grid/columns/column',\n    'jquery'\n], function (_, $t, Column, jQuery) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            bodyTmpl: 'Magento_Variable/grid/cells/radioselect',\n            draggable: false,\n            sortable: false,\n            selectedVariableCode: null,\n            selectedVariableType: null\n        },\n\n        /**\n         * Calls 'initObservable' of parent\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super().observe(['selectedVariableCode']);\n\n            return this;\n        },\n\n        /**\n         * Remove disable class from Insert Variable button after Variable has been chosen.\n         *\n         * @return {Boolean}\n         */\n        selectVariable: function () {\n            if (jQuery('#insert_variable').hasClass('disabled')) {\n                jQuery('#insert_variable').removeClass('disabled');\n            }\n\n            return true;\n        }\n    });\n});\n","Magento_Security/js/escaper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * A loose JavaScript version of Magento\\Framework\\Escaper\n *\n * Due to differences in how XML/HTML is processed in PHP vs JS there are a couple of minor differences in behavior\n * from the PHP counterpart.\n *\n * The first difference is that the default invocation of escapeHtml without allowedTags will double-escape existing\n * entities as the intention of such an invocation is that the input isn't supposed to contain any HTML.\n *\n * The second difference is that escapeHtml will not escape quotes. Since the input is actually being processed by the\n * DOM there is no chance of quotes being mixed with HTML syntax. And, since escapeHtml is not\n * intended to be used with raw injection into a HTML attribute, this is acceptable.\n *\n * @api\n */\ndefine([], function () {\n    'use strict';\n\n    return {\n        neverAllowedElements: ['script', 'img', 'embed', 'iframe', 'video', 'source', 'object', 'audio'],\n        generallyAllowedAttributes: ['id', 'class', 'href', 'title', 'style'],\n        forbiddenAttributesByElement: {\n            a: ['style']\n        },\n\n        /**\n         * Escape a string for safe injection into HTML\n         *\n         * @param {String} data\n         * @param {Array|null} allowedTags\n         * @returns {String}\n         */\n        escapeHtml: function (data, allowedTags) {\n            var domParser = new DOMParser(),\n                fragment = domParser.parseFromString('<div></div>', 'text/html');\n\n            fragment = fragment.body.childNodes[0];\n            allowedTags = typeof allowedTags === 'object' && allowedTags.length ? allowedTags : null;\n\n            if (allowedTags) {\n                fragment.innerHTML = data || '';\n                allowedTags = this._filterProhibitedTags(allowedTags);\n\n                this._removeComments(fragment);\n                this._removeNotAllowedElements(fragment, allowedTags);\n                this._removeNotAllowedAttributes(fragment);\n\n                return fragment.innerHTML;\n            }\n\n            fragment.textContent = data || '';\n\n            return fragment.innerHTML;\n        },\n\n        /**\n         * Remove the always forbidden tags from a list of provided tags\n         *\n         * @param {Array} tags\n         * @returns {Array}\n         * @private\n         */\n        _filterProhibitedTags: function (tags) {\n            return tags.filter(function (n) {\n                return this.neverAllowedElements.indexOf(n) === -1;\n            }.bind(this));\n        },\n\n        /**\n         * Remove comment nodes from the given node\n         *\n         * @param {Node} node\n         * @private\n         */\n        _removeComments: function (node) {\n            var treeWalker = node.ownerDocument.createTreeWalker(\n                    node,\n                    NodeFilter.SHOW_COMMENT,\n                    function () {\n                        return NodeFilter.FILTER_ACCEPT;\n                    },\n                    false\n                ),\n                nodesToRemove = [];\n\n            while (treeWalker.nextNode()) {\n                nodesToRemove.push(treeWalker.currentNode);\n            }\n\n            nodesToRemove.forEach(function (nodeToRemove) {\n                nodeToRemove.parentNode.removeChild(nodeToRemove);\n            });\n        },\n\n        /**\n         * Strip the given node of all disallowed tags while permitting any nested text nodes\n         *\n         * @param {Node} node\n         * @param {Array|null} allowedTags\n         * @private\n         */\n        _removeNotAllowedElements: function (node, allowedTags) {\n            var treeWalker = node.ownerDocument.createTreeWalker(\n                    node,\n                    NodeFilter.SHOW_ELEMENT,\n                    function (currentNode) {\n                        return allowedTags.indexOf(currentNode.nodeName.toLowerCase()) === -1 ?\n                            NodeFilter.FILTER_ACCEPT\n                            // SKIP instead of REJECT because REJECT also rejects child nodes\n                            : NodeFilter.FILTER_SKIP;\n                    },\n                false\n                ),\n                nodesToRemove = [];\n\n            while (treeWalker.nextNode()) {\n                if (allowedTags.indexOf(treeWalker.currentNode.nodeName.toLowerCase()) === -1) {\n                    nodesToRemove.push(treeWalker.currentNode);\n                }\n            }\n\n            nodesToRemove.forEach(function (nodeToRemove) {\n                nodeToRemove.parentNode.replaceChild(\n                    node.ownerDocument.createTextNode(nodeToRemove.textContent),\n                    nodeToRemove\n                );\n            });\n        },\n\n        /**\n         * Remove any invalid attributes from the given node\n         *\n         * @param {Node} node\n         * @private\n         */\n        _removeNotAllowedAttributes: function (node) {\n            var treeWalker = node.ownerDocument.createTreeWalker(\n                    node,\n                    NodeFilter.SHOW_ELEMENT,\n                    function () {\n                        return NodeFilter.FILTER_ACCEPT;\n                    },\n                false\n                ),\n                i,\n                attribute,\n                nodeName,\n                attributesToRemove = [];\n\n            while (treeWalker.nextNode()) {\n                for (i = 0; i < treeWalker.currentNode.attributes.length; i++) {\n                    attribute = treeWalker.currentNode.attributes[i];\n                    nodeName = treeWalker.currentNode.nodeName.toLowerCase();\n\n                    if (this.generallyAllowedAttributes.indexOf(attribute.name) === -1  || // eslint-disable-line max-depth,max-len\n                        this._checkHrefValue(attribute) ||\n                        this.forbiddenAttributesByElement[nodeName] &&\n                        this.forbiddenAttributesByElement[nodeName].indexOf(attribute.name) !== -1\n                    ) {\n                        attributesToRemove.push(attribute);\n                    }\n                }\n            }\n\n            attributesToRemove.forEach(function (attributeToRemove) {\n                attributeToRemove.ownerElement.removeAttribute(attributeToRemove.name);\n            });\n        },\n\n        /**\n         * Check that attribute contains script content\n         *\n         * @param {Object} attribute\n         * @private\n         */\n        _checkHrefValue: function (attribute) {\n            return attribute.nodeName === 'href' && attribute.nodeValue.startsWith('javascript');\n        }\n    };\n});\n","Magento_PageBuilder/js/widget-initializer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'jquery',\n    'mage/apply/main',\n    'Magento_Ui/js/lib/view/utils/dom-observer'\n], function (_, $, mage, domObserver) {\n    'use strict';\n\n    /**\n     * Initializes components assigned to HTML elements.\n     *\n     *\n     * @param {HTMLElement} el\n     * @param {Array} data\n     * @param {Object} breakpoints\n     * @param {Object} currentViewport\n     */\n    function initializeWidget(el, data, breakpoints, currentViewport) {\n        _.each(data, function (config, component) {\n            config = config || {};\n            config.breakpoints = breakpoints;\n            config.currentViewport = currentViewport;\n            mage.applyFor(el, config, component);\n        });\n    }\n\n    return function (data, contextElement) {\n        _.each(data.config, function (componentConfiguration, elementPath) {\n            domObserver.get(\n                elementPath,\n                function (element) {\n                    var $element = $(element);\n\n                    if (contextElement) {\n                        $element = $(contextElement).find(element);\n                    }\n\n                    if ($element.length) {\n                        initializeWidget($element, componentConfiguration, data.breakpoints, data.currentViewport);\n                    }\n                }\n            );\n        });\n    };\n});\n","Magento_PageBuilder/js/events.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['uiEvents'], function (uiEvents) {\n    'use strict';\n\n    return {\n\n        /**\n         * Calls callback when name event is triggered\n         *\n         * @param {String} events\n         * @param {Function} callback\n         * @param {Function} ns\n         * @return {Object}\n         */\n        on: function (events, callback, ns) {\n            uiEvents.on('pagebuilder:' + events, callback, 'pagebuilder:' + ns);\n\n            return this;\n        },\n\n        /**\n         * Removed callback from listening to target event\n         *\n         * @param {String} ns\n         * @return {Object}\n         */\n        off: function (ns) {\n            uiEvents.off('pagebuilder:' + ns);\n\n            return this;\n        },\n\n        /**\n         * Triggers event and executes all attached callbacks\n         *\n         * @param {String} name\n         * @param {any} args\n         * @returns {Boolean}\n         */\n        trigger: function (name, args) {\n            return uiEvents.trigger('pagebuilder:' + name, args);\n        }\n    };\n});\n","Magento_PageBuilder/js/content-type/banner/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'Magento_PageBuilder/js/widget/show-on-hover',\n    'Magento_PageBuilder/js/widget/video-background'\n], function (showOnHover, videoBackground) {\n    'use strict';\n\n    return function (config, element) {\n        var videoElement = element[0].querySelector('[data-background-type=video]');\n\n        showOnHover(config);\n\n        if (videoElement) {\n            videoBackground(config, videoElement);\n        }\n    };\n});\n","Magento_PageBuilder/js/content-type/tabs/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/events',\n    'jquery-ui-modules/tabs'\n], function ($, events) {\n    'use strict';\n\n    return function (config, element) {\n        var $element = $(element);\n\n        // Ignore stage builder preview tabs\n        if ($element.is('.pagebuilder-tabs')) {\n            return;\n        }\n\n        // Disambiguate between the mage/tabs component which is loaded randomly depending on requirejs order.\n        $.ui.tabs({\n            active: $element.data('activeTab') || 0,\n            create:\n\n                /**\n                 * Adjust the margin bottom of the navigation to correctly display the active tab\n                 */\n                function () {\n                    var borderWidth = parseInt($element.find('.tabs-content').css('borderWidth').toString(), 10);\n\n                    $element.find('.tabs-navigation').css('marginBottom', -borderWidth);\n                    $element.find('.tabs-navigation li:not(:first-child)').css('marginLeft', -borderWidth);\n                },\n            activate:\n\n                /**\n                 * Trigger redraw event since new content is being displayed\n                 */\n                function () {\n                    events.trigger('contentType:redrawAfter', {\n                        element: element\n                    });\n                }\n        }, element);\n    };\n});\n","Magento_PageBuilder/js/content-type/buttons/appearance/inline/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/events'\n], function ($, events) {\n    'use strict';\n\n    /**\n     * Equalize the width of a list of button-item components\n     *\n     * @param {JQuery} buttonList\n     */\n    var equalizeButtonWidth = function (buttonList) {\n        var buttonMinWidth = 0;\n\n        buttonList.css('min-width', buttonMinWidth);\n        buttonList.each(function () {\n            var buttonWidth = this.offsetWidth;\n\n            if (buttonWidth > buttonMinWidth) {\n                buttonMinWidth = buttonWidth;\n            }\n        });\n        buttonList.css('min-width', buttonMinWidth);\n    };\n\n    return function (config, element) {\n        var $element = $(element),\n            buttonSelector = '[data-element=\"link\"], [data-element=\"empty_link\"]';\n\n        if ($element.data('sameWidth')) {\n            equalizeButtonWidth($element.find(buttonSelector));\n            $(window).on('resize', function () {\n                equalizeButtonWidth($element.find(buttonSelector));\n            });\n            events.on('contentType:redrawAfter', function (eventData) {\n                if ($element.closest(eventData.element).length > 0) {\n                    equalizeButtonWidth($element.find(buttonSelector));\n                }\n            });\n        }\n    };\n});\n","Magento_PageBuilder/js/content-type/row/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/widget/video-background',\n    'jarallax'\n], function ($, videoBackground) {\n    'use strict';\n\n    return function (config, element) {\n        var $element = $(element),\n            parallaxSpeed = null,\n            elementStyle = null;\n\n        if ($element.data('appearance') === 'contained') {\n            $element = $(element).find('[data-element=\"inner\"]');\n        }\n\n        if ($element.data('background-type') === 'video') {\n            videoBackground(config, $element[0]);\n\n            return;\n        }\n\n        if ($element.data('enableParallax') !== 1) {\n            return;\n        }\n\n        $element.addClass('jarallax');\n        $element.attr('data-jarallax', '');\n\n        parallaxSpeed = parseFloat($element.data('parallaxSpeed'));\n        elementStyle = window.getComputedStyle($element[0]);\n\n        window.jarallax($element[0], {\n            imgPosition: elementStyle.backgroundPosition || '50% 50%',\n            imgRepeat: elementStyle.backgroundRepeat || 'no-repeat',\n            imgSize: elementStyle.backgroundSize || 'cover',\n            speed: !isNaN(parallaxSpeed) ? parallaxSpeed : 0.5\n        });\n    };\n});\n","Magento_PageBuilder/js/content-type/slider/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/events',\n    'slick'\n], function ($, events) {\n    'use strict';\n\n    return function (config, sliderElement) {\n        var $element = $(sliderElement);\n\n        /**\n         * Prevent each slick slider from being initialized more than once which could throw an error.\n         */\n        if ($element.hasClass('slick-initialized')) {\n            $element.slick('unslick');\n        }\n\n        $element.slick({\n            autoplay: $element.data('autoplay'),\n            autoplaySpeed: $element.data('autoplay-speed') || 0,\n            fade: $element.data('fade'),\n            infinite: $element.data('infinite-loop'),\n            arrows: $element.data('show-arrows'),\n            dots: $element.data('show-dots')\n        });\n\n        // Redraw slide after content type gets redrawn\n        events.on('contentType:redrawAfter', function (args) {\n            if ($element.closest(args.element).length) {\n                $element.slick('setPosition');\n            }\n        });\n        // eslint-disable-next-line jquery-no-bind-unbind\n        events.on('stage:viewportChangeAfter', $element.slick.bind($element, 'setPosition'));\n    };\n});\n","Magento_PageBuilder/js/content-type/map/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/utils/map'\n], function ($, GoogleMap) {\n    'use strict';\n\n    return function (config, element) {\n        var locations,\n            controls,\n            mapOptions = {};\n\n        element = element[0];\n\n        if (element !== undefined && element.hasAttribute('data-locations')) {\n\n            /**\n             * Set map display to none if no locations\n             */\n            if (element.getAttribute('data-locations') === '[]') {\n                $(element).hide();\n\n                return;\n            }\n            locations = JSON.parse(element.getAttribute('data-locations'));\n            locations.forEach(function (location) {\n                location.position.latitude = parseFloat(location.position.latitude);\n                location.position.longitude = parseFloat(location.position.longitude);\n            });\n            controls = element.getAttribute('data-show-controls');\n            mapOptions.disableDefaultUI = controls !== 'true';\n            mapOptions.mapTypeControl = controls === 'true';\n            new GoogleMap(element, locations, mapOptions);\n        }\n    };\n});\n","Magento_PageBuilder/js/content-type/products/appearance/carousel/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'matchMedia',\n    'Magento_PageBuilder/js/utils/breakpoints',\n    'Magento_PageBuilder/js/events',\n    'slick'\n], function ($, _, mediaCheck, breakpointsUtils, events) {\n    'use strict';\n\n    /**\n     * Build slick\n     *\n     * @param {jQuery} $carouselElement\n     * @param {Object} config\n     */\n    function buildSlick($carouselElement, config) {\n        /**\n         * Prevent each slick slider from being initialized more than once which could throw an error.\n         */\n        if ($carouselElement.hasClass('slick-initialized')) {\n            $carouselElement.slick('unslick');\n        }\n\n        config.slidesToScroll = config.slidesToShow;\n        $carouselElement.slick(config);\n    }\n\n    /**\n     * Initialize slider.\n     *\n     * @param {jQuery} $element\n     * @param {Object} slickConfig\n     * @param {Object} breakpoint\n     */\n    function initSlider($element, slickConfig, breakpoint) {\n        var productCount = $element.find('.product-item').length,\n            $carouselElement = $($element.children()),\n            centerModeClass = 'center-mode',\n            carouselMode = $element.data('carousel-mode'),\n            slidesToShow = breakpoint.options.products[carouselMode] ?\n                breakpoint.options.products[carouselMode].slidesToShow :\n                breakpoint.options.products.default.slidesToShow;\n\n        slickConfig.slidesToShow = parseFloat(slidesToShow);\n\n        if (carouselMode === 'continuous' && productCount > slickConfig.slidesToShow) {\n            $element.addClass(centerModeClass);\n            slickConfig.centerPadding = $element.data('center-padding');\n            slickConfig.centerMode = true;\n        } else {\n            $element.removeClass(centerModeClass);\n            slickConfig.infinite = $element.data('infinite-loop');\n        }\n\n        buildSlick($carouselElement, slickConfig);\n    }\n\n    return function (config, element) {\n        var $element = $(element),\n            $carouselElement = $($element.children()),\n            currentViewport = config.currentViewport,\n            currentBreakpoint = config.breakpoints[currentViewport],\n            slickConfig = {\n                autoplay: $element.data('autoplay'),\n                autoplaySpeed: $element.data('autoplay-speed') || 0,\n                arrows: $element.data('show-arrows'),\n                dots: $element.data('show-dots')\n            };\n\n        _.each(config.breakpoints, function (breakpoint) {\n            mediaCheck({\n                media: breakpointsUtils.buildMedia(breakpoint.conditions),\n\n                /** @inheritdoc */\n                entry: function () {\n                    initSlider($element, slickConfig, breakpoint);\n                }\n            });\n        });\n\n        //initialize slider when content type is added in mobile viewport\n        if (currentViewport === 'mobile') {\n            initSlider($element, slickConfig, currentBreakpoint);\n        }\n\n        // Redraw slide after content type gets redrawn\n        events.on('contentType:redrawAfter', function (args) {\n            if ($carouselElement.closest(args.element).length) {\n                $carouselElement.slick('setPosition');\n            }\n        });\n\n        events.on('stage:viewportChangeAfter', function (args) {\n            var breakpoint = config.breakpoints[args.viewport];\n\n            initSlider($element, slickConfig, breakpoint);\n        });\n    };\n});\n","Magento_PageBuilder/js/content-type/slide/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_PageBuilder/js/widget/show-on-hover',\n    'Magento_PageBuilder/js/widget/video-background'\n], function ($, _, showOnHover, videoBackground) {\n    'use strict';\n\n    return function (config, element) {\n        var videoElement = element[0].querySelector('[data-background-type=video]'),\n            viewportElement = document.createElement('div'),\n            $slider = null;\n\n        showOnHover(config);\n\n        if (videoElement) {\n            $slider = $(element).closest('[data-content-type=slider]');\n            viewportElement.classList.add('jarallax-viewport-element');\n            videoElement.setAttribute('data-element-in-viewport', '.jarallax-viewport-element');\n            videoElement.appendChild(viewportElement);\n            videoBackground(config, videoElement);\n\n            if ($slider.data('afterChangeIsSet')) {\n                return;\n            }\n\n            $slider.on('afterChange init', function () {\n                var videoSlides = $slider[0].querySelectorAll('.jarallax');\n\n                _.each(videoSlides, function (videoSlide) {\n                    videoSlide.jarallax && videoSlide.jarallax.onScroll();\n                });\n            });\n            $slider.data('afterChangeIsSet', true);\n        }\n    };\n});\n","Magento_PageBuilder/js/widget/video-background.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'jarallax',\n    'jarallaxVideo',\n    'vimeoWrapper'\n], function ($) {\n    'use strict';\n\n    return function (config, element) {\n        var $element = $(element),\n            parallaxSpeed = $element.data('enableParallax') !== 1 ? 1 : parseFloat($element.data('parallaxSpeed'));\n\n        if ($element.data('background-type') !== 'video') {\n            return;\n        }\n\n        $element.addClass('jarallax');\n        $element.attr('data-jarallax', '');\n\n        window.jarallax($element[0], {\n            imgSrc: $element.data('videoFallbackSrc'),\n            speed: !isNaN(parallaxSpeed) ? parallaxSpeed : 0.5,\n            videoLoop: $element.data('videoLoop'),\n            videoPlayOnlyVisible: $element.data('videoPlayOnlyVisible'),\n            videoLazyLoading: $element.data('videoLazyLoad'),\n            disableVideo: false,\n            elementInViewport: $element.data('elementInViewport') &&\n                $element[0].querySelector($element.data('elementInViewport'))\n        });\n        $element[0].jarallax.video && $element[0].jarallax.video.on('started', function () {\n            if ($element[0].jarallax.$video) {\n                $element[0].jarallax.$video.style.visibility = 'visible';\n            }\n        });\n    };\n});\n","Magento_PageBuilder/js/widget/show-on-hover.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['jquery'], function ($) {\n    'use strict';\n\n    /**\n     * Show the overlay on hover of specific elements\n     *\n     * @param {JQuery<Element>[]} $elements\n     */\n    function showOverlayOnHover($elements) {\n        $elements.each(function (index, element) {\n            var overlayEl = $(element).find('.pagebuilder-overlay'),\n                overlayColor = overlayEl.attr('data-overlay-color');\n\n            $(element).on('mouseenter', function () {\n                overlayEl.css('background-color', overlayColor);\n            });\n\n            $(element).on('mouseleave', function () {\n                overlayEl.css('background-color', 'transparent');\n            });\n        });\n    }\n\n    /**\n     * Show button on hover of specific elements\n     *\n     * @param {JQuery<Element>[]} $elements\n     * @param {String} buttonClass\n     */\n    function showButtonOnHover($elements, buttonClass) {\n        $elements.each(function (index, element) {\n            var buttonEl = $(element).find(buttonClass);\n\n            $(element).on('mouseenter', function () {\n                buttonEl.css({\n                    'opacity': '1',\n                    'visibility': 'visible'\n                });\n            });\n\n            $(element).on('mouseleave', function () {\n                buttonEl.css({\n                    'opacity': '0',\n                    'visibility': 'hidden'\n                });\n            });\n        });\n    }\n\n    return function (config) {\n\n        var buttonSelector = config.buttonSelector,\n            overlayHoverSelector = 'div[data-content-type=\"%s\"][data-show-overlay=\"%s\"]'\n                .replace('%s', config.dataRole)\n                .replace('%s', config.showOverlay),\n            overlayButtonSelector = 'div[data-content-type=\"%s\"][data-show-button=\"%s\"]'\n                .replace('%s', config.dataRole)\n                .replace('%s', config.showOverlay);\n\n        showOverlayOnHover($(overlayHoverSelector));\n        showButtonOnHover($(overlayButtonSelector), buttonSelector);\n    };\n});\n","Magento_PageBuilder/js/resource/jarallax/jarallax.js":"/*!\n * Jarallax v2.0.3 (https://github.com/nk-o/jarallax)\n * Copyright 2022 nK <https://nkdev.info>\n * Licensed under MIT (https://github.com/nk-o/jarallax/blob/master/LICENSE)\n */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n      typeof define === 'function' && define.amd ? define(factory) :\n          (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.jarallax = factory());\n})(this, (function () { 'use strict';\n\n  function ready(callback) {\n    if ('complete' === document.readyState || 'interactive' === document.readyState) {\n      // Already ready or interactive, execute callback\n      callback();\n    } else {\n      document.addEventListener('DOMContentLoaded', callback, {\n        capture: true,\n        once: true,\n        passive: true\n      });\n    }\n  }\n\n  /* eslint-disable import/no-mutable-exports */\n\n  /* eslint-disable no-restricted-globals */\n  let win;\n\n  if ('undefined' !== typeof window) {\n    win = window;\n  } else if ('undefined' !== typeof global) {\n    win = global;\n  } else if ('undefined' !== typeof self) {\n    win = self;\n  } else {\n    win = {};\n  }\n\n  var global$1 = win;\n\n  const {\n    navigator\n  } = global$1;\n  const isMobile = /*#__PURE__*/ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n  let $deviceHelper;\n  /**\n   * The most popular mobile browsers changes height after page scroll and this generates image jumping.\n   * We can fix it using this workaround with vh units.\n   */\n\n  function getDeviceHeight() {\n    if (!$deviceHelper && document.body) {\n      $deviceHelper = document.createElement('div');\n      $deviceHelper.style.cssText = 'position: fixed; top: -9999px; left: 0; height: 100vh; width: 0;';\n      document.body.appendChild($deviceHelper);\n    }\n\n    return ($deviceHelper ? $deviceHelper.clientHeight : 0) || global$1.innerHeight || document.documentElement.clientHeight;\n  } // Window height data\n\n\n  let wndH;\n\n  function updateWndVars() {\n    if (isMobile) {\n      wndH = getDeviceHeight();\n    } else {\n      wndH = global$1.innerHeight || document.documentElement.clientHeight;\n    }\n  }\n\n  updateWndVars();\n  global$1.addEventListener('resize', updateWndVars);\n  global$1.addEventListener('orientationchange', updateWndVars);\n  global$1.addEventListener('load', updateWndVars);\n  ready(() => {\n    updateWndVars();\n  }); // list with all jarallax instances\n  // need to render all in one scroll/resize event\n\n  const jarallaxList = []; // get all parents of the element.\n\n  function getParents(elem) {\n    const parents = [];\n\n    while (null !== elem.parentElement) {\n      elem = elem.parentElement;\n\n      if (1 === elem.nodeType) {\n        parents.push(elem);\n      }\n    }\n\n    return parents;\n  }\n\n  function updateParallax() {\n    if (!jarallaxList.length) {\n      return;\n    }\n\n    jarallaxList.forEach((data, k) => {\n      const {\n        instance,\n        oldData\n      } = data;\n      const clientRect = instance.$item.getBoundingClientRect();\n      const newData = {\n        width: clientRect.width,\n        height: clientRect.height,\n        top: clientRect.top,\n        bottom: clientRect.bottom,\n        wndW: global$1.innerWidth,\n        wndH\n      };\n      const isResized = !oldData || oldData.wndW !== newData.wndW || oldData.wndH !== newData.wndH || oldData.width !== newData.width || oldData.height !== newData.height;\n      const isScrolled = isResized || !oldData || oldData.top !== newData.top || oldData.bottom !== newData.bottom;\n      jarallaxList[k].oldData = newData;\n\n      if (isResized) {\n        instance.onResize();\n      }\n\n      if (isScrolled) {\n        instance.onScroll();\n      }\n    });\n    global$1.requestAnimationFrame(updateParallax);\n  }\n\n  let instanceID = 0; // Jarallax class\n\n  class Jarallax {\n    constructor(item, userOptions) {\n      const self = this;\n      self.instanceID = instanceID;\n      instanceID += 1;\n      self.$item = item;\n      self.defaults = {\n        type: 'scroll',\n        // type of parallax: scroll, scale, opacity, scale-opacity, scroll-opacity\n        speed: 0.5,\n        // supported value from -1 to 2\n        imgSrc: null,\n        imgElement: '.jarallax-img',\n        imgSize: 'cover',\n        imgPosition: '50% 50%',\n        imgRepeat: 'no-repeat',\n        // supported only for background, not for <img> tag\n        keepImg: false,\n        // keep <img> tag in it's default place\n        elementInViewport: null,\n        zIndex: -100,\n        disableParallax: false,\n        disableVideo: false,\n        // video\n        videoSrc: null,\n        videoStartTime: 0,\n        videoEndTime: 0,\n        videoVolume: 0,\n        videoLoop: true,\n        videoPlayOnlyVisible: true,\n        videoLazyLoading: true,\n        // events\n        onScroll: null,\n        // function(calculations) {}\n        onInit: null,\n        // function() {}\n        onDestroy: null,\n        // function() {}\n        onCoverImage: null // function() {}\n\n      }; // prepare data-options\n\n      const dataOptions = self.$item.dataset || {};\n      const pureDataOptions = {};\n      Object.keys(dataOptions).forEach(key => {\n        const loweCaseOption = key.substr(0, 1).toLowerCase() + key.substr(1);\n\n        if (loweCaseOption && 'undefined' !== typeof self.defaults[loweCaseOption]) {\n          pureDataOptions[loweCaseOption] = dataOptions[key];\n        }\n      });\n      self.options = self.extend({}, self.defaults, pureDataOptions, userOptions);\n      self.pureOptions = self.extend({}, self.options); // prepare 'true' and 'false' strings to boolean\n\n      Object.keys(self.options).forEach(key => {\n        if ('true' === self.options[key]) {\n          self.options[key] = true;\n        } else if ('false' === self.options[key]) {\n          self.options[key] = false;\n        }\n      }); // fix speed option [-1.0, 2.0]\n\n      self.options.speed = Math.min(2, Math.max(-1, parseFloat(self.options.speed))); // prepare disableParallax callback\n\n      if ('string' === typeof self.options.disableParallax) {\n        self.options.disableParallax = new RegExp(self.options.disableParallax);\n      }\n\n      if (self.options.disableParallax instanceof RegExp) {\n        const disableParallaxRegexp = self.options.disableParallax;\n\n        self.options.disableParallax = () => disableParallaxRegexp.test(navigator.userAgent);\n      }\n\n      if ('function' !== typeof self.options.disableParallax) {\n        self.options.disableParallax = () => false;\n      } // prepare disableVideo callback\n\n\n      if ('string' === typeof self.options.disableVideo) {\n        self.options.disableVideo = new RegExp(self.options.disableVideo);\n      }\n\n      if (self.options.disableVideo instanceof RegExp) {\n        const disableVideoRegexp = self.options.disableVideo;\n\n        self.options.disableVideo = () => disableVideoRegexp.test(navigator.userAgent);\n      }\n\n      if ('function' !== typeof self.options.disableVideo) {\n        self.options.disableVideo = () => false;\n      } // custom element to check if parallax in viewport\n\n\n      let elementInVP = self.options.elementInViewport; // get first item from array\n\n      if (elementInVP && 'object' === typeof elementInVP && 'undefined' !== typeof elementInVP.length) {\n        [elementInVP] = elementInVP;\n      } // check if dom element\n\n\n      if (!(elementInVP instanceof Element)) {\n        elementInVP = null;\n      }\n\n      self.options.elementInViewport = elementInVP;\n      self.image = {\n        src: self.options.imgSrc || null,\n        $container: null,\n        useImgTag: false,\n        // 1. Position fixed is needed for the most of browsers because absolute position have glitches\n        // 2. On MacOS with smooth scroll there is a huge lags with absolute position - https://github.com/nk-o/jarallax/issues/75\n        // 3. Previously used 'absolute' for mobile devices. But we re-tested on iPhone 12 and 'fixed' position is working better, then 'absolute', so for now position is always 'fixed'\n        position: 'fixed'\n      };\n\n      if (self.initImg() && self.canInitParallax()) {\n        self.init();\n      }\n    } // add styles to element\n    // eslint-disable-next-line class-methods-use-this\n\n\n    css(el, styles) {\n      if ('string' === typeof styles) {\n        return global$1.getComputedStyle(el).getPropertyValue(styles);\n      }\n\n      Object.keys(styles).forEach(key => {\n        el.style[key] = styles[key];\n      });\n      return el;\n    } // Extend like jQuery.extend\n    // eslint-disable-next-line class-methods-use-this\n\n\n    extend(out, ...args) {\n      out = out || {};\n      Object.keys(args).forEach(i => {\n        if (!args[i]) {\n          return;\n        }\n\n        Object.keys(args[i]).forEach(key => {\n          out[key] = args[i][key];\n        });\n      });\n      return out;\n    } // get window size and scroll position. Useful for extensions\n    // eslint-disable-next-line class-methods-use-this\n\n\n    getWindowData() {\n      return {\n        width: global$1.innerWidth || document.documentElement.clientWidth,\n        height: wndH,\n        y: document.documentElement.scrollTop\n      };\n    } // Jarallax functions\n\n\n    initImg() {\n      const self = this; // find image element\n\n      let $imgElement = self.options.imgElement;\n\n      if ($imgElement && 'string' === typeof $imgElement) {\n        $imgElement = self.$item.querySelector($imgElement);\n      } // check if dom element\n\n\n      if (!($imgElement instanceof Element)) {\n        if (self.options.imgSrc) {\n          $imgElement = new Image();\n          $imgElement.src = self.options.imgSrc;\n        } else {\n          $imgElement = null;\n        }\n      }\n\n      if ($imgElement) {\n        if (self.options.keepImg) {\n          self.image.$item = $imgElement.cloneNode(true);\n        } else {\n          self.image.$item = $imgElement;\n          self.image.$itemParent = $imgElement.parentNode;\n        }\n\n        self.image.useImgTag = true;\n      } // true if there is img tag\n\n\n      if (self.image.$item) {\n        return true;\n      } // get image src\n\n\n      if (null === self.image.src) {\n        self.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n        self.image.bgImage = self.css(self.$item, 'background-image');\n      }\n\n      return !(!self.image.bgImage || 'none' === self.image.bgImage);\n    }\n\n    canInitParallax() {\n      return !this.options.disableParallax();\n    }\n\n    init() {\n      const self = this;\n      const containerStyles = {\n        position: 'absolute',\n        top: 0,\n        left: 0,\n        width: '100%',\n        height: '100%',\n        overflow: 'hidden'\n      };\n      let imageStyles = {\n        pointerEvents: 'none',\n        transformStyle: 'preserve-3d',\n        backfaceVisibility: 'hidden',\n        willChange: 'transform,opacity'\n      };\n\n      if (!self.options.keepImg) {\n        // save default user styles\n        const curStyle = self.$item.getAttribute('style');\n\n        if (curStyle) {\n          self.$item.setAttribute('data-jarallax-original-styles', curStyle);\n        }\n\n        if (self.image.useImgTag) {\n          const curImgStyle = self.image.$item.getAttribute('style');\n\n          if (curImgStyle) {\n            self.image.$item.setAttribute('data-jarallax-original-styles', curImgStyle);\n          }\n        }\n      } // set relative position and z-index to the parent\n\n\n      if ('static' === self.css(self.$item, 'position')) {\n        self.css(self.$item, {\n          position: 'relative'\n        });\n      }\n\n      if ('auto' === self.css(self.$item, 'z-index')) {\n        self.css(self.$item, {\n          zIndex: 0\n        });\n      } // container for parallax image\n\n\n      self.image.$container = document.createElement('div');\n      self.css(self.image.$container, containerStyles);\n      self.css(self.image.$container, {\n        'z-index': self.options.zIndex\n      }); // it will remove some image overlapping\n      // overlapping occur due to an image position fixed inside absolute position element\n      // needed only when background in fixed position\n\n      if ('fixed' === this.image.position) {\n        self.css(self.image.$container, {\n          '-webkit-clip-path': 'polygon(0 0, 100% 0, 100% 100%, 0 100%)',\n          'clip-path': 'polygon(0 0, 100% 0, 100% 100%, 0 100%)'\n        });\n      }\n\n      self.image.$container.setAttribute('id', `jarallax-container-${self.instanceID}`);\n      self.$item.appendChild(self.image.$container); // use img tag\n\n      if (self.image.useImgTag) {\n        imageStyles = self.extend({\n          'object-fit': self.options.imgSize,\n          'object-position': self.options.imgPosition,\n          'max-width': 'none'\n        }, containerStyles, imageStyles); // use div with background image\n      } else {\n        self.image.$item = document.createElement('div');\n\n        if (self.image.src) {\n          imageStyles = self.extend({\n            'background-position': self.options.imgPosition,\n            'background-size': self.options.imgSize,\n            'background-repeat': self.options.imgRepeat,\n            'background-image': self.image.bgImage || `url(\"${self.image.src}\")`\n          }, containerStyles, imageStyles);\n        }\n      }\n\n      if ('opacity' === self.options.type || 'scale' === self.options.type || 'scale-opacity' === self.options.type || 1 === self.options.speed) {\n        self.image.position = 'absolute';\n      } // 1. Check if one of parents have transform style (without this check, scroll transform will be inverted if used parallax with position fixed)\n      //    discussion - https://github.com/nk-o/jarallax/issues/9\n      // 2. Check if parents have overflow scroll\n\n\n      if ('fixed' === self.image.position) {\n        const $parents = getParents(self.$item).filter(el => {\n          const styles = global$1.getComputedStyle(el);\n          const parentTransform = styles['-webkit-transform'] || styles['-moz-transform'] || styles.transform;\n          const overflowRegex = /(auto|scroll)/;\n          return parentTransform && 'none' !== parentTransform || overflowRegex.test(styles.overflow + styles['overflow-y'] + styles['overflow-x']);\n        });\n        self.image.position = $parents.length ? 'absolute' : 'fixed';\n      } // add position to parallax block\n\n\n      imageStyles.position = self.image.position; // insert parallax image\n\n      self.css(self.image.$item, imageStyles);\n      self.image.$container.appendChild(self.image.$item); // set initial position and size\n\n      self.onResize();\n      self.onScroll(true); // call onInit event\n\n      if (self.options.onInit) {\n        self.options.onInit.call(self);\n      } // remove default user background\n\n\n      if ('none' !== self.css(self.$item, 'background-image')) {\n        self.css(self.$item, {\n          'background-image': 'none'\n        });\n      }\n\n      self.addToParallaxList();\n    } // add to parallax instances list\n\n\n    addToParallaxList() {\n      jarallaxList.push({\n        instance: this\n      });\n\n      if (1 === jarallaxList.length) {\n        global$1.requestAnimationFrame(updateParallax);\n      }\n    } // remove from parallax instances list\n\n\n    removeFromParallaxList() {\n      const self = this;\n      jarallaxList.forEach((data, key) => {\n        if (data.instance.instanceID === self.instanceID) {\n          jarallaxList.splice(key, 1);\n        }\n      });\n    }\n\n    destroy() {\n      const self = this;\n      self.removeFromParallaxList(); // return styles on container as before jarallax init\n\n      const originalStylesTag = self.$item.getAttribute('data-jarallax-original-styles');\n      self.$item.removeAttribute('data-jarallax-original-styles'); // null occurs if there is no style tag before jarallax init\n\n      if (!originalStylesTag) {\n        self.$item.removeAttribute('style');\n      } else {\n        self.$item.setAttribute('style', originalStylesTag);\n      }\n\n      if (self.image.useImgTag) {\n        // return styles on img tag as before jarallax init\n        const originalStylesImgTag = self.image.$item.getAttribute('data-jarallax-original-styles');\n        self.image.$item.removeAttribute('data-jarallax-original-styles'); // null occurs if there is no style tag before jarallax init\n\n        if (!originalStylesImgTag) {\n          self.image.$item.removeAttribute('style');\n        } else {\n          self.image.$item.setAttribute('style', originalStylesTag);\n        } // move img tag to its default position\n\n\n        if (self.image.$itemParent) {\n          self.image.$itemParent.appendChild(self.image.$item);\n        }\n      } // remove additional dom elements\n\n\n      if (self.image.$container) {\n        self.image.$container.parentNode.removeChild(self.image.$container);\n      } // call onDestroy event\n\n\n      if (self.options.onDestroy) {\n        self.options.onDestroy.call(self);\n      } // delete jarallax from item\n\n\n      delete self.$item.jarallax;\n    } // Fallback for removed function.\n    // Does nothing now.\n    // eslint-disable-next-line class-methods-use-this\n\n\n    clipContainer() {}\n\n    coverImage() {\n      const self = this;\n      const rect = self.image.$container.getBoundingClientRect();\n      const contH = rect.height;\n      const {\n        speed\n      } = self.options;\n      const isScroll = 'scroll' === self.options.type || 'scroll-opacity' === self.options.type;\n      let scrollDist = 0;\n      let resultH = contH;\n      let resultMT = 0; // scroll parallax\n\n      if (isScroll) {\n        // scroll distance and height for image\n        if (0 > speed) {\n          scrollDist = speed * Math.max(contH, wndH);\n\n          if (wndH < contH) {\n            scrollDist -= speed * (contH - wndH);\n          }\n        } else {\n          scrollDist = speed * (contH + wndH);\n        } // size for scroll parallax\n\n\n        if (1 < speed) {\n          resultH = Math.abs(scrollDist - wndH);\n        } else if (0 > speed) {\n          resultH = scrollDist / speed + Math.abs(scrollDist);\n        } else {\n          resultH += (wndH - contH) * (1 - speed);\n        }\n\n        scrollDist /= 2;\n      } // store scroll distance\n\n\n      self.parallaxScrollDistance = scrollDist; // vertical center\n\n      if (isScroll) {\n        resultMT = (wndH - resultH) / 2;\n      } else {\n        resultMT = (contH - resultH) / 2;\n      } // apply result to item\n\n\n      self.css(self.image.$item, {\n        height: `${resultH}px`,\n        marginTop: `${resultMT}px`,\n        left: 'fixed' === self.image.position ? `${rect.left}px` : '0',\n        width: `${rect.width}px`\n      }); // call onCoverImage event\n\n      if (self.options.onCoverImage) {\n        self.options.onCoverImage.call(self);\n      } // return some useful data. Used in the video cover function\n\n\n      return {\n        image: {\n          height: resultH,\n          marginTop: resultMT\n        },\n        container: rect\n      };\n    }\n\n    isVisible() {\n      return this.isElementInViewport || false;\n    }\n\n    onScroll(force) {\n      const self = this;\n      const rect = self.$item.getBoundingClientRect();\n      const contT = rect.top;\n      const contH = rect.height;\n      const styles = {}; // check if in viewport\n\n      let viewportRect = rect;\n\n      if (self.options.elementInViewport) {\n        viewportRect = self.options.elementInViewport.getBoundingClientRect();\n      }\n\n      self.isElementInViewport = 0 <= viewportRect.bottom && 0 <= viewportRect.right && viewportRect.top <= wndH && viewportRect.left <= global$1.innerWidth; // stop calculations if item is not in viewport\n\n      if (force ? false : !self.isElementInViewport) {\n        return;\n      } // calculate parallax helping variables\n\n\n      const beforeTop = Math.max(0, contT);\n      const beforeTopEnd = Math.max(0, contH + contT);\n      const afterTop = Math.max(0, -contT);\n      const beforeBottom = Math.max(0, contT + contH - wndH);\n      const beforeBottomEnd = Math.max(0, contH - (contT + contH - wndH));\n      const afterBottom = Math.max(0, -contT + wndH - contH);\n      const fromViewportCenter = 1 - 2 * ((wndH - contT) / (wndH + contH)); // calculate on how percent of section is visible\n\n      let visiblePercent = 1;\n\n      if (contH < wndH) {\n        visiblePercent = 1 - (afterTop || beforeBottom) / contH;\n      } else if (beforeTopEnd <= wndH) {\n        visiblePercent = beforeTopEnd / wndH;\n      } else if (beforeBottomEnd <= wndH) {\n        visiblePercent = beforeBottomEnd / wndH;\n      } // opacity\n\n\n      if ('opacity' === self.options.type || 'scale-opacity' === self.options.type || 'scroll-opacity' === self.options.type) {\n        styles.transform = 'translate3d(0,0,0)';\n        styles.opacity = visiblePercent;\n      } // scale\n\n\n      if ('scale' === self.options.type || 'scale-opacity' === self.options.type) {\n        let scale = 1;\n\n        if (0 > self.options.speed) {\n          scale -= self.options.speed * visiblePercent;\n        } else {\n          scale += self.options.speed * (1 - visiblePercent);\n        }\n\n        styles.transform = `scale(${scale}) translate3d(0,0,0)`;\n      } // scroll\n\n\n      if ('scroll' === self.options.type || 'scroll-opacity' === self.options.type) {\n        let positionY = self.parallaxScrollDistance * fromViewportCenter; // fix if parallax block in absolute position\n\n        if ('absolute' === self.image.position) {\n          positionY -= contT;\n        }\n\n        styles.transform = `translate3d(0,${positionY}px,0)`;\n      }\n\n      self.css(self.image.$item, styles); // call onScroll event\n\n      if (self.options.onScroll) {\n        self.options.onScroll.call(self, {\n          section: rect,\n          beforeTop,\n          beforeTopEnd,\n          afterTop,\n          beforeBottom,\n          beforeBottomEnd,\n          afterBottom,\n          visiblePercent,\n          fromViewportCenter\n        });\n      }\n    }\n\n    onResize() {\n      this.coverImage();\n    }\n\n  } // global definition\n\n\n  const jarallax = function (items, options, ...args) {\n    // check for dom element\n    // thanks: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object\n    if ('object' === typeof HTMLElement ? items instanceof HTMLElement : items && 'object' === typeof items && null !== items && 1 === items.nodeType && 'string' === typeof items.nodeName) {\n      items = [items];\n    }\n\n    const len = items.length;\n    let k = 0;\n    let ret;\n\n    for (k; k < len; k += 1) {\n      if ('object' === typeof options || 'undefined' === typeof options) {\n        if (!items[k].jarallax) {\n          items[k].jarallax = new Jarallax(items[k], options);\n        }\n      } else if (items[k].jarallax) {\n        // eslint-disable-next-line prefer-spread\n        ret = items[k].jarallax[options].apply(items[k].jarallax, args);\n      }\n\n      if ('undefined' !== typeof ret) {\n        return ret;\n      }\n    }\n\n    return items;\n  };\n\n  jarallax.constructor = Jarallax;\n\n  const $ = global$1.jQuery; // jQuery support\n\n  if ('undefined' !== typeof $) {\n    const $Plugin = function (...args) {\n      Array.prototype.unshift.call(args, this);\n      const res = jarallax.apply(global$1, args);\n      return 'object' !== typeof res ? res : this;\n    };\n\n    $Plugin.constructor = jarallax.constructor; // no conflict\n\n    const old$Plugin = $.fn.jarallax;\n    $.fn.jarallax = $Plugin;\n\n    $.fn.jarallax.noConflict = function () {\n      $.fn.jarallax = old$Plugin;\n      return this;\n    };\n  } // data-jarallax initialization\n\n\n  ready(() => {\n    jarallax(document.querySelectorAll('[data-jarallax]'));\n  });\n\n  return jarallax;\n\n}));\n//# sourceMappingURL=jarallax.js.map\n","Magento_PageBuilder/js/resource/jarallax/jarallax-video.js":"/*!\n * Video Extension for Jarallax v2.0.3 (https://github.com/nk-o/jarallax)\n * Copyright 2022 nK <https://nkdev.info>\n * Licensed under MIT (https://github.com/nk-o/jarallax/blob/master/LICENSE)\n */\n\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n      typeof define === 'function' && define.amd ? define(factory) :\n          (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.jarallaxVideo = factory());\n})(this, (function () { 'use strict';\n\n  /*!\n   * Name    : Video Worker\n   * Version : 2.0.0\n   * Author  : nK <https://nkdev.info>\n   * GitHub  : https://github.com/nk-o/video-worker\n   */\n\n  /* eslint-disable import/no-mutable-exports */\n\n  /* eslint-disable no-restricted-globals */\n  let win$1;\n\n  if (typeof window !== 'undefined') {\n    win$1 = window;\n  } else if (typeof global !== 'undefined') {\n    win$1 = global;\n  } else if (typeof self !== 'undefined') {\n    win$1 = self;\n  } else {\n    win$1 = {};\n  }\n\n  var global$1$1 = win$1; // Deferred\n  // thanks http://stackoverflow.com/questions/18096715/implement-deferred-object-without-using-jquery\n\n  function Deferred() {\n    this.doneCallbacks = [];\n    this.failCallbacks = [];\n  }\n\n  Deferred.prototype = {\n    execute(list, args) {\n      let i = list.length; // eslint-disable-next-line no-param-reassign\n\n      args = Array.prototype.slice.call(args);\n\n      while (i) {\n        i -= 1;\n        list[i].apply(null, args);\n      }\n    },\n\n    resolve(...args) {\n      this.execute(this.doneCallbacks, args);\n    },\n\n    reject(...args) {\n      this.execute(this.failCallbacks, args);\n    },\n\n    done(callback) {\n      this.doneCallbacks.push(callback);\n    },\n\n    fail(callback) {\n      this.failCallbacks.push(callback);\n    }\n\n  };\n  let ID = 0;\n  let YoutubeAPIadded = 0;\n  let VimeoAPIadded = 0;\n  let loadingYoutubePlayer = 0;\n  let loadingVimeoPlayer = 0;\n  const loadingYoutubeDefer = /*#__PURE__*/new Deferred();\n  const loadingVimeoDefer = /*#__PURE__*/new Deferred();\n\n  class VideoWorker {\n    constructor(url, options) {\n      const self = this;\n      self.url = url;\n      self.options_default = {\n        autoplay: false,\n        loop: false,\n        mute: false,\n        volume: 100,\n        showControls: true,\n        accessibilityHidden: false,\n        // start / end video time in seconds\n        startTime: 0,\n        endTime: 0\n      };\n      self.options = self.extend({}, self.options_default, options); // Fix wrong option name.\n      // Thanks to https://github.com/nk-o/video-worker/issues/13.\n\n      if (typeof self.options.showContols !== 'undefined') {\n        self.options.showControls = self.options.showContols;\n        delete self.options.showContols;\n      } // check URL\n\n\n      self.videoID = self.parseURL(url); // init\n\n      if (self.videoID) {\n        self.ID = ID;\n        ID += 1;\n        self.loadAPI();\n        self.init();\n      }\n    } // Extend like jQuery.extend\n    // eslint-disable-next-line class-methods-use-this\n\n\n    extend(...args) {\n      const out = args[0] || {};\n      Object.keys(args).forEach(i => {\n        if (!args[i]) {\n          return;\n        }\n\n        Object.keys(args[i]).forEach(key => {\n          out[key] = args[i][key];\n        });\n      });\n      return out;\n    }\n\n    parseURL(url) {\n      // parse youtube ID\n      function getYoutubeID(ytUrl) {\n        // eslint-disable-next-line no-useless-escape\n        const regExp = /.*(?:youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=)([^#\\&\\?]*).*/;\n        const match = ytUrl.match(regExp);\n        return match && match[1].length === 11 ? match[1] : false;\n      } // parse vimeo ID\n\n\n      function getVimeoID(vmUrl) {\n        // eslint-disable-next-line no-useless-escape\n        const regExp = /https?:\\/\\/(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/([^/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|video\\/|)(\\d+)(?:$|\\/|\\?)/;\n        const match = vmUrl.match(regExp);\n        return match && match[3] ? match[3] : false;\n      } // parse local string\n\n\n      function getLocalVideos(locUrl) {\n        // eslint-disable-next-line no-useless-escape\n        const videoFormats = locUrl.split(/,(?=mp4\\:|webm\\:|ogv\\:|ogg\\:)/);\n        const result = {};\n        let ready = 0;\n        videoFormats.forEach(val => {\n          // eslint-disable-next-line no-useless-escape\n          const match = val.match(/^(mp4|webm|ogv|ogg)\\:(.*)/);\n\n          if (match && match[1] && match[2]) {\n            // eslint-disable-next-line prefer-destructuring\n            result[match[1] === 'ogv' ? 'ogg' : match[1]] = match[2];\n            ready = 1;\n          }\n        });\n        return ready ? result : false;\n      }\n\n      const Youtube = getYoutubeID(url);\n      const Vimeo = getVimeoID(url);\n      const Local = getLocalVideos(url);\n\n      if (Youtube) {\n        this.type = 'youtube';\n        return Youtube;\n      }\n\n      if (Vimeo) {\n        this.type = 'vimeo';\n        return Vimeo;\n      }\n\n      if (Local) {\n        this.type = 'local';\n        return Local;\n      }\n\n      return false;\n    }\n\n    isValid() {\n      return !!this.videoID;\n    } // events\n\n\n    on(name, callback) {\n      this.userEventsList = this.userEventsList || []; // add new callback in events list\n\n      (this.userEventsList[name] || (this.userEventsList[name] = [])).push(callback);\n    }\n\n    off(name, callback) {\n      if (!this.userEventsList || !this.userEventsList[name]) {\n        return;\n      }\n\n      if (!callback) {\n        delete this.userEventsList[name];\n      } else {\n        this.userEventsList[name].forEach((val, key) => {\n          if (val === callback) {\n            this.userEventsList[name][key] = false;\n          }\n        });\n      }\n    }\n\n    fire(name, ...args) {\n      if (this.userEventsList && typeof this.userEventsList[name] !== 'undefined') {\n        this.userEventsList[name].forEach(val => {\n          // call with all arguments\n          if (val) {\n            val.apply(this, args);\n          }\n        });\n      }\n    }\n\n    play(start) {\n      const self = this;\n\n      if (!self.player) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.playVideo) {\n        if (typeof start !== 'undefined') {\n          self.player.seekTo(start || 0);\n        }\n\n        if (global$1$1.YT.PlayerState.PLAYING !== self.player.getPlayerState()) {\n          self.player.playVideo();\n        }\n      }\n\n      if (self.type === 'vimeo') {\n        if (typeof start !== 'undefined') {\n          self.player.setCurrentTime(start);\n        }\n\n        self.player.getPaused().then(paused => {\n          if (paused) {\n            self.player.play();\n          }\n        });\n      }\n\n      if (self.type === 'local') {\n        if (typeof start !== 'undefined') {\n          self.player.currentTime = start;\n        }\n\n        if (self.player.paused) {\n          self.player.play();\n        }\n      }\n    }\n\n    pause() {\n      const self = this;\n\n      if (!self.player) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.pauseVideo) {\n        if (global$1$1.YT.PlayerState.PLAYING === self.player.getPlayerState()) {\n          self.player.pauseVideo();\n        }\n      }\n\n      if (self.type === 'vimeo') {\n        self.player.getPaused().then(paused => {\n          if (!paused) {\n            self.player.pause();\n          }\n        });\n      }\n\n      if (self.type === 'local') {\n        if (!self.player.paused) {\n          self.player.pause();\n        }\n      }\n    }\n\n    mute() {\n      const self = this;\n\n      if (!self.player) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.mute) {\n        self.player.mute();\n      }\n\n      if (self.type === 'vimeo' && self.player.setVolume) {\n        self.player.setVolume(0);\n      }\n\n      if (self.type === 'local') {\n        self.$video.muted = true;\n      }\n    }\n\n    unmute() {\n      const self = this;\n\n      if (!self.player) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.mute) {\n        self.player.unMute();\n      }\n\n      if (self.type === 'vimeo' && self.player.setVolume) {\n        self.player.setVolume(self.options.volume);\n      }\n\n      if (self.type === 'local') {\n        self.$video.muted = false;\n      }\n    }\n\n    setVolume(volume = false) {\n      const self = this;\n\n      if (!self.player || !volume) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.setVolume) {\n        self.player.setVolume(volume);\n      }\n\n      if (self.type === 'vimeo' && self.player.setVolume) {\n        self.player.setVolume(volume);\n      }\n\n      if (self.type === 'local') {\n        self.$video.volume = volume / 100;\n      }\n    }\n\n    getVolume(callback) {\n      const self = this;\n\n      if (!self.player) {\n        callback(false);\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.getVolume) {\n        callback(self.player.getVolume());\n      }\n\n      if (self.type === 'vimeo' && self.player.getVolume) {\n        self.player.getVolume().then(volume => {\n          callback(volume);\n        });\n      }\n\n      if (self.type === 'local') {\n        callback(self.$video.volume * 100);\n      }\n    }\n\n    getMuted(callback) {\n      const self = this;\n\n      if (!self.player) {\n        callback(null);\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.isMuted) {\n        callback(self.player.isMuted());\n      }\n\n      if (self.type === 'vimeo' && self.player.getVolume) {\n        self.player.getVolume().then(volume => {\n          callback(!!volume);\n        });\n      }\n\n      if (self.type === 'local') {\n        callback(self.$video.muted);\n      }\n    }\n\n    getImageURL(callback) {\n      const self = this;\n\n      if (self.videoImage) {\n        callback(self.videoImage);\n        return;\n      }\n\n      if (self.type === 'youtube') {\n        const availableSizes = ['maxresdefault', 'sddefault', 'hqdefault', '0'];\n        let step = 0;\n        const tempImg = new Image();\n\n        tempImg.onload = function () {\n          // if no thumbnail, youtube add their own image with width = 120px\n          if ((this.naturalWidth || this.width) !== 120 || step === availableSizes.length - 1) {\n            // ok\n            self.videoImage = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n            callback(self.videoImage);\n          } else {\n            // try another size\n            step += 1;\n            this.src = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n          }\n        };\n\n        tempImg.src = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n      }\n\n      if (self.type === 'vimeo') {\n        let request = new XMLHttpRequest(); // https://vimeo.com/api/oembed.json?url=https://vimeo.com/235212527\n\n        request.open('GET', `https://vimeo.com/api/oembed.json?url=${self.url}`, true);\n\n        request.onreadystatechange = function () {\n          if (this.readyState === 4) {\n            if (this.status >= 200 && this.status < 400) {\n              // Success!\n              const response = JSON.parse(this.responseText);\n\n              if (response.thumbnail_url) {\n                self.videoImage = response.thumbnail_url;\n                callback(self.videoImage);\n              }\n            }\n          }\n        };\n\n        request.send();\n        request = null;\n      }\n    } // fallback to the old version.\n\n\n    getIframe(callback) {\n      this.getVideo(callback);\n    }\n\n    getVideo(callback) {\n      const self = this; // return generated video block\n\n      if (self.$video) {\n        callback(self.$video);\n        return;\n      } // generate new video block\n\n\n      self.onAPIready(() => {\n        let hiddenDiv;\n\n        if (!self.$video) {\n          hiddenDiv = document.createElement('div');\n          hiddenDiv.style.display = 'none';\n        } // Youtube\n\n\n        if (self.type === 'youtube') {\n          self.playerOptions = {\n            // GDPR Compliance.\n            host: 'https://www.youtube-nocookie.com',\n            videoId: self.videoID,\n            playerVars: {\n              autohide: 1,\n              rel: 0,\n              autoplay: 0,\n              // autoplay enable on mobile devices\n              playsinline: 1\n            }\n          }; // hide controls\n\n          if (!self.options.showControls) {\n            self.playerOptions.playerVars.iv_load_policy = 3;\n            self.playerOptions.playerVars.modestbranding = 1;\n            self.playerOptions.playerVars.controls = 0;\n            self.playerOptions.playerVars.showinfo = 0;\n            self.playerOptions.playerVars.disablekb = 1;\n          } // events\n\n\n          let ytStarted;\n          let ytProgressInterval;\n          self.playerOptions.events = {\n            onReady(e) {\n              // mute\n              if (self.options.mute) {\n                e.target.mute();\n              } else if (self.options.volume) {\n                e.target.setVolume(self.options.volume);\n              } // autoplay\n\n\n              if (self.options.autoplay) {\n                self.play(self.options.startTime);\n              }\n\n              self.fire('ready', e); // For seamless loops, set the endTime to 0.1 seconds less than the video's duration\n              // https://github.com/nk-o/video-worker/issues/2\n\n              if (self.options.loop && !self.options.endTime) {\n                const secondsOffset = 0.1;\n                self.options.endTime = self.player.getDuration() - secondsOffset;\n              } // volumechange\n\n\n              setInterval(() => {\n                self.getVolume(volume => {\n                  if (self.options.volume !== volume) {\n                    self.options.volume = volume;\n                    self.fire('volumechange', e);\n                  }\n                });\n              }, 150);\n            },\n\n            onStateChange(e) {\n              // loop\n              if (self.options.loop && e.data === global$1$1.YT.PlayerState.ENDED) {\n                self.play(self.options.startTime);\n              }\n\n              if (!ytStarted && e.data === global$1$1.YT.PlayerState.PLAYING) {\n                ytStarted = 1;\n                self.fire('started', e);\n              }\n\n              if (e.data === global$1$1.YT.PlayerState.PLAYING) {\n                self.fire('play', e);\n              }\n\n              if (e.data === global$1$1.YT.PlayerState.PAUSED) {\n                self.fire('pause', e);\n              }\n\n              if (e.data === global$1$1.YT.PlayerState.ENDED) {\n                self.fire('ended', e);\n              } // progress check\n\n\n              if (e.data === global$1$1.YT.PlayerState.PLAYING) {\n                ytProgressInterval = setInterval(() => {\n                  self.fire('timeupdate', e); // check for end of video and play again or stop\n\n                  if (self.options.endTime && self.player.getCurrentTime() >= self.options.endTime) {\n                    if (self.options.loop) {\n                      self.play(self.options.startTime);\n                    } else {\n                      self.pause();\n                    }\n                  }\n                }, 150);\n              } else {\n                clearInterval(ytProgressInterval);\n              }\n            },\n\n            onError(e) {\n              self.fire('error', e);\n            }\n\n          };\n          const firstInit = !self.$video;\n\n          if (firstInit) {\n            const div = document.createElement('div');\n            div.setAttribute('id', self.playerID);\n            hiddenDiv.appendChild(div);\n            document.body.appendChild(hiddenDiv);\n          }\n\n          self.player = self.player || new global$1$1.YT.Player(self.playerID, self.playerOptions);\n\n          if (firstInit) {\n            self.$video = document.getElementById(self.playerID); // add accessibility attributes\n\n            if (self.options.accessibilityHidden) {\n              self.$video.setAttribute('tabindex', '-1');\n              self.$video.setAttribute('aria-hidden', 'true');\n            } // get video width and height\n\n\n            self.videoWidth = parseInt(self.$video.getAttribute('width'), 10) || 1280;\n            self.videoHeight = parseInt(self.$video.getAttribute('height'), 10) || 720;\n          }\n        } // Vimeo\n\n\n        if (self.type === 'vimeo') {\n          self.playerOptions = {\n            // GDPR Compliance.\n            dnt: 1,\n            id: self.videoID,\n            autopause: 0,\n            transparent: 0,\n            autoplay: self.options.autoplay ? 1 : 0,\n            loop: self.options.loop ? 1 : 0,\n            muted: self.options.mute ? 1 : 0\n          };\n\n          if (self.options.volume) {\n            self.playerOptions.volume = self.options.volume;\n          } // hide controls\n\n\n          if (!self.options.showControls) {\n            self.playerOptions.badge = 0;\n            self.playerOptions.byline = 0;\n            self.playerOptions.portrait = 0;\n            self.playerOptions.title = 0;\n            self.playerOptions.background = 1;\n          }\n\n          if (!self.$video) {\n            let playerOptionsString = '';\n            Object.keys(self.playerOptions).forEach(key => {\n              if (playerOptionsString !== '') {\n                playerOptionsString += '&';\n              }\n\n              playerOptionsString += `${key}=${encodeURIComponent(self.playerOptions[key])}`;\n            }); // we need to create iframe manually because when we create it using API\n            // js events won't triggers after iframe moved to another place\n\n            self.$video = document.createElement('iframe');\n            self.$video.setAttribute('id', self.playerID);\n            self.$video.setAttribute('src', `https://player.vimeo.com/video/${self.videoID}?${playerOptionsString}`);\n            self.$video.setAttribute('frameborder', '0');\n            self.$video.setAttribute('mozallowfullscreen', '');\n            self.$video.setAttribute('allowfullscreen', '');\n            self.$video.setAttribute('title', 'Vimeo video player'); // add accessibility attributes\n\n            if (self.options.accessibilityHidden) {\n              self.$video.setAttribute('tabindex', '-1');\n              self.$video.setAttribute('aria-hidden', 'true');\n            }\n\n            hiddenDiv.appendChild(self.$video);\n            document.body.appendChild(hiddenDiv);\n          }\n\n          self.player = self.player || new global$1$1.Vimeo.Player(self.$video, self.playerOptions); // set current time for autoplay\n\n          if (self.options.startTime && self.options.autoplay) {\n            self.player.setCurrentTime(self.options.startTime);\n          } // get video width and height\n\n\n          self.player.getVideoWidth().then(width => {\n            self.videoWidth = width || 1280;\n          });\n          self.player.getVideoHeight().then(height => {\n            self.videoHeight = height || 720;\n          }); // events\n\n          let vmStarted;\n          self.player.on('timeupdate', e => {\n            if (!vmStarted) {\n              self.fire('started', e);\n              vmStarted = 1;\n            }\n\n            self.fire('timeupdate', e); // check for end of video and play again or stop\n\n            if (self.options.endTime) {\n              if (self.options.endTime && e.seconds >= self.options.endTime) {\n                if (self.options.loop) {\n                  self.play(self.options.startTime);\n                } else {\n                  self.pause();\n                }\n              }\n            }\n          });\n          self.player.on('play', e => {\n            self.fire('play', e); // check for the start time and start with it\n\n            if (self.options.startTime && e.seconds === 0) {\n              self.play(self.options.startTime);\n            }\n          });\n          self.player.on('pause', e => {\n            self.fire('pause', e);\n          });\n          self.player.on('ended', e => {\n            self.fire('ended', e);\n          });\n          self.player.on('loaded', e => {\n            self.fire('ready', e);\n          });\n          self.player.on('volumechange', e => {\n            self.fire('volumechange', e);\n          });\n          self.player.on('error', e => {\n            self.fire('error', e);\n          });\n        } // Local\n\n\n        function addSourceToLocal(element, src, type) {\n          const source = document.createElement('source');\n          source.src = src;\n          source.type = type;\n          element.appendChild(source);\n        }\n\n        if (self.type === 'local') {\n          if (!self.$video) {\n            self.$video = document.createElement('video'); // show controls\n\n            if (self.options.showControls) {\n              self.$video.controls = true;\n            } // mute\n\n\n            if (self.options.mute) {\n              self.$video.muted = true;\n            } else if (self.$video.volume) {\n              self.$video.volume = self.options.volume / 100;\n            } // loop\n\n\n            if (self.options.loop) {\n              self.$video.loop = true;\n            } // autoplay enable on mobile devices\n\n\n            self.$video.setAttribute('playsinline', '');\n            self.$video.setAttribute('webkit-playsinline', ''); // add accessibility attributes\n\n            if (self.options.accessibilityHidden) {\n              self.$video.setAttribute('tabindex', '-1');\n              self.$video.setAttribute('aria-hidden', 'true');\n            }\n\n            self.$video.setAttribute('id', self.playerID);\n            hiddenDiv.appendChild(self.$video);\n            document.body.appendChild(hiddenDiv);\n            Object.keys(self.videoID).forEach(key => {\n              addSourceToLocal(self.$video, self.videoID[key], `video/${key}`);\n            });\n          }\n\n          self.player = self.player || self.$video;\n          let locStarted;\n          self.player.addEventListener('playing', e => {\n            if (!locStarted) {\n              self.fire('started', e);\n            }\n\n            locStarted = 1;\n          });\n          self.player.addEventListener('timeupdate', function (e) {\n            self.fire('timeupdate', e); // check for end of video and play again or stop\n\n            if (self.options.endTime) {\n              if (self.options.endTime && this.currentTime >= self.options.endTime) {\n                if (self.options.loop) {\n                  self.play(self.options.startTime);\n                } else {\n                  self.pause();\n                }\n              }\n            }\n          });\n          self.player.addEventListener('play', e => {\n            self.fire('play', e);\n          });\n          self.player.addEventListener('pause', e => {\n            self.fire('pause', e);\n          });\n          self.player.addEventListener('ended', e => {\n            self.fire('ended', e);\n          });\n          self.player.addEventListener('loadedmetadata', function () {\n            // get video width and height\n            self.videoWidth = this.videoWidth || 1280;\n            self.videoHeight = this.videoHeight || 720;\n            self.fire('ready'); // autoplay\n\n            if (self.options.autoplay) {\n              self.play(self.options.startTime);\n            }\n          });\n          self.player.addEventListener('volumechange', e => {\n            self.getVolume(volume => {\n              self.options.volume = volume;\n            });\n            self.fire('volumechange', e);\n          });\n          self.player.addEventListener('error', e => {\n            self.fire('error', e);\n          });\n        }\n\n        callback(self.$video);\n      });\n    }\n\n    init() {\n      const self = this;\n      self.playerID = `VideoWorker-${self.ID}`;\n    }\n\n    loadAPI() {\n      const self = this;\n\n      if (YoutubeAPIadded && VimeoAPIadded) {\n        return;\n      }\n\n      let src = ''; // load Youtube API\n\n      if (self.type === 'youtube' && !YoutubeAPIadded) {\n        YoutubeAPIadded = 1;\n        src = 'https://www.youtube.com/iframe_api';\n      } // load Vimeo API\n\n\n      if (self.type === 'vimeo' && !VimeoAPIadded) {\n        VimeoAPIadded = 1; // Useful when Vimeo API added using RequireJS https://github.com/nk-o/video-worker/pull/7\n\n        if (typeof global$1$1.Vimeo !== 'undefined') {\n          return;\n        }\n\n        src = 'https://player.vimeo.com/api/player.js';\n      }\n\n      if (!src) {\n        return;\n      } // add script in head section\n\n\n      let tag = document.createElement('script');\n      let head = document.getElementsByTagName('head')[0];\n      tag.src = src;\n      head.appendChild(tag);\n      head = null;\n      tag = null;\n    }\n\n    onAPIready(callback) {\n      const self = this; // Youtube\n\n      if (self.type === 'youtube') {\n        // Listen for global YT player callback\n        if ((typeof global$1$1.YT === 'undefined' || global$1$1.YT.loaded === 0) && !loadingYoutubePlayer) {\n          // Prevents Ready event from being called twice\n          loadingYoutubePlayer = 1; // Creates deferred so, other players know when to wait.\n\n          global$1$1.onYouTubeIframeAPIReady = function () {\n            global$1$1.onYouTubeIframeAPIReady = null;\n            loadingYoutubeDefer.resolve('done');\n            callback();\n          };\n        } else if (typeof global$1$1.YT === 'object' && global$1$1.YT.loaded === 1) {\n          callback();\n        } else {\n          loadingYoutubeDefer.done(() => {\n            callback();\n          });\n        }\n      } // Vimeo\n\n\n      if (self.type === 'vimeo') {\n        if (typeof global$1$1.Vimeo === 'undefined' && !loadingVimeoPlayer) {\n          loadingVimeoPlayer = 1;\n          const vimeoInterval = setInterval(() => {\n            if (typeof global$1$1.Vimeo !== 'undefined') {\n              clearInterval(vimeoInterval);\n              loadingVimeoDefer.resolve('done');\n              callback();\n            }\n          }, 20);\n        } else if (typeof global$1$1.Vimeo !== 'undefined') {\n          callback();\n        } else {\n          loadingVimeoDefer.done(() => {\n            callback();\n          });\n        }\n      } // Local\n\n\n      if (self.type === 'local') {\n        callback();\n      }\n    }\n\n  }\n\n  function ready(callback) {\n    if ('complete' === document.readyState || 'interactive' === document.readyState) {\n      // Already ready or interactive, execute callback\n      callback();\n    } else {\n      document.addEventListener('DOMContentLoaded', callback, {\n        capture: true,\n        once: true,\n        passive: true\n      });\n    }\n  }\n\n  /* eslint-disable import/no-mutable-exports */\n\n  /* eslint-disable no-restricted-globals */\n  let win;\n\n  if ('undefined' !== typeof window) {\n    win = window;\n  } else if ('undefined' !== typeof global) {\n    win = global;\n  } else if ('undefined' !== typeof self) {\n    win = self;\n  } else {\n    win = {};\n  }\n\n  var global$1 = win;\n\n  function jarallaxVideo(jarallax = global$1.jarallax) {\n    if ('undefined' === typeof jarallax) {\n      return;\n    }\n\n    const Jarallax = jarallax.constructor; // append video after when block will be visible.\n\n    const defOnScroll = Jarallax.prototype.onScroll;\n\n    Jarallax.prototype.onScroll = function () {\n      const self = this;\n      defOnScroll.apply(self);\n      const isReady = !self.isVideoInserted && self.video && (!self.options.videoLazyLoading || self.isElementInViewport) && !self.options.disableVideo();\n\n      if (isReady) {\n        self.isVideoInserted = true;\n        self.video.getVideo(video => {\n          const $parent = video.parentNode;\n          self.css(video, {\n            position: self.image.position,\n            top: '0px',\n            left: '0px',\n            right: '0px',\n            bottom: '0px',\n            width: '100%',\n            height: '100%',\n            maxWidth: 'none',\n            maxHeight: 'none',\n            pointerEvents: 'none',\n            transformStyle: 'preserve-3d',\n            backfaceVisibility: 'hidden',\n            willChange: 'transform,opacity',\n            margin: 0,\n            zIndex: -1\n          });\n          self.$video = video; // add Poster attribute to self-hosted video\n\n          if ('local' === self.video.type) {\n            if (self.image.src) {\n              self.$video.setAttribute('poster', self.image.src);\n            } else if (self.image.$item && 'IMG' === self.image.$item.tagName && self.image.$item.src) {\n              self.$video.setAttribute('poster', self.image.$item.src);\n            }\n          } // insert video tag\n\n\n          self.image.$container.appendChild(video); // remove parent video element (created by VideoWorker)\n\n          $parent.parentNode.removeChild($parent); // call onVideoInsert event\n\n          if (self.options.onVideoInsert) {\n            self.options.onVideoInsert.call(self);\n          }\n        });\n      }\n    }; // cover video\n\n\n    const defCoverImage = Jarallax.prototype.coverImage;\n\n    Jarallax.prototype.coverImage = function () {\n      const self = this;\n      const imageData = defCoverImage.apply(self);\n      const node = self.image.$item ? self.image.$item.nodeName : false;\n\n      if (imageData && self.video && node && ('IFRAME' === node || 'VIDEO' === node)) {\n        let h = imageData.image.height;\n        let w = h * self.image.width / self.image.height;\n        let ml = (imageData.container.width - w) / 2;\n        let mt = imageData.image.marginTop;\n\n        if (imageData.container.width > w) {\n          w = imageData.container.width;\n          h = w * self.image.height / self.image.width;\n          ml = 0;\n          mt += (imageData.image.height - h) / 2;\n        } // add video height over than need to hide controls\n\n\n        if ('IFRAME' === node) {\n          h += 400;\n          mt -= 200;\n        }\n\n        self.css(self.$video, {\n          width: `${w}px`,\n          marginLeft: `${ml}px`,\n          height: `${h}px`,\n          marginTop: `${mt}px`\n        });\n      }\n\n      return imageData;\n    }; // init video\n\n\n    const defInitImg = Jarallax.prototype.initImg;\n\n    Jarallax.prototype.initImg = function () {\n      const self = this;\n      const defaultResult = defInitImg.apply(self);\n\n      if (!self.options.videoSrc) {\n        self.options.videoSrc = self.$item.getAttribute('data-jarallax-video') || null;\n      }\n\n      if (self.options.videoSrc) {\n        self.defaultInitImgResult = defaultResult;\n        return true;\n      }\n\n      return defaultResult;\n    };\n\n    const defCanInitParallax = Jarallax.prototype.canInitParallax;\n\n    Jarallax.prototype.canInitParallax = function () {\n      const self = this;\n      let defaultResult = defCanInitParallax.apply(self);\n\n      if (!self.options.videoSrc) {\n        return defaultResult;\n      } // Init video api\n\n\n      const video = new VideoWorker(self.options.videoSrc, {\n        autoplay: true,\n        loop: self.options.videoLoop,\n        showControls: false,\n        accessibilityHidden: true,\n        startTime: self.options.videoStartTime || 0,\n        endTime: self.options.videoEndTime || 0,\n        mute: self.options.videoVolume ? 0 : 1,\n        volume: self.options.videoVolume || 0\n      }); // call onVideoWorkerInit event\n\n      if (self.options.onVideoWorkerInit) {\n        self.options.onVideoWorkerInit.call(self, video);\n      }\n\n      function resetDefaultImage() {\n        if (self.image.$default_item) {\n          self.image.$item = self.image.$default_item;\n          self.image.$item.style.display = 'block'; // set image width and height\n\n          self.coverImage();\n          self.onScroll();\n        }\n      }\n\n      if (video.isValid()) {\n        // Force enable parallax.\n        // When the parallax disabled on mobile devices, we still need to display videos.\n        // https://github.com/nk-o/jarallax/issues/159\n        if (this.options.disableParallax()) {\n          defaultResult = true;\n          self.image.position = 'absolute';\n          self.options.type = 'scroll';\n          self.options.speed = 1;\n        } // if parallax will not be inited, we can add thumbnail on background.\n\n\n        if (!defaultResult) {\n          if (!self.defaultInitImgResult) {\n            video.getImageURL(url => {\n              // save default user styles\n              const curStyle = self.$item.getAttribute('style');\n\n              if (curStyle) {\n                self.$item.setAttribute('data-jarallax-original-styles', curStyle);\n              } // set new background\n\n\n              self.css(self.$item, {\n                'background-image': `url(\"${url}\")`,\n                'background-position': 'center',\n                'background-size': 'cover'\n              });\n            });\n          } // init video\n\n        } else {\n          video.on('ready', () => {\n            if (self.options.videoPlayOnlyVisible) {\n              const oldOnScroll = self.onScroll;\n\n              self.onScroll = function () {\n                oldOnScroll.apply(self);\n\n                if (!self.videoError && (self.options.videoLoop || !self.options.videoLoop && !self.videoEnded)) {\n                  if (self.isVisible()) {\n                    video.play();\n                  } else {\n                    video.pause();\n                  }\n                }\n              };\n            } else {\n              video.play();\n            }\n          });\n          video.on('started', () => {\n            self.image.$default_item = self.image.$item;\n            self.image.$item = self.$video; // set video width and height\n\n            self.image.width = self.video.videoWidth || 1280;\n            self.image.height = self.video.videoHeight || 720;\n            self.coverImage();\n            self.onScroll(); // hide image\n\n            if (self.image.$default_item) {\n              self.image.$default_item.style.display = 'none';\n            }\n          });\n          video.on('ended', () => {\n            self.videoEnded = true;\n\n            if (!self.options.videoLoop) {\n              // show default image if Loop disabled.\n              resetDefaultImage();\n            }\n          });\n          video.on('error', () => {\n            self.videoError = true; // show default image if video loading error.\n\n            resetDefaultImage();\n          });\n          self.video = video; // set image if not exists\n\n          if (!self.defaultInitImgResult) {\n            // set empty image on self-hosted video if not defined\n            self.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n\n            if ('local' !== video.type) {\n              video.getImageURL(url => {\n                self.image.bgImage = `url(\"${url}\")`;\n                self.init();\n              });\n              return false;\n            }\n          }\n        }\n      }\n\n      return defaultResult;\n    }; // Destroy video parallax\n\n\n    const defDestroy = Jarallax.prototype.destroy;\n\n    Jarallax.prototype.destroy = function () {\n      const self = this;\n\n      if (self.image.$default_item) {\n        self.image.$item = self.image.$default_item;\n        delete self.image.$default_item;\n      }\n\n      defDestroy.apply(self);\n    };\n  }\n\n  jarallaxVideo(); // data-jarallax-video initialization\n\n  ready(() => {\n    if ('undefined' !== typeof global$1.jarallax) {\n      global$1.jarallax(document.querySelectorAll('[data-jarallax-video]'));\n    }\n  }); // We should add VideoWorker globally, since some project uses it.\n\n  if (!global$1.VideoWorker) {\n    global$1.VideoWorker = VideoWorker;\n  }\n\n  return jarallaxVideo;\n\n}));\n//# sourceMappingURL=jarallax-video.js.map\n","Magento_PageBuilder/js/resource/jarallax/jarallax-wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_PageBuilder/js/resource/jarallax/jarallax'\n], function(jarallax){\n    'use strict';\n\n    window.jarallax = window.jarallax || jarallax;\n});\n","Magento_PageBuilder/js/resource/slick/slick.min.js":"/*\n     _ _      _       _\n ___| (_) ___| | __  (_)___\n/ __| | |/ __| |/ /  | / __|\n\\__ \\ | | (__|   < _ | \\__ \\\n|___/_|_|\\___|_|\\_(_)/ |___/\n                   |__/\n\n Version: 1.9.0\n  Author: Ken Wheeler\n Website: http://kenwheeler.github.io\n    Docs: http://kenwheeler.github.io/slick\n    Repo: http://github.com/kenwheeler/slick\n  Issues: http://github.com/kenwheeler/slick/issues\n\n */\n(function(i){\"use strict\";\"function\"==typeof define&&define.amd?define([\"jquery\"],i):\"undefined\"!=typeof exports?module.exports=i(require(\"jquery\")):i(jQuery)})(function(i){\"use strict\";var e=window.Slick||{};e=function(){function e(e,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(e),appendDots:i(e),arrows:!0,asNavFor:null,prevArrow:'<button class=\"slick-prev\" aria-label=\"Previous\" type=\"button\">Previous</button>',nextArrow:'<button class=\"slick-next\" aria-label=\"Next\" type=\"button\">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:\"50px\",cssEase:\"ease\",customPaging:function(e,t){return i('<button type=\"button\" />').text(t+1)},dots:!1,dotsClass:\"slick-dots\",draggable:!0,easing:\"linear\",edgeFriction:.35,fade:!1,focusOnSelect:!1,focusOnChange:!1,infinite:!0,initialSlide:0,lazyLoad:\"ondemand\",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:\"window\",responsive:null,rows:1,rtl:!1,slide:\"\",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},n.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,scrolling:!1,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,swiping:!1,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},i.extend(n,n.initials),n.activeBreakpoint=null,n.animType=null,n.animProp=null,n.breakpoints=[],n.breakpointSettings=[],n.cssTransitions=!1,n.focussed=!1,n.interrupted=!1,n.hidden=\"hidden\",n.paused=!0,n.positionProp=null,n.respondTo=null,n.rowCount=1,n.shouldClick=!0,n.$slider=i(e),n.$slidesCache=null,n.transformType=null,n.transitionType=null,n.visibilityChange=\"visibilitychange\",n.windowWidth=0,n.windowTimer=null,s=i(e).data(\"slick\")||{},n.options=i.extend({},n.defaults,o,s),n.currentSlide=n.options.initialSlide,n.originalSettings=n.options,\"undefined\"!=typeof document.mozHidden?(n.hidden=\"mozHidden\",n.visibilityChange=\"mozvisibilitychange\"):\"undefined\"!=typeof document.webkitHidden&&(n.hidden=\"webkitHidden\",n.visibilityChange=\"webkitvisibilitychange\"),n.autoPlay=i.proxy(n.autoPlay,n),n.autoPlayClear=i.proxy(n.autoPlayClear,n),n.autoPlayIterator=i.proxy(n.autoPlayIterator,n),n.changeSlide=i.proxy(n.changeSlide,n),n.clickHandler=i.proxy(n.clickHandler,n),n.selectHandler=i.proxy(n.selectHandler,n),n.setPosition=i.proxy(n.setPosition,n),n.swipeHandler=i.proxy(n.swipeHandler,n),n.dragHandler=i.proxy(n.dragHandler,n),n.keyHandler=i.proxy(n.keyHandler,n),n.instanceUid=t++,n.htmlExpr=/^(?:\\s*(<[\\w\\W]+>)[^>]*)$/,n.registerBreakpoints(),n.init(!0)}var t=0;return e}(),e.prototype.activateADA=function(){var i=this;i.$slideTrack.find(\".slick-active\").attr({\"aria-hidden\":\"false\"}).find(\"a, input, button, select\").attr({tabindex:\"0\"})},e.prototype.addSlide=e.prototype.slickAdd=function(e,t,o){var s=this;if(\"boolean\"==typeof t)o=t,t=null;else if(t<0||t>=s.slideCount)return!1;s.unload(),\"number\"==typeof t?0===t&&0===s.$slides.length?i(e).appendTo(s.$slideTrack):o?i(e).insertBefore(s.$slides.eq(t)):i(e).insertAfter(s.$slides.eq(t)):o===!0?i(e).prependTo(s.$slideTrack):i(e).appendTo(s.$slideTrack),s.$slides=s.$slideTrack.children(this.options.slide),s.$slideTrack.children(this.options.slide).detach(),s.$slideTrack.append(s.$slides),s.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e)}),s.$slidesCache=s.$slides,s.reinit()},e.prototype.animateHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.animate({height:e},i.options.speed)}},e.prototype.animateSlide=function(e,t){var o={},s=this;s.animateHeight(),s.options.rtl===!0&&s.options.vertical===!1&&(e=-e),s.transformsEnabled===!1?s.options.vertical===!1?s.$slideTrack.animate({left:e},s.options.speed,s.options.easing,t):s.$slideTrack.animate({top:e},s.options.speed,s.options.easing,t):s.cssTransitions===!1?(s.options.rtl===!0&&(s.currentLeft=-s.currentLeft),i({animStart:s.currentLeft}).animate({animStart:e},{duration:s.options.speed,easing:s.options.easing,step:function(i){i=Math.ceil(i),s.options.vertical===!1?(o[s.animType]=\"translate(\"+i+\"px, 0px)\",s.$slideTrack.css(o)):(o[s.animType]=\"translate(0px,\"+i+\"px)\",s.$slideTrack.css(o))},complete:function(){t&&t.call()}})):(s.applyTransition(),e=Math.ceil(e),s.options.vertical===!1?o[s.animType]=\"translate3d(\"+e+\"px, 0px, 0px)\":o[s.animType]=\"translate3d(0px,\"+e+\"px, 0px)\",s.$slideTrack.css(o),t&&setTimeout(function(){s.disableTransition(),t.call()},s.options.speed))},e.prototype.getNavTarget=function(){var e=this,t=e.options.asNavFor;return t&&null!==t&&(t=i(t).not(e.$slider)),t},e.prototype.asNavFor=function(e){var t=this,o=t.getNavTarget();null!==o&&\"object\"==typeof o&&o.each(function(){var t=i(this).slick(\"getSlick\");t.unslicked||t.slideHandler(e,!0)})},e.prototype.applyTransition=function(i){var e=this,t={};e.options.fade===!1?t[e.transitionType]=e.transformType+\" \"+e.options.speed+\"ms \"+e.options.cssEase:t[e.transitionType]=\"opacity \"+e.options.speed+\"ms \"+e.options.cssEase,e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.autoPlay=function(){var i=this;i.autoPlayClear(),i.slideCount>i.options.slidesToShow&&(i.autoPlayTimer=setInterval(i.autoPlayIterator,i.options.autoplaySpeed))},e.prototype.autoPlayClear=function(){var i=this;i.autoPlayTimer&&clearInterval(i.autoPlayTimer)},e.prototype.autoPlayIterator=function(){var i=this,e=i.currentSlide+i.options.slidesToScroll;i.paused||i.interrupted||i.focussed||(i.options.infinite===!1&&(1===i.direction&&i.currentSlide+1===i.slideCount-1?i.direction=0:0===i.direction&&(e=i.currentSlide-i.options.slidesToScroll,i.currentSlide-1===0&&(i.direction=1))),i.slideHandler(e))},e.prototype.buildArrows=function(){var e=this;e.options.arrows===!0&&(e.$prevArrow=i(e.options.prevArrow).addClass(\"slick-arrow\"),e.$nextArrow=i(e.options.nextArrow).addClass(\"slick-arrow\"),e.slideCount>e.options.slidesToShow?(e.$prevArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.$nextArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.prependTo(e.options.appendArrows),e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.appendTo(e.options.appendArrows),e.options.infinite!==!0&&e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\")):e.$prevArrow.add(e.$nextArrow).addClass(\"slick-hidden\").attr({\"aria-disabled\":\"true\",tabindex:\"-1\"}))},e.prototype.buildDots=function(){var e,t,o=this;if(o.options.dots===!0&&o.slideCount>o.options.slidesToShow){for(o.$slider.addClass(\"slick-dotted\"),t=i(\"<ul />\").addClass(o.options.dotsClass),e=0;e<=o.getDotCount();e+=1)t.append(i(\"<li />\").append(o.options.customPaging.call(this,o,e)));o.$dots=t.appendTo(o.options.appendDots),o.$dots.find(\"li\").first().addClass(\"slick-active\")}},e.prototype.buildOut=function(){var e=this;e.$slides=e.$slider.children(e.options.slide+\":not(.slick-cloned)\").addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e).data(\"originalStyling\",i(t).attr(\"style\")||\"\")}),e.$slider.addClass(\"slick-slider\"),e.$slideTrack=0===e.slideCount?i('<div class=\"slick-track\"/>').appendTo(e.$slider):e.$slides.wrapAll('<div class=\"slick-track\"/>').parent(),e.$list=e.$slideTrack.wrap('<div class=\"slick-list\"/>').parent(),e.$slideTrack.css(\"opacity\",0),e.options.centerMode!==!0&&e.options.swipeToSlide!==!0||(e.options.slidesToScroll=1),i(\"img[data-lazy]\",e.$slider).not(\"[src]\").addClass(\"slick-loading\"),e.setupInfinite(),e.buildArrows(),e.buildDots(),e.updateDots(),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.options.draggable===!0&&e.$list.addClass(\"draggable\")},e.prototype.buildRows=function(){var i,e,t,o,s,n,r,l=this;if(o=document.createDocumentFragment(),n=l.$slider.children(),l.options.rows>0){for(r=l.options.slidesPerRow*l.options.rows,s=Math.ceil(n.length/r),i=0;i<s;i++){var d=document.createElement(\"div\");for(e=0;e<l.options.rows;e++){var a=document.createElement(\"div\");for(t=0;t<l.options.slidesPerRow;t++){var c=i*r+(e*l.options.slidesPerRow+t);n.get(c)&&a.appendChild(n.get(c))}d.appendChild(a)}o.appendChild(d)}l.$slider.empty().append(o),l.$slider.children().children().children().css({width:100/l.options.slidesPerRow+\"%\",display:\"inline-block\"})}},e.prototype.checkResponsive=function(e,t){var o,s,n,r=this,l=!1,d=r.$slider.width(),a=window.innerWidth||i(window).width();if(\"window\"===r.respondTo?n=a:\"slider\"===r.respondTo?n=d:\"min\"===r.respondTo&&(n=Math.min(a,d)),r.options.responsive&&r.options.responsive.length&&null!==r.options.responsive){s=null;for(o in r.breakpoints)r.breakpoints.hasOwnProperty(o)&&(r.originalSettings.mobileFirst===!1?n<r.breakpoints[o]&&(s=r.breakpoints[o]):n>r.breakpoints[o]&&(s=r.breakpoints[o]));null!==s?null!==r.activeBreakpoint?(s!==r.activeBreakpoint||t)&&(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):null!==r.activeBreakpoint&&(r.activeBreakpoint=null,r.options=r.originalSettings,e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e),l=s),e||l===!1||r.$slider.trigger(\"breakpoint\",[r,l])}},e.prototype.changeSlide=function(e,t){var o,s,n,r=this,l=i(e.currentTarget);switch(l.is(\"a\")&&e.preventDefault(),l.is(\"li\")||(l=l.closest(\"li\")),n=r.slideCount%r.options.slidesToScroll!==0,o=n?0:(r.slideCount-r.currentSlide)%r.options.slidesToScroll,e.data.message){case\"previous\":s=0===o?r.options.slidesToScroll:r.options.slidesToShow-o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide-s,!1,t);break;case\"next\":s=0===o?r.options.slidesToScroll:o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide+s,!1,t);break;case\"index\":var d=0===e.data.index?0:e.data.index||l.index()*r.options.slidesToScroll;r.slideHandler(r.checkNavigable(d),!1,t),l.children().trigger(\"focus\");break;default:return}},e.prototype.checkNavigable=function(i){var e,t,o=this;if(e=o.getNavigableIndexes(),t=0,i>e[e.length-1])i=e[e.length-1];else for(var s in e){if(i<e[s]){i=t;break}t=e[s]}return i},e.prototype.cleanUpEvents=function(){var e=this;e.options.dots&&null!==e.$dots&&(i(\"li\",e.$dots).off(\"click.slick\",e.changeSlide).off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)),e.options.accessibility===!0&&e.$dots.off(\"keydown.slick\",e.keyHandler)),e.$slider.off(\"focus.slick blur.slick\"),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&(e.$prevArrow&&e.$prevArrow.off(\"click.slick\",e.changeSlide),e.$nextArrow&&e.$nextArrow.off(\"click.slick\",e.changeSlide),e.options.accessibility===!0&&(e.$prevArrow&&e.$prevArrow.off(\"keydown.slick\",e.keyHandler),e.$nextArrow&&e.$nextArrow.off(\"keydown.slick\",e.keyHandler))),e.$list.off(\"touchstart.slick mousedown.slick\",e.swipeHandler),e.$list.off(\"touchmove.slick mousemove.slick\",e.swipeHandler),e.$list.off(\"touchend.slick mouseup.slick\",e.swipeHandler),e.$list.off(\"touchcancel.slick mouseleave.slick\",e.swipeHandler),e.$list.off(\"click.slick\",e.clickHandler),i(document).off(e.visibilityChange,e.visibility),e.cleanUpSlideEvents(),e.options.accessibility===!0&&e.$list.off(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().off(\"click.slick\",e.selectHandler),i(window).off(\"orientationchange.slick.slick-\"+e.instanceUid,e.orientationChange),i(window).off(\"resize.slick.slick-\"+e.instanceUid,e.resize),i(\"[draggable!=true]\",e.$slideTrack).off(\"dragstart\",e.preventDefault),i(window).off(\"load.slick.slick-\"+e.instanceUid,e.setPosition)},e.prototype.cleanUpSlideEvents=function(){var e=this;e.$list.off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.cleanUpRows=function(){var i,e=this;e.options.rows>0&&(i=e.$slides.children().children(),i.removeAttr(\"style\"),e.$slider.empty().append(i))},e.prototype.clickHandler=function(i){var e=this;e.shouldClick===!1&&(i.stopImmediatePropagation(),i.stopPropagation(),i.preventDefault())},e.prototype.destroy=function(e){var t=this;t.autoPlayClear(),t.touchObject={},t.cleanUpEvents(),i(\".slick-cloned\",t.$slider).detach(),t.$dots&&t.$dots.remove(),t.$prevArrow&&t.$prevArrow.length&&(t.$prevArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.prevArrow)&&t.$prevArrow.remove()),t.$nextArrow&&t.$nextArrow.length&&(t.$nextArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.nextArrow)&&t.$nextArrow.remove()),t.$slides&&(t.$slides.removeClass(\"slick-slide slick-active slick-center slick-visible slick-current\").removeAttr(\"aria-hidden\").removeAttr(\"data-slick-index\").each(function(){i(this).attr(\"style\",i(this).data(\"originalStyling\"))}),t.$slideTrack.children(this.options.slide).detach(),t.$slideTrack.detach(),t.$list.detach(),t.$slider.append(t.$slides)),t.cleanUpRows(),t.$slider.removeClass(\"slick-slider\"),t.$slider.removeClass(\"slick-initialized\"),t.$slider.removeClass(\"slick-dotted\"),t.unslicked=!0,e||t.$slider.trigger(\"destroy\",[t])},e.prototype.disableTransition=function(i){var e=this,t={};t[e.transitionType]=\"\",e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.fadeSlide=function(i,e){var t=this;t.cssTransitions===!1?(t.$slides.eq(i).css({zIndex:t.options.zIndex}),t.$slides.eq(i).animate({opacity:1},t.options.speed,t.options.easing,e)):(t.applyTransition(i),t.$slides.eq(i).css({opacity:1,zIndex:t.options.zIndex}),e&&setTimeout(function(){t.disableTransition(i),e.call()},t.options.speed))},e.prototype.fadeSlideOut=function(i){var e=this;e.cssTransitions===!1?e.$slides.eq(i).animate({opacity:0,zIndex:e.options.zIndex-2},e.options.speed,e.options.easing):(e.applyTransition(i),e.$slides.eq(i).css({opacity:0,zIndex:e.options.zIndex-2}))},e.prototype.filterSlides=e.prototype.slickFilter=function(i){var e=this;null!==i&&(e.$slidesCache=e.$slides,e.unload(),e.$slideTrack.children(this.options.slide).detach(),e.$slidesCache.filter(i).appendTo(e.$slideTrack),e.reinit())},e.prototype.focusHandler=function(){var e=this;e.$slider.off(\"focus.slick blur.slick\").on(\"focus.slick\",\"*\",function(t){var o=i(this);setTimeout(function(){e.options.pauseOnFocus&&o.is(\":focus\")&&(e.focussed=!0,e.autoPlay())},0)}).on(\"blur.slick\",\"*\",function(t){i(this);e.options.pauseOnFocus&&(e.focussed=!1,e.autoPlay())})},e.prototype.getCurrent=e.prototype.slickCurrentSlide=function(){var i=this;return i.currentSlide},e.prototype.getDotCount=function(){var i=this,e=0,t=0,o=0;if(i.options.infinite===!0)if(i.slideCount<=i.options.slidesToShow)++o;else for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else if(i.options.centerMode===!0)o=i.slideCount;else if(i.options.asNavFor)for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else o=1+Math.ceil((i.slideCount-i.options.slidesToShow)/i.options.slidesToScroll);return o-1},e.prototype.getLeft=function(i){var e,t,o,s,n=this,r=0;return n.slideOffset=0,t=n.$slides.first().outerHeight(!0),n.options.infinite===!0?(n.slideCount>n.options.slidesToShow&&(n.slideOffset=n.slideWidth*n.options.slidesToShow*-1,s=-1,n.options.vertical===!0&&n.options.centerMode===!0&&(2===n.options.slidesToShow?s=-1.5:1===n.options.slidesToShow&&(s=-2)),r=t*n.options.slidesToShow*s),n.slideCount%n.options.slidesToScroll!==0&&i+n.options.slidesToScroll>n.slideCount&&n.slideCount>n.options.slidesToShow&&(i>n.slideCount?(n.slideOffset=(n.options.slidesToShow-(i-n.slideCount))*n.slideWidth*-1,r=(n.options.slidesToShow-(i-n.slideCount))*t*-1):(n.slideOffset=n.slideCount%n.options.slidesToScroll*n.slideWidth*-1,r=n.slideCount%n.options.slidesToScroll*t*-1))):i+n.options.slidesToShow>n.slideCount&&(n.slideOffset=(i+n.options.slidesToShow-n.slideCount)*n.slideWidth,r=(i+n.options.slidesToShow-n.slideCount)*t),n.slideCount<=n.options.slidesToShow&&(n.slideOffset=0,r=0),n.options.centerMode===!0&&n.slideCount<=n.options.slidesToShow?n.slideOffset=n.slideWidth*Math.floor(n.options.slidesToShow)/2-n.slideWidth*n.slideCount/2:n.options.centerMode===!0&&n.options.infinite===!0?n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)-n.slideWidth:n.options.centerMode===!0&&(n.slideOffset=0,n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)),e=n.options.vertical===!1?i*n.slideWidth*-1+n.slideOffset:i*t*-1+r,n.options.variableWidth===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,n.options.centerMode===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow+1),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,e+=(n.$list.width()-o.outerWidth())/2)),e},e.prototype.getOption=e.prototype.slickGetOption=function(i){var e=this;return e.options[i]},e.prototype.getNavigableIndexes=function(){var i,e=this,t=0,o=0,s=[];for(e.options.infinite===!1?i=e.slideCount:(t=e.options.slidesToScroll*-1,o=e.options.slidesToScroll*-1,i=2*e.slideCount);t<i;)s.push(t),t=o+e.options.slidesToScroll,o+=e.options.slidesToScroll<=e.options.slidesToShow?e.options.slidesToScroll:e.options.slidesToShow;return s},e.prototype.getSlick=function(){return this},e.prototype.getSlideCount=function(){var e,t,o,s,n=this;return s=n.options.centerMode===!0?Math.floor(n.$list.width()/2):0,o=n.swipeLeft*-1+s,n.options.swipeToSlide===!0?(n.$slideTrack.find(\".slick-slide\").each(function(e,s){var r,l,d;if(r=i(s).outerWidth(),l=s.offsetLeft,n.options.centerMode!==!0&&(l+=r/2),d=l+r,o<d)return t=s,!1}),e=Math.abs(i(t).attr(\"data-slick-index\")-n.currentSlide)||1):n.options.slidesToScroll},e.prototype.goTo=e.prototype.slickGoTo=function(i,e){var t=this;t.changeSlide({data:{message:\"index\",index:parseInt(i)}},e)},e.prototype.init=function(e){var t=this;i(t.$slider).hasClass(\"slick-initialized\")||(i(t.$slider).addClass(\"slick-initialized\"),t.buildRows(),t.buildOut(),t.setProps(),t.startLoad(),t.loadSlider(),t.initializeEvents(),t.updateArrows(),t.updateDots(),t.checkResponsive(!0),t.focusHandler()),e&&t.$slider.trigger(\"init\",[t]),t.options.accessibility===!0&&t.initADA(),t.options.autoplay&&(t.paused=!1,t.autoPlay())},e.prototype.initADA=function(){var e=this,t=Math.ceil(e.slideCount/e.options.slidesToShow),o=e.getNavigableIndexes().filter(function(i){return i>=0&&i<e.slideCount});e.$slides.add(e.$slideTrack.find(\".slick-cloned\")).attr({\"aria-hidden\":\"true\",tabindex:\"-1\"}).find(\"a, input, button, select\").attr({tabindex:\"-1\"}),null!==e.$dots&&(e.$slides.not(e.$slideTrack.find(\".slick-cloned\")).each(function(t){var s=o.indexOf(t);if(i(this).attr({role:\"tabpanel\",id:\"slick-slide\"+e.instanceUid+t,tabindex:-1}),s!==-1){var n=\"slick-slide-control\"+e.instanceUid+s;i(\"#\"+n).length&&i(this).attr({\"aria-describedby\":n})}}),e.$dots.attr(\"role\",\"tablist\").find(\"li\").each(function(s){var n=o[s];i(this).attr({role:\"presentation\"}),i(this).find(\"button\").first().attr({role:\"tab\",id:\"slick-slide-control\"+e.instanceUid+s,\"aria-controls\":\"slick-slide\"+e.instanceUid+n,\"aria-label\":s+1+\" of \"+t,\"aria-selected\":null,tabindex:\"-1\"})}).eq(e.currentSlide).find(\"button\").attr({\"aria-selected\":\"true\",tabindex:\"0\"}).end());for(var s=e.currentSlide,n=s+e.options.slidesToShow;s<n;s++)e.options.focusOnChange?e.$slides.eq(s).attr({tabindex:\"0\"}):e.$slides.eq(s).removeAttr(\"tabindex\");e.activateADA()},e.prototype.initArrowEvents=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.off(\"click.slick\").on(\"click.slick\",{message:\"previous\"},i.changeSlide),i.$nextArrow.off(\"click.slick\").on(\"click.slick\",{message:\"next\"},i.changeSlide),i.options.accessibility===!0&&(i.$prevArrow.on(\"keydown.slick\",i.keyHandler),i.$nextArrow.on(\"keydown.slick\",i.keyHandler)))},e.prototype.initDotEvents=function(){var e=this;e.options.dots===!0&&e.slideCount>e.options.slidesToShow&&(i(\"li\",e.$dots).on(\"click.slick\",{message:\"index\"},e.changeSlide),e.options.accessibility===!0&&e.$dots.on(\"keydown.slick\",e.keyHandler)),e.options.dots===!0&&e.options.pauseOnDotsHover===!0&&e.slideCount>e.options.slidesToShow&&i(\"li\",e.$dots).on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.initSlideEvents=function(){var e=this;e.options.pauseOnHover&&(e.$list.on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)))},e.prototype.initializeEvents=function(){var e=this;e.initArrowEvents(),e.initDotEvents(),e.initSlideEvents(),e.$list.on(\"touchstart.slick mousedown.slick\",{action:\"start\"},e.swipeHandler),e.$list.on(\"touchmove.slick mousemove.slick\",{action:\"move\"},e.swipeHandler),e.$list.on(\"touchend.slick mouseup.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"touchcancel.slick mouseleave.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"click.slick\",e.clickHandler),i(document).on(e.visibilityChange,i.proxy(e.visibility,e)),e.options.accessibility===!0&&e.$list.on(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),i(window).on(\"orientationchange.slick.slick-\"+e.instanceUid,i.proxy(e.orientationChange,e)),i(window).on(\"resize.slick.slick-\"+e.instanceUid,i.proxy(e.resize,e)),i(\"[draggable!=true]\",e.$slideTrack).on(\"dragstart\",e.preventDefault),i(window).on(\"load.slick.slick-\"+e.instanceUid,e.setPosition),i(e.setPosition)},e.prototype.initUI=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.show(),i.$nextArrow.show()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.show()},e.prototype.keyHandler=function(i){var e=this;i.target.tagName.match(\"TEXTAREA|INPUT|SELECT\")||(37===i.keyCode&&e.options.accessibility===!0?e.changeSlide({data:{message:e.options.rtl===!0?\"next\":\"previous\"}}):39===i.keyCode&&e.options.accessibility===!0&&e.changeSlide({data:{message:e.options.rtl===!0?\"previous\":\"next\"}}))},e.prototype.lazyLoad=function(){function e(e){i(\"img[data-lazy]\",e).each(function(){var e=i(this),t=i(this).attr(\"data-lazy\"),o=i(this).attr(\"data-srcset\"),s=i(this).attr(\"data-sizes\")||r.$slider.attr(\"data-sizes\"),n=document.createElement(\"img\");n.onload=function(){e.animate({opacity:0},100,function(){o&&(e.attr(\"srcset\",o),s&&e.attr(\"sizes\",s)),e.attr(\"src\",t).animate({opacity:1},200,function(){e.removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\")}),r.$slider.trigger(\"lazyLoaded\",[r,e,t])})},n.onerror=function(){e.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),r.$slider.trigger(\"lazyLoadError\",[r,e,t])},n.src=t})}var t,o,s,n,r=this;if(r.options.centerMode===!0?r.options.infinite===!0?(s=r.currentSlide+(r.options.slidesToShow/2+1),n=s+r.options.slidesToShow+2):(s=Math.max(0,r.currentSlide-(r.options.slidesToShow/2+1)),n=2+(r.options.slidesToShow/2+1)+r.currentSlide):(s=r.options.infinite?r.options.slidesToShow+r.currentSlide:r.currentSlide,n=Math.ceil(s+r.options.slidesToShow),r.options.fade===!0&&(s>0&&s--,n<=r.slideCount&&n++)),t=r.$slider.find(\".slick-slide\").slice(s,n),\"anticipated\"===r.options.lazyLoad)for(var l=s-1,d=n,a=r.$slider.find(\".slick-slide\"),c=0;c<r.options.slidesToScroll;c++)l<0&&(l=r.slideCount-1),t=t.add(a.eq(l)),t=t.add(a.eq(d)),l--,d++;e(t),r.slideCount<=r.options.slidesToShow?(o=r.$slider.find(\".slick-slide\"),e(o)):r.currentSlide>=r.slideCount-r.options.slidesToShow?(o=r.$slider.find(\".slick-cloned\").slice(0,r.options.slidesToShow),e(o)):0===r.currentSlide&&(o=r.$slider.find(\".slick-cloned\").slice(r.options.slidesToShow*-1),e(o))},e.prototype.loadSlider=function(){var i=this;i.setPosition(),i.$slideTrack.css({opacity:1}),i.$slider.removeClass(\"slick-loading\"),i.initUI(),\"progressive\"===i.options.lazyLoad&&i.progressiveLazyLoad()},e.prototype.next=e.prototype.slickNext=function(){var i=this;i.changeSlide({data:{message:\"next\"}})},e.prototype.orientationChange=function(){var i=this;i.checkResponsive(),i.setPosition()},e.prototype.pause=e.prototype.slickPause=function(){var i=this;i.autoPlayClear(),i.paused=!0},e.prototype.play=e.prototype.slickPlay=function(){var i=this;i.autoPlay(),i.options.autoplay=!0,i.paused=!1,i.focussed=!1,i.interrupted=!1},e.prototype.postSlide=function(e){var t=this;if(!t.unslicked&&(t.$slider.trigger(\"afterChange\",[t,e]),t.animating=!1,t.slideCount>t.options.slidesToShow&&t.setPosition(),t.swipeLeft=null,t.options.autoplay&&t.autoPlay(),t.options.accessibility===!0&&(t.initADA(),t.options.focusOnChange))){var o=i(t.$slides.get(t.currentSlide));o.attr(\"tabindex\",0).focus()}},e.prototype.prev=e.prototype.slickPrev=function(){var i=this;i.changeSlide({data:{message:\"previous\"}})},e.prototype.preventDefault=function(i){i.preventDefault()},e.prototype.progressiveLazyLoad=function(e){e=e||1;var t,o,s,n,r,l=this,d=i(\"img[data-lazy]\",l.$slider);d.length?(t=d.first(),o=t.attr(\"data-lazy\"),s=t.attr(\"data-srcset\"),n=t.attr(\"data-sizes\")||l.$slider.attr(\"data-sizes\"),r=document.createElement(\"img\"),r.onload=function(){s&&(t.attr(\"srcset\",s),n&&t.attr(\"sizes\",n)),t.attr(\"src\",o).removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\"),l.options.adaptiveHeight===!0&&l.setPosition(),l.$slider.trigger(\"lazyLoaded\",[l,t,o]),l.progressiveLazyLoad()},r.onerror=function(){e<3?setTimeout(function(){l.progressiveLazyLoad(e+1)},500):(t.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),l.$slider.trigger(\"lazyLoadError\",[l,t,o]),l.progressiveLazyLoad())},r.src=o):l.$slider.trigger(\"allImagesLoaded\",[l])},e.prototype.refresh=function(e){var t,o,s=this;o=s.slideCount-s.options.slidesToShow,!s.options.infinite&&s.currentSlide>o&&(s.currentSlide=o),s.slideCount<=s.options.slidesToShow&&(s.currentSlide=0),t=s.currentSlide,s.destroy(!0),i.extend(s,s.initials,{currentSlide:t}),s.init(),e||s.changeSlide({data:{message:\"index\",index:t}},!1)},e.prototype.registerBreakpoints=function(){var e,t,o,s=this,n=s.options.responsive||null;if(\"array\"===i.type(n)&&n.length){s.respondTo=s.options.respondTo||\"window\";for(e in n)if(o=s.breakpoints.length-1,n.hasOwnProperty(e)){for(t=n[e].breakpoint;o>=0;)s.breakpoints[o]&&s.breakpoints[o]===t&&s.breakpoints.splice(o,1),o--;s.breakpoints.push(t),s.breakpointSettings[t]=n[e].settings}s.breakpoints.sort(function(i,e){return s.options.mobileFirst?i-e:e-i})}},e.prototype.reinit=function(){var e=this;e.$slides=e.$slideTrack.children(e.options.slide).addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.currentSlide>=e.slideCount&&0!==e.currentSlide&&(e.currentSlide=e.currentSlide-e.options.slidesToScroll),e.slideCount<=e.options.slidesToShow&&(e.currentSlide=0),e.registerBreakpoints(),e.setProps(),e.setupInfinite(),e.buildArrows(),e.updateArrows(),e.initArrowEvents(),e.buildDots(),e.updateDots(),e.initDotEvents(),e.cleanUpSlideEvents(),e.initSlideEvents(),e.checkResponsive(!1,!0),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.setPosition(),e.focusHandler(),e.paused=!e.options.autoplay,e.autoPlay(),e.$slider.trigger(\"reInit\",[e])},e.prototype.resize=function(){var e=this;i(window).width()!==e.windowWidth&&(clearTimeout(e.windowDelay),e.windowDelay=window.setTimeout(function(){e.windowWidth=i(window).width(),e.checkResponsive(),e.unslicked||e.setPosition()},50))},e.prototype.removeSlide=e.prototype.slickRemove=function(i,e,t){var o=this;return\"boolean\"==typeof i?(e=i,i=e===!0?0:o.slideCount-1):i=e===!0?--i:i,!(o.slideCount<1||i<0||i>o.slideCount-1)&&(o.unload(),t===!0?o.$slideTrack.children().remove():o.$slideTrack.children(this.options.slide).eq(i).remove(),o.$slides=o.$slideTrack.children(this.options.slide),o.$slideTrack.children(this.options.slide).detach(),o.$slideTrack.append(o.$slides),o.$slidesCache=o.$slides,void o.reinit())},e.prototype.setCSS=function(i){var e,t,o=this,s={};o.options.rtl===!0&&(i=-i),e=\"left\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",t=\"top\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",s[o.positionProp]=i,o.transformsEnabled===!1?o.$slideTrack.css(s):(s={},o.cssTransitions===!1?(s[o.animType]=\"translate(\"+e+\", \"+t+\")\",o.$slideTrack.css(s)):(s[o.animType]=\"translate3d(\"+e+\", \"+t+\", 0px)\",o.$slideTrack.css(s)))},e.prototype.setDimensions=function(){var i=this;i.options.vertical===!1?i.options.centerMode===!0&&i.$list.css({padding:\"0px \"+i.options.centerPadding}):(i.$list.height(i.$slides.first().outerHeight(!0)*i.options.slidesToShow),i.options.centerMode===!0&&i.$list.css({padding:i.options.centerPadding+\" 0px\"})),i.listWidth=i.$list.width(),i.listHeight=i.$list.height(),i.options.vertical===!1&&i.options.variableWidth===!1?(i.slideWidth=Math.ceil(i.listWidth/i.options.slidesToShow),i.$slideTrack.width(Math.ceil(i.slideWidth*i.$slideTrack.children(\".slick-slide\").length))):i.options.variableWidth===!0?i.$slideTrack.width(5e3*i.slideCount):(i.slideWidth=Math.ceil(i.listWidth),i.$slideTrack.height(Math.ceil(i.$slides.first().outerHeight(!0)*i.$slideTrack.children(\".slick-slide\").length)));var e=i.$slides.first().outerWidth(!0)-i.$slides.first().width();i.options.variableWidth===!1&&i.$slideTrack.children(\".slick-slide\").width(i.slideWidth-e)},e.prototype.setFade=function(){var e,t=this;t.$slides.each(function(o,s){e=t.slideWidth*o*-1,t.options.rtl===!0?i(s).css({position:\"relative\",right:e,top:0,zIndex:t.options.zIndex-2,opacity:0}):i(s).css({position:\"relative\",left:e,top:0,zIndex:t.options.zIndex-2,opacity:0})}),t.$slides.eq(t.currentSlide).css({zIndex:t.options.zIndex-1,opacity:1})},e.prototype.setHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.css(\"height\",e)}},e.prototype.setOption=e.prototype.slickSetOption=function(){var e,t,o,s,n,r=this,l=!1;if(\"object\"===i.type(arguments[0])?(o=arguments[0],l=arguments[1],n=\"multiple\"):\"string\"===i.type(arguments[0])&&(o=arguments[0],s=arguments[1],l=arguments[2],\"responsive\"===arguments[0]&&\"array\"===i.type(arguments[1])?n=\"responsive\":\"undefined\"!=typeof arguments[1]&&(n=\"single\")),\"single\"===n)r.options[o]=s;else if(\"multiple\"===n)i.each(o,function(i,e){r.options[i]=e});else if(\"responsive\"===n)for(t in s)if(\"array\"!==i.type(r.options.responsive))r.options.responsive=[s[t]];else{for(e=r.options.responsive.length-1;e>=0;)r.options.responsive[e].breakpoint===s[t].breakpoint&&r.options.responsive.splice(e,1),e--;r.options.responsive.push(s[t])}l&&(r.unload(),r.reinit())},e.prototype.setPosition=function(){var i=this;i.setDimensions(),i.setHeight(),i.options.fade===!1?i.setCSS(i.getLeft(i.currentSlide)):i.setFade(),i.$slider.trigger(\"setPosition\",[i])},e.prototype.setProps=function(){var i=this,e=document.body.style;i.positionProp=i.options.vertical===!0?\"top\":\"left\",\n\"top\"===i.positionProp?i.$slider.addClass(\"slick-vertical\"):i.$slider.removeClass(\"slick-vertical\"),void 0===e.WebkitTransition&&void 0===e.MozTransition&&void 0===e.msTransition||i.options.useCSS===!0&&(i.cssTransitions=!0),i.options.fade&&(\"number\"==typeof i.options.zIndex?i.options.zIndex<3&&(i.options.zIndex=3):i.options.zIndex=i.defaults.zIndex),void 0!==e.OTransform&&(i.animType=\"OTransform\",i.transformType=\"-o-transform\",i.transitionType=\"OTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.MozTransform&&(i.animType=\"MozTransform\",i.transformType=\"-moz-transform\",i.transitionType=\"MozTransition\",void 0===e.perspectiveProperty&&void 0===e.MozPerspective&&(i.animType=!1)),void 0!==e.webkitTransform&&(i.animType=\"webkitTransform\",i.transformType=\"-webkit-transform\",i.transitionType=\"webkitTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.msTransform&&(i.animType=\"msTransform\",i.transformType=\"-ms-transform\",i.transitionType=\"msTransition\",void 0===e.msTransform&&(i.animType=!1)),void 0!==e.transform&&i.animType!==!1&&(i.animType=\"transform\",i.transformType=\"transform\",i.transitionType=\"transition\"),i.transformsEnabled=i.options.useTransform&&null!==i.animType&&i.animType!==!1},e.prototype.setSlideClasses=function(i){var e,t,o,s,n=this;if(t=n.$slider.find(\".slick-slide\").removeClass(\"slick-active slick-center slick-current\").attr(\"aria-hidden\",\"true\"),n.$slides.eq(i).addClass(\"slick-current\"),n.options.centerMode===!0){var r=n.options.slidesToShow%2===0?1:0;e=Math.floor(n.options.slidesToShow/2),n.options.infinite===!0&&(i>=e&&i<=n.slideCount-1-e?n.$slides.slice(i-e+r,i+e+1).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(o=n.options.slidesToShow+i,t.slice(o-e+1+r,o+e+2).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\")),0===i?t.eq(t.length-1-n.options.slidesToShow).addClass(\"slick-center\"):i===n.slideCount-1&&t.eq(n.options.slidesToShow).addClass(\"slick-center\")),n.$slides.eq(i).addClass(\"slick-center\")}else i>=0&&i<=n.slideCount-n.options.slidesToShow?n.$slides.slice(i,i+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.length<=n.options.slidesToShow?t.addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(s=n.slideCount%n.options.slidesToShow,o=n.options.infinite===!0?n.options.slidesToShow+i:i,n.options.slidesToShow==n.options.slidesToScroll&&n.slideCount-i<n.options.slidesToShow?t.slice(o-(n.options.slidesToShow-s),o+s).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.slice(o,o+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"));\"ondemand\"!==n.options.lazyLoad&&\"anticipated\"!==n.options.lazyLoad||n.lazyLoad()},e.prototype.setupInfinite=function(){var e,t,o,s=this;if(s.options.fade===!0&&(s.options.centerMode=!1),s.options.infinite===!0&&s.options.fade===!1&&(t=null,s.slideCount>s.options.slidesToShow)){for(o=s.options.centerMode===!0?s.options.slidesToShow+1:s.options.slidesToShow,e=s.slideCount;e>s.slideCount-o;e-=1)t=e-1,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t-s.slideCount).prependTo(s.$slideTrack).addClass(\"slick-cloned\");for(e=0;e<o+s.slideCount;e+=1)t=e,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t+s.slideCount).appendTo(s.$slideTrack).addClass(\"slick-cloned\");s.$slideTrack.find(\".slick-cloned\").find(\"[id]\").each(function(){i(this).attr(\"id\",\"\")})}},e.prototype.interrupt=function(i){var e=this;i||e.autoPlay(),e.interrupted=i},e.prototype.selectHandler=function(e){var t=this,o=i(e.target).is(\".slick-slide\")?i(e.target):i(e.target).parents(\".slick-slide\"),s=parseInt(o.attr(\"data-slick-index\"));return s||(s=0),t.slideCount<=t.options.slidesToShow?void t.slideHandler(s,!1,!0):void t.slideHandler(s)},e.prototype.slideHandler=function(i,e,t){var o,s,n,r,l,d=null,a=this;if(e=e||!1,!(a.animating===!0&&a.options.waitForAnimate===!0||a.options.fade===!0&&a.currentSlide===i))return e===!1&&a.asNavFor(i),o=i,d=a.getLeft(o),r=a.getLeft(a.currentSlide),a.currentLeft=null===a.swipeLeft?r:a.swipeLeft,a.options.infinite===!1&&a.options.centerMode===!1&&(i<0||i>a.getDotCount()*a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):a.options.infinite===!1&&a.options.centerMode===!0&&(i<0||i>a.slideCount-a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):(a.options.autoplay&&clearInterval(a.autoPlayTimer),s=o<0?a.slideCount%a.options.slidesToScroll!==0?a.slideCount-a.slideCount%a.options.slidesToScroll:a.slideCount+o:o>=a.slideCount?a.slideCount%a.options.slidesToScroll!==0?0:o-a.slideCount:o,a.animating=!0,a.$slider.trigger(\"beforeChange\",[a,a.currentSlide,s]),n=a.currentSlide,a.currentSlide=s,a.setSlideClasses(a.currentSlide),a.options.asNavFor&&(l=a.getNavTarget(),l=l.slick(\"getSlick\"),l.slideCount<=l.options.slidesToShow&&l.setSlideClasses(a.currentSlide)),a.updateDots(),a.updateArrows(),a.options.fade===!0?(t!==!0?(a.fadeSlideOut(n),a.fadeSlide(s,function(){a.postSlide(s)})):a.postSlide(s),void a.animateHeight()):void(t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(d,function(){a.postSlide(s)}):a.postSlide(s)))},e.prototype.startLoad=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.hide(),i.$nextArrow.hide()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.hide(),i.$slider.addClass(\"slick-loading\")},e.prototype.swipeDirection=function(){var i,e,t,o,s=this;return i=s.touchObject.startX-s.touchObject.curX,e=s.touchObject.startY-s.touchObject.curY,t=Math.atan2(e,i),o=Math.round(180*t/Math.PI),o<0&&(o=360-Math.abs(o)),o<=45&&o>=0?s.options.rtl===!1?\"left\":\"right\":o<=360&&o>=315?s.options.rtl===!1?\"left\":\"right\":o>=135&&o<=225?s.options.rtl===!1?\"right\":\"left\":s.options.verticalSwiping===!0?o>=35&&o<=135?\"down\":\"up\":\"vertical\"},e.prototype.swipeEnd=function(i){var e,t,o=this;if(o.dragging=!1,o.swiping=!1,o.scrolling)return o.scrolling=!1,!1;if(o.interrupted=!1,o.shouldClick=!(o.touchObject.swipeLength>10),void 0===o.touchObject.curX)return!1;if(o.touchObject.edgeHit===!0&&o.$slider.trigger(\"edge\",[o,o.swipeDirection()]),o.touchObject.swipeLength>=o.touchObject.minSwipe){switch(t=o.swipeDirection()){case\"left\":case\"down\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide+o.getSlideCount()):o.currentSlide+o.getSlideCount(),o.currentDirection=0;break;case\"right\":case\"up\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide-o.getSlideCount()):o.currentSlide-o.getSlideCount(),o.currentDirection=1}\"vertical\"!=t&&(o.slideHandler(e),o.touchObject={},o.$slider.trigger(\"swipe\",[o,t]))}else o.touchObject.startX!==o.touchObject.curX&&(o.slideHandler(o.currentSlide),o.touchObject={})},e.prototype.swipeHandler=function(i){var e=this;if(!(e.options.swipe===!1||\"ontouchend\"in document&&e.options.swipe===!1||e.options.draggable===!1&&i.type.indexOf(\"mouse\")!==-1))switch(e.touchObject.fingerCount=i.originalEvent&&void 0!==i.originalEvent.touches?i.originalEvent.touches.length:1,e.touchObject.minSwipe=e.listWidth/e.options.touchThreshold,e.options.verticalSwiping===!0&&(e.touchObject.minSwipe=e.listHeight/e.options.touchThreshold),i.data.action){case\"start\":e.swipeStart(i);break;case\"move\":e.swipeMove(i);break;case\"end\":e.swipeEnd(i)}},e.prototype.swipeMove=function(i){var e,t,o,s,n,r,l=this;return n=void 0!==i.originalEvent?i.originalEvent.touches:null,!(!l.dragging||l.scrolling||n&&1!==n.length)&&(e=l.getLeft(l.currentSlide),l.touchObject.curX=void 0!==n?n[0].pageX:i.clientX,l.touchObject.curY=void 0!==n?n[0].pageY:i.clientY,l.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(l.touchObject.curX-l.touchObject.startX,2))),r=Math.round(Math.sqrt(Math.pow(l.touchObject.curY-l.touchObject.startY,2))),!l.options.verticalSwiping&&!l.swiping&&r>4?(l.scrolling=!0,!1):(l.options.verticalSwiping===!0&&(l.touchObject.swipeLength=r),t=l.swipeDirection(),void 0!==i.originalEvent&&l.touchObject.swipeLength>4&&(l.swiping=!0,i.preventDefault()),s=(l.options.rtl===!1?1:-1)*(l.touchObject.curX>l.touchObject.startX?1:-1),l.options.verticalSwiping===!0&&(s=l.touchObject.curY>l.touchObject.startY?1:-1),o=l.touchObject.swipeLength,l.touchObject.edgeHit=!1,l.options.infinite===!1&&(0===l.currentSlide&&\"right\"===t||l.currentSlide>=l.getDotCount()&&\"left\"===t)&&(o=l.touchObject.swipeLength*l.options.edgeFriction,l.touchObject.edgeHit=!0),l.options.vertical===!1?l.swipeLeft=e+o*s:l.swipeLeft=e+o*(l.$list.height()/l.listWidth)*s,l.options.verticalSwiping===!0&&(l.swipeLeft=e+o*s),l.options.fade!==!0&&l.options.touchMove!==!1&&(l.animating===!0?(l.swipeLeft=null,!1):void l.setCSS(l.swipeLeft))))},e.prototype.swipeStart=function(i){var e,t=this;return t.interrupted=!0,1!==t.touchObject.fingerCount||t.slideCount<=t.options.slidesToShow?(t.touchObject={},!1):(void 0!==i.originalEvent&&void 0!==i.originalEvent.touches&&(e=i.originalEvent.touches[0]),t.touchObject.startX=t.touchObject.curX=void 0!==e?e.pageX:i.clientX,t.touchObject.startY=t.touchObject.curY=void 0!==e?e.pageY:i.clientY,void(t.dragging=!0))},e.prototype.unfilterSlides=e.prototype.slickUnfilter=function(){var i=this;null!==i.$slidesCache&&(i.unload(),i.$slideTrack.children(this.options.slide).detach(),i.$slidesCache.appendTo(i.$slideTrack),i.reinit())},e.prototype.unload=function(){var e=this;i(\".slick-cloned\",e.$slider).remove(),e.$dots&&e.$dots.remove(),e.$prevArrow&&e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.remove(),e.$nextArrow&&e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.remove(),e.$slides.removeClass(\"slick-slide slick-active slick-visible slick-current\").attr(\"aria-hidden\",\"true\").css(\"width\",\"\")},e.prototype.unslick=function(i){var e=this;e.$slider.trigger(\"unslick\",[e,i]),e.destroy()},e.prototype.updateArrows=function(){var i,e=this;i=Math.floor(e.options.slidesToShow/2),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&!e.options.infinite&&(e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),0===e.currentSlide?(e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-e.options.slidesToShow&&e.options.centerMode===!1?(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-1&&e.options.centerMode===!0&&(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")))},e.prototype.updateDots=function(){var i=this;null!==i.$dots&&(i.$dots.find(\"li\").removeClass(\"slick-active\").end(),i.$dots.find(\"li\").eq(Math.floor(i.currentSlide/i.options.slidesToScroll)).addClass(\"slick-active\"))},e.prototype.visibility=function(){var i=this;i.options.autoplay&&(document[i.hidden]?i.interrupted=!0:i.interrupted=!1)},i.fn.slick=function(){var i,t,o=this,s=arguments[0],n=Array.prototype.slice.call(arguments,1),r=o.length;for(i=0;i<r;i++)if(\"object\"==typeof s||\"undefined\"==typeof s?o[i].slick=new e(o[i],s):t=o[i].slick[s].apply(o[i].slick,n),\"undefined\"!=typeof t)return t;return o}});\n","Magento_PageBuilder/js/utils/breakpoints.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    return {\n        /**\n         * Build media query.\n         *\n         * @param {Object} conditions\n         * @returns {String}\n         */\n        buildMedia: function (conditions) {\n            var result = _.map(_.pairs(conditions), function (condition) {\n                return '(' + condition.join(': ') + ')';\n            });\n\n            return result.join(' and ');\n        }\n    };\n});\n","Magento_PageBuilder/js/utils/map.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * googleMaps dependency is added within googlemaps.phtml through shim based on API key being set\n *\n * @api\n */\ndefine([\n    'underscore',\n    'module',\n    'Magento_PageBuilder/js/events'\n], function (_, module, events) {\n    'use strict';\n\n    var google = window.google || {},\n\n        /**\n         * Generates a google map usable latitude and longitude object\n         *\n         * @param {Object} position\n         * @return {google.maps.LatLng}\n         */\n        getGoogleLatitudeLongitude = function (position) {\n            return new google.maps.LatLng(position.latitude, position.longitude);\n        },\n        gmAuthFailure = false;\n\n    // jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n    /**\n     * Google's error listener for map loader failures\n     */\n    window.gm_authFailure = function () {\n        events.trigger('googleMaps:authFailure');\n        gmAuthFailure = true;\n    };\n    // jscs:enable requireCamelCaseOrUpperCaseIdentifiers\n\n    return function (element, markers, additionalOptions) {\n        var options,\n            style;\n\n        // If we've previously had an API key error, throw the error even again\n        if (gmAuthFailure) {\n            events.trigger('googleMaps:authFailure');\n\n            return;\n        }\n\n        // If Google Maps isn't loaded don't try init the map, it won't work\n        if (typeof google.maps === 'undefined') {\n            return;\n        }\n\n        /**\n         * Just in case of a bad JSON that bypassed validation\n         */\n        try {\n            style = module.config().style ? JSON.parse(module.config().style) : [];\n        }\n        catch (error) {\n            style = [];\n        }\n        options = _.extend({\n            zoom: 8,\n            center: getGoogleLatitudeLongitude({\n                latitude: 30.2672,\n                longitude: -97.7431\n            }),\n            scrollwheel: false,\n            disableDoubleClickZoom: false,\n            disableDefaultUI: false,\n            mapTypeControl: true,\n            mapTypeControlOptions: {\n                style: google.maps.MapTypeControlStyle.DEFAULT\n            },\n            styles: style\n        }, additionalOptions);\n\n        /* Create the map */\n        this.map = new google.maps.Map(element, options);\n        this.markers = [];\n\n        /**\n         * Callback function on map config update\n         * @param {Array} newMarkers\n         * @param {Object} updateOptions\n         */\n        this.onUpdate = function (newMarkers, updateOptions) {\n            this.map.setOptions(updateOptions);\n            this.setMarkers(newMarkers);\n        };\n\n        /**\n         * Sets the markers to selected map\n         * @param {Object} newMarkers\n         */\n        this.setMarkers = function (newMarkers) {\n            var activeInfoWindow,\n                latitudeLongitudeBounds = new google.maps.LatLngBounds();\n\n            this.markers.forEach(function (marker) {\n                marker.setMap(null);\n            }, this);\n\n            this.markers = [];\n            this.bounds = [];\n\n            /**\n             * Creates and set listener for markers\n             */\n            if (newMarkers && newMarkers.length) {\n                newMarkers.forEach(function (newMarker) {\n                    var location = _.escape(newMarker['location_name']) || '',\n                    comment = newMarker.comment ?\n                        '<p>' + _.escape(newMarker.comment).replace(/(?:\\r\\n|\\r|\\n)/g, '<br/>') + '</p>'\n                        : '',\n                    phone = newMarker.phone ? '<p>Phone: ' + _.escape(newMarker.phone) + '</p>' : '',\n                    address = newMarker.address ? _.escape(newMarker.address) + '<br/>' : '',\n                    city = _.escape(newMarker.city) || '',\n                    country = newMarker.country ? _.escape(newMarker.country) : '',\n                    state = newMarker.state ? _.escape(newMarker.state) + ' ' : '',\n                    zipCode = newMarker.zipcode ? _.escape(newMarker.zipcode) : '',\n                    cityComma = city !== '' && (zipCode !== '' || state !== '') ? ', ' : '',\n                    lineBreak = city !== '' || zipCode !== '' ? '<br/>' : '',\n                    contentString =\n                        '<div>' +\n                        '<h3><b>' + location + '</b></h3>' +\n                        comment +\n                        phone +\n                        '<p><span>' + address +\n                        city + cityComma + state + zipCode + lineBreak +\n                        country + '</span></p>' +\n                        '</div>',\n                    infowindow = new google.maps.InfoWindow({\n                        content: contentString,\n                        maxWidth: 350\n                    }),\n                    newCreatedMarker = new google.maps.Marker({\n                        map: this.map,\n                        position: getGoogleLatitudeLongitude(newMarker.position),\n                        title: location\n                    });\n\n                    if (location) {\n                        newCreatedMarker.addListener('click', function () {\n                            if (activeInfoWindow) {\n                                activeInfoWindow.close();\n                            }\n\n                            infowindow.open(this.map, newCreatedMarker);\n                            activeInfoWindow = infowindow;\n                        }, this);\n                    }\n\n                    this.markers.push(newCreatedMarker);\n                    this.bounds.push(getGoogleLatitudeLongitude(newMarker.position));\n                }, this);\n            }\n\n            /**\n             * This sets the bounds of the map for multiple locations\n             */\n            if (this.bounds.length > 1) {\n                this.bounds.forEach(function (bound) {\n                    latitudeLongitudeBounds.extend(bound);\n                });\n                this.map.fitBounds(latitudeLongitudeBounds);\n            }\n\n            /**\n             * Zoom to 8 if there is only a single location\n             */\n            if (this.bounds.length === 1) {\n                this.map.setCenter(this.bounds[0]);\n                this.map.setZoom(8);\n            }\n        };\n\n        this.setMarkers(markers);\n    };\n});\n","Magento_SalesRule/js/form/element/manage-coupon-codes.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'uiRegistry',\n    'Magento_Ui/js/form/components/fieldset',\n    'Magento_Ui/js/lib/view/utils/async'\n], function (_, uiRegistry, fieldset, async) {\n    'use strict';\n\n    return fieldset.extend({\n\n        /*eslint-disable no-unused-vars*/\n        /**\n         * Initialize element\n         *\n         * @returns {Abstract} Chainable\n         */\n        initialize: function (elems, position) {\n            var obj = this;\n\n            this._super();\n\n            async.async('#sales-rule-form-tab-coupons', document.getElementById('container'), function (node) {\n                var useAutoGeneration = uiRegistry.get(\n                    'sales_rule_form.sales_rule_form.rule_information.use_auto_generation'\n                );\n\n                useAutoGeneration.on('checked', function () {\n                    obj.enableDisableFields();\n                });\n                obj.enableDisableFields();\n            });\n\n            return this;\n        },\n\n        /*eslint-enable no-unused-vars*/\n        /*eslint-disable lines-around-comment*/\n\n        /**\n         * Enable/disable fields on Coupons tab\n         */\n        enableDisableFields: function () {\n            var selector,\n                isUseAutoGenerationChecked,\n                couponType,\n                disableAuto;\n\n            selector = '[id=sales-rule-form-tab-coupons] input, [id=sales-rule-form-tab-coupons] select, ' +\n                    '[id=sales-rule-form-tab-coupons] button';\n            isUseAutoGenerationChecked = uiRegistry\n                    .get('sales_rule_form.sales_rule_form.rule_information.use_auto_generation')\n                    .checked();\n            couponType = uiRegistry\n                .get('sales_rule_form.sales_rule_form.rule_information.coupon_type')\n                .value();\n            /**\n             * \\Magento\\Rule\\Model\\AbstractModel::COUPON_TYPE_AUTO\n             */\n            disableAuto = couponType === 3 || isUseAutoGenerationChecked;\n            _.each(\n                document.querySelectorAll(selector),\n                function (element) {\n                    element.disabled = !disableAuto;\n                }\n            );\n        }\n    });\n});\n","Magento_SalesRule/js/form/element/coupon-type.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'uiRegistry',\n    'Magento_Ui/js/form/element/select'\n], function (_, uiRegistry, select) {\n    'use strict';\n\n    return select.extend({\n\n        /**\n         * Hide fields on coupon tab\n         */\n        onUpdate: function () {\n\n            /* eslint-disable eqeqeq */\n            if (this.value() != this.displayOnlyForCouponType) {\n                uiRegistry.get('sales_rule_form.sales_rule_form.rule_information.use_auto_generation').checked(false);\n            }\n\n            this.enableDisableFields();\n        },\n\n        /**\n         * Enable/disable fields on Coupons tab\n         */\n        enableDisableFields: function () {\n            var selector,\n                isUseAutoGenerationChecked,\n                couponType,\n                disableAuto;\n\n            selector = '[id=sales-rule-form-tab-coupons] input, [id=sales-rule-form-tab-coupons] select, ' +\n                    '[id=sales-rule-form-tab-coupons] button';\n            isUseAutoGenerationChecked = uiRegistry\n                    .get('sales_rule_form.sales_rule_form.rule_information.use_auto_generation')\n                    .checked();\n            couponType = uiRegistry\n                .get('sales_rule_form.sales_rule_form.rule_information.coupon_type')\n                .value();\n            disableAuto = couponType === 3 || isUseAutoGenerationChecked;\n            _.each(\n                document.querySelectorAll(selector),\n                function (element) {\n                    element.disabled = !disableAuto;\n                }\n            );\n        }\n    });\n});\n","Magento_SalesRule/js/view/cart/totals/discount.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_SalesRule/js/view/summary/discount'\n], function (Component) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_SalesRule/cart/totals/discount'\n        },\n\n        /**\n         * @override\n         *\n         * @returns {Boolean}\n         */\n        isDisplayed: function () {\n            return this.getPureValue() != 0; //eslint-disable-line eqeqeq\n        }\n    });\n});\n","Magento_SalesRule/js/view/payment/discount-messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Ui/js/view/messages',\n    '../../model/payment/discount-messages'\n], function (Component, messageContainer) {\n    'use strict';\n\n    return Component.extend({\n        /** @inheritdoc */\n        initialize: function (config) {\n            return this._super(config, messageContainer);\n        }\n    });\n});\n","Magento_SalesRule/js/view/payment/captcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n        'Magento_Captcha/js/view/checkout/defaultCaptcha',\n        'Magento_Captcha/js/model/captchaList',\n        'Magento_SalesRule/js/action/set-coupon-code',\n        'Magento_SalesRule/js/action/cancel-coupon',\n        'Magento_Checkout/js/model/quote',\n        'ko'\n    ],\n    function (defaultCaptcha, captchaList, setCouponCodeAction, cancelCouponAction, quote, ko) {\n        'use strict';\n\n        var totals = quote.getTotals(),\n            couponCode = ko.observable(null),\n            isApplied;\n\n        if (totals()) {\n            couponCode(totals()['coupon_code']);\n        }\n        //Captcha can only be required for adding a coupon so we need to know if one was added already.\n        isApplied = ko.observable(couponCode() != null);\n\n        return defaultCaptcha.extend({\n            /** @inheritdoc */\n            initialize: function () {\n                var self = this,\n                    currentCaptcha;\n\n                this._super();\n                //Getting coupon captcha model.\n                currentCaptcha = captchaList.getCaptchaByFormId(this.formId);\n\n                if (currentCaptcha != null) {\n                    if (!isApplied()) {\n                        //Show captcha if we don't have a coupon applied.\n                        currentCaptcha.setIsVisible(true);\n                    }\n                    this.setCurrentCaptcha(currentCaptcha);\n                    //Add captcha code to coupon-apply request.\n                    setCouponCodeAction.registerDataModifier(function (headers) {\n                        if (self.isRequired()) {\n                            headers['X-Captcha'] = self.captchaValue()();\n                        }\n                    });\n                    //Refresh captcha after failed request.\n                    setCouponCodeAction.registerFailCallback(function () {\n                        if (self.isRequired()) {\n                            self.refresh();\n                        }\n                    });\n                    //Hide captcha when a coupon has been applied.\n                    setCouponCodeAction.registerSuccessCallback(function () {\n                        self.setIsVisible(false);\n                    });\n                    //Show captcha again if it was canceled.\n                    cancelCouponAction.registerSuccessCallback(function () {\n                        if (self.isRequired()) {\n                            self.setIsVisible(true);\n                        }\n                    });\n                }\n            }\n        });\n    });\n","Magento_SalesRule/js/view/payment/discount.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'ko',\n    'uiComponent',\n    'Magento_Checkout/js/model/quote',\n    'Magento_SalesRule/js/action/set-coupon-code',\n    'Magento_SalesRule/js/action/cancel-coupon',\n    'Magento_SalesRule/js/model/coupon'\n], function ($, ko, Component, quote, setCouponCodeAction, cancelCouponAction, coupon) {\n    'use strict';\n\n    var totals = quote.getTotals(),\n        couponCode = coupon.getCouponCode(),\n        isApplied = coupon.getIsApplied();\n\n    if (totals()) {\n        couponCode(totals()['coupon_code']);\n    }\n    isApplied(couponCode() != null);\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_SalesRule/payment/discount'\n        },\n        couponCode: couponCode,\n\n        /**\n         * Applied flag\n         */\n        isApplied: isApplied,\n\n        /**\n         * Coupon code application procedure\n         */\n        apply: function () {\n            if (this.validate()) {\n                setCouponCodeAction(couponCode(), isApplied);\n            }\n        },\n\n        /**\n         * Cancel using coupon\n         */\n        cancel: function () {\n            if (this.validate()) {\n                couponCode('');\n                cancelCouponAction(isApplied);\n            }\n        },\n\n        /**\n         * Coupon form validation\n         *\n         * @returns {Boolean}\n         */\n        validate: function () {\n            var form = '#discount-form';\n\n            return $(form).validation() && $(form).validation('isValid');\n        }\n    });\n});\n","Magento_SalesRule/js/view/summary/discount.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Checkout/js/view/summary/abstract-total',\n    'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_SalesRule/summary/discount'\n        },\n        totals: quote.getTotals(),\n\n        /**\n         * @return {*|Boolean}\n         */\n        isDisplayed: function () {\n            return this.isFullMode() && this.getPureValue() != 0; //eslint-disable-line eqeqeq\n        },\n\n        /**\n         * @return {*}\n         */\n        getCouponCode: function () {\n            if (!this.totals()) {\n                return null;\n            }\n\n            return this.totals()['coupon_code'];\n        },\n\n        /**\n         * @return {*}\n         */\n        getCouponLabel: function () {\n            if (!this.totals()) {\n                return null;\n            }\n\n            return this.totals()['coupon_label'];\n        },\n\n        /**\n         * Get discount title\n         *\n         * @returns {null|String}\n         */\n        getTitle: function () {\n            var discountSegments;\n\n            if (!this.totals()) {\n                return null;\n            }\n\n            discountSegments = this.totals()['total_segments'].filter(function (segment) {\n                return segment.code.indexOf('discount') !== -1;\n            });\n\n            return discountSegments.length ? discountSegments[0].title : null;\n        },\n\n        /**\n         * @return {Number}\n         */\n        getPureValue: function () {\n            var price = 0;\n\n            if (this.totals() && this.totals()['discount_amount']) {\n                price = parseFloat(this.totals()['discount_amount']);\n            }\n\n            return price;\n        },\n\n        /**\n         * @return {*|String}\n         */\n        getValue: function () {\n            return this.getFormattedPrice(this.getPureValue());\n        }\n    });\n});\n","Magento_SalesRule/js/action/select-payment-method-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'mage/utils/wrapper',\n    'Magento_Checkout/js/model/quote',\n    'Magento_SalesRule/js/model/payment/discount-messages',\n    'Magento_Checkout/js/action/set-payment-information-extended',\n    'Magento_Checkout/js/action/get-totals',\n    'Magento_SalesRule/js/model/coupon'\n], function ($, wrapper, quote, messageContainer, setPaymentInformationExtended, getTotalsAction, coupon) {\n    'use strict';\n\n    return function (selectPaymentMethodAction) {\n\n        return wrapper.wrap(selectPaymentMethodAction, function (originalSelectPaymentMethodAction, paymentMethod) {\n\n            originalSelectPaymentMethodAction(paymentMethod);\n\n            if (paymentMethod === null) {\n                return;\n            }\n\n            $.when(\n                setPaymentInformationExtended(\n                    messageContainer,\n                    {\n                        method: paymentMethod.method\n                    },\n                    true\n                )\n            ).done(\n                function () {\n                    var deferred = $.Deferred(),\n\n                        /**\n                         * Update coupon form.\n                         */\n                        updateCouponCallback = function () {\n                            if (quote.totals() && !quote.totals()['coupon_code']) {\n                                coupon.setCouponCode('');\n                                coupon.setIsApplied(false);\n                            }\n                        };\n\n                    getTotalsAction([], deferred);\n                    $.when(deferred).done(updateCouponCallback);\n                }\n            );\n        });\n    };\n\n});\n","Magento_SalesRule/js/action/set-coupon-code.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Customer store credit(balance) application\n */\ndefine([\n    'ko',\n    'jquery',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/resource-url-manager',\n    'Magento_Checkout/js/model/error-processor',\n    'Magento_SalesRule/js/model/payment/discount-messages',\n    'mage/storage',\n    'mage/translate',\n    'Magento_Checkout/js/action/get-payment-information',\n    'Magento_Checkout/js/model/totals',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Checkout/js/action/recollect-shipping-rates'\n], function (ko, $, quote, urlManager, errorProcessor, messageContainer, storage, $t, getPaymentInformationAction,\n    totals, fullScreenLoader, recollectShippingRates\n) {\n    'use strict';\n\n    var dataModifiers = [],\n        successCallbacks = [],\n        failCallbacks = [],\n        action;\n\n    /**\n     * Apply provided coupon.\n     *\n     * @param {String} couponCode\n     * @param {Boolean}isApplied\n     * @returns {Deferred}\n     */\n    action = function (couponCode, isApplied) {\n        var quoteId = quote.getQuoteId(),\n            url = urlManager.getApplyCouponUrl(couponCode, quoteId),\n            message = $t('Your coupon was successfully applied.'),\n            data = {},\n            headers = {};\n\n        //Allowing to modify coupon-apply request\n        dataModifiers.forEach(function (modifier) {\n            modifier(headers, data);\n        });\n        fullScreenLoader.startLoader();\n\n        return storage.put(\n            url,\n            data,\n            false,\n            null,\n            headers\n        ).done(function (response) {\n            var deferred;\n\n            if (response) {\n                deferred = $.Deferred();\n\n                isApplied(true);\n                totals.isLoading(true);\n                recollectShippingRates();\n                getPaymentInformationAction(deferred);\n                $.when(deferred).done(function () {\n                    fullScreenLoader.stopLoader();\n                    totals.isLoading(false);\n                });\n                messageContainer.addSuccessMessage({\n                    'message': message\n                });\n                //Allowing to tap into apply-coupon process.\n                successCallbacks.forEach(function (callback) {\n                    callback(response);\n                });\n            }\n        }).fail(function (response) {\n            fullScreenLoader.stopLoader();\n            totals.isLoading(false);\n            errorProcessor.process(response, messageContainer);\n            //Allowing to tap into apply-coupon process.\n            failCallbacks.forEach(function (callback) {\n                callback(response);\n            });\n        });\n    };\n\n    /**\n     * Modifying data to be sent.\n     *\n     * @param {Function} modifier\n     */\n    action.registerDataModifier = function (modifier) {\n        dataModifiers.push(modifier);\n    };\n\n    /**\n     * When successfully added a coupon.\n     *\n     * @param {Function} callback\n     */\n    action.registerSuccessCallback = function (callback) {\n        successCallbacks.push(callback);\n    };\n\n    /**\n     * When failed to add a coupon.\n     *\n     * @param {Function} callback\n     */\n    action.registerFailCallback = function (callback) {\n        failCallbacks.push(callback);\n    };\n\n    return action;\n});\n","Magento_SalesRule/js/action/cancel-coupon.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Customer store credit(balance) application\n */\ndefine([\n    'jquery',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/resource-url-manager',\n    'Magento_Checkout/js/model/error-processor',\n    'Magento_SalesRule/js/model/payment/discount-messages',\n    'mage/storage',\n    'Magento_Checkout/js/action/get-payment-information',\n    'Magento_Checkout/js/model/totals',\n    'mage/translate',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Checkout/js/action/recollect-shipping-rates'\n], function ($, quote, urlManager, errorProcessor, messageContainer, storage, getPaymentInformationAction, totals, $t,\n  fullScreenLoader, recollectShippingRates\n) {\n    'use strict';\n\n    var successCallbacks = [],\n        action,\n        callSuccessCallbacks;\n\n    /**\n     * Execute callbacks when a coupon is successfully canceled.\n     */\n    callSuccessCallbacks = function () {\n        successCallbacks.forEach(function (callback) {\n            callback();\n        });\n    };\n\n    /**\n     * Cancel applied coupon.\n     *\n     * @param {Boolean} isApplied\n     * @returns {Deferred}\n     */\n    action =  function (isApplied) {\n        var quoteId = quote.getQuoteId(),\n            url = urlManager.getCancelCouponUrl(quoteId),\n            message = $t('Your coupon was successfully removed.');\n\n        messageContainer.clear();\n        fullScreenLoader.startLoader();\n\n        return storage.delete(\n            url,\n            false\n        ).done(function () {\n            var deferred = $.Deferred();\n\n            totals.isLoading(true);\n            recollectShippingRates();\n            getPaymentInformationAction(deferred);\n            $.when(deferred).done(function () {\n                isApplied(false);\n                totals.isLoading(false);\n                fullScreenLoader.stopLoader();\n                //Allowing to tap into coupon-cancel process.\n                callSuccessCallbacks();\n            });\n            messageContainer.addSuccessMessage({\n                'message': message\n            });\n        }).fail(function (response) {\n            totals.isLoading(false);\n            fullScreenLoader.stopLoader();\n            errorProcessor.process(response, messageContainer);\n        });\n    };\n\n    /**\n     * Callback for when the cancel-coupon process is finished.\n     *\n     * @param {Function} callback\n     */\n    action.registerSuccessCallback = function (callback) {\n        successCallbacks.push(callback);\n    };\n\n    return action;\n});\n","Magento_SalesRule/js/model/shipping-save-processor-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'mage/utils/wrapper',\n    'Magento_Checkout/js/model/quote',\n    'Magento_SalesRule/js/model/coupon'\n], function (wrapper, quote, coupon) {\n    'use strict';\n\n    return function (shippingSaveProcessor) {\n        shippingSaveProcessor.saveShippingInformation = wrapper.wrapSuper(\n            shippingSaveProcessor.saveShippingInformation,\n            function (type) {\n                var updateCouponCallback;\n\n                /**\n                 * Update coupon form\n                 */\n                updateCouponCallback = function () {\n                    if (quote.totals() && !quote.totals()['coupon_code']) {\n                        coupon.setCouponCode('');\n                        coupon.setIsApplied(false);\n                    }\n                };\n\n                return this._super(type).done(updateCouponCallback);\n            }\n        );\n\n        return shippingSaveProcessor;\n    };\n});\n","Magento_SalesRule/js/model/place-order-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'mage/utils/wrapper',\n    'Magento_Checkout/js/model/quote',\n    'Magento_SalesRule/js/model/coupon',\n    'Magento_Checkout/js/action/get-totals'\n], function ($, wrapper, quote, coupon, getTotalsAction) {\n    'use strict';\n\n    return function (placeOrderAction) {\n        return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, messageContainer) {\n            var result;\n\n            $.when(\n                result = originalAction(paymentData, messageContainer)\n            ).fail(\n                function () {\n                    var deferred = $.Deferred(),\n\n                        /**\n                         * Update coupon form\n                         */\n                        updateCouponCallback = function () {\n                            if (quote.totals() && !quote.totals()['coupon_code']) {\n                                coupon.setCouponCode('');\n                                coupon.setIsApplied(false);\n                            }\n                        };\n\n                    getTotalsAction([], deferred);\n                    $.when(deferred).done(updateCouponCallback);\n                }\n            );\n\n            return result;\n        });\n    };\n});\n","Magento_SalesRule/js/model/coupon.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * Coupon model.\n */\ndefine([\n    'ko',\n    'domReady!'\n], function (ko) {\n    'use strict';\n\n    var couponCode = ko.observable(null),\n        isApplied = ko.observable(null);\n\n    return {\n        couponCode: couponCode,\n        isApplied: isApplied,\n\n        /**\n         * @return {*}\n         */\n        getCouponCode: function () {\n            return couponCode;\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        getIsApplied: function () {\n            return isApplied;\n        },\n\n        /**\n         * @param {*} couponCodeValue\n         */\n        setCouponCode: function (couponCodeValue) {\n            couponCode(couponCodeValue);\n        },\n\n        /**\n         * @param {Boolean} isAppliedValue\n         */\n        setIsApplied: function (isAppliedValue) {\n            isApplied(isAppliedValue);\n        }\n    };\n});\n","Magento_SalesRule/js/model/payment/discount-messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Ui/js/model/messages'\n], function (Messages) {\n    'use strict';\n\n    return new Messages();\n});\n","PayPal_Braintree/js/form-builder.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(\n    [\n        'jquery',\n        'underscore',\n        'mage/template'\n    ],\n    function ($, _, mageTemplate) {\n        'use strict';\n\n        return {\n\n            /**\n             * @param {Object} formData\n             * @returns {*|jQuery}\n             */\n            build: function (formData) {\n                var formTmpl = mageTemplate('<form action=\"<%= data.action %>\"' +\n                    ' method=\"POST\" hidden enctype=\"application/x-www-form-urlencoded\">' +\n                        '<% _.each(data.fields, function(val, key){ %>' +\n                            '<input value=\\'<%= val %>\\' name=\"<%= key %>\" type=\"hidden\">' +\n                        '<% }); %>' +\n                    '</form>');\n\n                return $(formTmpl({\n                    data: {\n                        action: formData.action,\n                        fields: formData.fields\n                    }\n                })).appendTo($('[data-container=\"body\"]'));\n            }\n        };\n    }\n);\n","PayPal_Braintree/js/validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    return {\n        config: {},\n\n        /**\n         * Set configuration\n         * @param {Object} config\n         */\n        setConfig: function (config) {\n            this.config = config;\n        },\n\n        /**\n         * Get List of available card types\n         * @returns {*|exports.defaults.availableCardTypes|{}}\n         */\n        getAvailableCardTypes: function () {\n            return this.config.availableCardTypes;\n        },\n\n        /**\n         * Get list of card types\n         * @returns {Object}\n         */\n        getCcTypesMapper: function () {\n            return this.config.ccTypesMapper;\n        },\n\n        /**\n         * Find mage card type by Braintree type\n         * @param {String} type\n         * @param {Object} availableTypes\n         * @returns {*}\n         */\n        getMageCardType: function (type, availableTypes) {\n            var storedCardType = null,\n                mapper = this.getCcTypesMapper();\n\n            if (type && typeof mapper[type] !== 'undefined') {\n                storedCardType = mapper[type];\n\n                if (_.indexOf(availableTypes, storedCardType) !== -1) {\n                    return storedCardType;\n                }\n            }\n\n            return null;\n        },\n\n        /**\n         * Filter list of available card types\n         * @param {Object} availableTypes\n         * @param {Object} countrySpecificCardTypes\n         * @returns {Object}\n         */\n        collectTypes: function (availableTypes, countrySpecificCardTypes) {\n            var key,\n                filteredTypes = [];\n\n            for (key in availableTypes) {\n                if (_.indexOf(countrySpecificCardTypes, availableTypes[key]) !== -1) {\n                    filteredTypes.push(availableTypes[key]);\n                }\n            }\n\n            return filteredTypes;\n        },\n\n        /**\n         * Get list of card types for country\n         * @param {String} countryId\n         * @returns {*}\n         */\n        getCountrySpecificCardTypes: function (countryId) {\n            if (typeof this.config.countrySpecificCardTypes[countryId] !== 'undefined') {\n                return this.config.countrySpecificCardTypes[countryId];\n            }\n\n            return false;\n        }\n    };\n});\n","PayPal_Braintree/js/view/product-page.js":"define(\n    ['uiComponent'],\n    function (Component) {\n        'use strict';\n\n        return Component.extend({\n\n        });\n    }\n);","PayPal_Braintree/js/view/payment/venmo.js":"define(\n    [\n        'uiComponent',\n        'Magento_Checkout/js/model/payment/renderer-list'\n    ],\n    function (\n        Component,\n        rendererList\n    ) {\n        'use strict';\n\n        rendererList.push(\n            {\n                type: 'braintree_venmo',\n                component: 'PayPal_Braintree/js/view/payment/method-renderer/venmo'\n            }\n        );\n\n        return Component.extend({});\n    }\n);\n","PayPal_Braintree/js/view/payment/braintree.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n    'use strict';\n\n    let config = window.checkoutConfig.payment,\n        braintreeType = 'braintree',\n        payPalType = 'braintree_paypal',\n        braintreeAchDirectDebit = 'braintree_ach_direct_debit',\n        braintreeVenmo = 'braintree_venmo',\n        braintreeLocalPayment = 'braintree_local_payment';\n\n    if (config[braintreeType] && config[braintreeType].isActive && config[braintreeType].clientToken) {\n        rendererList.push({\n            type: braintreeType,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/hosted-fields'\n        });\n    }\n\n    if (config[payPalType] && config[payPalType].isActive) {\n        rendererList.push({\n            type: payPalType,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/paypal'\n        });\n    }\n\n    if (config[braintreeVenmo] && config[braintreeVenmo].isAllowed && config[braintreeVenmo].clientToken) {\n        rendererList.push({\n            type: braintreeVenmo,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/venmo'\n        });\n    }\n\n    if (config[braintreeAchDirectDebit] && config[braintreeAchDirectDebit].isActive && config[braintreeAchDirectDebit].clientToken) {\n        rendererList.push({\n            type: braintreeAchDirectDebit,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/ach'\n        });\n    }\n\n    if (config[braintreeLocalPayment] && config[braintreeLocalPayment].clientToken) {\n        rendererList.push({\n            type: braintreeLocalPayment,\n            component: 'PayPal_Braintree/js/view/payment/method-renderer/lpm'\n        });\n    }\n\n    /** Add view logic here if needed */\n    return Component.extend({});\n});\n","PayPal_Braintree/js/view/payment/validator-handler.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\n\ndefine([\n    'jquery',\n    'Magento_Ui/js/model/messageList',\n    'PayPal_Braintree/js/view/payment/3d-secure',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function ($, globalMessageList, verify3DSecure, fullScreenLoader) {\n    'use strict';\n\n    return {\n        validators: [],\n\n        /**\n         * Get payment config\n         * @returns {Object}\n         */\n        getConfig: function () {\n            return window.checkoutConfig.payment;\n        },\n\n        /**\n         * Init list of validators\n         */\n        initialize: function () {\n            var config = this.getConfig();\n\n            if (config[verify3DSecure.getCode()].enabled) {\n                verify3DSecure.setConfig(config[verify3DSecure.getCode()]);\n                this.add(verify3DSecure);\n            }\n        },\n\n        /**\n         * Add new validator\n         * @param {Object} validator\n         */\n        add: function (validator) {\n            this.validators.push(validator);\n        },\n\n        /**\n         * Run pull of validators\n         * @param {Object} context\n         * @param {Function} callback\n         */\n        validate: function (context, callback, errorCallback) {\n            var self = this,\n                deferred;\n\n            // no available validators\n            if (!self.validators.length) {\n                callback();\n\n                return;\n            }\n\n            // get list of deferred validators\n            deferred = $.map(self.validators, function (current) {\n                return current.validate(context);\n            });\n\n            $.when.apply($, deferred)\n                .done(function () {\n                    callback();\n                }).fail(function (error) {\n                    errorCallback();\n                    self.showError(error);\n                });\n        },\n\n        /**\n         * Show error message\n         * @param {String} errorMessage\n         */\n        showError: function (errorMessage) {\n            globalMessageList.addErrorMessage({\n                message: errorMessage\n            });\n            fullScreenLoader.stopLoader(true);\n        }\n    };\n});\n","PayPal_Braintree/js/view/payment/ach.js":"define(\n    [\n        'uiComponent',\n        'Magento_Checkout/js/model/payment/renderer-list'\n    ],\n    function (\n        Component,\n        rendererList\n    ) {\n        'use strict';\n\n        rendererList.push(\n            {\n                type: 'braintree_ach_direct_debit',\n                component: 'PayPal_Braintree/js/view/payment/method-renderer/ach'\n            }\n        );\n\n        return Component.extend({});\n    }\n);\n","PayPal_Braintree/js/view/payment/3d-secure.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\n\ndefine([\n    'jquery',\n    'PayPal_Braintree/js/view/payment/adapter',\n    'Magento_Checkout/js/model/quote',\n    'mage/translate',\n    'braintreeThreeDSecure',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function ($, braintree, quote, $t, threeDSecure, fullScreenLoader) {\n    'use strict';\n\n    return {\n        config: null,\n\n        /**\n         * Set 3d secure config\n         * @param {Object} config\n         */\n        setConfig: function (config) {\n            this.config = config;\n            this.config.thresholdAmount = parseFloat(config.thresholdAmount);\n        },\n\n        /**\n         * Get code\n         * @returns {String}\n         */\n        getCode: function () {\n            return 'three_d_secure';\n        },\n\n        /**\n         * convert Non-ASCII characters into unicode\n         * @param str\n         * @returns {string}\n         */\n        escapeNonAsciiCharacters: function (str) {\n            return str.split(\"\").map(function (c) { return /[^\\x00-\\x7F]$/.test(c) ? c : c.split(\"\").map(function (a) { return \"\\\\u00\" + a.charCodeAt().toString(16)}).join(\"\")}).join(\"\");\n        },\n\n        /**\n         * Validate Braintree payment nonce\n         * @param {Object} context\n         * @returns {Object}\n         */\n        validate: function (context) {\n            let clientInstance = braintree.getApiClient(),\n                state = $.Deferred(),\n                totalAmount = parseFloat(quote.totals()['base_grand_total']).toFixed(2),\n                billingAddress = quote.billingAddress();\n\n            if (billingAddress.regionCode == null) {\n                billingAddress.regionCode = undefined;\n            }\n\n            if (billingAddress.regionCode !== undefined && billingAddress.regionCode.length > 2) {\n                billingAddress.regionCode = undefined;\n            }\n\n            // No 3d secure if using CVV verification on vaulted cards\n            if (quote.paymentMethod().method.indexOf('braintree_cc_vault_') !== -1) {\n                if (this.config.useCvvVault === true) {\n                    state.resolve();\n                    return state.promise();\n                }\n            }\n\n            if (!this.isAmountAvailable(totalAmount) || !this.isCountryAvailable(billingAddress.countryId)) {\n                state.resolve();\n                return state.promise();\n            }\n\n            let firstName = this.escapeNonAsciiCharacters(billingAddress.firstname);\n            let lastName = this.escapeNonAsciiCharacters(billingAddress.lastname);\n\n            let challengeRequested = this.getChallengeRequested();\n\n            fullScreenLoader.startLoader();\n\n            let setup3d = function(clientInstance) {\n                threeDSecure.create({\n                    version: 2,\n                    client: clientInstance\n                }, function (threeDSecureErr, threeDSecureInstance) {\n                    if (threeDSecureErr) {\n                        fullScreenLoader.stopLoader();\n                        return state.reject($t('Please try again with another form of payment.'));\n                    }\n\n                    let threeDSContainer = document.createElement('div'),\n                        tdMask = document.createElement('div'),\n                        tdFrame = document.createElement('div'),\n                        tdBody = document.createElement('div');\n\n                    threeDSContainer.id = 'braintree-three-d-modal';\n                    tdMask.className =\"bt-mask\";\n                    tdFrame.className =\"bt-modal-frame\";\n                    tdBody.className =\"bt-modal-body\";\n\n                    tdFrame.appendChild(tdBody);\n                    threeDSContainer.appendChild(tdMask);\n                    threeDSContainer.appendChild(tdFrame);\n\n                    threeDSecureInstance.verifyCard({\n                        amount: totalAmount,\n                        nonce: context.paymentMethodNonce,\n                        bin: context.creditCardBin,\n                        challengeRequested: challengeRequested,\n                        billingAddress: {\n                            givenName: firstName,\n                            surname: lastName,\n                            phoneNumber: billingAddress.telephone,\n                            streetAddress: billingAddress.street[0],\n                            extendedAddress: billingAddress.street[1],\n                            locality: billingAddress.city,\n                            region: billingAddress.regionCode,\n                            postalCode: billingAddress.postcode,\n                            countryCodeAlpha2: billingAddress.countryId\n                        },\n                        onLookupComplete: function (data, next) {\n                            next();\n                        },\n                        addFrame: function (err, iframe) {\n                            fullScreenLoader.stopLoader();\n\n                            if (err) {\n                                console.log(\"Unable to verify card over 3D Secure\", err);\n                                return state.reject($t('Please try again with another form of payment.'));\n                            }\n\n                            tdBody.appendChild(iframe);\n                            document.body.appendChild(threeDSContainer);\n                        },\n                        removeFrame: function () {\n                            fullScreenLoader.startLoader();\n                            document.body.removeChild(threeDSContainer);\n                        }\n                    }, function (err, response) {\n                        fullScreenLoader.stopLoader();\n\n                        if (err) {\n                            console.error(\"3DSecure validation failed\", err);\n                            if (err.code === 'THREEDS_LOOKUP_VALIDATION_ERROR') {\n                                let errorMessage = err.details.originalError.details.originalError.error.message;\n                                if (errorMessage === 'Billing line1 format is invalid.' && billingAddress.street[0].length > 50) {\n                                    return state.reject(\n                                      $t('Billing line1 must be string and less than 50 characters. Please update the address and try again.')\n                                    );\n\n                                } else if (errorMessage === 'Billing line2 format is invalid.' && billingAddress.street[1].length > 50) {\n                                    return state.reject(\n                                      $t('Billing line2 must be string and less than 50 characters. Please update the address and try again.')\n                                    );\n                                }\n                                return state.reject($t(errorMessage));\n                            } else {\n                                return state.reject($t('Please try again with another form of payment.'));\n                            }\n                        }\n\n                        let liability = {\n                            shifted: response.liabilityShifted,\n                            shiftPossible: response.liabilityShiftPossible\n                        };\n\n                        if (liability.shifted || !liability.shifted && !liability.shiftPossible) {\n                            context.paymentMethodNonce = response.nonce;\n                            state.resolve();\n                        } else {\n                            state.reject($t('Please try again with another form of payment.'));\n                        }\n                    });\n                });\n            };\n\n            if (!clientInstance) {\n                require(['PayPal_Braintree/js/view/payment/method-renderer/cc-form'], function(c) {\n                    let config = c.extend({\n                        defaults: {\n                            clientConfig: {\n                                onReady: function() {}\n                            }\n                        }\n                    });\n                    braintree.setConfig(config.defaults.clientConfig);\n                    braintree.setup(setup3d);\n                });\n            } else {\n                setup3d(clientInstance);\n            }\n\n            return state.promise();\n        },\n\n        /**\n         * Check minimal amount for 3d secure activation\n         * @param {Number} amount\n         * @returns {Boolean}\n         */\n        isAmountAvailable: function (amount) {\n            amount = parseFloat(amount.toString());\n\n            return amount >= this.config.thresholdAmount;\n        },\n\n        /**\n         * Check if current country is available for 3d secure\n         * @param {String} countryId\n         * @returns {Boolean}\n         */\n        isCountryAvailable: function (countryId) {\n            let key,\n                specificCountries = this.config.specificCountries;\n\n            // all countries are available\n            if (!specificCountries.length) {\n                return true;\n            }\n\n            for (key in specificCountries) {\n                if (countryId === specificCountries[key]) {\n                    return true;\n                }\n            }\n\n            return false;\n        },\n\n        /**\n         * @returns {Boolean}\n         */\n        getChallengeRequested: function () {\n            return this.config.challengeRequested;\n        }\n    };\n});\n","PayPal_Braintree/js/view/payment/adapter.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n    'jquery',\n    'braintree',\n    'braintreeDataCollector',\n    'braintreeHostedFields',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Ui/js/model/messageList',\n    'mage/translate'\n], function ($, client, dataCollector, hostedFields, fullScreenLoader, globalMessageList, $t) {\n    'use strict';\n\n    return {\n        apiClient: null,\n        config: {},\n        checkout: null,\n        deviceData: null,\n        clientInstance: null,\n        hostedFieldsInstance: null,\n        paypalInstance: null,\n        code: 'braintree',\n\n        /**\n         * {Object}\n         */\n        events: {\n            onClick: null,\n            onCancel: null,\n            onError: null\n        },\n\n        /**\n         * Get Braintree api client\n         * @returns {Object}\n         */\n        getApiClient: function () {\n            return this.clientInstance;\n        },\n\n        /**\n         * Set configuration\n         * @param {Object} config\n         */\n        setConfig: function (config) {\n            this.config = config;\n        },\n\n        /**\n         * Get payment name\n         * @returns {String}\n         */\n        getCode: function () {\n            if (window.checkoutConfig.payment[this.code]) {\n                return this.code;\n            } else {\n                return 'braintree_paypal';\n            }\n        },\n\n        /**\n         * Get client token\n         * @returns {String|*}\n         */\n        getClientToken: function () {\n            return window.checkoutConfig.payment[this.getCode()].clientToken;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getEnvironment: function () {\n            return window.checkoutConfig.payment[this.getCode()].environment;\n        },\n\n        getCurrentCode: function (paypalType = null) {\n            var code = 'braintree_paypal';\n            if (paypalType !== 'paypal') {\n                code = code + '_' + paypalType;\n            }\n            return code;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getColor: function (paypalType = null) {\n            return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.color;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getShape: function (paypalType = null) {\n            return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.shape;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getSize: function (paypalType = null) {\n            return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.size;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getLabel: function (paypalType = null) {\n            return window.checkoutConfig.payment[this.getCurrentCode(paypalType)].style.label;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getBranding: function () {\n            return null;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getFundingIcons: function () {\n            return null;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getDisabledFunding: function () {\n            return window.checkoutConfig.payment[this.getCode()].disabledFunding;\n        },\n\n        /**\n         * Show error message\n         *\n         * @param {String} errorMessage\n         */\n        showError: function (errorMessage) {\n            globalMessageList.addErrorMessage({\n                message: errorMessage\n            });\n            fullScreenLoader.stopLoader(true);\n        },\n\n        /**\n         * Disable submit button\n         */\n        disableButton: function () {\n            // stop any previous shown loaders\n            fullScreenLoader.stopLoader(true);\n            fullScreenLoader.startLoader();\n            $('[data-button=\"place\"]').attr('disabled', 'disabled');\n        },\n\n        /**\n         * Enable submit button\n         */\n        enableButton: function () {\n            $('[data-button=\"place\"]').removeAttr('disabled');\n            fullScreenLoader.stopLoader();\n        },\n\n        /**\n         * Has PayPal been init'd already\n         */\n        getPayPalInstance: function() {\n            if (typeof this.config.paypalInstance !== 'undefined' && this.config.paypalInstance) {\n                return this.config.paypalInstance;\n            }\n\n            return null;\n        },\n\n        setPayPalInstance: function(val) {\n            this.config.paypalInstance = val;\n        },\n\n        /**\n         * Setup Braintree SDK\n         */\n        setup: function (callback) {\n            if (!this.getClientToken()) {\n                this.showError($t('Sorry, but something went wrong.'));\n                return;\n            }\n\n            if (this.clientInstance) {\n                if (typeof this.config.onReady === 'function') {\n                    this.config.onReady(this);\n                }\n\n                if (typeof callback === \"function\") {\n                    callback(this.clientInstance);\n                }\n                return;\n            }\n\n            client.create({\n                authorization: this.getClientToken()\n            }, function (clientErr, clientInstance) {\n                if (clientErr) {\n                    console.error('Braintree Setup Error', clientErr);\n                    return this.showError(\"Sorry, but something went wrong. Please contact the store owner.\");\n                }\n\n                var options = {\n                    client: clientInstance\n                };\n\n                if (typeof this.config.dataCollector === 'object' && typeof this.config.dataCollector.paypal === 'boolean') {\n                    options.paypal = true;\n                }\n\n                dataCollector.create(options, function (err, dataCollectorInstance) {\n                    if (err) {\n                        return console.log(err);\n                    }\n\n                    this.deviceData = dataCollectorInstance.deviceData;\n                    this.config.onDeviceDataReceived(this.deviceData);\n                }.bind(this));\n\n                this.clientInstance = clientInstance;\n\n                if (typeof this.config.onReady === 'function') {\n                    this.config.onReady(this);\n                }\n\n                if (typeof callback === \"function\") {\n                    callback(this.clientInstance);\n                }\n            }.bind(this));\n        },\n\n        /**\n         * Setup hosted fields instance\n         */\n        setupHostedFields: function () {\n            var self = this;\n\n            if (this.hostedFieldsInstance) {\n                this.hostedFieldsInstance.teardown(function () {\n                    this.hostedFieldsInstance = null;\n                    this.setupHostedFields();\n                }.bind(this));\n                return;\n            }\n\n            hostedFields.create({\n                client: this.clientInstance,\n                fields: this.config.hostedFields,\n                styles: {\n                    \"input\": {\n                        \"font-size\": \"14pt\",\n                        \"color\": \"#3A3A3A\"\n                    },\n                    \":focus\": {\n                        \"color\": \"black\"\n                    },\n                    \".valid\": {\n                        \"color\": \"green\"\n                    },\n                    \".invalid\": {\n                        \"color\": \"red\"\n                    }\n                }\n            }, function (createErr, hostedFieldsInstance) {\n                if (createErr) {\n                    self.showError($t(\"Braintree hosted fields could not be initialized. Please contact the store owner.\"));\n                    console.error('Braintree hosted fields error', createErr);\n                    return;\n                }\n\n                this.config.onInstanceReady(hostedFieldsInstance);\n                this.hostedFieldsInstance = hostedFieldsInstance;\n            }.bind(this));\n        },\n\n        tokenizeHostedFields: function () {\n            this.hostedFieldsInstance.tokenize({}, function (tokenizeErr, payload) {\n                if (tokenizeErr) {\n                    switch (tokenizeErr.code) {\n                        case 'HOSTED_FIELDS_FIELDS_EMPTY':\n                            // occurs when none of the fields are filled in\n                            console.error('All fields are empty! Please fill out the form.');\n                            break;\n                        case 'HOSTED_FIELDS_FIELDS_INVALID':\n                            // occurs when certain fields do not pass client side validation\n                            console.error('Some fields are invalid:', tokenizeErr.details.invalidFieldKeys);\n                            break;\n                        case 'HOSTED_FIELDS_TOKENIZATION_FAIL_ON_DUPLICATE':\n                            // occurs when:\n                            //   * the client token used for client authorization was generated\n                            //     with a customer ID and the fail on duplicate payment method\n                            //     option is set to true\n                            //   * the card being tokenized has previously been vaulted (with any customer)\n                            // See: https://developers.braintreepayments.com/reference/request/client-token/generate/#options.fail_on_duplicate_payment_method\n                            console.error('This payment method already exists in your vault.');\n                            break;\n                        case 'HOSTED_FIELDS_TOKENIZATION_CVV_VERIFICATION_FAILED':\n                            // occurs when:\n                            //   * the client token used for client authorization was generated\n                            //     with a customer ID and the verify card option is set to true\n                            //     and you have credit card verification turned on in the Braintree\n                            //     control panel\n                            //   * the cvv does not pass verfication (https://developers.braintreepayments.com/reference/general/testing/#avs-and-cvv/cid-responses)\n                            // See: https://developers.braintreepayments.com/reference/request/client-token/generate/#options.verify_card\n                            console.error('CVV did not pass verification');\n                            break;\n                        case 'HOSTED_FIELDS_FAILED_TOKENIZATION':\n                            // occurs for any other tokenization error on the server\n                            console.error('Tokenization failed server side. Is the card valid?');\n                            break;\n                        case 'HOSTED_FIELDS_TOKENIZATION_NETWORK_ERROR':\n                            // occurs when the Braintree gateway cannot be contacted\n                            console.error('Network error occurred when tokenizing.');\n                            break;\n                        default:\n                            console.error('Something bad happened!', tokenizeErr);\n                    }\n                } else {\n                    this.config.onPaymentMethodReceived(payload);\n                }\n            }.bind(this));\n        }\n    };\n});\n\n","PayPal_Braintree/js/view/payment/lpm.js":"define(\n    [\n        'uiComponent',\n        'Magento_Checkout/js/model/payment/renderer-list'\n    ],\n    function (\n        Component,\n        rendererList\n    ) {\n        'use strict';\n\n        rendererList.push(\n            {\n                type: 'braintree_local_payment',\n                component: 'PayPal_Braintree/js/view/payment/method-renderer/lpm'\n            }\n        );\n\n        return Component.extend({});\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n    'ko',\n    'jquery',\n    'Magento_Vault/js/view/payment/method-renderer/vault',\n    'PayPal_Braintree/js/view/payment/adapter',\n    'Magento_Ui/js/model/messageList',\n    'PayPal_Braintree/js/view/payment/validator-handler',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'braintree',\n    'braintreeHostedFields',\n    'mage/url'\n], function (\n    ko,\n    $,\n    VaultComponent,\n    Braintree,\n    globalMessageList,\n    validatorManager,\n    additionalValidators,\n    fullScreenLoader,\n    client,\n    hostedFields,\n    url\n) {\n    'use strict';\n\n    return VaultComponent.extend({\n        defaults: {\n            active: false,\n            hostedFieldsInstance: null,\n            imports: {\n                onActiveChange: 'active'\n            },\n            modules: {\n                hostedFields: '${ $.parentName }.braintree'\n            },\n            template: 'PayPal_Braintree/payment/cc/vault',\n            updatePaymentUrl: url.build('braintree/payment/updatepaymentmethod'),\n            vaultedCVV: ko.observable(\"\"),\n            validatorManager: validatorManager,\n            isValidCvv: false,\n            onInstanceReady: function (instance) {\n                instance.on('validityChange', this.onValidityChange.bind(this));\n            }\n        },\n\n        /**\n         * Event fired by Braintree SDK whenever input value length matches the validation length.\n         * In the case of a CVV, this is 3, or 4 for AMEX.\n         * @param event\n         */\n        onValidityChange: function (event) {\n            if (event.emittedBy === 'cvv') {\n                this.isValidCvv = event.fields.cvv.isValid;\n            }\n        },\n\n        /**\n         * @returns {exports}\n         */\n        initObservable: function () {\n            this._super().observe(['active']);\n            this.validatorManager.initialize();\n            return this;\n        },\n\n        /**\n         * Is payment option active?\n         * @returns {boolean}\n         */\n        isActive: function () {\n            let active = this.getId() === this.isChecked();\n            this.active(active);\n            return active;\n        },\n\n        /**\n         * Fired whenever a payment option is changed.\n         * @param isActive\n         */\n        onActiveChange: function (isActive) {\n            let self = this;\n\n            if (!isActive) {\n                return;\n            }\n\n            if (self.showCvvVerify()) {\n                if (self.hostedFieldsInstance) {\n                    self.hostedFieldsInstance.teardown(function (teardownError) {\n                        if (teardownError) {\n                            globalMessageList.addErrorMessage({\n                                message: teardownError.message\n                            });\n                        }\n                        self.hostedFieldsInstance = null;\n                        self.initHostedCvvField();\n                    });\n                    return;\n                }\n                self.initHostedCvvField();\n            }\n        },\n\n        /**\n         * Initialize the CVV input field with the Braintree Hosted Fields SDK.\n         */\n        initHostedCvvField: function () {\n            let self = this;\n            client.create({\n                authorization: Braintree.getClientToken()\n            }, function (clientError, clientInstance) {\n                if (clientError) {\n                    globalMessageList.addErrorMessage({\n                        message: clientError.message\n                    });\n                }\n                hostedFields.create({\n                    client: clientInstance,\n                    fields: {\n                        cvv: {\n                            selector: '#' + self.getId() + '_cid',\n                            placeholder: '123'\n                        }\n                    }\n                }, function (hostedError, hostedFieldsInstance) {\n                    if (hostedError) {\n                        globalMessageList.addErrorMessage({\n                            message: hostedError.message\n                        });\n                        return;\n                    }\n\n                    self.hostedFieldsInstance = hostedFieldsInstance;\n                    self.onInstanceReady(self.hostedFieldsInstance);\n                });\n            });\n        },\n\n        /**\n         * Return the payment method code.\n         * @returns {string}\n         */\n        getCode: function () {\n            return 'braintree_cc_vault';\n        },\n\n        /**\n         * Get last 4 digits of card\n         * @returns {String}\n         */\n        getMaskedCard: function () {\n            return this.details.maskedCC;\n        },\n\n        /**\n         * Get expiration date\n         * @returns {String}\n         */\n        getExpirationDate: function () {\n            return this.details.expirationDate;\n        },\n\n        /**\n         * Get card type\n         * @returns {String}\n         */\n        getCardType: function () {\n            return this.details.type;\n        },\n\n        /**\n         * Get show CVV Field\n         * @returns {Boolean}\n         */\n        showCvvVerify: function () {\n            return window.checkoutConfig.payment[this.code].cvvVerify;\n        },\n\n        /**\n         * Show or hide the error message.\n         * @param selector\n         * @param state\n         * @returns {boolean}\n         */\n        validateCvv: function (selector, state) {\n            let $selector = $(selector),\n                invalidClass = 'braintree-hosted-fields-invalid';\n\n            if (state === true) {\n                $selector.removeClass(invalidClass);\n                return true;\n            }\n\n            $selector.addClass(invalidClass);\n            return false;\n        },\n\n        /**\n         * Place order\n         */\n        placeOrder: function () {\n            let self = this;\n\n            if (self.showCvvVerify()) {\n                if (!self.validateCvv('#' + self.getId() + '_cid', self.isValidCvv) || !additionalValidators.validate()) {\n                    return;\n                }\n            } else {\n                if (!additionalValidators.validate()) {\n                    return;\n                }\n            }\n\n            fullScreenLoader.startLoader();\n\n            if (self.showCvvVerify() && typeof self.hostedFieldsInstance !== 'undefined') {\n                self.hostedFieldsInstance.tokenize({}, function (error, payload) {\n                    if (error) {\n                        fullScreenLoader.stopLoader();\n                        globalMessageList.addErrorMessage({\n                            message: error.message\n                        });\n                        return;\n                    }\n                    $.getJSON(self.updatePaymentUrl, {\n                        'nonce': payload.nonce,\n                        'public_hash': self.publicHash\n                    }).done(function (response) {\n                        if (response.success === false) {\n                            fullScreenLoader.stopLoader();\n                            globalMessageList.addErrorMessage({\n                                message: 'CVV verification failed.'\n                            });\n                            return;\n                        }\n                        self.getPaymentMethodNonce();\n                    })\n                });\n            } else {\n                self.getPaymentMethodNonce();\n            }\n        },\n\n        /**\n         * Send request to get payment method nonce\n         */\n        getPaymentMethodNonce: function () {\n            let self = this;\n\n            fullScreenLoader.startLoader();\n            $.getJSON(self.nonceUrl, {\n                'public_hash': self.publicHash,\n                'cvv': self.vaultedCVV()\n            }).done(function (response) {\n                fullScreenLoader.stopLoader();\n                self.hostedFields(function (formComponent) {\n                    formComponent.setPaymentMethodNonce(response.paymentMethodNonce);\n                    formComponent.setCreditCardBin(response.details.bin);\n                    formComponent.additionalData['public_hash'] = self.publicHash;\n                    formComponent.code = self.code;\n                    if (self.vaultedCVV()) {\n                        formComponent.additionalData['cvv'] = self.vaultedCVV();\n                    }\n\n                    self.validatorManager.validate(formComponent, function () {\n                        fullScreenLoader.stopLoader();\n                        return formComponent.placeOrder('parent');\n                    }, function() {\n                        // No teardown actions required.\n                        fullScreenLoader.stopLoader();\n                        formComponent.setPaymentMethodNonce(null);\n                        formComponent.setCreditCardBin(null);\n                    });\n\n                });\n            }).fail(function (response) {\n                let error = JSON.parse(response.responseText);\n\n                fullScreenLoader.stopLoader();\n                globalMessageList.addErrorMessage({\n                    message: error.message\n                });\n            });\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/venmo.js":"define(\n    [\n        'Magento_Checkout/js/view/payment/default',\n        'braintree',\n        'braintreeDataCollector',\n        'braintreeVenmo',\n        'PayPal_Braintree/js/form-builder',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Checkout/js/model/full-screen-loader',\n        'Magento_Checkout/js/model/payment/additional-validators',\n        'mage/translate'\n    ],\n    function (\n        Component,\n        braintree,\n        dataCollector,\n        venmo,\n        formBuilder,\n        messageList,\n        fullScreenLoader,\n        additionalValidators,\n        $t\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                deviceData: null,\n                paymentMethodNonce: null,\n                template: 'PayPal_Braintree/payment/venmo',\n                venmoInstance: null\n            },\n\n            clickVenmoBtn: function () {\n                let self = this;\n\n                if (!additionalValidators.validate()) {\n                    return false;\n                }\n\n                if (!this.venmoInstance) {\n                    this.setErrorMsg($t('Venmo not initialized, please try reloading.'));\n                    return;\n                }\n\n                this.venmoInstance.tokenize(function (tokenizeErr, payload) {\n                    if (tokenizeErr) {\n                        if (tokenizeErr.code === 'VENMO_CANCELED') {\n                            self.setErrorMsg($t('Venmo app is not available or the payment flow was cancelled.'));\n                        } else if (tokenizeErr.code === 'VENMO_APP_CANCELED') {\n                            self.setErrorMsg($t('Venmo payment flow cancelled.'));\n                        } else {\n                            self.setErrorMsg(tokenizeErr.message);\n                        }\n                    } else {\n                        self.handleVenmoSuccess(payload);\n                    }\n                });\n            },\n\n            collectDeviceData: function (clientInstance, callback) {\n                let self = this;\n                dataCollector.create({\n                    client: clientInstance,\n                    paypal: true\n                }, function (dataCollectorErr, dataCollectorInstance) {\n                    if (dataCollectorErr) {\n                        return;\n                    }\n                    self.deviceData = dataCollectorInstance.deviceData;\n                    callback();\n                });\n            },\n\n            getClientToken: function () {\n                return window.checkoutConfig.payment[this.getCode()].clientToken;\n            },\n\n            getCode: function() {\n                return 'braintree_venmo';\n            },\n\n            getData: function () {\n                let data = {\n                    'method': this.getCode(),\n                    'additional_data': {\n                        'payment_method_nonce': this.paymentMethodNonce,\n                        'device_data': this.deviceData\n                    }\n                };\n\n                data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n                return data;\n            },\n\n            getPaymentMarkSrc: function () {\n                return window.checkoutConfig.payment[this.getCode()].paymentMarkSrc;\n            },\n\n            getTitle: function() {\n                return 'Venmo';\n            },\n\n            handleVenmoSuccess: function (payload) {\n                this.setPaymentMethodNonce(payload.nonce);\n                this.placeOrder();\n            },\n\n            initialize: function () {\n                this._super();\n\n                let self = this;\n\n                braintree.create({\n                    authorization: self.getClientToken()\n                }, function (clientError, clientInstance) {\n                    if (clientError) {\n                        this.setErrorMsg($t('Unable to initialize Braintree Client.'));\n                        return;\n                    }\n\n                    // Collect device data\n                    self.collectDeviceData(clientInstance, function () {\n                        // callback from collectDeviceData\n                        venmo.create({\n                            client: clientInstance,\n                            allowDesktop: true,\n                            allowDesktopWebLogin: true,\n                            mobileWebFallBack: true,\n                            paymentMethodUsage: 'single_use',\n                            allowNewBrowserTab: false\n                        }, function (venmoErr, venmoInstance) {\n                            if (venmoErr) {\n                                self.setErrorMsg($t('Error initializing Venmo: %1').replace('%1', venmoErr));\n                                return;\n                            }\n\n                            if (!venmoInstance.isBrowserSupported()) {\n                                console.log('Browser does not support Venmo');\n                                return;\n                            }\n\n                            self.setVenmoInstance(venmoInstance);\n                        });\n                    });\n                });\n\n                return this;\n            },\n\n            isAllowed: function () {\n                return window.checkoutConfig.payment[this.getCode()].isAllowed;\n            },\n\n            setErrorMsg: function (message) {\n                messageList.addErrorMessage({\n                    message: message\n                });\n            },\n\n            setPaymentMethodNonce: function (nonce) {\n                this.paymentMethodNonce = nonce;\n            },\n\n            setVenmoInstance: function (instance) {\n                this.venmoInstance = instance;\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/paypal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Checkout/js/view/payment/default',\n    'braintree',\n    'braintreeCheckoutPayPalAdapter',\n    'braintreePayPalCheckout',\n    'Magento_Checkout/js/model/quote',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/step-navigator',\n    'Magento_Vault/js/view/payment/vault-enabler',\n    'Magento_Checkout/js/action/create-billing-address',\n    'Magento_Checkout/js/action/select-billing-address',\n    'Magento_CheckoutAgreements/js/view/checkout-agreements',\n    'mage/translate'\n], function (\n    $,\n    _,\n    Component,\n    braintree,\n    Braintree,\n    paypalCheckout,\n    quote,\n    fullScreenLoader,\n    additionalValidators,\n    stepNavigator,\n    VaultEnabler,\n    createBillingAddress,\n    selectBillingAddress,\n    checkoutAgreements,\n    $t\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/payment/paypal',\n            code: 'braintree_paypal',\n            active: false,\n            paypalInstance: null,\n            paymentMethodNonce: null,\n            grandTotalAmount: null,\n            isReviewRequired: false,\n            customerEmail: null,\n\n            /**\n             * Additional payment data\n             *\n             * {Object}\n             */\n            additionalData: {},\n\n            /**\n             * {Array}\n             */\n            lineItemsArray: [\n                'name',\n                'kind',\n                'quantity',\n                'unitAmount',\n                'unitTaxAmount',\n                'productCode',\n                'description'\n            ],\n\n            /**\n             * PayPal client configuration\n             * {Object}\n             */\n            clientConfig: {\n                offerCredit: false,\n                offerCreditOnly: false,\n                dataCollector: {\n                    paypal: true\n                },\n\n                buttonPayPalId: 'braintree_paypal_placeholder',\n                buttonCreditId: 'braintree_paypal_credit_placeholder',\n                buttonPaylaterId: 'braintree_paypal_paylater_placeholder',\n\n                onDeviceDataReceived: function (deviceData) {\n                    this.additionalData['device_data'] = deviceData;\n                },\n\n                /**\n                 * Triggers when widget is loaded\n                 * @param {Object} context\n                 */\n                onReady: function (context) {\n                    this.setupPayPal();\n                },\n\n                /**\n                 * Triggers on payment nonce receive\n                 * @param {Object} response\n                 */\n                onPaymentMethodReceived: function (response) {\n                    this.beforePlaceOrder(response);\n                }\n            },\n            imports: {\n                onActiveChange: 'active'\n            }\n        },\n\n        /**\n         * Set list of observable attributes\n         * @returns {exports.initObservable}\n         */\n        initObservable: function () {\n            var self = this;\n\n            this._super()\n                .observe(['active', 'isReviewRequired', 'customerEmail']);\n\n            window.addEventListener('hashchange', function (e) {\n                var methodCode = quote.paymentMethod();\n\n                if (methodCode === 'braintree_paypal' || methodCode === 'braintree_paypal_vault') {\n                    if (e.newURL.indexOf('payment') > 0 && self.grandTotalAmount !== null) {\n                        self.reInitPayPal();\n                    }\n                }\n            });\n\n            quote.paymentMethod.subscribe(function (value) {\n                var methodCode = value;\n\n                if (methodCode === 'braintree_paypal' || methodCode === 'braintree_paypal_vault') {\n                    self.reInitPayPal();\n                }\n            });\n\n            this.vaultEnabler = new VaultEnabler();\n            this.vaultEnabler.setPaymentCode(this.getVaultCode());\n            this.vaultEnabler.isActivePaymentTokenEnabler.subscribe(function () {\n                self.onVaultPaymentTokenEnablerChange();\n            });\n\n            this.grandTotalAmount = quote.totals()['base_grand_total'];\n\n            quote.totals.subscribe(function () {\n                if (self.grandTotalAmount !== quote.totals()['base_grand_total']) {\n                    self.grandTotalAmount = quote.totals()['base_grand_total'];\n                    var methodCode = quote.paymentMethod();\n\n                    if (methodCode && (methodCode.method === 'braintree_paypal' || methodCode.method === 'braintree_paypal_vault')) {\n                        self.reInitPayPal();\n                    }\n                }\n            });\n\n            // for each component initialization need update property\n            this.isReviewRequired(false);\n            this.initClientConfig();\n\n            return this;\n        },\n\n        /**\n         * Get payment name\n         *\n         * @returns {String}\n         */\n        getCode: function () {\n            return this.code;\n        },\n\n        /**\n         * Get payment title\n         *\n         * @returns {String}\n         */\n        getTitle: function () {\n            return window.checkoutConfig.payment[this.getCode()].title;\n        },\n\n        /**\n         * Check if payment is active\n         *\n         * @returns {Boolean}\n         */\n        isActive: function () {\n            var active = this.getCode() === this.isChecked();\n\n            this.active(active);\n\n            return active;\n        },\n\n        /**\n         * Triggers when payment method change\n         * @param {Boolean} isActive\n         */\n        onActiveChange: function (isActive) {\n            if (!isActive) {\n                return;\n            }\n\n            // need always re-init Braintree with PayPal configuration\n            this.reInitPayPal();\n        },\n\n        /**\n         * Init config\n         */\n        initClientConfig: function () {\n            this.clientConfig = _.extend(this.clientConfig, this.getPayPalConfig());\n\n            _.each(this.clientConfig, function (fn, name) {\n                if (typeof fn === 'function') {\n                    this.clientConfig[name] = fn.bind(this);\n                }\n            }, this);\n        },\n\n        /**\n         * Set payment nonce\n         * @param {String} paymentMethodNonce\n         */\n        setPaymentMethodNonce: function (paymentMethodNonce) {\n            this.paymentMethodNonce = paymentMethodNonce;\n        },\n\n        /**\n         * Update quote billing address\n         * @param {Object}customer\n         * @param {Object}address\n         */\n        setBillingAddress: function (customer, address) {\n            var billingAddress = {\n                street: [address.line1],\n                city: address.city,\n                postcode: address.postalCode,\n                countryId: address.countryCode,\n                email: customer.email,\n                firstname: customer.firstName,\n                lastname: customer.lastName,\n                telephone: typeof customer.phone !== 'undefined' ? customer.phone : '00000000000'\n            };\n\n            billingAddress['region_code'] = typeof address.state === 'string' ? address.state : '';\n            billingAddress = createBillingAddress(billingAddress);\n            quote.billingAddress(billingAddress);\n        },\n\n        /**\n         * Prepare data to place order\n         * @param {Object} data\n         */\n        beforePlaceOrder: function (data) {\n            this.setPaymentMethodNonce(data.nonce);\n            this.customerEmail(data.details.email);\n            if (quote.isVirtual()) {\n                this.isReviewRequired(true);\n            } else {\n                if (this.isRequiredBillingAddress() === '1' || quote.billingAddress() === null) {\n                    if (typeof data.details.billingAddress !== 'undefined') {\n                        this.setBillingAddress(data.details, data.details.billingAddress);\n                    } else {\n                        this.setBillingAddress(data.details, data.details.shippingAddress);\n                    }\n                } else {\n                    if (quote.shippingAddress() === quote.billingAddress()) {\n                        selectBillingAddress(quote.shippingAddress());\n                    } else {\n                        selectBillingAddress(quote.billingAddress());\n                    }\n                }\n            }\n            this.placeOrder();\n        },\n\n        /**\n         * Re-init PayPal Auth Flow\n         */\n        reInitPayPal: function () {\n            this.disableButton();\n            this.clientConfig.paypal.amount = parseFloat(this.grandTotalAmount).toFixed(2);\n\n            if (!quote.isVirtual()) {\n                this.clientConfig.paypal.enableShippingAddress = true;\n                this.clientConfig.paypal.shippingAddressEditable = false;\n                this.clientConfig.paypal.shippingAddressOverride = this.getShippingAddress();\n            }\n            // Send Line Items\n            this.clientConfig.paypal.lineItems = this.getLineItems();\n\n            Braintree.setConfig(this.clientConfig);\n\n            if (Braintree.getPayPalInstance()) {\n                Braintree.getPayPalInstance().teardown(function () {\n                    Braintree.setup();\n                }.bind(this));\n                Braintree.setPayPalInstance(null);\n            } else {\n                Braintree.setup();\n                this.enableButton();\n            }\n        },\n\n        /**\n         * Setup PayPal instance\n         */\n        setupPayPal: function () {\n            var self = this;\n\n            if (Braintree.config.paypalInstance) {\n                fullScreenLoader.stopLoader(true);\n                return;\n            }\n\n            paypalCheckout.create({\n                client: Braintree.clientInstance\n            }, function (createErr, paypalCheckoutInstance) {\n                if (createErr) {\n                    Braintree.showError($t(\"PayPal Checkout could not be initialized. Please contact the store owner.\"));\n                    console.error('paypalCheckout error', createErr);\n                    return;\n                }\n                let quoteObj = quote.totals();\n\n                var configSDK = {\n                    components: 'buttons,messages,funding-eligibility',\n                    \"enable-funding\": \"paylater\",\n                    currency: quoteObj['base_currency_code']\n                };\n                var merchantCountry = window.checkoutConfig.payment['braintree_paypal'].merchantCountry;\n                if (Braintree.getEnvironment() == 'sandbox' && merchantCountry != null) {\n                    configSDK[\"buyer-country\"] = merchantCountry;\n                }\n                paypalCheckoutInstance.loadPayPalSDK(configSDK, function () {\n                    this.loadPayPalButton(paypalCheckoutInstance, 'paypal');\n                    if (this.isCreditEnabled()) {\n                        this.loadPayPalButton(paypalCheckoutInstance, 'credit');\n                    }\n                    if (this.isPaylaterEnabled()) {\n                        this.loadPayPalButton(paypalCheckoutInstance, 'paylater');\n                    }\n\n                }.bind(this));\n            }.bind(this));\n        },\n\n        loadPayPalButton: function (paypalCheckoutInstance, funding) {\n            var paypalPayment = Braintree.config.paypal,\n                onPaymentMethodReceived = Braintree.config.onPaymentMethodReceived;\n            var style = {\n                color: Braintree.getColor(funding),\n                shape: Braintree.getShape(funding),\n                size: Braintree.getSize(funding),\n                label: Braintree.getLabel(funding)\n            };\n\n            if (Braintree.getBranding()) {\n                style.branding = Braintree.getBranding();\n            }\n            if (Braintree.getFundingIcons()) {\n                style.fundingicons = Braintree.getFundingIcons();\n            }\n\n            if (funding === 'credit') {\n                Braintree.config.buttonId = this.clientConfig.buttonCreditId;\n            } else if (funding === 'paylater') {\n                Braintree.config.buttonId = this.clientConfig.buttonPaylaterId;\n            } else {\n                Braintree.config.buttonId = this.clientConfig.buttonPayPalId;\n            }\n            // Render\n            Braintree.config.paypalInstance = paypalCheckoutInstance;\n            var events = Braintree.events;\n            $('#' + Braintree.config.buttonId).html('');\n\n            var button = paypal.Buttons({\n                fundingSource: funding,\n                env: Braintree.getEnvironment(),\n                style: style,\n                commit: true,\n                locale: Braintree.config.paypal.locale,\n\n                onInit: function (data, actions) {\n                    var agreements = checkoutAgreements().agreements,\n                        shouldDisableActions = false;\n\n                    actions.disable();\n\n                    _.each(agreements, function (item, index) {\n                        if (checkoutAgreements().isAgreementRequired(item)) {\n                            var paymentMethodCode = quote.paymentMethod().method,\n                                inputId = '#agreement_' + paymentMethodCode + '_' + item.agreementId,\n                                inputEl = document.querySelector(inputId);\n\n\n                            if (!inputEl.checked) {\n                                shouldDisableActions = true;\n                            }\n\n                            inputEl.addEventListener('change', function (event) {\n                                if (additionalValidators.validate()) {\n                                    actions.enable();\n                                } else {\n                                    actions.disable();\n                                }\n                            });\n                        }\n                    });\n\n                    if (!shouldDisableActions) {\n                        actions.enable();\n                    }\n                },\n\n                createOrder: function () {\n                    return paypalCheckoutInstance.createPayment(paypalPayment).catch(function (err) {\n                        throw err.details.originalError.details.originalError.paymentResource;\n                    });\n                },\n\n                onCancel: function (data) {\n                    console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));\n\n                    if (typeof events.onCancel === 'function') {\n                        events.onCancel();\n                    }\n                },\n\n                onError: function (err) {\n                    if (err.errorName === 'VALIDATION_ERROR' && err.errorMessage.indexOf('Value is invalid') !== -1) {\n                        Braintree.showError($t('Address failed validation. Please check and confirm your City, State, and Postal Code'));\n                    } else {\n                        Braintree.showError($t(\"PayPal Checkout could not be initialized. Please contact the store owner.\"));\n                    }\n                    Braintree.config.paypalInstance = null;\n                    console.error('Paypal checkout.js error', err);\n\n                    if (typeof events.onError === 'function') {\n                        events.onError(err);\n                    }\n                }.bind(this),\n\n                onClick: function (data) {\n                    if (!quote.isVirtual()) {\n                        this.clientConfig.paypal.enableShippingAddress = true;\n                        this.clientConfig.paypal.shippingAddressEditable = false;\n                        this.clientConfig.paypal.shippingAddressOverride = this.getShippingAddress();\n                    }\n\n                    // To check term & conditions input checked - validate additional validators.\n                    if (!additionalValidators.validate()) {\n                        return false;\n                    }\n\n                    if (typeof events.onClick === 'function') {\n                        events.onClick(data);\n                    }\n                }.bind(this),\n\n                onApprove: function (data, actions) {\n                    return paypalCheckoutInstance.tokenizePayment(data)\n                        .then(function (payload) {\n                            onPaymentMethodReceived(payload);\n                        });\n                }\n\n            });\n            if (button.isEligible() && $('#' + Braintree.config.buttonId).length) {\n                button.render('#' + Braintree.config.buttonId).then(function () {\n                    Braintree.enableButton();\n                    if (typeof Braintree.config.onPaymentMethodError === 'function') {\n                        Braintree.config.onPaymentMethodError();\n                    }\n                }.bind(this)).then(function (data) {\n                    if (typeof events.onRender === 'function') {\n                        events.onRender(data);\n                    }\n                });\n            }\n        },\n\n        /**\n         * Get locale\n         * @returns {String}\n         */\n        getLocale: function () {\n            return window.checkoutConfig.payment[this.getCode()].locale;\n        },\n\n        /**\n         * Is Billing Address required from PayPal side\n         * @returns {exports.isRequiredBillingAddress|(function())|boolean}\n         */\n        isRequiredBillingAddress: function () {\n            return window.checkoutConfig.payment[this.getCode()].isRequiredBillingAddress;\n        },\n\n        /**\n         * Get configuration for PayPal\n         * @returns {Object}\n         */\n        getPayPalConfig: function () {\n            var totals = quote.totals(),\n                config = {},\n                isActiveVaultEnabler = this.isActiveVault();\n\n            config.paypal = {\n                flow: 'checkout',\n                amount: parseFloat(this.grandTotalAmount).toFixed(2),\n                currency: totals['base_currency_code'],\n                locale: this.getLocale(),\n\n                /**\n                 * Triggers on any Braintree error\n                 */\n                onError: function () {\n                    this.paymentMethodNonce = null;\n                },\n\n                /**\n                 * Triggers if browser doesn't support PayPal Checkout\n                 */\n                onUnsupported: function () {\n                    this.paymentMethodNonce = null;\n                }\n            };\n\n            if (isActiveVaultEnabler) {\n                config.paypal.requestBillingAgreement = true;\n            }\n\n            if (!quote.isVirtual()) {\n                config.paypal.enableShippingAddress = true;\n                config.paypal.shippingAddressEditable = false;\n                config.paypal.shippingAddressOverride = this.getShippingAddress();\n            }\n\n            if (this.getMerchantName()) {\n                config.paypal.displayName = this.getMerchantName();\n            }\n\n            return config;\n        },\n\n        /**\n         * Get shipping address\n         * @returns {Object}\n         */\n        getShippingAddress: function () {\n            var address = quote.shippingAddress();\n\n            return {\n                recipientName: address.firstname + ' ' + address.lastname,\n                line1: address.street[0],\n                line2: typeof address.street[2] === 'undefined' ? address.street[1] : address.street[1] + ' ' + address.street[2],\n                city: address.city,\n                countryCode: address.countryId,\n                postalCode: address.postcode,\n                state: address.regionCode\n            };\n        },\n\n        /**\n         * Get merchant name\n         * @returns {String}\n         */\n        getMerchantName: function () {\n            return window.checkoutConfig.payment[this.getCode()].merchantName;\n        },\n\n        /**\n         * Get data\n         * @returns {Object}\n         */\n        getData: function () {\n            var data = {\n                'method': this.getCode(),\n                'additional_data': {\n                    'payment_method_nonce': this.paymentMethodNonce\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            this.vaultEnabler.visitAdditionalData(data);\n\n            return data;\n        },\n\n        /**\n         * Returns payment acceptance mark image path\n         * @returns {String}\n         */\n        getPaymentAcceptanceMarkSrc: function () {\n            return window.checkoutConfig.payment[this.getCode()].paymentAcceptanceMarkSrc;\n        },\n\n        /**\n         * @returns {String}\n         */\n        getVaultCode: function () {\n            return window.checkoutConfig.payment[this.getCode()].vaultCode;\n        },\n\n        /**\n         * Check if need to skip order review\n         * @returns {Boolean}\n         */\n        isSkipOrderReview: function () {\n            return window.checkoutConfig.payment[this.getCode()].skipOrderReview;\n        },\n\n        /**\n         * Checks if vault is active\n         * @returns {Boolean}\n         */\n        isActiveVault: function () {\n            return this.vaultEnabler.isVaultEnabled() && this.vaultEnabler.isActivePaymentTokenEnabler();\n        },\n\n        /**\n         * Re-init PayPal Auth flow to use Vault\n         */\n        onVaultPaymentTokenEnablerChange: function () {\n            this.clientConfig.paypal.singleUse = !this.isActiveVault();\n            this.reInitPayPal();\n        },\n\n        /**\n         * Disable submit button\n         */\n        disableButton: function () {\n            // stop any previous shown loaders\n            fullScreenLoader.stopLoader(true);\n            fullScreenLoader.startLoader();\n            $('[data-button=\"place\"]').attr('disabled', 'disabled');\n        },\n\n        /**\n         * Enable submit button\n         */\n        enableButton: function () {\n            $('[data-button=\"place\"]').removeAttr('disabled');\n            fullScreenLoader.stopLoader(true);\n        },\n\n        /**\n         * Triggers when customer click \"Continue to PayPal\" button\n         */\n        payWithPayPal: function () {\n            if (additionalValidators.validate()) {\n                Braintree.checkout.paypal.initAuthFlow();\n            }\n        },\n\n        /**\n         * Get button id\n         * @returns {String}\n         */\n        getPayPalButtonId: function () {\n            return this.clientConfig.buttonPayPalId;\n        },\n\n        /**\n         * Get button id\n         * @returns {String}\n         */\n        getCreditButtonId: function () {\n            return this.clientConfig.buttonCreditId;\n        },\n\n        /**\n         * Get button id\n         * @returns {String}\n         */\n        getPaylaterButtonId: function () {\n            return this.clientConfig.buttonPaylaterId;\n        },\n\n        isPaylaterEnabled: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['isActive'];\n        },\n\n        isPaylaterMessageEnabled: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['isMessageActive'];\n        },\n\n        getGrandTotalAmount: function () {\n            return parseFloat(this.grandTotalAmount).toFixed(2);\n        },\n\n        isCreditEnabled: function () {\n            return window.checkoutConfig.payment['braintree_paypal_credit']['isActive'];\n        },\n\n        /**\n         * Get Message Layout\n         * @returns {*}\n         */\n        getMessagingLayout: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['layout'];\n        },\n\n        /**\n         * Get Message Logo\n         * @returns {*}\n         */\n        getMessagingLogo: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['logo'];\n        },\n\n        /**\n         * Get Message Logo position\n         * @returns {*}\n         */\n        getMessagingLogoPosition: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['logo_position'];\n        },\n\n        /**\n         * Get Message Text Color\n         * @returns {*}\n         */\n        getMessagingTextColor: function () {\n            return window.checkoutConfig.payment['braintree_paypal_paylater']['message']['text_color'];\n        },\n\n        /**\n         * Get line items\n         * @returns {Array}\n         */\n        getLineItems: function () {\n            let self = this;\n            let lineItems = [], storeCredit = 0, giftCardAccount = 0;\n            let giftWrappingItems = 0, giftWrappingOrder = 0;\n            $.each(quote.totals()['total_segments'], function(segmentsKey, segmentsItem) {\n                if (segmentsItem['code'] === 'customerbalance') {\n                    storeCredit = parseFloat(Math.abs(segmentsItem['value']).toString()).toFixed(2);\n                }\n                if (segmentsItem['code'] === 'giftcardaccount') {\n                    giftCardAccount = parseFloat(Math.abs(segmentsItem['value']).toString()).toFixed(2);\n                }\n                if (segmentsItem['code'] === 'giftwrapping') {\n                    let extensionAttributes = segmentsItem['extension_attributes'];\n                    giftWrappingOrder = extensionAttributes['gw_base_price'];\n                    giftWrappingItems = extensionAttributes['gw_items_base_price'];\n                }\n            });\n            if (this.canSendLineItems()) {\n                $.each(quote.getItems(), function(quoteItemKey, quoteItem) {\n                    if (quoteItem.parent_item_id !== null || 0.0 === quoteItem.price) {\n                        return true;\n                    }\n\n                    let itemName = self.replaceUnsupportedCharacters(quoteItem.name);\n                    let itemSku = self.replaceUnsupportedCharacters(quoteItem.sku);\n\n                    let description = '';\n                    let itemQty = parseFloat(quoteItem.qty);\n                    let itemUnitAmount = parseFloat(quoteItem.price);\n                    if (itemQty > Math.floor(itemQty) && itemQty < Math.ceil(itemQty)) {\n                        description = 'Item quantity is ' + itemQty.toFixed(2) + ' and per unit amount is ' + itemUnitAmount.toFixed(2);\n                        itemUnitAmount = parseFloat(itemQty * itemUnitAmount);\n                        itemQty = parseFloat('1');\n                    }\n\n                    let lineItemValues = [\n                        itemName,\n                        'debit',\n                        itemQty.toFixed(2),\n                        itemUnitAmount.toFixed(2),\n                        parseFloat(quoteItem.base_tax_amount).toFixed(2),\n                        itemSku,\n                        description\n                    ];\n\n                    let mappedLineItems = $.map(self.lineItemsArray, function(itemElement, itemIndex) {\n                        return [[\n                            self.lineItemsArray[itemIndex],\n                            lineItemValues[itemIndex]\n                        ]]\n                    });\n\n                    lineItems[quoteItemKey] = Object.fromEntries(mappedLineItems);\n                });\n\n                /**\n                 * Adds credit (refund or discount) kind as LineItems for the\n                 * PayPal transaction if discount amount is greater than 0(Zero)\n                 * as discountAmount lineItem field is not being used by PayPal.\n                 *\n                 * https://developer.paypal.com/braintree/docs/reference/response/transaction-line-item/php#discount_amount\n                 */\n                let baseDiscountAmount = parseFloat(Math.abs(quote.totals()['base_discount_amount']).toString()).toFixed(2);\n                if (baseDiscountAmount > 0) {\n                    let discountLineItem = {\n                        'name': 'Discount',\n                        'kind': 'credit',\n                        'quantity': 1.00,\n                        'unitAmount': baseDiscountAmount\n                    };\n\n                    lineItems = $.merge(lineItems, [discountLineItem]);\n                }\n\n                /**\n                 * Adds shipping as LineItems for the PayPal transaction\n                 * if shipping amount is greater than 0(Zero) to manage\n                 * the totals with client-side implementation as there is\n                 * no any field exist in the client-side implementation\n                 * to send the shipping amount to the Braintree.\n                 */\n                if (quote.totals()['base_shipping_amount'] > 0) {\n                    let shippingLineItem = {\n                        'name': 'Shipping',\n                        'kind': 'debit',\n                        'quantity': 1.00,\n                        'unitAmount': quote.totals()['base_shipping_amount']\n                    };\n\n                    lineItems = $.merge(lineItems, [shippingLineItem]);\n                }\n\n                /**\n                 * Adds credit (Store Credit) kind as LineItems for the\n                 * PayPal transaction if store credit is greater than 0(Zero)\n                 * to manage the totals with client-side implementation\n                 */\n                if (storeCredit > 0) {\n                    let storeCreditItem = {\n                        'name': 'Store Credit',\n                        'kind': 'credit',\n                        'quantity': 1.00,\n                        'unitAmount': storeCredit\n                    };\n\n                    lineItems = $.merge(lineItems, [storeCreditItem]);\n                }\n\n                /**\n                 * Adds Gift Wrapping for items as LineItems for the PayPal\n                 * transaction if it is greater than 0(Zero) to manage\n                 * the totals with client-side implementation\n                 */\n                if (giftWrappingItems > 0) {\n                    let gwItems = {\n                        'name': 'Gift Wrapping for Items',\n                        'kind': 'debit',\n                        'quantity': 1.00,\n                        'unitAmount': giftWrappingItems\n                    };\n\n                    lineItems = $.merge(lineItems, [gwItems]);\n                }\n\n                /**\n                 * Adds Gift Wrapping for order as LineItems for the PayPal\n                 * transaction if it is greater than 0(Zero) to manage\n                 * the totals with client-side implementation\n                 */\n                if (giftWrappingOrder > 0) {\n                    let gwOrderItem = {\n                        'name': 'Gift Wrapping for Order',\n                        'kind': 'debit',\n                        'quantity': 1.00,\n                        'unitAmount': giftWrappingOrder\n                    };\n\n                    lineItems = $.merge(lineItems, [gwOrderItem]);\n                }\n\n                /**\n                 * Adds Gift Cards as credit LineItems for the PayPal\n                 * transaction if it is greater than 0(Zero) to manage\n                 * the totals with client-side implementation\n                 */\n                if (giftCardAccount > 0) {\n                    let giftCardItem = {\n                        'name': 'Gift Cards',\n                        'kind': 'credit',\n                        'quantity': 1.00,\n                        'unitAmount': giftCardAccount\n                    };\n\n                    lineItems = $.merge(lineItems, [giftCardItem]);\n                }\n\n                if (lineItems.length >= 250) {\n                    lineItems = [];\n                }\n            }\n            return lineItems;\n        },\n\n        /**\n         * Regex to replace all unsupported characters.\n         *\n         * @param str\n         */\n        replaceUnsupportedCharacters: function (str) {\n            str.replace('/[^a-zA-Z0-9\\s\\-.\\']/', '');\n            return str.substr(0, 127);\n        },\n\n        /**\n         * Can send line items\n         *\n         * @returns {Boolean}\n         */\n        canSendLineItems: function () {\n            return window.checkoutConfig.payment[this.getCode()].canSendLineItems;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/ach.js":"define(\n    [\n        'Magento_Checkout/js/view/payment/default',\n        'ko',\n        'jquery',\n        'braintree',\n        'braintreeDataCollector',\n        'braintreeAch',\n        'PayPal_Braintree/js/form-builder',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Checkout/js/action/select-billing-address',\n        'Magento_Checkout/js/model/full-screen-loader',\n        'Magento_Checkout/js/model/quote',\n        'mage/translate'\n    ],\n    function (\n        Component,\n        ko,\n        $,\n        braintree,\n        dataCollector,\n        ach,\n        formBuilder,\n        messageList,\n        selectBillingAddress,\n        fullScreenLoader,\n        quote,\n        $t\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                deviceData: null,\n                paymentMethodNonce: null,\n                template: 'PayPal_Braintree/payment/ach',\n                achInstance: null,\n                routingNumber: ko.observable(\"\"),\n                accountNumber: ko.observable(\"\"),\n                accountType: ko.observable(\"checking\"),\n                ownershipType: ko.observable(\"personal\"),\n                firstName: ko.observable(\"\"),\n                lastName: ko.observable(\"\"),\n                businessName: ko.observable(\"\"),\n                hasAuthorization: ko.observable(false),\n                business: ko.observable(false), // for ownership type\n                personal: ko.observable(true) // for ownership type\n            },\n\n            clickAchBtn: function () {\n                if (!this.validateForm('#' + this.getCode() + '-form')) {\n                    return;\n                }\n\n                fullScreenLoader.startLoader();\n\n                var self = this;\n\n                var billingAddress = quote.billingAddress();\n\n                let regionCode;\n\n                let bankDetails = {\n                    routingNumber: self.routingNumber(),\n                    accountNumber: self.accountNumber(),\n                    accountType: self.accountType(),\n                    ownershipType: self.ownershipType(),\n                    billingAddress: {\n                        streetAddress: billingAddress.street[0],\n                        extendedAddress: billingAddress.street[1],\n                        locality: billingAddress.city,\n                        region: billingAddress.regionCode,\n                        postalCode: billingAddress.postcode,\n                    }\n                };\n\n                if (bankDetails.ownershipType === 'personal') {\n                    bankDetails.firstName = self.firstName();\n                    bankDetails.lastName = self.lastName();\n                } else {\n                    bankDetails.businessName = self.businessName();\n                }\n\n                var mandateText = document.getElementById('braintree-ach-mandate').textContent;\n\n                // if no region code is available, lets find one!\n                if (typeof billingAddress.regionCode === 'undefined') {\n                    $.get('/rest/V1/directory/countries/' + billingAddress.countryId).done(function (data) {\n                        if (typeof data.available_regions !== 'undefined') {\n                            for (var i = 0; i < data.available_regions.length; ++i) {\n                                if (data.available_regions[i].id === billingAddress.regionId) {\n                                    regionCode = data.available_regions[i].code;\n                                    bankDetails.billingAddress.region = regionCode;\n                                    self.tokenizeAch(bankDetails, mandateText);\n                                }\n                            }\n                        } else {\n                            fullScreenLoader.stopLoader();\n                            self.tokenizeAch(bankDetails, mandateText);\n                        }\n                    }).fail(function() {\n                        fullScreenLoader.stopLoader();\n                    });\n                } else {\n                    self.tokenizeAch(bankDetails, mandateText);\n                }\n            },\n\n            tokenizeAch: function (bankDetails, mandateText) {\n                var self = this;\n                this.achInstance.tokenize({\n                    bankDetails: bankDetails,\n                    mandateText: mandateText\n                }, function (tokenizeErr, tokenizedPayload) {\n                    if (tokenizeErr) {\n                        self.setErrorMsg($t('There was an error with the provided bank details. Please check and try again.'));\n                        self.hasAuthorization(false);\n                    } else {\n                        fullScreenLoader.stopLoader();\n                        self.handleAchSuccess(tokenizedPayload);\n                    }\n                });\n            },\n\n            getClientToken: function () {\n                return window.checkoutConfig.payment[this.getCode()].clientToken;\n            },\n\n            getCode: function () {\n                return 'braintree_ach_direct_debit';\n            },\n\n            getStoreName: function () {\n                return window.checkoutConfig.payment[this.getCode()].storeName;\n            },\n\n            getData: function () {\n                let data = {\n                    'method': this.getCode(),\n                    'additional_data': {\n                        'payment_method_nonce': this.paymentMethodNonce,\n                    }\n                };\n\n                data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n                return data;\n            },\n\n            getTitle: function() {\n                return 'ACH Direct Debit';\n            },\n\n            handleAchSuccess: function (payload) {\n                this.setPaymentMethodNonce(payload.nonce);\n                this.placeOrder();\n            },\n\n            initialize: function () {\n                this._super();\n\n                var self = this;\n\n                braintree.create({\n                    authorization: self.getClientToken()\n                }, function (clientError, clientInstance) {\n                    if (clientError) {\n                        this.setErrorMsg($t('Unable to initialize Braintree Client.'));\n                        return;\n                    }\n\n                    ach.create({\n                        client: clientInstance\n                    }, function (achErr, achInstance) {\n                        if (achErr) {\n                            self.setErrorMsg($t('Error initializing ACH: %1').replace('%1', achErr));\n                            return;\n                        }\n\n                        self.setAchInstance(achInstance);\n                    });\n                });\n\n                return this;\n            },\n\n            isAllowed: function () {\n                return window.checkoutConfig.payment[this.getCode()].isAllowed;\n            },\n\n            changeOwnershipType: function (data, event) {\n                var self = this;\n                if (event.currentTarget.value === 'business') {\n                    self.business(true);\n                    self.personal(false);\n                } else {\n                    self.business(false);\n                    self.personal(true);\n                }\n            },\n\n            isBusiness: function () {\n                return this.business;\n            },\n\n            isPersonal: function () {\n                return this.personal;\n            },\n\n            setErrorMsg: function (message) {\n                messageList.addErrorMessage({\n                    message: message\n                });\n            },\n\n            setPaymentMethodNonce: function (nonce) {\n                this.paymentMethodNonce = nonce;\n            },\n\n            setAchInstance: function (instance) {\n                this.achInstance = instance;\n            },\n\n            validateForm: function (form) {\n                return $(form).validation() && $(form).validation('isValid');\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/cc-form.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine(\n    [\n        'underscore',\n        'jquery',\n        'Magento_Payment/js/view/payment/cc-form',\n        'Magento_Checkout/js/model/quote',\n        'PayPal_Braintree/js/view/payment/adapter',\n        'mage/translate',\n        'PayPal_Braintree/js/validator',\n        'PayPal_Braintree/js/view/payment/validator-handler',\n        'Magento_Checkout/js/model/full-screen-loader'\n    ],\n    function (\n        _,\n        $,\n        Component,\n        quote,\n        braintree,\n        $t,\n        validator,\n        validatorManager,\n        fullScreenLoader\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                active: false,\n                braintreeClient: null,\n                braintreeDeviceData: null,\n                paymentMethodNonce: null,\n                lastBillingAddress: null,\n                validatorManager: validatorManager,\n                code: 'braintree',\n                isProcessing: false,\n                creditCardBin: null,\n\n                /**\n                 * Additional payment data\n                 *\n                 * {Object}\n                 */\n                additionalData: {},\n\n                /**\n                 * Braintree client configuration\n                 *\n                 * {Object}\n                 */\n                clientConfig: {\n                    onReady: function (context) {\n                        context.setupHostedFields();\n                    },\n\n                    /**\n                     * Triggers on payment nonce receive\n                     * @param {Object} response\n                     */\n                    onPaymentMethodReceived: function (response) {\n                        this.handleNonce(response);\n                        this.isProcessing = false;\n                    },\n\n                    /**\n                     * Allow a new nonce to be generated\n                     */\n                    onPaymentMethodError: function() {\n                        this.isProcessing = false;\n                    },\n\n                    /**\n                     * Device data initialization\n                     * @param {String} deviceData\n                     */\n                    onDeviceDataReceived: function (deviceData) {\n                        this.additionalData['device_data'] = deviceData;\n                    },\n\n                    /**\n                     * After Braintree instance initialization\n                     */\n                    onInstanceReady: function () {},\n\n                    /**\n                     * Triggers on any Braintree error\n                     * @param {Object} response\n                     */\n                    onError: function (response) {\n                        this.isProcessing = false;\n                        braintree.showError($t('Payment ' + this.getTitle() + ' can\\'t be initialized'));\n                        throw response.message;\n                    },\n\n                    /**\n                     * Triggers when customer click \"Cancel\"\n                     */\n                    onCancelled: function () {\n                        this.paymentMethodNonce = null;\n                        this.isProcessing = false;\n                    }\n                },\n                imports: {\n                    onActiveChange: 'active'\n                }\n            },\n\n            /**\n             * Set list of observable attributes\n             *\n             * @returns {exports.initObservable}\n             */\n            initObservable: function () {\n                validator.setConfig(window.checkoutConfig.payment[this.getCode()]);\n                this._super()\n                    .observe(['active']);\n                this.validatorManager.initialize();\n                this.initClientConfig();\n\n                return this;\n            },\n\n            /**\n             * Get payment name\n             *\n             * @returns {String}\n             */\n            getCode: function () {\n                return this.code;\n            },\n\n            /**\n             * Check if payment is active\n             *\n             * @returns {Boolean}\n             */\n            isActive: function () {\n                let active = this.getCode() === this.isChecked();\n                this.active(active);\n\n                return active;\n            },\n\n            /**\n             * Triggers when payment method change\n             * @param {Boolean} isActive\n             */\n            onActiveChange: function (isActive) {\n                if (!isActive) {\n                    return;\n                }\n\n                this.initBraintree();\n            },\n\n            /**\n             * Init config\n             */\n            initClientConfig: function () {\n                _.each(this.clientConfig, function (fn, name) {\n                    if (typeof fn === 'function') {\n                        this.clientConfig[name] = fn.bind(this);\n                    }\n                }, this);\n            },\n\n            /**\n             * Init Braintree configuration\n             */\n            initBraintree: function () {\n                let intervalId = setInterval(function () {\n                    // stop loader when frame will be loaded\n                    if ($('#braintree-hosted-field-number').length) {\n                        clearInterval(intervalId);\n                        fullScreenLoader.stopLoader(true);\n                    }\n                }, 500);\n\n                if (braintree.checkout) {\n                    braintree.checkout.teardown(function () {\n                        braintree.checkout = null;\n                    });\n                }\n\n                fullScreenLoader.startLoader();\n                braintree.setConfig(this.clientConfig);\n                braintree.setup();\n            },\n\n            /**\n             * Get full selector name\n             *\n             * @param {String} field\n             * @returns {String}\n             */\n            getSelector: function (field) {\n                return '#' + this.getCode() + '_' + field;\n            },\n\n            /**\n             * Get list of available CC types\n             *\n             * @returns {Object}\n             */\n            getCcAvailableTypes: function () {\n                let availableTypes = validator.getAvailableCardTypes(),\n                    billingAddress = quote.billingAddress(),\n                    billingCountryId;\n\n                this.lastBillingAddress = quote.shippingAddress();\n\n                if (!billingAddress) {\n                    billingAddress = this.lastBillingAddress;\n                }\n\n                billingCountryId = billingAddress.countryId;\n\n                if (billingCountryId && validator.getCountrySpecificCardTypes(billingCountryId)) {\n                    return validator.collectTypes(\n                        availableTypes,\n                        validator.getCountrySpecificCardTypes(billingCountryId)\n                    );\n                }\n\n                return availableTypes;\n            },\n\n            /**\n             * @returns {String}\n             */\n            getEnvironment: function () {\n                return window.checkoutConfig.payment[this.getCode()].environment;\n            },\n\n            /**\n             * Get data\n             *\n             * @returns {Object}\n             */\n            getData: function () {\n                let data = {\n                    'method': this.getCode(),\n                    'additional_data': {\n                        'payment_method_nonce': this.paymentMethodNonce,\n                        'g-recaptcha-response' : $(\"#token-grecaptcha-braintree\").val()\n                    }\n                };\n\n                data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n                return data;\n            },\n\n            /**\n             * Set payment nonce\n             * @param {String} paymentMethodNonce\n             */\n            setPaymentMethodNonce: function (paymentMethodNonce) {\n                this.paymentMethodNonce = paymentMethodNonce;\n            },\n\n            /**\n             * Set credit card bin\n             * @param creditCardBin\n             */\n            setCreditCardBin: function (creditCardBin) {\n                this.creditCardBin = creditCardBin;\n            },\n\n            /**\n             * Prepare payload to place order\n             * @param {Object} payload\n             */\n            handleNonce: function (payload) {\n                let self = this;\n\n                this.setPaymentMethodNonce(payload.nonce);\n                this.setCreditCardBin(payload.details.bin);\n\n                // place order on success validation\n                self.validatorManager.validate(self, function () {\n                    return self.placeOrder('parent');\n                }, function() {\n                    self.isProcessing = false;\n                    self.paymentMethodNonce = null;\n                    self.creditCardBin = null;\n                });\n            },\n\n            /**\n             * Action to place order\n             * @param {String} key\n             */\n            placeOrder: function (key) {\n                if (key) {\n                    return this._super();\n                }\n\n                if (this.isProcessing) {\n                    return false;\n                } else {\n                    this.isProcessing = true;\n                }\n\n                braintree.tokenizeHostedFields();\n                return false;\n            },\n\n            /**\n             * Get payment icons\n             * @param {String} type\n             * @returns {Boolean}\n             */\n            getIcons: function (type) {\n                return window.checkoutConfig.payment.braintree.icons.hasOwnProperty(type) ?\n                    window.checkoutConfig.payment.braintree.icons[type]\n                    : false;\n            },\n        });\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/paypal-vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Vault/js/view/payment/method-renderer/vault',\n    'Magento_Ui/js/model/messageList',\n    'Magento_Checkout/js/model/full-screen-loader'\n], function ($, _, VaultComponent, globalMessageList, fullScreenLoader) {\n    'use strict';\n\n    return VaultComponent.extend({\n        defaults: {\n            template: 'PayPal_Braintree/payment/paypal/vault',\n            additionalData: {}\n        },\n\n        /**\n         * Get PayPal payer email\n         * @returns {String}\n         */\n        getPayerEmail: function () {\n            return this.details.payerEmail;\n        },\n\n        /**\n         * Get type of payment\n         * @returns {String}\n         */\n        getPaymentIcon: function () {\n            return window.checkoutConfig.payment['braintree_paypal'].paymentIcon;\n        },\n\n        /**\n         * Place order\n         */\n        beforePlaceOrder: function () {\n            this.getPaymentMethodNonce();\n        },\n\n        /**\n         * Send request to get payment method nonce\n         */\n        getPaymentMethodNonce: function () {\n            var self = this;\n\n            fullScreenLoader.startLoader();\n            $.getJSON(self.nonceUrl, {\n                'public_hash': self.publicHash\n            })\n                .done(function (response) {\n                    fullScreenLoader.stopLoader();\n                    self.additionalData['payment_method_nonce'] = response.paymentMethodNonce;\n                    self.placeOrder();\n                })\n                .fail(function (response) {\n                    var error = JSON.parse(response.responseText);\n\n                    fullScreenLoader.stopLoader();\n                    globalMessageList.addErrorMessage({\n                        message: error.message\n                    });\n                });\n        },\n\n        /**\n         * Get payment method data\n         * @returns {Object}\n         */\n        getData: function () {\n            var data = {\n                'method': this.code,\n                'additional_data': {\n                    'public_hash': this.publicHash\n                }\n            };\n\n            data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n            return data;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/hosted-fields.js":"/**\n * Copyright 2013-2017 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\n\ndefine([\n    'jquery',\n    'PayPal_Braintree/js/view/payment/method-renderer/cc-form',\n    'PayPal_Braintree/js/validator',\n    'Magento_Vault/js/view/payment/vault-enabler',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'mage/translate'\n], function ($, Component, validator, VaultEnabler, additionalValidators, $t) {\n    'use strict';\n\n    return Component.extend({\n\n        defaults: {\n            template: 'PayPal_Braintree/payment/form',\n            clientConfig: {\n\n                /**\n                 * {String}\n                 */\n                id: 'co-transparent-form-braintree'\n            },\n            isValidCardNumber: false,\n            isValidExpirationDate: false,\n            isValidCvvNumber: false,\n\n            onInstanceReady: function (instance) {\n                instance.on('validityChange', this.onValidityChange.bind(this));\n                instance.on('cardTypeChange', this.onCardTypeChange.bind(this));\n            }\n        },\n\n        /**\n         * @returns {exports.initialize}\n         */\n        initialize: function () {\n            this._super();\n            this.vaultEnabler = new VaultEnabler();\n            this.vaultEnabler.setPaymentCode(this.getVaultCode());\n\n            return this;\n        },\n\n        /**\n         * Init config\n         */\n        initClientConfig: function () {\n            this._super();\n\n            this.clientConfig.hostedFields = this.getHostedFields();\n            this.clientConfig.onInstanceReady = this.onInstanceReady.bind(this);\n        },\n\n        /**\n         * @returns {Object}\n         */\n        getData: function () {\n            var data = this._super();\n\n            this.vaultEnabler.visitAdditionalData(data);\n\n            return data;\n        },\n\n        /**\n         * @returns {Bool}\n         */\n        isVaultEnabled: function () {\n            return this.vaultEnabler.isVaultEnabled();\n        },\n\n        /**\n         * Get Braintree Hosted Fields\n         * @returns {Object}\n         */\n        getHostedFields: function () {\n            var self = this,\n                fields = {\n                    number: {\n                        selector: self.getSelector('cc_number'),\n                        placeholder: $t('4111 1111 1111 1111')\n                    },\n                    expirationDate: {\n                        selector: self.getSelector('expirationDate'),\n                        placeholder: $t('MM/YYYY')\n                    }\n                };\n\n            if (self.hasVerification()) {\n                fields.cvv = {\n                    selector: self.getSelector('cc_cid'),\n                    placeholder: $t('123')\n                };\n            }\n\n            return fields;\n        },\n\n        /**\n         * Triggers on Hosted Field changes\n         * @param {Object} event\n         * @returns {Boolean}\n         */\n        onValidityChange: function (event) {\n            // Handle a change in validation or card type\n            if (event.emittedBy === 'number') {\n                this.selectedCardType(null);\n\n                if (event.cards.length === 1) {\n                    this.isValidCardNumber = event.fields.number.isValid;\n                    this.selectedCardType(\n                        validator.getMageCardType(event.cards[0].type, this.getCcAvailableTypes())\n                    );\n                    this.validateCardType();\n                } else {\n                    this.isValidCardNumber = event.fields.number.isValid;\n                    this.validateCardType();\n                }\n            }\n\n            // Other field validations\n            if (event.emittedBy === 'expirationDate') {\n                this.isValidExpirationDate = event.fields.expirationDate.isValid;\n            }\n            if (event.emittedBy === 'cvv') {\n                this.isValidCvvNumber = event.fields.cvv.isValid;\n            }\n        },\n\n        /**\n         * Triggers on Hosted Field card type changes\n         * @param {Object} event\n         * @returns {Boolean}\n         */\n        onCardTypeChange: function (event) {\n            if (event.cards.length === 1) {\n                this.selectedCardType(\n                    validator.getMageCardType(event.cards[0].type, this.getCcAvailableTypes())\n                );\n            } else {\n                this.selectedCardType(null);\n            }\n        },\n\n        /**\n         * Toggle invalid class on selector\n         * @param selector\n         * @param state\n         * @returns {boolean}\n         */\n        validateField: function (selector, state) {\n            var $selector = $(this.getSelector(selector)),\n                invalidClass = 'braintree-hosted-fields-invalid';\n\n            if (state === true) {\n                $selector.removeClass(invalidClass);\n                return true;\n            }\n\n            $selector.addClass(invalidClass);\n            return false;\n        },\n\n        /**\n         * Validate current credit card type\n         * @returns {Boolean}\n         */\n        validateCardType: function () {\n            return this.validateField(\n                'cc_number',\n                (this.isValidCardNumber)\n            );\n        },\n\n        /**\n         * Validate current expiry date\n         * @returns {boolean}\n         */\n        validateExpirationDate: function () {\n            return this.validateField(\n                'expirationDate',\n                (this.isValidExpirationDate === true)\n            );\n        },\n\n        /**\n         * Validate current CVV field\n         * @returns {boolean}\n         */\n        validateCvvNumber: function () {\n            var self = this;\n\n            if (self.hasVerification() === false) {\n                return true;\n            }\n\n            return this.validateField(\n                'cc_cid',\n                (this.isValidCvvNumber === true)\n            );\n        },\n\n        /**\n         * Validate all fields\n         * @returns {boolean}\n         */\n        validateFormFields: function () {\n            return (this.validateCardType() && this.validateExpirationDate() && this.validateCvvNumber()) === true;\n        },\n\n        /**\n         * Trigger order placing\n         */\n        placeOrderClick: function () {\n            if (this.validateFormFields() && additionalValidators.validate()) {\n                this.placeOrder();\n            }\n        },\n        /**\n         * @returns {String}\n         */\n        getVaultCode: function () {\n            return window.checkoutConfig.payment[this.getCode()].ccVaultCode;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/lpm.js":"define(\n    [\n        'Magento_Checkout/js/view/payment/default',\n        'ko',\n        'jquery',\n        'braintree',\n        'braintreeLpm',\n        'PayPal_Braintree/js/form-builder',\n        'Magento_Ui/js/model/messageList',\n        'Magento_Checkout/js/action/select-billing-address',\n        'Magento_Checkout/js/model/full-screen-loader',\n        'Magento_Checkout/js/model/quote',\n        'Magento_Checkout/js/model/payment/additional-validators',\n        'mage/url',\n        'mage/translate'\n    ],\n    function (\n        Component,\n        ko,\n        $,\n        braintree,\n        lpm,\n        formBuilder,\n        messageList,\n        selectBillingAddress,\n        fullScreenLoader,\n        quote,\n        additionalValidators,\n        url,\n        $t\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                code: 'braintree_local_payment',\n                paymentMethodsAvailable: ko.observable(false),\n                paymentMethodNonce: null,\n                template: 'PayPal_Braintree/payment/lpm'\n            },\n\n            clickPaymentBtn: function (method) {\n                var self = this;\n\n                if (additionalValidators.validate()) {\n                    fullScreenLoader.startLoader();\n\n                    braintree.create({\n                        authorization: self.getClientToken()\n                    }, function (clientError, clientInstance) {\n                        if (clientError) {\n                            self.setErrorMsg($t('Unable to initialize Braintree Client.'));\n                            fullScreenLoader.stopLoader();\n                            return;\n                        }\n\n                        lpm.create({\n                            client: clientInstance,\n                            merchantAccountId: self.getMerchantAccountId()\n                        }, function (lpmError, lpmInstance) {\n                            if (lpmError) {\n                                self.setErrorMsg(lpmError);\n                                fullScreenLoader.stopLoader();\n                                return;\n                            }\n\n                            lpmInstance.startPayment({\n                                amount: self.getAmount(),\n                                currencyCode: self.getCurrencyCode(),\n                                email: self.getCustomerDetails().email,\n                                phone: self.getCustomerDetails().phone,\n                                givenName: self.getCustomerDetails().firstName,\n                                surname: self.getCustomerDetails().lastName,\n                                shippingAddressRequired: !quote.isVirtual(),\n                                address: self.getAddress(),\n                                paymentType: method,\n                                onPaymentStart: function (data, start) {\n                                    start();\n                                },\n                                // This is a required option, however it will apparently never be used in the current payment flow.\n                                // Therefore, both values are set to allow the payment flow to continute, rather than erroring out.\n                                fallback: {\n                                    url: 'N/A',\n                                    buttonText: 'N/A'\n                                }\n                            }, function (startPaymentError, payload) {\n                                fullScreenLoader.stopLoader();\n                                if (startPaymentError) {\n                                    switch (startPaymentError.code) {\n                                        case 'LOCAL_PAYMENT_POPUP_CLOSED':\n                                            self.setErrorMsg($t('Local Payment popup was closed unexpectedly.'));\n                                            break;\n                                        case 'LOCAL_PAYMENT_WINDOW_OPEN_FAILED':\n                                            self.setErrorMsg($t('Local Payment popup failed to open.'));\n                                            break;\n                                        case 'LOCAL_PAYMENT_WINDOW_CLOSED':\n                                            self.setErrorMsg($t('Local Payment popup was closed. Payment cancelled.'));\n                                            break;\n                                        default:\n                                            self.setErrorMsg('Error! ' + startPaymentError);\n                                            break;\n                                    }\n                                } else {\n                                    // Send the nonce to your server to create a transaction\n                                    self.setPaymentMethodNonce(payload.nonce);\n                                    self.placeOrder();\n                                }\n                            });\n                        });\n                    });\n                }\n            },\n\n            getAddress: function () {\n                var shippingAddress = quote.shippingAddress();\n\n                if (quote.isVirtual()) {\n                    return {\n                        countryCode: shippingAddress.countryId\n                    }\n                }\n\n                return {\n                    streetAddress: shippingAddress.street[0],\n                    extendedAddress: shippingAddress.street[1],\n                    locality: shippingAddress.city,\n                    postalCode: shippingAddress.postcode,\n                    region: shippingAddress.region,\n                    countryCode: shippingAddress.countryId\n                }\n            },\n\n            getAmount: function () {\n                return quote.totals()['base_grand_total'].toString();\n            },\n\n            getBillingAddress: function () {\n                return quote.billingAddress();\n            },\n\n            getClientToken: function () {\n                return window.checkoutConfig.payment[this.getCode()].clientToken;\n            },\n\n            getCode: function () {\n                return this.code;\n            },\n\n            getCurrencyCode: function () {\n                return quote.totals()['base_currency_code'];\n            },\n\n            getCustomerDetails: function () {\n                var billingAddress = quote.billingAddress();\n                return {\n                    firstName: billingAddress.firstname,\n                    lastName: billingAddress.lastname,\n                    phone: billingAddress.telephone,\n                    email: typeof quote.guestEmail === 'string' ? quote.guestEmail : window.checkoutConfig.customerData.email\n                }\n            },\n\n            getData: function () {\n                let data = {\n                    'method': this.getCode(),\n                    'additional_data': {\n                        'payment_method_nonce': this.paymentMethodNonce,\n                    }\n                };\n\n                data['additional_data'] = _.extend(data['additional_data'], this.additionalData);\n\n                return data;\n            },\n\n            getMerchantAccountId: function () {\n                return window.checkoutConfig.payment[this.getCode()].merchantAccountId;\n            },\n\n            getPaymentMethod: function (method) {\n                var methods = this.getPaymentMethods();\n\n                for (var i = 0; i < methods.length; i++) {\n                    if (methods[i].method === method) {\n                        return methods[i]\n                    }\n                }\n            },\n\n            getPaymentMethods: function () {\n                return window.checkoutConfig.payment[this.getCode()].allowedMethods;\n            },\n\n            getPaymentMarkSrc: function () {\n                return window.checkoutConfig.payment[this.getCode()].paymentIcons;\n            },\n\n            getTitle: function () {\n                return window.checkoutConfig.payment[this.getCode()].title;\n            },\n\n            initialize: function () {\n                this._super();\n                return this;\n            },\n\n            isActive: function () {\n                var address = quote.billingAddress() || quote.shippingAddress();\n                var methods = this.getPaymentMethods();\n\n                for (var i = 0; i < methods.length; i++) {\n                    if (methods[i].countries.includes(address.countryId)) {\n                        return true;\n                    }\n                }\n\n                return false;\n            },\n\n            isValidCountryAndCurrency: function (method) {\n                var address = quote.billingAddress();\n\n                if (!address) {\n                    this.paymentMethodsAvailable(false);\n                    return false;\n                }\n\n                var countryId = address.countryId;\n                var quoteCurrency = quote.totals()['base_currency_code'];\n                var paymentMethodDetails = this.getPaymentMethod(method);\n\n                if ((countryId !== 'GB' && paymentMethodDetails.countries.includes(countryId) && (quoteCurrency === 'EUR' || quoteCurrency === 'PLN')) || (countryId === 'GB' && paymentMethodDetails.countries.includes(countryId) && quoteCurrency === 'GBP')) {\n                    this.paymentMethodsAvailable(true);\n                    return true;\n                }\n\n                return false;\n            },\n\n            setErrorMsg: function (message) {\n                messageList.addErrorMessage({\n                    message: message\n                });\n            },\n\n            setPaymentMethodNonce: function (nonce) {\n                this.paymentMethodNonce = nonce;\n            },\n\n            validateForm: function (form) {\n                return $(form).validation() && $(form).validation('isValid');\n            }\n        });\n    }\n);\n","PayPal_Braintree/js/view/payment/method-renderer/multishipping/paypal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine([\n    'jquery',\n    'underscore',\n    'braintreeCheckoutPayPalAdapter',\n    'Magento_Checkout/js/model/quote',\n    'PayPal_Braintree/js/view/payment/method-renderer/paypal',\n    'Magento_Checkout/js/action/set-payment-information',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'mage/translate'\n], function (\n    $,\n    _,\n    Braintree,\n    quote,\n    Component,\n    setPaymentInformationAction,\n    additionalValidators,\n    fullScreenLoader,\n    $t\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/payment/multishipping/paypal',\n            submitButtonSelector: '[id=\"parent-payment-continue\"]',\n            reviewButtonHtml: ''\n        },\n\n        /**\n         * @override\n         */\n        initObservable: function () {\n            this.reviewButtonHtml = $(this.submitButtonSelector).html();\n            return this._super();\n        },\n\n        initClientConfig: function () {\n            this.clientConfig = _.extend(this.clientConfig, this.getPayPalConfig());\n            this.clientConfig.paypal.enableShippingAddress = false;\n\n            _.each(this.clientConfig, function (fn, name) {\n                if (typeof fn === 'function') {\n                    this.clientConfig[name] = fn.bind(this);\n                }\n            }, this);\n            this.clientConfig.buttonPayPalId = 'parent-payment-continue';\n\n        },\n\n        /**\n         * @override\n         */\n        onActiveChange: function (isActive) {\n            this.updateSubmitButtonHtml(isActive);\n            this._super(isActive);\n        },\n\n        /**\n         * @override\n         */\n        beforePlaceOrder: function (data) {\n            this._super(data);\n        },\n\n        /**\n         * Re-init PayPal Auth Flow\n         */\n        reInitPayPal: function () {\n            this.disableButton();\n            this.clientConfig.paypal.amount = parseFloat(this.grandTotalAmount).toFixed(2);\n\n            if (!quote.isVirtual()) {\n                this.clientConfig.paypal.enableShippingAddress = false;\n                this.clientConfig.paypal.shippingAddressEditable = false;\n            }\n\n            Braintree.setConfig(this.clientConfig);\n\n            if (Braintree.getPayPalInstance()) {\n                Braintree.getPayPalInstance().teardown(function () {\n                    Braintree.setup();\n                }.bind(this));\n                Braintree.setPayPalInstance(null);\n            } else {\n                Braintree.setup();\n                this.enableButton();\n            }\n        },\n\n        loadPayPalButton: function (paypalCheckoutInstance, funding) {\n            let paypalPayment = Braintree.config.paypal,\n                onPaymentMethodReceived = Braintree.config.onPaymentMethodReceived;\n            let style = {\n                color: Braintree.getColor(funding),\n                shape: Braintree.getShape(funding),\n                size: Braintree.getSize(funding),\n                label: Braintree.getLabel(funding)\n            };\n\n            if (Braintree.getBranding()) {\n                style.branding = Braintree.getBranding();\n            }\n            if (Braintree.getFundingIcons()) {\n                style.fundingicons = Braintree.getFundingIcons();\n            }\n\n            if (funding === 'credit') {\n                Braintree.config.buttonId = this.clientConfig.buttonCreditId;\n            } else if (funding === 'paylater') {\n                Braintree.config.buttonId = this.clientConfig.buttonPaylaterId;\n            } else {\n                Braintree.config.buttonId = this.clientConfig.buttonPayPalId;\n            }\n\n            // Render\n            Braintree.config.paypalInstance = paypalCheckoutInstance;\n            var events = Braintree.events;\n            $('#' + Braintree.config.buttonId).html('');\n\n            var button = paypal.Buttons({\n                fundingSource: funding,\n                env: Braintree.getEnvironment(),\n                style: style,\n                commit: true,\n                locale: Braintree.config.paypal.locale,\n\n                createOrder: function () {\n                    return paypalCheckoutInstance.createPayment(paypalPayment);\n                },\n\n                onCancel: function (data) {\n                    console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));\n\n                    if (typeof events.onCancel === 'function') {\n                        events.onCancel();\n                    }\n                },\n\n                onError: function (err) {\n                    Braintree.showError($t(\"PayPal Checkout could not be initialized. Please contact the store owner.\"));\n                    Braintree.config.paypalInstance = null;\n                    console.error('Paypal checkout.js error', err);\n\n                    if (typeof events.onError === 'function') {\n                        events.onError(err);\n                    }\n                }.bind(this),\n\n                onClick: function (data) {\n                    // To check term & conditions input checked - validate additional validators.\n                    if (!additionalValidators.validate()) {\n                        return false;\n                    }\n\n                    if (typeof events.onClick === 'function') {\n                        events.onClick(data);\n                    }\n                }.bind(this),\n\n                onApprove: function (data, actions) {\n                    return paypalCheckoutInstance.tokenizePayment(data)\n                        .then(function (payload) {\n                            onPaymentMethodReceived(payload);\n                        });\n                }\n\n            });\n            if (button.isEligible() && $('#' + Braintree.config.buttonId).length) {\n\n                button.render('#' + Braintree.config.buttonId).then(function () {\n                    Braintree.enableButton();\n                    if (typeof Braintree.config.onPaymentMethodError === 'function') {\n                        Braintree.config.onPaymentMethodError();\n                    }\n                }.bind(this)).then(function (data) {\n                    if (typeof events.onRender === 'function') {\n                        events.onRender(data);\n                    }\n                });\n            }\n        },\n\n        /**\n         * Get configuration for PayPal\n         * @returns {Object}\n         */\n        getPayPalConfig: function () {\n            var totals = quote.totals(),\n                config = {},\n                isActiveVaultEnabler = this.isActiveVault();\n\n            config.paypal = {\n                flow: 'checkout',\n                amount: parseFloat(this.grandTotalAmount).toFixed(2),\n                currency: totals['base_currency_code'],\n                locale: this.getLocale(),\n                requestBillingAgreement: true,\n                /**\n                 * Triggers on any Braintree error\n                 */\n                onError: function () {\n                    this.paymentMethodNonce = null;\n                },\n\n                /**\n                 * Triggers if browser doesn't support PayPal Checkout\n                 */\n                onUnsupported: function () {\n                    this.paymentMethodNonce = null;\n                }\n            };\n\n            if (!quote.isVirtual()) {\n                config.paypal.enableShippingAddress = false;\n                config.paypal.shippingAddressEditable = false;\n            }\n\n            if (this.getMerchantName()) {\n                config.paypal.displayName = this.getMerchantName();\n            }\n\n            return config;\n        },\n\n        getShippingAddress: function () {\n\n            return {};\n        },\n\n        /**\n         * @override\n         */\n        getData: function () {\n            var data = this._super();\n\n            data['additional_data']['is_active_payment_token_enabler'] = true;\n\n            return data;\n        },\n\n        /**\n         * @override\n         */\n        isActiveVault: function () {\n            return true;\n        },\n\n        /**\n         * Skipping order review step on checkout with multiple addresses is not allowed.\n         *\n         * @returns {Boolean}\n         */\n        isSkipOrderReview: function () {\n            return false;\n        },\n\n        /**\n         * Checks if payment method nonce is already received.\n         *\n         * @returns {Boolean}\n         */\n        isPaymentMethodNonceReceived: function () {\n            return this.paymentMethodNonce !== null;\n        },\n\n        /**\n         * Update submit button on multi-addresses checkout billing form.\n         *\n         * @param {Boolean} isActive\n         */\n        updateSubmitButtonHtml: function (isActive) {\n            $(this.submitButtonSelector).removeClass(\"primary\");\n            if (this.isPaymentMethodNonceReceived() || !isActive) {\n                $(this.submitButtonSelector).addClass(\"primary\");\n                $(this.submitButtonSelector).html(this.reviewButtonHtml);\n            }\n        },\n\n        /**\n         * @override\n         */\n        placeOrder: function () {\n            if (!this.isPaymentMethodNonceReceived()) {\n                this.payWithPayPal();\n            } else {\n                fullScreenLoader.startLoader();\n\n                $.when(\n                    setPaymentInformationAction(\n                        this.messageContainer,\n                        this.getData()\n                    )\n                ).done(this.done.bind(this))\n                    .fail(this.fail.bind(this));\n            }\n        },\n\n        /**\n         * {Function}\n         */\n        fail: function () {\n            fullScreenLoader.stopLoader();\n\n            return this;\n        },\n\n        /**\n         * {Function}\n         */\n        done: function () {\n            fullScreenLoader.stopLoader();\n            $('#multishipping-billing-form').submit();\n\n            return this;\n        }\n    });\n});\n","PayPal_Braintree/js/view/payment/method-renderer/multishipping/hosted-fields.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\n\ndefine([\n    'jquery',\n    'PayPal_Braintree/js/view/payment/method-renderer/hosted-fields',\n    'PayPal_Braintree/js/validator',\n    'Magento_Ui/js/model/messageList',\n    'mage/translate',\n    'Magento_Checkout/js/model/full-screen-loader',\n    'Magento_Checkout/js/action/set-payment-information',\n    'Magento_Checkout/js/model/payment/additional-validators',\n    'PayPal_Braintree/js/view/payment/adapter'\n], function (\n    $,\n    Component,\n    validator,\n    messageList,\n    $t,\n    fullScreenLoader,\n    setPaymentInformationAction,\n    additionalValidators,\n    braintree\n) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            template: 'PayPal_Braintree/payment/multishipping/form'\n        },\n\n        /**\n         * Get list of available CC types\n         *\n         * @returns {Object}\n         */\n        getCcAvailableTypes: function () {\n            let availableTypes = validator.getAvailableCardTypes(),\n                billingCountryId;\n\n            billingCountryId = $('#multishipping_billing_country_id').val();\n\n            if (billingCountryId && validator.getCountrySpecificCardTypes(billingCountryId)) {\n                return validator.collectTypes(\n                    availableTypes, validator.getCountrySpecificCardTypes(billingCountryId)\n                );\n            }\n\n            return availableTypes;\n        },\n\n        /**\n         * @override\n         */\n        handleNonce: function (payload) {\n            let self = this;\n            this.setPaymentMethodNonce(payload.nonce);\n            this.setCreditCardBin(payload.details.bin);\n\n            // place order on success validation\n            self.validatorManager.validate(self, function () {\n                return self.setPaymentInformation();\n            }, function() {\n                self.isProcessing = false;\n                self.paymentMethodNonce = null;\n                self.creditCardBin = null;\n            });\n        },\n\n        /**\n         * @override\n         */\n        placeOrder: function () {\n            if (this.isProcessing) {\n                return false;\n            } else {\n                this.isProcessing = true;\n            }\n\n            braintree.tokenizeHostedFields();\n            return false;\n        },\n\n        /**\n         * @override\n         */\n        setPaymentInformation: function () {\n            if (additionalValidators.validate()) {\n                fullScreenLoader.startLoader();\n                $.when(\n                    setPaymentInformationAction(\n                        this.messageContainer,\n                        this.getData()\n                    )\n                ).done(this.done.bind(this))\n                    .fail(this.fail.bind(this));\n            }\n        },\n\n        /**\n         * {Function}\n         */\n        fail: function () {\n            fullScreenLoader.stopLoader();\n\n            return this;\n        },\n\n        /**\n         * {Function}\n         */\n        done: function () {\n            fullScreenLoader.stopLoader();\n            $('#multishipping-billing-form').submit();\n\n            return this;\n        }\n    });\n});\n","PayPal_Braintree/js/applepay/api.js":"/**\n * Braintree Apple Pay button API\n *\n **/\ndefine(\n    [\n        'jquery',\n        'underscore',\n        'uiComponent',\n        'mage/translate',\n        'mage/storage',\n        'Magento_Customer/js/customer-data'\n    ],\n    function (\n        $,\n        _,\n        Component,\n        $t,\n        storage,\n        customerData\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                clientToken: null,\n                quoteId: 0,\n                displayName: null,\n                actionSuccess: null,\n                grandTotalAmount: 0,\n                isLoggedIn: false,\n                storeCode: \"default\",\n                shippingAddress: {},\n                countryDirectory: null,\n                shippingMethods: {}\n            },\n\n            initialize: function () {\n                this._super();\n                if (!this.countryDirectory) {\n                    storage.get(\"rest/V1/directory/countries\").done(function (result) {\n                        this.countryDirectory = {};\n                        let i, data, x, region;\n                        for (i = 0; i < result.length; ++i) {\n                            data = result[i];\n                            this.countryDirectory[data.two_letter_abbreviation] = {};\n                            if (typeof data.available_regions !== 'undefined') {\n                                for (x = 0; x < data.available_regions.length; ++x) {\n                                    region = data.available_regions[x];\n                                    this.countryDirectory[data.two_letter_abbreviation][region.name.toLowerCase().replace(/[^A-Z0-9]/ig, '')] = region.id;\n                                }\n                            }\n                        }\n                    }.bind(this));\n                }\n            },\n\n            /**\n             * Get region ID\n             */\n            getRegionId: function (countryCode, regionName) {\n                if (typeof regionName !== 'string') {\n                    return null;\n                }\n\n                regionName = regionName.toLowerCase().replace(/[^A-Z0-9]/ig, '');\n\n                if (typeof this.countryDirectory[countryCode] !== 'undefined' && typeof this.countryDirectory[countryCode][regionName] !== 'undefined') {\n                    return this.countryDirectory[countryCode][regionName];\n                }\n\n                return 0;\n            },\n\n            /**\n             * Set & get api token\n             */\n            setClientToken: function (value) {\n                this.clientToken = value;\n            },\n            getClientToken: function () {\n                return this.clientToken;\n            },\n\n            /**\n             * Set and get quote id\n             */\n            setQuoteId: function (value) {\n                this.quoteId = value;\n            },\n            getQuoteId: function () {\n                return this.quoteId;\n            },\n\n            /**\n             * Set and get display name\n             */\n            setDisplayName: function (value) {\n                this.displayName = value;\n            },\n            getDisplayName: function () {\n                return this.displayName;\n            },\n\n            /**\n             * Set and get success redirection url\n             */\n            setActionSuccess: function (value) {\n                this.actionSuccess = value;\n            },\n            getActionSuccess: function () {\n                return this.actionSuccess;\n            },\n\n            /**\n             * Set and get grand total\n             */\n            setGrandTotalAmount: function (value) {\n                this.grandTotalAmount = parseFloat(value).toFixed(2);\n            },\n            getGrandTotalAmount: function () {\n                return parseFloat(this.grandTotalAmount);\n            },\n\n            /**\n             * Set and get is logged in\n             */\n            setIsLoggedIn: function (value) {\n                this.isLoggedIn = value;\n            },\n            getIsLoggedIn: function () {\n                return this.isLoggedIn;\n            },\n\n            /**\n             * Set and get store code\n             */\n            setStoreCode: function (value) {\n                this.storeCode = value;\n            },\n            getStoreCode: function () {\n                return this.storeCode;\n            },\n\n            /**\n             * API Urls for logged in / guest\n             */\n            getApiUrl: function (uri) {\n                if (this.getIsLoggedIn() === true) {\n                    return \"rest/\" + this.getStoreCode() + \"/V1/carts/mine/\" + uri;\n                } else {\n                    return \"rest/\" + this.getStoreCode() + \"/V1/guest-carts/\" + this.getQuoteId() + \"/\" + uri;\n                }\n            },\n\n            /**\n             * Payment request info\n             */\n            getPaymentRequest: function () {\n                return {\n                    total: {\n                        label: this.getDisplayName(),\n                        amount: this.getGrandTotalAmount()\n                    },\n                    requiredShippingContactFields: ['postalAddress', 'name', 'email', 'phone'],\n                    requiredBillingContactFields: ['postalAddress', 'name']\n                };\n            },\n\n            /**\n             * Retrieve shipping methods based on address\n             */\n            onShippingContactSelect: function (event, session) {\n                // Get the address.\n                let address = event.shippingContact;\n\n                // Create a payload.\n                let payload = {\n                    address: {\n                        city: address.locality,\n                        region: address.administrativeArea,\n                        country_id: address.countryCode.toUpperCase(),\n                        postcode: address.postalCode,\n                        save_in_address_book: 0\n                    }\n                };\n\n                this.shippingAddress = payload.address;\n\n                // POST to endpoint for shipping methods.\n                storage.post(\n                    this.getApiUrl(\"estimate-shipping-methods\"),\n                    JSON.stringify(payload)\n                ).done(function (result) {\n                    // Stop if no shipping methods.\n                    let virtualFlag = false;\n                    if (result.length === 0) {\n                        let productItems = customerData.get('cart')().items;\n                        _.each(productItems,\n                            function (item) {\n                                if (item.is_virtual || item.product_type == 'bundle') {\n                                    virtualFlag = true;\n                                } else {\n                                    virtualFlag = false;\n                                }\n                            }\n                        );\n                        if (!virtualFlag) {\n                            session.abort();\n                            alert($t(\"There are no shipping methods available for you right now. Please try again or use an alternative payment method.\"));\n                            return false;\n                        }\n                    }\n\n                    let shippingMethods = [];\n                    this.shippingMethods = {};\n\n                    // Format shipping methods array.\n                    for (let i = 0; i < result.length; i++) {\n                        if (typeof result[i].method_code !== 'string') {\n                            continue;\n                        }\n\n                        let method = {\n                            identifier: result[i].method_code,\n                            label: result[i].method_title,\n                            detail: result[i].carrier_title ? result[i].carrier_title : \"\",\n                            amount: parseFloat(result[i].amount).toFixed(2)\n                        };\n\n                        // Add method object to array.\n                        shippingMethods.push(method);\n\n                        this.shippingMethods[result[i].method_code] = result[i];\n\n                        if (!this.shippingMethod) {\n                            this.shippingMethod = result[i].method_code;\n                        }\n                    }\n\n                    // Create payload to get totals\n                    let totalsPayload = {\n                        \"addressInformation\": {\n                            \"address\": {\n                                \"countryId\": this.shippingAddress.country_id,\n                                \"region\": this.shippingAddress.region,\n                                \"regionId\": this.getRegionId(this.shippingAddress.country_id, this.shippingAddress.region),\n                                \"postcode\": this.shippingAddress.postcode\n                            },\n                            \"shipping_method_code\": virtualFlag ? null : this.shippingMethods[shippingMethods[0].identifier].method_code,\n                            \"shipping_carrier_code\": virtualFlag ? null : this.shippingMethods[shippingMethods[0].identifier].carrier_code\n                        }\n                    };\n\n                    // POST to endpoint to get totals, using 1st shipping method\n                    storage.post(\n                        this.getApiUrl(\"totals-information\"),\n                        JSON.stringify(totalsPayload)\n                    ).done(function (result) {\n                        // Set total\n                        this.setGrandTotalAmount(result.base_grand_total);\n\n                        // Pass shipping methods back\n                        session.completeShippingContactSelection(\n                            ApplePaySession.STATUS_SUCCESS,\n                            shippingMethods,\n                            {\n                                label: this.getDisplayName(),\n                                amount: this.getGrandTotalAmount()\n                            },\n                            [{\n                                type: 'final',\n                                label: $t('Shipping'),\n                                amount: virtualFlag ? 0 : shippingMethods[0].amount\n                            }]\n                        );\n                    }.bind(this)).fail(function (result) {\n                        session.abort();\n                        alert($t(\"We're unable to fetch the cart totals for you. Please try an alternative payment method.\"));\n                        console.error(\"Braintree ApplePay: Unable to get totals\", result);\n                        return false;\n                    });\n\n                }.bind(this)).fail(function (result) {\n                    session.abort();\n                    alert($t(\"We're unable to find any shipping methods for you. Please try an alternative payment method.\"));\n                    console.error(\"Braintree ApplePay: Unable to find shipping methods for estimate-shipping-methods\", result);\n                    return false;\n                });\n            },\n\n            /**\n             * Record which shipping method has been selected & Updated totals\n             */\n            onShippingMethodSelect: function (event, session) {\n                let shippingMethod = event.shippingMethod;\n                this.shippingMethod = shippingMethod.identifier;\n\n                let payload = {\n                    \"addressInformation\": {\n                        \"address\": {\n                            \"countryId\": this.shippingAddress.country_id,\n                            \"region\": this.shippingAddress.region,\n                            \"regionId\": this.getRegionId(this.shippingAddress.country_id, this.shippingAddress.region),\n                            \"postcode\": this.shippingAddress.postcode\n                        },\n                        \"shipping_method_code\": this.shippingMethods[this.shippingMethod].method_code,\n                        \"shipping_carrier_code\": this.shippingMethods[this.shippingMethod].carrier_code\n                    }\n                };\n\n                storage.post(\n                    this.getApiUrl(\"totals-information\"),\n                    JSON.stringify(payload)\n                ).done(function (r) {\n                    this.setGrandTotalAmount(r.base_grand_total);\n\n                    session.completeShippingMethodSelection(\n                        ApplePaySession.STATUS_SUCCESS,\n                        {\n                            label: this.getDisplayName(),\n                            amount: this.getGrandTotalAmount()\n                        },\n                        [{\n                            type: 'final',\n                            label: $t('Shipping'),\n                            amount: shippingMethod.amount\n                        }]\n                    );\n                }.bind(this));\n            },\n\n            /**\n             * Place the order\n             */\n            startPlaceOrder: function (nonce, event, session, device_data) {\n                let shippingContact = event.payment.shippingContact,\n                    billingContact = event.payment.billingContact,\n                    payload = {\n                        \"addressInformation\": {\n                            \"shipping_address\": {\n                                \"email\": shippingContact.emailAddress,\n                                \"telephone\": shippingContact.phoneNumber,\n                                \"firstname\": shippingContact.givenName,\n                                \"lastname\": shippingContact.familyName,\n                                \"street\": shippingContact.addressLines,\n                                \"city\": shippingContact.locality,\n                                \"region\": shippingContact.administrativeArea,\n                                \"region_id\": this.getRegionId(shippingContact.countryCode.toUpperCase(), shippingContact.administrativeArea),\n                                \"region_code\": null,\n                                \"country_id\": shippingContact.countryCode.toUpperCase(),\n                                \"postcode\": shippingContact.postalCode,\n                                \"same_as_billing\": 0,\n                                \"customer_address_id\": 0,\n                                \"save_in_address_book\": 0\n                            },\n                            \"billing_address\": {\n                                \"email\": shippingContact.emailAddress,\n                                \"telephone\": shippingContact.phoneNumber,\n                                \"firstname\": billingContact.givenName,\n                                \"lastname\": billingContact.familyName,\n                                \"street\": billingContact.addressLines,\n                                \"city\": billingContact.locality,\n                                \"region\": billingContact.administrativeArea,\n                                \"region_id\": this.getRegionId(billingContact.countryCode.toUpperCase(), billingContact.administrativeArea),\n                                \"region_code\": null,\n                                \"country_id\": billingContact.countryCode.toUpperCase(),\n                                \"postcode\": billingContact.postalCode,\n                                \"same_as_billing\": 0,\n                                \"customer_address_id\": 0,\n                                \"save_in_address_book\": 0\n                            },\n                            \"shipping_method_code\": this.shippingMethod ? this.shippingMethods[this.shippingMethod].method_code : '' ,\n                            \"shipping_carrier_code\": this.shippingMethod ? this.shippingMethods[this.shippingMethod].carrier_code : ''\n                        }\n                    };\n\n                // Set addresses\n                storage.post(\n                    this.getApiUrl(\"shipping-information\"),\n                    JSON.stringify(payload)\n                ).done(function () {\n                    // Submit payment information\n                    let paymentInformation = {\n                            \"email\": shippingContact.emailAddress,\n                            \"paymentMethod\": {\n                                \"method\": \"braintree_applepay\",\n                                \"additional_data\": {\n                                    \"payment_method_nonce\": nonce,\n                                    \"device_data\": device_data\n                                }\n                            }\n                        };\n                    if (window.checkout && window.checkout.agreementIds) {\n                        paymentInformation.paymentMethod.extension_attributes = {\n                            \"agreement_ids\": window.checkout.agreementIds\n                        };\n                    }\n                    storage.post(\n                        this.getApiUrl(\"payment-information\"),\n                        JSON.stringify(paymentInformation)\n                    ).done(function (r) {\n                        document.location = this.getActionSuccess();\n                        session.completePayment(ApplePaySession.STATUS_SUCCESS);\n                    }.bind(this)).fail(function (r) {\n                        session.completePayment(ApplePaySession.STATUS_FAILURE);\n                        session.abort();\n                        alert($t(\"We're unable to take your payment through Apple Pay. Please try an again or use an alternative payment method.\"));\n                        console.error(\"Braintree ApplePay Unable to take payment\", r);\n                        return false;\n                    });\n\n                }.bind(this)).fail(function (r) {\n                    console.error(\"Braintree ApplePay Unable to set shipping information\", r);\n                    session.completePayment(ApplePaySession.STATUS_INVALID_BILLING_POSTAL_ADDRESS);\n                });\n            }\n        });\n    });\n"}
}});

Spamworldpro Mini