bundle1.js 937 KB
Newer Older
Ketan's avatar
Ketan committed
1 2 3
require.config({"config": {
        "jsbuild":{"mage/calendar.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/*eslint max-depth: 0*/\n(function (factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'jquery/ui',\n            'jquery/jquery-ui-timepicker-addon'\n        ], factory);\n    } else {\n        factory(window.jQuery);\n    }\n}(function ($) {\n    'use strict';\n\n    var calendarBasePrototype,\n        datepickerPrototype = $.datepicker.constructor.prototype;\n\n    $.datepicker.markerClassName = '_has-datepicker';\n\n    /**\n     * Extend JQuery date picker prototype with store local time methods\n     */\n    $.extend(datepickerPrototype, {\n        /**\n         * Get date/time according to store settings.\n         * We use serverTimezoneOffset (in seconds) instead of serverTimezoneSeconds\n         * in order to have ability to know actual store time even if page hadn't been reloaded\n         * @returns {Date}\n         */\n        _getTimezoneDate: function (options) {\n            // local time in ms\n            var ms = Date.now();\n\n            options = options || $.calendarConfig || {};\n\n            // Adjust milliseconds according to store timezone offset,\n            // mind the GMT zero offset\n            if (typeof options.serverTimezoneOffset !== 'undefined') {\n                // Make UTC time and add store timezone offset in seconds\n                ms += new Date().getTimezoneOffset() * 60 * 1000 + options.serverTimezoneOffset * 1000;\n            } else if (typeof options.serverTimezoneSeconds !== 'undefined') {\n                //Set milliseconds according to client local timezone offset\n                ms = (options.serverTimezoneSeconds + new Date().getTimezoneOffset() * 60) * 1000;\n            }\n\n            return new Date(ms);\n        },\n\n        /**\n         * Set date/time according to store settings.\n         * @param {String|Object} target - the target input field or division or span\n         */\n        _setTimezoneDateDatepicker: function (target) {\n            this._setDateDatepicker(target, this._getTimezoneDate());\n        }\n    });\n\n    /**\n     * Widget calendar\n     */\n    $.widget('mage.calendar', {\n        options: {\n            autoComplete: true\n        },\n\n        /**\n         * Merge global options with options passed to widget invoke\n         * @protected\n         */\n        _create: function () {\n            this._enableAMPM();\n            this.options = $.extend(\n                {},\n                $.calendarConfig ? $.calendarConfig : {},\n                this.options.showsTime ? {\n                    showTime: true,\n                    showHour: true,\n                    showMinute: true\n                } : {},\n                this.options\n            );\n            this._initPicker(this.element);\n            this._overwriteGenerateHtml();\n        },\n\n        /**\n         * Get picker name\n         * @protected\n         */\n        _picker: function () {\n            return this.options.showsTime ? 'datetimepicker' : 'datepicker';\n        },\n\n        /**\n         * Fix for Timepicker - Set ampm option for Timepicker if timeformat contains string 'tt'\n         * @protected\n         */\n        _enableAMPM: function () {\n            if (this.options.timeFormat && this.options.timeFormat.indexOf('tt') >= 0) {\n                this.options.ampm = true;\n            }\n        },\n\n        /**\n         * Wrapper for overwrite jQuery UI datepicker function.\n         */\n        _overwriteGenerateHtml: function () {\n            /**\n             * Overwrite jQuery UI datepicker function.\n             * Reason: magento date could be set before calendar show\n             * but local date will be styled as current in original _generateHTML\n             *\n             * @param {Object} inst - instance datepicker.\n             * @return {String} html template\n             */\n            $.datepicker.constructor.prototype._generateHTML = function (inst) {\n                var today = this._getTimezoneDate(),\n                    isRTL = this._get(inst, 'isRTL'),\n                    showButtonPanel = this._get(inst, 'showButtonPanel'),\n                    hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'),\n                    navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'),\n                    numMonths = this._getNumberOfMonths(inst),\n                    showCurrentAtPos = this._get(inst, 'showCurrentAtPos'),\n                    stepMonths = this._get(inst, 'stepMonths'),\n                    isMultiMonth = parseInt(numMonths[0], 10) !== 1 || parseInt(numMonths[1], 10) !== 1,\n                    currentDate = this._daylightSavingAdjust(!inst.currentDay ? new Date(9999, 9, 9) :\n                        new Date(inst.currentYear, inst.currentMonth, inst.currentDay)),\n                    minDate = this._getMinMaxDate(inst, 'min'),\n                    maxDate = this._getMinMaxDate(inst, 'max'),\n                    drawMonth = inst.drawMonth - showCurrentAtPos,\n                    drawYear = inst.drawYear,\n                    maxDraw,\n                    prevText = this._get(inst, 'prevText'),\n                    prev,\n                    nextText = this._get(inst, 'nextText'),\n                    next,\n                    currentText = this._get(inst, 'currentText'),\n                    gotoDate,\n                    controls,\n                    buttonPanel,\n                    firstDay,\n                    showWeek = this._get(inst, 'showWeek'),\n                    dayNames = this._get(inst, 'dayNames'),\n                    dayNamesMin = this._get(inst, 'dayNamesMin'),\n                    monthNames = this._get(inst, 'monthNames'),\n                    monthNamesShort =  this._get(inst, 'monthNamesShort'),\n                    beforeShowDay = this._get(inst, 'beforeShowDay'),\n                    showOtherMonths = this._get(inst, 'showOtherMonths'),\n                    selectOtherMonths = this._get(inst, 'selectOtherMonths'),\n                    defaultDate = this._getDefaultDate(inst),\n                    html = '',\n                    row = 0,\n                    col = 0,\n                    selectedDate,\n                    cornerClass = ' ui-corner-all',\n                    group = '',\n                    calender = '',\n                    dow = 0,\n                    thead,\n                    day,\n                    daysInMonth,\n                    leadDays,\n                    curRows,\n                    numRows,\n                    printDate,\n                    dRow = 0,\n                    tbody,\n                    daySettings,\n                    otherMonth,\n                    unselectable;\n\n                if (drawMonth < 0) {\n                    drawMonth += 12;\n                    drawYear--;\n                }\n\n                if (maxDate) {\n                    maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),\n                        maxDate.getMonth() - numMonths[0] * numMonths[1] + 1, maxDate.getDate()));\n                    maxDraw = minDate && maxDraw < minDate ? minDate : maxDraw;\n\n                    while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {\n                        drawMonth--;\n\n                        if (drawMonth < 0) {\n                            drawMonth = 11;\n                            drawYear--;\n\n                        }\n                    }\n                }\n                inst.drawMonth = drawMonth;\n                inst.drawYear = drawYear;\n                prevText = !navigationAsDateFormat ? prevText : this.formatDate(prevText,\n                    this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),\n                    this._getFormatConfig(inst));\n                prev = this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?\n                    '<a class=\"ui-datepicker-prev ui-corner-all\" data-handler=\"prev\" data-event=\"click\"' +\n                    ' title=\"' + prevText + '\">' +\n                    '<span class=\"ui-icon ui-icon-circle-triangle-' + (isRTL ? 'e' : 'w') + '\">' +\n                    '' + prevText + '</span></a>'\n                    : hideIfNoPrevNext ? ''\n                        :   '<a class=\"ui-datepicker-prev ui-corner-all ui-state-disabled\" title=\"' +\n                            '' + prevText + '\"><span class=\"ui-icon ui-icon-circle-triangle-' +\n                            '' + (isRTL ? 'e' : 'w') + '\">' + prevText + '</span></a>';\n                nextText = !navigationAsDateFormat ?\n                    nextText\n                    :   this.formatDate(nextText,\n                        this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),\n                        this._getFormatConfig(inst));\n                next = this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?\n                    '<a class=\"ui-datepicker-next ui-corner-all\" data-handler=\"next\" data-event=\"click\"' +\n                    'title=\"' + nextText + '\"><span class=\"ui-icon ui-icon-circle-triangle-' +\n                    '' + (isRTL ? 'w' : 'e') + '\">' + nextText + '</span></a>'\n                    : hideIfNoPrevNext ? ''\n                        :   '<a class=\"ui-datepicker-next ui-corner-all ui-state-disabled\" title=\"' + nextText + '\">' +\n                            '<span class=\"ui-icon ui-icon-circle-triangle-' + (isRTL ? 'w' : 'e') + '\">' + nextText +\n                            '</span></a>';\n                gotoDate = this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today;\n                currentText = !navigationAsDateFormat ? currentText :\n                    this.formatDate(currentText, gotoDate, this._getFormatConfig(inst));\n                controls = !inst.inline ?\n                    '<button type=\"button\" class=\"ui-datepicker-close ui-state-default ui-priority-primary ' +\n                    'ui-corner-all\" data-handler=\"hide\" data-event=\"click\">' +\n                    this._get(inst, 'closeText') + '</button>'\n                    : '';\n                buttonPanel = showButtonPanel ?\n                    '<div class=\"ui-datepicker-buttonpane ui-widget-content\">' + (isRTL ? controls : '') +\n                    (this._isInRange(inst, gotoDate) ? '<button type=\"button\" class=\"ui-datepicker-current ' +\n                    'ui-state-default ui-priority-secondary ui-corner-all\" data-handler=\"today\" data-event=\"click\"' +\n                    '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';\n                firstDay = parseInt(this._get(inst, 'firstDay'), 10);\n                firstDay = isNaN(firstDay) ? 0 : firstDay;\n\n                for (row = 0; row < numMonths[0]; row++) {\n                    this.maxRows = 4;\n\n                    for (col = 0; col < numMonths[1]; col++) {\n                        selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));\n\n                        calender = '';\n\n                        if (isMultiMonth) {\n                            calender += '<div class=\"ui-datepicker-group';\n\n                            if (numMonths[1] > 1) {\n                                switch (col) {\n                                    case 0: calender += ' ui-datepicker-group-first';\n                                        cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left');\n                                        break;\n\n                                    case numMonths[1] - 1: calender += ' ui-datepicker-group-last';\n                                        cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right');\n                                        break;\n\n                                    default: calender += ' ui-datepicker-group-middle'; cornerClass = '';\n                                }\n                            }\n                            calender += '\">';\n                        }\n                        calender += '<div class=\"ui-datepicker-header ' +\n                            'ui-widget-header ui-helper-clearfix' + cornerClass + '\">' +\n                            (/all|left/.test(cornerClass) && parseInt(row, 10) === 0 ? isRTL ? next : prev : '') +\n                            (/all|right/.test(cornerClass) && parseInt(row, 10) === 0 ? isRTL ? prev : next : '') +\n                            this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,\n                            row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers\n                            '</div><table class=\"ui-datepicker-calendar\"><thead>' +\n                            '<tr>';\n                        thead = showWeek ?\n                            '<th class=\"ui-datepicker-week-col\">' + this._get(inst, 'weekHeader') + '</th>' : '';\n\n                        for (dow = 0; dow < 7; dow++) { // days of the week\n                            day = (dow + firstDay) % 7;\n                            thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ?\n                                ' class=\"ui-datepicker-week-end\"' : '') + '>' +\n                                '<span title=\"' + dayNames[day] + '\">' + dayNamesMin[day] + '</span></th>';\n                        }\n                        calender += thead + '</tr></thead><tbody>';\n                        daysInMonth = this._getDaysInMonth(drawYear, drawMonth);\n\n                        if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {\n                            inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);\n                        }\n                        leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;\n                        curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate\n                        numRows = isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows;\n                        this.maxRows = numRows;\n                        printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));\n\n                        for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows\n                            calender += '<tr>';\n                            tbody = !showWeek ? '' : '<td class=\"ui-datepicker-week-col\">' +\n                            this._get(inst, 'calculateWeek')(printDate) + '</td>';\n\n                            for (dow = 0; dow < 7; dow++) { // create date picker days\n                                daySettings = beforeShowDay ?\n                                    beforeShowDay.apply(inst.input ? inst.input[0] : null, [printDate]) : [true, ''];\n                                otherMonth = printDate.getMonth() !== drawMonth;\n                                unselectable = otherMonth && !selectOtherMonths || !daySettings[0] ||\n                                minDate && printDate < minDate || maxDate && printDate > maxDate;\n                                tbody += '<td class=\"' +\n                                ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends\n                                (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months\n                                (printDate.getTime() === selectedDate.getTime() &&\n                                drawMonth === inst.selectedMonth && inst._keyEvent || // user pressed key\n                                defaultDate.getTime() === printDate.getTime() &&\n                                defaultDate.getTime() === selectedDate.getTime() ?\n                                    // or defaultDate is current printedDate and defaultDate is selectedDate\n                                ' ' + this._dayOverClass : '') + // highlight selected day\n                                (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled' : '') +\n                                (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates\n                                (printDate.getTime() === currentDate.getTime() ? ' ' + this._currentClass : '') +\n                                (printDate.getDate() === today.getDate() && printDate.getMonth() === today.getMonth() &&\n                                printDate.getYear() === today.getYear() ? ' ui-datepicker-today' : '')) + '\"' +\n                                ((!otherMonth || showOtherMonths) && daySettings[2] ?\n                                ' title=\"' + daySettings[2] + '\"' : '') + // cell title\n                                (unselectable ? '' : ' data-handler=\"selectDay\" data-event=\"click\" data-month=\"' +\n                                '' + printDate.getMonth() + '\" data-year=\"' + printDate.getFullYear() + '\"') + '>' +\n                                (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months\n                                    unselectable ? '<span class=\"ui-state-default\">' + printDate.getDate() + '</span>'\n                                        : '<a class=\"ui-state-default' +\n                                    (printDate.getTime() === today.getTime() ? ' ' : '') +\n                                    (printDate.getTime() === currentDate.getTime() ? ' ui-state-active' : '') +\n                                    (otherMonth ? ' ui-priority-secondary' : '') +\n                                    '\" href=\"#\">' + printDate.getDate() + '</a>') + '</td>';\n                                printDate.setDate(printDate.getDate() + 1);\n                                printDate = this._daylightSavingAdjust(printDate);\n                            }\n                            calender += tbody + '</tr>';\n                        }\n                        drawMonth++;\n\n                        if (drawMonth > 11) {\n                            drawMonth = 0;\n                            drawYear++;\n                        }\n                        calender += '</tbody></table>' + (isMultiMonth ? '</div>' +\n                        (numMonths[0] > 0 && col === numMonths[1] - 1 ? '<div class=\"ui-datepicker-row-break\"></div>'\n                            : '') : '');\n                        group += calender;\n                    }\n                    html += group;\n                }\n                html += buttonPanel + ($.ui.ie6 && !inst.inline ?\n                    '<iframe src=\"javascript:false;\" class=\"ui-datepicker-cover\" frameborder=\"0\"></iframe>' : '');\n                inst._keyEvent = false;\n\n                return html;\n            };\n        },\n\n        /**\n         * Set current date if the date is not set\n         * @protected\n         * @param {Object} element\n         */\n        _setCurrentDate: function (element) {\n            if (!element.val()) {\n                element[this._picker()]('setTimezoneDate').val('');\n            }\n        },\n\n        /**\n         * Init Datetimepicker\n         * @protected\n         * @param {Object} element\n         */\n        _initPicker: function (element) {\n            var picker = element[this._picker()](this.options),\n                pickerButtonText = picker.next('.ui-datepicker-trigger')\n                    .find('img')\n                    .attr('title');\n\n            picker.next('.ui-datepicker-trigger')\n                .addClass('v-middle')\n                .text('') // Remove jQuery UI datepicker generated image\n                .append('<span>' + pickerButtonText + '</span>');\n\n            $(element).attr('autocomplete', this.options.autoComplete ? 'on' : 'off');\n\n            this._setCurrentDate(element);\n        },\n\n        /**\n         * destroy instance of datetimepicker\n         */\n        _destroy: function () {\n            this.element[this._picker()]('destroy');\n            this._super();\n        },\n\n        /**\n         * Method is kept for backward compatibility and unit-tests acceptance\n         * see \\mage\\calendar\\calendar-test.js\n         * @return {Object} date\n         */\n        getTimezoneDate: function () {\n            return datepickerPrototype._getTimezoneDate.call(this, this.options);\n        }\n    });\n\n    calendarBasePrototype = $.mage.calendar.prototype;\n\n    /**\n     * Extension for Calendar - date and time format convert functionality\n     * @var {Object}\n     */\n    $.widget('mage.calendar', $.extend({}, calendarBasePrototype,\n            /** @lends {$.mage.calendar.prototype} */ {\n                /**\n                 * key - backend format, value - jquery format\n                 * @type {Object}\n                 * @private\n                 */\n                dateTimeFormat: {\n                    date: {\n                        'EEEE': 'DD',\n                        'EEE': 'D',\n                        'EE': 'D',\n                        'E': 'D',\n                        'D': 'o',\n                        'MMMM': 'MM',\n                        'MMM': 'M',\n                        'MM': 'mm',\n                        'M': 'mm',\n                        'yyyy': 'yy',\n                        'y': 'yy',\n                        'Y': 'yy',\n                        'yy': 'yy' // Always long year format on frontend\n                    },\n                    time: {\n                        'a': 'TT'\n                    }\n                },\n\n                /**\n                 * Add Date and Time converting to _create method\n                 * @protected\n                 */\n                _create: function () {\n                    if (this.options.dateFormat) {\n                        this.options.dateFormat = this._convertFormat(this.options.dateFormat, 'date');\n                    }\n\n                    if (this.options.timeFormat) {\n                        this.options.timeFormat = this._convertFormat(this.options.timeFormat, 'time');\n                    }\n                    calendarBasePrototype._create.apply(this, arguments);\n                },\n\n                /**\n                 * Converting date or time format\n                 * @protected\n                 * @param {String} format\n                 * @param {String} type\n                 * @return {String}\n                 */\n                _convertFormat: function (format, type) {\n                    var symbols = format.match(/([a-z]+)/ig),\n                        separators = format.match(/([^a-z]+)/ig),\n                        self = this,\n                        convertedFormat = '';\n\n                    if (symbols) {\n                        $.each(symbols, function (key, val) {\n                            convertedFormat +=\n                                (self.dateTimeFormat[type][val] || val) +\n                                (separators[key] || '');\n                        });\n                    }\n\n                    return convertedFormat;\n                }\n            })\n    );\n\n    /**\n     * Widget dateRange\n     * @extends $.mage.calendar\n     */\n    $.widget('mage.dateRange', $.mage.calendar, {\n\n        /**\n         * creates two instances of datetimepicker for date range selection\n         * @protected\n         */\n        _initPicker: function () {\n            var from,\n                to;\n\n            if (this.options.from && this.options.to) {\n                from = this.element.find('#' + this.options.from.id);\n                to = this.element.find('#' + this.options.to.id);\n                this.options.onSelect = $.proxy(function (selectedDate) {\n                    to[this._picker()]('option', 'minDate', selectedDate);\n                }, this);\n                $.mage.calendar.prototype._initPicker.call(this, from);\n                from.on('change', $.proxy(function () {\n                    to[this._picker()]('option', 'minDate', from[this._picker()]('getDate'));\n                }, this));\n                this.options.onSelect = $.proxy(function (selectedDate) {\n                    from[this._picker()]('option', 'maxDate', selectedDate);\n                }, this);\n                $.mage.calendar.prototype._initPicker.call(this, to);\n                to.on('change', $.proxy(function () {\n                    from[this._picker()]('option', 'maxDate', to[this._picker()]('getDate'));\n                }, this));\n            }\n        },\n\n        /**\n         * destroy two instances of datetimepicker\n         */\n        _destroy: function () {\n            if (this.options.from) {\n                this.element.find('#' + this.options.from.id)[this._picker()]('destroy');\n            }\n\n            if (this.options.to) {\n                this.element.find('#' + this.options.to.id)[this._picker()]('destroy');\n            }\n            this._super();\n        }\n    });\n\n    // Overrides the \"today\" button functionality to select today's date when clicked.\n    $.datepicker._gotoTodayOriginal = $.datepicker._gotoToday;\n\n    /**\n     * overwrite jQuery UI _showDatepicker function for proper HTML generation conditions.\n     *\n     */\n    $.datepicker._showDatepickerOriginal = $.datepicker._showDatepicker;\n\n    /**\n     * Triggers original method showDataPicker for rendering calendar\n     * @param {HTMLObject} input\n     * @private\n     */\n    $.datepicker._showDatepicker = function (input) {\n        if (!input.disabled) {\n            $.datepicker._showDatepickerOriginal.call(this, input);\n        }\n    };\n\n    /**\n     * _gotoToday\n     * @param {Object} el\n     */\n    $.datepicker._gotoToday = function (el) {\n        //Set date/time according to timezone offset\n        $(el).datepicker('setTimezoneDate')\n            // To ensure that user can re-select date field without clicking outside it first.\n            .blur().trigger('change');\n    };\n\n    return {\n        dateRange:  $.mage.dateRange,\n        calendar:   $.mage.calendar\n    };\n}));\n","mage/translate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable strict */\n(function (factory) {\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'mage/mage'\n        ], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($) {\n    $.extend(true, $, {\n        mage: {\n            translate: (function () {\n                /**\n                 * Key-value translations storage\n                 * @type {Object}\n                 * @private\n                 */\n                var _data = {};\n\n                /**\n                 * Add new translation (two string parameters) or several translations (object)\n                 */\n                this.add = function () {\n                    if (arguments.length > 1) {\n                        _data[arguments[0]] = arguments[1];\n                    } else if (typeof arguments[0] === 'object') {\n                        $.extend(_data, arguments[0]);\n                    }\n                };\n\n                /**\n                 * Make a translation with parsing (to handle case when _data represents tuple)\n                 * @param {String} text\n                 * @return {String}\n                 */\n                this.translate = function (text) {\n                    return _data[text] ? _data[text] : text;\n                };\n\n                return this;\n            }())\n        }\n    });\n    $.mage.__ = $.proxy($.mage.translate.translate, $.mage.translate);\n\n    return $.mage.__;\n}));\n","mage/ie-class-fixer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable strict */\n(function () {\n    var userAgent = navigator.userAgent, // user agent identifier\n        html = document.documentElement, // html tag\n        gap = ''; // gap between classes\n\n    if (html.className) { // check if neighbour class exist in html tag\n        gap = ' ';\n    } // end if\n\n    if (userAgent.match(/Trident.*rv[ :]*11\\./)) { // Special case for IE11\n        html.className += gap + 'ie11';\n    } // end if\n\n})();\n","mage/template.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n(function (root, factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'underscore'\n        ], factory);\n    } else {\n        root.mageTemplate = factory(root._);\n    }\n}(this, function (_) {\n    'use strict';\n\n    /**\n     * Checks if provided string is a valid DOM selector.\n     *\n     * @param {String} selector - Selector to be checked.\n     * @returns {Boolean}\n     */\n    function isSelector(selector) {\n        try {\n            document.querySelector(selector);\n\n            return true;\n        } catch (e) {\n            return false;\n        }\n    }\n\n    /**\n     * Unescapes characters used in underscore templates.\n     *\n     * @param {String} str - String to be processed.\n     * @returns {String}\n     */\n    function unescape(str) {\n        return str.replace(/&lt;%|%3C%/g, '<%').replace(/%&gt;|%%3E/g, '%>');\n    }\n\n    /**\n     * If 'tmpl' is a valid selector, returns target node's innerHTML if found.\n     * Else, returns empty string and emits console warning.\n     * If 'tmpl' is not a selector, returns 'tmpl' as is.\n     *\n     * @param {String} tmpl\n     * @returns {String}\n     */\n    function getTmplString(tmpl) {\n        if (isSelector(tmpl)) {\n            tmpl = document.querySelector(tmpl);\n\n            if (tmpl) {\n                tmpl = tmpl.innerHTML.trim();\n            } else {\n                console.warn('No template was found by selector: ' + tmpl);\n\n                tmpl = '';\n            }\n        }\n\n        return unescape(tmpl);\n    }\n\n    /**\n     * Compiles or renders template provided either\n     * by selector or by the template string.\n     *\n     * @param {String} tmpl - Template string or selector.\n     * @param {(Object|Array|Function)} [data] - Data object with which to render template.\n     * @returns {String|Function}\n     */\n    return function (tmpl, data) {\n        var render;\n\n        tmpl   = getTmplString(tmpl);\n        render = _.template(tmpl);\n\n        return !_.isUndefined(data) ?\n            render(data) :\n            render;\n    };\n}));\n","mage/polyfill.js":"try {\n    if (!window.localStorage || !window.sessionStorage) {\n        throw new Error();\n    }\n\n    localStorage.setItem('storage_test', 1);\n    localStorage.removeItem('storage_test');\n} catch (e) {\n    (function () {\n        'use strict';\n\n        /**\n         * Returns a storage object to shim local or sessionStorage\n         * @param {String} type - either 'local' or 'session'\n         */\n        var Storage = function (type) {\n            var data;\n\n            /**\n             * Creates a cookie\n             * @param {String} name\n             * @param {String} value\n             * @param {Integer} days\n             */\n            function createCookie(name, value, days) {\n                var date, expires;\n\n                if (days) {\n                    date = new Date();\n                    date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);\n                    expires = '; expires=' + date.toGMTString();\n                } else {\n                    expires = '';\n                }\n                document.cookie = name + '=' + value + expires + '; path=/';\n            }\n\n            /**\n             * Reads value of a cookie\n             * @param {String} name\n             */\n            function readCookie(name) {\n                var nameEQ = name + '=',\n                    ca = document.cookie.split(';'),\n                    i = 0,\n                    c;\n\n                for (i = 0; i < ca.length; i++) {\n                    c = ca[i];\n\n                    while (c.charAt(0) === ' ') {\n                        c = c.substring(1, c.length);\n                    }\n\n                    if (c.indexOf(nameEQ) === 0) {\n                        return c.substring(nameEQ.length, c.length);\n                    }\n                }\n\n                return null;\n            }\n\n            /**\n             * Returns cookie name based upon the storage type.\n             * If this is session storage, the function returns a unique cookie per tab\n             */\n            function getCookieName() {\n\n                if (type !== 'session') {\n                    return 'localstorage';\n                }\n\n                if (!window.name) {\n                    window.name = new Date().getTime();\n                }\n\n                return 'sessionStorage' + window.name;\n            }\n\n            /**\n             * Sets storage cookie to a data object\n             * @param {Object} dataObject\n             */\n            function setData(dataObject) {\n                data = encodeURIComponent(JSON.stringify(dataObject));\n                createCookie(getCookieName(), data, 365);\n            }\n\n            /**\n             * Clears value of cookie data\n             */\n            function clearData() {\n                createCookie(getCookieName(), '', 365);\n            }\n\n            /**\n             * @returns value of cookie data\n             */\n            function getData() {\n                var dataResponse = readCookie(getCookieName());\n\n                return dataResponse ? JSON.parse(decodeURIComponent(dataResponse)) : {};\n            }\n\n            data = getData();\n\n            return {\n                length: 0,\n\n                /**\n                 * Clears data from storage\n                 */\n                clear: function () {\n                    data = {};\n                    this.length = 0;\n                    clearData();\n                },\n\n                /**\n                 * Gets an item from storage\n                 * @param {String} key\n                 */\n                getItem: function (key) {\n                    return data[key] === undefined ? null : data[key];\n                },\n\n                /**\n                 * Gets an item by index from storage\n                 * @param {Integer} i\n                 */\n                key: function (i) {\n                    var ctr = 0,\n                        k;\n\n                    for (k in data) {\n\n                        if (data.hasOwnProperty(k)) {\n\n                            // eslint-disable-next-line max-depth\n                            if (ctr.toString() === i.toString()) {\n                                return k;\n                            }\n                            ctr++;\n                        }\n                    }\n\n                    return null;\n                },\n\n                /**\n                 * Removes an item from storage\n                 * @param {String} key\n                 */\n                removeItem: function (key) {\n                    delete data[key];\n                    this.length--;\n                    setData(data);\n                },\n\n                /**\n                 * Sets an item from storage\n                 * @param {String} key\n                 * @param {String} value\n                 */\n                setItem: function (key, value) {\n                    data[key] = value.toString();\n                    this.length++;\n                    setData(data);\n                }\n            };\n        };\n\n        window.localStorage.prototype = window.localStorage = new Storage('local');\n        window.sessionStorage.prototype = window.sessionStorage = new Storage('session');\n    })();\n}\n","mage/edit-trigger.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\n(function (root, factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'mage/template',\n            'jquery/ui'\n        ], factory);\n    } else {\n        factory(root.jQuery, root.mageTemplate);\n    }\n}(this, function ($, mageTemplate) {\n    'use strict';\n\n    var editTriggerPrototype;\n\n    $.widget('mage.editTrigger', {\n        options: {\n            img: '',\n            alt: '[TR]',\n            template: '#translate-inline-icon',\n            zIndex: 2000,\n            editSelector: '[data-translate]',\n            delay: 2000,\n            offsetTop: -3,\n            singleElement: true\n        },\n\n        /**\n         * editTriger creation\n         * @protected\n         */\n        _create: function () {\n            this.tmpl = mageTemplate(this.options.template);\n            this._initTrigger();\n            this._bind();\n        },\n\n        /**\n         * @return {Object}\n         * @private\n         */\n        _getCss: function () {\n            return {\n                position: 'absolute',\n                cursor: 'pointer',\n                display: 'none',\n                'z-index': this.options.zIndex\n            };\n        },\n\n        /**\n         * @param {*} appendTo\n         * @return {*|jQuery}\n         * @private\n         */\n        _createTrigger: function (appendTo) {\n            var tmpl = this.tmpl({\n                data: this.options\n            });\n\n            return $(tmpl)\n                .css(this._getCss())\n                .data('role', 'edit-trigger-element')\n                .appendTo(appendTo);\n        },\n\n        /**\n         * @private\n         */\n        _initTrigger: function () {\n            this.trigger = this._createTrigger($('body'));\n        },\n\n        /**\n         * Bind on mousemove event\n         * @protected\n         */\n        _bind: function () {\n            this.trigger.on('click.' + this.widgetName, $.proxy(this._onClick, this));\n            this.element.on('mousemove.' + this.widgetName, $.proxy(this._onMouseMove, this));\n        },\n\n        /**\n         * Show editTriger\n         */\n        show: function () {\n            if (this.trigger.is(':hidden')) {\n                this.trigger.show();\n            }\n        },\n\n        /**\n         * Hide editTriger\n         */\n        hide: function () {\n            this.currentTarget = null;\n\n            if (this.trigger && this.trigger.is(':visible')) {\n                this.trigger.hide();\n            }\n        },\n\n        /**\n         * Set editTriger position\n         * @protected\n         */\n        _setPosition: function (el) {\n            var offset = el.offset();\n\n            this.trigger.css({\n                top: offset.top + el.outerHeight() + this.options.offsetTop,\n                left: offset.left\n            });\n        },\n\n        /**\n         * Show/hide trigger on mouse move.\n         *\n         * @param {jQuery.Event} e\n         * @protected\n         */\n        _onMouseMove: function (e) {\n            var target = $(e.target),\n                inner = target.find(this.options.editSelector);\n\n            if ($(e.target).is('button') && inner.length) {\n                target = inner;\n            } else if (!target.is(this.trigger) && !target.is(this.options.editSelector)) {\n                target = target.parents(this.options.editSelector).first();\n            }\n\n            if (target.length) {\n                if (!target.is(this.trigger)) {\n                    this._setPosition(target);\n                    this.currentTarget = target;\n                }\n                this.show();\n            } else {\n                this.hide();\n            }\n        },\n\n        /**\n         * Trigger event \"edit\" on element for translate.\n         *\n         * @param {jQuery.Event} e\n         * @protected\n         */\n        _onClick: function (e) {\n            e.preventDefault();\n            e.stopImmediatePropagation();\n            $(this.currentTarget).trigger('edit.' + this.widgetName);\n            this.hide(true);\n        },\n\n        /**\n         * Destroy editTriger\n         */\n        destroy: function () {\n            this.trigger.remove();\n            this.element.off('.' + this.widgetName);\n\n            return $.Widget.prototype.destroy.call(this);\n        }\n    });\n\n    /**\n     * Extention for widget editTrigger - hide trigger with delay\n     */\n    editTriggerPrototype = $.mage.editTrigger.prototype;\n\n    $.widget('mage.editTrigger', $.extend({}, editTriggerPrototype, {\n        /**\n         * Added clear timeout on trigger show\n         */\n        show: function () {\n            editTriggerPrototype.show.apply(this, arguments);\n\n            if (this.options.delay) {\n                this._clearTimer();\n            }\n        },\n\n        /**\n         * Added setTimeout on trigger hide\n         */\n        hide: function (immediate) {\n            if (!immediate && this.options.delay) {\n                if (!this.timer) {\n                    this.timer = setTimeout($.proxy(function () {\n                        editTriggerPrototype.hide.apply(this, arguments);\n                        this._clearTimer();\n                    }, this), this.options.delay);\n                }\n            } else {\n                editTriggerPrototype.hide.apply(this, arguments);\n            }\n        },\n\n        /**\n         * Clear timer\n         * @protected\n         */\n        _clearTimer: function () {\n            if (this.timer) {\n                clearTimeout(this.timer);\n                this.timer = null;\n            }\n        }\n    }));\n\n    return $.mage.editTrigger;\n}));\n","mage/dropdown_old.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    var ESC_KEY_CODE = '27';\n\n    $(document)\n        .on('click.dropdown', function (event) {\n            if (!$(event.target).is('[data-toggle=dropdown].active, ' +\n                '[data-toggle=dropdown].active *, ' +\n                '[data-toggle=dropdown].active + .dropdown-menu, ' +\n                '[data-toggle=dropdown].active + .dropdown-menu *,' +\n                '[data-toggle=dropdown].active + [data-target=\"dropdown\"],' +\n                '[data-toggle=dropdown].active + [data-target=\"dropdown\"] *')\n            ) {\n                $('[data-toggle=dropdown].active').trigger('close.dropdown');\n            }\n        })\n        .on('keyup.dropdown', function (event) {\n            if (event.keyCode == ESC_KEY_CODE) { //eslint-disable-line eqeqeq\n                $('[data-toggle=dropdown].active').trigger('close.dropdown');\n            }\n        });\n\n    /**\n     * @param {Object} options\n     */\n    $.fn.dropdown = function (options) {\n        options = $.extend({\n            parent: null,\n            btnArrow: '.arrow',\n            activeClass: 'active'\n        }, options);\n\n        return this.each(function () {\n            var elem = $(this);\n\n            elem.off('open.dropdown, close.dropdown, click.dropdown');\n            elem.on('open.dropdown', function () {\n                elem\n                    .addClass(options.activeClass)\n                    .parent()\n                    .addClass(options.activeClass);\n                elem.find(options.btnArrow).text('\\u25b2'); // arrow up\n            });\n\n            elem.on('close.dropdown', function () {\n                elem\n                    .removeClass(options.activeClass)\n                    .parent()\n                    .removeClass(options.activeClass);\n                elem.find(options.btnArrow).text('\\u25bc'); // arrow down\n            });\n\n            elem.on('click.dropdown', function () {\n                var isActive = elem.hasClass('active');\n\n                $('[data-toggle=dropdown].active').trigger('close.dropdown');\n                elem.trigger(isActive ? 'close.dropdown' : 'open.dropdown');\n\n                return false;\n            });\n        });\n    };\n\n    return function (data, el) {\n        $(el).dropdown(data);\n    };\n});\n","mage/tabs.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery/ui',\n    'mage/mage',\n    'mage/collapsible'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.tabs', {\n        options: {\n            active: 0,\n            disabled: [],\n            openOnFocus: true,\n            collapsible: false,\n            collapsibleElement: '[data-role=collapsible]',\n            header: '[data-role=title]',\n            content: '[data-role=content]',\n            trigger: '[data-role=trigger]',\n            closedState: null,\n            openedState: null,\n            disabledState: null,\n            ajaxUrlElement: '[data-ajax=true]',\n            ajaxContent: false,\n            loadingClass: null,\n            saveState: false,\n            animate: false,\n            icons: {\n                activeHeader: null,\n                header: null\n            }\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            if (typeof this.options.disabled === 'string') {\n                this.options.disabled = this.options.disabled.split(' ').map(function (item) {\n                    return parseInt(item, 10);\n                });\n            }\n            this._processPanels();\n            this._handleDeepLinking();\n            this._processTabIndex();\n            this._closeOthers();\n            this._bind();\n        },\n\n        /**\n         * @private\n         */\n        _destroy: function () {\n            $.each(this.collapsibles, function () {\n                $(this).collapsible('destroy');\n            });\n        },\n\n        /**\n         * If deep linking is used, all sections must be closed but the one that contains the anchor.\n         * @private\n         */\n        _handleDeepLinking: function () {\n            var self = this,\n                anchor = window.location.hash,\n                isValid = $.mage.isValidSelector(anchor),\n                anchorId = anchor.replace('#', '');\n\n            if (anchor && isValid) {\n                $.each(self.contents, function (i) {\n                    if ($(this).attr('id') === anchorId) {\n                        self.collapsibles.not(self.collapsibles.eq(i)).collapsible('forceDeactivate');\n\n                        return false;\n                    }\n                });\n            }\n        },\n\n        /**\n         * When the widget gets instantiated, the first tab that is not disabled receive focusable property\n         * All tabs receive tabIndex 0\n         * @private\n         */\n        _processTabIndex: function () {\n            var self = this;\n\n            self.triggers.attr('tabIndex', 0);\n            $.each(this.collapsibles, function (i) {\n                self.triggers.attr('tabIndex', 0);\n                self.triggers.eq(i).attr('tabIndex', 0);\n            });\n        },\n\n        /**\n         * Prepare the elements for instantiating the collapsible widget\n         * @private\n         */\n        _processPanels: function () {\n            this.contents = this.element.find(this.options.content);\n\n            this.collapsibles = this.element.find(this.options.collapsibleElement);\n\n            this.collapsibles\n                .attr('role', 'presentation')\n                .parent()\n                .attr('role', 'tablist');\n\n            this.headers = this.element.find(this.options.header);\n\n            if (this.headers.length === 0) {\n                this.headers = this.collapsibles;\n            }\n            this.triggers = this.element.find(this.options.trigger);\n\n            if (this.triggers.length === 0) {\n                this.triggers = this.headers;\n            }\n            this._callCollapsible();\n        },\n\n        /**\n         * Setting the disabled and active tabs and calling instantiation of collapsible\n         * @private\n         */\n        _callCollapsible: function () {\n            var self = this,\n                disabled = false,\n                active = false;\n\n            $.each(this.collapsibles, function (i) {\n                disabled = active = false;\n\n                if ($.inArray(i, self.options.disabled) !== -1) {\n                    disabled = true;\n                }\n\n                if (i === self.options.active) {\n                    active = true;\n                }\n                self._instantiateCollapsible(this, i, active, disabled);\n            });\n        },\n\n        /**\n         * Instantiate collapsible.\n         *\n         * @param {HTMLElement} element\n         * @param {Number} index\n         * @param {*} active\n         * @param {*} disabled\n         * @private\n         */\n        _instantiateCollapsible: function (element, index, active, disabled) {\n            $(element).collapsible(\n                $.extend({}, this.options, {\n                    active: active,\n                    disabled: disabled,\n                    header: this.headers.eq(index),\n                    content: this.contents.eq(index),\n                    trigger: this.triggers.eq(index)\n                })\n            );\n        },\n\n        /**\n         * Adding callback to close others tabs when one gets opened\n         * @private\n         */\n        _closeOthers: function () {\n            var self = this;\n\n            $.each(this.collapsibles, function () {\n                $(this).on('beforeOpen', function () {\n                    self.collapsibles.not(this).collapsible('forceDeactivate');\n                });\n            });\n        },\n\n        /**\n         * @param {*} index\n         */\n        activate: function (index) {\n            this._toggleActivate('activate', index);\n        },\n\n        /**\n         * @param {*} index\n         */\n        deactivate: function (index) {\n            this._toggleActivate('deactivate', index);\n        },\n\n        /**\n         * @param {*} action\n         * @param {*} index\n         * @private\n         */\n        _toggleActivate: function (action, index) {\n            this.collapsibles.eq(index).collapsible(action);\n        },\n\n        /**\n         * @param {*} index\n         */\n        disable: function (index) {\n            this._toggleEnable('disable', index);\n        },\n\n        /**\n         * @param {*} index\n         */\n        enable: function (index) {\n            this._toggleEnable('enable', index);\n        },\n\n        /**\n         * @param {*} action\n         * @param {*} index\n         * @private\n         */\n        _toggleEnable: function (action, index) {\n            var self = this;\n\n            if ($.isArray(index)) {\n                $.each(index, function () {\n                    self.collapsibles.eq(this).collapsible(action);\n                });\n            } else if (index === undefined) {\n                this.collapsibles.collapsible(action);\n            } else {\n                this.collapsibles.eq(index).collapsible(action);\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _keydown: function (event) {\n            var self = this,\n                keyCode, toFocus, toFocusIndex, enabledTriggers, length, currentIndex, nextToFocus;\n\n            if (event.altKey || event.ctrlKey) {\n                return;\n            }\n            keyCode = $.ui.keyCode;\n            toFocus = false;\n            enabledTriggers = [];\n\n            $.each(this.triggers, function () {\n                if (!self.collapsibles.eq(self.triggers.index($(this))).collapsible('option', 'disabled')) {\n                    enabledTriggers.push(this);\n                }\n            });\n            length = $(enabledTriggers).length;\n            currentIndex = $(enabledTriggers).index(event.target);\n\n            /**\n             * @param {String} direction\n             * @return {*}\n             */\n            nextToFocus = function (direction) {\n                if (length > 0) {\n                    if (direction === 'right') {\n                        toFocusIndex = (currentIndex + 1) % length;\n                    } else {\n                        toFocusIndex = (currentIndex + length - 1) % length;\n                    }\n\n                    return enabledTriggers[toFocusIndex];\n                }\n\n                return event.target;\n            };\n\n            switch (event.keyCode) {\n                case keyCode.RIGHT:\n                case keyCode.DOWN:\n                    toFocus = nextToFocus('right');\n                    break;\n\n                case keyCode.LEFT:\n                case keyCode.UP:\n                    toFocus = nextToFocus('left');\n                    break;\n\n                case keyCode.HOME:\n                    toFocus = enabledTriggers[0];\n                    break;\n\n                case keyCode.END:\n                    toFocus = enabledTriggers[length - 1];\n                    break;\n            }\n\n            if (toFocus) {\n                toFocusIndex = this.triggers.index(toFocus);\n                $(event.target).attr('tabIndex', -1);\n                $(toFocus).attr('tabIndex', 0);\n                toFocus.focus();\n\n                if (this.options.openOnFocus) {\n                    this.activate(toFocusIndex);\n                }\n                event.preventDefault();\n            }\n        },\n\n        /**\n         * @private\n         */\n        _bind: function () {\n            var events = {\n                keydown: '_keydown'\n            };\n\n            this._off(this.triggers);\n            this._on(this.triggers, events);\n        }\n    });\n\n    return $.mage.tabs;\n});\n","mage/apply/scripts.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'jquery'\n], function (_, $) {\n    'use strict';\n\n    var scriptSelector = 'script[type=\"text/x-magento-init\"]',\n        dataAttr = 'data-mage-init',\n        virtuals = [];\n\n    /**\n     * Adds components to the virtual list.\n     *\n     * @param {Object} components\n     */\n    function addVirtual(components) {\n        virtuals.push({\n            el: false,\n            data: components\n        });\n    }\n\n    /**\n     * Merges provided data with a current data\n     * of a elements' \"data-mage-init\" attribute.\n     *\n     * @param {Object} components - Object with components and theirs configuration.\n     * @param {HTMLElement} elem - Element whose data should be modified.\n     */\n    function setData(components, elem) {\n        var data = elem.getAttribute(dataAttr);\n\n        data = data ? JSON.parse(data) : {};\n        _.each(components, function (obj, key) {\n            if (_.has(obj, 'mixins')) {\n                data[key] = data[key] || {};\n                data[key].mixins = data[key].mixins || [];\n                data[key].mixins = data[key].mixins.concat(obj.mixins);\n                delete obj.mixins;\n            }\n        });\n\n        data = $.extend(true, data, components);\n        data = JSON.stringify(data);\n        elem.setAttribute(dataAttr, data);\n    }\n\n    /**\n     * Search for the elements by privded selector and extends theirs data.\n     *\n     * @param {Object} components - Object with components and theirs configuration.\n     * @param {String} selector - Selector for the elements.\n     */\n    function processElems(components, selector) {\n        var elems,\n            iterator;\n\n        if (selector === '*') {\n            addVirtual(components);\n\n            return;\n        }\n\n        elems = document.querySelectorAll(selector);\n        iterator = setData.bind(null, components);\n\n        _.toArray(elems).forEach(iterator);\n    }\n\n    /**\n     * Parses content of a provided script node.\n     * Note: node will be removed from DOM.\n     *\n     * @param {HTMLScriptElement} node - Node to be processed.\n     * @returns {Object}\n     */\n    function getNodeData(node) {\n        var data = node.textContent;\n\n        node.parentNode.removeChild(node);\n\n        return JSON.parse(data);\n    }\n\n    /**\n     * Parses 'script' tags with a custom type attribute and moves it's data\n     * to a 'data-mage-init' attribute of an element found by provided selector.\n     * Note: All found script nodes will be removed from DOM.\n     *\n     * @returns {Array} An array of components not assigned to the specific element.\n     *\n     * @example Sample declaration.\n     *      <script type=\"text/x-magento-init\">\n     *          {\n     *              \"body\": {\n     *                  \"path/to/component\": {\"foo\": \"bar\"}\n     *              }\n     *          }\n     *      </script>\n     *\n     * @example Providing data without selector.\n     *      {\n     *          \"*\": {\n     *              \"path/to/component\": {\"bar\": \"baz\"}\n     *          }\n     *      }\n     */\n    return function () {\n        var nodes = document.querySelectorAll(scriptSelector);\n\n        _.toArray(nodes)\n            .map(getNodeData)\n            .forEach(function (item) {\n                _.each(item, processElems);\n            });\n\n        return virtuals.splice(0, virtuals.length);\n    };\n});\n","mage/apply/main.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'jquery',\n    './scripts'\n], function (_, $, processScripts) {\n    'use strict';\n\n    var dataAttr = 'data-mage-init',\n        nodeSelector = '[' + dataAttr + ']';\n\n    /**\n     * Initializes components assigned to a specified element via data-* attribute.\n     *\n     * @param {HTMLElement} el - Element to initialize components with.\n     * @param {Object|String} config - Initial components' config.\n     * @param {String} component - Components' path.\n     */\n    function init(el, config, component) {\n        require([component], function (fn) {\n\n            if (typeof fn === 'object') {\n                fn = fn[component].bind(fn);\n            }\n\n            if (_.isFunction(fn)) {\n                fn(config, el);\n            } else if ($(el)[component]) {\n                $(el)[component](config);\n            }\n        }, function (error) {\n            if ('console' in window && typeof window.console.error === 'function') {\n                console.error(error);\n            }\n\n            return true;\n        });\n    }\n\n    /**\n     * Parses elements 'data-mage-init' attribute as a valid JSON data.\n     * Note: data-mage-init attribute will be removed.\n     *\n     * @param {HTMLElement} el - Element whose attribute should be parsed.\n     * @returns {Object}\n     */\n    function getData(el) {\n        var data = el.getAttribute(dataAttr);\n\n        el.removeAttribute(dataAttr);\n\n        return {\n            el: el,\n            data: JSON.parse(data)\n        };\n    }\n\n    return {\n        /**\n         * Initializes components assigned to HTML elements via [data-mage-init].\n         *\n         * @example Sample 'data-mage-init' declaration.\n         *      data-mage-init='{\"path/to/component\": {\"foo\": \"bar\"}}'\n         */\n        apply: function (context) {\n            var virtuals = processScripts(!context ? document : context),\n                nodes = document.querySelectorAll(nodeSelector);\n\n            _.toArray(nodes)\n                .map(getData)\n                .concat(virtuals)\n                .forEach(function (itemContainer) {\n                    var element = itemContainer.el;\n\n                    _.each(itemContainer.data, function (obj, key) {\n                            if (obj.mixins) {\n                                require(obj.mixins, function () { //eslint-disable-line max-nested-callbacks\n                                    var i, len;\n\n                                    for (i = 0, len = arguments.length; i < len; i++) {\n                                        $.extend(\n                                            true,\n                                            itemContainer.data[key],\n                                            arguments[i](itemContainer.data[key], element)\n                                        );\n                                    }\n\n                                    delete obj.mixins;\n                                    init.call(null, element, obj, key);\n                                });\n                            } else {\n                                init.call(null, element, obj, key);\n                            }\n\n                        }\n                    );\n\n                });\n        },\n        applyFor: init\n    };\n});\n","mage/app/config.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\n/* eslint-disable strict */\ndefine([], function () {\n    return {\n        /**\n         * Get base url.\n         */\n        getBaseUrl: function () {\n            return this.values.baseUrl;\n        },\n\n        /**\n         * Get form key.\n         */\n        getFormKey: function () {\n            return this.values.formKey;\n        }\n    };\n});\n","mage/requirejs/baseUrlResolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Sample configuration:\n *\n require.config({\n        \"config\": {\n            \"baseUrlInterceptor\": {\n                \"Magento_Ui/js/lib/knockout/bindings/collapsible.js\": \"../../../../frontend/Magento/luma/en_US/\"\n            }\n        }\n    });\n */\n\n/* global jsSuffixRegExp */\n/* eslint-disable max-depth */\ndefine('baseUrlInterceptor', [\n    'module'\n], function (module) {\n    'use strict';\n\n    /**\n     * RequireJS Context object\n     */\n    var ctx = require.s.contexts._,\n\n        /**\n         * Original function\n         *\n         * @type {Function}\n         */\n        origNameToUrl = ctx.nameToUrl,\n\n        /**\n         * Original function\n         *\n         * @type {Function}\n         */\n        newContextConstr = require.s.newContext;\n\n    /**\n     * Remove dots from URL\n     *\n     * @param {Array} ary\n     */\n    function trimDots(ary) {\n        var i, part, length = ary.length;\n\n        for (i = 0; i < length; i++) {\n            part = ary[i];\n\n            if (part === '.') {\n                ary.splice(i, 1);\n                i -= 1;\n            } else if (part === '..') {\n                if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {\n                    //End of the line. Keep at least one non-dot\n                    //path segment at the front so it can be mapped\n                    //correctly to disk. Otherwise, there is likely\n                    //no path mapping for a path starting with '..'.\n                    //This can still fail, but catches the most reasonable\n                    //uses of ..\n                    break;\n                } else if (i > 0) {\n                    ary.splice(i - 1, 2);\n                    i -= 2;\n                }\n            }\n        }\n    }\n\n    /**\n     * Normalize URL string (remove '/../')\n     *\n     * @param {String} name\n     * @param {String} baseName\n     * @param {Object} applyMap\n     * @param {Object} localContext\n     * @returns {*}\n     */\n    function normalize(name, baseName, applyMap, localContext) {\n        var lastIndex,\n            baseParts = baseName && baseName.split('/'),\n            normalizedBaseParts = baseParts;\n\n        //Adjust any relative paths.\n        if (name && name.charAt(0) === '.') {\n            //If have a base name, try to normalize against it,\n            //otherwise, assume it is a top-level require that will\n            //be relative to baseUrl in the end.\n            if (baseName) {\n                //Convert baseName to array, and lop off the last part,\n                //so that . matches that 'directory' and not name of the baseName's\n                //module. For instance, baseName of 'one/two/three', maps to\n                //'one/two/three.js', but we want the directory, 'one/two' for\n                //this normalization.\n                normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);\n                name = name.split('/');\n                lastIndex = name.length - 1;\n\n                // If wanting node ID compatibility, strip .js from end\n                // of IDs. Have to do this here, and not in nameToUrl\n                // because node allows either .js or non .js to map\n                // to same file.\n                if (localContext.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {\n                    name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');\n                }\n\n                name = normalizedBaseParts.concat(name);\n                trimDots(name);\n                name = name.join('/');\n            } else if (name.indexOf('./') === 0) {\n                // No baseName, so this is ID is resolved relative\n                // to baseUrl, pull off the leading dot.\n                name = name.substring(2);\n            }\n        }\n\n        return name;\n    }\n\n    /**\n     * Get full url.\n     *\n     * @param {Object} context\n     * @param {String} url\n     * @return {String}\n     */\n    function getUrl(context, url) {\n        var baseUrl = context.config.baseUrl,\n            newConfig = context.config,\n            modulePath = url.replace(baseUrl, ''),\n            newBaseUrl,\n            rewrite = module.config()[modulePath];\n\n        if (!rewrite) {\n            return url;\n        }\n\n        newBaseUrl = normalize(rewrite, baseUrl, undefined, newConfig);\n\n        return newBaseUrl + modulePath;\n    }\n\n    /**\n     * Replace original function.\n     *\n     * @returns {*}\n     */\n    ctx.nameToUrl = function () {\n        return getUrl(ctx, origNameToUrl.apply(ctx, arguments));\n    };\n\n    /**\n     * Replace original function.\n     *\n     * @return {*}\n     */\n    require.s.newContext = function () {\n        var newCtx = newContextConstr.apply(require.s, arguments),\n            newOrigNameToUrl = newCtx.nameToUrl;\n\n        /**\n         * New implementation of native function.\n         *\n         * @returns {String}\n         */\n        newCtx.nameToUrl = function () {\n            return getUrl(newCtx, newOrigNameToUrl.apply(newCtx, arguments));\n        };\n\n        return newCtx;\n    };\n});\n\nrequire(['baseUrlInterceptor'], function () {\n    'use strict';\n\n});\n","mage/requirejs/text.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* inspired by http://github.com/requirejs/text */\n/*global XMLHttpRequest, XDomainRequest */\n\ndefine(['module'], function (module) {\n    'use strict';\n\n    var xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\n        stripReg = /!strip$/i,\n        defaultConfig = module.config && module.config() || {};\n\n    /**\n     * Strips <?xml ...?> declarations so that external SVG and XML documents can be\n     * added to a document without worry.\n     * Also, if the string is an HTML document, only the part inside the body tag is returned.\n     *\n     * @param {String} external\n     * @returns {String}\n     */\n    function stripContent(external) {\n        var matches;\n\n        if (!external) {\n            return '';\n        }\n\n        matches = external.match(bodyRegExp);\n        external = matches ?\n            matches[1] :\n            external.replace(xmlRegExp, '');\n\n        return external;\n    }\n\n    /**\n     * Checks that url match current location\n     *\n     * @param {String} url\n     * @returns {Boolean}\n     */\n    function sameDomain(url) {\n        var uProtocol, uHostName, uPort,\n            xdRegExp = /^([\\w:]+)?\\/\\/([^\\/\\\\]+)/i,\n            location = window.location,\n            match = xdRegExp.exec(url);\n\n        if (!match) {\n            return true;\n        }\n        uProtocol = match[1];\n        uHostName = match[2];\n\n        uHostName = uHostName.split(':');\n        uPort = uHostName[1] || '';\n        uHostName = uHostName[0];\n\n        return (!uProtocol || uProtocol === location.protocol) &&\n            (!uHostName || uHostName.toLowerCase() === location.hostname.toLowerCase()) &&\n            (!uPort && !uHostName || uPort === location.port);\n    }\n\n    /**\n     * @returns {XMLHttpRequest|XDomainRequest|null}\n     */\n    function createRequest(url) {\n        var xhr = new XMLHttpRequest();\n\n        if (!sameDomain(url) && typeof XDomainRequest !== 'undefined') {\n            xhr = new XDomainRequest();\n        }\n\n        return xhr;\n    }\n\n    /**\n     * XHR requester. Returns value to callback.\n     *\n     * @param {String} url\n     * @param {Function} callback\n     * @param {Function} fail\n     * @param {Object} headers\n     */\n    function getContent(url, callback, fail, headers) {\n        var xhr = createRequest(url),\n            header;\n\n        xhr.open('GET', url);\n\n        /*eslint-disable max-depth */\n        if ('setRequestHeader' in xhr && headers) {\n            for (header in headers) {\n                if (headers.hasOwnProperty(header)) {\n                    xhr.setRequestHeader(header.toLowerCase(), headers[header]);\n                }\n            }\n        }\n\n        /**\n         * @inheritdoc\n         */\n        xhr.onreadystatechange = function () {\n            var status, err;\n\n            //Do not explicitly handle errors, those should be\n            //visible via console output in the browser.\n            if (xhr.readyState === 4) {\n                status = xhr.status || 0;\n\n                if (status > 399 && status < 600) {\n                    //An http 4xx or 5xx error. Signal an error.\n                    err = new Error(url + ' HTTP status: ' + status);\n                    err.xhr = xhr;\n\n                    if (fail) {\n                        fail(err);\n                    }\n                } else {\n                    callback(xhr.responseText);\n\n                    if (defaultConfig.onXhrComplete) {\n                        defaultConfig.onXhrComplete(xhr, url);\n                    }\n                }\n            }\n        };\n\n        /*eslint-enable max-depth */\n\n        if (defaultConfig.onXhr) {\n            defaultConfig.onXhr(xhr, url);\n        }\n\n        xhr.send();\n    }\n\n    /**\n     * Main method used by RequireJs.\n     *\n     * @param {String} name - has format: some.module.filext!strip\n     * @param {Function} req\n     * @param {Function|undefined} onLoad\n     */\n    function loadContent(name, req, onLoad) {\n\n        var toStrip = stripReg.test(name),\n            url = req.toUrl(name.replace(stripReg, '')),\n            headers = defaultConfig.headers;\n\n        getContent(url, function (content) {\n                content = toStrip ? stripContent(content) : content;\n                onLoad(content);\n            }, onLoad.error, headers);\n    }\n\n    return {\n        load: loadContent,\n        get: getContent\n    };\n});\n","mage/requirejs/resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore',\n    'domReady!'\n], function (_) {\n    'use strict';\n\n    var context = require.s.contexts._,\n        execCb = context.execCb,\n        registry = context.registry,\n        callbacks = [],\n        retries = 10,\n        updateDelay = 1,\n        ready,\n        update;\n\n    /**\n     * Checks if provided callback already exists in the callbacks list.\n     *\n     * @param {Object} callback - Callback object to be checked.\n     * @returns {Boolean}\n     */\n    function isSubscribed(callback) {\n        return !!_.findWhere(callbacks, callback);\n    }\n\n    /**\n     * Checks if provided module is rejected during load.\n     *\n     * @param {Object} module - Module to be checked.\n     * @return {Boolean}\n     */\n    function isRejected(module) {\n        return registry[module.id] && (registry[module.id].inited || registry[module.id].error);\n    }\n\n    /**\n     * Checks if provided module has unresolved dependencies.\n     *\n     * @param {Object} module - Module to be checked.\n     * @returns {Boolean}\n     */\n    function isPending(module) {\n        if (!module.depCount) {\n            return false;\n        }\n\n        return module.depCount > _.filter(module.depMaps, isRejected).length;\n    }\n\n    /**\n     * Checks if requirejs's registry object contains pending modules.\n     *\n     * @returns {Boolean}\n     */\n    function hasPending() {\n        return _.some(registry, isPending);\n    }\n\n    /**\n     * Checks if 'resolver' module is in ready\n     * state and that there are no pending modules.\n     *\n     * @returns {Boolean}\n     */\n    function isReady() {\n        return ready && !hasPending();\n    }\n\n    /**\n     * Invokes provided callback handler.\n     *\n     * @param {Object} callback\n     */\n    function invoke(callback) {\n        callback.handler.call(callback.ctx);\n    }\n\n    /**\n     * Sets 'resolver' module to a ready state\n     * and invokes pending callbacks.\n     */\n    function resolve() {\n        ready = true;\n\n        callbacks.splice(0).forEach(invoke);\n    }\n\n    /**\n     * Drops 'ready' flag and runs the update process.\n     */\n    function tick() {\n        ready = false;\n\n        update(retries);\n    }\n\n    /**\n     * Adds callback which will be invoked\n     * when all of the pending modules are initiated.\n     *\n     * @param {Function} handler - 'Ready' event handler function.\n     * @param {Object} [ctx] - Optional context with which handler\n     *      will be invoked.\n     */\n    function subscribe(handler, ctx) {\n        var callback = {\n            handler: handler,\n            ctx: ctx\n        };\n\n        if (!isSubscribed(callback)) {\n            callbacks.push(callback);\n\n            if (isReady()) {\n                _.defer(tick);\n            }\n        }\n    }\n\n    /**\n     * Checks for all modules to be initiated\n     * and invokes pending callbacks if it's so.\n     *\n     * @param {Number} [retry] - Number of retries\n     *      that will be used to repeat the 'update' function\n     *      invokation in case if there are no pending requests.\n     */\n    update = _.debounce(function (retry) {\n        if (!hasPending()) {\n            retry ? update(--retry) : resolve();\n        }\n    }, updateDelay);\n\n    /**\n     * Overrides requirejs's original 'execCb' method\n     * in order to track pending modules.\n     *\n     * @returns {*} Result of original method call.\n     */\n    context.execCb = function () {\n        var exported = execCb.apply(context, arguments);\n\n        tick();\n\n        return exported;\n    };\n\n    return subscribe;\n});\n","mage/adminhtml/accordion.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global varienAccordion, varienLoader, Cookie */\n/* eslint-disable strict */\ndefine([\n    'prototype'\n], function () {\n    window.varienAccordion = new Class.create(); //eslint-disable-line\n    varienAccordion.prototype = {\n        /**\n         * @param {*} containerId\n         * @param {*} activeOnlyOne\n         */\n        initialize: function (containerId, activeOnlyOne) {\n            var links, i;\n\n            this.containerId = containerId;\n            this.activeOnlyOne = activeOnlyOne || false;\n            this.container = $(this.containerId);\n            this.items = $$('#' + this.containerId + ' dt');\n            this.loader = new varienLoader(true); //jscs:ignore requireCapitalizedConstructors\n\n            links = $$('#' + this.containerId + ' dt a');\n\n            for (i in links) {\n                if (links[i].href) {\n                    Event.observe(links[i], 'click', this.clickItem.bind(this));\n                    this.items[i].dd = this.items[i].next('dd');\n                    this.items[i].link = links[i];\n                }\n            }\n\n            this.initFromCookie();\n        },\n\n        /**\n         * Init from cookie.\n         */\n        initFromCookie: function () {\n            var activeItemId, visibility;\n\n            if (this.activeOnlyOne &&\n                (activeItemId = Cookie.read(this.cookiePrefix() + 'active-item')) !== null) {\n                this.hideAllItems();\n                this.showItem(this.getItemById(activeItemId));\n            } else if (!this.activeOnlyOne) {\n                this.items.each(function (item) {\n                    if ((visibility = Cookie.read(this.cookiePrefix() + item.id)) !== null) {\n                        if (visibility == 0) { //eslint-disable-line eqeqeq\n                            this.hideItem(item);\n                        } else {\n                            this.showItem(item);\n                        }\n                    }\n                }.bind(this));\n            }\n        },\n\n        /**\n         * @return {String}\n         */\n        cookiePrefix: function () {\n            return 'accordion-' + this.containerId + '-';\n        },\n\n        /**\n         * @param {*} itemId\n         * @return {*}\n         */\n        getItemById: function (itemId) {\n            var result = null;\n\n            this.items.each(function (item) {\n                if (item.id == itemId) { //eslint-disable-line\n                    result = item;\n                    throw $break;\n                }\n            });\n\n            return result;\n        },\n\n        /**\n         * @param {*} event\n         */\n        clickItem: function (event) {\n            var item = Event.findElement(event, 'dt');\n\n            if (this.activeOnlyOne) {\n                this.hideAllItems();\n                this.showItem(item);\n                Cookie.write(this.cookiePrefix() + 'active-item', item.id, 30 * 24 * 60 * 60);\n            } else {\n                if (this.isItemVisible(item)) { //eslint-disable-line no-lonely-if\n                    this.hideItem(item);\n                    Cookie.write(this.cookiePrefix() + item.id, 0, 30 * 24 * 60 * 60);\n                } else {\n                    this.showItem(item);\n                    Cookie.write(this.cookiePrefix() + item.id, 1, 30 * 24 * 60 * 60);\n                }\n            }\n            Event.stop(event);\n        },\n\n        /**\n         * @param {Object} item\n         */\n        showItem: function (item) {\n            if (item && item.link) {\n                if (item.link.href) {\n                    this.loadContent(item);\n                }\n\n                Element.addClassName(item, 'open');\n                Element.addClassName(item.dd, 'open');\n            }\n        },\n\n        /**\n         * @param {Object} item\n         */\n        hideItem: function (item) {\n            Element.removeClassName(item, 'open');\n            Element.removeClassName(item.dd, 'open');\n        },\n\n        /**\n         * @param {*} item\n         * @return {*}\n         */\n        isItemVisible: function (item) {\n            return Element.hasClassName(item, 'open');\n        },\n\n        /**\n         * @param {*} item\n         */\n        loadContent: function (item) {\n            if (item.link.href.indexOf('#') == item.link.href.length - 1) { //eslint-disable-line eqeqeq\n                return;\n            }\n\n            if (Element.hasClassName(item.link, 'ajax')) {\n                this.loadingItem = item;\n                this.loader.load(item.link.href, {\n                    updaterId: this.loadingItem.dd.id\n                }, this.setItemContent.bind(this));\n\n                return;\n            }\n            location.href = item.link.href;\n        },\n\n        /**\n         * @param {Object} content\n         */\n        setItemContent: function (content) {\n            if (content.isJSON) {\n                return;\n            }\n            this.loadingItem.dd.innerHTML = content;\n        },\n\n        /**\n         * Hide all items\n         */\n        hideAllItems: function () {\n            var i;\n\n            for (i in this.items) {\n                if (this.items[i].id) {\n                    Element.removeClassName(this.items[i], 'open');\n                    Element.removeClassName(this.items[i].dd, 'open');\n                }\n            }\n        }\n    };\n});\n","mage/adminhtml/grid.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n// also depends on a mage/adminhtml/tools.js for Base64 encoding\n/* global varienGrid, setLocation, varienGlobalEvents, FORM_KEY,\n    BASE_URL, Base64, varienGridMassaction, varienStringArray, serializerController\n*/\n/* eslint-disable strict */\ndefine([\n    'jquery',\n    'mage/template',\n    'Magento_Ui/js/modal/alert',\n    'Magento_Ui/js/modal/confirm',\n    'mage/mage',\n    'prototype',\n    'mage/adminhtml/form',\n    'mage/adminhtml/events'\n], function (jQuery, mageTemplate, alert, confirm) {\n    /**\n     * @param {*} grid\n     * @param {*} event\n     */\n    function openGridRow(grid, event) {\n        var element = Event.findElement(event, 'tr');\n\n        if (['a', 'input', 'select', 'option'].indexOf(Event.element(event).tagName.toLowerCase()) !== -1) {\n            return;\n        }\n\n        if (element.title) {\n            setLocation(element.title);\n        }\n    }\n    window.openGridRow = openGridRow;\n\n    window.varienGrid = new Class.create();\n\n    varienGrid.prototype = {\n        /**\n         * @param {String} containerId\n         * @param {String} url\n         * @param {*} pageVar\n         * @param {*} sortVar\n         * @param {*} dirVar\n         * @param {*} filterVar\n         */\n        initialize: function (containerId, url, pageVar, sortVar, dirVar, filterVar) {\n            this.containerId = containerId;\n            jQuery('#' + containerId).data('gridObject', this);\n            this.url = url;\n            this.pageVar = pageVar || false;\n            this.sortVar = sortVar || false;\n            this.dirVar = dirVar || false;\n            this.filterVar = filterVar || false;\n            this.tableSufix = '_table';\n            this.useAjax = false;\n            this.rowClickCallback = false;\n            this.checkboxCheckCallback = false;\n            this.preInitCallback = false;\n            this.initCallback = false;\n            this.initRowCallback = false;\n            this.doFilterCallback = false;\n            this.sortableUpdateCallback = false;\n\n            this.reloadParams = false;\n\n            this.trOnMouseOver = this.rowMouseOver.bindAsEventListener(this);\n            this.trOnMouseOut = this.rowMouseOut.bindAsEventListener(this);\n            this.trOnClick = this.rowMouseClick.bindAsEventListener(this);\n            this.trOnDblClick = this.rowMouseDblClick.bindAsEventListener(this);\n            this.trOnKeyPress = this.keyPress.bindAsEventListener(this);\n\n            this.thLinkOnClick = this.doSort.bindAsEventListener(this);\n            this.initGrid();\n        },\n\n        /**\n         * Init grid.\n         */\n        initGrid: function () {\n            var row, columns, col;\n\n            if (this.preInitCallback) {\n                this.preInitCallback(this);\n            }\n\n            if ($(this.containerId + this.tableSufix)) {\n                this.rows = $$('#' + this.containerId + this.tableSufix + ' tbody tr');\n\n                for (row = 0; row < this.rows.length; row++) {\n                    if (row % 2 == 0) { //eslint-disable-line eqeqeq, max-depth\n                        Element.addClassName(this.rows[row], 'even');\n                    }\n\n                    Event.observe(this.rows[row], 'mouseover', this.trOnMouseOver);\n                    Event.observe(this.rows[row], 'mouseout', this.trOnMouseOut);\n                    Event.observe(this.rows[row], 'click', this.trOnClick);\n                    Event.observe(this.rows[row], 'dblclick', this.trOnDblClick);\n                }\n            }\n\n            if (this.sortVar && this.dirVar) {\n                columns = $$('#' + this.containerId + this.tableSufix + ' thead [data-sort]');\n\n                for (col = 0; col < columns.length; col++) {\n                    Event.observe(columns[col], 'click', this.thLinkOnClick);\n                }\n            }\n            this.bindFilterFields();\n            this.bindFieldsChange();\n\n            if (this.initCallback) {\n                try {\n                    this.initCallback(this);\n                }\n                catch (e) {\n                    if (window.console) { //eslint-disable-line max-depth\n                        console.log(e);\n                    }\n                }\n            }\n            jQuery('#' + this.containerId).trigger('gridinit', this);\n        },\n\n        /**\n         * Init grid ajax.\n         */\n        initGridAjax: function () {\n            this.initGrid();\n            this.initGridRows();\n        },\n\n        /**\n         * Init grid rows.\n         */\n        initGridRows: function () {\n            var row;\n\n            if (this.initRowCallback) {\n                for (row = 0; row < this.rows.length; row++) {\n                    try { //eslint-disable-line max-depth\n                        this.initRowCallback(this, this.rows[row]);\n                    } catch (e) {\n                        if (window.console) { //eslint-disable-line max-depth\n                            console.log(e);\n                        }\n                    }\n                }\n            }\n        },\n\n        /**\n         * @param {*} event\n         */\n        rowMouseOver: function (event) {\n            var element = Event.findElement(event, 'tr');\n\n            if (!element.title) {\n                return;\n            }\n\n            Element.addClassName(element, 'on-mouse');\n\n            if (!Element.hasClassName('_clickable') && (this.rowClickCallback !== openGridRow || element.title)) {\n                if (element.title) {\n                    Element.addClassName(element, '_clickable');\n                }\n            }\n        },\n\n        /**\n         * @param {*} event\n         */\n        rowMouseOut: function (event) {\n            var element = Event.findElement(event, 'tr');\n\n            Element.removeClassName(element, 'on-mouse');\n        },\n\n        /**\n         * @param {*} event\n         */\n        rowMouseClick: function (event) {\n            if (this.rowClickCallback) {\n                try {\n                    this.rowClickCallback(this, event);\n                }\n                catch (e) {\n                }\n            }\n            varienGlobalEvents.fireEvent('gridRowClick', event);\n        },\n\n        /**\n         * @param {*} event\n         */\n        rowMouseDblClick: function (event) {\n            varienGlobalEvents.fireEvent('gridRowDblClick', event);\n        },\n\n        /**\n         * Key press.\n         */\n        keyPress: function () {},\n\n        /**\n         * @param {*} event\n         * @return {Boolean}\n         */\n        doSort: function (event) {\n            var element = Event.findElement(event, 'th');\n\n            if (element.readAttribute('data-sort') && element.readAttribute('data-direction')) {\n                this.addVarToUrl(this.sortVar, element.readAttribute('data-sort'));\n                this.addVarToUrl(this.dirVar, element.readAttribute('data-direction'));\n                this.reload(this.url);\n            }\n            Event.stop(event);\n\n            return false;\n        },\n\n        /**\n         * @param {Object} element\n         */\n        loadByElement: function (element) {\n            if (element && element.name) {\n                this.reload(this.addVarToUrl(element.name, element.value));\n            }\n        },\n\n        /**\n         * @param {*} data\n         * @param {*} textStatus\n         * @param {*} transport\n         * @private\n         */\n        _onAjaxSeccess: function (data, textStatus, transport) {\n            var responseText, response, divId;\n\n            /* eslint-disable max-depth */\n            try {\n                responseText = transport.responseText;\n\n                if (transport.responseText.isJSON()) {\n                    response = transport.responseText.evalJSON();\n\n                    if (response.error) {\n                        alert({\n                            content: response.message\n                        });\n                    }\n\n                    if (response.ajaxExpired && response.ajaxRedirect) {\n                        setLocation(response.ajaxRedirect);\n                    }\n                } else {\n\n                    /*eslint-disable max-len*/\n                    /**\n                     * For IE <= 7.\n                     * If there are two elements, and first has name, that equals id of second.\n                     * In this case, IE will choose one that is above\n                     *\n                     * @see https://prototype.lighthouseapp.com/projects/8886/tickets/994-id-selector-finds-elements-by-name-attribute-in-ie7\n                     */\n\n                    /*eslint-enable max-len*/\n                    divId = $(this.containerId);\n\n                    if (divId.id == this.containerId) { //eslint-disable-line eqeqeq\n                        divId.update(responseText);\n                    } else {\n                        $$('div[id=\"' + this.containerId + '\"]')[0].update(responseText);\n                    }\n                }\n            } catch (e) {\n                divId = $(this.containerId);\n\n                if (divId.id == this.containerId) { //eslint-disable-line eqeqeq\n                    divId.update(responseText);\n                } else {\n                    $$('div[id=\"' + this.containerId + '\"]')[0].update(responseText);\n                }\n            }\n\n            /* eslint-enable max-depth */\n            jQuery('#' + this.containerId).trigger('contentUpdated');\n        },\n\n        /**\n         * @param {*} url\n         * @param {Function} onSuccessCallback\n         * @return {*}\n         */\n        reload: function (url, onSuccessCallback) {\n            var ajaxSettings, ajaxRequest;\n\n            this.reloadParams = this.reloadParams || {};\n            this.reloadParams['form_key'] = FORM_KEY;\n            url = url || this.url;\n\n            if (this.useAjax) {\n                ajaxSettings = {\n                    url: url + (url.match(new RegExp('\\\\?')) ? '&ajax=true' : '?ajax=true'),\n                    showLoader: true,\n                    method: 'post',\n                    context: jQuery('#' + this.containerId),\n                    data: this.reloadParams,\n                    error: this._processFailure.bind(this),\n                    complete: this.initGridAjax.bind(this),\n                    dataType: 'html',\n\n                    /**\n                     * Success callback.\n                     */\n                    success: function (data, textStatus, transport) {\n                        this._onAjaxSeccess(data, textStatus, transport);\n\n                        if (onSuccessCallback && typeof onSuccessCallback === 'function') {\n                            // execute the callback, passing parameters as necessary\n                            onSuccessCallback();\n                        }\n                    }.bind(this)\n                };\n                jQuery('#' + this.containerId).trigger('gridajaxsettings', ajaxSettings);\n                ajaxRequest = jQuery.ajax(ajaxSettings);\n                jQuery('#' + this.containerId).trigger('gridajax', ajaxRequest);\n\n                return ajaxRequest;\n            }\n\n            if (this.reloadParams) {\n                $H(this.reloadParams).each(function (pair) {\n                    url = this.addVarToUrl(pair.key, pair.value);\n                }.bind(this));\n            }\n            location.href = url;\n        },\n\n        /**\n         * @private\n         */\n        _processFailure: function () {\n            location.href = BASE_URL;\n        },\n\n        /**\n         * @param {*} url\n         * @param {*} varName\n         * @param {*} varValue\n         * @return {String|*}\n         * @private\n         */\n        _addVarToUrl: function (url, varName, varValue) {\n            var re = new RegExp('\\/(' + varName + '\\/.*?\\/)'),\n                parts = url.split(new RegExp('\\\\?'));\n\n            url = parts[0].replace(re, '/');\n            url += varName + '/' + varValue + '/';\n\n            if (parts.size() > 1) {\n                url += '?' + parts[1];\n            }\n\n            return url;\n        },\n\n        /**\n         * @param {*} varName\n         * @param {*} varValue\n         * @return {*|String}\n         */\n        addVarToUrl: function (varName, varValue) {\n            this.url = this._addVarToUrl(this.url, varName, varValue);\n\n            return this.url;\n        },\n\n        /**\n         * Do export.\n         */\n        doExport: function () {\n            var exportUrl;\n\n            if ($(this.containerId + '_export')) {\n                exportUrl = $(this.containerId + '_export').value;\n\n                if (this.massaction && this.massaction.checkedString) {\n                    exportUrl = this._addVarToUrl(\n                        exportUrl,\n                        this.massaction.formFieldNameInternal,\n                        this.massaction.checkedString\n                    );\n                }\n                location.href = exportUrl;\n            }\n        },\n\n        /**\n         * Bind filter fields.\n         */\n        bindFilterFields: function () {\n            var filters = $$(\n                    '#' + this.containerId + ' [data-role=\"filter-form\"] input',\n                    '#' + this.containerId + ' [data-role=\"filter-form\"] select'\n                ),\n                i;\n\n            for (i = 0; i < filters.length; i++) {\n                Event.observe(filters[i], 'keypress', this.filterKeyPress.bind(this));\n            }\n        },\n\n        /**\n         * Bind field change.\n         */\n        bindFieldsChange: function () {\n            var dataElements, i;\n\n            if (!$(this.containerId)) {\n                return;\n            }\n            //var dataElements = $(this.containerId+this.tableSufix).down('.data tbody').select('input', 'select');\n            dataElements = $(this.containerId + this.tableSufix).down('tbody').select('input', 'select');\n\n            for (i = 0; i < dataElements.length; i++) {\n                Event.observe(dataElements[i], 'change', dataElements[i].setHasChanges.bind(dataElements[i]));\n            }\n        },\n\n        /**\n         * Bind sortable.\n         */\n        bindSortable: function () {\n            if (jQuery('#' + this.containerId).find('.draggable-handle').length) {\n                jQuery('#' + this.containerId).find('tbody').sortable({\n                    axis: 'y',\n                    handle: '.draggable-handle',\n\n                    /**\n                     * @param {*} event\n                     * @param {*} ui\n                     * @return {*}\n                     */\n                    helper: function (event, ui) {\n                        ui.children().each(function () {\n                            jQuery(this).width(jQuery(this).width());\n                        });\n\n                        return ui;\n                    },\n                    update: this.sortableUpdateCallback ? this.sortableUpdateCallback : function () {},\n                    tolerance: 'pointer'\n                });\n            }\n        },\n\n        /**\n         * @param {Object} event\n         */\n        filterKeyPress: function (event) {\n            if (event.keyCode == Event.KEY_RETURN) { //eslint-disable-line eqeqeq\n                this.doFilter();\n            }\n        },\n\n        /**\n         * @param {Function} callback\n         */\n        doFilter: function (callback) {\n            var filters = $$(\n                    '#' + this.containerId + ' [data-role=\"filter-form\"] input',\n                    '#' + this.containerId + ' [data-role=\"filter-form\"] select'\n                ),\n                elements = [],\n                i;\n\n            for (i in filters) {\n                if (filters[i].value && filters[i].value.length) {\n                    elements.push(filters[i]);\n                }\n            }\n\n            if (!this.doFilterCallback || this.doFilterCallback && this.doFilterCallback()) {\n                this.reload(\n                    this.addVarToUrl(this.filterVar, Base64.encode(Form.serializeElements(elements))),\n                    callback\n                );\n            }\n        },\n\n        /**\n         * @param {Function} callback\n         */\n        resetFilter: function (callback) {\n            this.reload(this.addVarToUrl(this.filterVar, ''), callback);\n        },\n\n        /**\n         * @param {Object} element\n         */\n        checkCheckboxes: function (element) {\n            var elements = Element.select($(this.containerId), 'input[name=\"' + element.name + '\"]'),\n                i;\n\n            for (i = 0; i < elements.length; i++) {\n                this.setCheckboxChecked(elements[i], element.checked);\n            }\n\n            /*eslint-enable no-undef*/\n        },\n\n        /**\n         *\n         * @param {HTMLElement} element\n         * @param {*} checked\n         */\n        setCheckboxChecked: function (element, checked) {\n            element.checked = checked;\n            jQuery(element).trigger('change');\n            element.setHasChanges({});\n\n            if (this.checkboxCheckCallback) {\n                this.checkboxCheckCallback(this, element, checked);\n            }\n        },\n\n        /**\n         * @param {Object} event\n         */\n        inputPage: function (event) {\n            var element = Event.element(event),\n                keyCode = event.keyCode || event.which;\n\n            if (keyCode == Event.KEY_RETURN) { //eslint-disable-line eqeqeq\n                this.setPage(element.value);\n            }\n\n            /*if(keyCode>47 && keyCode<58){\n\n             }\n             else{\n             Event.stop(event);\n             }*/\n        },\n\n        /**\n         * @param {*} pageNumber\n         */\n        setPage: function (pageNumber) {\n            this.reload(this.addVarToUrl(this.pageVar, pageNumber));\n        }\n    };\n\n    window.varienGridMassaction = Class.create();\n    varienGridMassaction.prototype = {\n        /* Predefined vars */\n        checkedValues: $H({}),\n        checkedString: '',\n        oldCallbacks: {},\n        errorText: '',\n        items: {},\n        gridIds: [],\n        useSelectAll: false,\n        currentItem: false,\n        lastChecked: {\n            left: false,\n            top: false,\n            checkbox: false\n        },\n        fieldTemplate: mageTemplate('<input type=\"hidden\" name=\"<%- name %>\" value=\"<%- value %>\" />'),\n\n        /**\n         * @param {*} containerId\n         * @param {*} grid\n         * @param {*} checkedValues\n         * @param {*} formFieldNameInternal\n         * @param {*} formFieldName\n         */\n        initialize: function (containerId, grid, checkedValues, formFieldNameInternal, formFieldName) {\n            this.setOldCallback('row_click', grid.rowClickCallback);\n            this.setOldCallback('init',      grid.initCallback);\n            this.setOldCallback('init_row',  grid.initRowCallback);\n            this.setOldCallback('pre_init',  grid.preInitCallback);\n\n            this.useAjax        = false;\n            this.grid           = grid;\n            this.grid.massaction = this;\n            this.containerId    = containerId;\n            this.initMassactionElements();\n\n            this.checkedString          = checkedValues;\n            this.formFieldName          = formFieldName;\n            this.formFieldNameInternal  = formFieldNameInternal;\n\n            this.grid.initCallback      = this.onGridInit.bind(this);\n            this.grid.preInitCallback   = this.onGridPreInit.bind(this);\n            this.grid.initRowCallback   = this.onGridRowInit.bind(this);\n            this.grid.rowClickCallback  = this.onGridRowClick.bind(this);\n            this.initCheckboxes();\n            this.checkCheckboxes();\n        },\n\n        /**\n         * @param {*} flag\n         */\n        setUseAjax: function (flag) {\n            this.useAjax = flag;\n        },\n\n        /**\n         * @param {*} flag\n         */\n        setUseSelectAll: function (flag) {\n            this.useSelectAll = flag;\n        },\n\n        /**\n         * Init massaction elements.\n         */\n        initMassactionElements: function () {\n            this.container      = $(this.containerId);\n            this.multiselect    = $(this.containerId + '-mass-select');\n            this.count          = $(this.containerId + '-count');\n            this.formHiddens    = $(this.containerId + '-form-hiddens');\n            this.formAdditional = $(this.containerId + '-form-additional');\n            this.select         = $(this.containerId + '-select');\n            this.form           = this.prepareForm();\n            jQuery(this.form).mage('validation');\n            this.select.observe('change', this.onSelectChange.bindAsEventListener(this));\n            this.lastChecked    = {\n                left: false,\n                top: false,\n                checkbox: false\n            };\n            this.select.addClassName(this.select.value ? '_selected' : '');\n            this.initMassSelect();\n        },\n\n        /**\n         * @return {jQuery|*|HTMLElement}\n         */\n        prepareForm: function () {\n            var form = $(this.containerId + '-form'),\n                formPlace = null,\n                formElement = this.formHiddens || this.formAdditional;\n\n            if (!formElement) {\n                formElement = this.container.getElementsByTagName('button')[0];\n                formElement && formElement.parentNode;\n            }\n\n            if (!form && formElement) {\n                /* fix problem with rendering form in FF through innerHTML property */\n                form = document.createElement('form');\n                form.setAttribute('method', 'post');\n                form.setAttribute('action', '');\n                form.id = this.containerId + '-form';\n                formPlace = formElement.parentNode;\n                formPlace.parentNode.appendChild(form);\n                form.appendChild(formPlace);\n            }\n\n            return form;\n        },\n\n        /**\n         * @param {Array} gridIds\n         */\n        setGridIds: function (gridIds) {\n            this.gridIds = gridIds;\n            this.updateCount();\n        },\n\n        /**\n         * @return {Array}\n         */\n        getGridIds: function () {\n            return this.gridIds;\n        },\n\n        /**\n         * @param {*} items\n         */\n        setItems: function (items) {\n            this.items = items;\n            this.updateCount();\n        },\n\n        /**\n         * @return {Object}\n         */\n        getItems: function () {\n            return this.items;\n        },\n\n        /**\n         * @param {*} itemId\n         * @return {*}\n         */\n        getItem: function (itemId) {\n            if (this.items[itemId]) {\n                return this.items[itemId];\n            }\n\n            return false;\n        },\n\n        /**\n         * @param {String} callbackName\n         * @return {Function}\n         */\n        getOldCallback: function (callbackName) {\n            return this.oldCallbacks[callbackName] ? this.oldCallbacks[callbackName] : Prototype.emptyFunction;\n        },\n\n        /**\n         * @param {String} callbackName\n         * @param {Function} callback\n         */\n        setOldCallback: function (callbackName, callback) {\n            this.oldCallbacks[callbackName] = callback;\n        },\n\n        /**\n         * @param {*} grid\n         */\n        onGridPreInit: function (grid) {\n            this.initMassactionElements();\n            this.getOldCallback('pre_init')(grid);\n        },\n\n        /**\n         * @param {*} grid\n         */\n        onGridInit: function (grid) {\n            this.initCheckboxes();\n            this.checkCheckboxes();\n            this.updateCount();\n            this.getOldCallback('init')(grid);\n        },\n\n        /**\n         * @param {*} grid\n         * @param {*} row\n         */\n        onGridRowInit: function (grid, row) {\n            this.getOldCallback('init_row')(grid, row);\n        },\n\n        /**\n         * @param {Object} evt\n         */\n        isDisabled: function (evt) {\n            var target = jQuery(evt.target),\n                tr,\n                checkbox;\n\n            tr = target.is('tr') ? target : target.closest('tr');\n            checkbox = tr.find('input[type=\"checkbox\"]');\n\n            return checkbox.is(':disabled');\n        },\n\n        /**\n         * @param {*} grid\n         * @param {*} evt\n         * @return {*}\n         */\n        onGridRowClick: function (grid, evt) {\n            var tdElement = Event.findElement(evt, 'td'),\n                trElement = Event.findElement(evt, 'tr'),\n                checkbox, isInput, checked;\n\n            if (this.isDisabled(evt)) {\n                return false;\n            }\n\n            if (!$(tdElement).down('input')) {\n                if ($(tdElement).down('a') || $(tdElement).down('select')) {\n                    return; //eslint-disable-line\n                }\n\n                if (trElement.title && trElement.title.strip() != '#') { //eslint-disable-line eqeqeq\n                    this.getOldCallback('row_click')(grid, evt);\n                } else {\n                    checkbox = Element.select(trElement, 'input');\n                    isInput  = Event.element(evt).tagName == 'input'; //eslint-disable-line eqeqeq\n                    checked = isInput ? checkbox[0].checked : !checkbox[0].checked;\n\n                    if (checked) { //eslint-disable-line max-depth\n                        this.checkedString = varienStringArray.add(checkbox[0].value, this.checkedString);\n                    } else {\n                        this.checkedString = varienStringArray.remove(checkbox[0].value, this.checkedString);\n                    }\n                    this.grid.setCheckboxChecked(checkbox[0], checked);\n                    this.updateCount();\n                }\n\n                return; //eslint-disable-line\n            }\n\n            if (Event.element(evt).isMassactionCheckbox) {\n                this.setCheckbox(Event.element(evt));\n            } else if (checkbox = this.findCheckbox(evt)) { //eslint-disable-line no-cond-assign\n                checkbox.checked = !checkbox.checked;\n                jQuery(checkbox).trigger('change');\n                this.setCheckbox(checkbox);\n            }\n        },\n\n        /**\n         * @param {Object} evt\n         */\n        onSelectChange: function (evt) {\n            var item = this.getSelectedItem();\n\n            if (item) {\n                this.formAdditional.update($(this.containerId + '-item-' + item.id + '-block').innerHTML);\n                evt.target.addClassName('_selected');\n            } else {\n                this.formAdditional.update('');\n                evt.target.removeClassName('_selected');\n            }\n            jQuery(this.form).data('validator').resetForm();\n        },\n\n        /**\n         * @param {Object} evt\n         * @return {*}\n         */\n        findCheckbox: function (evt) {\n            if (['a', 'input', 'select'].indexOf(Event.element(evt).tagName.toLowerCase()) !== -1) {\n                return false;\n            }\n            checkbox = false; //eslint-disable-line no-undef\n            Event.findElement(evt, 'tr').select('[data-role=\"select-row\"]').each(function (element) { //eslint-disable-line\n                if (element.isMassactionCheckbox) {\n                    checkbox = element; //eslint-disable-line no-undef\n                }\n            });\n\n            return checkbox; //eslint-disable-line no-undef\n        },\n\n        /**\n         * Init checkobox.\n         */\n        initCheckboxes: function () {\n            this.getCheckboxes().each(function (checkbox) { //eslint-disable-line no-extra-bind\n                checkbox.isMassactionCheckbox = true; //eslint-disable-line no-undef\n            });\n        },\n\n        /**\n         * Check checkbox.\n         */\n        checkCheckboxes: function () {\n            this.getCheckboxes().each(function (checkbox) {\n                checkbox.checked = varienStringArray.has(checkbox.value, this.checkedString);\n                jQuery(checkbox).trigger('change');\n            }.bind(this));\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        selectAll: function () {\n            this.setCheckedValues(this.useSelectAll ? this.getGridIds() : this.getCheckboxesValuesAsString());\n            this.checkCheckboxes();\n            this.updateCount();\n            this.clearLastChecked();\n\n            return false;\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        unselectAll: function () {\n            this.setCheckedValues('');\n            this.checkCheckboxes();\n            this.updateCount();\n            this.clearLastChecked();\n\n            return false;\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        selectVisible: function () {\n            this.setCheckedValues(this.getCheckboxesValuesAsString());\n            this.checkCheckboxes();\n            this.updateCount();\n            this.clearLastChecked();\n\n            return false;\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        unselectVisible: function () {\n            this.getCheckboxesValues().each(function (key) {\n                this.checkedString = varienStringArray.remove(key, this.checkedString);\n            }.bind(this));\n            this.checkCheckboxes();\n            this.updateCount();\n            this.clearLastChecked();\n\n            return false;\n        },\n\n        /**\n         * @param {*} values\n         */\n        setCheckedValues: function (values) {\n            this.checkedString = values;\n        },\n\n        /**\n         * @return {String}\n         */\n        getCheckedValues: function () {\n            return this.checkedString;\n        },\n\n        /**\n         * @return {Array}\n         */\n        getCheckboxes: function () {\n            var result = [];\n\n            this.grid.rows.each(function (row) {\n                var checkboxes = row.select('[data-role=\"select-row\"]');\n\n                checkboxes.each(function (checkbox) {\n                    result.push(checkbox);\n                });\n            });\n\n            return result;\n        },\n\n        /**\n         * @return {Array}\n         */\n        getCheckboxesValues: function () {\n            var result = [];\n\n            this.getCheckboxes().each(function (checkbox) { //eslint-disable-line no-extra-bind\n                result.push(checkbox.value);\n            });\n\n            return result;\n        },\n\n        /**\n         * @return {String}\n         */\n        getCheckboxesValuesAsString: function () {\n            return this.getCheckboxesValues().join(',');\n        },\n\n        /**\n         * @param {Object} checkbox\n         */\n        setCheckbox: function (checkbox) {\n            if (checkbox.checked) {\n                this.checkedString = varienStringArray.add(checkbox.value, this.checkedString);\n            } else {\n                this.checkedString = varienStringArray.remove(checkbox.value, this.checkedString);\n            }\n            this.updateCount();\n        },\n\n        /**\n         * Update count.\n         */\n        updateCount: function () {\n            var checkboxesTotal = varienStringArray.count(\n                this.useSelectAll ? this.getGridIds() : this.getCheckboxesValuesAsString()\n                ),\n                checkboxesChecked = varienStringArray.count(this.checkedString);\n\n            jQuery('[data-role=\"counter\"]', this.count).html(checkboxesChecked);\n\n            if (!checkboxesTotal) {\n                this.multiselect.addClassName('_disabled');\n            } else {\n                this.multiselect.removeClassName('_disabled');\n            }\n\n            if (checkboxesChecked == checkboxesTotal && checkboxesTotal != 0) { //eslint-disable-line eqeqeq\n                this.count.removeClassName('_empty');\n                this.multiselect.addClassName('_checked').removeClassName('_indeterminate');\n            } else if (checkboxesChecked == 0) { //eslint-disable-line eqeqeq\n                this.count.addClassName('_empty');\n                this.multiselect.removeClassName('_checked').removeClassName('_indeterminate');\n            } else {\n                this.count.removeClassName('_empty');\n                this.multiselect.addClassName('_checked').addClassName('_indeterminate');\n            }\n\n            if (!this.grid.reloadParams) {\n                this.grid.reloadParams = {};\n            }\n            this.grid.reloadParams[this.formFieldNameInternal] = this.checkedString;\n        },\n\n        /**\n         * @return {*}\n         */\n        getSelectedItem: function () {\n            if (this.getItem(this.select.value)) {\n                return this.getItem(this.select.value);\n            }\n\n            return false;\n        },\n\n        /**\n         * Apply.\n         */\n        apply: function () {\n            var item, fieldName;\n\n            if (varienStringArray.count(this.checkedString) == 0) { //eslint-disable-line eqeqeq\n                alert({\n                    content: this.errorText\n                });\n\n                return;\n            }\n\n            item = this.getSelectedItem();\n\n            if (!item) {\n                jQuery(this.form).valid();\n\n                return;\n            }\n            this.currentItem = item;\n            fieldName = item.field ? item.field : this.formFieldName;\n\n            if (this.currentItem.confirm) {\n                confirm({\n                    content: this.currentItem.confirm,\n                    actions: {\n                        confirm: this.onConfirm.bind(this, fieldName, item)\n                    }\n                });\n            } else {\n                this.onConfirm(fieldName, item);\n            }\n        },\n\n        /**\n         * @param {*} fieldName\n         * @param {*} item\n         */\n        onConfirm: function (fieldName, item) {\n            this.formHiddens.update('');\n            new Insertion.Bottom(this.formHiddens, this.fieldTemplate({\n                name: fieldName,\n                value: this.checkedString\n            }));\n            new Insertion.Bottom(this.formHiddens, this.fieldTemplate({\n                name: 'massaction_prepare_key',\n                value: fieldName\n            }));\n\n            if (!jQuery(this.form).valid()) {\n                return;\n            }\n\n            if (this.useAjax && item.url) {\n                new Ajax.Request(item.url, {\n                    'method': 'post',\n                    'parameters': this.form.serialize(true),\n                    'onComplete': this.onMassactionComplete.bind(this)\n                });\n            } else if (item.url) {\n                this.form.action = item.url;\n                this.form.submit();\n            }\n        },\n\n        /**\n         * @param {*} transport\n         */\n        onMassactionComplete: function (transport) {\n            var listener;\n\n            if (this.currentItem.complete) {\n                try {\n                    listener = this.getListener(this.currentItem.complete) || Prototype.emptyFunction;\n                    listener(this.grid, this, transport);\n                } catch (e) {}\n            }\n        },\n\n        /**\n         * @param {*} strValue\n         * @return {Object}\n         */\n        getListener: function (strValue) {\n            return eval(strValue); //eslint-disable-line no-eval\n        },\n\n        /**\n         * Init mass select.\n         */\n        initMassSelect: function () {\n            $$('input[data-role=\"select-row\"]').each(function (element) {\n                element.observe('click', this.massSelect.bind(this));\n            }.bind(this));\n        },\n\n        /**\n         * Clear last checked.\n         */\n        clearLastChecked: function () {\n            this.lastChecked = {\n                left: false,\n                top: false,\n                checkbox: false\n            };\n        },\n\n        /**\n         * @param {Object} evt\n         */\n        massSelect: function (evt) {\n            var currentCheckbox, lastCheckbox, start, finish;\n\n            if (this.lastChecked.left !== false &&\n                this.lastChecked.top !== false &&\n                evt.button === 0 &&\n                evt.shiftKey === true\n            ) {\n                currentCheckbox = Event.element(evt);\n                lastCheckbox = this.lastChecked.checkbox;\n\n                if (lastCheckbox != currentCheckbox) { //eslint-disable-line eqeqeq\n                    start = this.getCheckboxOrder(lastCheckbox);\n                    finish = this.getCheckboxOrder(currentCheckbox);\n\n                    if (start !== false && finish !== false) { //eslint-disable-line max-depth\n                        this.selectCheckboxRange(\n                            Math.min(start, finish),\n                            Math.max(start, finish),\n                            currentCheckbox.checked\n                        );\n                    }\n                }\n            }\n\n            this.lastChecked = {\n                left: Event.element(evt).viewportOffset().left,\n                top: Event.element(evt).viewportOffset().top,\n                checkbox: Event.element(evt) // \"boundary\" checkbox\n            };\n        },\n\n        /**\n         * @param {*} curCheckbox\n         * @return {Boolean}\n         */\n        getCheckboxOrder: function (curCheckbox) {\n            var order = false;\n\n            this.getCheckboxes().each(function (checkbox, key) {\n                if (curCheckbox == checkbox) { //eslint-disable-line eqeqeq\n                    order = key;\n                }\n            });\n\n            return order;\n        },\n\n        /**\n         * @param {*} start\n         * @param {*} finish\n         * @param {*} isChecked\n         */\n        selectCheckboxRange: function (start, finish, isChecked) {\n            this.getCheckboxes().each(function (checkbox, key) {\n                if (key >= start && key <= finish) {\n                    checkbox.checked = isChecked;\n                    this.setCheckbox(checkbox);\n                }\n            }.bind(this));\n        }\n    };\n\n    window.varienGridAction = {\n        /**\n         * @param {Object} select\n         */\n        execute: function (select) {\n            var config, win;\n\n            if (!select.value || !select.value.isJSON()) {\n                return;\n            }\n\n            config = select.value.evalJSON();\n\n            if (config.confirm && !window.confirm(config.confirm)) { //eslint-disable-line no-alert\n                select.options[0].selected = true;\n\n                return;\n            }\n\n            if (config.popup) {\n                win = window.open(config.href, 'action_window', 'width=500,height=600,resizable=1,scrollbars=1');\n                win.focus();\n                select.options[0].selected = true;\n            } else {\n                setLocation(config.href);\n            }\n        }\n    };\n\n    window.varienStringArray = {\n        /**\n         * @param {*} str\n         * @param {*} haystack\n         * @return {*}\n         */\n        remove: function (str, haystack) {\n            haystack = ',' + haystack + ',';\n            haystack = haystack.replace(new RegExp(',' + str + ',', 'g'), ',');\n\n            return this.trimComma(haystack);\n        },\n\n        /**\n         * @param {*} str\n         * @param {*} haystack\n         * @return {*}\n         */\n        add: function (str, haystack) {\n            haystack = ',' + haystack + ',';\n\n            if (haystack.search(new RegExp(',' + str + ',', 'g'), haystack) === -1) {\n                haystack += str + ',';\n            }\n\n            return this.trimComma(haystack);\n        },\n\n        /**\n         * @param {*} str\n         * @param {*} haystack\n         * @return {Boolean}\n         */\n        has: function (str, haystack) {\n            haystack = ',' + haystack + ',';\n\n            if (haystack.search(new RegExp(',' + str + ',', 'g'), haystack) === -1) {\n                return false;\n            }\n\n            return true;\n        },\n\n        /**\n         * @param {*} haystack\n         * @return {*}\n         */\n        count: function (haystack) {\n            var match;\n\n            if (typeof haystack != 'string') {\n                return 0;\n            }\n\n            /* eslint-disable no-undef, no-cond-assign, eqeqeq */\n            if (match = haystack.match(new RegExp(',', 'g'))) {\n                return match.length + 1;\n            } else if (haystack.length != 0) {\n                return 1;\n            }\n\n            /* eslint-enable no-undef, no-cond-assign, eqeqeq */\n            return 0;\n        },\n\n        /**\n         * @param {*} haystack\n         * @param {*} fnc\n         */\n        each: function (haystack, fnc) {\n            var i;\n\n            haystack = haystack.split(',');\n\n            for (i = 0; i < haystack.length; i++) {\n                fnc(haystack[i]);\n            }\n        },\n\n        /**\n         * @param {String} string\n         * @return {String}\n         */\n        trimComma: function (string) {\n            string = string.replace(new RegExp('^(,+)','i'), '');\n            string = string.replace(new RegExp('(,+)$','i'), '');\n\n            return string;\n        }\n    };\n\n    window.serializerController = Class.create();\n    serializerController.prototype = {\n        oldCallbacks: {},\n\n        /**\n         * @param {*} hiddenDataHolder\n         * @param {*} predefinedData\n         * @param {*} inputsToManage\n         * @param {*} grid\n         * @param {*} reloadParamName\n         */\n        initialize: function (hiddenDataHolder, predefinedData, inputsToManage, grid, reloadParamName) {\n            //Grid inputs\n            this.tabIndex = 1000;\n            this.inputsToManage       = inputsToManage;\n            this.multidimensionalMode = inputsToManage.length > 0;\n\n            //Hash with grid data\n            this.gridData             = this.getGridDataHash(predefinedData);\n\n            //Hidden input data holder\n            this.hiddenDataHolder     = $(hiddenDataHolder);\n            this.hiddenDataHolder.value = this.serializeObject();\n\n            this.grid = grid;\n\n            // Set old callbacks\n            this.setOldCallback('row_click', this.grid.rowClickCallback);\n            this.setOldCallback('init_row', this.grid.initRowCallback);\n            this.setOldCallback('checkbox_check', this.grid.checkboxCheckCallback);\n\n            //Grid\n            this.reloadParamName = reloadParamName;\n            this.grid.reloadParams = {};\n            this.grid.reloadParams[this.reloadParamName + '[]'] = this.getDataForReloadParam();\n            this.grid.rowClickCallback = this.rowClick.bind(this);\n            this.grid.initRowCallback = this.rowInit.bind(this);\n            this.grid.checkboxCheckCallback = this.registerData.bind(this);\n            this.grid.rows.each(this.eachRow.bind(this));\n        },\n\n        /**\n         * @param {String} callbackName\n         * @param {Function} callback\n         */\n        setOldCallback: function (callbackName, callback) {\n            this.oldCallbacks[callbackName] = callback;\n        },\n\n        /**\n         * @param {String} callbackName\n         * @return {Prototype.emptyFunction}\n         */\n        getOldCallback: function (callbackName) {\n            return this.oldCallbacks[callbackName] ? this.oldCallbacks[callbackName] : Prototype.emptyFunction;\n        },\n\n        /**\n         * @param {*} grid\n         * @param {*} element\n         * @param {*} checked\n         */\n        registerData: function (grid, element, checked) {\n            var i;\n\n            if (this.multidimensionalMode) {\n                if (checked) {\n                    /*eslint-disable max-depth*/\n                    if (element.inputElements) {\n                        this.gridData.set(element.value, {});\n\n                        for (i = 0; i < element.inputElements.length; i++) {\n                            element.inputElements[i].disabled = false;\n                            this.gridData.get(element.value)[element.inputElements[i].name] =\n                                element.inputElements[i].value;\n                        }\n                    }\n                } else {\n                    if (element.inputElements) {\n                        for (i = 0; i < element.inputElements.length; i++) {\n                            element.inputElements[i].disabled = true;\n                        }\n                    }\n                    this.gridData.unset(element.value);\n                }\n            } else {\n                if (checked) { //eslint-disable-line no-lonely-if\n                    this.gridData.set(element.value, element.value);\n                } else {\n                    this.gridData.unset(element.value);\n                }\n            }\n\n            this.hiddenDataHolder.value = this.serializeObject();\n            this.grid.reloadParams = {};\n            this.grid.reloadParams[this.reloadParamName + '[]'] = this.getDataForReloadParam();\n            this.getOldCallback('checkbox_check')(grid, element, checked);\n\n            /*eslint-enable max-depth*/\n        },\n\n        /**\n         * @param {*} row\n         */\n        eachRow: function (row) {\n            this.rowInit(this.grid, row);\n        },\n\n        /**\n         * @param {*} grid\n         * @param {*} event\n         */\n        rowClick: function (grid, event) {\n            var trElement = Event.findElement(event, 'tr'),\n                isInput   = Event.element(event).tagName == 'INPUT', //eslint-disable-line eqeqeq\n                checkbox, checked;\n\n            if (trElement) {\n                checkbox = Element.select(trElement, 'input');\n\n                if (checkbox[0] && !checkbox[0].disabled) {\n                    checked = isInput ? checkbox[0].checked : !checkbox[0].checked;\n                    this.grid.setCheckboxChecked(checkbox[0], checked);\n                }\n            }\n            this.getOldCallback('row_click')(grid, event);\n        },\n\n        /**\n         * @param {*} event\n         */\n        inputChange: function (event) {\n            var element = Event.element(event);\n\n            if (element && element.checkboxElement && element.checkboxElement.checked) {\n                this.gridData.get(element.checkboxElement.value)[element.name] = element.value;\n                this.hiddenDataHolder.value = this.serializeObject();\n            }\n        },\n\n        /**\n         * @param {*} grid\n         * @param {*} row\n         */\n        rowInit: function (grid, row) {\n            var checkbox, selectors, inputs, i;\n\n            if (this.multidimensionalMode) {\n                checkbox = $(row).select('.checkbox')[0];\n                selectors = this.inputsToManage.map(function (name) {\n                    return ['input[name=\"' + name + '\"]', 'select[name=\"' + name + '\"]'];\n                });\n                inputs = $(row).select.apply($(row), selectors.flatten());\n\n                if (checkbox && inputs.length > 0) {\n                    checkbox.inputElements = inputs;\n\n                    /* eslint-disable max-depth */\n                    for (i = 0; i < inputs.length; i++) {\n                        inputs[i].checkboxElement = checkbox;\n\n                        if (this.gridData.get(checkbox.value) && this.gridData.get(checkbox.value)[inputs[i].name]) {\n                            inputs[i].value = this.gridData.get(checkbox.value)[inputs[i].name];\n                        }\n                        inputs[i].disabled = !checkbox.checked;\n                        inputs[i].tabIndex = this.tabIndex++;\n                        Event.observe(inputs[i], 'keyup', this.inputChange.bind(this));\n                        Event.observe(inputs[i], 'change', this.inputChange.bind(this));\n                    }\n                }\n            }\n\n            /* eslint-enable max-depth */\n            this.getOldCallback('init_row')(grid, row);\n        },\n\n        /**\n         * Stuff methods.\n         *\n         * @param {*} _object\n         * @return {*}\n         */\n        getGridDataHash: function (_object) {\n            return $H(this.multidimensionalMode ? _object : this.convertArrayToObject(_object));\n        },\n\n        /**\n         * @return {*}\n         */\n        getDataForReloadParam: function () {\n            return this.multidimensionalMode ? this.gridData.keys() : this.gridData.values();\n        },\n\n        /**\n         * @return {*}\n         */\n        serializeObject: function () {\n            var clone;\n\n            if (this.multidimensionalMode) {\n                clone = this.gridData.clone();\n                clone.each(function (pair) {\n                    clone.set(pair.key, Base64.encode(Object.toQueryString(pair.value)));\n                });\n\n                return clone.toQueryString();\n            }\n\n            return this.gridData.values().join('&');\n        },\n\n        /**\n         * @param {Array} _array\n         * @return {Object}\n         */\n        convertArrayToObject: function (_array) {\n            var _object = {},\n                i, l;\n\n            for (i = 0, l = _array.length; i < l; i++) {\n                _object[_array[i]] = _array[i];\n            }\n\n            return _object;\n        }\n    };\n});\n","mage/adminhtml/events.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global varienEvents */\n/* eslint-disable strict */\ndefine([\n    'Magento_Ui/js/modal/alert',\n    'prototype'\n], function (alert) {\n    // from http://www.someelement.com/2007/03/eventpublisher-custom-events-la-pubsub.html\n    window.varienEvents = Class.create();\n\n    varienEvents.prototype = {\n        /**\n         * Initialize.\n         */\n        initialize: function () {\n            this.arrEvents = {};\n            this.eventPrefix = '';\n        },\n\n        /**\n        * Attaches a {handler} function to the publisher's {eventName} event for execution upon the event firing\n        * @param {String} eventName\n        * @param {Function} handler\n        * @param {Boolean} [asynchFlag] - Defaults to false if omitted.\n        * Indicates whether to execute {handler} asynchronously (true) or not (false).\n        */\n        attachEventHandler: function (eventName, handler) {\n            var asynchVar, handlerObj;\n\n            if (typeof handler == 'undefined' || handler == null) {\n                return;\n            }\n            eventName += this.eventPrefix;\n            // using an event cache array to track all handlers for proper cleanup\n            if (this.arrEvents[eventName] == null) {\n                this.arrEvents[eventName] = [];\n            }\n            //create a custom object containing the handler method and the asynch flag\n            asynchVar = arguments.length > 2 ? arguments[2] : false;\n            handlerObj = {\n                method: handler,\n                asynch: asynchVar\n            };\n            this.arrEvents[eventName].push(handlerObj);\n        },\n\n        /**\n        * Removes a single handler from a specific event\n        * @param {String} eventName - The event name to clear the handler from\n        * @param {Function} handler - A reference to the handler function to un-register from the event\n        */\n        removeEventHandler: function (eventName, handler) {\n            eventName += this.eventPrefix;\n\n            if (this.arrEvents[eventName] != null) {\n                this.arrEvents[eventName] = this.arrEvents[eventName].reject(function (obj) {\n                    return obj.method == handler; //eslint-disable-line eqeqeq\n                });\n            }\n        },\n\n        /**\n        * Removes all handlers from a single event\n        * @param {String} eventName - The event name to clear handlers from\n        */\n        clearEventHandlers: function (eventName) {\n            eventName += this.eventPrefix;\n            this.arrEvents[eventName] = null;\n        },\n\n        /**\n        * Removes all handlers from ALL events\n        */\n        clearAllEventHandlers: function () {\n            this.arrEvents = {};\n        },\n\n        /**\n         * Collect and modify value of arg synchronously in succession and return its new value.\n         * In order to use, call attachEventHandler and add function handlers with eventName.\n         * Then call fireEventReducer with eventName and any argument to have its value accumulatively modified.\n         * Event handlers will be applied to argument in order of first attached to last attached.\n         * @param {String} eventName\n         * @param {*} arg\n         */\n        fireEventReducer: function (eventName, arg) {\n            var evtName = eventName + this.eventPrefix,\n                result = arg,\n                len,\n                i;\n\n            if (!this.arrEvents[evtName]) {\n                return result;\n            }\n\n            len = this.arrEvents[evtName].length; //optimization\n\n            for (i = 0; i < len; i++) {\n                /* eslint-disable max-depth */\n                try {\n                    result = this.arrEvents[evtName][i].method(result);\n                } catch (e) {\n                    if (this.id) {\n                        alert({\n                            content: 'error: error in ' + this.id + '.fireEventReducer():\\n\\nevent name: ' +\n                            eventName + '\\n\\nerror message: ' + e.message\n                        });\n                    } else {\n                        alert({\n                            content: 'error: error in [unknown object].fireEventReducer():\\n\\nevent name: ' +\n                            eventName + '\\n\\nerror message: ' + e.message\n                        });\n                    }\n                }\n                /* eslint-disable max-depth */\n            }\n\n            return result;\n        },\n\n        /**\n        * Fires the event {eventName}, resulting in all registered handlers to be executed.\n        * It also collects and returns results of all non-asynchronous handlers\n        * @param {String} eventName - The name of the event to fire\n        * @param {Object} [args] - Any object, will be passed into the handler function as the only argument\n        * @return {Array}\n        */\n        fireEvent: function (eventName) {\n            var evtName = eventName + this.eventPrefix,\n                results = [],\n                result, len, i, eventArgs, method, eventHandler;\n\n            if (this.arrEvents[evtName] != null) {\n                len = this.arrEvents[evtName].length; //optimization\n\n                for (i = 0; i < len; i++) {\n                    /* eslint-disable max-depth */\n                    try {\n                        if (arguments.length > 1) {\n                            if (this.arrEvents[evtName][i].asynch) {\n                                eventArgs = arguments[1];\n                                method = this.arrEvents[evtName][i].method.bind(this);\n                                setTimeout(function () { //eslint-disable-line no-loop-func\n                                    method(eventArgs);\n                                }, 10);\n                            } else {\n                                result = this.arrEvents[evtName][i].method(arguments[1]);\n                            }\n                        } else {\n                            if (this.arrEvents[evtName][i].asynch) { //eslint-disable-line no-lonely-if\n                                eventHandler = this.arrEvents[evtName][i].method;\n                                setTimeout(eventHandler, 1);\n                            } else if (\n                                this.arrEvents &&\n                                this.arrEvents[evtName] &&\n                                this.arrEvents[evtName][i] &&\n                                this.arrEvents[evtName][i].method\n                            ) {\n                                result = this.arrEvents[evtName][i].method();\n                            }\n                        }\n                        results.push(result);\n                    }\n                    catch (e) {\n                        if (this.id) {\n                            alert({\n                                content: 'error: error in ' + this.id + '.fireEvent():\\n\\nevent name: ' +\n                                eventName + '\\n\\nerror message: ' + e.message\n                            });\n                        } else {\n                            alert({\n                                content: 'error: error in [unknown object].fireEvent():\\n\\nevent name: ' +\n                                eventName + '\\n\\nerror message: ' + e.message\n                            });\n                        }\n                    }\n\n                    /* eslint-enable max-depth */\n                }\n            }\n\n            return results;\n        }\n    };\n\n    window.varienGlobalEvents = new varienEvents(); //jscs:ignore requireCapitalizedConstructors\n\n    return window.varienGlobalEvents;\n});\n","mage/adminhtml/globals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global setLocation */\ndefine([\n    'Magento_Ui/js/modal/confirm',\n    'mage/dataPost'\n], function (confirm, dataPost) {\n    'use strict';\n\n    /**\n     * Set of a temporary methods used to provide\n     * backward compatability with a legacy code.\n     */\n    window.setLocation = function (url) {\n        window.location.href = url;\n    };\n\n    /**\n     * Helper for onclick action.\n     * @param {String} message\n     * @param {String} url\n     * @param {Object} postData\n     * @returns {Boolean}\n     */\n    window.deleteConfirm = function (message, url, postData) {\n        confirm({\n            content: message,\n            actions: {\n                /**\n                 * Confirm action.\n                 */\n                confirm: function () {\n                    if (postData !== undefined) {\n                        postData.action = url;\n                        dataPost().postData(postData);\n                    } else {\n                        setLocation(url);\n                    }\n                }\n            }\n        });\n\n        return false;\n    };\n\n    /**\n     * Helper for onclick action.\n     * @param {String} message\n     * @param {String} url\n     * @returns {Boolean}\n     */\n    window.confirmSetLocation = window.deleteConfirm;\n});\n","mage/adminhtml/backup.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\n/* global  AdminBackup, setLocation */\n/* eslint-disable strict */\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/modal',\n    'mage/mage',\n    'prototype'\n], function (jQuery) {\n    window.AdminBackup = new Class.create();\n\n    AdminBackup.prototype = {\n        /**\n         * Initialize.\n         */\n        initialize: function () {\n            this.reset();\n            this.rollbackUrl = this.backupUrl = '';\n        },\n\n        /**\n         * reset.\n         */\n        reset: function () {\n            this.time = 0;\n            this.type = '';\n        },\n\n        /**\n         * @param {*} type\n         * @return {Boolean}\n         */\n        backup: function (type) {\n            this.reset();\n            this.type = type;\n            this.requestBackupOptions();\n\n            return false;\n        },\n\n        /**\n         * @param {*} type\n         * @param {*} time\n         * @return {Boolean}\n         */\n        rollback: function (type, time) {\n            this.reset();\n            this.time = time;\n            this.type = type;\n            this.showRollbackWarning();\n\n            return false;\n        },\n\n        /**\n         * Show rollback warning.\n         */\n        showRollbackWarning: function () {\n            this.showPopup('rollback-warning');\n        },\n\n        /**\n         * request backup options.\n         */\n        requestBackupOptions: function () {\n            var action;\n\n            this.hidePopups();\n            action = this.type != 'snapshot' ? 'hide' : 'show'; //eslint-disable-line eqeqeq\n            this.showPopup('backup-options');\n\n            $$('#exclude-media-checkbox-container').invoke(action);\n        },\n\n        /**\n         * Request password.\n         */\n        requestPassword: function () {\n            this.hidePopups();\n\n            this.showPopup('rollback-request-password');\n\n            this.type != 'db' ? //eslint-disable-line eqeqeq\n                $('use-ftp-checkbox-row').show() :\n                $('use-ftp-checkbox-row').hide();\n        },\n\n        /**\n         * Toggle Ftp Credentials Form.\n         */\n        toggleFtpCredentialsForm: function () {\n            $('use_ftp').checked ? $('ftp-credentials-container').show()\n                : $('ftp-credentials-container').hide();\n\n            $$('#ftp-credentials-container input').each(function (item) {\n                if (item.name == 'ftp_path') { //eslint-disable-line eqeqeq\n                    return;\n                }\n                $('use_ftp').checked ? item.addClassName('required-entry') : item.removeClassName('required-entry');\n            });\n        },\n\n        /**\n         * Submit backup.\n         */\n        submitBackup: function () {\n            var data = {\n                'type': this.type,\n                'maintenance_mode': $('backup_maintenance_mode').checked ? 1 : 0,\n                'backup_name': $('backup_name').value,\n                'exclude_media': $('exclude_media').checked ? 1 : 0\n            };\n\n            new Ajax.Request(this.backupUrl, {\n                onSuccess: function (transport) {\n                    this.processResponse(transport, 'backup-options');\n                }.bind(this),\n                method: 'post',\n                parameters: data\n            });\n\n            this.modal.modal('closeModal');\n        },\n\n        /**\n         * Submit rollback.\n         */\n        submitRollback: function () {\n            var data = this.getPostData();\n\n            new Ajax.Request(this.rollbackUrl, {\n                onSuccess: function (transport) {\n                    this.processResponse(transport, 'rollback-request-password');\n                }.bind(this),\n                method: 'post',\n                parameters: data\n            });\n\n            this.modal.modal('closeModal');\n        },\n\n        /**\n         * @param {Object} transport\n         * @param {*} popupId\n         */\n        processResponse: function (transport, popupId) {\n            var json;\n\n            if (!transport.responseText.isJSON()) {\n                return;\n            }\n\n            json = transport.responseText.evalJSON();\n\n            if (json.error) {\n                this.showPopup(popupId);\n                this.displayError(popupId, json.error);\n\n                return;\n            }\n\n            if (json['redirect_url']) {\n                setLocation(json['redirect_url']);\n            }\n        },\n\n        /**\n         * @param {*} parentContainer\n         * @param {*} message\n         */\n        displayError: function (parentContainer, message) {\n            var messageHtml = this.getErrorMessageHtml(message);\n\n            $$('#' + parentContainer + ' .backup-messages .messages').invoke('update', messageHtml);\n            $$('#' + parentContainer + ' .backup-messages').invoke('show');\n        },\n\n        /**\n         * @param {*} message\n         * @return {String}\n         */\n        getErrorMessageHtml: function (message) {\n            return '<div class=\"message message-error error\"><div>' + message + '</div></div>';\n        },\n\n        /**\n         * @return {*|jQuery}\n         */\n        getPostData: function () {\n            var data = $('rollback-form').serialize(true);\n\n            data.time = this.time;\n            data.type = this.type;\n\n            return data;\n        },\n        backupConfig: {\n            'backup-options': {\n                title: jQuery.mage.__('Backup options'),\n\n                /**\n                 * @return {String}\n                 */\n                content: function () {\n                    return document.getElementById('backup-options-template').textContent;\n                },\n\n                /**\n                 * Action Ok.\n                 */\n                actionOk: function () {\n                    this.modal.find('#backup-form').validation({\n                        submitHandler: jQuery.proxy(this.submitBackup, this)\n                    });\n                    this.modal.find('#backup-form').submit();\n                }\n            },\n            'rollback-warning': {\n                title: jQuery.mage.__('Warning'),\n\n                /**\n                 * @return {String}\n                 */\n                content: function () {\n                    return document.getElementById('rollback-warning-template').textContent;\n                },\n\n                /**\n                 * Action Ok.\n                 */\n                actionOk: function () {\n                    this.modal.modal('closeModal');\n                    this.requestPassword();\n                }\n            },\n            'rollback-request-password': {\n                title: jQuery.mage.__('Backup options'),\n\n                /**\n                 * @return {String}\n                 */\n                content: function () {\n                    return document.getElementById('rollback-request-password-template').textContent;\n                },\n\n                /**\n                 * Action Ok.\n                 */\n                actionOk: function () {\n                    this.modal.find('#rollback-form').validation({\n                        submitHandler: jQuery.proxy(this.submitRollback, this)\n                    });\n                    this.modal.find('#rollback-form').submit();\n                },\n\n                /**\n                 * Opened.\n                 */\n                opened: function () {\n                    this.toggleFtpCredentialsForm();\n                }\n            }\n        },\n\n        /**\n         * @param {*} divId\n         */\n        showPopup: function (divId) {\n            var self = this;\n\n            this.modal = jQuery('<div/>').attr({\n                id: divId\n            }).html(this.backupConfig[divId].content()).modal({\n                modalClass: 'magento',\n                title: this.backupConfig[divId].title,\n                type: 'slide',\n\n                /**\n                 * @param {juery.Event} e\n                 * @param {Object} modal\n                 */\n                closed: function (e, modal) {\n                    modal.modal.remove();\n                },\n\n                /**\n                 * Opened.\n                 */\n                opened: function () {\n                    if (self.backupConfig[divId].opened) {\n                        self.backupConfig[divId].opened.call(self);\n                    }\n                },\n                buttons: [{\n                    text: jQuery.mage.__('Cancel'),\n                    'class': 'action cancel',\n\n                    /**\n                     * Click action.\n                     */\n                    click: function () {\n                        this.closeModal();\n                    }\n                }, {\n                    text: jQuery.mage.__('Ok'),\n                    'class': 'action primary',\n\n                    /**\n                     * Click action.\n                     */\n                    click: function () {\n                        self.backupConfig[divId].actionOk.call(self);\n                    }\n                }]\n            });\n            this.modal.modal('openModal');\n        },\n\n        /**\n         * Hide Popups.\n         */\n        hidePopups: function () {\n            var mask;\n\n            $$('.backup-dialog').each(Element.hide);\n            mask = $('popup-window-mask');\n\n            if (mask) {\n                mask.hide();\n            }\n        }\n    };\n});\n","mage/adminhtml/form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global varienGlobalEvents, varienWindowOnloadCache, RegionUpdater, FormElementDependenceController */\n/* eslint-disable strict */\ndefine([\n    'jquery',\n    'prototype',\n    'mage/adminhtml/events'\n], function (jQuery) {\n    var varienElementMethods;\n\n    /*\n     * @TODO Need to be removed after refactoring all dependent of the form the components\n     */\n    (function ($) {\n        $(document).ready(function () {\n            $(document).on('beforeSubmit', function (e) { //eslint-disable-line max-nested-callbacks\n                if (typeof varienGlobalEvents !== 'undefined') {\n                    varienGlobalEvents.fireEvent('formSubmit', $(e.target).attr('id'));\n                }\n            });\n        });\n    })(jQuery);\n\n    /**\n     *  Additional elements methods\n     */\n    varienElementMethods = {\n        /**\n         * @param {HTMLElement} element\n         */\n        setHasChanges: function (element) {\n            var elm;\n\n            if ($(element) && $(element).hasClassName('no-changes')) {\n                return;\n            }\n            elm = element;\n\n            while (elm && elm.tagName != 'BODY') { //eslint-disable-line eqeqeq\n                if (elm.statusBar) {\n                    Element.addClassName($(elm.statusBar), 'changed');\n                }\n                elm = elm.parentNode;\n            }\n        },\n\n        /**\n         * @param {HTMLElement} element\n         * @param {*} flag\n         * @param {Object} form\n         */\n        setHasError: function (element, flag, form) {\n            var elm = element;\n\n            while (elm && elm.tagName != 'BODY') { //eslint-disable-line eqeqeq\n                if (elm.statusBar) {\n                    /* eslint-disable max-depth */\n                    if (form.errorSections.keys().indexOf(elm.statusBar.id) < 0) {\n                        form.errorSections.set(elm.statusBar.id, flag);\n                    }\n\n                    if (flag) {\n                        Element.addClassName($(elm.statusBar), 'error');\n\n                        if (form.canShowError && $(elm.statusBar).show) {\n                            form.canShowError = false;\n                            $(elm.statusBar).show();\n                        }\n                        form.errorSections.set(elm.statusBar.id, flag);\n                    } else if (!form.errorSections.get(elm.statusBar.id)) {\n                        Element.removeClassName($(elm.statusBar), 'error');\n                    }\n\n                    /* eslint-enable max-depth */\n                }\n                elm = elm.parentNode;\n            }\n            this.canShowElement = false;\n        }\n    };\n\n    Element.addMethods(varienElementMethods);\n\n    // Global bind changes\n    window.varienWindowOnloadCache = {};\n\n    /**\n     * @param {*} useCache\n     */\n    function varienWindowOnload(useCache) {\n        var dataElements = $$('input', 'select', 'textarea'),\n            i;\n\n        for (i = 0; i < dataElements.length; i++) {\n            if (dataElements[i] && dataElements[i].id) {\n\n                /* eslint-disable max-depth */\n                if (!useCache || !varienWindowOnloadCache[dataElements[i].id]) {\n                    Event.observe(dataElements[i], 'change', dataElements[i].setHasChanges.bind(dataElements[i]));\n\n                    if (useCache) {\n                        varienWindowOnloadCache[dataElements[i].id] = true;\n                    }\n                }\n\n                /* eslint-disable max-depth */\n            }\n        }\n    }\n    Event.observe(window, 'load', varienWindowOnload);\n\n    window.RegionUpdater = Class.create();\n    RegionUpdater.prototype = {\n        /**\n         * @param {HTMLElement} countryEl\n         * @param {HTMLElement} regionTextEl\n         * @param {HTMLElement}regionSelectEl\n         * @param {Object} regions\n         * @param {*} disableAction\n         * @param {*} clearRegionValueOnDisable\n         */\n        initialize: function (\n            countryEl, regionTextEl, regionSelectEl, regions, disableAction, clearRegionValueOnDisable\n        ) {\n            this.isRegionRequired = true;\n            this.countryEl = $(countryEl);\n            this.regionTextEl = $(regionTextEl);\n            this.regionSelectEl = $(regionSelectEl);\n            this.config = regions.config;\n            delete regions.config;\n            this.regions = regions;\n            this.disableAction = typeof disableAction === 'undefined' ? 'hide' : disableAction;\n            this.clearRegionValueOnDisable = typeof clearRegionValueOnDisable === 'undefined' ?\n                false : clearRegionValueOnDisable;\n\n            if (this.regionSelectEl.options.length <= 1) {\n                this.update();\n            } else {\n                this.lastCountryId = this.countryEl.value;\n            }\n\n            this.countryEl.changeUpdater = this.update.bind(this);\n\n            Event.observe(this.countryEl, 'change', this.update.bind(this));\n        },\n\n        /**\n         * @private\n         */\n        _checkRegionRequired: function () {\n            var label, wildCard, elements, that, regionRequired;\n\n            if (!this.isRegionRequired) {\n                return;\n            }\n\n            elements = [this.regionTextEl, this.regionSelectEl];\n            that = this;\n\n            if (typeof this.config == 'undefined') {\n                return;\n            }\n            regionRequired = this.config['regions_required'].indexOf(this.countryEl.value) >= 0;\n\n            elements.each(function (currentElement) {\n                var form, validationInstance, field, topElement;\n\n                if (!currentElement) {\n                    return;\n                }\n                form = currentElement.form;\n                validationInstance = form ? jQuery(form).data('validation') : null;\n                field = currentElement.up('.field') || new Element('div');\n\n                if (validationInstance) {\n                    validationInstance.clearError(currentElement);\n                }\n                label = $$('label[for=\"' + currentElement.id + '\"]')[0];\n\n                if (label) {\n                    wildCard = label.down('em') || label.down('span.required');\n                    topElement = label.up('tr') || label.up('li');\n\n                    if (!that.config['show_all_regions'] && topElement) {\n                        if (regionRequired) {\n                            topElement.show();\n                        } else {\n                            topElement.hide();\n                        }\n                    }\n                }\n\n                if (label && wildCard) {\n                    if (!regionRequired) {\n                        wildCard.hide();\n                    } else {\n                        wildCard.show();\n                    }\n                }\n\n                //compute the need for the required fields\n                if (!regionRequired || !currentElement.visible()) {\n                    if (field.hasClassName('required')) {\n                        field.removeClassName('required');\n                    }\n\n                    if (currentElement.hasClassName('required-entry')) {\n                        currentElement.removeClassName('required-entry');\n                    }\n\n                    if (currentElement.tagName.toLowerCase() == 'select' && //eslint-disable-line eqeqeq\n                        currentElement.hasClassName('validate-select')\n                    ) {\n                        currentElement.removeClassName('validate-select');\n                    }\n                } else {\n                    if (!field.hasClassName('required')) {\n                        field.addClassName('required');\n                    }\n\n                    if (!currentElement.hasClassName('required-entry')) {\n                        currentElement.addClassName('required-entry');\n                    }\n\n                    if (currentElement.tagName.toLowerCase() == 'select' && //eslint-disable-line eqeqeq\n                        !currentElement.hasClassName('validate-select')\n                    ) {\n                        currentElement.addClassName('validate-select');\n                    }\n                }\n            });\n        },\n\n        /**\n         * Disable region validation.\n         */\n        disableRegionValidation: function () {\n            this.isRegionRequired = false;\n        },\n\n        /**\n         * Update.\n         */\n        update: function () {\n            var option, region, def, regionId;\n\n            if (this.regions[this.countryEl.value]) {\n                if (this.lastCountryId != this.countryEl.value) { //eslint-disable-line eqeqeq\n                    def = this.regionSelectEl.getAttribute('defaultValue');\n\n                    if (this.regionTextEl) {\n                        if (!def) {\n                            def = this.regionTextEl.value.toLowerCase();\n                        }\n                        this.regionTextEl.value = '';\n                    }\n\n                    this.regionSelectEl.options.length = 1;\n\n                    for (regionId in this.regions[this.countryEl.value]) { //eslint-disable-line guard-for-in\n                        region = this.regions[this.countryEl.value][regionId];\n\n                        option = document.createElement('OPTION');\n                        option.value = regionId;\n                        option.text = region.name.stripTags();\n                        option.title = region.name;\n\n                        if (this.regionSelectEl.options.add) {\n                            this.regionSelectEl.options.add(option);\n                        } else {\n                            this.regionSelectEl.appendChild(option);\n                        }\n\n                        if (regionId == def || region.name.toLowerCase() == def || region.code.toLowerCase() == def) { //eslint-disable-line\n                            this.regionSelectEl.value = regionId;\n                        }\n                    }\n                }\n\n                if (this.disableAction == 'hide') { //eslint-disable-line eqeqeq\n                    if (this.regionTextEl) {\n                        this.regionTextEl.style.display = 'none';\n                        this.regionTextEl.style.disabled = true;\n                    }\n                    this.regionSelectEl.style.display = '';\n                    this.regionSelectEl.disabled = false;\n                } else if (this.disableAction == 'disable') { //eslint-disable-line eqeqeq\n                    if (this.regionTextEl) {\n                        this.regionTextEl.disabled = true;\n                    }\n                    this.regionSelectEl.disabled = false;\n                }\n                this.setMarkDisplay(this.regionSelectEl, true);\n\n                this.lastCountryId = this.countryEl.value;\n            } else {\n                if (this.disableAction == 'hide') { //eslint-disable-line eqeqeq\n                    if (this.regionTextEl) {\n                        this.regionTextEl.style.display = '';\n                        this.regionTextEl.style.disabled = false;\n                    }\n                    this.regionSelectEl.style.display = 'none';\n                    this.regionSelectEl.disabled = true;\n                } else if (this.disableAction == 'disable') { //eslint-disable-line eqeqeq\n                    if (this.regionTextEl) {\n                        this.regionTextEl.disabled = false;\n                    }\n                    this.regionSelectEl.disabled = true;\n\n                    if (this.clearRegionValueOnDisable) {\n                        this.regionSelectEl.value = '';\n                    }\n                } else if (this.disableAction == 'nullify') { //eslint-disable-line eqeqeq\n                    this.regionSelectEl.options.length = 1;\n                    this.regionSelectEl.value = '';\n                    this.regionSelectEl.selectedIndex = 0;\n                    this.lastCountryId = '';\n                }\n                this.setMarkDisplay(this.regionSelectEl, false);\n            }\n            varienGlobalEvents.fireEvent('address_country_changed', this.countryEl);\n            this._checkRegionRequired();\n        },\n\n        /**\n         * @param {HTMLElement} elem\n         * @param {*} display\n         */\n        setMarkDisplay: function (elem, display) {\n            var marks;\n\n            if (elem.parentNode.parentNode) {\n                marks = Element.select(elem.parentNode.parentNode, '.required');\n\n                if (marks[0]) {\n                    display ? marks[0].show() : marks[0].hide();\n                }\n            }\n        }\n    };\n\n    window.regionUpdater = RegionUpdater;\n\n    /**\n     * Fix errorrs in IE\n     */\n    Event.pointerX = function (event) {\n        try {\n            return event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)); //eslint-disable-line\n        }\n        catch (e) {}\n    };\n\n    /**\n     * @param {jQuery.Event} event\n     * @return {*}\n     */\n    Event.pointerY = function (event) {\n        try {\n            return event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)); //eslint-disable-line\n        }\n        catch (e) {}\n    };\n\n    /**\n     * Observer that watches for dependent form elements\n     * If an element depends on 1 or more of other elements,\n     * it should show up only when all of them gain specified values\n     */\n    window.FormElementDependenceController = Class.create();\n    FormElementDependenceController.prototype = {\n        /**\n         * Structure of elements: {\n         *     'id_of_dependent_element' : {\n         *         'id_of_master_element_1' : 'reference_value',\n         *         'id_of_master_element_2' : 'reference_value'\n         *         'id_of_master_element_3' : ['reference_value1', 'reference_value2']\n         *         ...\n         *     }\n         * }\n         * @param {Object} elementsMap\n         * @param {Object} config\n         */\n        initialize: function (elementsMap, config) {\n            var idTo, idFrom, values, fromId, radioFrom;\n\n            if (config) {\n                this._config = jQuery.extend(this._config, config);\n            }\n\n            for (idTo in elementsMap) { //eslint-disable-line guard-for-in\n                for (idFrom in elementsMap[idTo]) { //eslint-disable-line guard-for-in\n                    if ($(idFrom)) {\n                        Event.observe(\n                            $(idFrom),\n                            'change',\n                            this.trackChange.bindAsEventListener(this, idTo, elementsMap[idTo])\n                        );\n                    } else {\n                        // Check if radio button\n                        values = elementsMap[idTo][idFrom].values;\n                        fromId = $(idFrom + values[0]);\n                        radioFrom = fromId ? $$('[name=\"' + fromId.name + '\"]') : false;\n\n                        if (radioFrom) {\n                            radioFrom.invoke(\n                                'on',\n                                'change',\n                                this.trackChange.bindAsEventListener(this, idTo, elementsMap[idTo])\n                            );\n                        }\n                    }\n                    this.trackChange(null, idTo, elementsMap[idTo]);\n                }\n            }\n        },\n\n        /**\n         * Misc. config options\n         * Keys are underscored intentionally\n         */\n        _config: {\n            'levels_up': 1 // how many levels up to travel when toggling element\n        },\n\n        /**\n         * Define whether target element should be toggled and show/hide its row\n         *\n         * @param {Object} e - event\n         * @param {String} idTo - id of target element\n         * @param {Object} valuesFrom - ids of master elements and reference values\n         * @return\n         */\n        trackChange: function (e, idTo, valuesFrom) {\n            // define whether the target should show up\n            var shouldShowUp = true,\n                idFrom, from, values, isInArray, isNegative, headElement, isInheritCheckboxChecked, target, inputs,\n                isAnInputOrSelect, currentConfig, rowElement, fromId, radioFrom;\n\n            for (idFrom in valuesFrom) { //eslint-disable-line guard-for-in\n                from = $(idFrom);\n\n                if (from) {\n                    values = valuesFrom[idFrom].values;\n                    isInArray = values.indexOf(from.value) != -1; //eslint-disable-line\n                    isNegative = valuesFrom[idFrom].negative;\n\n                    if (!from || isInArray && isNegative || !isInArray && !isNegative) {\n                        shouldShowUp = false;\n                    }\n                // Check if radio button\n                } else {\n                    values = valuesFrom[idFrom].values;\n                    fromId = $(idFrom + values[0]);\n\n                    if (fromId) {\n                        radioFrom = $$('[name=\"' + fromId.name + '\"]:checked');\n                        isInArray = radioFrom.length > 0 && values.indexOf(radioFrom[0].value) !== -1;\n                        isNegative = valuesFrom[idFrom].negative;\n\n                        if (!radioFrom || isInArray && isNegative || !isInArray && !isNegative) {\n                            shouldShowUp = false;\n                        }\n                    }\n                }\n            }\n\n            // toggle target row\n            headElement = $(idTo + '-head');\n            isInheritCheckboxChecked = $(idTo + '_inherit') && $(idTo + '_inherit').checked;\n            target = $(idTo);\n\n            // Target won't always exist (for example, if field type is \"label\")\n            if (target) {\n                inputs = target.up(this._config['levels_up']).select('input', 'select', 'td');\n                isAnInputOrSelect = ['input', 'select'].indexOf(target.tagName.toLowerCase()) != -1; //eslint-disable-line\n\n                if (target.type === 'fieldset') {\n                    inputs = target.select('input', 'select', 'td');\n                }\n            } else {\n                inputs = false;\n                isAnInputOrSelect = false;\n            }\n\n            if (shouldShowUp) {\n                currentConfig = this._config;\n\n                if (inputs) {\n                    inputs.each(function (item) {\n                        // don't touch hidden inputs (and Use Default inputs too), bc they may have custom logic\n                        if ((!item.type || item.type != 'hidden') && !($(item.id + '_inherit') && $(item.id + '_inherit').checked) && //eslint-disable-line\n                            !(currentConfig['can_edit_price'] != undefined && !currentConfig['can_edit_price']) //eslint-disable-line\n                        ) {\n                            item.disabled = false;\n                            jQuery(item).removeClass('ignore-validate');\n                        }\n                    });\n                }\n\n                if (headElement) {\n                    headElement.show();\n\n                    if (headElement.hasClassName('open') && target) {\n                        target.show();\n                    } else if (target) {\n                        target.hide();\n                    }\n                } else {\n                    if (target) {\n                        target.show();\n                    }\n\n                    if (isAnInputOrSelect && !isInheritCheckboxChecked) {\n                        if (target) {\n                            if (target.getAttribute('readonly')) {\n                                target.disabled = true;\n                            } else {\n                                target.disabled = false;\n                            }\n                        }\n\n                        jQuery('#' + idTo).removeClass('ignore-validate');\n                    }\n                }\n            } else {\n                if (inputs) {\n                    inputs.each(function (item) {\n                        // don't touch hidden inputs (and Use Default inputs too), bc they may have custom logic\n                        if ((!item.type || item.type != 'hidden') && //eslint-disable-line eqeqeq\n                            !($(item.id + '_inherit') && $(item.id + '_inherit').checked)\n                        ) {\n                            item.disabled = true;\n                            jQuery(item).addClass('ignore-validate');\n                        }\n                    });\n                }\n\n                if (headElement) {\n                    headElement.hide();\n                }\n\n                if (target) {\n                    target.hide();\n                }\n\n                if (isAnInputOrSelect && !isInheritCheckboxChecked) {\n                    if (target) {\n                        target.disabled = true;\n                    }\n                    jQuery('#' + idTo).addClass('ignore-validate');\n                }\n\n            }\n            rowElement = $('row_' + idTo);\n\n            if (rowElement == undefined && target) { //eslint-disable-line eqeqeq\n                rowElement = target.up(this._config['levels_up']);\n\n                if (target.type === 'fieldset') {\n                    rowElement = target;\n                }\n            }\n\n            if (rowElement) {\n                if (shouldShowUp) {\n                    rowElement.show();\n                } else {\n                    rowElement.hide();\n                }\n            }\n        }\n    };\n\n    window.varienWindowOnload = varienWindowOnload;\n    window.varienElementMethods = varienElementMethods;\n});\n","mage/adminhtml/browser.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global MediabrowserUtility, FORM_KEY, tinyMceEditors */\n/* eslint-disable strict */\ndefine([\n    'jquery',\n    'wysiwygAdapter',\n    'Magento_Ui/js/modal/prompt',\n    'Magento_Ui/js/modal/confirm',\n    'Magento_Ui/js/modal/alert',\n    'Magento_Ui/js/modal/modal',\n    'jquery/ui',\n    'jquery/jstree/jquery.jstree',\n    'mage/mage'\n], function ($, wysiwyg, prompt, confirm, alert) {\n    window.MediabrowserUtility = {\n        windowId: 'modal_dialog_message',\n\n        /**\n         * @return {Number}\n         */\n        getMaxZIndex: function () {\n            var max = 0,\n                cn = document.body.childNodes,\n                i, el, zIndex;\n\n            for (i = 0; i < cn.length; i++) {\n                el = cn[i];\n                zIndex = el.nodeType == 1 ? parseInt(el.style.zIndex, 10) || 0 : 0; //eslint-disable-line eqeqeq\n\n                if (zIndex < 10000) {\n                    max = Math.max(max, zIndex);\n                }\n            }\n\n            return max + 10;\n        },\n\n        /**\n         * @param {*} url\n         * @param {*} width\n         * @param {*} height\n         * @param {*} title\n         * @param {Object} options\n         */\n        openDialog: function (url, width, height, title, options) {\n            var windowId = this.windowId,\n                content = '<div class=\"popup-window\" id=\"' + windowId + '\"></div>',\n                self = this;\n\n            if (this.modal) {\n                this.modal.html($(content).html());\n\n                if (options && typeof options.closed !== 'undefined') {\n                    this.modal.modal('option', 'closed', options.closed);\n                }\n            } else {\n                this.modal = $(content).modal($.extend({\n                    title:  title || 'Insert File...',\n                    modalClass: 'magento',\n                    type: 'slide',\n                    buttons: []\n                }, options));\n            }\n            this.modal.modal('openModal');\n            $.ajax({\n                url: url,\n                type: 'get',\n                context: $(this),\n                showLoader: true\n\n            }).done(function (data) {\n                self.modal.html(data).trigger('contentUpdated');\n            });\n        },\n\n        /**\n         * Close dialog.\n         */\n        closeDialog: function () {\n            this.modal.modal('closeModal');\n        }\n    };\n\n    $.widget('mage.mediabrowser', {\n        eventPrefix: 'mediabrowser',\n        options: {\n            targetElementId: null,\n            contentsUrl: null,\n            onInsertUrl: null,\n            newFolderUrl: null,\n            deleteFolderUrl: null,\n            deleteFilesUrl: null,\n            headerText: null,\n            tree: null,\n            currentNode: null,\n            storeId: null,\n            showBreadcrumbs: null,\n            hidden: 'no-display'\n        },\n\n        /**\n         * Proxy creation\n         * @protected\n         */\n        _create: function () {\n            this._on({\n                'click [data-row=file]': 'selectFile',\n                'dblclick [data-row=file]': 'insert',\n                'click #new_folder': 'newFolder',\n                'click #delete_folder': 'deleteFolder',\n                'click #delete_files': 'deleteFiles',\n                'click #insert_files': 'insertSelectedFiles',\n                'fileuploaddone': '_uploadDone',\n                'click [data-row=breadcrumb]': 'selectFolder'\n            });\n            this.activeNode = null;\n            //tree dont use event bubbling\n            this.tree = this.element.find('[data-role=tree]');\n            this.tree.on('select_node.jstree', $.proxy(this._selectNode, this));\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @param {Object} data\n         * @private\n         */\n        _selectNode: function (event, data) {\n            var node = data.rslt.obj.data('node');\n\n            this.activeNode = node;\n            this.element.find('#delete_files, #insert_files').toggleClass(this.options.hidden, true);\n            this.element.find('#contents').toggleClass(this.options.hidden, false);\n            this.element.find('#delete_folder')\n                .toggleClass(this.options.hidden, node.id == 'root'); //eslint-disable-line eqeqeq\n            this.element.find('#content_header_text')\n                .html(node.id == 'root' ? this.headerText : node.text); //eslint-disable-line eqeqeq\n\n            this.drawBreadcrumbs(data);\n            this.loadFileList(node);\n        },\n\n        /**\n         * @return {*}\n         */\n        reload: function (uploaded) {\n            return this.loadFileList(this.activeNode, uploaded);\n        },\n\n        /**\n         * @param {Object} element\n         * @param {*} value\n         */\n        insertAtCursor: function (element, value) {\n            var sel, startPos, endPos, scrollTop;\n\n            if ('selection' in document) {\n                //For browsers like Internet Explorer\n                element.focus();\n                sel = document.selection.createRange();\n                sel.text = value;\n                element.focus();\n            } else if (element.selectionStart || element.selectionStart == '0') { //eslint-disable-line eqeqeq\n                //For browsers like Firefox and Webkit based\n                startPos = element.selectionStart;\n                endPos = element.selectionEnd;\n                scrollTop = element.scrollTop;\n                element.value = element.value.substring(0, startPos) + value +\n                    element.value.substring(startPos, endPos) + element.value.substring(endPos, element.value.length);\n                element.focus();\n                element.selectionStart = startPos + value.length;\n                element.selectionEnd = startPos + value.length + element.value.substring(startPos, endPos).length;\n                element.scrollTop = scrollTop;\n            } else {\n                element.value += value;\n                element.focus();\n            }\n        },\n\n        /**\n         * @param {Object} node\n         */\n        loadFileList: function (node, uploaded) {\n            var contentBlock = this.element.find('#contents');\n\n            return $.ajax({\n                url: this.options.contentsUrl,\n                type: 'GET',\n                dataType: 'html',\n                data: {\n                    'form_key': FORM_KEY,\n                    node: node.id\n                },\n                context: contentBlock,\n                showLoader: true\n            }).done(function (data) {\n                contentBlock.html(data).trigger('contentUpdated');\n\n                if (uploaded) {\n                    contentBlock.find('.filecnt:last').click();\n                }\n            });\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        selectFolder: function (event) {\n            this.element.find('[data-id=\"' + $(event.currentTarget).data('node').id + '\"]>a').click();\n        },\n\n        /**\n         * Insert selected files.\n         */\n        insertSelectedFiles: function () {\n            this.element.find('[data-row=file].selected').trigger('dblclick');\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        selectFile: function (event) {\n            var fileRow = $(event.currentTarget);\n\n            fileRow.toggleClass('selected');\n            this.element.find('[data-row=file]').not(fileRow).removeClass('selected');\n            this.element.find('#delete_files, #insert_files')\n                .toggleClass(this.options.hidden, !fileRow.is('.selected'));\n            fileRow.trigger('selectfile');\n        },\n\n        /**\n         * @private\n         */\n        _uploadDone: function () {\n            this.element.find('.file-row').remove();\n            this.reload(true);\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @return {Boolean}\n         */\n        insert: function (event) {\n            var fileRow = $(event.currentTarget),\n                targetEl;\n\n            if (!fileRow.prop('id')) {\n                return false;\n            }\n            targetEl = this.getTargetElement();\n\n            if (!targetEl.length) {\n                MediabrowserUtility.closeDialog();\n                throw 'Target element not found for content update';\n            }\n\n            return $.ajax({\n                url: this.options.onInsertUrl,\n                data: {\n                    filename: fileRow.attr('id'),\n                    node: this.activeNode.id,\n                    store: this.options.storeId,\n                    'as_is': targetEl.is('textarea') ? 1 : 0,\n                    'force_static_path': targetEl.data('force_static_path') ? 1 : 0,\n                    'form_key': FORM_KEY\n                },\n                context: this,\n                showLoader: true\n            }).done($.proxy(function (data) {\n                if (targetEl.is('textarea')) {\n                    this.insertAtCursor(targetEl.get(0), data);\n                } else {\n                    targetEl\n                        .val(data)\n                        .data('size', fileRow.data('size'))\n                        .data('mime-type', fileRow.data('mime-type'))\n                        .trigger('change');\n                }\n                MediabrowserUtility.closeDialog();\n                targetEl.focus();\n                jQuery(targetEl).change();\n            }, this));\n        },\n\n        /**\n         * Find document target element in next order:\n         *  in acive file browser opener:\n         *  - input field with ID: \"src\" in opener window\n         *  - input field with ID: \"href\" in opener window\n         *  in document:\n         *  - element with target ID\n         *\n         * return {HTMLElement|null}\n         */\n        getTargetElement: function () {\n            var opener, targetElementId;\n\n            if (typeof wysiwyg != 'undefined' && wysiwyg.get(this.options.targetElementId)) {\n                opener = this.getMediaBrowserOpener() || window;\n                targetElementId = tinyMceEditors.get(this.options.targetElementId).getMediaBrowserTargetElementId();\n\n                return $(opener.document.getElementById(targetElementId));\n            }\n\n            return $('#' + this.options.targetElementId);\n        },\n\n        /**\n         * Return opener Window object if it exists, not closed and editor is active\n         *\n         * return {Object|null}\n         */\n        getMediaBrowserOpener: function () {\n            if (typeof wysiwyg != 'undefined' &&\n                wysiwyg.get(this.options.targetElementId) &&\n                typeof tinyMceEditors != 'undefined' &&\n                !tinyMceEditors.get(this.options.targetElementId).getMediaBrowserOpener().closed\n            ) {\n                return tinyMceEditors.get(this.options.targetElementId).getMediaBrowserOpener();\n            }\n\n            return null;\n        },\n\n        /**\n         * New folder.\n         */\n        newFolder: function () {\n            var self = this;\n\n            prompt({\n                title: this.options.newFolderPrompt,\n                actions: {\n                    /**\n                     * @param {*} folderName\n                     */\n                    confirm: function (folderName) {\n                        return $.ajax({\n                            url: self.options.newFolderUrl,\n                            dataType: 'json',\n                            data: {\n                                name: folderName,\n                                node: self.activeNode.id,\n                                store: self.options.storeId,\n                                'form_key': FORM_KEY\n                            },\n                            context: self.element,\n                            showLoader: true\n                        }).done($.proxy(function (data) {\n                            if (data.error) {\n                                alert({\n                                    content: data.message\n                                });\n                            } else {\n                                self.tree.jstree(\n                                    'refresh',\n                                    self.element.find('[data-id=\"' + self.activeNode.id + '\"]')\n                                );\n                            }\n                        }, this));\n                    }\n                }\n            });\n        },\n\n        /**\n         * Delete folder.\n         */\n        deleteFolder: function () {\n            var self = this;\n\n            confirm({\n                content: this.options.deleteFolderConfirmationMessage,\n                actions: {\n                    /**\n                     * Confirm.\n                     */\n                    confirm: function () {\n                        return $.ajax({\n                            url: self.options.deleteFolderUrl,\n                            dataType: 'json',\n                            data: {\n                                node: self.activeNode.id,\n                                store: self.options.storeId,\n                                'form_key': FORM_KEY\n                            },\n                            context: self.element,\n                            showLoader: true\n                        }).done($.proxy(function () {\n                            self.tree.jstree('refresh', self.activeNode.id);\n                        }, this));\n                    },\n\n                    /**\n                     * @return {Boolean}\n                     */\n                    cancel: function () {\n                        return false;\n                    }\n                }\n            });\n        },\n\n        /**\n         * Delete files.\n         */\n        deleteFiles: function () {\n            var self = this;\n\n            confirm({\n                content: this.options.deleteFileConfirmationMessage,\n                actions: {\n                    /**\n                     * Confirm.\n                     */\n                    confirm: function () {\n                        var selectedFiles = self.element.find('[data-row=file].selected'),\n                            ids = selectedFiles.map(function () {\n                                return $(this).attr('id');\n                            }).toArray();\n\n                        return $.ajax({\n                            url: self.options.deleteFilesUrl,\n                            data: {\n                                files: ids,\n                                store: self.options.storeId,\n                                'form_key': FORM_KEY\n                            },\n                            context: self.element,\n                            showLoader: true\n                        }).done($.proxy(function () {\n                            self.reload();\n                            self.element.find('#delete_files, #insert_files').toggleClass(self.options.hidden, true);\n\n                            $(window).trigger('fileDeleted.mediabrowser', {\n                                ids: ids\n                            });\n                        }, this));\n                    },\n\n                    /**\n                     * @return {Boolean}\n                     */\n                    cancel: function () {\n                        return false;\n                    }\n                }\n            });\n        },\n\n        /**\n         * @param {Object} data\n         */\n        drawBreadcrumbs: function (data) {\n            var node, breadcrumbs;\n\n            if (this.element.find('#breadcrumbs').length) {\n                this.element.find('#breadcrumbs').remove();\n            }\n            node = data.rslt.obj.data('node');\n\n            if (node.id == 'root') { //eslint-disable-line eqeqeq\n                return;\n            }\n            breadcrumbs = $('<ul class=\"breadcrumbs\" id=\"breadcrumbs\" />');\n            $(data.rslt.obj.parents('[data-id]').get().reverse()).add(data.rslt.obj).each(function (index, element) {\n                var nodeData = $(element).data('node');\n\n                if (index > 0) {\n                    breadcrumbs.append($('<li>\\/</li>'));\n                }\n                breadcrumbs.append($('<li />')\n                    .data('node', nodeData).attr('data-row', 'breadcrumb').text(nodeData.text));\n\n            });\n\n            breadcrumbs.insertAfter(this.element.find('#content_header'));\n        }\n    });\n\n    return window.MediabrowserUtility;\n});\n","mage/adminhtml/wysiwyg/events.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        afterInitialization: 'afterInitialization',\n        afterChangeContent: 'afterChangeContent',\n        afterUndo: 'afterUndo',\n        afterPaste: 'afterPaste',\n        beforeSetContent: 'beforeSetContent',\n        afterSetContent: 'afterSetContent',\n        afterSave: 'afterSave',\n        afterOpenFileBrowser: 'afterOpenFileBrowser',\n        afterFormSubmit: 'afterFormSubmit',\n        afterBlur: 'afterBlur',\n        afterFocus: 'afterFocus'\n    };\n});\n","mage/adminhtml/wysiwyg/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global setLocation, Base64, updateElementAtCursor, varienGlobalEvents */\n/* eslint-disable strict */\ndefine([\n    'jquery',\n    'wysiwygAdapter',\n    'Magento_Ui/js/modal/alert',\n    'jquery/ui',\n    'mage/translate',\n    'mage/mage',\n    'mage/validation',\n    'mage/adminhtml/events',\n    'prototype',\n    'Magento_Ui/js/modal/modal'\n], function (jQuery, wysiwyg, alert) {\n    var widgetTools = {\n\n        /**\n         * Sets the widget to be active and is the scope of the slide out if the value is set\n         */\n        activeSelectedNode: null,\n        editMode: false,\n        cursorLocation: 0,\n\n        /**\n         * Set active selected node.\n         *\n         * @param {Object} activeSelectedNode\n         */\n        setActiveSelectedNode: function (activeSelectedNode) {\n            this.activeSelectedNode = activeSelectedNode;\n        },\n\n        /**\n         * Get active selected node.\n         *\n         * @returns {null}\n         */\n        getActiveSelectedNode: function () {\n            return this.activeSelectedNode;\n        },\n\n        /**\n         *\n         * @param {Boolean} editMode\n         */\n        setEditMode: function (editMode) {\n            this.editMode = editMode;\n        },\n\n        /**\n         * @param {*} id\n         * @param {*} html\n         * @return {String}\n         */\n        getDivHtml: function (id, html) {\n\n            if (!html) {\n                html = '';\n            }\n\n            return '<div id=\"' + id + '\">' + html + '</div>';\n        },\n\n        /**\n         * @param {Object} transport\n         */\n        onAjaxSuccess: function (transport) {\n            var response;\n\n            if (transport.responseText.isJSON()) {\n                response = transport.responseText.evalJSON();\n\n                if (response.error) {\n                    throw response;\n                } else if (response.ajaxExpired && response.ajaxRedirect) {\n                    setLocation(response.ajaxRedirect);\n                }\n            }\n        },\n\n        dialogOpened: false,\n\n        /**\n         * @return {Number}\n         */\n        getMaxZIndex: function () {\n            var max = 0,\n                cn = document.body.childNodes,\n                i, el, zIndex;\n\n            for (i = 0; i < cn.length; i++) {\n                el = cn[i];\n                zIndex = el.nodeType == 1 ? parseInt(el.style.zIndex, 10) || 0 : 0; //eslint-disable-line eqeqeq\n\n                if (zIndex < 10000) {\n                    max = Math.max(max, zIndex);\n                }\n            }\n\n            return max + 10;\n        },\n\n        /**\n         * @param {String} widgetUrl\n         */\n        openDialog: function (widgetUrl) {\n            var oThis = this,\n                title = 'Insert Widget',\n                mode = 'new',\n                dialog;\n\n            if (this.editMode) {\n                title = 'Edit Widget';\n                mode = 'edit';\n            }\n\n            if (this.dialogOpened) {\n                return;\n            }\n\n            this.dialogWindow = jQuery('<div/>').modal({\n\n                title: jQuery.mage.__(title),\n                type: 'slide',\n                buttons: [],\n\n                /**\n                 * Opened.\n                 */\n                opened: function () {\n                    dialog = jQuery(this).addClass('loading magento-message');\n\n                    widgetUrl += 'mode/' + mode;\n\n                    new Ajax.Updater($(this), widgetUrl, {\n                        evalScripts: true,\n\n                        /**\n                         * On complete.\n                         */\n                        onComplete: function () {\n                            dialog.removeClass('loading');\n                        }\n                    });\n                },\n\n                /**\n                 * @param {jQuery.Event} e\n                 * @param {Object} modal\n                 */\n                closed: function (e, modal) {\n                    modal.modal.remove();\n                    oThis.dialogOpened = false;\n                }\n            });\n\n            this.dialogOpened = true;\n            this.dialogWindow.modal('openModal');\n        }\n    },\n    WysiwygWidget = {};\n\n    WysiwygWidget.Widget = Class.create();\n    WysiwygWidget.Widget.prototype = {\n        /**\n         * @param {HTMLElement} formEl\n         * @param {HTMLElement} widgetEl\n         * @param {*} widgetOptionsEl\n         * @param {*} optionsSourceUrl\n         * @param {*} widgetTargetId\n         */\n        initialize: function (formEl, widgetEl, widgetOptionsEl, optionsSourceUrl, widgetTargetId) {\n            $(formEl).insert({\n                bottom: widgetTools.getDivHtml(widgetOptionsEl)\n            });\n\n            this.formEl = formEl;\n            this.widgetEl = $(widgetEl);\n            this.widgetOptionsEl = $(widgetOptionsEl);\n            this.optionsUrl = optionsSourceUrl;\n            this.optionValues = new Hash({});\n            this.widgetTargetId = widgetTargetId;\n\n            if (typeof wysiwyg != 'undefined' && wysiwyg.activeEditor()) { //eslint-disable-line eqeqeq\n                this.bMark = wysiwyg.activeEditor().selection.getBookmark();\n            }\n\n            // disable -- Please Select -- option from being re-selected\n            this.widgetEl.querySelector('option').setAttribute('disabled', 'disabled');\n\n            Event.observe(this.widgetEl, 'change', this.loadOptions.bind(this));\n\n            this.initOptionValues();\n        },\n\n        /**\n         * @return {String}\n         */\n        getOptionsContainerId: function () {\n            return this.widgetOptionsEl.id + '_' + this.widgetEl.value.gsub(/\\//, '_');\n        },\n\n        /**\n         * @param {*} containerId\n         */\n        switchOptionsContainer: function (containerId) {\n            $$('#' + this.widgetOptionsEl.id + ' div[id^=' + this.widgetOptionsEl.id + ']').each(function (e) {\n                this.disableOptionsContainer(e.id);\n            }.bind(this));\n\n            if (containerId != undefined) { //eslint-disable-line eqeqeq\n                this.enableOptionsContainer(containerId);\n            }\n            this._showWidgetDescription();\n        },\n\n        /**\n         * @param {*} containerId\n         */\n        enableOptionsContainer: function (containerId) {\n            $$('#' + containerId + ' .widget-option').each(function (e) {\n                e.removeClassName('skip-submit');\n\n                if (e.hasClassName('obligatory')) {\n                    e.removeClassName('obligatory');\n                    e.addClassName('required-entry');\n                }\n            });\n            $(containerId).removeClassName('no-display');\n        },\n\n        /**\n         * @param {*} containerId\n         */\n        disableOptionsContainer: function (containerId) {\n\n            if ($(containerId).hasClassName('no-display')) {\n                return;\n            }\n            $$('#' + containerId + ' .widget-option').each(function (e) {\n                // Avoid submitting fields of unactive container\n                if (!e.hasClassName('skip-submit')) {\n                    e.addClassName('skip-submit');\n                }\n                // Form validation workaround for unactive container\n                if (e.hasClassName('required-entry')) {\n                    e.removeClassName('required-entry');\n                    e.addClassName('obligatory');\n                }\n            });\n            $(containerId).addClassName('no-display');\n        },\n\n        /**\n         * Assign widget options values when existing widget selected in WYSIWYG.\n         *\n         * @return {Boolean}\n         */\n        initOptionValues: function () {\n            var e, widgetCode;\n\n            if (!this.wysiwygExists()) {\n                return false;\n            }\n\n            e = this.getWysiwygNode();\n\n            if (e.localName === 'span') {\n                e = e.firstElementChild;\n            }\n\n            if (e != undefined && e.id) { //eslint-disable-line eqeqeq\n                // attempt to Base64-decode id on selected node; exception is thrown if it is in fact not a widget node\n                try {\n                    widgetCode = Base64.idDecode(e.id);\n                } catch (ex) {\n                    return false;\n                }\n\n                if (widgetCode.indexOf('{{widget') !== -1) {\n                    this.optionValues = new Hash({});\n                    widgetCode.gsub(/([a-z0-9\\_]+)\\s*\\=\\s*[\\\"]{1}([^\\\"]+)[\\\"]{1}/i, function (match) {\n\n                        if (match[1] == 'type') { //eslint-disable-line eqeqeq\n                            this.widgetEl.value = match[2];\n                        } else {\n                            this.optionValues.set(match[1], match[2]);\n                        }\n\n                    }.bind(this));\n\n                    this.loadOptions();\n                }\n            }\n        },\n\n        /**\n         * Load options.\n         */\n        loadOptions: function () {\n            var optionsContainerId,\n                params,\n                msg,\n                msgTmpl,\n                $wrapper,\n                typeName = this.optionValues.get('type_name');\n\n            if (!this.widgetEl.value) {\n                if (typeName) {\n                    msgTmpl = jQuery.mage.__('The widget %1 is no longer available. Select a different widget.');\n                    msg = jQuery.mage.__(msgTmpl).replace('%1', typeName);\n\n                    jQuery('body').notification('clear').notification('add', {\n                        error: true,\n                        message: msg,\n\n                        /**\n                         * @param {String} message\n                         */\n                        insertMethod: function (message) {\n                            $wrapper = jQuery('<div/>').html(message);\n\n                            $wrapper.insertAfter('.modal-slide .page-main-actions');\n                        }\n                    });\n                }\n                this.switchOptionsContainer();\n\n                return;\n            }\n\n            optionsContainerId = this.getOptionsContainerId();\n\n            if ($(optionsContainerId) != undefined) { //eslint-disable-line eqeqeq\n                this.switchOptionsContainer(optionsContainerId);\n\n                return;\n            }\n\n            this._showWidgetDescription();\n\n            params = {\n                'widget_type': this.widgetEl.value,\n                values: this.optionValues\n            };\n            new Ajax.Request(this.optionsUrl, {\n                parameters: {\n                    widget: Object.toJSON(params)\n                },\n\n                /**\n                 * On success.\n                 */\n                onSuccess: function (transport) {\n                    try {\n                        widgetTools.onAjaxSuccess(transport);\n                        this.switchOptionsContainer();\n\n                        if ($(optionsContainerId) == undefined) { //eslint-disable-line eqeqeq\n                            this.widgetOptionsEl.insert({\n                                bottom: widgetTools.getDivHtml(optionsContainerId, transport.responseText)\n                            });\n                        } else {\n                            this.switchOptionsContainer(optionsContainerId);\n                        }\n                    } catch (e) {\n                        alert({\n                            content: e.message\n                        });\n                    }\n                }.bind(this)\n            });\n        },\n\n        /**\n         * @private\n         */\n        _showWidgetDescription: function () {\n            var noteCnt = this.widgetEl.next().down('small'),\n                descrCnt = $('widget-description-' + this.widgetEl.selectedIndex),\n                description;\n\n            if (noteCnt != undefined) { //eslint-disable-line eqeqeq\n                description = descrCnt != undefined ? descrCnt.innerHTML : ''; //eslint-disable-line eqeqeq\n                noteCnt.update(description);\n            }\n        },\n\n        /**\n         * Validate field.\n         */\n        validateField: function () {\n            jQuery(this.widgetEl).valid();\n            jQuery('#insert_button').removeClass('disabled');\n        },\n\n        /**\n         * Closes the modal\n         */\n        closeModal: function () {\n            widgetTools.dialogWindow.modal('closeModal');\n        },\n\n        /* eslint-disable max-depth*/\n        /**\n         * Insert widget.\n         */\n        insertWidget: function () {\n            var validationResult,\n                $form = jQuery('#' + this.formEl),\n                formElements,\n                i,\n                params,\n                editor,\n                activeNode;\n\n            // remove cached validator instance, which caches elements to validate\n            jQuery.data($form[0], 'validator', null);\n\n            $form.validate({\n                /**\n                 * Ignores elements with .skip-submit, .no-display ancestor elements\n                 */\n                ignore: function () {\n                    return jQuery(this).closest('.skip-submit, .no-display').length;\n                },\n                errorClass: 'mage-error'\n            });\n\n            validationResult = $form.valid();\n\n            if (validationResult) {\n                formElements = [];\n                i = 0;\n                Form.getElements($(this.formEl)).each(function (e) {\n\n                    if (!e.hasClassName('skip-submit')) {\n                        formElements[i] = e;\n                        i++;\n                    }\n                });\n\n                // Add as_is flag to parameters if wysiwyg editor doesn't exist\n                params = Form.serializeElements(formElements);\n\n                if (!this.wysiwygExists()) {\n                    params += '&as_is=1';\n                }\n\n                new Ajax.Request($(this.formEl).action, {\n                    parameters: params,\n                    onComplete: function (transport) {\n                        try {\n                            editor = wysiwyg.activeEditor();\n\n                            widgetTools.onAjaxSuccess(transport);\n                            widgetTools.dialogWindow.modal('closeModal');\n\n                            if (editor) {\n                                editor.focus();\n                                activeNode = widgetTools.getActiveSelectedNode();\n\n                                if (activeNode) {\n                                    editor.selection.select(activeNode);\n                                    editor.selection.setContent(transport.responseText);\n                                } else if (this.bMark) {\n                                    wysiwyg.activeEditor().selection.moveToBookmark(this.bMark);\n                                }\n                            }\n\n                            if (!activeNode) {\n                                this.updateContent(transport.responseText);\n                            }\n                        } catch (e) {\n                            alert({\n                                content: e.message\n                            });\n                        }\n                    }.bind(this)\n                });\n            }\n        },\n\n        /**\n         * @param {Object} content\n         */\n        updateContent: function (content) {\n            var textarea;\n\n            if (this.wysiwygExists()) {\n                wysiwyg.insertContent(content, false);\n            } else {\n                textarea = document.getElementById(this.widgetTargetId);\n                updateElementAtCursor(textarea, content);\n                varienGlobalEvents.fireEvent('tinymceChange');\n                jQuery(textarea).change();\n            }\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        wysiwygExists: function () {\n            return typeof wysiwyg != 'undefined' && wysiwyg.get(this.widgetTargetId);\n        },\n\n        /**\n         * @return {null|wysiwyg.Editor|*}\n         */\n        getWysiwyg: function () {\n            return wysiwyg.activeEditor();\n        },\n\n        /**\n         * @return {*|Element}\n         */\n        getWysiwygNode: function () {\n            return widgetTools.getActiveSelectedNode() || wysiwyg.activeEditor().selection.getNode();\n        }\n    };\n\n    WysiwygWidget.chooser = Class.create();\n    WysiwygWidget.chooser.prototype = {\n\n        // HTML element A, on which click event fired when choose a selection\n        chooserId: null,\n\n        // Source URL for Ajax requests\n        chooserUrl: null,\n\n        // Chooser config\n        config: null,\n\n        // Chooser dialog window\n        dialogWindow: null,\n\n        // Chooser content for dialog window\n        dialogContent: null,\n\n        overlayShowEffectOptions: null,\n        overlayHideEffectOptions: null,\n\n        /**\n         * @param {*} chooserId\n         * @param {*} chooserUrl\n         * @param {*} config\n         */\n        initialize: function (chooserId, chooserUrl, config) {\n            this.chooserId = chooserId;\n            this.chooserUrl = chooserUrl;\n            this.config = config;\n        },\n\n        /**\n         * @return {String}\n         */\n        getResponseContainerId: function () {\n            return 'responseCnt' + this.chooserId;\n        },\n\n        /**\n         * @return {jQuery|*|HTMLElement}\n         */\n        getChooserControl: function () {\n            return $(this.chooserId + 'control');\n        },\n\n        /**\n         * @return {jQuery|*|HTMLElement}\n         */\n        getElement: function () {\n            return $(this.chooserId + 'value');\n        },\n\n        /**\n         * @return {jQuery|*|HTMLElement}\n         */\n        getElementLabel: function () {\n            return $(this.chooserId + 'label');\n        },\n\n        /**\n         * Open.\n         */\n        open: function () {\n            $(this.getResponseContainerId()).show();\n        },\n\n        /**\n         * Close.\n         */\n        close: function () {\n            $(this.getResponseContainerId()).hide();\n            this.closeDialogWindow();\n        },\n\n        /**\n         * Choose.\n         */\n        choose: function () {\n            // Open dialog window with previously loaded dialog content\n            var responseContainerId;\n\n            if (this.dialogContent) {\n                this.openDialogWindow(this.dialogContent);\n\n                return;\n            }\n            // Show or hide chooser content if it was already loaded\n            responseContainerId = this.getResponseContainerId();\n\n            // Otherwise load content from server\n            new Ajax.Request(this.chooserUrl, {\n                parameters: {\n                    'element_value': this.getElementValue(),\n                    'element_label': this.getElementLabelText()\n                },\n\n                /**\n                 * On success.\n                 */\n                onSuccess: function (transport) {\n                    try {\n                        widgetTools.onAjaxSuccess(transport);\n                        this.dialogContent = widgetTools.getDivHtml(responseContainerId, transport.responseText);\n                        this.openDialogWindow(this.dialogContent);\n                    } catch (e) {\n                        alert({\n                            content: e.message\n                        });\n                    }\n                }.bind(this)\n            });\n        },\n\n        /**\n         * Open dialog winodw.\n         *\n         * @param {*} content\n         */\n        openDialogWindow: function (content) {\n            this.dialogWindow = jQuery('<div/>').modal({\n                title: this.config.buttons.open,\n                type: 'slide',\n                buttons: [],\n\n                /**\n                 * Opened.\n                 */\n                opened: function () {\n                    jQuery(this).addClass('magento-message');\n                },\n\n                /**\n                 * @param {jQuery.Event} e\n                 * @param {Object} modal\n                 */\n                closed: function (e, modal) {\n                    modal.modal.remove();\n                    this.dialogWindow = null;\n                }\n            });\n\n            this.dialogWindow.modal('openModal').append(content);\n        },\n\n        /**\n         * Close dialog window.\n         */\n        closeDialogWindow: function () {\n            this.dialogWindow.modal('closeModal').remove();\n        },\n\n        /**\n         * @return {*|Number}\n         */\n        getElementValue: function () {\n            return this.getElement().value;\n        },\n\n        /**\n         * @return {String}\n         */\n        getElementLabelText: function () {\n            return this.getElementLabel().innerHTML;\n        },\n\n        /**\n         * @param {*} value\n         */\n        setElementValue: function (value) {\n            this.getElement().value = value;\n        },\n\n        /**\n         * @param {*} value\n         */\n        setElementLabel: function (value) {\n            this.getElementLabel().innerHTML = value;\n        }\n    };\n\n    window.WysiwygWidget = WysiwygWidget;\n    window.widgetTools = widgetTools;\n});\n","mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global popups, tinyMceEditors, MediabrowserUtility, Base64 */\n/* eslint-disable strict */\ndefine([\n    'jquery',\n    'underscore',\n    'tinymce4',\n    'mage/adminhtml/events',\n    'mage/adminhtml/wysiwyg/events',\n    'mage/translate',\n    'prototype',\n    'jquery/ui'\n], function (jQuery, _, tinyMCE4, varienGlobalEvents, wysiwygEvents) {\n    'use strict';\n\n    var tinyMce4Wysiwyg = Class.create();\n\n    tinyMce4Wysiwyg.prototype = {\n        mediaBrowserOpener: null,\n        mediaBrowserTargetElementId: null,\n        magentoVariablesPlugin: null,\n        mode: 'exact',\n\n        /**\n         * @param {*} htmlId\n         * @param {Object} config\n         */\n        initialize: function (htmlId, config) {\n            this.id = htmlId;\n            this.config = config;\n\n            _.bindAll(\n                this,\n                'beforeSetContent',\n                'saveContent',\n                'onChangeContent',\n                'openFileBrowser',\n                'updateTextArea',\n                'onUndo',\n                'removeEvents'\n            );\n\n            varienGlobalEvents.attachEventHandler('tinymceChange', this.onChangeContent);\n            varienGlobalEvents.attachEventHandler('tinymceBeforeSetContent', this.beforeSetContent);\n            varienGlobalEvents.attachEventHandler('tinymceSetContent', this.updateTextArea);\n            varienGlobalEvents.attachEventHandler('tinymceSaveContent', this.saveContent);\n            varienGlobalEvents.attachEventHandler('tinymceUndo', this.onUndo);\n\n            if (typeof tinyMceEditors === 'undefined') {\n                window.tinyMceEditors = $H({});\n            }\n\n            tinyMceEditors.set(this.id, this);\n        },\n\n        /**\n         * Ensures the undo operation works properly\n         */\n        onUndo: function () {\n            this.addContentEditableAttributeBackToNonEditableNodes();\n        },\n\n        /**\n         * Setup TinyMCE4 editor\n         */\n        setup: function (mode) {\n            var deferreds = [],\n                settings,\n                self = this;\n\n            this.turnOff();\n\n            if (this.config.plugins) {\n                this.config.plugins.forEach(function (plugin) {\n                    var deferred;\n\n                    self.addPluginToToolbar(plugin.name, '|');\n\n                    if (!plugin.src) {\n                        return;\n                    }\n\n                    deferred = jQuery.Deferred();\n                    deferreds.push(deferred);\n\n                    require([plugin.src], function (factoryFn) {\n                        if (typeof factoryFn === 'function') {\n                            factoryFn(plugin.options);\n                        }\n\n                        tinyMCE4.PluginManager.load(plugin.name, plugin.src);\n                        deferred.resolve();\n                    });\n                });\n            }\n\n            if (jQuery.isReady) {\n                tinyMCE4.dom.Event.domLoaded = true;\n            }\n\n            settings = this.getSettings();\n\n            if (mode === 'inline') {\n                settings.inline = true;\n\n                if (!isNaN(settings.toolbarZIndex)) {\n                    tinyMCE4.ui.FloatPanel.zIndex = settings.toolbarZIndex;\n                }\n\n                this.removeEvents(self.id);\n            }\n\n            jQuery.when.apply(jQuery, deferreds).done(function () {\n                tinyMCE4.init(settings);\n                this.getPluginButtons().hide();\n                this.eventBus.attachEventHandler('open_browser_callback', tinyMceEditors.get(self.id).openFileBrowser);\n            }.bind(this));\n        },\n\n        /**\n         * Remove events from instance.\n         *\n         * @param {String} wysiwygId\n         */\n        removeEvents: function (wysiwygId) {\n            var editor;\n\n            if (typeof tinyMceEditors !== 'undefined' && tinyMceEditors.get(wysiwygId)) {\n                editor = tinyMceEditors.get(wysiwygId);\n                varienGlobalEvents.removeEventHandler('tinymceChange', editor.onChangeContent);\n            }\n        },\n\n        /**\n         * Add plugin to the toolbar if not added.\n         *\n         * @param {String} plugin\n         * @param {String} separator\n         */\n        addPluginToToolbar: function (plugin, separator) {\n            var plugins = this.config.tinymce4.plugins.split(' '),\n                toolbar = this.config.tinymce4.toolbar.split(' ');\n\n            if (plugins.indexOf(plugin) === -1) {\n                plugins.push(plugin);\n            }\n\n            if (toolbar.indexOf(plugin) === -1) {\n                toolbar.push(separator || '', plugin);\n            }\n\n            this.config.tinymce4.plugins = plugins.join(' ');\n            this.config.tinymce4.toolbar = toolbar.join(' ');\n        },\n\n        /**\n         * Set the status of the toolbar to disabled or enabled (true for enabled, false for disabled)\n         * @param {Boolean} enabled\n         */\n        setToolbarStatus: function (enabled) {\n            var controlIds = this.get(this.getId()).theme.panel.rootControl.controlIdLookup;\n\n            _.each(controlIds, function (controlId) {\n                controlId.disabled(!enabled);\n                controlId.canFocus = enabled;\n\n                if (controlId.tooltip) {\n                    controlId.tooltip().state.set('rendered', enabled);\n\n                    if (enabled) {\n                        jQuery(controlId.getEl()).children('button').andSelf().removeAttr('style');\n                    } else {\n                        jQuery(controlId.getEl()).children('button').andSelf().attr('style', 'color: inherit;' +\n                            'background-color: inherit;' +\n                            'border-color: transparent;'\n                        );\n                    }\n                }\n            });\n        },\n\n        /**\n         * @return {Object}\n         */\n        getSettings: function () {\n            var settings,\n                eventBus = this.eventBus;\n\n            settings = {\n                selector: '#' + this.getId(),\n                theme: 'modern',\n                'entity_encoding': 'raw',\n                'convert_urls': false,\n                'content_css': this.config.tinymce4['content_css'],\n                'relative_urls': true,\n                menubar: false,\n                plugins: this.config.tinymce4.plugins,\n                toolbar: this.config.tinymce4.toolbar,\n                adapter: this,\n\n                /**\n                 * @param {Object} editor\n                 */\n                setup: function (editor) {\n                    var onChange;\n\n                    editor.on('BeforeSetContent', function (evt) {\n                        varienGlobalEvents.fireEvent('tinymceBeforeSetContent', evt);\n                        eventBus.fireEvent(wysiwygEvents.beforeSetContent);\n                    });\n\n                    editor.on('SaveContent', function (evt) {\n                        varienGlobalEvents.fireEvent('tinymceSaveContent', evt);\n                        eventBus.fireEvent(wysiwygEvents.afterSave);\n                    });\n\n                    editor.on('paste', function (evt) {\n                        varienGlobalEvents.fireEvent('tinymcePaste', evt);\n                        eventBus.fireEvent(wysiwygEvents.afterPaste);\n                    });\n\n                    editor.on('PostProcess', function (evt) {\n                        varienGlobalEvents.fireEvent('tinymceSaveContent', evt);\n                        eventBus.fireEvent(wysiwygEvents.afterSave);\n                    });\n\n                    editor.on('undo', function (evt) {\n                        varienGlobalEvents.fireEvent('tinymceUndo', evt);\n                        eventBus.fireEvent(wysiwygEvents.afterUndo);\n                    });\n\n                    editor.on('focus', function () {\n                        eventBus.fireEvent(wysiwygEvents.afterFocus);\n                    });\n\n                    editor.on('blur', function () {\n                        eventBus.fireEvent(wysiwygEvents.afterBlur);\n                    });\n\n                    /**\n                     * @param {*} evt\n                     */\n                    onChange = function (evt) {\n                        varienGlobalEvents.fireEvent('tinymceChange', evt);\n                        eventBus.fireEvent(wysiwygEvents.afterChangeContent);\n                    };\n\n                    editor.on('Change', onChange);\n                    editor.on('keyup', onChange);\n\n                    editor.on('ExecCommand', function (cmd) {\n                        varienGlobalEvents.fireEvent('tinymceExecCommand', cmd);\n                    });\n\n                    editor.on('init', function (args) {\n                        varienGlobalEvents.fireEvent('wysiwygEditorInitialized', args.target);\n                        eventBus.fireEvent(wysiwygEvents.afterInitialization);\n                    });\n                }\n            };\n\n            if (this.config.baseStaticUrl && this.config.baseStaticDefaultUrl) {\n                settings['document_base_url'] = this.config.baseStaticUrl;\n            }\n            // Set the document base URL\n            if (this.config['document_base_url']) {\n                settings['document_base_url'] = this.config['document_base_url'];\n            }\n\n            if (this.config['files_browser_window_url']) {\n                /**\n                 * @param {*} fieldName\n                 * @param {*} url\n                 * @param {*} objectType\n                 * @param {*} w\n                 */\n                settings['file_browser_callback'] = function (fieldName, url, objectType, w) {\n                    var payload = {\n                        win: w,\n                        type: objectType,\n                        field: fieldName\n                    };\n\n                    varienGlobalEvents.fireEvent('open_browser_callback', payload);\n                    this.eventBus.fireEvent('open_browser_callback', payload);\n                }.bind(this);\n            }\n\n            if (this.config.width) {\n                settings.width = this.config.width;\n            }\n\n            if (this.config.height) {\n                settings.height = this.config.height;\n            }\n\n            if (this.config.plugins) {\n                settings.magentoPluginsOptions = {};\n\n                _.each(this.config.plugins, function (plugin) {\n                    settings.magentoPluginsOptions[plugin.name] = plugin.options;\n                });\n            }\n\n            if (this.config.settings) {\n                Object.extend(settings, this.config.settings);\n            }\n\n            return settings;\n        },\n\n        /**\n         * @param {String} id\n         */\n        get: function (id) {\n            return tinyMCE4.get(id);\n        },\n\n        /**\n         * @return {String|null}\n         */\n        getId: function () {\n            return this.id || (this.activeEditor() ? this.activeEditor().id : null) || tinyMceEditors.values()[0].id;\n        },\n\n        /**\n         * @return {Object}\n         */\n        activeEditor: function () {\n            return tinyMCE4.activeEditor;\n        },\n\n        /**\n         * Insert content to active editor.\n         *\n         * @param {String} content\n         * @param {Boolean} ui\n         */\n        insertContent: function (content, ui) {\n            this.activeEditor().execCommand('mceInsertContent', typeof ui !== 'undefined' ? ui : false, content);\n        },\n\n        /**\n         * Replace entire contents of wysiwyg with string content parameter\n         *\n         * @param {String} content\n         */\n        setContent: function (content) {\n            this.get(this.getId()).setContent(content);\n        },\n\n        /**\n         * Set caret location in WYSIWYG editor.\n         *\n         * @param {Object} targetElement\n         */\n        setCaretOnElement: function (targetElement) {\n            this.activeEditor().selection.select(targetElement);\n            this.activeEditor().selection.collapse();\n        },\n\n        /**\n         * @param {Object} o\n         */\n        openFileBrowser: function (o) {\n            var typeTitle = this.translate('Select Images'),\n                storeId = this.config['store_id'] !== null ? this.config['store_id'] : 0,\n                frameDialog = jQuery('div.mce-container[role=\"dialog\"]'),\n                wUrl = this.config['files_browser_window_url'] +\n                    'target_element_id/' + this.getId() + '/' +\n                    'store/' + storeId + '/';\n\n            this.mediaBrowserOpener = o.win;\n            this.mediaBrowserTargetElementId = o.field;\n\n            if (typeof o.type !== 'undefined' && o.type !== '') { //eslint-disable-line eqeqeq\n                wUrl = wUrl + 'type/' + o.type + '/';\n            }\n\n            frameDialog.hide();\n            jQuery('#mce-modal-block').hide();\n\n            require(['mage/adminhtml/browser'], function () {\n                MediabrowserUtility.openDialog(wUrl, false, false, typeTitle, {\n                    /**\n                     * Closed.\n                     */\n                    closed: function () {\n                        frameDialog.show();\n                        jQuery('#mce-modal-block').show();\n                    }\n                });\n            });\n        },\n\n        /**\n         * @param {String} string\n         * @return {String}\n         */\n        translate: function (string) {\n            return jQuery.mage.__ ? jQuery.mage.__(string) : string;\n        },\n\n        /**\n         * @return {null}\n         */\n        getMediaBrowserOpener: function () {\n            return this.mediaBrowserOpener;\n        },\n\n        /**\n         * @return {null}\n         */\n        getMediaBrowserTargetElementId: function () {\n            return this.mediaBrowserTargetElementId;\n        },\n\n        /**\n         * @return {jQuery|*|HTMLElement}\n         */\n        getToggleButton: function () {\n            return $('toggle' + this.getId());\n        },\n\n        /**\n         * Get plugins button.\n         */\n        getPluginButtons: function () {\n            return jQuery('#buttons' + this.getId() + ' > button.plugin');\n        },\n\n        /**\n         * @param {*} mode\n         * @return {wysiwygSetup}\n         */\n        turnOn: function (mode) {\n            this.closePopups();\n\n            this.setup(mode);\n\n            this.getPluginButtons().hide();\n\n            tinyMCE4.execCommand('mceAddControl', false, this.getId());\n\n            return this;\n        },\n\n        /**\n         * @param {String} name\n         */\n        closeEditorPopup: function (name) {\n            if (typeof popups !== 'undefined' && popups[name] !== undefined && !popups[name].closed) {\n                popups[name].close();\n            }\n        },\n\n        /**\n         * @return {wysiwygSetup}\n         */\n        turnOff: function () {\n            this.closePopups();\n\n            this.getPluginButtons().show();\n\n            tinyMCE4.execCommand('mceRemoveEditor', false, this.getId());\n\n            return this;\n        },\n\n        /**\n         * Close popups.\n         */\n        closePopups: function () {\n            // close all popups to avoid problems with updating parent content area\n            varienGlobalEvents.fireEvent('wysiwygClosePopups');\n            this.closeEditorPopup('browser_window' + this.getId());\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        toggle: function () {\n            if (!tinyMCE4.get(this.getId())) {\n                this.turnOn();\n\n                return true;\n            }\n            this.turnOff();\n\n            return false;\n        },\n\n        /**\n         * On form validation.\n         */\n        onFormValidation: function () {\n            if (tinyMCE4.get(this.getId())) {\n                $(this.getId()).value = tinyMCE4.get(this.getId()).getContent();\n            }\n        },\n\n        /**\n         * On change content.\n         */\n        onChangeContent: function () {\n            // Add \"changed\" to tab class if it exists\n            var tab;\n\n            this.updateTextArea();\n\n            if (this.config['tab_id']) {\n                tab = $$('a[id$=' + this.config['tab_id'] + ']')[0];\n\n                if ($(tab) != undefined && $(tab).hasClassName('tab-item-link')) { //eslint-disable-line eqeqeq\n                    $(tab).addClassName('changed');\n                }\n            }\n        },\n\n        /**\n         * @param {Object} o\n         */\n        beforeSetContent: function (o) {\n            o.content = this.encodeContent(o.content);\n        },\n\n        /**\n         * @param {Object} o\n         */\n        saveContent: function (o) {\n            o.content = this.decodeContent(o.content);\n        },\n\n        /**\n         * Return the content stored in the WYSIWYG field\n         * @param {String} id\n         * @return {String}\n         */\n        getContent: function (id) {\n            return id ? this.get(id).getContent() : this.get(this.getId()).getContent();\n        },\n\n        /**\n         * @returns {Object}\n         */\n        getAdapterPrototype: function () {\n            return tinyMce4Wysiwyg;\n        },\n\n        /**\n         * Fix range selection placement when typing.  This fixes MAGETWO-84769\n         * @param {Object} editor\n         */\n        fixRangeSelection: function (editor) {\n            var selection = editor.selection,\n                dom = editor.dom,\n                rng = dom.createRng(),\n                doc = editor.getDoc(),\n                markerHtml,\n                marker;\n\n            // Validate the range we're trying to fix is contained within the current editors document\n            if (!selection.getContent().length && jQuery.contains(doc, selection.getRng().startContainer)) {\n                markerHtml = '<span id=\"mce_marker\" data-mce-type=\"bookmark\">\\uFEFF</span>';\n                selection.setContent(markerHtml);\n                marker = dom.get('mce_marker');\n                rng.setStartBefore(marker);\n                rng.setEndBefore(marker);\n                dom.remove(marker);\n                selection.setRng(rng);\n            }\n        },\n\n        /**\n         * Update text area.\n         */\n        updateTextArea: function () {\n            var editor = this.get(this.getId()),\n                content;\n\n            if (!editor || editor.id !== this.activeEditor().id) {\n                return;\n            }\n\n            this.addContentEditableAttributeBackToNonEditableNodes();\n            this.fixRangeSelection(editor);\n\n            content = editor.getContent();\n            content = this.decodeContent(content);\n\n            this.getTextArea().val(content).trigger('change');\n        },\n\n        /**\n         * @return {Object} jQuery textarea element\n         */\n        getTextArea: function () {\n            return jQuery('#' + this.getId());\n        },\n\n        /**\n         * Set the status of the editor and toolbar\n         *\n         * @param {Boolean} enabled\n         */\n        setEnabledStatus: function (enabled) {\n            if (this.activeEditor()) {\n                this.activeEditor().getBody().setAttribute('contenteditable', enabled);\n                this.activeEditor().readonly = !enabled;\n                this.setToolbarStatus(enabled);\n            }\n\n            if (enabled) {\n                this.getTextArea().removeProp('disabled');\n            } else {\n                this.getTextArea().prop('disabled', 'disabled');\n            }\n        },\n\n        /**\n         * Retrieve directives URL with substituted directive value.\n         *\n         * @param {String} directive\n         */\n        makeDirectiveUrl: function (directive) {\n            return this.config['directives_url']\n                .replace(/directive/, 'directive/___directive/' + directive)\n                .replace(/\\/$/, '');\n        },\n\n        /**\n         * Convert {{directive}} style attributes syntax to absolute URLs\n         * @param {Object} content\n         * @return {*}\n         */\n        encodeDirectives: function (content) {\n            // collect all HTML tags with attributes that contain directives\n            return content.gsub(/<([a-z0-9\\-\\_]+[^>]+?)([a-z0-9\\-\\_]+=\"[^\"]*?\\{\\{.+?\\}\\}.*?\".*?)>/i, function (match) {\n                var attributesString = match[2],\n                    decodedDirectiveString;\n\n                // process tag attributes string\n                attributesString = attributesString.gsub(/([a-z0-9\\-\\_]+)=\"(.*?)(\\{\\{.+?\\}\\})(.*?)\"/i, function (m) {\n                    decodedDirectiveString = encodeURIComponent(Base64.mageEncode(m[3].replace(/&quot;/g, '\"')));\n\n                    return m[1] + '=\"' + m[2] + this.makeDirectiveUrl(decodedDirectiveString) + m[4] + '\"';\n                }.bind(this));\n\n                return '<' + match[1] + attributesString + '>';\n            }.bind(this));\n        },\n\n        /**\n         * Convert absolute URLs to {{directive}} style attributes syntax\n         * @param {Object} content\n         * @return {*}\n         */\n        decodeDirectives: function (content) {\n            var directiveUrl = this.makeDirectiveUrl('%directive%').split('?')[0], // remove query string from directive\n                // escape special chars in directives url to use in regular expression\n                regexEscapedDirectiveUrl = directiveUrl.replace(/([$^.?*!+:=()\\[\\]{}|\\\\])/g, '\\\\$1'),\n                regexDirectiveUrl = regexEscapedDirectiveUrl\n                    .replace(\n                        '%directive%',\n                        '([a-zA-Z0-9,_-]+(?:%2[A-Z]|)+\\/?)(?:(?!\").)*'\n                    ) + '/?(\\\\\\\\?[^\"]*)?', // allow optional query string\n                reg = new RegExp(regexDirectiveUrl);\n\n            return content.gsub(reg, function (match) {\n                return Base64.mageDecode(decodeURIComponent(match[1]).replace(/\\/$/, '')).replace(/\"/g, '&quot;');\n            });\n        },\n\n        /**\n         * @param {Object} attributes\n         * @return {Object}\n         */\n        parseAttributesString: function (attributes) {\n            var result = {};\n\n            // Decode &quot; entity, as regex below does not support encoded quote\n            attributes = attributes.replace(/&quot;/g, '\"');\n\n            attributes.gsub(\n                /(\\w+)(?:\\s*=\\s*(?:(?:\"((?:\\\\.|[^\"])*)\")|(?:'((?:\\\\.|[^'])*)')|([^>\\s]+)))?/,\n                function (match) {\n                    result[match[1]] = match[2];\n                }\n            );\n\n            return result;\n        },\n\n        /**\n         * @param {Object} content\n         * @return {*}\n         */\n        decodeContent: function (content) {\n            if (this.config['add_directives']) {\n                content = this.decodeDirectives(content);\n            }\n\n            content = varienGlobalEvents.fireEventReducer('wysiwygDecodeContent', content);\n\n            return content;\n        },\n\n        /**\n         * @param {Object} content\n         * @return {*}\n         */\n        encodeContent: function (content) {\n            if (this.config['add_directives']) {\n                content = this.encodeDirectives(content);\n            }\n\n            content = varienGlobalEvents.fireEventReducer('wysiwygEncodeContent', content);\n\n            return content;\n        },\n\n        /**\n         * Reinstate contenteditable attributes on .mceNonEditable nodes\n         */\n        addContentEditableAttributeBackToNonEditableNodes: function () {\n            jQuery('.mceNonEditable', this.activeEditor().getDoc()).attr('contenteditable', false);\n        }\n    };\n\n    return tinyMce4Wysiwyg.prototype;\n});\n","mage/adminhtml/wysiwyg/tiny_mce/setup.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable strict */\ndefine([\n    'jquery',\n    'underscore',\n    'wysiwygAdapter',\n    'module',\n    'mage/translate',\n    'prototype',\n    'mage/adminhtml/events',\n    'mage/adminhtml/browser'\n], function (jQuery, _, wysiwygAdapter, module) {\n    var baseConfig = module.config().config || {},\n        wysiwygSetup = Class.create({\n        wysiwygInstance: null\n    });\n\n    wysiwygSetup.prototype = {\n\n        /**\n         * @param {*} htmlId\n         * @param {Object} config\n         */\n        initialize: function (htmlId, config) {\n            var WysiwygInstancePrototype = new wysiwygAdapter.getAdapterPrototype();\n\n            _.bindAll(this, 'openFileBrowser');\n\n            config = _.extend({}, baseConfig, config || {});\n            this.wysiwygInstance = new WysiwygInstancePrototype(htmlId, config);\n            this.wysiwygInstance.eventBus = this.eventBus = new window.varienEvents();\n        },\n\n        /**\n         * @param {*} mode\n         */\n        setup: function (mode) {\n            this.wysiwygInstance.setup(mode);\n        },\n\n        /**\n         * @param {Object} o\n         */\n        openFileBrowser: function (o) {\n            this.wysiwygInstance.openFileBrowser(o);\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        toggle: function () {\n            return this.wysiwygInstance.toggle();\n        },\n\n        /**\n         * On form validation.\n         */\n        onFormValidation: function () {\n            this.wysiwygInstance.onFormValidation();\n        },\n\n        /**\n         * Encodes the content so it can be inserted into the wysiwyg\n         * @param {String} content - The content to be encoded\n         *\n         * @returns {*} - The encoded content\n         */\n        updateContent: function (content) {\n            return this.wysiwygInstance.encodeContent(content);\n        }\n\n    };\n    window.wysiwygSetup = wysiwygSetup;\n\n    return wysiwygSetup;\n});\n","mage/adminhtml/wysiwyg/tiny_mce/html5-schema.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    /* eslint-disable max-len */\n\n    var schema = {\n        blockContent: [\n            'address', 'article', 'aside', 'blockquote', 'details', 'dialog', 'div', 'dl', 'fieldset',\n            'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr',\n            'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul'\n        ],\n        phrasingContent: [\n            '#comment', '#text', 'a', 'abbr', 'audio', 'b', 'bdi', 'bdo', 'br', 'button', 'canvas',\n            'cite','code', 'command', 'datalist', 'del', 'dfn', 'em', 'embed', 'i', 'iframe', 'img',\n            'input', 'ins', 'kbd', 'keygen', 'label', 'map', 'mark', 'meter', 'noscript', 'object',\n            'output', 'picture', 'progress', 'q', 'ruby', 's', 'samp', 'script', 'select', 'small',\n            'span', 'strong', 'sub', 'sup', 'textarea', 'time', 'u', 'var', 'video', 'wbr'\n        ],\n        blockElements: [\n            'address', 'article', 'aside', 'blockquote', 'caption', 'center', 'datalist', 'dd', 'dir', 'div',\n            'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n            'header', 'hgroup', 'hr', 'isindex', 'li', 'menu', 'nav', 'noscript', 'ol', 'optgroup', 'option',\n            'p', 'pre', 'section', 'select', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'ul'\n        ],\n        boolAttrs: [\n            'autoplay', 'checked', 'compact', 'controls', 'declare', 'defer', 'disabled', 'ismap', 'loop',\n            'multiple', 'nohref', 'noresize', 'noshade', 'nowrap', 'readonly', 'selected'\n        ],\n        shortEnded: [\n            'area', 'base', 'basefont', 'br', 'col', 'embed', 'frame', 'hr', 'img', 'input', 'isindex',\n            'link', 'meta', 'param', 'source', 'track', 'wbr'\n        ],\n        whiteSpace: [\n            'audio', 'iframe', 'noscript', 'object', 'pre', 'script', 'style', 'textarea', 'video'\n        ],\n        selfClosing: [\n            'colgroup', 'dd', 'dt', 'li', 'option', 'p', 'td', 'tfoot', 'th', 'thead', 'tr'\n        ]\n    };\n\n    schema.flowContent = schema.blockContent.concat(schema.phrasingContent, ['style']);\n    schema.nonEmpty = ['td', 'th', 'iframe', 'video', 'audio', 'object', 'script', 'i', 'em', 'span'].concat(schema.shortEnded);\n\n    _.extend(schema, (function (phrasingContent, flowContent) {\n        var validElements   = [],\n            validChildren   = [],\n            compiled        = {},\n            globalAttrs,\n            rawData;\n\n        globalAttrs = [\n            'id', 'dir', 'lang', 'class', 'style', 'title', 'hidden', 'onclick', 'onkeyup',\n            'tabindex', 'dropzone', 'accesskey', 'draggable', 'translate', 'onmouseup',\n            'onkeydown', 'spellcheck', 'ondblclick', 'onmouseout', 'onkeypress', 'contextmenu',\n            'onmousedown', 'onmouseover', 'onmousemove', 'contenteditable'\n        ];\n\n        rawData = [\n            ['html', 'manifest', 'head body'],\n            ['head', '', 'base command link meta noscript script style title'],\n            ['title hr noscript br'],\n            ['base', 'href target'],\n            ['link', 'href rel media hreflang type sizes hreflang'],\n            ['meta', 'name http-equiv content charset'],\n            ['style', 'media type scoped'],\n            ['script', 'src async defer type charset'],\n            ['body', 'onafterprint onbeforeprint onbeforeunload onblur onerror onfocus ' +\n                'onhashchange onload onmessage onoffline ononline onpagehide onpageshow ' +\n                'onpopstate onresize onscroll onstorage onunload background bgcolor text link vlink alink', flowContent\n            ],\n            ['caption', '', _.without(flowContent, 'table')],\n            ['address dt dd div', '', flowContent],\n            ['h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn', '', phrasingContent],\n            ['blockquote', 'cite', flowContent],\n            ['ol', 'reversed start type', 'li'],\n            ['ul', 'type compact', 'li'],\n            ['li', 'value type', flowContent],\n            ['dl', '', 'dt dd'],\n            ['a', 'href target rel media hreflang type charset name rev shape coords download', phrasingContent],\n            ['q', 'cite', phrasingContent],\n            ['ins del', 'cite datetime', flowContent],\n            ['img', 'src sizes srcset alt usemap ismap width height name longdesc align border hspace vspace'],\n            ['iframe', 'src name width height longdesc frameborder marginwidth marginheight scrolling align sandbox seamless allowfullscreen', flowContent],\n            ['embed', 'src type width height'],\n            ['object', 'data type typemustmatch name usemap form width height declare classid code codebase codetype archive standby align border hspace vspace', flowContent.concat(['param'])],\n            ['param', 'name value valuetype type'],\n            ['map', 'name', flowContent.concat(['area'])],\n            ['area', 'alt coords shape href target rel media hreflang type nohref'],\n            ['table', 'border summary width frame rules cellspacing cellpadding align bgcolor', 'caption colgroup thead tfoot tbody tr col'],\n            ['colgroup', 'span width align char charoff valign', 'col'],\n            ['col', 'span'],\n            ['tbody thead tfoot', 'align char charoff valign', 'tr'],\n            ['tr', 'align char charoff valign bgcolor', 'td th'],\n            ['td', 'colspan rowspan headers abbr axis scope align char charoff valign nowrap bgcolor width height', flowContent],\n            ['th', 'colspan rowspan headers scope abbr axis align char charoff valign nowrap bgcolor width height accept', flowContent],\n            ['form', 'accept-charset action autocomplete enctype method name novalidate target onsubmit onreset', flowContent],\n            ['fieldset', 'disabled form name', flowContent.concat(['legend'])],\n            ['label', 'form for', phrasingContent],\n            ['input', 'accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate ' +\n                'formtarget height list max maxlength min multiple name pattern readonly required size src step type value width usemap align'\n            ],\n            ['button', 'disabled form formaction formenctype formmethod formnovalidate formtarget name type value', phrasingContent],\n            ['select', 'disabled form multiple name required size onfocus onblur onchange', 'option optgroup'],\n            ['optgroup', 'disabled label', 'option'],\n            ['option', 'disabled label selected value'],\n            ['textarea', 'cols dirname disabled form maxlength name readonly required rows wrap'],\n            ['menu', 'type label', flowContent.concat(['li'])],\n            ['noscript', '', flowContent],\n            ['wbr'],\n            ['ruby', '', phrasingContent.concat(['rt', 'rp'])],\n            ['figcaption', '', flowContent],\n            ['mark rt rp summary bdi', '', phrasingContent],\n            ['canvas', 'width height', flowContent],\n            ['video', 'src crossorigin poster preload autoplay mediagroup loop muted controls width height buffered', flowContent.concat(['track', 'source'])],\n            ['audio', 'src crossorigin preload autoplay mediagroup loop muted controls buffered volume', flowContent.concat(['track', 'source'])],\n            ['picture', '', 'img source'],\n            ['source', 'src srcset type media sizes'],\n            ['track', 'kind src srclang label default'],\n            ['datalist', '', phrasingContent.concat(['option'])],\n            ['article section nav aside header footer', '', flowContent],\n            ['hgroup', '', 'h1 h2 h3 h4 h5 h6'],\n            ['figure', '', flowContent.concat(['figcaption'])],\n            ['time', 'datetime', phrasingContent],\n            ['dialog', 'open', flowContent],\n            ['command', 'type label icon disabled checked radiogroup command'],\n            ['output', 'for form name', phrasingContent],\n            ['progress', 'value max', phrasingContent],\n            ['meter', 'value min max low high optimum', phrasingContent],\n            ['details', 'open', flowContent.concat(['summary'])],\n            ['keygen', 'autofocus challenge disabled form keytype name'],\n            ['script', 'language xml:space'],\n            ['style', 'xml:space'],\n            ['embed', 'align name hspace vspace'],\n            ['br', 'clear'],\n            ['applet', 'codebase archive code object alt name width height align hspace vspace'],\n            ['font basefont', 'size color face'],\n            ['h1 h2 h3 h4 h5 h6 div p legend caption', 'align'],\n            ['ol dl menu dir', 'compact'],\n            ['pre', 'width xml:space'],\n            ['hr', 'align noshade size width'],\n            ['isindex', 'prompt'],\n            ['col', 'width align char charoff valign'],\n            ['input button select textarea', 'autofocus'],\n            ['input textarea', 'placeholder onselect onchange onfocus onblur'],\n            ['link script img', 'crossorigin']\n        ];\n\n        rawData.forEach(function (data) {\n            var nodes       = data[0].split(' '),\n                attributes  = data[1] || [],\n                children    = data[2] || [],\n                ni          = nodes.length,\n                nodeName,\n                schemaData;\n\n            if (typeof attributes === 'string') {\n                attributes = attributes.split(' ');\n            }\n\n            if (typeof children === 'string') {\n                children = children.split(' ');\n            }\n\n            while (ni--) {\n                nodeName    = nodes[ni];\n                schemaData  = compiled[nodeName] || {};\n\n                compiled[nodeName] = {\n                    attributes: _.union(schemaData.attributes, globalAttrs, attributes),\n                    children: _.union(schemaData.children, children)\n                };\n            }\n        });\n\n        ['a', 'dfn', 'form', 'meter', 'progress'].forEach(function (nodeName) {\n            var node = compiled[nodeName];\n\n            node.children = _.without(node.children, nodeName);\n        });\n\n        _.each(compiled, function (node, nodeName) {\n            var filteredAttributes = [];\n\n            _.each(node.attributes, function (attribute) { //eslint-disable-line max-nested-callbacks\n                // Disallowing usage of 'on*' attributes.\n                if (!/^on/.test(attribute)) {\n                    filteredAttributes.push(attribute);\n                }\n            });\n\n            node.attributes = filteredAttributes;\n\n            validElements.push(nodeName + '[' + node.attributes.join('|') + ']');\n            validChildren.push(nodeName + '[' + node.children.join('|') + ']');\n        });\n\n        return {\n            nodes: compiled,\n            validElements: validElements,\n            validChildren: validChildren\n        };\n    })(schema.phrasingContent, schema.flowContent));\n\n    return schema;\n});\n","mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global tinymce, widgetTools, jQuery, Base64 */\n/* eslint-disable strict */\ndefine([\n    'wysiwygAdapter',\n    'mage/adminhtml/events',\n    'mage/adminhtml/wysiwyg/widget'\n], function (wysiwyg, varienGlobalEvents) {\n    return function (config) {\n        tinymce.create('tinymce.plugins.magentowidget', {\n\n            /**\n             * @param {tinymce.Editor} editor - Editor instance that the plugin is initialized in.\n             * @param {String} url - Absolute URL to where the plugin is located.\n             */\n            init: function (editor, url) {\n                var self = this;\n\n                this.activePlaceholder = null;\n\n                editor.addCommand('mceMagentowidget', function (img) {\n                    if (self.activePlaceholder) {\n                        img = self.activePlaceholder;\n                    }\n\n                    widgetTools.setActiveSelectedNode(img);\n                    widgetTools.openDialog(\n                        config['window_url'] + 'widget_target_id/' + editor.getElement().id + '/'\n                    );\n                });\n\n                // Register Widget plugin button\n                editor.addButton('magentowidget', {\n                    title: jQuery.mage.__('Insert Widget'),\n                    cmd: 'mceMagentowidget',\n                    image: url + '/img/icon.png',\n\n                    /**\n                     * Fires after the rendering has completed. This ensures the editor will be instantiated\n                     */\n                    onPostRender: function () {\n                        var ctrl = this;\n\n                        // Add a node change handler, selects the button in the UI when a image is selected\n                        editor.on('nodeChange', function (e) {\n                            var placeholder = e.element;\n\n                            if (self.isWidgetPlaceholderSelected(placeholder)) {\n                                widgetTools.setEditMode(true);\n                                ctrl.active(true);\n                            } else {\n                                widgetTools.setEditMode(false);\n                                ctrl.active(false);\n                            }\n                        });\n                    }\n                });\n\n                // Add a widget placeholder image double click callback\n                editor.on('dblClick', function (e) {\n                    var placeholder = e.target;\n\n                    if (self.isWidgetPlaceholderSelected(placeholder)) {\n                        widgetTools.setEditMode(true);\n                        this.execCommand('mceMagentowidget', null);\n                    }\n                });\n\n                /**\n                 * Attach event handler for when wysiwyg editor is about to encode its content\n                 */\n                varienGlobalEvents.attachEventHandler('wysiwygEncodeContent', function (content) {\n                    content = self.encodeWidgets(self.decodeWidgets(content));\n                    content = self.removeDuplicateAncestorWidgetSpanElement(content);\n\n                    return content;\n                });\n\n                /**\n                 * Attach event handler for when wysiwyg editor is about to decode its content\n                 */\n                varienGlobalEvents.attachEventHandler('wysiwygDecodeContent', function (content) {\n                    content = self.decodeWidgets(content);\n\n                    return content;\n                });\n\n                /**\n                 * Attach event handler for when popups associated with wysiwyg are about to be closed\n                 */\n                varienGlobalEvents.attachEventHandler('wysiwygClosePopups', function () {\n                    wysiwyg.closeEditorPopup('widget_window' + wysiwyg.getId());\n                });\n            },\n\n            /**\n             * @param {Object} placeholder - Contains the selected node\n             * @returns {Boolean}\n             */\n            isWidgetPlaceholderSelected: function (placeholder) {\n                var isSelected = false;\n\n                if (placeholder.nodeName &&\n                    (placeholder.nodeName === 'SPAN' || placeholder.nodeName === 'IMG') &&\n                    placeholder.className && placeholder.className.indexOf('magento-widget') !== -1\n                ) {\n                    this.activePlaceholder = placeholder;\n                    isSelected = true;\n                } else {\n                    this.activePlaceholder = null;\n                }\n\n                return isSelected;\n            },\n\n            /**\n             * Convert {{widget}} style syntax to image placeholder HTML\n             * @param {String} content\n             * @return {*}\n             */\n            encodeWidgets: function (content) {\n                return content.gsub(/\\{\\{widget(.*?)\\}\\}/i, function (match) {\n                    var attributes = wysiwyg.parseAttributesString(match[1]),\n                        imageSrc,\n                        imageHtml = '';\n\n                    if (attributes.type) {\n                        attributes.type = attributes.type.replace(/\\\\\\\\/g, '\\\\');\n                        imageSrc = config.placeholders[attributes.type];\n\n                        if (config.types.indexOf(attributes['type_name']) > -1) {\n                            imageHtml += '<span class=\"magento-placeholder magento-widget mceNonEditable\" ' +\n                                'contenteditable=\"false\">';\n                        } else {\n                            imageSrc = config['error_image_url'];\n                            imageHtml += '<span ' +\n                                'class=\"magento-placeholder magento-placeholder-error magento-widget mceNonEditable\" ' +\n                                'contenteditable=\"false\">';\n                        }\n\n                        imageHtml += '<img';\n                        imageHtml += ' id=\"' + Base64.idEncode(match[0]) + '\"';\n                        imageHtml += ' src=\"' + imageSrc + '\"';\n                        imageHtml += ' />';\n\n                        if (attributes['type_name']) {\n                            imageHtml += attributes['type_name'];\n                        }\n\n                        imageHtml += '</span>';\n\n                        return imageHtml;\n                    }\n                });\n            },\n\n            /**\n             * Convert image placeholder HTML to {{widget}} style syntax\n             * @param {String} content\n             * @return {*}\n             */\n            decodeWidgets: function (content) {\n                return content.gsub(\n                    /(<span class=\"[^\"]*magento-widget[^\"]*\"[^>]*>)?<img([^>]+id=\"[^>]+)>(([^>]*)<\\/span>)?/i,\n                    function (match) {\n                        var attributes = wysiwyg.parseAttributesString(match[2]),\n                            widgetCode;\n\n                        if (attributes.id) {\n                            widgetCode = Base64.idDecode(attributes.id);\n\n                            if (widgetCode.indexOf('{{widget') !== -1) {\n                                return widgetCode;\n                            }\n                        }\n\n                        return match[0];\n                    }\n                );\n            },\n\n            /**\n             * Tinymce has strange behavior with html and this removes one of its side-effects\n             * @param {String} content\n             * @return {String}\n             */\n            removeDuplicateAncestorWidgetSpanElement: function (content) {\n                var parser, doc;\n\n                if (!window.DOMParser) {\n                    return content;\n                }\n\n                parser = new DOMParser();\n                doc = parser.parseFromString(content.replace(/&quot;/g, '&amp;quot;'), 'text/html');\n\n                [].forEach.call(doc.querySelectorAll('.magento-widget'), function (widgetEl) {\n                    var widgetChildEl = widgetEl.querySelector('.magento-widget');\n\n                    if (!widgetChildEl) {\n                        return;\n                    }\n\n                    [].forEach.call(widgetEl.childNodes, function (el) {\n                        widgetEl.parentNode.insertBefore(el, widgetEl);\n                    });\n\n                    widgetEl.parentNode.removeChild(widgetEl);\n                });\n\n                return doc.body ? doc.body.innerHTML.replace(/&amp;quot;/g, '&quot;') : content;\n            },\n\n            /**\n             * @return {Object}\n             */\n            getInfo: function () {\n                return {\n                    longname: 'Magento Widget Manager Plugin',\n                    author: 'Magento Core Team',\n                    authorurl: 'http://magentocommerce.com',\n                    infourl: 'http://magentocommerce.com',\n                    version: '1.0'\n                };\n            }\n        });\n\n        // Register plugin\n        tinymce.PluginManager.add('magentowidget', tinymce.plugins.magentowidget);\n    };\n});\n","mage/adminhtml/wysiwyg/tiny_mce/plugins/magentovariable/editor_plugin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global tinymce, MagentovariablePlugin, varienGlobalEvents, Base64 */\n/* eslint-disable strict */\ndefine([\n    'Magento_Variable/js/config-directive-generator',\n    'Magento_Variable/js/custom-directive-generator',\n    'wysiwygAdapter',\n    'jquery'\n], function (configDirectiveGenerator, customDirectiveGenerator, wysiwyg, jQuery) {\n    return function (config) {\n        tinymce.create('tinymce.plugins.magentovariable', {\n\n            /**\n             * Initialize editor plugin.\n             *\n             * @param {tinymce.editor} editor - Editor instance that the plugin is initialized in.\n             * @param {String} url - Absolute URL to where the plugin is located.\n             */\n            init: function (editor, url) {\n                var self = this;\n\n                /**\n                 * Add new command to open variables selector slideout.\n                 */\n                editor.addCommand('openVariablesSlideout', function (commandConfig) {\n                    var selectedElement;\n\n                    if (commandConfig) {\n                        selectedElement = commandConfig.selectedElement;\n                    } else {\n                        selectedElement = tinymce.activeEditor.selection.getNode();\n                    }\n                    MagentovariablePlugin.setEditor(editor);\n                    MagentovariablePlugin.loadChooser(\n                        config.url,\n                        wysiwyg.getId(),\n                        selectedElement\n                    );\n                });\n\n                /**\n                 * Add button to the editor toolbar.\n                 */\n                editor.addButton('magentovariable', {\n                    title: jQuery.mage.__('Insert Variable'),\n                    tooltip: jQuery.mage.__('Insert Variable'),\n                    cmd: 'openVariablesSlideout',\n                    image: url + '/img/icon.png',\n\n                    /**\n                     * Highlight or dismiss Insert Variable button when variable is selected or deselected.\n                     */\n                    onPostRender: function () {\n                        var _this = this,\n\n                        /**\n                         * Toggle active state of Insert Variable button.\n                         *\n                         * @param {Object} e\n                         */\n                        toggleVariableButton = function (e) {\n                            _this.active(false);\n\n                            if (jQuery(e.target).hasClass('magento-variable')) {\n                                _this.active(true);\n                            }\n                        };\n\n                        editor.on('click', toggleVariableButton);\n                        editor.on('change', toggleVariableButton);\n                    }\n                });\n\n                /**\n                 * Double click handler on the editor to handle dbl click on variable placeholder.\n                 */\n                editor.on('dblclick', function (evt) {\n                    if (jQuery(evt.target).hasClass('magento-variable')) {\n                        editor.selection.collapse(false);\n                        editor.execCommand('openVariablesSlideout', {\n                            ui: true,\n                            selectedElement: evt.target\n                        });\n                    }\n                });\n\n                /**\n                 * Attach event handler for when wysiwyg editor is about to encode its content\n                 */\n                varienGlobalEvents.attachEventHandler('wysiwygEncodeContent', function (content) {\n                    content = self.encodeVariables(content);\n\n                    return content;\n                });\n\n                /**\n                 * Attach event handler for when wysiwyg editor is about to decode its content\n                 */\n                varienGlobalEvents.attachEventHandler('wysiwygDecodeContent', function (content) {\n                    content = self.decodeVariables(content);\n\n                    return content;\n                });\n            },\n\n            /**\n             * Encode variables in content\n             *\n             * @param {String} content\n             * @returns {*}\n             */\n            encodeVariables: function (content) {\n                content = content.gsub(/\\{\\{config path=\\\"([^\\\"]+)\\\"\\}\\}/i, function (match) {\n                    var path = match[1],\n                        magentoVariables,\n                        imageHtml;\n\n                    magentoVariables = JSON.parse(config.placeholders);\n\n                    if (magentoVariables[match[1]] && magentoVariables[match[1]]['variable_type'] === 'default') {\n                        imageHtml = '<span id=\"%id\" class=\"magento-variable magento-placeholder mceNonEditable\">' +\n                            '%s</span>';\n                        imageHtml = imageHtml.replace('%s', magentoVariables[match[1]]['variable_name']);\n                    } else {\n                        imageHtml = '<span id=\"%id\" class=\"' +\n                            'magento-variable magento-placeholder magento-placeholder-error ' +\n                            'mceNonEditable' +\n                            '\">' +\n                            'Not found' +\n                            '</span>';\n                    }\n\n                    return imageHtml.replace('%id', Base64.idEncode(path));\n                });\n\n                content = content.gsub(/\\{\\{customVar code=([^\\}\\\"]+)\\}\\}/i, function (match) {\n                    var path = match[1],\n                        magentoVariables,\n                        imageHtml;\n\n                    magentoVariables = JSON.parse(config.placeholders);\n\n                    if (magentoVariables[match[1]] && magentoVariables[match[1]]['variable_type'] === 'custom') {\n                        imageHtml = '<span id=\"%id\" class=\"magento-variable magento-custom-var magento-placeholder ' +\n                            'mceNonEditable\">%s</span>';\n                        imageHtml = imageHtml.replace('%s', magentoVariables[match[1]]['variable_name']);\n                    } else {\n                        imageHtml = '<span id=\"%id\" class=\"' +\n                            'magento-variable magento-custom-var magento-placeholder ' +\n                            'magento-placeholder-error mceNonEditable' +\n                            '\">' +\n                            match[1] +\n                            '</span>';\n                    }\n\n                    return imageHtml.replace('%id', Base64.idEncode(path));\n                });\n\n                return content;\n            },\n\n            /**\n             * Decode variables in content.\n             *\n             * @param {String} content\n             * @returns {String}\n             */\n            decodeVariables: function (content) {\n                var doc = (new DOMParser()).parseFromString(content.replace(/&quot;/g, '&amp;quot;'), 'text/html');\n\n                [].forEach.call(doc.querySelectorAll('span.magento-variable'), function (el) {\n                    var $el = jQuery(el);\n\n                    if ($el.hasClass('magento-custom-var')) {\n                        $el.replaceWith(\n                            customDirectiveGenerator.processConfig(\n                                Base64.idDecode(\n                                    $el.attr('id')\n                                )\n                            )\n                        );\n                    } else {\n                        $el.replaceWith(\n                            configDirectiveGenerator.processConfig(\n                                Base64.idDecode(\n                                    $el.attr('id')\n                                )\n                            )\n                        );\n                    }\n                });\n\n                return doc.body ? doc.body.innerHTML.replace(/&amp;quot;/g, '&quot;') : content;\n            },\n\n            /**\n             * @return {Object}\n             */\n            getInfo: function () {\n                return {\n                    longname: 'Magento Variable Manager Plugin',\n                    author: 'Magento Core Team',\n                    authorurl: 'http://magentocommerce.com',\n                    infourl: 'http://magentocommerce.com',\n                    version: '1.0'\n                };\n            }\n        });\n\n        /**\n         * Register plugin\n         */\n        tinymce.PluginManager.add('magentovariable', tinymce.plugins.magentovariable);\n    };\n});\n","mage/view/composite.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\n/* eslint-disable strict */\ndefine(['jquery'], function ($) {\n    return function () {\n        var renderedChildren = {},\n            children = {};\n\n        return {\n            /**\n             * @param {*} child\n             * @param {String} key\n             */\n            addChild: function (child, key) {\n                children[key] = child;\n            },\n\n            /**\n             * @param {*} root\n             */\n            render: function (root) {\n                $.each(children, function (key, child) {\n                    var childRoot = $('<div>');\n\n                    renderedChildren[key] = child.render(childRoot);\n                    root.append(childRoot);\n                });\n            }\n        };\n    };\n});\n","mage/validation/url.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n\n        /**\n         * Redirects to the url if it is considered safe\n         *\n         * @param {String} path - url to be redirected to\n         */\n        redirect: function (path) {\n            path = this.sanitize(path);\n\n            if (this.validate(path)) {\n                window.location.href = path;\n            }\n        },\n\n        /**\n         * Validates url\n         *\n         * @param {Object} path - url to be validated\n         * @returns {Boolean}\n         */\n        validate: function (path) {\n            var hostname = window.location.hostname;\n\n            if (path.indexOf(hostname) === -1 ||\n                path.indexOf('javascript:') !== -1 ||\n                path.indexOf('vbscript:') !== -1) {\n                return false;\n            }\n\n            return true;\n        },\n\n        /**\n         * Sanitize url, replacing disallowed chars\n         *\n         * @param {String} path - url to be normalized\n         * @returns {String}\n         */\n        sanitize: function (path) {\n            return path.replace('[^-A-Za-z0-9+&@#/%?=~_|!:,.;\\(\\)]', '');\n        }\n    };\n});\n","mage/utils/wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Utility methods used to wrap and extend functions.\n *\n * @example Usage of a 'wrap' method with arguments delegation.\n *      var multiply = function (a, b) {\n *          return a * b;\n *      };\n *\n *      multiply = module.wrap(multiply, function (orig) {\n *          return 'Result is: ' + orig();\n *      });\n *\n *      multiply(2, 2);\n *      => 'Result is: 4'\n *\n * @example Usage of 'wrapSuper' method.\n *      var multiply = function (a, b) {\n *         return a * b;\n *      };\n *\n *      var obj = {\n *          multiply: module.wrapSuper(multiply, function () {\n *              return 'Result is: ' + this._super();\n *          });\n *      };\n *\n *      obj.multiply(2, 2);\n *      => 'Result is: 4'\n */\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    /**\n     * Checks if string has a '_super' substring.\n     */\n    var superReg = /\\b_super\\b/;\n\n    return {\n\n        /**\n         * Wraps target function with a specified wrapper, which will receive\n         * reference to the original function as a first argument.\n         *\n         * @param {Function} target - Function to be wrapped.\n         * @param {Function} wrapper - Wrapper function.\n         * @returns {Function} Wrapper function.\n         */\n        wrap: function (target, wrapper) {\n            if (!_.isFunction(target) || !_.isFunction(wrapper)) {\n                return wrapper;\n            }\n\n            return function () {\n                var args    = _.toArray(arguments),\n                    ctx     = this,\n                    _super;\n\n                /**\n                 * Function that will be passed to the wrapper.\n                 * If no arguments will be passed to it, then the original\n                 * function will be called with an arguments of a wrapper function.\n                 */\n                _super = function () {\n                    var superArgs = arguments.length ? arguments : args.slice(1);\n\n                    return target.apply(ctx, superArgs);\n                };\n\n                args.unshift(_super);\n\n                return wrapper.apply(ctx, args);\n            };\n        },\n\n        /**\n         * Wraps the incoming function to implement support of the '_super' method.\n         *\n         * @param {Function} target - Function to be wrapped.\n         * @param {Function} wrapper - Wrapper function.\n         * @returns {Function} Wrapped function.\n         */\n        wrapSuper: function (target, wrapper) {\n            if (!this.hasSuper(wrapper) || !_.isFunction(target)) {\n                return wrapper;\n            }\n\n            return function () {\n                var _super  = this._super,\n                    args    = arguments,\n                    result;\n\n                /**\n                 * Temporary define '_super' method which\n                 * contains call to the original function.\n                 */\n                this._super = function () {\n                    var superArgs = arguments.length ? arguments : args;\n\n                    return target.apply(this, superArgs);\n                };\n\n                result = wrapper.apply(this, args);\n\n                this._super = _super;\n\n                return result;\n            };\n        },\n\n        /**\n         * Checks wether the incoming method contains calls of the '_super' method.\n         *\n         * @param {Function} fn - Function to be checked.\n         * @returns {Boolean}\n         */\n        hasSuper: function (fn) {\n            return _.isFunction(fn) && superReg.test(fn);\n        },\n\n        /**\n         * Extends target object with provided extenders.\n         * If property in target and extender objects is a function,\n         * then it will be wrapped using 'wrap' method.\n         *\n         * @param {Object} target - Object to be extended.\n         * @param {...Object} extenders - Multiple extenders objects.\n         * @returns {Object} Modified target object.\n         */\n        extend: function (target) {\n            var extenders = _.toArray(arguments).slice(1),\n                iterator = this._extend.bind(this, target);\n\n            extenders.forEach(iterator);\n\n            return target;\n        },\n\n        /**\n         * Same as the 'extend' method, but operates only on one extender object.\n         *\n         * @private\n         * @param {Object} target\n         * @param {Object} extender\n         */\n        _extend: function (target, extender) {\n            _.each(extender, function (value, key) {\n                target[key] = this.wrap(target[key], extender[key]);\n            }, this);\n        }\n    };\n});\n","mage/utils/arrays.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    './strings'\n], function (_, utils) {\n    'use strict';\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 getIndex(item, container) {\n        var index = container.indexOf(item);\n\n        if (~index) {\n            return index;\n        }\n\n        return _.findIndex(container, function (value) {\n            return value && value.name === item;\n        });\n    }\n\n    return {\n        /**\n         * Facade method to remove/add value from/to array\n         * without creating a new instance.\n         *\n         * @param {Array} arr - Array to be modified.\n         * @param {*} value - Value to add/remove.\n         * @param {Boolean} add - Flag that specfies operation.\n         * @returns {Utils} Chainable.\n         */\n        toggle: function (arr, value, add) {\n            return add ?\n                this.add(arr, value) :\n                this.remove(arr, value);\n        },\n\n        /**\n         * Removes the incoming value from array in case\n         * without creating a new instance of it.\n         *\n         * @param {Array} arr - Array to be modified.\n         * @param {*} value - Value to be removed.\n         * @returns {Utils} Chainable.\n         */\n        remove: function (arr, value) {\n            var index = arr.indexOf(value);\n\n            if (~index) {\n                arr.splice(index, 1);\n            }\n\n            return this;\n        },\n\n        /**\n         * Adds the incoming value to array if\n         * it's not alredy present in there.\n         *\n         * @param {Array} arr - Array to be modifed.\n         * @param {...*} arguments - Values to be added.\n         * @returns {Utils} Chainable.\n         */\n        add: function (arr) {\n            var values = _.toArray(arguments).slice(1);\n\n            values.forEach(function (value) {\n                if (!~arr.indexOf(value)) {\n                    arr.push(value);\n                }\n            });\n\n            return this;\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        insert: function (item, container, position) {\n            var currentIndex = getIndex(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 = getIndex(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        /**\n         * @param {Array} elems\n         * @param {Number} offset\n         * @return {Number|*}\n         */\n        formatOffset: function (elems, offset) {\n            if (utils.isEmpty(offset)) {\n                offset = -1;\n            }\n\n            offset = +offset;\n\n            if (offset < 0) {\n                offset += elems.length + 1;\n            }\n\n            return offset;\n        }\n    };\n});\n","mage/utils/compare.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore',\n    'mage/utils/objects'\n], function (_, utils) {\n    'use strict';\n\n    var result = [];\n\n    /**\n     * Checks if all of the provided arrays contains equal values.\n     *\n     * @param {(Boolean|Array)} [keepOrder=false]\n     * @param {Array} target\n     * @returns {Boolean}\n     */\n    function equalArrays(keepOrder, target) {\n        var args = _.toArray(arguments),\n            arrays;\n\n        if (!Array.isArray(keepOrder)) {\n            arrays      = args.slice(2);\n        } else {\n            target      = keepOrder;\n            keepOrder   = false;\n            arrays      = args.slice(1);\n        }\n\n        if (!arrays.length) {\n            return true;\n        }\n\n        return arrays.every(function (array) {\n            if (array === target) {\n                return true;\n            } else if (array.length !== target.length) {\n                return false;\n            } else if (!keepOrder) {\n                return !_.difference(target, array).length;\n            }\n\n            return array.every(function (value, index) {\n                return target.indexOf(value) === index;\n            });\n        });\n    }\n\n    /**\n     * Checks if two values are different.\n     *\n     * @param {*} a - First value.\n     * @param {*} b - Second value.\n     * @returns {Boolean}\n     */\n    function isDifferent(a, b) {\n        var oldIsPrimitive = utils.isPrimitive(a);\n\n        if (Array.isArray(a) && Array.isArray(b)) {\n            return !equalArrays(true, a, b);\n        }\n\n        return oldIsPrimitive ? a !== b : true;\n    }\n\n    /**\n     * @param {String} prefix\n     * @param {String} part\n     */\n    function getPath(prefix, part) {\n        return prefix ? prefix + '.' + part : part;\n    }\n\n    /**\n     * Checks if object has own specified property.\n     *\n     * @param {*} obj - Value to be checked.\n     * @param {String} key - Key of the property.\n     * @returns {Boolean}\n     */\n    function hasOwn(obj, key) {\n        return Object.prototype.hasOwnProperty.call(obj, key);\n    }\n\n    /**\n     * @param {Array} changes\n     */\n    function getContainers(changes) {\n        var containers  = {},\n            indexed     = _.indexBy(changes, 'path');\n\n        _.each(indexed, function (change, name) {\n            var path;\n\n            name.split('.').forEach(function (part) {\n                path = getPath(path, part);\n\n                if (path in indexed) {\n                    return;\n                }\n\n                (containers[path] = containers[path] || []).push(change);\n            });\n        });\n\n        return containers;\n    }\n\n    /**\n     * @param {String} path\n     * @param {String} name\n     * @param {String} type\n     * @param {String} newValue\n     * @param {String} oldValue\n     */\n    function addChange(path, name, type, newValue, oldValue) {\n        var data;\n\n        data = {\n            path: path,\n            name: name,\n            type: type\n        };\n\n        if (type !== 'remove') {\n            data.value = newValue;\n            data.oldValue = oldValue;\n        } else {\n            data.oldValue = newValue;\n        }\n\n        result.push(data);\n    }\n\n    /**\n     * @param {String} ns\n     * @param {String} name\n     * @param {String} type\n     * @param {String} iterator\n     * @param {String} placeholder\n     */\n    function setAll(ns, name, type, iterator, placeholder) {\n        var key;\n\n        if (arguments.length > 4) {\n            type === 'add' ?\n                addChange(ns, name, 'update', iterator, placeholder) :\n                addChange(ns, name, 'update', placeholder, iterator);\n        } else {\n            addChange(ns, name, type, iterator);\n        }\n\n        if (!utils.isObject(iterator)) {\n            return;\n        }\n\n        for (key in iterator) {\n            if (hasOwn(iterator, key)) {\n                setAll(getPath(ns, key), key, type, iterator[key]);\n            }\n        }\n    }\n\n    /*eslint-disable max-depth*/\n    /**\n     * @param {Object} old\n     * @param {Object} current\n     * @param {String} ns\n     * @param {String} name\n     */\n    function compare(old, current, ns, name) {\n        var key,\n            oldIsObj = utils.isObject(old),\n            newIsObj = utils.isObject(current);\n\n        if (oldIsObj && newIsObj) {\n            for (key in old) {\n                if (hasOwn(old, key) && !hasOwn(current, key)) {\n                    setAll(getPath(ns, key), key, 'remove', old[key]);\n                }\n            }\n\n            for (key in current) {\n                if (hasOwn(current, key)) {\n                    hasOwn(old, key) ?\n                        compare(old[key], current[key], getPath(ns, key), key) :\n                        setAll(getPath(ns, key), key, 'add', current[key]);\n                }\n            }\n        } else if (oldIsObj) {\n            setAll(ns, name, 'remove', old, current);\n        } else if (newIsObj) {\n            setAll(ns, name, 'add', current, old);\n        } else if (isDifferent(old, current)) {\n            addChange(ns, name, 'update', current, old);\n        }\n    }\n\n    /*eslint-enable max-depth*/\n\n    return {\n\n        /**\n         *\n         * @returns {Object}\n         */\n        compare: function () {\n            var changes;\n\n            compare.apply(null, arguments);\n\n            changes = result.splice(0);\n\n            return {\n                containers: getContainers(changes),\n                changes: changes,\n                equal: !changes.length\n            };\n        },\n\n        equalArrays: equalArrays\n    };\n});\n","mage/utils/strings.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    var jsonRe = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/;\n\n    return {\n\n        /**\n         * Attempts to convert string to one of the primitive values,\n         * or to parse it as a valid json object.\n         *\n         * @param {String} str - String to be processed.\n         * @returns {*}\n         */\n        castString: function (str) {\n            try {\n                str = str === 'true' ? true :\n                    str === 'false' ? false :\n                        str === 'null' ? null :\n                            +str + '' === str ? +str :\n                                jsonRe.test(str) ? JSON.parse(str) :\n                                    str;\n            } catch (e) {\n            }\n\n            return str;\n        },\n\n        /**\n         * Splits string by separator if it's possible,\n         * otherwise returns the incoming value.\n         *\n         * @param {(String|Array|*)} str - String to split.\n         * @param {String} [separator=' '] - Seperator based on which to split the string.\n         * @returns {Array|*} Splitted string or the incoming value.\n         */\n        stringToArray: function (str, separator) {\n            separator = separator || ' ';\n\n            return typeof str === 'string' ?\n                str.split(separator) :\n                str;\n        },\n\n        /**\n         * Converts the incoming string which consists\n         * of a specified delimiters into a format commonly used in form elements.\n         *\n         * @param {String} name - The incoming string.\n         * @param {String} [separator='.']\n         * @returns {String} Serialized string.\n         *\n         * @example\n         *      utils.serializeName('one.two.three');\n         *      => 'one[two][three]';\n         */\n        serializeName: function (name, separator) {\n            var result;\n\n            separator = separator || '.';\n            name = name.split(separator);\n\n            result = name.shift();\n\n            name.forEach(function (part) {\n                result += '[' + part + ']';\n            });\n\n            return result;\n        },\n\n        /**\n         * Checks wether the incoming value is not empty,\n         * e.g. not 'null' or 'undefined'\n         *\n         * @param {*} value - Value to check.\n         * @returns {Boolean}\n         */\n        isEmpty: function (value) {\n            return value === '' || _.isUndefined(value) || _.isNull(value);\n        },\n\n        /**\n         * Adds 'prefix' to the 'part' value if it was provided.\n         *\n         * @param {String} prefix\n         * @param {String} part\n         * @returns {String}\n         */\n        fullPath: function (prefix, part) {\n            return prefix ? prefix + '.' + part : part;\n        },\n\n        /**\n         * Splits incoming string and returns its' part specified by offset.\n         *\n         * @param {String} parts\n         * @param {Number} [offset]\n         * @param {String} [delimiter=.]\n         * @returns {String}\n         */\n        getPart: function (parts, offset, delimiter) {\n            delimiter = delimiter || '.';\n            parts = parts.split(delimiter);\n            offset = this.formatOffset(parts, offset);\n\n            parts.splice(offset, 1);\n\n            return parts.join(delimiter) || '';\n        },\n\n        /**\n         * Converts nameThroughCamelCase to name-through-minus\n         *\n         * @param {String} string\n         * @returns {String}\n         */\n        camelCaseToMinus: function camelCaseToMinus(string) {\n            return ('' + string)\n                .split('')\n                .map(function (symbol, index) {\n                    return index ?\n                        symbol.toUpperCase() === symbol ?\n                        '-' + symbol.toLowerCase() :\n                            symbol :\n                        symbol.toLowerCase();\n                })\n                .join('');\n        },\n\n        /**\n         * Converts name-through-minus to nameThroughCamelCase\n         *\n         * @param {String} string\n         * @returns {String}\n         */\n        minusToCamelCase: function minusToCamelCase(string) {\n            return ('' + string)\n                .split('-')\n                .map(function (part, index) {\n                    return index ? part.charAt(0).toUpperCase() + part.slice(1) : part;\n                })\n                .join('');\n        }\n    };\n});\n","mage/utils/main.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 utils = {},\n        _ = require('underscore');\n\n    return _.extend(\n        utils,\n        require('./arrays'),\n        require('./compare'),\n        require('./misc'),\n        require('./objects'),\n        require('./strings'),\n        require('./template')\n    );\n});\n","mage/utils/template.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable no-shadow */\n\ndefine([\n    'jquery',\n    'underscore',\n    'mage/utils/objects',\n    'mage/utils/strings'\n], function ($, _, utils, stringUtils) {\n    'use strict';\n\n    var tmplSettings = _.templateSettings,\n        interpolate = /\\$\\{([\\s\\S]+?)\\}/g,\n        opener = '${',\n        template,\n        hasStringTmpls;\n\n    /**\n     * Identifies whether ES6 templates are supported.\n     */\n    hasStringTmpls = (function () {\n        var testString = 'var foo = \"bar\"; return `${ foo }` === foo';\n\n        try {\n            return Function(testString)();\n        } catch (e) {\n            return false;\n        }\n    })();\n\n    if (hasStringTmpls) {\n\n        /*eslint-disable no-unused-vars, no-eval*/\n        /**\n         * Evaluates template string using ES6 templates.\n         *\n         * @param {String} tmpl - Template string.\n         * @param {Object} $ - Data object used in a template.\n         * @returns {String} Compiled template.\n         */\n        template = function (tmpl, $) {\n            return eval('`' + tmpl + '`');\n        };\n\n        /*eslint-enable no-unused-vars, no-eval*/\n    } else {\n\n        /**\n         * Fallback function used when ES6 templates are not supported.\n         * Uses underscore templates renderer.\n         *\n         * @param {String} tmpl - Template string.\n         * @param {Object} data - Data object used in a template.\n         * @returns {String} Compiled template.\n         */\n        template = function (tmpl, data) {\n            var cached = tmplSettings.interpolate;\n\n            tmplSettings.interpolate = interpolate;\n\n            tmpl = _.template(tmpl, {\n                variable: '$'\n            })(data);\n\n            tmplSettings.interpolate = cached;\n\n            return tmpl;\n        };\n    }\n\n    /**\n     * Checks if provided value contains template syntax.\n     *\n     * @param {*} value - Value to be checked.\n     * @returns {Boolean}\n     */\n    function isTemplate(value) {\n        return typeof value === 'string' &&\n            value.indexOf(opener) !== -1 &&\n            // the below pattern almost always indicates an accident which should not cause template evaluation\n            // refuse to evaluate\n            value.indexOf('${{') === -1;\n    }\n\n    /**\n     * Iteratively processes provided string\n     * until no templates syntax will be found.\n     *\n     * @param {String} tmpl - Template string.\n     * @param {Object} data - Data object used in a template.\n     * @param {Boolean} [castString=false] - Flag that indicates whether template\n     *      should be casted after evaluation to a value of another type or\n     *      that it should be leaved as a string.\n     * @returns {*} Compiled template.\n     */\n    function render(tmpl, data, castString) {\n        var last = tmpl;\n\n        while (~tmpl.indexOf(opener)) {\n            tmpl = template(tmpl, data);\n\n            if (tmpl === last) {\n                break;\n            }\n\n            last = tmpl;\n        }\n\n        return castString ?\n            stringUtils.castString(tmpl) :\n            tmpl;\n    }\n\n    return {\n\n        /**\n         * Applies provided data to the template.\n         *\n         * @param {Object|String} tmpl\n         * @param {Object} [data] - Data object to match with template.\n         * @param {Boolean} [castString=false] - Flag that indicates whether template\n         *      should be casted after evaluation to a value of another type or\n         *      that it should be leaved as a string.\n         * @returns {*}\n         *\n         * @example Template defined as a string.\n         *      var source = { foo: 'Random Stuff', bar: 'Some' };\n         *\n         *      utils.template('${ $.bar } ${ $.foo }', source);\n         *      => 'Some Random Stuff';\n         *\n         * @example Template defined as an object.\n         *      var tmpl = {\n         *              key: {'${ $.$data.bar }': '${ $.$data.foo }'},\n         *              foo: 'bar',\n         *              x1: 2, x2: 5,\n         *              delta: '${ $.x2 - $.x1 }',\n         *              baz: 'Upper ${ $.foo.toUpperCase() }'\n         *      };\n         *\n         *      utils.template(tmpl, source);\n         *      => {\n         *          key: {'Some': 'Random Stuff'},\n         *          foo: 'bar',\n         *          x1: 2, x2: 5,\n         *          delta: 3,\n         *          baz: 'Upper BAR'\n         *      };\n         */\n        template: function (tmpl, data, castString, dontClone) {\n            if (typeof tmpl === 'string') {\n                return render(tmpl, data, castString);\n            }\n\n            if (!dontClone) {\n                tmpl = utils.copy(tmpl);\n            }\n\n            tmpl.$data = data || {};\n\n            /**\n             * Template iterator function.\n             */\n            _.each(tmpl, function iterate(value, key, list) {\n                if (key === '$data') {\n                    return;\n                }\n\n                if (isTemplate(key)) {\n                    delete list[key];\n\n                    key = render(key, tmpl);\n                    list[key] = value;\n                }\n\n                if (isTemplate(value)) {\n                    list[key] = render(value, tmpl, castString);\n                } else if ($.isPlainObject(value) || Array.isArray(value)) {\n                    _.each(value, iterate);\n                }\n            });\n\n            delete tmpl.$data;\n\n            return tmpl;\n        }\n    };\n});\n","mage/utils/misc.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'jquery',\n    'FormData'\n], function (_, $) {\n    'use strict';\n\n    var defaultAttributes,\n        ajaxSettings,\n        map;\n\n    defaultAttributes = {\n        method: 'post',\n        enctype: 'multipart/form-data'\n    };\n\n    ajaxSettings = {\n        default: {\n            method: 'POST',\n            cache: false,\n            processData: false,\n            contentType: false\n        },\n        simple: {\n            method: 'POST',\n            dataType: 'json'\n        }\n    };\n\n    map = {\n        'D': 'DDD',\n        'dd': 'DD',\n        'd': 'D',\n        'EEEE': 'dddd',\n        'EEE': 'ddd',\n        'e': 'd',\n        'yyyy': 'YYYY',\n        'yy': 'YY',\n        'y': 'YYYY',\n        'a': 'A'\n    };\n\n    return {\n\n        /**\n         * Generates a unique identifier.\n         *\n         * @param {Number} [size=7] - Length of a resulting identifier.\n         * @returns {String}\n         */\n        uniqueid: function (size) {\n            var code = Math.random() * 25 + 65 | 0,\n                idstr = String.fromCharCode(code);\n\n            size = size || 7;\n\n            while (idstr.length < size) {\n                code = Math.floor(Math.random() * 42 + 48);\n\n                if (code < 58 || code > 64) {\n                    idstr += String.fromCharCode(code);\n                }\n            }\n\n            return idstr;\n        },\n\n        /**\n         * Limits function call.\n         *\n         * @param {Object} owner\n         * @param {String} target\n         * @param {Number} limit\n         */\n        limit: function (owner, target, limit) {\n            var fn = owner[target];\n\n            owner[target] = _.debounce(fn.bind(owner), limit);\n        },\n\n        /**\n         * Converts mage date format to a moment.js format.\n         *\n         * @param {String} mageFormat\n         * @returns {String}\n         */\n        normalizeDate: function (mageFormat) {\n            var result = mageFormat;\n\n            _.each(map, function (moment, mage) {\n                result = result.replace(mage, moment);\n            });\n\n            return result;\n        },\n\n        /**\n         * Puts provided value in range of min and max parameters.\n         *\n         * @param {Number} value - Value to be located.\n         * @param {Number} min - Min value.\n         * @param {Number} max - Max value.\n         * @returns {Number}\n         */\n        inRange: function (value, min, max) {\n            return Math.min(Math.max(min, value), max);\n        },\n\n        /**\n         * Serializes and sends data via POST request.\n         *\n         * @param {Object} options - Options object that consists of\n         *      a 'url' and 'data' properties.\n         * @param {Object} attrs - Attributes that will be added to virtual form.\n         */\n        submit: function (options, attrs) {\n            var form        = document.createElement('form'),\n                data        = this.serialize(options.data),\n                attributes  = _.extend({}, defaultAttributes, attrs || {});\n\n            if (!attributes.action) {\n                attributes.action = options.url;\n            }\n\n            data['form_key'] = window.FORM_KEY;\n\n            _.each(attributes, function (value, name) {\n                form.setAttribute(name, value);\n            });\n\n            data = _.map(\n                data,\n                function (value, name) {\n                    return '<input type=\"hidden\" ' +\n                        'name=\"' + _.escape(name) + '\" ' +\n                        'value=\"' + _.escape(value) + '\"' +\n                        ' />';\n                }\n            ).join('');\n\n            form.insertAdjacentHTML('afterbegin', data);\n            document.body.appendChild(form);\n\n            form.submit();\n        },\n\n        /**\n         * Serializes and sends data via AJAX POST request.\n         *\n         * @param {Object} options - Options object that consists of\n         *      a 'url' and 'data' properties.\n         * @param {Object} config\n         */\n        ajaxSubmit: function (options, config) {\n            var t = new Date().getTime(),\n                settings;\n\n            options.data['form_key'] = window.FORM_KEY;\n            options.data = this.prepareFormData(options.data, config.ajaxSaveType);\n            settings = _.extend({}, ajaxSettings[config.ajaxSaveType], options || {});\n\n            if (!config.ignoreProcessEvents) {\n                $('body').trigger('processStart');\n            }\n\n            return $.ajax(settings)\n                .done(function (data) {\n                    if (config.response) {\n                        data.t = t;\n                        config.response.data(data);\n                        config.response.status(undefined);\n                        config.response.status(!data.error);\n                    }\n                })\n                .fail(function () {\n                    config.response.status(undefined);\n                    config.response.status(false);\n                    config.response.data({\n                        error: true,\n                        messages: 'Something went wrong.',\n                        t: t\n                    });\n                })\n                .always(function () {\n                    if (!config.ignoreProcessEvents) {\n                        $('body').trigger('processStop');\n                    }\n                });\n        },\n\n        /**\n         * Creates FormData object and append this data.\n         *\n         * @param {Object} data\n         * @param {String} type\n         * @returns {FormData}\n         */\n        prepareFormData: function (data, type) {\n            var formData;\n\n            if (type === 'default') {\n                formData = new FormData();\n                _.each(this.serialize(data), function (val, name) {\n                    formData.append(name, val);\n                });\n            } else if (type === 'simple') {\n                formData = this.serialize(data);\n            }\n\n            return formData;\n        },\n\n        /**\n         * Filters data object. Finds properties with suffix\n         * and sets their values to properties with the same name without suffix.\n         *\n         * @param {Object} data - The data object that should be filtered\n         * @param {String} suffix - The string by which data object should be filtered\n         * @param {String} separator - The string that is separator between property and suffix\n         *\n         * @returns {Object} Filtered data object\n         */\n        filterFormData: function (data, suffix, separator) {\n            data = data || {};\n            suffix = suffix || 'prepared-for-send';\n            separator = separator || '-';\n\n            _.each(data, function (value, key) {\n                if (_.isObject(value) && !value.length) {\n                    this.filterFormData(value, suffix, separator);\n                } else if (_.isString(key) && ~key.indexOf(suffix)) {\n                    data[key.split(separator)[0]] = value;\n                    delete data[key];\n                }\n            }, this);\n\n            return data;\n        },\n\n        /**\n         * Replaces symbol codes with their unescaped counterparts.\n         *\n         * @param {String} data\n         *\n         * @returns {String}\n         */\n        unescape: function (data) {\n            var unescaped = _.unescape(data),\n                mapCharacters = {\n                    '&#039;': '\\''\n                };\n\n            _.each(mapCharacters, function (value, key) {\n                unescaped = unescaped.replace(key, value);\n            });\n\n            return unescaped;\n        },\n\n        /**\n         * Converts PHP IntlFormatter format to moment format.\n         *\n         * @param {String} format - PHP format\n         * @returns {String} - moment compatible formatting\n         */\n        convertToMomentFormat: function (format) {\n            var newFormat;\n\n            newFormat = format.replace(/yyyy|yy|y/, 'YYYY'); // replace the year\n            newFormat = newFormat.replace(/dd|d/g, 'DD'); // replace the date\n\n            return newFormat;\n        },\n\n        /**\n         * Get Url Parameters.\n         *\n         * @param {String} url - Url string\n         * @returns {Object}\n         */\n        getUrlParameters: function (url) {\n            var params = {},\n                queries = url.split('?'),\n                temp,\n                i,\n                l;\n\n            if (!queries[1]) {\n                return params;\n            }\n\n            queries = queries[1].split('&');\n\n            for (i = 0, l = queries.length; i < l; i++) {\n                temp = queries[i].split('=');\n\n                if (temp[1]) {\n                    params[temp[0]] = decodeURIComponent(temp[1].replace(/\\+/g, '%20'));\n                } else {\n                    params[temp[0]] = '';\n                }\n            }\n\n            return params;\n        }\n    };\n});\n","mage/utils/objects.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'ko',\n    'jquery',\n    'underscore'\n], function (ko, $, _) {\n    'use strict';\n\n    var primitives = [\n        'undefined',\n        'boolean',\n        'number',\n        'string'\n    ];\n\n    /**\n     * Sets nested property of a specified object.\n     * @private\n     *\n     * @param {Object} parent - Object to look inside for the properties.\n     * @param {Array} path - Splitted path the property.\n     * @param {*} value - Value of the last property in 'path' array.\n     * returns {*} New value for the property.\n     */\n    function setNested(parent, path, value) {\n        var last = path.pop(),\n            len = path.length,\n            pi = 0,\n            part = path[pi];\n\n        for (; pi < len; part = path[++pi]) {\n            if (!_.isObject(parent[part])) {\n                parent[part] = {};\n            }\n\n            parent = parent[part];\n        }\n\n        if (typeof parent[last] === 'function') {\n            parent[last](value);\n        } else {\n            parent[last] = value;\n        }\n\n        return value;\n    }\n\n    /**\n     * Retrieves value of a nested property.\n     * @private\n     *\n     * @param {Object} parent - Object to look inside for the properties.\n     * @param {Array} path - Splitted path the property.\n     * @returns {*} Value of the property.\n     */\n    function getNested(parent, path) {\n        var exists = true,\n            len = path.length,\n            pi = 0;\n\n        for (; pi < len && exists; pi++) {\n            parent = parent[path[pi]];\n\n            if (typeof parent === 'undefined') {\n                exists = false;\n            }\n        }\n\n        if (exists) {\n            if (ko.isObservable(parent)) {\n                parent = parent();\n            }\n\n            return parent;\n        }\n    }\n\n    /**\n     * Removes property from a specified object.\n     * @private\n     *\n     * @param {Object} parent - Object from which to remove property.\n     * @param {Array} path - Splitted path to the property.\n     */\n    function removeNested(parent, path) {\n        var field = path.pop();\n\n        parent = getNested(parent, path);\n\n        if (_.isObject(parent)) {\n            delete parent[field];\n        }\n    }\n\n    return {\n\n        /**\n         * Retrieves or defines objects' property by a composite path.\n         *\n         * @param {Object} data - Container for the properties specified in path.\n         * @param {String} path - Objects' properties divided by dots.\n         * @param {*} [value] - New value for the last property.\n         * @returns {*} Returns value of the last property in chain.\n         *\n         * @example\n         *      utils.nested({}, 'one.two', 3);\n         *      => { one: {two: 3} }\n         */\n        nested: function (data, path, value) {\n            var action = arguments.length > 2 ? setNested : getNested;\n\n            path = path ? path.split('.') : [];\n\n            return action(data, path, value);\n        },\n\n        /**\n         * Removes nested property from an object.\n         *\n         * @param {Object} data - Data source.\n         * @param {String} path - Path to the property e.g. 'one.two.three'\n         */\n        nestedRemove: function (data, path) {\n            path = path.split('.');\n\n            removeNested(data, path);\n        },\n\n        /**\n         * Flattens objects' nested properties.\n         *\n         * @param {Object} data - Object to flatten.\n         * @param {String} [separator='.'] - Objects' keys separator.\n         * @returns {Object} Flattened object.\n         *\n         * @example Example with a default separator.\n         *      utils.flatten({one: { two: { three: 'value'} }});\n         *      => { 'one.two.three': 'value' };\n         *\n         * @example Example with a custom separator.\n         *      utils.flatten({one: { two: { three: 'value'} }}, '=>');\n         *      => {'one=>two=>three': 'value'};\n         */\n        flatten: function (data, separator, parent, result) {\n            separator = separator || '.';\n            result = result || {};\n\n            _.each(data, function (node, name) {\n                if (parent) {\n                    name = parent + separator + name;\n                }\n\n                typeof node === 'object' ?\n                    this.flatten(node, separator, name, result) :\n                    result[name] = node;\n\n            }, this);\n\n            return result;\n        },\n\n        /**\n         * Opposite operation of the 'flatten' method.\n         *\n         * @param {Object} data - Previously flattened object.\n         * @param {String} [separator='.'] - Keys separator.\n         * @returns {Object} Object with nested properties.\n         *\n         * @example Example using custom separator.\n         *      utils.unflatten({'one=>two': 'value'}, '=>');\n         *      => {\n         *          one: { two: 'value' }\n         *      };\n         */\n        unflatten: function (data, separator) {\n            var result = {};\n\n            separator = separator || '.';\n\n            _.each(data, function (value, nodes) {\n                nodes = nodes.split(separator);\n\n                setNested(result, nodes, value);\n            });\n\n            return result;\n        },\n\n        /**\n         * Same operation as 'flatten' method,\n         * but returns objects' keys wrapped in '[]'.\n         *\n         * @param {Object} data - Object that should be serialized.\n         * @returns {Object} Serialized data.\n         *\n         * @example\n         *      utils.serialize({one: { two: { three: 'value'} }});\n         *      => { 'one[two][three]': 'value' }\n         */\n        serialize: function (data) {\n            var result = {};\n\n            data = this.flatten(data);\n\n            _.each(data, function (value, keys) {\n                keys = this.serializeName(keys);\n                value = _.isUndefined(value) ? '' : value;\n\n                result[keys] = value;\n            }, this);\n\n            return result;\n        },\n\n        /**\n         * Performs deep extend of specified objects.\n         *\n         * @returns {Object|Array} Extended object.\n         */\n        extend: function () {\n            var args = _.toArray(arguments);\n\n            args.unshift(true);\n\n            return $.extend.apply($, args);\n        },\n\n        /**\n         * Performs a deep clone of a specified object.\n         *\n         * @param {(Object|Array)} data - Data that should be copied.\n         * @returns {Object|Array} Cloned object.\n         */\n        copy: function (data) {\n            var result = data,\n                isArray = Array.isArray(data),\n                placeholder;\n\n            if (this.isObject(data) || isArray) {\n                placeholder = isArray ? [] : {};\n                result = this.extend(placeholder, data);\n            }\n\n            return result;\n        },\n\n        /**\n         * Performs a deep clone of a specified object.\n         * Doesn't save links to original object.\n         *\n         * @param {*} original - Object to clone\n         * @returns {*}\n         */\n        hardCopy: function (original) {\n            if (original === null || typeof original !== 'object') {\n                return original;\n            }\n\n            return JSON.parse(JSON.stringify(original));\n        },\n\n        /**\n         * Removes specified nested properties from the target object.\n         *\n         * @param {Object} target - Object whose properties should be removed.\n         * @param {(...String|Array|Object)} list - List that specifies properties to be removed.\n         * @returns {Object} Modified object.\n         *\n         * @example Basic usage\n         *      var obj = {a: {b: 2}, c: 'a'};\n         *\n         *      omit(obj, 'a.b');\n         *      => {'a.b': 2};\n         *      obj => {a: {}, c: 'a'};\n         *\n         * @example Various syntaxes that would return same result\n         *      omit(obj, ['a.b', 'c']);\n         *      omit(obj, 'a.b', 'c');\n         *      omit(obj, {'a.b': true, 'c': true});\n         */\n        omit: function (target, list) {\n            var removed = {},\n                ignored = list;\n\n            if (this.isObject(list)) {\n                ignored = [];\n\n                _.each(list, function (value, key) {\n                    if (value) {\n                        ignored.push(key);\n                    }\n                });\n            } else if (_.isString(list)) {\n                ignored = _.toArray(arguments).slice(1);\n            }\n\n            _.each(ignored, function (path) {\n                var value = this.nested(target, path);\n\n                if (!_.isUndefined(value)) {\n                    removed[path] = value;\n\n                    this.nestedRemove(target, path);\n                }\n            }, this);\n\n            return removed;\n        },\n\n        /**\n         * Checks if provided value is a plain object.\n         *\n         * @param {*} value - Value to be checked.\n         * @returns {Boolean}\n         */\n        isObject: function (value) {\n            var objProto = Object.prototype;\n\n            return typeof value == 'object' ?\n            objProto.toString.call(value) === '[object Object]' :\n                false;\n        },\n\n        /**\n         *\n         * @param {*} value\n         * @returns {Boolean}\n         */\n        isPrimitive: function (value) {\n            return value === null || ~primitives.indexOf(typeof value);\n        },\n\n        /**\n         * Iterates over obj props/array elems recursively, applying action to each one\n         *\n         * @param {Object|Array} data - Data to be iterated.\n         * @param {Function} action - Callback to be called with each item as an argument.\n         * @param {Number} [maxDepth=7] - Max recursion depth.\n         */\n        forEachRecursive: function (data, action, maxDepth) {\n            maxDepth = typeof maxDepth === 'number' && !isNaN(maxDepth) ? maxDepth - 1 : 7;\n\n            if (!_.isFunction(action) || _.isFunction(data) || maxDepth < 0) {\n                return;\n            }\n\n            if (!_.isObject(data)) {\n                action(data);\n\n                return;\n            }\n\n            _.each(data, function (value) {\n                this.forEachRecursive(value, action, maxDepth);\n            }, this);\n\n            action(data);\n        },\n\n        /**\n         * Maps obj props/array elems recursively\n         *\n         * @param {Object|Array} data - Data to be iterated.\n         * @param {Function} action - Callback to transform each item.\n         * @param {Number} [maxDepth=7] - Max recursion depth.\n         *\n         * @returns {Object|Array}\n         */\n        mapRecursive: function (data, action, maxDepth) {\n            var newData;\n\n            maxDepth = typeof maxDepth === 'number' && !isNaN(maxDepth) ? maxDepth - 1 : 7;\n\n            if (!_.isFunction(action) || _.isFunction(data) || maxDepth < 0) {\n                return data;\n            }\n\n            if (!_.isObject(data)) {\n                return action(data);\n            }\n\n            if (_.isArray(data)) {\n                newData = _.map(data, function (item) {\n                    return this.mapRecursive(item, action, maxDepth);\n                }, this);\n\n                return action(newData);\n            }\n\n            newData = _.mapObject(data, function (val, key) {\n                if (data.hasOwnProperty(key)) {\n                    return this.mapRecursive(val, action, maxDepth);\n                }\n\n                return val;\n            }, this);\n\n            return action(newData);\n        },\n\n        /**\n         * Removes empty(in common sence) obj props/array elems\n         *\n         * @param {*} data - Data to be cleaned.\n         * @returns {*}\n         */\n        removeEmptyValues: function (data) {\n            if (!_.isObject(data)) {\n                return data;\n            }\n\n            if (_.isArray(data)) {\n                return data.filter(function (item) {\n                    return !this.isEmptyObj(item);\n                }, this);\n            }\n\n            return _.omit(data, this.isEmptyObj.bind(this));\n        },\n\n        /**\n         * Checks that argument of any type is empty in common sence:\n         * empty string, string with spaces only, object without own props, empty array, null or undefined\n         *\n         * @param {*} val - Value to be checked.\n         * @returns {Boolean}\n         */\n        isEmptyObj: function (val) {\n\n            return _.isObject(val) && _.isEmpty(val) ||\n            this.isEmpty(val) ||\n            val && val.trim && this.isEmpty(val.trim());\n        }\n    };\n});\n","mage/backend/notification.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/template',\n    'jquery/ui'\n], function ($, mageTemplate) {\n    'use strict';\n\n    $.widget('mage.notification', {\n        options: {\n            templates: {\n                global: '<div data-role=\"messages\" id=\"messages\">' +\n                    '<div class=\"message <% if (data.error) { %>error<% } %>\"><div><%- data.message %></div></div>' +\n                '</div>',\n                error: '<div data-role=\"messages\" id=\"messages\">' +\n                    '<div class=\"messages\"><div class=\"message message-error error\">' +\n                        '<div data-ui-id=\"messages-message-error\"><%- data.message %></div></div>' +\n                    '</div></div>'\n            }\n        },\n        placeholder: '[data-role=messages]',\n\n        /**\n         * Notification creation\n         * @protected\n         */\n        _create: function () {\n            $(document).on('ajaxComplete ajaxError', $.proxy(this._add, this));\n        },\n\n        /**\n         * Add new message\n         * @protected\n         * @param {Object} event - object\n         * @param {Object} jqXHR - The jQuery XMLHttpRequest object returned by $.ajax()\n         */\n        _add: function (event, jqXHR) {\n            var response;\n\n            try {\n                response = JSON.parse(jqXHR.responseText);\n\n                if (response && response.error && response['html_message']) {\n                    $(this.placeholder).html(response['html_message']);\n                }\n            } catch (e) {}\n        },\n\n        /**\n         * Adds new message.\n         *\n         * @param {Object} data - Data with a message to be displayed.\n         */\n        add: function (data) {\n            var template = data.error ? this.options.templates.error : this.options.templates.global,\n                message = mageTemplate(template, {\n                    data: data\n                }),\n                messageContainer;\n\n            if (typeof data.insertMethod === 'function') {\n                data.insertMethod(message);\n            } else {\n                messageContainer = data.messageContainer || this.placeholder;\n                $(messageContainer).prepend(message);\n            }\n\n            return this;\n        },\n\n        /**\n         * Removes error messages.\n         */\n        clear: function () {\n            $(this.placeholder).html('');\n        }\n    });\n\n    return $.mage.notification;\n});\n","mage/backend/bootstrap.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global FORM_KEY */\ndefine([\n    'jquery',\n    'mage/apply/main',\n    'mage/backend/notification',\n    'Magento_Ui/js/lib/knockout/bootstrap',\n    'mage/mage',\n    'mage/translate'\n], function ($, mage, notification) {\n    'use strict';\n\n    var bootstrap;\n\n    $.ajaxSetup({\n        /*\n         * @type {string}\n         */\n        type: 'POST',\n\n        /**\n         * Ajax before send callback.\n         *\n         * @param {Object} jqXHR - The jQuery XMLHttpRequest object returned by $.ajax()\n         * @param {Object} settings\n         */\n        beforeSend: function (jqXHR, settings) {\n            var formKey = typeof FORM_KEY !== 'undefined' ? FORM_KEY : null;\n\n            if (!settings.url.match(new RegExp('[?&]isAjax=true',''))) {\n                settings.url = settings.url.match(\n                    new RegExp('\\\\?', 'g')) ?\n                    settings.url + '&isAjax=true' :\n                    settings.url + '?isAjax=true';\n            }\n\n            if (!settings.data) {\n                settings.data = {\n                    'form_key': formKey\n                };\n            } else if ($.type(settings.data) === 'string' &&\n                settings.data.indexOf('form_key=') === -1) {\n                settings.data += '&' + $.param({\n                    'form_key': formKey\n                });\n            } else if ($.isPlainObject(settings.data) && !settings.data['form_key']) {\n                settings.data['form_key'] = formKey;\n            }\n        },\n\n        /**\n         * Ajax complete callback.\n         *\n         * @param {Object} jqXHR - The jQuery XMLHttpRequest object returned by $.ajax()\n         */\n        complete: function (jqXHR) {\n            var jsonObject;\n\n            if (jqXHR.readyState === 4) {\n                try {\n                    jsonObject = $.parseJSON(jqXHR.responseText);\n\n                    if (jsonObject.ajaxExpired && jsonObject.ajaxRedirect) { //eslint-disable-line max-depth\n                        window.location.replace(jsonObject.ajaxRedirect);\n                    }\n                } catch (e) {}\n            }\n        },\n\n        /**\n         * Error callback.\n         */\n        error: function () {\n            $('body').notification('clear')\n                .notification('add', {\n                    error: true,\n                    message: $.mage.__(\n                        'A technical problem with the server created an error. ' +\n                        'Try again to continue what you were doing. If the problem persists, try again later.'\n                    ),\n\n                    /**\n                     * @param {String} message\n                     */\n                    insertMethod: function (message) {\n                        var $wrapper = $('<div/>').html(message);\n\n                        $('.page-main-actions').after($wrapper);\n                    }\n                });\n        }\n    });\n\n    /**\n     * Bootstrap application.\n     */\n    bootstrap = function () {\n        /**\n         * Init all components defined via data-mage-init attribute\n         * and subscribe init action on contentUpdated event\n         */\n        mage.apply();\n\n        /*\n         * Initialization of notification widget\n         */\n        notification({}, $('body'));\n    };\n\n    $(bootstrap);\n});\n","mage/backend/validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global BASE_URL, alertAlreadyDisplayed */\n(function (factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'underscore',\n            'Magento_Ui/js/modal/alert',\n            'jquery/ui',\n            'jquery/validate',\n            'mage/translate',\n            'mage/validation'\n        ], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($, _, alert) {\n    'use strict';\n\n    $.extend(true, $.validator.prototype, {\n        /**\n         * Focus invalid fields\n         */\n        focusInvalid: function () {\n            if (this.settings.focusInvalid) {\n                try {\n                    $(this.errorList.length && this.errorList[0].element || [])\n                        .focus()\n                        .trigger('focusin');\n                } catch (e) {\n                    // ignore IE throwing errors when focusing hidden elements\n                }\n            }\n        },\n\n        /**\n         * Elements.\n         */\n        elements: function () {\n            var validator = this,\n                rulesCache = {};\n\n            // select all valid inputs inside the form (no submit or reset buttons)\n            return $(this.currentForm)\n                .find('input, select, textarea')\n                .not(this.settings.forceIgnore)\n                .not(':submit, :reset, :image, [disabled]')\n                .not(this.settings.ignore)\n                .filter(function () {\n                    if (!this.name && validator.settings.debug && window.console) {\n                        console.error('%o has no name assigned', this);\n                    }\n\n                    // select only the first element for each name, and only those with rules specified\n                    if (this.name in rulesCache || !validator.objectLength($(this).rules())) {\n                        return false;\n                    }\n\n                    rulesCache[this.name] = true;\n\n                    return true;\n                });\n        }\n    });\n\n    $.extend($.fn, {\n        /**\n         * ValidationDelegate overridden for those cases where the form is located in another form,\n         *     to avoid not correct working of validate plug-in\n         * @override\n         * @param {String} delegate - selector, if event target matched against this selector,\n         *     then event will be delegated\n         * @param {String} type - event type\n         * @param {Function} handler - event handler\n         * @return {Element}\n         */\n        validateDelegate: function (delegate, type, handler) {\n            return this.on(type, $.proxy(function (event) {\n                var target = $(event.target),\n                    form = target[0].form;\n\n                if (form && $(form).is(this) && $.data(form, 'validator') && target.is(delegate)) {\n                    return handler.apply(target, arguments);\n                }\n            }, this));\n        }\n    });\n\n    $.widget('mage.validation', $.mage.validation, {\n        options: {\n            messagesId: 'messages',\n            forceIgnore: '',\n            ignore: ':disabled, .ignore-validate, .no-display.template, ' +\n                ':disabled input, .ignore-validate input, .no-display.template input, ' +\n                ':disabled select, .ignore-validate select, .no-display.template select, ' +\n                ':disabled textarea, .ignore-validate textarea, .no-display.template textarea',\n            errorElement: 'label',\n            errorUrl: typeof BASE_URL !== 'undefined' ? BASE_URL : null,\n\n            /**\n             * @param {HTMLElement} element\n             */\n            highlight: function (element) {\n                if ($.validator.defaults.highlight && $.isFunction($.validator.defaults.highlight)) {\n                    $.validator.defaults.highlight.apply(this, arguments);\n                }\n                $(element).trigger('highlight.validate');\n            },\n\n            /**\n             * @param {HTMLElement} element\n             */\n            unhighlight: function (element) {\n                if ($.validator.defaults.unhighlight && $.isFunction($.validator.defaults.unhighlight)) {\n                    $.validator.defaults.unhighlight.apply(this, arguments);\n                }\n                $(element).trigger('unhighlight.validate');\n            }\n        },\n\n        /**\n         * Validation creation\n         * @protected\n         */\n        _create: function () {\n            if (!this.options.submitHandler && $.type(this.options.submitHandler) !== 'function') {\n                if (!this.options.frontendOnly && this.options.validationUrl) {\n                    this.options.submitHandler = $.proxy(this._ajaxValidate, this);\n                } else {\n                    this.options.submitHandler = $.proxy(this._submit, this);\n                }\n            }\n            this.element.on('resetElement', function (e) {\n                $(e.target).rules('remove');\n            });\n            this._super('_create');\n        },\n\n        /**\n         * ajax validation\n         * @protected\n         */\n        _ajaxValidate: function () {\n            $.ajax({\n                url: this.options.validationUrl,\n                type: 'POST',\n                dataType: 'json',\n                data: this.element.serialize(),\n                context: $('body'),\n                success: $.proxy(this._onSuccess, this),\n                error: $.proxy(this._onError, this),\n                showLoader: true,\n                dontHide: false\n            });\n        },\n\n        /**\n         * Process ajax success.\n         *\n         * @protected\n         * @param {Object} response\n         */\n        _onSuccess: function (response) {\n            if (!response.error) {\n                this._submit();\n            } else {\n                this._showErrors(response);\n                $(this.element[0]).trigger('afterValidate.error');\n                $('body').trigger('processStop');\n            }\n        },\n\n        /**\n         * Submitting a form.\n         * @private\n         */\n        _submit: function () {\n            $(this.element[0]).trigger('afterValidate.beforeSubmit');\n            this.element[0].submit();\n        },\n\n        /**\n         * Displays errors after backend validation.\n         *\n         * @param {Object} data - Data that came from backend.\n         */\n        _showErrors: function (data) {\n            $('body').notification('clear')\n                .notification('add', {\n                    error: data.error,\n                    message: data.message,\n\n                    /**\n                     * @param {*} message\n                     */\n                    insertMethod: function (message) {\n                        $('.messages:first').html(message);\n                    }\n                });\n        },\n\n        /**\n         * Tries to retrieve element either by id or by inputs' name property.\n         * @param {String} code - String to search by.\n         * @returns {jQuery} jQuery element.\n         */\n        _getByCode: function (code) {\n            var parent = this.element[0],\n                element;\n\n            element = parent.querySelector('#' + code) || parent.querySelector('input[name=' + code + ']');\n\n            return $(element);\n        },\n\n        /**\n         * Process ajax error\n         * @protected\n         */\n        _onError: function () {\n            $(this.element[0]).trigger('afterValidate.error');\n            $('body').trigger('processStop');\n\n            if (this.options.errorUrl) {\n                location.href = this.options.errorUrl;\n            }\n        }\n    });\n\n    _.each({\n        'validate-greater-zero-based-on-option': [\n            function (v, el) {\n                var optionType = $(el)\n                    .closest('.form-list')\n                    .prev('.fieldset-alt')\n                    .find('select.select-product-option-type'),\n                    optionTypeVal = optionType.val();\n\n                v = Number(v) || 0;\n\n                if (optionType && (optionTypeVal == 'checkbox' || optionTypeVal == 'multi') && v <= 0) { //eslint-disable-line\n                    return false;\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter a number greater 0 in this field.')\n        ],\n        'validate-rating': [\n            function () {\n                var ratings = $('#detailed_rating').find('.field-rating'),\n                    noError = true;\n\n                ratings.each(function (index, rating) {\n                    noError = noError && $(rating).find('input:checked').length > 0;\n                });\n\n                return noError;\n            },\n            $.mage.__('Please select one of each ratings above.')\n        ],\n        'validate-downloadable-file': [\n            function (v, element) {\n                var elmParent = $(element).parent(),\n                    linkType = elmParent.find('input[value=\"file\"]'),\n                    newFileContainer;\n\n                if (linkType.is(':checked') && (v === '' || v === '[]')) {\n                    newFileContainer = elmParent.find('.new-file');\n\n                    if (!alertAlreadyDisplayed && (newFileContainer.empty() || newFileContainer.is(':visible'))) {\n                        window.alertAlreadyDisplayed = true;\n                        alert({\n                            content: $.mage.__('There are files that were selected but not uploaded yet. ' +\n                            'Please upload or remove them first')\n                        });\n                    }\n\n                    return false;\n                }\n\n                return true;\n            },\n            'Please upload a file.'\n        ],\n        'validate-downloadable-url': [\n            function (v, element) {\n                var linkType = $(element).parent().find('input[value=\"url\"]');\n\n                if (linkType.is(':checked') && v === '') {\n                    return false;\n                }\n\n                return true;\n            },\n            $.mage.__('Please specify Url.')\n        ]\n    }, function (rule, i) {\n        rule.unshift(i);\n        $.validator.addMethod.apply($.validator, rule);\n    });\n\n    return $.mage.validation;\n}));\n","mage/backend/editablemultiselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\n/* global EditableMultiselect */\n/* eslint-disable strict */\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/alert',\n    'Magento_Ui/js/modal/confirm',\n    'jquery/editableMultiselect/js/jquery.editable',\n    'jquery/editableMultiselect/js/jquery.multiselect'\n], function ($, alert, confirm) {\n    /**\n     * Editable multiselect wrapper for multiselects\n     * This class is defined in global scope ('var' is not needed).\n     *\n     *  @param {Object} settings - settings object.\n     *  @param {String} settings.add_button_caption - caption of the 'Add New Value' button\n     *  @param {String} settings.new_url - URL to which new request has to be submitted\n     *  @param {String} settings.save_url - URL to which save request has to be submitted\n     *  @param {String} settings.delete_url - URL to which delete request has to be submitted\n     *  @param {String} settings.delete_confirm_message - confirmation message that is shown to user during\n     *      delete operation\n     *  @param {String} settings.target_select_id - HTML ID of target select element\n     *  @param {Hash} settings.submit_data - extra parameters to send with new/edit/delete requests\n     *  @param {String} settings.entity_value_name - name of the request parameter that represents select option text\n     *  @param {String} settings.entity_id_name - name of the request parameter that represents select option value\n     *  @param {Boolean} settings.is_entry_editable - flag that shows if user can add/edit/remove data\n     *\n     * @constructor\n     */\n    window.EditableMultiselect = function (settings) {\n\n        this.settings = settings || {};\n        this.addButtonCaption = this.settings['add_button_caption'] || 'Add new value';\n        this.newUrl = this.settings['new_url'];\n        this.saveUrl = this.settings['save_url'];\n        this.deleteUrl = this.settings['delete_url'];\n        this.deleteConfirmMessage = this.settings['delete_confirm_message'];\n        this.targetSelectId = this.settings['target_select_id'];\n        this.submitData = this.settings['submit_data'] || {};\n        this.entityIdName = this.settings['entity_id_name'] || 'entity_id';\n        this.entityValueName = this.settings['entity_value_name'] || 'entity_value';\n        this.isEntityEditable = this.settings['is_entity_editable'] || false;\n\n        /**\n         * Initialize editable multiselect (make it visible in UI)\n         */\n        EditableMultiselect.prototype.init = function () {\n            var self = this,\n                mselectOptions = {\n                    addText: this.addButtonCaption,\n\n                    /**\n                     * @param {*} value\n                     * @param {*} options\n                     */\n                    mselectInputSubmitCallback: function (value, options) {\n                        self.createEntity(value, options);\n                    }\n                },\n                mselectList;\n\n            if (!this.isEntityEditable) {\n                // Override default layout of editable multiselect\n                mselectOptions.layout = '<section class=\"block %mselectListClass%\">' +\n                    '<div class=\"block-content\"><div class=\"%mselectItemsWrapperClass%\">' +\n                    '%items%' +\n                    '</div></div>' +\n                    '<div class=\"%mselectInputContainerClass%\">' +\n                    '<input type=\"text\" class=\"%mselectInputClass%\" title=\"%inputTitle%\"/>' +\n                    '<span class=\"%mselectButtonCancelClass%\" title=\"%cancelText%\"></span>' +\n                    '<span class=\"%mselectButtonSaveClass%\" title=\"Add\"></span>' +\n                    '</div>' +\n                    '</section>';\n            }\n\n            $('#' + this.targetSelectId).multiselect(mselectOptions);\n\n            // Make multiselect editable if needed\n            if (this.isEntityEditable) {\n                this.makeMultiselectEditable();\n\n                // Root element of HTML markup that represents select element in UI\n                mselectList = $('#' + this.targetSelectId).next();\n                this.attachEventsToControls(mselectList);\n            }\n        };\n\n        /**\n         * Attach required event handlers to control elements of editable multiselect\n         *\n         * @param {Object} mselectList\n         */\n        EditableMultiselect.prototype.attachEventsToControls = function (mselectList) {\n            mselectList.on('click.mselect-delete', '.mselect-delete', {\n                container: this\n            }, function (event) {\n                // Pass the clicked button to container\n                event.data.container.deleteEntity({\n                    'delete_button': this\n                });\n            });\n\n            mselectList.on('click.mselect-checked', '.mselect-list-item input', {\n                container: this\n            }, function (event) {\n                var el = $(this),\n                    checkedClassName = 'mselect-checked';\n\n                el[el.is(':checked') ? 'addClass' : 'removeClass'](checkedClassName);\n                event.data.container.makeMultiselectEditable();\n            });\n\n            mselectList.on('click.mselect-edit', '.mselect-edit', {\n                container: this\n            }, function (event) {\n                event.data.container.makeMultiselectEditable();\n                $(this).parent().find('label span').trigger('dblclick');\n            });\n        };\n\n        /**\n         * Make multiselect editable\n         */\n        EditableMultiselect.prototype.makeMultiselectEditable = function () {\n            var entityIdName = this.entityIdName,\n                entityValueName = this.entityValueName,\n                selectList = $('#' + this.targetSelectId).next();\n\n            selectList.find('.mselect-list-item:not(.mselect-list-item-not-editable) label span').editable(this.saveUrl,\n            {\n                type: 'text',\n                submit: '<button class=\"mselect-save\" title=\"Save\" type=\"submit\" />',\n                cancel: '<span class=\"mselect-cancel\" title=\"Cancel\"></span>',\n                event: 'dblclick',\n                placeholder: '',\n\n                /**\n                 * Is checked.\n                 */\n                isChecked: function () {\n                    var that = $(this),\n                        checked;\n\n                    if (!that.closest('.mselect-list-item').hasClass('mselect-disabled')) {\n                        checked = that.parent().find('[type=checkbox]').prop('disabled');\n                        that.parent().find('[type=checkbox]').prop({\n                            disabled: !checked\n                        });\n                    }\n                },\n\n                /**\n                 * @param {*} value\n                 * @param {Object} sett\n                 * @return {*}\n                 */\n                data: function (value, sett) {\n                    var retval;\n\n                    sett.isChecked.apply(this, [sett]);\n\n                    if (typeof value === 'string') {\n                        retval = value.unescapeHTML();\n\n                        return retval;\n                    }\n\n                    return value;\n                },\n                submitdata: this.submitData,\n                onblur: 'cancel',\n                name: entityValueName,\n                ajaxoptions: {\n                    dataType: 'json'\n                },\n\n                /**\n                 * @param {Object} sett\n                 * @param {*} original\n                 */\n                onsubmit: function (sett, original) {\n                    var select = $(original).closest('.mselect-list').prev(),\n                        current = $(original).closest('.mselect-list-item').index(),\n                        entityId = select.find('option').eq(current).val(),\n                        entityInfo = {};\n\n                    entityInfo[entityIdName] = entityId;\n                    sett.submitdata = $.extend(sett.submitdata || {}, entityInfo);\n                },\n\n                /**\n                 * @param {Object} result\n                 * @param {Object} sett\n                 */\n                callback: function (result, sett) {\n                    var select, current;\n\n                    sett.isChecked.apply(this, [sett]);\n                    select = $(this).closest('.mselect-list').prev();\n                    current = $(this).closest('.mselect-list-item').index();\n\n                    if (result.success) {\n                        if (typeof result[entityValueName] === 'string') {\n                            select.find('option').eq(current).val(result[entityIdName]).text(result[entityValueName]);\n                            $(this).html(result[entityValueName].escapeHTML());\n                        }\n                    } else {\n                        alert({\n                            content: result['error_message']\n                        });\n                    }\n                }\n            });\n        };\n\n        /**\n         * Callback function that is called when admin adds new value to select\n         *\n         * @param {*} value\n         * @param {Object} options - list of settings of multiselect\n         */\n        EditableMultiselect.prototype.createEntity = function (value, options) {\n            var select, entityIdName, entityValueName, entityInfo, postData, ajaxOptions;\n\n            if (!value) {\n                return;\n            }\n\n            select = $('#' + this.targetSelectId),\n            entityIdName = this.entityIdName,\n            entityValueName = this.entityValueName,\n            entityInfo = {};\n            entityInfo[entityIdName] = null;\n            entityInfo[entityValueName] = value;\n\n            postData = $.extend(entityInfo, this.submitData);\n\n            ajaxOptions = {\n                type: 'POST',\n                data: postData,\n                dataType: 'json',\n                url: this.newUrl,\n\n                /**\n                 * @param {Object} result\n                 */\n                success: function (result) {\n                    var resultEntityValueName, mselectItemHtml, sectionBlock, itemsWrapper, inputSelector;\n\n                    if (result.success) {\n                        resultEntityValueName = '';\n\n                        if (typeof result[entityValueName] === 'string') {\n                            resultEntityValueName = result[entityValueName].escapeHTML();\n                        } else {\n                            resultEntityValueName = result[entityValueName];\n                        }\n                        // Add item to initial select element\n                        select.append('<option value=\"' + result[entityIdName] + '\" selected=\"selected\">' +\n                        resultEntityValueName + '</option>');\n                        // Add editable multiselect item\n                        mselectItemHtml = $(options.item.replace(/%value%|%label%/gi, resultEntityValueName)\n                                .replace(/%mselectDisabledClass%|%iseditable%|%isremovable%/gi, '')\n                                .replace(/%mselectListItemClass%/gi, options.mselectListItemClass))\n                                .find('[type=checkbox]')\n                                .attr('checked', true)\n                                .addClass(options.mselectCheckedClass)\n                                .end();\n                        sectionBlock = select.nextAll('section.block:first');\n                        itemsWrapper = sectionBlock.find('.' + options.mselectItemsWrapperClass + '');\n\n                        if (itemsWrapper.children('.' + options.mselectListItemClass + '').length) {\n                            itemsWrapper.children('.' + options.mselectListItemClass + ':last').after(mselectItemHtml);\n                        } else {\n                            itemsWrapper.prepend(mselectItemHtml);\n                        }\n                        // Trigger blur event on input field, that is used to add new value, to hide it\n                        inputSelector = '.' + options.mselectInputContainerClass + ' [type=text].' +\n                            options.mselectInputClass + '';\n                        sectionBlock.find(inputSelector).trigger('blur');\n                    } else {\n                        alert({\n                            content: result['error_message']\n                        });\n                    }\n                }\n            };\n            $.ajax(ajaxOptions);\n        };\n\n        /**\n         * Callback function that is called when user tries to delete value from select\n         *\n         * @param {Object} options\n         */\n        EditableMultiselect.prototype.deleteEntity = function (options) {\n            var self = this;\n\n            if (options['delete_button']) {\n                confirm({\n                    content: this.deleteConfirmMessage,\n                    actions: {\n                        /**\n                         * Confirm.\n                         */\n                        confirm: function () {\n                            // Button that has been clicked\n                            var deleteButton = $(options['delete_button']),\n                                index = deleteButton.parent().index(),\n                                select = deleteButton.closest('.mselect-list').prev(),\n                                entityId = select.find('option').eq(index).val(),\n                                entityInfo = {},\n                                postData, ajaxOptions;\n\n                            entityInfo[self.entityIdName] = entityId;\n                            postData = $.extend(entityInfo, self.submitData);\n\n                            ajaxOptions = {\n                                type: 'POST',\n                                data: postData,\n                                dataType: 'json',\n                                url: self.deleteUrl,\n\n                                /**\n                                 * @param {Object} result\n                                 */\n                                success: function (result) {\n                                    if (result.success) {\n                                        deleteButton.parent().remove();\n                                        select.find('option').eq(index).remove();\n                                    } else {\n                                        alert({\n                                            content: result['error_message']\n                                        });\n                                    }\n                                }\n                            };\n                            $.ajax(ajaxOptions);\n                        }\n                    }\n                });\n            }\n        };\n    };\n});\n","mage/backend/action-link.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery/ui'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.actionLink', {\n        /**\n         * Button creation\n         * @protected\n         */\n        _create: function () {\n            this._bind();\n        },\n\n        /**\n         * Bind handler on button click\n         * @protected\n         */\n        _bind: function () {\n            var keyCode = $.ui.keyCode;\n\n            this._on({\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                mousedown: function (e) {\n                    this._stopPropogation(e);\n                },\n\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                mouseup: function (e) {\n                    this._stopPropogation(e);\n                },\n\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                click: function (e) {\n                    this._stopPropogation(e);\n                    this._triggerEvent();\n                },\n\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                keydown: function (e) {\n                    switch (e.keyCode) {\n                        case keyCode.ENTER:\n                        case keyCode.NUMPAD_ENTER:\n                            this._stopPropogation(e);\n                            this._triggerEvent();\n                            break;\n                    }\n                },\n\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                keyup: function (e) {\n                    switch (e.keyCode) {\n                        case keyCode.ENTER:\n                        case keyCode.NUMPAD_ENTER:\n                            this._stopPropogation(e);\n                            break;\n                    }\n                }\n            });\n        },\n\n        /**\n         * @param {Object} e - event object\n         * @private\n         */\n        _stopPropogation: function (e) {\n            e.stopImmediatePropagation();\n            e.preventDefault();\n        },\n\n        /**\n         * @private\n         */\n        _triggerEvent: function () {\n            $(this.options.related || this.element)\n                .trigger(this.options.event, this.options.eventData ? [this.options.eventData] : [{}]);\n        }\n    });\n\n    return $.mage.actionLink;\n});\n","mage/backend/tree-suggest.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n(function (root, factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'jquery/ui',\n            'jquery/jstree/jquery.jstree',\n            'mage/backend/suggest'\n        ], factory);\n    } else {\n        factory(root.jQuery);\n    }\n}(this, function ($) {\n    'use strict';\n\n    /* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */\n    var hover_node, dehover_node, select_node, init;\n\n    $.extend(true, $, {\n        // @TODO: Move method 'treeToList' in file with utility functions\n        mage: {\n            /**\n             * @param {Array} list\n             * @param {Object} nodes\n             * @param {*} level\n             * @param {*} path\n             * @return {*}\n             */\n            treeToList: function (list, nodes, level, path) {\n                $.each(nodes, function () {\n                    if ($.type(this) === 'object') {\n                        list.push({\n                            label: this.label,\n                            id: this.id,\n                            level: level,\n                            item: this,\n                            path: path + this.label\n                        });\n\n                        if (this.children) {\n                            $.mage.treeToList(list, this.children, level + 1, path + this.label + ' / ');\n                        }\n                    }\n                });\n\n                return list;\n            }\n        }\n    });\n\n    hover_node = $.jstree._instance.prototype.hover_node;\n    dehover_node = $.jstree._instance.prototype.dehover_node;\n    select_node = $.jstree._instance.prototype.select_node;\n    init = $.jstree._instance.prototype.init;\n\n    $.extend(true, $.jstree._instance.prototype, {\n        /**\n         * @override\n         */\n        init: function () {\n            this.get_container()\n                .show()\n                .on('keydown', $.proxy(function (e) {\n                    var o;\n\n                    if (e.keyCode === $.ui.keyCode.ENTER) {\n                        o = this.data.ui.hovered || this.data.ui.last_selected || -1;\n                        this.select_node(o, true);\n                    }\n                }, this));\n            init.call(this);\n        },\n\n        /**\n         * @override\n         */\n        hover_node: function (obj) {\n            hover_node.apply(this, arguments);\n            obj = this._get_node(obj);\n\n            if (!obj.length) {\n                return false;\n            }\n            this.get_container().trigger('hover_node', [{\n                item: obj.find('a:first')\n            }]);\n        },\n\n        /**\n         * @override\n         */\n        dehover_node: function () {\n            dehover_node.call(this);\n            this.get_container().trigger('dehover_node');\n        },\n\n        /**\n         * @override\n         */\n        select_node: function (o) {\n            var node;\n\n            select_node.apply(this, arguments);\n            node = this._get_node(o);\n\n            (node ? $(node) : this.data.ui.last_selected)\n                .trigger('select_tree_node');\n        }\n    });\n\n    $.widget('mage.treeSuggest', $.mage.suggest, {\n        widgetEventPrefix: 'suggest',\n        options: {\n            template:\n                '<% if (data.items.length) { %>' +\n                    '<% if (data.allShown()) { %>' +\n                        '<% if (typeof data.nested === \"undefined\") { %>' +\n                            '<div style=\"display:none;\" data-mage-init=\"{&quot;jstree&quot;:{&quot;plugins&quot;:[&quot;themes&quot;,&quot;html_data&quot;,&quot;ui&quot;,&quot;hotkeys&quot;],&quot;themes&quot;:{&quot;theme&quot;:&quot;default&quot;,&quot;dots&quot;:false,&quot;icons&quot;:false}}}\">' + //eslint-disable-line max-len\n                        '<% } %>' +\n                        '<ul>' +\n                            '<% _.each(data.items, function(value) { %>' +\n                                '<li class=\"<% if (data.itemSelected(value)) { %>mage-suggest-selected<% } %>' +\n                '                   <% if (value.is_active == 0) { %> mage-suggest-not-active<% } %>\">' +\n                                    '<a href=\"#\" <%= data.optionData(value) %>><%- value.label %></a>' +\n                                    '<% if (value.children && value.children.length) { %>' +\n                                        '<%= data.renderTreeLevel(value.children) %>' +\n                                    '<% } %>' +\n                                '</li>' +\n                            '<% }); %>' +\n                        '</ul>' +\n                        '<% if (typeof data.nested === \"undefined\") { %>' +\n                            '</div>' +\n                        '<% } %>' +\n                    '<% } else { %>' +\n                        '<ul data-mage-init=\"{&quot;menu&quot;:[]}\">' +\n                            '<% _.each(data.items, function(value) { %>' +\n                                '<% if (!data.itemSelected(value)) {%>' +\n                                    '<li <%= data.optionData(value) %>>' +\n                                        '<a href=\"#\">' +\n                                            '<span class=\"category-label\"><%- value.label %></span>' +\n                                            '<span class=\"category-path\"><%- value.path %></span>' +\n                                        '</a>' +\n                                    '</li>' +\n                                '<% } %>' +\n                            '<% }); %>' +\n                        '</ul>' +\n                    '<% } %>' +\n                '<% } else { %>' +\n                    '<span class=\"mage-suggest-no-records\"><%- data.noRecordsText %></span>' +\n                '<% } %>',\n            controls: {\n                selector: ':ui-menu, :mage-menu, .jstree',\n                eventsMap: {\n                    focus: ['menufocus', 'hover_node'],\n                    blur: ['menublur', 'dehover_node'],\n                    select: ['menuselect', 'select_tree_node']\n                }\n            }\n        },\n\n        /**\n         * @override\n         */\n        _bind: function () {\n            this._super();\n            this._on({\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                keydown: function (event) {\n                    var keyCode = $.ui.keyCode;\n\n                    switch (event.keyCode) {\n                        case keyCode.LEFT:\n                        case keyCode.RIGHT:\n\n                            if (this.isDropdownShown()) {\n                                event.preventDefault();\n                                this._proxyEvents(event);\n                            }\n                            break;\n                    }\n                }\n            });\n        },\n\n        /**\n         * @override\n         */\n        close: function (e) {\n            var eType = e ? e.type : null;\n\n            if (eType === 'select_tree_node') {\n                this.element.focus();\n            } else {\n                this._superApply(arguments);\n            }\n        },\n\n        /**\n         * @override\n         */\n        _filterSelected: function (items, context) {\n            if (context._allShown) {\n                return items;\n            }\n\n            return this._superApply(arguments);\n        },\n\n        /**\n         * @override\n         */\n        _prepareDropdownContext: function () {\n            var context = this._superApply(arguments),\n                optionData = context.optionData,\n                templates = this.templates,\n                tmplName = this.templateName;\n\n            /**\n             * @param {Object} item\n             * @return {*|String}\n             */\n            context.optionData = function (item) {\n                item = $.extend({}, item);\n                delete item.children;\n\n                return optionData(item);\n            };\n\n            return $.extend(context, {\n                /**\n                 * @param {*} children\n                 * @return {*|jQuery}\n                 */\n                renderTreeLevel: function (children) {\n                    var _context = $.extend({}, this, {\n                        items: children,\n                        nested: true\n                    }),\n                    tmpl = templates[tmplName];\n\n                    tmpl = tmpl({\n                        data: _context\n                    });\n\n                    return $('<div>').append($(tmpl)).html();\n                }\n            });\n        },\n\n        /**\n         * @override\n         */\n        _processResponse: function (e, items, context) {\n            var control;\n\n            if (context && !context._allShown) {\n                items = this.filter($.mage.treeToList([], items, 0, ''), this._term);\n            }\n            control = this.dropdown.find(this._control.selector);\n\n            if (control.length && control.hasClass('jstree')) {\n                control.jstree('destroy');\n            }\n            this._superApply([e, items, context]);\n        }\n    });\n\n    return $.mage.treeSuggest;\n}));\n","mage/backend/menu.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n(function (factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'jquery/ui'\n        ], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($) {\n    'use strict';\n\n    $.widget('mage.menu', {\n        widgetEventPrefix: 'menu',\n        version: '1.10.1',\n        defaultElement: '<ul>',\n        delay: 300,\n        options: {\n            icons: {\n                submenu: 'ui-icon-carat-1-e'\n            },\n            menus: 'ul',\n            position: {\n                my: 'left top',\n                at: 'right top'\n            },\n            role: 'menu',\n\n            // callbacks\n            blur: null,\n            focus: null,\n            select: null\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            this.activeMenu = this.element;\n            // flag used to prevent firing of the click handler\n            // as the event bubbles up through nested menus\n            this.mouseHandled = false;\n            this.element\n                .uniqueId()\n                .addClass('ui-menu ui-widget ui-widget-content ui-corner-all')\n                .toggleClass('ui-menu-icons', !!this.element.find('.ui-icon').length)\n                .attr({\n                    role: this.options.role,\n                    tabIndex: 0\n                })\n                // need to catch all clicks on disabled menu\n                // not possible through _on\n                .bind('click' + this.eventNamespace, $.proxy(function (event) {\n                    if (this.options.disabled) {\n                        event.preventDefault();\n                    }\n                }, this));\n\n            if (this.options.disabled) {\n                this.element\n                    .addClass('ui-state-disabled')\n                    .attr('aria-disabled', 'true');\n            }\n\n            this._on({\n                /**\n                 * Prevent focus from sticking to links inside menu after clicking\n                 * them (focus should always stay on UL during navigation).\n                 */\n                'mousedown .ui-menu-item > a': function (event) {\n                    event.preventDefault();\n                },\n\n                /**\n                 * Prevent focus from sticking to links inside menu after clicking\n                 * them (focus should always stay on UL during navigation).\n                 */\n                'click .ui-state-disabled > a': function (event) {\n                    event.preventDefault();\n                },\n\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                'click .ui-menu-item:has(a)': function (event) {\n                    var target = $(event.target).closest('.ui-menu-item');\n\n                    if (!this.mouseHandled && target.not('.ui-state-disabled').length) {\n                        this.mouseHandled = true;\n\n                        this.select(event);\n                        // Open submenu on click\n                        if (target.has('.ui-menu').length) {\n                            this.expand(event);\n                        } else if (!this.element.is(':focus')) {\n                            // Redirect focus to the menu\n                            this.element.trigger('focus', [true]);\n\n                            // If the active item is on the top level, let it stay active.\n                            // Otherwise, blur the active item since it is no longer visible.\n                            if (this.active && this.active.parents('.ui-menu').length === 1) { //eslint-disable-line\n                                clearTimeout(this.timer);\n                            }\n                        }\n                    }\n                },\n\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                'mouseenter .ui-menu-item': function (event) {\n                    var target = $(event.currentTarget);\n\n                    // Remove ui-state-active class from siblings of the newly focused menu item\n                    // to avoid a jump caused by adjacent elements both having a class with a border\n                    target.siblings().children('.ui-state-active').removeClass('ui-state-active');\n                    this.focus(event, target);\n                },\n                mouseleave: 'collapseAll',\n                'mouseleave .ui-menu': 'collapseAll',\n\n                /**\n                 * @param {jQuery.Event} event\n                 * @param {*} keepActiveItem\n                 */\n                focus: function (event, keepActiveItem) {\n                    // If there's already an active item, keep it active\n                    // If not, activate the first item\n                    var item = this.active || this.element.children('.ui-menu-item').eq(0);\n\n                    if (!keepActiveItem) {\n                        this.focus(event, item);\n                    }\n                },\n\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                blur: function (event) {\n                    this._delay(function () {\n                        if (!$.contains(this.element[0], this.document[0].activeElement)) {\n                            this.collapseAll(event);\n                        }\n                    });\n                },\n                keydown: '_keydown'\n            });\n\n            this.refresh();\n\n            // Clicks outside of a menu collapse any open menus\n            this._on(this.document, {\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                click: function (event) {\n                    if (!$(event.target).closest('.ui-menu').length) {\n                        this.collapseAll(event);\n                    }\n\n                    // Reset the mouseHandled flag\n                    this.mouseHandled = false;\n                }\n            });\n        },\n\n        /**\n         * @private\n         */\n        _destroy: function () {\n            // Destroy (sub)menus\n            this.element\n                .removeAttr('aria-activedescendant')\n                .find('.ui-menu').addBack()\n                .removeClass('ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons')\n                .removeAttr('role')\n                .removeAttr('tabIndex')\n                .removeAttr('aria-labelledby')\n                .removeAttr('aria-expanded')\n                .removeAttr('aria-hidden')\n                .removeAttr('aria-disabled')\n                .removeUniqueId()\n                .show();\n\n            // Destroy menu items\n            this.element.find('.ui-menu-item')\n                .removeClass('ui-menu-item')\n                .removeAttr('role')\n                .removeAttr('aria-disabled')\n                .children('a')\n                .removeUniqueId()\n                .removeClass('ui-corner-all ui-state-hover')\n                .removeAttr('tabIndex')\n                .removeAttr('role')\n                .removeAttr('aria-haspopup')\n                .children().each(function () {\n                    var elem = $(this);\n\n                    if (elem.data('ui-menu-submenu-carat')) {\n                        elem.remove();\n                    }\n                });\n\n            // Destroy menu dividers\n            this.element.find('.ui-menu-divider').removeClass('ui-menu-divider ui-widget-content');\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _keydown: function (event) {\n            var match, prev, character, skip, regex,\n                preventDefault = true;\n\n            /**\n             * @param {String} value\n             */\n            function escape(value) {\n                return value.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, '\\\\$&');\n            }\n\n            switch (event.keyCode) {\n                case $.ui.keyCode.PAGE_UP:\n                    this.previousPage(event);\n                    break;\n\n                case $.ui.keyCode.PAGE_DOWN:\n                    this.nextPage(event);\n                    break;\n\n                case $.ui.keyCode.HOME:\n                    this._move('first', 'first', event);\n                    break;\n\n                case $.ui.keyCode.END:\n                    this._move('last', 'last', event);\n                    break;\n\n                case $.ui.keyCode.UP:\n                    this.previous(event);\n                    break;\n\n                case $.ui.keyCode.DOWN:\n                    this.next(event);\n                    break;\n\n                case $.ui.keyCode.LEFT:\n                    this.collapse(event);\n                    break;\n\n                case $.ui.keyCode.RIGHT:\n                    if (this.active && !this.active.is('.ui-state-disabled')) {\n                        this.expand(event);\n                    }\n                    break;\n\n                case $.ui.keyCode.ENTER:\n                case $.ui.keyCode.SPACE:\n                    this._activate(event);\n                    break;\n\n                case $.ui.keyCode.ESCAPE:\n                    this.collapse(event);\n                    break;\n\n                default:\n                    preventDefault = false;\n                    prev = this.previousFilter || '';\n                    character = String.fromCharCode(event.keyCode);\n                    skip = false;\n\n                    clearTimeout(this.filterTimer);\n\n                    if (character === prev) {\n                        skip = true;\n                    } else {\n                        character = prev + character;\n                    }\n\n                    regex = new RegExp('^' + escape(character), 'i');\n                    match = this.activeMenu.children('.ui-menu-item').filter(function () {\n                        return regex.test($(this).children('a').text());\n                    });\n                    match = skip && match.index(this.active.next()) !== -1 ?\n                        this.active.nextAll('.ui-menu-item') :\n                        match;\n\n                    // If no matches on the current filter, reset to the last character pressed\n                    // to move down the menu to the first item that starts with that character\n                    if (!match.length) {\n                        character = String.fromCharCode(event.keyCode);\n                        regex = new RegExp('^' + escape(character), 'i');\n                        match = this.activeMenu.children('.ui-menu-item').filter(function () {\n                            return regex.test($(this).children('a').text());\n                        });\n                    }\n\n                    if (match.length) {\n                        this.focus(event, match);\n\n                        if (match.length > 1) { //eslint-disable-line max-depth\n                            this.previousFilter = character;\n                            this.filterTimer = this._delay(function () {\n                                delete this.previousFilter;\n                            }, 1000);\n                        } else {\n                            delete this.previousFilter;\n                        }\n                    } else {\n                        delete this.previousFilter;\n                    }\n            }\n\n            if (preventDefault) {\n                event.preventDefault();\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _activate: function (event) {\n            if (!this.active.is('.ui-state-disabled')) {\n                if (this.active.children('a[aria-haspopup=\"true\"]').length) {\n                    this.expand(event);\n                } else {\n                    this.select(event);\n                }\n            }\n        },\n\n        /**\n         * Refresh.\n         */\n        refresh: function () {\n            var menus,\n                icon = this.options.icons.submenu,\n                submenus = this.element.find(this.options.menus);\n\n            // Initialize nested menus\n            submenus.filter(':not(.ui-menu)')\n                .addClass('ui-menu ui-widget ui-widget-content ui-corner-all')\n                .hide()\n                .attr({\n                    role: this.options.role,\n                    'aria-hidden': 'true',\n                    'aria-expanded': 'false'\n                })\n                .each(function () {\n                    var menu = $(this),\n                        item = menu.prev('a'),\n                        submenuCarat = $('<span>')\n                            .addClass('ui-menu-icon ui-icon ' + icon)\n                            .data('ui-menu-submenu-carat', true);\n\n                    item\n                        .attr('aria-haspopup', 'true')\n                        .prepend(submenuCarat);\n                    menu.attr('aria-labelledby', item.attr('id'));\n                });\n\n            menus = submenus.add(this.element);\n\n            // Don't refresh list items that are already adapted\n            menus.children(':not(.ui-menu-item):has(a)')\n                .addClass('ui-menu-item')\n                .attr('role', 'presentation')\n                .children('a')\n                .uniqueId()\n                .addClass('ui-corner-all')\n                .attr({\n                    tabIndex: -1,\n                    role: this._itemRole()\n                });\n\n            // Initialize unlinked menu-items containing spaces and/or dashes only as dividers\n            menus.children(':not(.ui-menu-item)').each(function () {\n                var item = $(this);\n\n                // hyphen, em dash, en dash\n                if (!/[^\\-\\u2014\\u2013\\s]/.test(item.text())) {\n                    item.addClass('ui-widget-content ui-menu-divider');\n                }\n            });\n\n            // Add aria-disabled attribute to any disabled menu item\n            menus.children('.ui-state-disabled').attr('aria-disabled', 'true');\n\n            // If the active item has been removed, blur the menu\n            if (this.active && !$.contains(this.element[0], this.active[0])) {\n                this.blur();\n            }\n        },\n\n        /**\n         * @return {*}\n         * @private\n         */\n        _itemRole: function () {\n            return {\n                menu: 'menuitem',\n                listbox: 'option'\n            }[this.options.role];\n        },\n\n        /**\n         * @param {String} key\n         * @param {*} value\n         * @private\n         */\n        _setOption: function (key, value) {\n            if (key === 'icons') {\n                this.element.find('.ui-menu-icon')\n                    .removeClass(this.options.icons.submenu)\n                    .addClass(value.submenu);\n            }\n            this._super(key, value);\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @param {Object} item\n         */\n        focus: function (event, item) {\n            var nested, focused;\n\n            this.blur(event, event && event.type === 'focus');\n\n            this._scrollIntoView(item);\n\n            this.active = item.first();\n            focused = this.active.children('a').addClass('ui-state-focus');\n            // Only update aria-activedescendant if there's a role\n            // otherwise we assume focus is managed elsewhere\n            if (this.options.role) {\n                this.element.attr('aria-activedescendant', focused.attr('id'));\n            }\n\n            // Highlight active parent menu item, if any\n            this.active\n                .parent()\n                .closest('.ui-menu-item')\n                .children('a:first')\n                .addClass('ui-state-active');\n\n            if (event && event.type === 'keydown') {\n                this._close();\n            } else {\n                this.timer = this._delay(function () {\n                    this._close();\n                }, this.delay);\n            }\n\n            nested = item.children('.ui-menu');\n\n            if (nested.length && /^mouse/.test(event.type)) {\n                this._startOpening(nested);\n            }\n            this.activeMenu = item.parent();\n\n            this._trigger('focus', event, {\n                item: item\n            });\n        },\n\n        /**\n         * @param {Object} item\n         * @private\n         */\n        _scrollIntoView: function (item) {\n            var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;\n\n            if (this._hasScroll()) {\n                borderTop = parseFloat($.css(this.activeMenu[0], 'borderTopWidth')) || 0;\n                paddingTop = parseFloat($.css(this.activeMenu[0], 'paddingTop')) || 0;\n                offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;\n                scroll = this.activeMenu.scrollTop();\n                elementHeight = this.activeMenu.height();\n                itemHeight = item.height();\n\n                if (offset < 0) {\n                    this.activeMenu.scrollTop(scroll + offset);\n                } else if (offset + itemHeight > elementHeight) {\n                    this.activeMenu.scrollTop(scroll + offset - elementHeight + itemHeight);\n                }\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @param {*} fromFocus\n         */\n        blur: function (event, fromFocus) {\n            if (!fromFocus) {\n                clearTimeout(this.timer);\n            }\n\n            if (!this.active) {\n                return;\n            }\n\n            this.active.children('a').removeClass('ui-state-focus');\n            this.active = null;\n\n            this._trigger('blur', event, {\n                item: this.active\n            });\n        },\n\n        /**\n         * @param {*} submenu\n         * @private\n         */\n        _startOpening: function (submenu) {\n            clearTimeout(this.timer);\n\n            // Don't open if already open fixes a Firefox bug that caused a .5 pixel\n            // shift in the submenu position when mousing over the carat icon\n            if (submenu.attr('aria-hidden') !== 'true') {\n                return;\n            }\n\n            this.timer = this._delay(function () {\n                this._close();\n                this._open(submenu);\n            }, this.delay);\n        },\n\n        /**\n         * @param {*} submenu\n         * @private\n         */\n        _open: function (submenu) {\n            var position = $.extend({\n                of: this.active\n            }, this.options.position);\n\n            clearTimeout(this.timer);\n            this.element.find('.ui-menu').not(submenu.parents('.ui-menu'))\n                .hide()\n                .attr('aria-hidden', 'true');\n\n            submenu\n                .show()\n                .removeAttr('aria-hidden')\n                .attr('aria-expanded', 'true')\n                .position(position);\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @param {*} all\n         */\n        collapseAll: function (event, all) {\n            clearTimeout(this.timer);\n            this.timer = this._delay(function () {\n                // If we were passed an event, look for the submenu that contains the event\n                var currentMenu = all ? this.element :\n                    $(event && event.target).closest(this.element.find('.ui-menu'));\n\n                // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway\n                if (!currentMenu.length) {\n                    currentMenu = this.element;\n                }\n\n                this._close(currentMenu);\n\n                this.blur(event);\n                this.activeMenu = currentMenu;\n            }, this.delay);\n        },\n\n        // With no arguments, closes the currently active menu - if nothing is active\n        // it closes all menus.  If passed an argument, it will search for menus BELOW\n        /**\n         * With no arguments, closes the currently active menu - if nothing is active\n         * it closes all menus.  If passed an argument, it will search for menus BELOW.\n         *\n         * @param {*} startMenu\n         * @private\n         */\n        _close: function (startMenu) {\n            if (!startMenu) {\n                startMenu = this.active ? this.active.parent() : this.element;\n            }\n\n            startMenu\n                .find('.ui-menu')\n                .hide()\n                .attr('aria-hidden', 'true')\n                .attr('aria-expanded', 'false')\n                .end()\n                .find('a.ui-state-active')\n                .removeClass('ui-state-active');\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        collapse: function (event) {\n            var newItem = this.active &&\n                this.active.parent().closest('.ui-menu-item', this.element);\n\n            if (newItem && newItem.length) {\n                this._close();\n                this.focus(event, newItem);\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        expand: function (event) {\n            var newItem = this.active &&\n                this.active\n                    .children('.ui-menu ')\n                    .children('.ui-menu-item')\n                    .first();\n\n            if (newItem && newItem.length) {\n                this._open(newItem.parent());\n\n                // Delay so Firefox will not hide activedescendant change in expanding submenu from AT\n                this._delay(function () {\n                    this.focus(event, newItem);\n                });\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        next: function (event) {\n            this._move('next', 'first', event);\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        previous: function (event) {\n            this._move('prev', 'last', event);\n        },\n\n        /**\n         * @return {null|Boolean}\n         */\n        isFirstItem: function () {\n            return this.active && !this.active.prevAll('.ui-menu-item').length;\n        },\n\n        /**\n         * @return {null|Boolean}\n         */\n        isLastItem: function () {\n            return this.active && !this.active.nextAll('.ui-menu-item').length;\n        },\n\n        /**\n         * @param {*} direction\n         * @param {*} filter\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _move: function (direction, filter, event) {\n            var next;\n\n            if (this.active) {\n                if (direction === 'first' || direction === 'last') {\n                    next = this.active\n                        [direction === 'first' ? 'prevAll' : 'nextAll']('.ui-menu-item')\n                        .eq(-1);\n                } else {\n                    next = this.active\n                        [direction + 'All']('.ui-menu-item')\n                        .eq(0);\n                }\n            }\n\n            if (!next || !next.length || !this.active) {\n                next = this.activeMenu.children('.ui-menu-item')[filter]();\n            }\n\n            this.focus(event, next);\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        nextPage: function (event) {\n            var item, base, height;\n\n            if (!this.active) {\n                this.next(event);\n\n                return;\n            }\n\n            if (this.isLastItem()) {\n                return;\n            }\n\n            if (this._hasScroll()) {\n                base = this.active.offset().top;\n                height = this.element.height();\n                this.active.nextAll('.ui-menu-item').each(function () {\n                    item = $(this);\n\n                    return item.offset().top - base - height < 0;\n                });\n\n                this.focus(event, item);\n            } else {\n                this.focus(event, this.activeMenu.children('.ui-menu-item')\n                    [!this.active ? 'first' : 'last']());\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        previousPage: function (event) {\n            var item, base, height;\n\n            if (!this.active) {\n                this.next(event);\n\n                return;\n            }\n\n            if (this.isFirstItem()) {\n                return;\n            }\n\n            if (this._hasScroll()) {\n                base = this.active.offset().top;\n                height = this.element.height();\n                this.active.prevAll('.ui-menu-item').each(function () {\n                    item = $(this);\n\n                    return item.offset().top - base + height > 0;\n                });\n\n                this.focus(event, item);\n            } else {\n                this.focus(event, this.activeMenu.children('.ui-menu-item').first());\n            }\n        },\n\n        /**\n         * @return {Boolean}\n         * @private\n         */\n        _hasScroll: function () {\n            return this.element.outerHeight() < this.element.prop('scrollHeight');\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        select: function (event) {\n            // TODO: It should never be possible to not have an active item at this\n            // point, but the tests don't trigger mouseenter before click.\n            var ui;\n\n            this.active = this.active || $(event.target).closest('.ui-menu-item');\n            ui = {\n                item: this.active\n            };\n\n            if (!this.active.has('.ui-menu').length) {\n                this.collapseAll(event, true);\n            }\n            this._trigger('select', event, ui);\n        }\n    });\n\n    return $.mage.menu;\n}));\n","mage/backend/jstree-mixin.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    return function () {\n        $.jstree._themes = require.s.contexts._.config.baseUrl + 'jquery/jstree/themes/';\n    };\n});\n","mage/backend/suggest.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n(function (root, factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'mage/template',\n            'mage/mage',\n            'jquery/ui',\n            'mage/backend/menu',\n            'mage/translate'\n        ], factory);\n    } else {\n        factory(root.jQuery, root.mageTemplate);\n    }\n}(this, function ($, mageTemplate) {\n    'use strict';\n\n    /**\n     * Implement base functionality\n     */\n    $.widget('mage.suggest', {\n        widgetEventPrefix: 'suggest',\n        options: {\n            template: '<% if (data.items.length) { %>' +\n                '<% if (!data.term && !data.allShown() && data.recentShown()) { %>' +\n                '<h5 class=\"title\"><%- data.recentTitle %></h5>' +\n                '<% } %>' +\n                '<ul data-mage-init=\\'{\"menu\":[]}\\'>' +\n                '<% _.each(data.items, function(value){ %>' +\n                '<% if (!data.itemSelected(value)) { %><li <%= data.optionData(value) %>>' +\n                '<a href=\"#\"><%- value.label %></a></li><% } %>' +\n                '<% }); %>' +\n                '<% if (!data.term && !data.allShown() && data.recentShown()) { %>' +\n                '<li data-mage-init=\\'{\"actionLink\":{\"event\":\"showAll\"}}\\' class=\"show-all\">' +\n                '<a href=\"#\"><%- data.showAllTitle %></a></li>' +\n                '<% } %>' +\n                '</ul><% } else { %><span class=\"mage-suggest-no-records\"><%- data.noRecordsText %></span><% } %>',\n            minLength: 1,\n\n            /**\n             * @type {(String|Array)}\n             */\n            source: null,\n            delay: 500,\n            loadingClass: 'mage-suggest-state-loading',\n            events: {},\n            appendMethod: 'after',\n            controls: {\n                selector: ':ui-menu, :mage-menu',\n                eventsMap: {\n                    focus: ['menufocus'],\n                    blur: ['menublur'],\n                    select: ['menuselect']\n                }\n            },\n            termAjaxArgument: 'label_part',\n            filterProperty: 'label',\n            className: null,\n            inputWrapper: '<div class=\"mage-suggest\"><div class=\"mage-suggest-inner\"></div></div>',\n            dropdownWrapper: '<div class=\"mage-suggest-dropdown\"></div>',\n            preventClickPropagation: true,\n            currentlySelected: null,\n            submitInputOnEnter: true\n        },\n\n        /**\n         * Component's constructor\n         * @private\n         */\n        _create: function () {\n            this._term = null;\n            this._nonSelectedItem = {\n                id: '',\n                label: ''\n            };\n            this.templates = {};\n            this._renderedContext = null;\n            this._selectedItem = this._nonSelectedItem;\n            this._control = this.options.controls || {};\n            this._setTemplate();\n            this._prepareValueField();\n            this._render();\n            this._bind();\n        },\n\n        /**\n         * Render base elements for suggest component\n         * @private\n         */\n        _render: function () {\n            var wrapper;\n\n            this.dropdown = $(this.options.dropdownWrapper).hide();\n            wrapper = this.options.className ?\n                $(this.options.inputWrapper).addClass(this.options.className) :\n                $(this.options.inputWrapper);\n            this.element\n                .wrap(wrapper)[this.options.appendMethod](this.dropdown)\n                .attr('autocomplete', 'off');\n        },\n\n        /**\n         * Define a field for storing item id (find in DOM or create a new one)\n         * @private\n         */\n        _prepareValueField: function () {\n            if (this.options.valueField) {\n                this.valueField = $(this.options.valueField);\n            } else {\n                this.valueField = this._createValueField()\n                    .insertBefore(this.element)\n                    .attr('name', this.element.attr('name'));\n                this.element.removeAttr('name');\n            }\n        },\n\n        /**\n         * Create value field which keeps a id for selected option\n         * can be overridden in descendants\n         * @return {jQuery}\n         * @private\n         */\n        _createValueField: function () {\n            return $('<input/>', {\n                type: 'hidden'\n            });\n        },\n\n        /**\n         * Component's destructor\n         * @private\n         */\n        _destroy: function () {\n            this.element\n                .unwrap()\n                .removeAttr('autocomplete');\n\n            if (!this.options.valueField) {\n                this.element.attr('name', this.valueField.attr('name'));\n                this.valueField.remove();\n            }\n\n            this.dropdown.remove();\n            this._off(this.element, 'keydown keyup blur');\n        },\n\n        /**\n         * Return actual value of an \"input\"-element\n         * @return {String}\n         * @private\n         */\n        _value: function () {\n            return $.trim(this.element[this.element.is(':input') ? 'val' : 'text']());\n        },\n\n        /**\n         * Pass original event to a control component for handling it as it's own event\n         * @param {Object} event - event object\n         * @private\n         */\n        _proxyEvents: function (event) {\n            var fakeEvent = $.extend({}, $.Event(event.type), {\n                    ctrlKey: event.ctrlKey,\n                    keyCode: event.keyCode,\n                    which: event.keyCode\n                }),\n                target = this._control.selector ? this.dropdown.find(this._control.selector) : this.dropdown;\n\n            target.trigger(fakeEvent);\n        },\n\n        /**\n         * Bind handlers on specific events\n         * @private\n         */\n        _bind: function () {\n            this._on($.extend({\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                keydown: function (event) {\n                    var keyCode = $.ui.keyCode,\n                        suggestList,\n                        hasSuggestedItems,\n                        hasSelectedItems,\n                        selectedItem;\n\n                    switch (event.keyCode) {\n                        case keyCode.PAGE_UP:\n                        case keyCode.UP:\n                            if (!event.shiftKey) {\n                                event.preventDefault();\n                                this._proxyEvents(event);\n                            }\n\n                            suggestList = event.currentTarget.parentNode.getElementsByTagName('ul')[0];\n                            hasSuggestedItems = event.currentTarget\n                                    .parentNode.getElementsByTagName('ul')[0].children.length >= 0;\n\n                            if (hasSuggestedItems) {\n                                selectedItem =  $(suggestList.getElementsByClassName('_active')[0])\n                                    .removeClass('_active').prev().addClass('_active');\n                                event.currentTarget.value = selectedItem.find('a').text();\n                            }\n\n                            break;\n\n                        case keyCode.PAGE_DOWN:\n                        case keyCode.DOWN:\n                            if (!event.shiftKey) {\n                                event.preventDefault();\n                                this._proxyEvents(event);\n                            }\n\n                            suggestList = event.currentTarget.parentNode.getElementsByTagName('ul')[0];\n                            hasSuggestedItems = event.currentTarget\n                                .parentNode.getElementsByTagName('ul')[0].children.length >= 0;\n\n                            if (hasSuggestedItems) {\n                                hasSelectedItems = suggestList.getElementsByClassName('_active').length === 0;\n\n                                if (hasSelectedItems) { //eslint-disable-line max-depth\n                                    selectedItem = $(suggestList.children[0]).addClass('_active');\n                                    event.currentTarget.value = selectedItem.find('a').text();\n                                } else {\n                                    selectedItem = $(suggestList.getElementsByClassName('_active')[0])\n                                        .removeClass('_active').next().addClass('_active');\n                                    event.currentTarget.value = selectedItem.find('a').text();\n                                }\n                            }\n                            break;\n\n                        case keyCode.TAB:\n                            if (this.isDropdownShown()) {\n                                this._onSelectItem(event, null);\n                                event.preventDefault();\n                            }\n                            break;\n\n                        case keyCode.ENTER:\n                        case keyCode.NUMPAD_ENTER:\n                            this._toggleEnter(event);\n\n                            if (this.isDropdownShown() && this._focused) {\n                                this._proxyEvents(event);\n                                event.preventDefault();\n                            }\n                            break;\n\n                        case keyCode.ESCAPE:\n                            if (this.isDropdownShown()) {\n                                event.stopPropagation();\n                            }\n                            this.close(event);\n                            this._blurItem();\n                            break;\n                    }\n                },\n\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                keyup: function (event) {\n                    var keyCode = $.ui.keyCode;\n\n                    switch (event.keyCode) {\n                        case keyCode.HOME:\n                        case keyCode.END:\n                        case keyCode.PAGE_UP:\n                        case keyCode.PAGE_DOWN:\n                        case keyCode.ESCAPE:\n                        case keyCode.UP:\n                        case keyCode.DOWN:\n                        case keyCode.LEFT:\n                        case keyCode.RIGHT:\n                        case keyCode.TAB:\n                            break;\n\n                        case keyCode.ENTER:\n                        case keyCode.NUMPAD_ENTER:\n                            if (this.isDropdownShown()) {\n                                event.preventDefault();\n                            }\n                            break;\n                        default:\n                            this.search(event);\n                    }\n                },\n\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                blur: function (event) {\n                    if (!this.preventBlur) {\n                        this._abortSearch();\n                        this.close(event);\n                        this._change(event);\n                    } else {\n                        this.element.trigger('focus');\n                    }\n                },\n                cut: this.search,\n                paste: this.search,\n                input: this.search,\n                selectItem: this._onSelectItem,\n                click: this.search\n            }, this.options.events));\n\n            this._bindSubmit();\n            this._bindDropdown();\n        },\n\n        /**\n         * @param {Object} event\n         * @private\n         */\n        _toggleEnter: function (event) {\n            var suggestList,\n                activeItems,\n                selectedItem;\n\n            if (!this.options.submitInputOnEnter) {\n                event.preventDefault();\n            }\n\n            suggestList = $(event.currentTarget.parentNode).find('ul').first();\n            activeItems = suggestList.find('._active');\n\n            if (activeItems.length >= 0) {\n                selectedItem = activeItems.first();\n\n                if (selectedItem.find('a') && selectedItem.find('a').attr('href') !== undefined) {\n                    window.location = selectedItem.find('a').attr('href');\n                    event.preventDefault();\n                }\n            }\n        },\n\n        /**\n         * Bind handlers for submit on enter\n         * @private\n         */\n        _bindSubmit: function () {\n            this.element.parents('form').on('submit', function (event) {\n                if (!this.submitInputOnEnter) {\n                    event.preventDefault();\n                }\n            });\n        },\n\n        /**\n         * @param {Object} e - event object\n         * @private\n         */\n        _change: function (e) {\n            if (this._term !== this._value()) {\n                this._trigger('change', e);\n            }\n        },\n\n        /**\n         * Bind handlers for dropdown element on specific events\n         * @private\n         */\n        _bindDropdown: function () {\n            var events = {\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                click: function (e) {\n                    // prevent default browser's behavior of changing location by anchor href\n                    e.preventDefault();\n                },\n\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                mousedown: function (e) {\n                    e.preventDefault();\n                }\n            };\n\n            $.each(this._control.eventsMap, $.proxy(function (suggestEvent, controlEvents) {\n                $.each(controlEvents, $.proxy(function (i, handlerName) {\n                    switch (suggestEvent) {\n                        case 'select':\n                            events[handlerName] = this._onSelectItem;\n                            break;\n\n                        case 'focus':\n                            events[handlerName] = this._focusItem;\n                            break;\n\n                        case 'blur':\n                            events[handlerName] = this._blurItem;\n                            break;\n                    }\n                }, this));\n            }, this));\n\n            if (this.options.preventClickPropagation) {\n                this._on(this.dropdown, events);\n            }\n            // Fix for IE 8\n            this._on(this.dropdown, {\n                /**\n                 * Mousedown.\n                 */\n                mousedown: function () {\n                    this.preventBlur = true;\n                },\n\n                /**\n                 * Mouseup.\n                 */\n                mouseup: function () {\n                    this.preventBlur = false;\n                }\n            });\n        },\n\n        /**\n         * @override\n         */\n        _trigger: function (type, event) {\n            var result = this._superApply(arguments);\n\n            if (result === false && event) {\n                event.stopImmediatePropagation();\n                event.preventDefault();\n            }\n\n            return result;\n        },\n\n        /**\n         * Handle focus event of options item\n         * @param {Object} e - event object\n         * @param {Object} ui - object that can contain information about focused item\n         * @private\n         */\n        _focusItem: function (e, ui) {\n            if (ui && ui.item) {\n                this._focused = $(ui.item).prop('tagName') ?\n                    this._readItemData(ui.item) :\n                    ui.item;\n\n                this.element.val(this._focused.label);\n                this._trigger('focus', e, {\n                    item: this._focused\n                });\n            }\n        },\n\n        /**\n         * Handle blur event of options item\n         * @private\n         */\n        _blurItem: function () {\n            this._focused = null;\n            this.element.val(this._term);\n        },\n\n        /**\n         * @param {Object} e - event object\n         * @param {Object} item\n         * @private\n         */\n        _onSelectItem: function (e, item) {\n            if (item && $.type(item) === 'object' && $(e.target).is(this.element)) {\n                this._focusItem(e, {\n                    item: item\n                });\n            }\n\n            if (this._trigger('beforeselect', e || null, {\n                    item: this._focused\n                }) === false) {\n                return;\n            }\n            this._selectItem(e);\n            this._blurItem();\n            this._trigger('select', e || null, {\n                item: this._selectedItem\n            });\n        },\n\n        /**\n         * Save selected item and hide dropdown\n         * @private\n         * @param {Object} e - event object\n         */\n        _selectItem: function (e) {\n            if (this._focused) {\n                this._selectedItem = this._focused;\n\n                if (this._selectedItem !== this._nonSelectedItem) {\n                    this._term = this._selectedItem.label;\n                    this.valueField.val(this._selectedItem.id);\n                    this.close(e);\n                }\n            }\n        },\n\n        /**\n         * Read option data from item element\n         * @param {Element} element\n         * @return {Object}\n         * @private\n         */\n        _readItemData: function (element) {\n            return element.data('suggestOption') || this._nonSelectedItem;\n        },\n\n        /**\n         * Check if dropdown is shown\n         * @return {Boolean}\n         */\n        isDropdownShown: function () {\n            return this.dropdown.is(':visible');\n        },\n\n        /**\n         * Open dropdown\n         * @private\n         * @param {Object} e - event object\n         */\n        open: function (e) {\n            if (!this.isDropdownShown()) {\n                this.element.addClass('_suggest-dropdown-open');\n                this.dropdown.show();\n                this._trigger('open', e);\n            }\n        },\n\n        /**\n         * Close and clear dropdown content\n         * @private\n         * @param {Object} e - event object\n         */\n        close: function (e) {\n            this._renderedContext = null;\n\n            if (this.dropdown.length) {\n                this.element.removeClass('_suggest-dropdown-open');\n                this.dropdown.hide().empty();\n            }\n\n            this._trigger('close', e);\n        },\n\n        /**\n         * Acquire content template\n         * @private\n         */\n        _setTemplate: function () {\n            this.templateName = 'suggest' + Math.random().toString(36).substr(2);\n\n            this.templates[this.templateName] = mageTemplate(this.options.template);\n        },\n\n        /**\n         * Execute search process\n         * @public\n         * @param {Object} e - event object\n         */\n        search: function (e) {\n            var term = this._value();\n\n            if ((this._term !== term || term.length === 0) && !this.preventBlur) {\n                this._term = term;\n\n                if ($.type(term) === 'string' && term.length >= this.options.minLength) {\n                    if (this._trigger('search', e) === false) { //eslint-disable-line max-depth\n                        return;\n                    }\n                    this._search(e, term, {});\n                } else {\n                    this._selectedItem = this._nonSelectedItem;\n                    this._resetSuggestValue();\n                }\n            }\n        },\n\n        /**\n         * Clear suggest hidden input\n         * @private\n         */\n        _resetSuggestValue: function () {\n            this.valueField.val(this._nonSelectedItem.id);\n        },\n\n        /**\n         * Actual search method, can be overridden in descendants\n         * @param {Object} e - event object\n         * @param {String} term - search phrase\n         * @param {Object} context - search context\n         * @private\n         */\n        _search: function (e, term, context) {\n            var response = $.proxy(function (items) {\n                return this._processResponse(e, items, context || {});\n            }, this);\n\n            this.element.addClass(this.options.loadingClass);\n\n            if (this.options.delay) {\n                if ($.type(this.options.data) !== 'undefined') {\n                    response(this.filter(this.options.data, term));\n                }\n                clearTimeout(this._searchTimeout);\n                this._searchTimeout = this._delay(function () {\n                    this._source(term, response);\n                }, this.options.delay);\n            } else {\n                this._source(term, response);\n            }\n        },\n\n        /**\n         * Extend basic context with additional data (search results, search term)\n         * @param {Object} context\n         * @return {Object}\n         * @private\n         */\n        _prepareDropdownContext: function (context) {\n            return $.extend(context, {\n                items: this._items,\n                term: this._term,\n\n                /**\n                 * @param {Object} item\n                 * @return {String}\n                 */\n                optionData: function (item) {\n                    return 'data-suggest-option=\"' +\n                        $('<div>').text(JSON.stringify(item)).html().replace(/\"/g, '&quot;') + '\"';\n                },\n                itemSelected: $.proxy(this._isItemSelected, this),\n                noRecordsText: $.mage.__('No records found.')\n            });\n        },\n\n        /**\n         * @param {Object} item\n         * @return {Boolean}\n         * @private\n         */\n        _isItemSelected: function (item) {\n            return item.id == (this._selectedItem && this._selectedItem.id ? //eslint-disable-line eqeqeq\n                this._selectedItem.id :\n                this.options.currentlySelected);\n        },\n\n        /**\n         * Render content of suggest's dropdown\n         * @param {Object} e - event object\n         * @param {Array} items - list of label+id objects\n         * @param {Object} context - template's context\n         * @private\n         */\n        _renderDropdown: function (e, items, context) {\n            var tmpl = this.templates[this.templateName];\n\n            this._items = items;\n\n            tmpl = tmpl({\n                data: this._prepareDropdownContext(context)\n            });\n\n            $(tmpl).appendTo(this.dropdown.empty());\n\n            this.dropdown.trigger('contentUpdated')\n                .find(this._control.selector).on('focus', function (event) {\n                    event.preventDefault();\n                });\n\n            this._renderedContext = context;\n            this.element.removeClass(this.options.loadingClass);\n            this.open(e);\n        },\n\n        /**\n         * @param {Object} e\n         * @param {Object} items\n         * @param {Object} context\n         * @private\n         */\n        _processResponse: function (e, items, context) {\n            var renderer = $.proxy(function (i) {\n                return this._renderDropdown(e, i, context || {});\n            }, this);\n\n            if (this._trigger('response', e, [items, renderer]) === false) {\n                return;\n            }\n            this._renderDropdown(e, items, context);\n        },\n\n        /**\n         * Implement search process via spesific source\n         * @param {String} term - search phrase\n         * @param {Function} response - search results handler, process search result\n         * @private\n         */\n        _source: function (term, response) {\n            var o = this.options,\n                ajaxData;\n\n            if ($.isArray(o.source)) {\n                response(this.filter(o.source, term));\n            } else if ($.type(o.source) === 'string') {\n                ajaxData = {};\n                ajaxData[this.options.termAjaxArgument] = term;\n\n                this._xhr = $.ajax($.extend(true, {\n                    url: o.source,\n                    type: 'POST',\n                    dataType: 'json',\n                    data: ajaxData,\n                    success: $.proxy(function (items) {\n                        this.options.data = items;\n                        response.apply(response, arguments);\n                    }, this)\n                }, o.ajaxOptions || {}));\n            } else if ($.type(o.source) === 'function') {\n                o.source.apply(o.source, arguments);\n            }\n        },\n\n        /**\n         * Abort search process\n         * @private\n         */\n        _abortSearch: function () {\n            this.element.removeClass(this.options.loadingClass);\n            clearTimeout(this._searchTimeout);\n        },\n\n        /**\n         * Perform filtering in advance loaded items and returns search result\n         * @param {Array} items - all available items\n         * @param {String} term - search phrase\n         * @return {Object}\n         */\n        filter: function (items, term) {\n            var matcher = new RegExp(term.replace(/[\\-\\/\\\\\\^$*+?.()|\\[\\]{}]/g, '\\\\$&'), 'i'),\n                itemsArray = $.isArray(items) ? items : $.map(items, function (element) {\n                    return element;\n                }),\n                property = this.options.filterProperty;\n\n            return $.grep(\n                itemsArray,\n                function (value) {\n                    return matcher.test(value[property] || value.id || value);\n                }\n            );\n        }\n    });\n\n    /**\n     * Implement show all functionality and storing and display recent searches\n     */\n    $.widget('mage.suggest', $.mage.suggest, {\n        options: {\n            showRecent: false,\n            showAll: false,\n            storageKey: 'suggest',\n            storageLimit: 10\n        },\n\n        /**\n         * @override\n         */\n        _create: function () {\n            var recentItems;\n\n            if (this.options.showRecent && window.localStorage) {\n                recentItems = JSON.parse(localStorage.getItem(this.options.storageKey));\n\n                /**\n                 * @type {Array} - list of recently searched items\n                 * @private\n                 */\n                this._recentItems = $.isArray(recentItems) ? recentItems : [];\n            }\n            this._super();\n        },\n\n        /**\n         * @override\n         */\n        _bind: function () {\n            this._super();\n            this._on(this.dropdown, {\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                showAll: function (e) {\n                    e.stopImmediatePropagation();\n                    e.preventDefault();\n                    this.element.trigger('showAll');\n                }\n            });\n\n            if (this.options.showRecent || this.options.showAll) {\n                this._on({\n                    /**\n                     * @param {jQuery.Event} e\n                     */\n                    focus: function (e) {\n                        if (!this.isDropdownShown()) {\n                            this.search(e);\n                        }\n                    },\n                    showAll: this._showAll\n                });\n            }\n        },\n\n        /**\n         * @private\n         * @param {Object} e - event object\n         */\n        _showAll: function (e) {\n            this._abortSearch();\n            this._search(e, '', {\n                _allShown: true\n            });\n        },\n\n        /**\n         * @override\n         */\n        search: function (e) {\n            if (!this._value()) {\n\n                if (this.options.showRecent) {\n\n                    if (this._recentItems.length) { //eslint-disable-line max-depth\n                        this._processResponse(e, this._recentItems, {});\n                    } else {\n                        this._showAll(e);\n                    }\n                } else if (this.options.showAll) {\n                    this._showAll(e);\n                }\n            }\n            this._superApply(arguments);\n        },\n\n        /**\n         * @override\n         */\n        _selectItem: function () {\n            this._superApply(arguments);\n\n            if (this._selectedItem && this._selectedItem.id && this.options.showRecent) {\n                this._addRecent(this._selectedItem);\n            }\n        },\n\n        /**\n         * @override\n         */\n        _prepareDropdownContext: function () {\n            var context = this._superApply(arguments);\n\n            return $.extend(context, {\n                recentShown: $.proxy(function () {\n                    return this.options.showRecent;\n                }, this),\n                recentTitle: $.mage.__('Recent items'),\n                showAllTitle: $.mage.__('Show all...'),\n\n                /**\n                 * @return {Boolean}\n                 */\n                allShown: function () {\n                    return !!context._allShown;\n                }\n            });\n        },\n\n        /**\n         * Add selected item of search result into storage of recents\n         * @param {Object} item - label+id object\n         * @private\n         */\n        _addRecent: function (item) {\n            this._recentItems = $.grep(this._recentItems, function (obj) {\n                return obj.id !== item.id;\n            });\n            this._recentItems.unshift(item);\n            this._recentItems = this._recentItems.slice(0, this.options.storageLimit);\n            localStorage.setItem(this.options.storageKey, JSON.stringify(this._recentItems));\n        }\n    });\n\n    /**\n     * Implement multi suggest functionality\n     */\n    $.widget('mage.suggest', $.mage.suggest, {\n        options: {\n            multiSuggestWrapper: '<ul class=\"mage-suggest-choices\">' +\n                '<li class=\"mage-suggest-search-field\" data-role=\"parent-choice-element\"><' +\n                'label class=\"mage-suggest-search-label\"></label></li></ul>',\n            choiceTemplate: '<li class=\"mage-suggest-choice button\"><div><%- text %></div>' +\n            '<span class=\"mage-suggest-choice-close\" tabindex=\"-1\" ' +\n            'data-mage-init=\\'{\"actionLink\":{\"event\":\"removeOption\"}}\\'></span></li>',\n            selectedClass: 'mage-suggest-selected'\n        },\n\n        /**\n         * @override\n         */\n        _create: function () {\n            this.choiceTmpl = mageTemplate(this.options.choiceTemplate);\n\n            this._super();\n\n            if (this.options.multiselect) {\n                this.valueField.hide();\n            }\n        },\n\n        /**\n         * @override\n         */\n        _render: function () {\n            this._super();\n\n            if (this.options.multiselect) {\n                this._renderMultiselect();\n            }\n        },\n\n        /**\n         * Render selected options\n         * @private\n         */\n        _renderMultiselect: function () {\n            var that = this;\n\n            this.element.wrap(this.options.multiSuggestWrapper);\n            this.elementWrapper = this.element.closest('[data-role=\"parent-choice-element\"]');\n            $(function () {\n                that._getOptions()\n                    .each(function (i, option) {\n                        option = $(option);\n                        that._createOption({\n                            id: option.val(),\n                            label: option.text()\n                        });\n                    });\n            });\n        },\n\n        /**\n         * @return {Array} array of DOM-elements\n         * @private\n         */\n        _getOptions: function () {\n            return this.valueField.find('option');\n        },\n\n        /**\n         * @override\n         */\n        _bind: function () {\n            this._super();\n\n            if (this.options.multiselect) {\n                this._on({\n                    /**\n                     * @param {jQuery.Event} event\n                     */\n                    keydown: function (event) {\n                        if (event.keyCode === $.ui.keyCode.BACKSPACE) {\n                            if (!this._value()) {\n                                this._removeLastAdded(event);\n                            }\n                        }\n                    },\n                    removeOption: this.removeOption\n                });\n            }\n        },\n\n        /**\n         * @param {Array} items\n         * @return {Array}\n         * @private\n         */\n        _filterSelected: function (items) {\n            var options = this._getOptions();\n\n            return $.grep(items, function (value) {\n                var itemSelected = false;\n\n                $.each(options, function () {\n                    if (value.id == $(this).val()) { //eslint-disable-line eqeqeq\n                        itemSelected = true;\n                    }\n                });\n\n                return !itemSelected;\n            });\n        },\n\n        /**\n         * @override\n         */\n        _processResponse: function (e, items, context) {\n            if (this.options.multiselect) {\n                items = this._filterSelected(items, context);\n            }\n            this._superApply([e, items, context]);\n        },\n\n        /**\n         * @override\n         */\n        _prepareValueField: function () {\n            this._super();\n\n            if (this.options.multiselect && !this.options.valueField && this.options.selectedItems) {\n                $.each(this.options.selectedItems, $.proxy(function (i, item) {\n                    this._addOption(item);\n                }, this));\n            }\n        },\n\n        /**\n         * If \"multiselect\" option is set, then do not need to clear value for hidden select, to avoid losing of\n         *      previously selected items\n         * @override\n         */\n        _resetSuggestValue: function () {\n            if (!this.options.multiselect) {\n                this._super();\n            }\n        },\n\n        /**\n         * @override\n         */\n        _createValueField: function () {\n            if (this.options.multiselect) {\n                return $('<select/>', {\n                    type: 'hidden',\n                    multiple: 'multiple'\n                });\n            }\n\n            return this._super();\n        },\n\n        /**\n         * @override\n         */\n        _selectItem: function (e) {\n            if (this.options.multiselect) {\n                if (this._focused) {\n                    this._selectedItem = this._focused;\n\n                    /* eslint-disable max-depth */\n                    if (this._selectedItem !== this._nonSelectedItem) {\n                        this._term = '';\n                        this.element.val(this._term);\n\n                        if (this._isItemSelected(this._selectedItem)) {\n                            $(e.target).removeClass(this.options.selectedClass);\n                            this.removeOption(e, this._selectedItem);\n                            this._selectedItem = this._nonSelectedItem;\n                        } else {\n                            $(e.target).addClass(this.options.selectedClass);\n                            this._addOption(e, this._selectedItem);\n                        }\n                    }\n\n                    /* eslint-enable max-depth */\n                }\n                this.close(e);\n            } else {\n                this._superApply(arguments);\n            }\n        },\n\n        /**\n         * @override\n         */\n        _isItemSelected: function (item) {\n            if (this.options.multiselect) {\n                return this.valueField.find('option[value=' + item.id + ']').length > 0;\n            }\n\n            return this._superApply(arguments);\n        },\n\n        /**\n         *\n         * @param {Object} item\n         * @return {Element}\n         * @private\n         */\n        _createOption: function (item) {\n            var option = this._getOption(item);\n\n            if (!option.length) {\n                option = $('<option>', {\n                    value: item.id,\n                    selected: true\n                }).text(item.label);\n            }\n\n            return option.data('renderedOption', this._renderOption(item));\n        },\n\n        /**\n         * Add selected item in to select options\n         * @param {Object} e - event object\n         * @param {*} item\n         * @private\n         */\n        _addOption: function (e, item) {\n            this.valueField.append(this._createOption(item).data('selectTarget', $(e.target)));\n        },\n\n        /**\n         * @param {Object|Element} item\n         * @return {Element}\n         * @private\n         */\n        _getOption: function (item) {\n            return $(item).prop('tagName') ?\n                $(item) :\n                this.valueField.find('option[value=' + item.id + ']');\n        },\n\n        /**\n         * Remove last added option\n         * @private\n         * @param {Object} e - event object\n         */\n        _removeLastAdded: function (e) {\n            var lastAdded = this._getOptions().last();\n\n            if (lastAdded.length) {\n                this.removeOption(e, lastAdded);\n            }\n        },\n\n        /**\n         * Remove item from select options\n         * @param {Object} e - event object\n         * @param {Object} item\n         * @private\n         */\n        removeOption: function (e, item) {\n            var option = this._getOption(item),\n                selectTarget = option.data('selectTarget');\n\n            if (selectTarget && selectTarget.length) {\n                selectTarget.removeClass(this.options.selectedClass);\n            }\n\n            option.data('renderedOption').remove();\n            option.remove();\n        },\n\n        /**\n         * Render visual element of selected item\n         * @param {Object} item - selected item\n         * @private\n         */\n        _renderOption: function (item) {\n            var tmpl = this.choiceTmpl({\n                text: item.label\n            });\n\n            return $(tmpl)\n                .insertBefore(this.elementWrapper)\n                .trigger('contentUpdated')\n                .on('removeOption', $.proxy(function (e) {\n                    this.removeOption(e, item);\n                }, this));\n        }\n    });\n\n    return $.mage.suggest;\n}));\n","mage/backend/form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n(function (factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'jquery/ui'\n        ], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($) {\n    'use strict';\n\n    $.widget('mage.form', {\n        options: {\n            handlersData: {\n                save: {},\n                saveAndContinueEdit: {\n                    action: {\n                        args: {\n                            back: 'edit'\n                        }\n                    }\n                },\n                preview: {\n                    target: '_blank'\n                }\n            }\n        },\n\n        /**\n         * Form creation\n         * @protected\n         */\n        _create: function () {\n            this._bind();\n        },\n\n        /**\n         * Set form attributes to initial state\n         * @protected\n         */\n        _rollback: function () {\n            if (this.oldAttributes) {\n                this.element.prop(this.oldAttributes);\n            }\n        },\n\n        /**\n         * Check if field value is changed\n         * @protected\n         * @param {Object} e - event object\n         */\n        _changesObserver: function (e) {\n            var target = $(e.target),\n                changed;\n\n            if (e.type === 'focus' || e.type === 'focusin') {\n                this.currentField = {\n                    statuses: {\n                        checked: target.is(':checked'),\n                        selected: target.is(':selected')\n                    },\n                    val: target.val()\n                };\n\n            } else {\n                if (this.currentField) { //eslint-disable-line no-lonely-if\n                    changed = target.val() !== this.currentField.val ||\n                        target.is(':checked') !== this.currentField.statuses.checked ||\n                        target.is(':selected') !== this.currentField.statuses.selected;\n\n                    if (changed) { //eslint-disable-line max-depth\n                        target.trigger('changed');\n                    }\n                }\n            }\n        },\n\n        /**\n         * Get array with handler names\n         * @protected\n         * @return {Array} Array of handler names\n         */\n        _getHandlers: function () {\n            var handlers = [];\n\n            $.each(this.options.handlersData, function (key) {\n                handlers.push(key);\n            });\n\n            return handlers;\n        },\n\n        /**\n         * Store initial value of form attribute\n         * @param {String} attrName - name of attribute\n         * @protected\n         */\n        _storeAttribute: function (attrName) {\n            var prop;\n\n            this.oldAttributes = this.oldAttributes || {};\n\n            if (!this.oldAttributes[attrName]) {\n                prop = this.element.attr(attrName);\n                this.oldAttributes[attrName] = prop ? prop : '';\n            }\n        },\n\n        /**\n         * Bind handlers\n         * @protected\n         */\n        _bind: function () {\n            this.element\n                .on(this._getHandlers().join(' '), $.proxy(this._submit, this))\n                .on('focus blur focusin focusout', $.proxy(this._changesObserver, this));\n        },\n\n        /**\n         * Get action url for form\n         * @param {Object|String} data - object with parameters for action url or url string\n         * @return {String} action url\n         */\n        _getActionUrl: function (data) {\n            if ($.type(data) === 'object') {\n                return this._buildURL(this.oldAttributes.action, data.args);\n            }\n\n            return $.type(data) === 'string' ? data : this.oldAttributes.action;\n        },\n\n        /**\n         * Add additional parameters into URL\n         * @param {String} url - original url\n         * @param {Object} params - object with parameters for action url\n         * @return {String} action url\n         * @private\n         */\n        _buildURL: function (url, params) {\n            var concat = /\\?/.test(url) ? ['&', '='] : ['/', '/'];\n\n            url = url.replace(/[\\/&]+$/, '');\n            $.each(params, function (key, value) {\n                url += concat[0] + key + concat[1] + window.encodeURIComponent(value);\n            });\n\n            return url + (concat[0] === '/' ? '/' : '');\n        },\n\n        /**\n         * Prepare data for form attributes\n         * @protected\n         * @param {Object} data\n         * @return {Object}\n         */\n        _processData: function (data) {\n            $.each(data, $.proxy(function (attrName, attrValue) {\n                this._storeAttribute(attrName);\n\n                if (attrName === 'action') {\n                    data[attrName] = this._getActionUrl(attrValue);\n                }\n            }, this));\n\n            return data;\n        },\n\n        /**\n         * Get additional data before form submit\n         * @protected\n         * @param {String} handlerName\n         * @param {Object} data\n         */\n        _beforeSubmit: function (handlerName, data) {\n            var submitData = {},\n                event = new $.Event('beforeSubmit');\n\n            this.element.trigger(event, [submitData, handlerName]);\n            data = $.extend(\n                true, {},\n                this.options.handlersData[handlerName] || {},\n                submitData,\n                data\n            );\n            this.element.prop(this._processData(data));\n\n            return !event.isDefaultPrevented();\n        },\n\n        /**\n         * Submit the form\n         * @param {Object} e - event object\n         * @param {Object} data - event data object\n         */\n        _submit: function (e, data) {\n            this._rollback();\n\n            if (this._beforeSubmit(e.type, data) !== false) {\n                this.element.trigger('submit', e);\n            }\n        }\n    });\n\n    return $.mage.form;\n}));\n","mage/backend/floating-header.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery/ui'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.floatingHeader', {\n        options: {\n            placeholderAttrs: {\n                'class': 'page-actions-placeholder'\n            },\n            fixedClass: '_fixed',\n            hiddenClass: '_hidden',\n            title: '.page-title-wrapper .page-title',\n            pageMainActions: '.page-main-actions',\n            contains: '[data-role=modal]'\n        },\n\n        /**\n         * Widget initialization\n         * @private\n         */\n        _create: function () {\n            var title = $(this.options.title).text(),\n                wrapped = this.element.find('.page-actions-buttons').children();\n\n            if (this.element.parents(this.options.contains).length) {\n                return this;\n            }\n\n            this._setVars();\n            this._bind();\n            this.element.find('script').remove();\n\n            if (wrapped.length) {\n                wrapped\n                    .unwrap()   // .page-actions-buttons\n                    .unwrap();  // .page-actions-inner\n            }\n            this.element.wrapInner($('<div/>', {\n                'class': 'page-actions-buttons'\n            }));\n            this.element.wrapInner($('<div/>', {\n                'class': 'page-actions-inner', 'data-title': title\n            }));\n        },\n\n        /**\n         * Set privat variables on load, for performance purposes\n         * @private\n         */\n        _setVars: function () {\n            this._placeholder = this.element.before($('<div/>', this.options.placeholderAttrs)).prev();\n            this._offsetTop = this._placeholder.offset().top;\n            this._height = this.element\n                .parents(this.options.pageMainActions)\n                .outerHeight();\n        },\n\n        /**\n         * Event binding, will monitor scroll and resize events (resize events left for backward compat)\n         * @private\n         */\n        _bind: function () {\n            this._on(window, {\n                scroll: this._handlePageScroll,\n                resize: this._handlePageScroll\n            });\n        },\n\n        /**\n         * Event handler for setting fixed positioning\n         * @private\n         */\n        _handlePageScroll: function () {\n            var isActive = $(window).scrollTop() > this._offsetTop;\n\n            if (isActive) {\n                this.element\n                    .addClass(this.options.fixedClass)\n                    .parents(this.options.pageMainActions)\n                    .addClass(this.options.hiddenClass);\n            } else {\n                this.element\n                    .removeClass(this.options.fixedClass)\n                    .parents(this.options.pageMainActions)\n                    .removeClass(this.options.hiddenClass);\n            }\n\n            this._placeholder.height(isActive ? this._height : '');\n        },\n\n        /**\n         * Widget destroy functionality\n         * @private\n         */\n        _destroy: function () {\n            this._placeholder.remove();\n            this._off($(window));\n        }\n    });\n\n    return $.mage.floatingHeader;\n});\n","mage/backend/tabs.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global FORM_KEY */\n(function (factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'jquery/ui'\n        ], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($) {\n    'use strict';\n\n    var rhash, isLocal;\n\n    // mage.tabs base functionality\n    $.widget('mage.tabs', $.ui.tabs, {\n        options: {\n            spinner: false,\n            groups: null,\n            tabPanelClass: '',\n            excludedPanel: ''\n        },\n\n        /**\n         * Tabs creation\n         * @protected\n         */\n        _create: function () {\n            var activeIndex = this._getTabIndex(this.options.active);\n\n            this.options.active = activeIndex >= 0 ? activeIndex : 0;\n            this._super();\n        },\n\n        /**\n         * @override\n         * @private\n         * @return {Array} Array of DOM-elements\n         */\n        _getList: function () {\n            if (this.options.groups) {\n                return this.element.find(this.options.groups);\n            }\n\n            return this._super();\n        },\n\n        /**\n         * Get active anchor\n         * @return {Element}\n         */\n        activeAnchor: function () {\n            return this.anchors.eq(this.option('active'));\n        },\n\n        /**\n         * Get tab index by tab id\n         * @protected\n         * @param {String} id - id of tab\n         * @return {Number}\n         */\n        _getTabIndex: function (id) {\n            var anchors = this.anchors ?\n                this.anchors :\n                this._getList().find('> li > a[href]');\n\n            return anchors.index($('#' + id));\n        },\n\n        /**\n         * Switch between tabs\n         * @protected\n         * @param {Object} event - event object\n         * @param {undefined|Object} eventData\n         */\n        _toggle: function (event, eventData) {\n            var anchor = $(eventData.newTab).find('a');\n\n            if ($(eventData.newTab).find('a').data().tabType === 'link') {\n                location.href = anchor.prop('href');\n            } else {\n                this._superApply(arguments);\n            }\n        }\n    });\n\n    rhash = /#.*$/;\n\n    /**\n     * @param {*} anchor\n     * @return {Boolean}\n     */\n    isLocal = function (anchor) {\n        return anchor.hash.length > 1 &&\n            anchor.href.replace(rhash, '') ===\n                location.href.replace(rhash, '')\n                    // support: Safari 5.1\n                    // Safari 5.1 doesn't encode spaces in window.location\n                    // but it does encode spaces from anchors (#8777)\n                    .replace(/\\s/g, '%20');\n    };\n\n    // Extension for mage.tabs - Move panels in destination element\n    $.widget('mage.tabs', $.mage.tabs, {\n        /**\n         * Move panels in destination element on creation\n         * @protected\n         * @override\n         */\n        _create: function () {\n            this._super();\n            this._movePanelsInDestination(this.panels);\n        },\n\n        /**\n         * Get panel for tab. If panel no exist in tabs container, then find panel in destination element\n         * @protected\n         * @override\n         * @param {Element} tab - tab \"li\" DOM-element\n         * @return {Element}\n         */\n        _getPanelForTab: function (tab) {\n            var panel = this._superApply(arguments),\n                id;\n\n            if (!panel.length) {\n                id = $(tab).attr('aria-controls');\n                panel = $(this.options.destination).find(this._sanitizeSelector('#' + id));\n            }\n\n            return panel;\n        },\n\n        /**\n         * @private\n         */\n        _processTabs: function () {\n            var that = this;\n\n            this.tablist = this._getList()\n                .addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all')\n                .attr('role', 'tablist');\n\n            this.tabs = this.tablist.find('> li:has(a[href])')\n                .addClass('ui-state-default ui-corner-top')\n                .attr({\n                    role: 'tab',\n                    tabIndex: -1\n                });\n\n            this.anchors = this.tabs.map(function () {\n                return $('a', this)[ 0 ];\n            })\n                .addClass('ui-tabs-anchor')\n                .attr({\n                    role: 'presentation',\n                    tabIndex: -1\n                });\n\n            this.panels = $();\n\n            this.anchors.each(function (i, anchor) {\n                var selector, panel, panelId,\n                    anchorId = $(anchor).uniqueId().attr('id'),\n                    tab = $(anchor).closest('li'),\n                    originalAriaControls = tab.attr('aria-controls');\n\n                // inline tab\n                if (isLocal(anchor)) {\n                    selector = anchor.hash;\n                    panel = that.document.find(that._sanitizeSelector(selector));\n                    // remote tab\n                } else {\n                    panelId = that._tabId(tab);\n                    selector = '#' + panelId;\n                    panel = that.document.find(selector);\n\n                    if (!panel.length) {\n                        panel = that._createPanel(panelId);\n                        panel.insertAfter(that.panels[ i - 1 ] || that.tablist);\n                    }\n                    panel.attr('aria-live', 'polite');\n                }\n\n                if (panel.length) {\n                    that.panels = that.panels.add(panel);\n                }\n\n                if (originalAriaControls) {\n                    tab.data('ui-tabs-aria-controls', originalAriaControls);\n                }\n                tab.attr({\n                    'aria-controls': selector.substring(1),\n                    'aria-labelledby': anchorId\n                });\n                panel.attr('aria-labelledby', anchorId);\n\n                if (that.options.excludedPanel.indexOf(anchorId + '_content') < 0) {\n                    panel.addClass(that.options.tabPanelClass);\n                }\n            });\n\n            this.panels\n                .addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')\n                .attr('role', 'tabpanel');\n        },\n\n        /**\n         * Move panels in destination element\n         * @protected\n         * @override\n         */\n        _movePanelsInDestination: function (panels) {\n            if (this.options.destination && !panels.parents(this.options.destination).length) {\n                this.element.trigger('beforePanelsMove', panels);\n\n                panels.find('script:not([type]), script[type=\"text/javascript\"]').remove();\n\n                panels.appendTo(this.options.destination)\n                    .each($.proxy(function (i, panel) {\n                        $(panel).trigger('move.tabs', this.anchors.eq(i));\n                    }, this));\n            }\n        },\n\n        /**\n         * Move panels in destination element on tabs switching\n         * @protected\n         * @override\n         * @param {Object} event - event object\n         * @param {Object} eventData\n         */\n        _toggle: function (event, eventData) {\n            this._movePanelsInDestination(eventData.newPanel);\n            this._superApply(arguments);\n        }\n    });\n\n    // Extension for mage.tabs - Ajax functionality for tabs\n    $.widget('mage.tabs', $.mage.tabs, {\n        options: {\n            ajaxOptions: {\n                data: {\n                    isAjax: true,\n                    'form_key': typeof FORM_KEY !== 'undefined' ? FORM_KEY : null\n                }\n            },\n\n            /**\n             * Replacing href attribute with loaded panel id\n             * @param {Object} event - event object\n             * @param {Object} ui\n             */\n            load: function (event, ui) {\n                var panel = $(ui.panel);\n\n                $(ui.tab).prop('href', '#' + panel.prop('id'));\n                panel.trigger('contentUpdated');\n            }\n        }\n    });\n\n    // Extension for mage.tabs - Attach event handlers to tabs\n    $.widget('mage.tabs', $.mage.tabs, {\n        options: {\n            tabIdArgument: 'tab',\n            tabsBlockPrefix: null\n        },\n\n        /**\n         * Attach event handlers to tabs, on creation\n         * @protected\n         * @override\n         */\n        _refresh: function () {\n            this._super();\n            $.each(this.tabs, $.proxy(function (i, tab) {\n                $(this._getPanelForTab(tab))\n                    .off('changed' + this.eventNamespace)\n                    .off('highlight.validate' + this.eventNamespace)\n                    .off('focusin' + this.eventNamespace)\n\n                    .on('changed' + this.eventNamespace, {\n                        index: i\n                    }, $.proxy(this._onContentChange, this))\n                    .on('highlight.validate' + this.eventNamespace, {\n                        index: i\n                    }, $.proxy(this._onInvalid, this))\n                    .on('focusin' + this.eventNamespace, {\n                        index: i\n                    }, $.proxy(this._onFocus, this));\n            }, this));\n\n            ($(this.options.destination).is('form') ?\n                $(this.options.destination) :\n                $(this.options.destination).closest('form'))\n                    .off('beforeSubmit' + this.eventNamespace)\n                    .on('beforeSubmit' + this.eventNamespace, $.proxy(this._onBeforeSubmit, this));\n        },\n\n        /**\n         * Mark tab as changed if some field inside tab panel is changed\n         * @protected\n         * @param {Object} e - event object\n         */\n        _onContentChange: function (e) {\n            var cssChanged = '_changed';\n\n            this.anchors.eq(e.data.index).addClass(cssChanged);\n            this._updateNavTitleMessages(e, cssChanged);\n        },\n\n        /**\n         * Clone messages (tooltips) from anchor to parent element\n         * @protected\n         * @param {Object} e - event object\n         * @param {String} messageType - changed or error\n         */\n        _updateNavTitleMessages: function (e, messageType) {\n            var curAnchor = this.anchors.eq(e.data.index),\n                curItem = curAnchor.parents('[data-role=\"container\"]').find('[data-role=\"title\"]'),\n                curItemMessages = curItem.find('[data-role=\"title-messages\"]'),\n                activeClass = '_active';\n\n            if (curItemMessages.is(':empty')) {\n                curAnchor\n                    .find('[data-role=\"item-messages\"]')\n                    .clone()\n                    .appendTo(curItemMessages);\n            }\n\n            curItemMessages.find('.' + messageType).addClass(activeClass);\n        },\n\n        /**\n         * Mark tab as error if some field inside tab panel is not passed validation\n         * @param {Object} e - event object\n         * @protected\n         */\n        _onInvalid: function (e) {\n            var cssError = '_error',\n                fakeEvent = e;\n\n            fakeEvent.currentTarget = $(this.anchors).eq(e.data.index);\n            this._eventHandler(fakeEvent);\n            this.anchors.eq(e.data.index).addClass(cssError).find('.' + cssError).show();\n            this._updateNavTitleMessages(e, cssError);\n        },\n\n        /**\n         * Show tab panel if focus event triggered of some field inside tab panel\n         * @param {Object} e - event object\n         * @protected\n         */\n        _onFocus: function (e) {\n            this.option('_active', e.data.index);\n        },\n\n        /**\n         * Add active tab id in data object when \"beforeSubmit\" event is triggered\n         * @param {Object} e - event object\n         * @param {Object} data - event data object\n         * @protected\n         */\n        _onBeforeSubmit: function (e, data) { //eslint-disable-line no-unused-vars\n            var activeAnchor = this.activeAnchor(),\n                activeTabId = activeAnchor.prop('id'),\n                options;\n\n            if (this.options.tabsBlockPrefix) {\n                if (activeAnchor.is('[id*=\"' + this.options.tabsBlockPrefix + '\"]')) {\n                    activeTabId = activeAnchor.prop('id').substr(this.options.tabsBlockPrefix.length);\n                }\n            }\n            $(this.anchors).removeClass('error');\n            options = {\n                action: {\n                    args: {}\n                }\n            };\n            options.action.args[this.options.tabIdArgument] = activeTabId;\n            data = data ? $.extend(data, options) : options;\n        }\n    });\n\n    // Extension for mage.tabs - Shadow tabs functionality\n    $.widget('mage.tabs', $.mage.tabs, {\n        /**\n         * Add shadow tabs functionality on creation\n         * @protected\n         * @override\n         */\n        _refresh: function () {\n            var anchors, shadowTabs, tabs;\n\n            this._super();\n            anchors = this.anchors;\n            shadowTabs = this.options.shadowTabs;\n            tabs = this.tabs;\n\n            if (shadowTabs) {\n                anchors.each($.proxy(function (i, anchor) {\n                    var anchorId = $(anchor).prop('id');\n\n                    if (shadowTabs[anchorId]) {\n                        $(anchor).parents('li').on('click', $.proxy(function () {\n                            $.each(shadowTabs[anchorId], $.proxy(function (key, id) {\n                                this.load($(tabs).index($('#' + id).parents('li')), {});\n                            }, this));\n                        }, this));\n                    }\n                }, this));\n            }\n        }\n    });\n\n    return $.mage.tabs;\n}));\n","mage/backend/button.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n(function (factory) {\n    'use strict';\n\n    if (typeof define === 'function' && define.amd) {\n        define([\n            'jquery',\n            'jquery/ui'\n        ], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($) {\n    'use strict';\n\n    $.widget('ui.button', $.ui.button, {\n        options: {\n            eventData: {},\n            waitTillResolved: true\n        },\n\n        /**\n         * Button creation.\n         * @protected\n         */\n        _create: function () {\n            if (this.options.event) {\n                this.options.target = this.options.target || this.element;\n                this._bind();\n            }\n\n            this._super();\n        },\n\n        /**\n         * Bind handler on button click.\n         * @protected\n         */\n        _bind: function () {\n            this.element\n                .off('click.button')\n                .on('click.button', $.proxy(this._click, this));\n        },\n\n        /**\n         * Button click handler.\n         * @protected\n         */\n        _click: function () {\n            var options = this.options;\n\n            $(options.target).trigger(options.event, [options.eventData]);\n        }\n    });\n\n    return $.ui.button;\n}));\n","Magento_AdvancedSearch/js/testconnection.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/alert',\n    'jquery/ui'\n], function ($, alert) {\n    'use strict';\n\n    $.widget('mage.testConnection', {\n        options: {\n            url: '',\n            elementId: '',\n            successText: '',\n            failedText: '',\n            fieldMapping: ''\n        },\n\n        /**\n         * Bind handlers to events\n         */\n        _create: function () {\n            this._on({\n                'click': $.proxy(this._connect, this)\n            });\n        },\n\n        /**\n         * Method triggers an AJAX request to check search engine connection\n         * @private\n         */\n        _connect: function () {\n            var result = this.options.failedText,\n                element =  $('#' + this.options.elementId),\n                self = this,\n                params = {},\n                msg = '';\n\n            element.removeClass('success').addClass('fail');\n            $.each($.parseJSON(this.options.fieldMapping), function (key, el) {\n                params[key] = $('#' + el).val();\n            });\n            $.ajax({\n                url: this.options.url,\n                showLoader: true,\n                data: params\n            }).done(function (response) {\n                if (response.success) {\n                    element.removeClass('fail').addClass('success');\n                    result = self.options.successText;\n                } else {\n                    msg = response.errorMessage;\n\n                    if (msg) {\n                        alert({\n                            content: msg\n                        });\n                    }\n                }\n            }).always(function () {\n                $('#' + self.options.elementId + '_result').text(result);\n            });\n        }\n    });\n\n    return $.mage.testConnection;\n});\n","Magento_Rule/rules.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_Ui/js/modal/alert',\n    'mage/translate',\n    'prototype'\n], function (jQuery) {\n\n    var VarienRulesForm = new Class.create();\n\n    VarienRulesForm.prototype = {\n        initialize: function (parent, newChildUrl) {\n            this.parent = $(parent);\n            this.newChildUrl  = newChildUrl;\n            this.shownElement = null;\n            this.updateElement = null;\n            this.chooserSelectedItems = $H({});\n            this.readOnly = false;\n\n            var elems = this.parent.getElementsByClassName('rule-param');\n\n            for (var i = 0; i < elems.length; i++) {\n                this.initParam(elems[i]);\n            }\n        },\n\n        setReadonly: function (readonly) {\n            this.readOnly = readonly;\n            var elems = this.parent.getElementsByClassName('rule-param-remove');\n\n            for (var i = 0; i < elems.length; i++) {\n                var element = elems[i];\n\n                if (this.readOnly) {\n                    element.hide();\n                } else {\n                    element.show();\n                }\n            }\n\n            var elems = this.parent.getElementsByClassName('rule-param-new-child');\n\n            for (var i = 0; i < elems.length; i++) {\n                var element = elems[i];\n\n                if (this.readOnly) {\n                    element.hide();\n                } else {\n                    element.show();\n                }\n            }\n\n            var elems = this.parent.getElementsByClassName('rule-param');\n\n            for (var i = 0; i < elems.length; i++) {\n                var container = elems[i];\n                var label = Element.down(container, '.label');\n\n                if (label) {\n                    if (this.readOnly) {\n                        label.addClassName('label-disabled');\n                    } else {\n                        label.removeClassName('label-disabled');\n                    }\n                }\n            }\n        },\n\n        initParam: function (container) {\n            container.rulesObject = this;\n            var label = Element.down(container, '.label');\n\n            if (label) {\n                Event.observe(label, 'click', this.showParamInputField.bind(this, container));\n            }\n\n            var elem = Element.down(container, '.element');\n\n            if (elem) {\n                var trig = elem.down('.rule-chooser-trigger');\n\n                if (trig) {\n                    Event.observe(trig, 'click', this.toggleChooser.bind(this, container));\n                }\n\n                var apply = elem.down('.rule-param-apply');\n\n                if (apply) {\n                    Event.observe(apply, 'click', this.hideParamInputField.bind(this, container));\n                } else {\n                    elem = elem.down('.element-value-changer');\n                    elem.container = container;\n\n                    if (!elem.multiple) {\n                        Event.observe(elem, 'change', this.hideParamInputField.bind(this, container));\n\n                        this.changeVisibilityForValueRuleParam(elem);\n\n                    }\n                    Event.observe(elem, 'blur', this.hideParamInputField.bind(this, container));\n                }\n            }\n\n            var remove = Element.down(container, '.rule-param-remove');\n\n            if (remove) {\n                Event.observe(remove, 'click', this.removeRuleEntry.bind(this, container));\n            }\n        },\n\n        showChooserElement: function (chooser) {\n            this.chooserSelectedItems = $H({});\n\n            if (chooser.hasClassName('no-split')) {\n                this.chooserSelectedItems.set(this.updateElement.value, 1);\n            } else {\n                var values = this.updateElement.value.split(','),\n s = '';\n\n                for (i = 0; i < values.length; i++) {\n                    s = values[i].strip();\n\n                    if (s != '') {\n                        this.chooserSelectedItems.set(s, 1);\n                    }\n                }\n            }\n            new Ajax.Request(chooser.getAttribute('url'), {\n                evalScripts: true,\n                parameters: {\n                    'form_key': FORM_KEY, 'selected[]': this.chooserSelectedItems.keys()\n                },\n                onSuccess: function (transport) {\n                    if (this._processSuccess(transport)) {\n                        jQuery(chooser).html(transport.responseText);\n                        this.showChooserLoaded(chooser, transport);\n                        jQuery(chooser).trigger('contentUpdated');\n                    }\n                }.bind(this),\n                onFailure: this._processFailure.bind(this)\n            });\n        },\n\n        showChooserLoaded: function (chooser, transport) {\n            chooser.style.display = 'block';\n        },\n\n        showChooser: function (container, event) {\n            var chooser = container.up('li');\n\n            if (!chooser) {\n                return;\n            }\n            chooser = chooser.down('.rule-chooser');\n\n            if (!chooser) {\n                return;\n            }\n            this.showChooserElement(chooser);\n        },\n\n        hideChooser: function (container, event) {\n            var chooser = container.up('li');\n\n            if (!chooser) {\n                return;\n            }\n            chooser = chooser.down('.rule-chooser');\n\n            if (!chooser) {\n                return;\n            }\n            chooser.style.display = 'none';\n        },\n\n        toggleChooser: function (container, event) {\n            if (this.readOnly) {\n                return false;\n            }\n\n            var chooser = container.up('li').down('.rule-chooser');\n\n            if (!chooser) {\n                return;\n            }\n\n            if (chooser.style.display == 'block') {\n                chooser.style.display = 'none';\n                this.cleanChooser(container, event);\n            } else {\n                this.showChooserElement(chooser);\n            }\n        },\n\n        cleanChooser: function (container, event) {\n            var chooser = container.up('li').down('.rule-chooser');\n\n            if (!chooser) {\n                return;\n            }\n            chooser.innerHTML = '';\n        },\n\n        showParamInputField: function (container, event) {\n            if (this.readOnly) {\n                return false;\n            }\n\n            if (this.shownElement) {\n                this.hideParamInputField(this.shownElement, event);\n            }\n\n            Element.addClassName(container, 'rule-param-edit');\n            var elemContainer = Element.down(container, '.element');\n\n            var elem = Element.down(elemContainer, 'input.input-text');\n\n            jQuery(elem).trigger('contentUpdated');\n\n            if (elem) {\n                elem.focus();\n\n                if (elem && elem.id && elem.id.match(/__value$/)) {\n                    this.updateElement = elem;\n                }\n\n            }\n\n            var elem = Element.down(elemContainer, '.element-value-changer');\n\n            if (elem) {\n                elem.focus();\n            }\n\n            this.shownElement = container;\n        },\n\n        hideParamInputField: function (container, event) {\n            Element.removeClassName(container, 'rule-param-edit');\n            var label = Element.down(container, '.label'),\n elem;\n\n            if (!container.hasClassName('rule-param-new-child')) {\n                elem = Element.down(container, '.element-value-changer');\n\n                if (elem && elem.options) {\n                    var selectedOptions = [];\n\n                    for (i = 0; i < elem.options.length; i++) {\n                        if (elem.options[i].selected) {\n                            selectedOptions.push(elem.options[i].text);\n                        }\n                    }\n\n                    var str = selectedOptions.join(', ');\n\n                    label.innerHTML = str != '' ? str : '...';\n                }\n\n                this.changeVisibilityForValueRuleParam(elem);\n\n                elem = Element.down(container, 'input.input-text');\n\n                if (elem) {\n                    var str = elem.value.replace(/(^\\s+|\\s+$)/g, '');\n\n                    elem.value = str;\n\n                    if (str == '') {\n                        str = '...';\n                    } else if (str.length > 30) {\n                        str = str.substr(0, 30) + '...';\n                    }\n                    label.innerHTML = str.escapeHTML();\n                }\n            } else {\n                elem = container.down('.element-value-changer');\n\n                if (elem.value) {\n                    this.addRuleNewChild(elem);\n                }\n                elem.value = '';\n            }\n\n            if (elem && elem.id && elem.id.match(/__value$/)) {\n                this.hideChooser(container, event);\n                this.updateElement = null;\n            }\n\n            this.shownElement = null;\n        },\n\n        changeVisibilityForValueRuleParam: function(elem) {\n            let parsedElementId = elem.id.split('__');\n            if (parsedElementId[2] != 'operator') {\n                return false;\n            }\n\n            let valueElement = jQuery('#' + parsedElementId[0] + '__' + parsedElementId[1] + '__value');\n\n            if(elem.value == '<=>') {\n                valueElement.closest('.rule-param').hide();\n            } else {\n                valueElement.closest('.rule-param').show();\n            }\n\n            return true;\n        },\n\n        addRuleNewChild: function (elem) {\n            var parent_id = elem.id.replace(/^.*__(.*)__.*$/, '$1');\n            var children_ul_id = elem.id.replace(/__/g, ':').replace(/[^:]*$/, 'children').replace(/:/g, '__');\n            var children_ul = $(this.parent).select('#' + children_ul_id)[0];\n            var max_id = 0,\n i;\n            var children_inputs = Selector.findChildElements(children_ul, $A(['input.hidden']));\n\n            if (children_inputs.length) {\n                children_inputs.each(function (el) {\n                    if (el.id.match(/__type$/)) {\n                        i = 1 * el.id.replace(/^.*__.*?([0-9]+)__.*$/, '$1');\n                        max_id = i > max_id ? i : max_id;\n                    }\n                });\n            }\n            var new_id = parent_id + '--' + (max_id + 1);\n            var new_type = elem.value;\n            var new_elem = document.createElement('LI');\n\n            new_elem.className = 'rule-param-wait';\n            new_elem.innerHTML = jQuery.mage.__('This won\\'t take long . . .');\n            children_ul.insertBefore(new_elem, $(elem).up('li'));\n\n            new Ajax.Request(this.newChildUrl, {\n                evalScripts: true,\n                parameters: {\n                    form_key: FORM_KEY, type: new_type.replace('/', '-'), id: new_id\n                },\n                onComplete: this.onAddNewChildComplete.bind(this, new_elem),\n                onSuccess: function (transport) {\n                    if (this._processSuccess(transport)) {\n                        $(new_elem).update(transport.responseText);\n                    }\n                }.bind(this),\n                onFailure: this._processFailure.bind(this)\n            });\n        },\n\n        _processSuccess: function (transport) {\n            if (transport.responseText.isJSON()) {\n                var response = transport.responseText.evalJSON();\n\n                if (response.error) {\n                    alert(response.message);\n                }\n\n                if (response.ajaxExpired && response.ajaxRedirect) {\n                    setLocation(response.ajaxRedirect);\n                }\n\n                return false;\n            }\n\n            return true;\n        },\n\n        _processFailure: function (transport) {\n            location.href = BASE_URL;\n        },\n\n        onAddNewChildComplete: function (new_elem) {\n            if (this.readOnly) {\n                return false;\n            }\n\n            $(new_elem).removeClassName('rule-param-wait');\n            var elems = new_elem.getElementsByClassName('rule-param');\n\n            for (var i = 0; i < elems.length; i++) {\n                this.initParam(elems[i]);\n            }\n        },\n\n        removeRuleEntry: function (container, event) {\n            var li = Element.up(container, 'li');\n\n            li.parentNode.removeChild(li);\n        },\n\n        chooserGridInit: function (grid) {\n            //grid.reloadParams = {'selected[]':this.chooserSelectedItems.keys()};\n        },\n\n        chooserGridRowInit: function (grid, row) {\n            if (!grid.reloadParams) {\n                grid.reloadParams = {\n                    'selected[]': this.chooserSelectedItems.keys()\n                };\n            }\n        },\n\n        chooserGridRowClick: function (grid, event) {\n            var trElement = Event.findElement(event, 'tr');\n            var isInput = Event.element(event).tagName == 'INPUT';\n\n            if (trElement) {\n                var checkbox = Element.select(trElement, 'input');\n\n                if (checkbox[0]) {\n                    var checked = isInput ? checkbox[0].checked : !checkbox[0].checked;\n\n                    grid.setCheckboxChecked(checkbox[0], checked);\n\n                }\n            }\n        },\n\n        chooserGridCheckboxCheck: function (grid, element, checked) {\n            if (checked) {\n                if (!element.up('th')) {\n                    this.chooserSelectedItems.set(element.value, 1);\n                }\n            } else {\n                this.chooserSelectedItems.unset(element.value);\n            }\n            grid.reloadParams = {\n                'selected[]': this.chooserSelectedItems.keys()\n            };\n            this.updateElement.value = this.chooserSelectedItems.keys().join(', ');\n        }\n    };\n\n    return VarienRulesForm;\n});\n","Magento_Rule/conditions-data-normalizer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore'\n], function ($, _) {\n    'use strict';\n\n    /**\n     * @constructor\n     */\n    var ConditionsDataNormalizer = function () {\n        this.patterns = {\n            validate: /^[a-z0-9_.-][a-z0-9_.-]*(?:\\[(?:\\d*|[a-z0-9_.-]+)\\])*$/i,\n            key: /[a-z0-9_.-]+|(?=\\[\\])/gi,\n            push: /^$/,\n            fixed: /^\\d+$/,\n            named: /^[a-z0-9_.-]+$/i\n        };\n    };\n\n    ConditionsDataNormalizer.prototype = {\n        /**\n         * Will convert an object:\n         * {\n         *   \"foo[bar][1][baz]\": 123,\n         *   \"foo[bar][1][blah]\": 321\n         *   \"foo[bar][1--1][ah]\": 456\n         * }\n         *\n         * to\n         * {\n         *   \"foo\": {\n         *     \"bar\": {\n         *       \"1\": {\n         *         \"baz\": 123,\n         *         \"blah\": 321\n         *       },\n         *       \"1--1\": {\n         *         \"ah\": 456\n         *       }\n         *     }\n         *   }\n         * }\n         */\n        normalize: function normalize(value) {\n            var el, _this = this;\n\n            this.pushes = {};\n            this.data = {};\n\n            _.each(value, function (e, i) {\n                el = {};\n                el[i] = e;\n\n                _this._addPair({\n                    name: i,\n                    value: e\n                });\n            });\n\n            return this.data;\n        },\n\n        /**\n         * @param {Object} base\n         * @param {String} key\n         * @param {String} value\n         * @return {Object}\n         * @private\n         */\n        _build: function build(base, key, value) {\n            base[key] = value;\n\n            return base;\n        },\n\n        /**\n         * @param {Object} root\n         * @param {String} value\n         * @return {*}\n         * @private\n         */\n        _makeObject: function makeObject(root, value) {\n            var keys = root.match(this.patterns.key),\n                k, idx; // nest, nest, ..., nest\n\n            while ((k = keys.pop()) !== undefined) {\n                // foo[]\n                if (this.patterns.push.test(k)) {\n                    idx = this._incrementPush(root.replace(/\\[\\]$/, ''));\n                    value = this._build([], idx, value);\n                } // foo[n]\n                else if (this.patterns.fixed.test(k)) {\n                    value = this._build({}, k, value);\n                } // foo; foo[bar]\n                else if (this.patterns.named.test(k)) {\n                    value = this._build({}, k, value);\n                }\n            }\n\n            return value;\n        },\n\n        /**\n         * @param {String} key\n         * @return {Number}\n         * @private\n         */\n        _incrementPush: function incrementPush(key) {\n            if (this.pushes[key] === undefined) {\n                this.pushes[key] = 0;\n            }\n\n            return this.pushes[key]++;\n        },\n\n        /**\n         * @param {Object} pair\n         * @return {Object}\n         * @private\n         */\n        _addPair: function addPair(pair) {\n            var obj = this._makeObject(pair.name, pair.value);\n\n            if (!this.patterns.validate.test(pair.name)) {\n                return this;\n            }\n\n            this.data = $.extend(true, this.data, obj);\n\n            return this;\n        }\n    };\n\n    return ConditionsDataNormalizer;\n});\n","Magento_ConfigurableProduct/js/configurable.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**************************** CONFIGURABLE PRODUCT **************************/\n/* global Product, optionsPrice */\ndefine([\n    'jquery',\n    'mage/template',\n    'mage/translate',\n    'prototype'\n], function (jQuery, mageTemplate) {\n    'use strict';\n\n    if (typeof Product == 'undefined') {\n        window.Product = {};\n    }\n\n    Product.Config = Class.create();\n    Product.Config.prototype = {\n        /**\n         * Initialize function.\n         *\n         * @param {Object} config\n         */\n        initialize: function (config) {\n            var separatorIndex, paramsStr, urlValues, i, childSettings, prevSetting, nextSetting;\n\n            // Magic preprocessing\n            // TODO MAGETWO-31539\n            config.taxConfig = {\n                showBothPrices: false,\n                inclTaxTitle: jQuery.mage.__('Incl. Tax')\n            };\n\n            this.config     = config;\n            this.taxConfig  = this.config.taxConfig;\n\n            if (config.containerId) {\n                this.settings   = $$('#' + config.containerId + ' ' + '.super-attribute-select');\n            } else {\n                this.settings   = $$('.super-attribute-select');\n            }\n            this.state      = new Hash();\n            this.priceTemplate = mageTemplate(this.config.template);\n            this.prices     = config.prices;\n            this.values     = {};\n\n            // Set default values from config\n            if (config.defaultValues) {\n                this.values = config.defaultValues;\n            }\n\n            // Overwrite defaults by url\n            separatorIndex = window.location.href.indexOf('#');\n\n            if (separatorIndex != -1) { //eslint-disable-line eqeqeq\n                paramsStr = window.location.href.substr(separatorIndex + 1);\n                urlValues = paramsStr.toQueryParams();\n\n                for (i in urlValues) { //eslint-disable-line guard-for-in\n                    this.values[i] = urlValues[i];\n                }\n            }\n\n            // Overwrite defaults by inputs values if needed\n            if (config.inputsInitialized) {\n                this.values = {};\n                this.settings.each(function (element) {\n                    var attributeId;\n\n                    if (element.value) {\n                        attributeId = element.id.replace(/[a-z]*/, '');\n                        this.values[attributeId] = element.value;\n                    }\n                }.bind(this));\n            }\n\n            // Put events to check select reloads\n            this.settings.each(function (element) {\n                Event.observe(element, 'change', this.configure.bind(this));\n            }.bind(this));\n\n            // fill state\n            this.settings.each(function (element) {\n                var attributeId = element.id.replace(/[a-z]*/, '');\n\n                if (attributeId && this.config.attributes[attributeId]) {\n                    element.config = this.config.attributes[attributeId];\n                    element.attributeId = attributeId;\n                    this.state[attributeId] = false;\n                }\n            }.bind(this));\n\n            // Init settings dropdown\n            childSettings = [];\n\n            for (i = this.settings.length - 1; i >= 0; i--) {\n                prevSetting = this.settings[i - 1] ? this.settings[i - 1] : false;\n                nextSetting = this.settings[i + 1] ? this.settings[i + 1] : false;\n\n                if (i === 0) {\n                    this.fillSelect(this.settings[i]);\n                } else {\n                    this.settings[i].disabled = true;\n                }\n                $(this.settings[i]).childSettings = childSettings.clone();\n                $(this.settings[i]).prevSetting   = prevSetting;\n                $(this.settings[i]).nextSetting   = nextSetting;\n                childSettings.push(this.settings[i]);\n            }\n\n            // Set values to inputs\n            this.configureForValues();\n            document.observe('dom:loaded', this.configureForValues.bind(this));\n        },\n\n        /**\n         * Configure for values.\n         */\n        configureForValues: function () {\n            if (this.values) {\n                this.settings.each(function (element) {\n                    var attributeId = element.attributeId;\n\n                    element.value = typeof this.values[attributeId] === 'undefined' ? '' : this.values[attributeId];\n                    this.configureElement(element);\n                }.bind(this));\n            }\n        },\n\n        /**\n         * @param {Object} event\n         */\n        configure: function (event) {\n            var element = Event.element(event);\n\n            this.configureElement(element);\n        },\n\n        /**\n         * @param {Object} element\n         */\n        configureElement: function (element) {\n            this.reloadOptionLabels(element);\n\n            if (element.value) {\n                this.state[element.config.id] = element.value;\n\n                if (element.nextSetting) {\n                    element.nextSetting.disabled = false;\n                    this.fillSelect(element.nextSetting);\n                    this.resetChildren(element.nextSetting);\n                }\n            } else {\n                this.resetChildren(element);\n            }\n            this.reloadPrice();\n        },\n\n        /**\n         * @param {Object} element\n         */\n        reloadOptionLabels: function (element) {\n            var selectedPrice = 0,\n                option, i;\n\n            if (element.options[element.selectedIndex] && element.options[element.selectedIndex].config) {\n                option = element.options[element.selectedIndex].config;\n                selectedPrice = parseFloat(this.config.optionPrices[option.allowedProducts[0]].finalPrice.amount);\n            }\n            element.setAttribute('price', selectedPrice);\n\n            for (i = 0; i < element.options.length; i++) {\n                if (element.options[i].config) {\n                    element.options[i].setAttribute('price', selectedPrice);\n                    element.options[i].setAttribute('summarizePrice', 0);\n                    element.options[i].text = this.getOptionLabel(element.options[i].config, selectedPrice);\n                }\n            }\n        },\n\n        /* eslint-disable max-depth */\n        /**\n         * @param {Object} element\n         */\n        resetChildren: function (element) {\n            var i;\n\n            if (element.childSettings) {\n                for (i = 0; i < element.childSettings.length; i++) {\n                    element.childSettings[i].selectedIndex = 0;\n                    element.childSettings[i].disabled = true;\n\n                    if (element.config) {\n                        this.state[element.config.id] = false;\n                    }\n                }\n            }\n        },\n\n        /**\n         * @param {Object} element\n         */\n        fillSelect: function (element) {\n            var attributeId = element.id.replace(/[a-z]*/, ''),\n                options = this.getAttributeOptions(attributeId),\n                prevConfig = false,\n                index = 1,\n                i, j, allowedProducts;\n\n            this.clearSelect(element);\n            element.options[0] = new Option('', '');\n            element.options[0].innerHTML = this.config.chooseText;\n\n            if (element.prevSetting) {\n                prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];\n            }\n\n            if (options) {\n                for (i = 0; i < options.length; i++) {\n                    allowedProducts = [];\n\n                    if (prevConfig) {\n                        for (j = 0; j < options[i].products.length; j++) {\n                            if (prevConfig.config.allowedProducts &&\n                                prevConfig.config.allowedProducts.indexOf(options[i].products[j]) > -1\n                            ) {\n                                allowedProducts.push(options[i].products[j]);\n                            }\n                        }\n                    } else {\n                        allowedProducts = options[i].products.clone();\n                    }\n\n                    if (allowedProducts.size() > 0) {\n                        options[i].allowedProducts = allowedProducts;\n                        element.options[index] = new Option(this.getOptionLabel(options[i]), options[i].id);\n\n                        if (typeof options[i].price != 'undefined') {\n                            element.options[index].setAttribute('price', options[i].price);\n                        }\n                        element.options[index].config = options[i];\n                        index++;\n                    }\n                }\n            }\n        },\n\n        //eslint-enable max-depth\n        /**\n         * @param {Object} option\n         */\n        getOptionLabel: function (option) {\n            return option.label;\n        },\n\n        /**\n         * @param {*} price\n         * @param {Boolean} showSign\n         * @return {String}\n         */\n        formatPrice: function (price, showSign) {\n            var str = '',\n                roundedPrice;\n\n            price = parseFloat(price);\n\n            if (showSign) {\n                if (price < 0) {\n                    str += '-';\n                    price = -price;\n                } else {\n                    str += '+';\n                }\n            }\n\n            roundedPrice = Number(Math.round(price + 'e+2') + 'e-2').toString();\n\n            if (this.prices && this.prices[roundedPrice]) {\n                str += this.prices[roundedPrice];\n            } else {\n                str += this.priceTemplate({\n                    data: {\n                        price: price.toFixed(2)\n                    }\n                });\n            }\n\n            return str;\n        },\n\n        /**\n         * @param {Object} element\n         */\n        clearSelect: function (element) {\n            var i;\n\n            for (i = element.options.length - 1; i >= 0; i--) {\n                element.remove(i);\n            }\n        },\n\n        /**\n         * @param {*} attributeId\n         * @return {*|undefined}\n         */\n        getAttributeOptions: function (attributeId) {\n            if (this.config.attributes[attributeId]) {\n                return this.config.attributes[attributeId].options;\n            }\n        },\n\n        /**\n         * Reload price.\n         *\n         * @return {undefined|Number}\n         */\n        reloadPrice: function () {\n            var price = 0,\n                oldPrice = 0,\n                inclTaxPrice = 0,\n                exclTaxPrice = 0,\n                i, selected;\n\n            if (this.config.disablePriceReload) {\n                return undefined;\n            }\n\n            for (i = this.settings.length - 1; i >= 0; i--) {\n                selected = this.settings[i].options[this.settings[i].selectedIndex];\n\n                if (selected.config) {\n                    price += parseFloat(selected.config.price);\n                    oldPrice += parseFloat(selected.config.oldPrice);\n                    inclTaxPrice += parseFloat(selected.config.inclTaxPrice);\n                    exclTaxPrice += parseFloat(selected.config.exclTaxPrice);\n                }\n            }\n\n            optionsPrice.changePrice(\n                'config', {\n                    'price': price,\n                    'oldPrice': oldPrice,\n                    'inclTaxPrice': inclTaxPrice,\n                    'exclTaxPrice': exclTaxPrice\n                }\n            );\n            optionsPrice.reload();\n\n            return price;\n        },\n\n        /**\n         * Reload old price.\n         */\n        reloadOldPrice: function () {\n            var price, i, selected;\n\n            if (this.config.disablePriceReload) {\n                return;\n            }\n\n            if ($('old-price-' + this.config.productId)) {\n\n                price = parseFloat(this.config.oldPrice);\n\n                for (i = this.settings.length - 1; i >= 0; i--) {\n                    selected = this.settings[i].options[this.settings[i].selectedIndex];\n\n                    if (selected.config) {\n                        price += parseFloat(selected.config.price);\n                    }\n                }\n\n                if (price < 0) {\n                    price = 0;\n                }\n                price = this.formatPrice(price);\n\n                if ($('old-price-' + this.config.productId)) {\n                    $('old-price-' + this.config.productId).innerHTML = price;\n                }\n\n            }\n        }\n    };\n});\n","Magento_ConfigurableProduct/js/configurable-type-handler.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_Catalog/catalog/type-events',\n    'collapsible',\n    'Magento_Ui/js/modal/modal',\n    'mage/translate',\n    'domReady!'\n], function ($, productType) {\n    'use strict';\n\n    return {\n        $block: null,\n        hasVariations: null,\n        configurationSectionMessageHandler: (function () {\n            var title = $('[data-role=\"product-create-configuration-info\"]'),\n                buttons = $('[data-action=\"product-create-configuration-buttons\"]'),\n                newText = 'Configurations cannot be created for a standard product with downloadable files.' +\n                ' To create configurations, first remove all downloadable files.',\n                oldText = title.text();\n\n            return function (change) {\n                if (change) {\n                    title.text(newText);\n                    buttons.hide();\n                } else {\n                    title.text(oldText);\n                    buttons.show();\n                }\n            };\n        }()),\n\n        /**\n         * Set element disabled\n         * @param {Object} $element - jquery instance element\n         * @param {Bool} state\n         * @param {Bool} triggerEvent\n         * @private\n         */\n        _setElementDisabled: function ($element, state, triggerEvent) {\n            if (!$element.is('[data-locked]')) {\n                $element.prop('disabled', state);\n\n                if (triggerEvent) {\n                    $element.trigger('change');\n                }\n            }\n        },\n\n        /**\n         * Show\n         */\n        show: function () {\n            this.configurationSectionMessageHandler(false);\n        },\n\n        /**\n         * Hide\n         */\n        hide: function () {\n            this.configurationSectionMessageHandler(true);\n        },\n\n        /**\n         * Bind all\n         */\n        bindAll: function () {\n            $(document).on('changeConfigurableTypeProduct', function (event, isConfigurable) {\n                $(document).trigger('setTypeProduct', isConfigurable ?\n                    'configurable' :\n                    productType.type.init === 'configurable' ? 'simple' : productType.type.init\n                );\n            });\n            $(document).on('changeTypeProduct', this._initType.bind(this));\n        },\n\n        /**\n         * Init type\n         * @private\n         */\n        _initType: function () {\n\n            /*var suggestContainer = $('#product-template-suggest-container .action-dropdown > .action-toggle');\n\n\n            if (productType.type.current === 'configurable') {\n                this._setElementDisabled(suggestContainer.addClass('disabled'), true);\n                this._setElementDisabled($('#inventory_qty'), true);\n                this._setElementDisabled($('#inventory_stock_availability'), false);\n                this._setElementDisabled($('#qty'), true, true);\n                this._setElementDisabled($('#quantity_and_stock_status'), false, false);\n            } else {\n                this._setElementDisabled(suggestContainer.removeClass('disabled'), false);\n                this._setElementDisabled($('#inventory_qty'), false);\n                this._setElementDisabled($('#inventory_stock_availability'), true);\n                this._setElementDisabled($('#qty'), false, true);\n            }\n            */\n\n            /*if (['simple', 'virtual', 'configurable'].indexOf(productType.type.current) < 0) {\n                this.hide();\n            } else {\n                this.show();\n            }*/\n\n            this.show();\n        },\n\n        /**\n         * Constructor component\n         * @param {Object} data - this backend data\n         */\n        'Magento_ConfigurableProduct/js/configurable-type-handler': function (data) {\n            this.$block = $(data.blockId + ' input[name=\"attributes[]\"]');\n            this.hasVariations = data.hasVariations;\n\n            //advancedPricingHandler.init();\n            //priceTypeHandler.init();\n\n            /*if (productType.type.init === 'configurable' && !this.hasVariations) {\n                $(document).trigger('setTypeProduct', 'simple');\n            }*/\n            $(document).trigger('setTypeProduct', 'simple');\n\n            this.bindAll();\n            this._initType();\n        }\n    };\n});\n","Magento_ConfigurableProduct/js/components/associated-product-insert-listing.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'Magento_Ui/js/form/components/insert-listing'\n], function (_, insertListing) {\n    'use strict';\n\n    return insertListing.extend({\n        defaults: {\n            gridInitialized: false,\n            paramsUpdated: false,\n            showMassActionColumn: true,\n            currentProductId: 0,\n            dataScopeAssociatedProduct: 'data.associated_product_ids',\n            typeGrid: '',\n            product: {},\n            rowIndexForChange: undefined,\n            changeProductData: [],\n            modules: {\n                productsProvider: '${ $.productsProvider }',\n                productsColumns: '${ $.productsColumns }',\n                productsMassAction: '${ $.productsMassAction }',\n                modalWithGrid: '${ $.modalWithGrid }',\n                productsFilters: '${ $.productsFilters }'\n            },\n            exports: {\n                externalProviderParams: '${ $.externalProvider }:params'\n            },\n            links: {\n                changeProductData: '${ $.provider }:${ $.changeProductProvider }'\n            },\n            listens: {\n                '${ $.externalProvider }:params': '_setFilters _setVisibilityMassActionColumn',\n                '${ $.productsProvider }:data': '_handleManualGridOpening',\n                '${ $.productsMassAction }:selected': '_handleManualGridSelect'\n            }\n        },\n\n        /**\n         * Initialize observables.\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super().observe(\n                'changeProductData'\n            );\n\n            return this;\n        },\n\n        /**\n         * Get ids of used products.\n         *\n         * @returns {Array}\n         */\n        getUsedProductIds: function () {\n            var usedProductsIds = this.source.get(this.dataScopeAssociatedProduct);\n\n            return usedProductsIds.slice();\n        },\n\n        /**\n         * Request for render content.\n         *\n         * @returns {Object}\n         */\n        doRender: function (showMassActionColumn, typeGrid) {\n            this.typeGrid = typeGrid;\n            this.showMassActionColumn = showMassActionColumn;\n\n            if (this.gridInitialized) {\n                this.paramsUpdated = false;\n                this.productsFilters().clear();\n                this._setFilters(this.externalProviderParams);\n                this._setVisibilityMassActionColumn();\n            }\n\n            return this.render();\n        },\n\n        /**\n         * Show grid with assigned product.\n         *\n         * @returns {Object}\n         */\n        showGridAssignProduct: function () {\n            this.product = {};\n            this.rowIndexForChange = undefined;\n\n            return this.doRender(true, 'assignProduct');\n        },\n\n        /**\n         * Show grid with changed product.\n         *\n         * @param {String} rowIndex\n         * @param {String} product\n         */\n        showGridChangeProduct: function (rowIndex, product) {\n            this.rowIndexForChange = rowIndex;\n            this.product = product;\n            this.doRender(false, 'changeProduct');\n        },\n\n        /**\n         * Select product.\n         *\n         * @param {String} rowIndex\n         */\n        selectProduct: function (rowIndex) {\n            this.changeProductData({\n                rowIndex: this.rowIndexForChange,\n                product: this.productsProvider().data.items[rowIndex]\n            });\n            this.modalWithGrid().closeModal();\n        },\n\n        /**\n         * Set visibility state for mass action column\n         *\n         * @private\n         */\n        _setVisibilityMassActionColumn: function () {\n            this.productsMassAction(function (massActionComponent) {\n                this.productsColumns().elems().each(function (rowElement) {\n                    rowElement.disableAction = this.showMassActionColumn;\n                }, this);\n                massActionComponent.visible = this.showMassActionColumn;\n            }.bind(this));\n        },\n\n        /**\n         * Set filters.\n         *\n         * @param {Object} params\n         * @private\n         */\n        _setFilters: function (params) {\n            var filterModifier = {},\n                attrCodes,\n                usedProductIds,\n                attributes;\n\n            params = _.omit(params);\n\n            if (!this.paramsUpdated) {\n                this.gridInitialized = true;\n                this.paramsUpdated = true;\n\n                attrCodes = this._getAttributesCodes();\n                usedProductIds = this.getUsedProductIds();\n\n                if (this.currentProductId) {\n                    usedProductIds.push(this.currentProductId);\n                }\n\n                filterModifier['entity_id'] = {\n                    'condition_type': 'nin', value: usedProductIds\n                };\n                attrCodes.each(function (code) {\n                    filterModifier[code] = {\n                        'condition_type': 'notnull'\n                    };\n                });\n\n                if (this.typeGrid === 'changeProduct') {\n                    attributes = JSON.parse(this.product.attributes);\n\n                    filterModifier = _.extend(filterModifier, _.mapObject(attributes, function (value) {\n                        return {\n                            'condition_type': 'eq',\n                            'value': value\n                        };\n                    }));\n\n                    params.filters = attributes;\n                } else {\n                    params.filters = {};\n                }\n\n                params['attributes_codes'] = attrCodes;\n\n                this.set('externalProviderParams', params);\n                this.set('externalFiltersModifier', filterModifier);\n            }\n        },\n\n        /**\n         * Get attribute codes.\n         *\n         * @returns {Array}\n         * @private\n         */\n        _getAttributesCodes: function () {\n            var attrCodes = this.source.get('data.attribute_codes');\n\n            return attrCodes ? attrCodes : [];\n        },\n\n        /**\n         * Get product variations.\n         *\n         * @returns {Array}\n         * @private\n         */\n        _getProductVariations: function () {\n            var matrix = this.source.get('data.configurable-matrix');\n\n            return matrix ? matrix : [];\n        },\n\n        /**\n         * Handle manual grid after opening\n         * @private\n         */\n        _handleManualGridOpening: function (data) {\n            if (data.items.length && this.typeGrid === 'assignProduct') {\n                this.productsColumns().elems().each(function (rowElement) {\n                    rowElement.disableAction = true;\n                });\n\n                this._disableRows(data.items);\n            }\n        },\n\n        /**\n         * Handle manual selection.\n         *\n         * @param {Array} selected\n         * @private\n         */\n        _handleManualGridSelect: function (selected) {\n            var selectedRows,\n                selectedVariationKeys;\n\n            if (this.typeGrid === 'assignProduct') {\n                selectedRows = _.filter(this.productsProvider().data.items, function (row) {\n                    return selected.indexOf(row['entity_id']) !== -1;\n                });\n                selectedVariationKeys = _.values(this._getVariationKeyMap(selectedRows));\n                this._disableRows(this.productsProvider().data.items, selectedVariationKeys, selected);\n            }\n        },\n\n        /**\n         * Disable rows in grid for products with the same variation key\n         *\n         * @param {Array} items\n         * @param {Array} selectedVariationKeys\n         * @param {Array} selected\n         * @private\n         */\n        _disableRows: function (items, selectedVariationKeys, selected) {\n            selectedVariationKeys = selectedVariationKeys === undefined ? [] : selectedVariationKeys;\n            selected = selected === undefined ? [] : selected;\n            this.productsMassAction(function (massaction) {\n                var configurableVariationKeys = _.union(\n                    selectedVariationKeys,\n                    _.pluck(this._getProductVariations(), 'variationKey')\n                    ),\n                    variationKeyMap = this._getVariationKeyMap(items),\n                    rowsForDisable = _.keys(_.pick(\n                        variationKeyMap,\n                        function (variationKey) {\n                            return configurableVariationKeys.indexOf(variationKey) !== -1;\n                        }\n                    ));\n\n                massaction.disabled(_.difference(rowsForDisable, selected));\n            }.bind(this));\n        },\n\n        /**\n         * Get variation key map used in manual grid.\n         *\n         * @param {Array} items\n         * @returns {Array} [{entity_id: variation-key}, ...]\n         * @private\n         */\n        _getVariationKeyMap: function (items) {\n            var variationKeyMap = {};\n\n            _.each(items, function (row) {\n                variationKeyMap[row['entity_id']] = _.values(\n                    _.pick(row, this._getAttributesCodes())\n                ).sort().join('-');\n\n            }, this);\n\n            return variationKeyMap;\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/components/modal-configurable.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Ui/js/modal/modal-component',\n    'uiRegistry',\n    'underscore'\n], function (Modal, registry, _) {\n    'use strict';\n\n    return Modal.extend({\n        defaults: {\n            stepWizard: '',\n            modules: {\n                form: '${ $.formName }'\n            }\n        },\n\n        /**\n         * Open modal\n         */\n        openModal: function () {\n            var stepWizard = {};\n\n            this.form().validate();\n\n            if (this.form().source.get('params.invalid') === false) {\n                stepWizard = registry.get('index = ' + this.stepWizard);\n\n                if (!_.isUndefined(stepWizard)) {\n                    stepWizard.open();\n                }\n\n                this._super();\n            }\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/components/dynamic-rows-configurable.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/dynamic-rows/dynamic-rows',\n    'jquery'\n], function (_, registry, dynamicRows, $) {\n    'use strict';\n\n    return dynamicRows.extend({\n        defaults: {\n            actionsListOpened: false,\n            canEditField: 'canEdit',\n            newProductField: 'newProduct',\n            dataScopeAssociatedProduct: 'data.associated_product_ids',\n            dataProviderFromGrid: '',\n            dataProviderChangeFromGrid: '',\n            insertDataFromGrid: [],\n            changeDataFromGrid: [],\n            dataProviderFromWizard: '',\n            insertDataFromWizard: [],\n            map: null,\n            isEmpty: true,\n            isShowAddProductButton: false,\n            cacheGridData: [],\n            unionInsertData: [],\n            deleteProperty: false,\n            dataLength: 0,\n            identificationProperty: 'id',\n            'attribute_set_id': '',\n            attributesTmp: [],\n            changedFlag: 'was_changed',\n            listens: {\n                'insertDataFromGrid': 'processingInsertDataFromGrid',\n                'insertDataFromWizard': 'processingInsertDataFromWizard',\n                'unionInsertData': 'processingUnionInsertData',\n                'changeDataFromGrid': 'processingChangeDataFromGrid',\n                'isEmpty': 'changeVisibility'\n            },\n            imports: {\n                'attribute_set_id': '${$.provider}:data.product.attribute_set_id'\n            },\n            'exports': {\n                'attribute_set_id': '${$.provider}:data.new-variations-attribute-set-id'\n            },\n            modules: {\n                modalWithGrid: '${ $.modalWithGrid }',\n                gridWithProducts: '${ $.gridWithProducts}'\n            }\n        },\n\n        /**\n         * Invokes initialize method of parent class,\n         * contains initialization logic\n         */\n        initialize: function () {\n            this._super()\n                .changeVisibility(this.isEmpty());\n\n            return this;\n        },\n\n        /**\n         * Change visibility\n         *\n         * When isEmpty = true, then visbible = false\n         *\n         * @param {Boolean} isEmpty\n         */\n        changeVisibility: function (isEmpty) {\n            this.visible(!isEmpty);\n        },\n\n        /**\n         * Open modal with grid.\n         *\n         * @param {String} rowIndex\n         */\n        openModalWithGrid: function (rowIndex) {\n            var productSource = this.source.get(this.dataScope + '.' + this.index + '.' + rowIndex),\n                product = {\n                    'id': productSource.id,\n                    'attributes': productSource['configurable_attribute']\n                };\n\n            this.modalWithGrid().openModal();\n            this.gridWithProducts().showGridChangeProduct(rowIndex, product);\n        },\n\n        /**\n         * Initialize children\n         *\n         * @returns {Object} Chainable.\n         */\n        initChildren: function () {\n            var tmpArray = [];\n\n            this.recordData.each(function (recordData) {\n                tmpArray.push(recordData);\n            }, this);\n\n            this.unionInsertData(tmpArray);\n\n            return this;\n        },\n\n        /**\n         * Delete record\n         *\n         * @param {Number} index - row index\n         */\n        deleteRecord: function (index) {\n            var tmpArray,\n                lastRecord;\n\n            this.reRender = false;\n            tmpArray = this.getUnionInsertData();\n            tmpArray.splice(index, 1);\n\n            if (!tmpArray.length) {\n                this.attributesTmp = this.source.get('data.attributes');\n                this.source.set('data.attributes', []);\n                this.cacheGridData = [];\n            }\n\n            if (parseInt(this.currentPage(), 10) === this.pages()) {\n                lastRecord =\n                    _.findWhere(this.elems(), {\n                        index: this.startIndex + this.getChildItems().length - 1\n                    }) ||\n                    _.findWhere(this.elems(), {\n                        index: (this.startIndex + this.getChildItems().length - 1).toString()\n                    });\n\n                lastRecord.destroy();\n            }\n\n            this.unionInsertData(tmpArray);\n\n            if (this.pages() < parseInt(this.currentPage(), 10)) {\n                this.currentPage(this.pages());\n            }\n\n            this.reRender = true;\n            this.showSpinner(false);\n        },\n\n        /**\n         * Generate associated products\n         */\n        generateAssociatedProducts: function () {\n            var productsIds = [];\n\n            this.getUnionInsertData().forEach(function (data) {\n                if (data.id !== null) {\n                    productsIds.push(data.id);\n                }\n            });\n\n            this.source.set(this.dataScopeAssociatedProduct, productsIds);\n        },\n\n        /**\n         * Calls 'initObservable' of parent\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe([\n                    'insertDataFromGrid', 'unionInsertData', 'isEmpty', 'isShowAddProductButton', 'actionsListOpened'\n                ]);\n\n            return this;\n        },\n\n        /**\n         * Get union insert data from source\n         *\n         * @returns {Array}\n         */\n        getUnionInsertData: function () {\n            var source = this.source.get(this.dataScope + '.' + this.index),\n                result = [];\n\n            _.each(source, function (data) {\n                result.push(data);\n            });\n\n            return result;\n        },\n\n        /**\n         * Process union insert data.\n         *\n         * @param {Array} data\n         */\n        processingUnionInsertData: function (data) {\n            var dataCount,\n                elemsCount,\n                tmpData,\n                path,\n                attributeCodes = this.source.get('data.attribute_codes');\n\n            this.isEmpty(data.length === 0);\n            this.isShowAddProductButton(\n                (!attributeCodes || data.length > 0 ? data.length : attributeCodes.length) > 0\n            );\n\n            tmpData = data.slice(this.pageSize * (this.currentPage() - 1),\n                                 this.pageSize * (this.currentPage() - 1) + this.pageSize);\n\n            this.source.set(this.dataScope + '.' + this.index, []);\n\n            _.each(tmpData, function (row, index) {\n                path = this.dataScope + '.' + this.index + '.' + (this.startIndex + index);\n                row.attributes = $('<i></i>').text(row.attributes).html();\n                row.sku = $('<i></i>').text(row.sku).html();\n                this.source.set(path, row);\n            }, this);\n\n            this.source.set(this.dataScope + '.' + this.index, data);\n            this.parsePagesData(data);\n\n            // Render\n            dataCount = data.length;\n            elemsCount = this.elems().length;\n\n            if (dataCount > elemsCount) {\n                this.getChildItems().each(function (elemData, index) {\n                    this.addChild(elemData, this.startIndex + index);\n                }, this);\n            } else {\n                for (elemsCount; elemsCount > dataCount; elemsCount--) {\n                    this.elems()[elemsCount - 1].destroy();\n                }\n            }\n\n            this.generateAssociatedProducts();\n        },\n\n        /**\n         * Parsed data\n         *\n         * @param {Array} data - array with data\n         * about selected records\n         */\n        processingInsertDataFromGrid: function (data) {\n            var changes,\n                tmpArray;\n\n            if (!data.length) {\n                return;\n            }\n\n            tmpArray = this.getUnionInsertData();\n\n            changes = this._checkGridData(data);\n            this.cacheGridData = data;\n\n            changes.each(function (changedObject) {\n                var mappedData = this.mappingValue(changedObject);\n\n                mappedData[this.canEditField] = 0;\n                mappedData[this.newProductField] = 0;\n                mappedData.variationKey = this._getVariationKey(changedObject);\n                mappedData['configurable_attribute'] = this._getConfigurableAttribute(changedObject);\n                tmpArray.push(mappedData);\n            }, this);\n\n            // Attributes cannot be changed before regeneration thought wizard\n            if (!this.source.get('data.attributes').length) {\n                this.source.set('data.attributes', this.attributesTmp);\n            }\n            this.unionInsertData(tmpArray);\n        },\n\n        /**\n         * Process changes from grid.\n         *\n         * @param {Object} data\n         */\n        processingChangeDataFromGrid: function (data) {\n            var tmpArray = this.getUnionInsertData(),\n                mappedData = this.mappingValue(data.product);\n\n            mappedData[this.canEditField] = 0;\n            mappedData[this.newProductField] = 0;\n            mappedData.variationKey = this._getVariationKey(data.product);\n            mappedData['configurable_attribute'] = this._getConfigurableAttribute(data.product);\n            tmpArray[data.rowIndex] = mappedData;\n\n            this.unionInsertData(tmpArray);\n        },\n\n        /**\n         * Get variation key.\n         *\n         * @param {Object} data\n         * @returns {String}\n         * @private\n         */\n        _getVariationKey: function (data) {\n            var attrCodes = this.source.get('data.attribute_codes'),\n                key = [];\n\n            attrCodes.each(function (code) {\n                key.push(data[code]);\n            });\n\n            return key.sort().join('-');\n        },\n\n        /**\n         * Get configurable attribute.\n         *\n         * @param {Object} data\n         * @returns {String}\n         * @private\n         */\n        _getConfigurableAttribute: function (data) {\n            var attrCodes = this.source.get('data.attribute_codes'),\n                confAttrs = {};\n\n            attrCodes.each(function (code) {\n                confAttrs[code] = data[code];\n            });\n\n            return JSON.stringify(confAttrs);\n        },\n\n        /**\n         * Process data insertion from wizard\n         *\n         * @param {Object} data\n         */\n        processingInsertDataFromWizard: function (data) {\n            var tmpArray = this.getUnionInsertData(),\n                productIdsToDelete = this.source.get(this.dataScopeAssociatedProduct),\n                index,\n                product = {};\n\n            tmpArray = this.unsetArrayItem(\n                tmpArray,\n                {\n                    id: null\n                }\n            );\n\n            _.each(data, function (row) {\n                if (row.productId) {\n                    index = _.indexOf(productIdsToDelete, row.productId);\n\n                    if (index > -1) {\n                        productIdsToDelete.splice(index, 1);\n                        tmpArray = this.unsetArrayItem(\n                            tmpArray,\n                            {\n                                id: row.productId\n                            }\n                        );\n                    }\n                }\n                product = this.getProductData(row);\n\n                product[this.changedFlag] = true;\n                product[this.canEditField] = row.editable;\n                product[this.newProductField] = row.newProduct;\n                tmpArray.push(product);\n            }, this);\n\n            _.each(productIdsToDelete, function (id) {\n                tmpArray = this.unsetArrayItem(\n                    tmpArray,\n                    {\n                        id: id\n                    }\n                );\n            }, this);\n\n            this.unionInsertData(tmpArray);\n        },\n\n        /**\n         *\n         * @param {Object} row\n         * @returns {Object}\n         */\n        getProductData: function (row) {\n            var product,\n                attributesText = '';\n\n            _.each(row.options, function (attribute) {\n                if (attributesText) {\n                    attributesText += ', ';\n                }\n                attributesText += attribute['attribute_label'] + ': ' + attribute.label;\n            }, this);\n\n            product = {\n                'id': row.productId,\n                'product_link': row.productUrl,\n                'name': $('<i></i>').text(row.name).html(),\n                'sku': $('<i></i>').text(row.sku).html(),\n                'status': row.status,\n                'price': row.price,\n                'price_currency': row.priceCurrency,\n                'price_string': row.priceCurrency + row.price,\n                'weight': row.weight,\n                'qty': row.quantity,\n                'variationKey': row.variationKey,\n                'configurable_attribute': row.attribute,\n                'thumbnail_image': row.images.preview,\n                'media_gallery': row['media_gallery'],\n                'swatch_image': row['swatch_image'],\n                'small_image': row['small_image'],\n                image: row.image,\n                'thumbnail': row.thumbnail,\n                'attributes': attributesText\n            };\n\n            return product;\n        },\n\n        /**\n         * Remove array items matching condition.\n         *\n         * @param {Array} data\n         * @param {Object} condition\n         * @returns {Array}\n         */\n        unsetArrayItem: function (data, condition) {\n            var objs = _.where(data, condition);\n\n            _.each(objs, function (obj) {\n                var index = _.indexOf(data, obj);\n\n                if (index > -1) {\n                    data.splice(index, 1);\n                }\n            });\n\n            return data;\n        },\n\n        /**\n         * Check changed records\n         *\n         * @param {Array} data - array with records data\n         * @returns {Array} Changed records\n         */\n        _checkGridData: function (data) {\n            var cacheLength = this.cacheGridData.length,\n                curData = data.length,\n                max = cacheLength > curData ? this.cacheGridData : data,\n                changes = [],\n                obj = {};\n\n            max.each(function (record, index) {\n                obj[this.map.id] = record[this.map.id];\n\n                if (!_.where(this.cacheGridData, obj).length) {\n                    changes.push(data[index]);\n                }\n            }, this);\n\n            return changes;\n        },\n\n        /**\n         * Mapped value\n         */\n        mappingValue: function (data) {\n            var result = {};\n\n            _.each(this.map, function (prop, index) {\n                result[index] = data[prop];\n            });\n\n            return result;\n        },\n\n        /**\n         * Toggle actions list.\n         *\n         * @param {Number} rowIndex\n         * @returns {Object} Chainable.\n         */\n        toggleActionsList: function (rowIndex) {\n            var state = false;\n\n            if (rowIndex !== this.actionsListOpened()) {\n                state = rowIndex;\n            }\n            this.actionsListOpened(state);\n\n            return this;\n        },\n\n        /**\n         * Close action list.\n         *\n         * @param {Number} rowIndex\n         * @returns {Object} Chainable\n         */\n        closeList: function (rowIndex) {\n            if (this.actionsListOpened() === rowIndex) {\n                this.actionsListOpened(false);\n            }\n\n            return this;\n        },\n\n        /**\n         * Toggle product status.\n         *\n         * @param {Number} rowIndex\n         */\n        toggleStatusProduct: function (rowIndex) {\n            var tmpArray = this.getUnionInsertData(),\n                status = parseInt(tmpArray[rowIndex].status, 10);\n\n            if (status === 1) {\n                tmpArray[rowIndex].status = 2;\n            } else {\n                tmpArray[rowIndex].status = 1;\n            }\n\n            tmpArray[rowIndex][this.changedFlag] = true;\n            this.unionInsertData(tmpArray);\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/components/custom-options-warning.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Ui/js/form/components/html'\n], function (Html) {\n    'use strict';\n\n    return Html.extend({\n        defaults: {\n            isConfigurable: false\n        },\n\n        /**\n         * Updates component visibility state.\n         *\n         * @param {Boolean} variationsEmpty\n         * @returns {Boolean}\n         */\n        updateVisibility: function (variationsEmpty) {\n            var isVisible = this.isConfigurable || !variationsEmpty;\n\n            this.visible(isVisible);\n\n            return isVisible;\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/components/file-uploader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'Magento_Ui/js/form/element/file-uploader',\n    'underscore'\n], function (Element, _) {\n    'use strict';\n\n    return Element.extend({\n        processedFile: {},\n        actionsListOpened: false,\n        thumbnailUrl: '',\n        thumbnail: null,\n        smallImage: null,\n        defaults: {\n            fileInputName: ''\n        },\n\n        /**\n         * Initialize observables.\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super().observe(['processedFile', 'actionsListOpened', 'thumbnailUrl', 'thumbnail', 'smallImage']);\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        setInitialValue: function () {\n            var value = this.getInitialValue();\n\n            if (!_.isString(value)) {\n                this._super();\n            }\n\n            return this;\n        },\n\n        /**\n         * Adds provided file to the files list.\n         *\n         * @param {Object} file\n         * @returns {Object} Chainable.\n         */\n        addFile: function (file) {\n            this.processedFile(this.processFile(file));\n\n            this.value(this.processedFile().file);\n\n            return this;\n        },\n\n        /**\n         * Toggle actions list.\n         *\n         * @returns {Object} Chainable.\n         */\n        toggleActionsList: function () {\n            if (this.actionsListOpened()) {\n                this.actionsListOpened(false);\n            } else {\n                this.actionsListOpened(true);\n            }\n\n            return this;\n        },\n\n        /**\n         * Close action list.\n         *\n         * @returns {Object} Chainable\n         */\n        closeList: function () {\n            if (this.actionsListOpened()) {\n                this.actionsListOpened(false);\n            }\n\n            return this;\n        },\n\n        /**\n         * Delete Image\n         *\n         * @returns {Object} Chainable\n         */\n        deleteImage: function () {\n            this.processedFile({});\n            this.value(null);\n            this.thumbnail(null);\n            this.thumbnailUrl(null);\n            this.smallImage(null);\n\n            return this;\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/components/price-configurable.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore',\n    'uiRegistry',\n    'Magento_Ui/js/form/element/abstract'\n], function (_, registry, Abstract) {\n    'use strict';\n\n    return Abstract.extend({\n        defaults: {\n            imports: {\n                isConfigurable: '!ns = ${ $.ns }, index = configurable-matrix:isEmpty'\n            },\n            modules: {\n                createConfigurableButton: '${$.createConfigurableButton}'\n            }\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super();\n            // resolve initial disable state\n            this.handlePriceValue(this.isConfigurable);\n            // add listener to track \"configurable\" type\n            this.setListeners({\n                isConfigurable: 'handlePriceValue'\n            });\n\n            return this;\n        },\n\n        /**\n         * Calls 'initObservable' of parent\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe(['content']);\n\n            return this;\n        },\n\n        /**\n         * Disable and clear price if product type changed to configurable\n         *\n         * @param {String} isConfigurable\n         */\n        handlePriceValue: function (isConfigurable) {\n            this.disabled(!!this.isUseDefault() || isConfigurable);\n\n            if (isConfigurable) {\n                this.clear();\n            }\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/components/container-configurable-handler.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent'\n], function (Element) {\n    'use strict';\n\n    return Element.extend({\n        defaults: {\n            listens: {\n                '${ $.provider }:data.is_downloadable': 'handleProductType'\n            },\n            links: {\n                isDownloadable: '${ $.provider }:data.is_downloadable'\n            },\n            modules: {\n                createConfigurableButton: '${$.createConfigurableButton}'\n            }\n        },\n\n        /**\n         * Invokes initialize method of parent class,\n         * contains initialization logic\n         */\n        initialize: function () {\n            this._super();\n            this.handleProductType(this.isDownloadable);\n\n            return this;\n        },\n\n        /**\n         * Calls 'initObservable' of parent\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super()\n                .observe(['content']);\n\n            return this;\n        },\n\n        /**\n         * Change content for container and visibility for button\n         *\n         * @param {String} isDownloadable\n         */\n        handleProductType: function (isDownloadable) {\n            if (isDownloadable === '1') {\n                this.content(this.content2);\n\n                if (this.createConfigurableButton()) {\n                    this.createConfigurableButton().visible(false);\n                }\n            } else {\n                this.content(this.content1);\n\n                if (this.createConfigurableButton()) {\n                    this.createConfigurableButton().visible(true);\n                }\n            }\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/components/custom-options-price-type.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'Magento_Catalog/js/components/custom-options-price-type'\n], function (_, PriceType) {\n    'use strict';\n\n    return PriceType.extend({\n        defaults: {\n            isConfigurable: false,\n            isFiltered: null,\n            defaultOptions: null,\n            filteredOptions: null,\n            bannedOptions: []\n        },\n\n        /**\n         * Updates options.\n         *\n         * @param {Boolean} variationsEmpty\n         * @returns {Boolean}\n         */\n        updateOptions: function (variationsEmpty) {\n            var isFiltered = this.isConfigurable || !variationsEmpty,\n                value;\n\n            if (this.isFiltered !== isFiltered) {\n                value = this.value();\n\n                this.options(isFiltered ? this.getFilteredOptions() : this.getDefaultOptions());\n                this.value(value);\n            }\n\n            return isFiltered;\n        },\n\n        /**\n         * Get default list of options.\n         *\n         * @returns {Array}\n         */\n        getDefaultOptions: function () {\n            if (this.defaultOptions === null) {\n                this.defaultOptions = this.options();\n            }\n\n            return this.defaultOptions;\n        },\n\n        /**\n         * Get filtered list of options.\n         *\n         * @returns {Array}\n         */\n        getFilteredOptions: function () {\n            var defaultOptions;\n\n            if (this.filteredOptions === null) {\n                defaultOptions = this.getDefaultOptions();\n                this.filteredOptions = [];\n\n                _.each(defaultOptions, function (option) {\n                    if (this.bannedOptions.indexOf(option.value) === -1) {\n                        this.filteredOptions.push(option);\n                    }\n                }, this);\n            }\n\n            return this.filteredOptions;\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/options/price-type-handler.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/*\ndefine([\n    'jquery',\n    'Magento_Catalog/catalog/type-events',\n    'notification',\n    'mage/translate'\n], function ($, productType) {\n    'use strict';\n\n    return {\n        isConfigurable: false,\n        messageInited: false,\n        messageSelector: '[data-role=product-custom-options-content]',\n        isPercentPriceTypeExist: function () {\n            var productOptionsContainer = $('#product_options_container_top');\n\n            return !!productOptionsContainer.length;\n        },\n        showWarning: function () {\n            if (!this.messageInited) {\n                $(this.messageSelector).notification();\n                this.messageInited = true;\n            }\n            this.hideWarning();\n            $(this.messageSelector).notification('add', {\n                message: $.mage.__('Custom options with price type \"percent\" is not available for ' +\n                    'configurable product.'),\n                error: false,\n                messageContainer: this.messageSelector\n            });\n        },\n        hideWarning: function () {\n            $(this.messageSelector).notification('clear');\n        },\n        init: function () {\n            $(document).on('changeTypeProduct', this._initType.bind(this));\n\n            $('#product-edit-form-tabs').on('change', '.opt-type > select', function () {\n                var selected = $('.opt-type > select :selected'),\n                    optGroup = selected.parent().attr('label');\n\n                if (optGroup === 'Select') {\n                    $('#product-edit-form-tabs').on(\n                        'click',\n                        '[data-ui-id=\"admin-product-options-options-box-select-option-type-add-select-row-button\"]',\n                        function () {\n                            this.percentPriceTypeHandler();\n                        }.bind(this)\n                    );\n                } else {\n                    this.percentPriceTypeHandler();\n                }\n            }.bind(this));\n\n            this._initType();\n        },\n        _initType: function () {\n            this.isConfigurable = productType.type.current === 'configurable';\n            if (this.isPercentPriceTypeExist()) {\n                this.percentPriceTypeHandler();\n            }\n        },\n        percentPriceTypeHandler: function () {\n            var priceType = $('[data-attr=\"price-type\"]'),\n                optionPercentPriceType = priceType.find('option[value=\"percent\"]');\n\n            if (this.isConfigurable) {\n                this.showWarning();\n                optionPercentPriceType.hide();\n                optionPercentPriceType.parent().val() === 'percent' ? optionPercentPriceType.parent().val('fixed') : '';\n            } else {\n                $(this.messageSelector).notification();\n                optionPercentPriceType.show();\n                this.hideWarning();\n            }\n        }\n    };\n});\n*/\n","Magento_ConfigurableProduct/js/variations/product-grid.js":"// jscs:disable requireDotNotation\n/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'jquery',\n    'Magento_Ui/js/core/app',\n    'underscore',\n    'notification',\n    'mage/translate'\n], function (Component, $, bootstrap, _) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            productsGridUrl: null,\n            productAttributes: [],\n            productsModal: null,\n            button: '',\n            gridSelector: '[data-grid-id=associated-products-container]',\n            modules: {\n                productsFilter: '${ $.productsFilter }',\n                productsProvider: '${ $.productsProvider }',\n                productsMassAction: '${ $.productsMassAction }',\n                productsColumns: '${ $.productsColumns }',\n                variationsComponent: '${ $.configurableVariations }'\n            },\n            listens: {\n                '${ $.productsProvider }:data': '_showMessageAssociatedGrid _handleManualGridOpening',\n                '${ $.productsMassAction }:selected': '_handleManualGridSelect',\n                '${ $.configurableVariations }:productMatrix': '_showButtonAddManual _switchProductType'\n            }\n        },\n\n        /**\n         * Initialize\n         *\n         * @param {Array} options\n         */\n        initialize: function (options) {\n            this._super(options);\n            this.productsModal = $(this.gridSelector).modal({\n                title: $.mage.__('Select Associated Product'),\n                type: 'slide',\n                buttons: [\n                    {\n                        text: $.mage.__('Cancel'),\n\n                        /** Close modal */\n                        click: function () {\n                            this.closeModal();\n                        }\n                    }, {\n                        text: $.mage.__('Done'),\n                        click: this.close.bind(this, null)\n                    }\n                ]\n            });\n\n            this.productsProvider(function () {\n                this.productsModal.notification();\n            }.bind(this));\n            this.variationsComponent(function (variation) {\n                this._showButtonAddManual(variation.productMatrix());\n            }.bind(this));\n\n            this._initGrid = _.once(this._initGrid);\n            this._switchProductType = _.wrap(this._switchProductType.bind(this), function (func, params) {\n                if (!!params.length !== !!this.init) {\n                    this.init = !!params.length;\n                    func(params);\n                }\n            }.bind(this._switchProductType));\n        },\n\n        /**\n         * Initial observerable\n         * @returns {*}\n         */\n        initObservable: function () {\n            this._super().observe('button');\n\n            return this;\n        },\n\n        /**\n         * init Grid\n         * @private\n         */\n        _initGrid: function (filterData) {\n            $.ajax({\n                type: 'GET',\n                url: this._buildGridUrl(filterData),\n                context: $('body')\n            }).done(function (data) {\n                bootstrap(JSON.parse(data));\n            });\n        },\n\n        /**\n         * Select different product in configurations section\n         * @see configurable_associated_product_listing.xml\n         * @param {Integer} rowIndex\n         */\n        selectProduct: function (rowIndex) {\n            this.close(rowIndex);\n        },\n\n        /**\n         * Open\n         * @param {Object} filterData - filter data\n         * @param {Object|*} filterData.filters - attribute name\n         * @param {Object|*} filterData.filters_modifier - modifier value\n         * @param {String} callbackName\n         * @param {Boolean} showMassActionColumn\n         */\n        open: function (filterData, callbackName, showMassActionColumn) {\n            this.callbackName = callbackName;\n            this.productsMassAction(function (massActionComponent) {\n                this.productsColumns().elems().each(function (rowElement) {\n                    rowElement.disableAction = showMassActionColumn;\n                });\n                massActionComponent.visible = showMassActionColumn;\n            }.bind(this));\n            this._setFilter(filterData);\n            this._initGrid(filterData);\n            this.productsModal.trigger('openModal');\n        },\n\n        /**\n         * Close\n         */\n        close: function (rowIndex) {\n            try {\n                if (this.productsMassAction().selected.getLength()) {\n                    this.variationsComponent()[this.callbackName](this.productsMassAction()\n                        .selected.map(this.getProductById.bind(this)));\n                    this.productsMassAction().deselectAll();\n                } else if (!_.isNull(rowIndex)) {\n                    this.variationsComponent()[this.callbackName]([this.getProductByIndex(rowIndex)]);\n                }\n                this.productsModal.trigger('closeModal');\n            } catch (e) {\n                if (e.name === 'UserException') {\n                    this.productsModal.notification('clear');\n                    this.productsModal.notification('add', {\n                        message: e.message,\n                        messageContainer: this.gridSelector\n                    });\n                } else {\n                    throw e;\n                }\n            }\n        },\n\n        /**\n         * Get product by id\n         * @param {Integer} productId\n         * @returns {*}\n         */\n        getProductById: function (productId) {\n            return _.findWhere(this.productsProvider().data.items, {\n                'entity_id': productId\n            });\n        },\n\n        /**\n         * Get product\n         * @param {Integer} rowIndex\n         * @returns {*}\n         */\n        getProductByIndex: function (rowIndex) {\n            return this.productsProvider().data.items[rowIndex];\n        },\n\n        /**\n         * Build grid url\n         * @private\n         */\n        _buildGridUrl: function (filterData) {\n            var params = '?' + $.param({\n                'filters': filterData.filters,\n                'attributes_codes': this._getAttributesCodes(),\n                'filters_modifier': filterData['filters_modifier']\n            });\n\n            return this.productsGridUrl + params;\n        },\n\n        /**\n         * Show button add manual\n         * @param {Array} variations\n         * @returns {*}\n         * @private\n         */\n        _showButtonAddManual: function (variations) {\n            return this.button(variations.length);\n        },\n\n        /**\n         * @param {Array} variations\n         * @private\n         */\n        _switchProductType: function (variations) {\n            $(document).trigger('changeConfigurableTypeProduct', variations.length);\n        },\n\n        /**\n         * Get attributes codes used for configurable\n         * @private\n         */\n        _getAttributesCodes: function () {\n            return this.variationsComponent().attributes.pluck('code');\n        },\n\n        /**\n         * Show data associated grid\n         * @private\n         */\n        _showMessageAssociatedGrid: function (data) {\n            this.productsModal.notification('clear');\n\n            if (data.items.length) {\n                this.productsModal.notification('add', {\n                    message: $.mage.__('Choose a new product to delete and replace the current product configuration.'),\n                    messageContainer: this.gridSelector\n                });\n            } else {\n                this.productsModal.notification('add', {\n                    message: $.mage.__('For better results, add attributes and attribute values to your products.'),\n                    messageContainer: this.gridSelector\n                });\n            }\n        },\n\n        /**\n         * Show manually grid\n         */\n        showManuallyGrid: function () {\n            var filterModifier = _.mapObject(_.object(this._getAttributesCodes(), []), function () {\n                    return {\n                        'condition_type': 'notnull'\n                    };\n                }),\n                usedProductIds = _.values(this.variationsComponent().productAttributesMap);\n\n            if (usedProductIds && usedProductIds.length > 0) {\n                filterModifier['entity_id'] = {\n                    'condition_type': 'nin', value: usedProductIds\n                };\n            }\n\n            this.open(\n                {\n                    'filters_modifier': filterModifier\n                },\n                'appendProducts',\n                true\n            );\n        },\n\n        /**\n         * Handle manual grid after opening\n         * @private\n         */\n        _handleManualGridOpening: function (data) {\n            if (data.items.length && this.callbackName == 'appendProducts') { //eslint-disable-line eqeqeq\n                this.productsColumns().elems().each(function (rowElement) {\n                    rowElement.disableAction = true;\n                });\n\n                this._disableRows(data.items);\n            }\n        },\n\n        /**\n         * Disable rows in grid for products with the same variation key\n         *\n         * @param {Array} items\n         * @param {Array} selectedVariationKeys\n         * @param {Array} selected\n         * @private\n         */\n        _disableRows: function (items, selectedVariationKeys, selected) {\n            selectedVariationKeys = selectedVariationKeys === undefined ? [] : selectedVariationKeys;\n            selected = selected === undefined ? [] : selected;\n            this.productsMassAction(function (massaction) {\n                var configurableVariationKeys = _.union(\n                        selectedVariationKeys,\n                        _.pluck(this.variationsComponent().productMatrix(), 'variationKey')\n                    ),\n                    variationKeyMap = this._getVariationKeyMap(items),\n                    rowsForDisable = _.keys(_.pick(\n                        variationKeyMap,\n                        function (variationKey) {\n                            return configurableVariationKeys.indexOf(variationKey) !== -1;\n                        }\n                    ));\n\n                massaction.disabled(_.difference(rowsForDisable, selected));\n            }.bind(this));\n        },\n\n        /**\n         * @private\n         */\n        _handleManualGridSelect: function (selected) {\n            var selectedRows, selectedVariationKeys;\n\n            if (this.callbackName == 'appendProducts') { //eslint-disable-line eqeqeq\n                selectedRows = _.filter(this.productsProvider().data.items, function (row) {\n                    return selected.indexOf(row['entity_id']) !== -1;\n                });\n                selectedVariationKeys = _.values(this._getVariationKeyMap(selectedRows));\n                this._disableRows(this.productsProvider().data.items, selectedVariationKeys, selected);\n            }\n        },\n\n        /**\n         * Get variation key map used in manual grid.\n         *\n         * @param {Object} items\n         * @returns {Array} [{entity_id: variation-key}, ...]\n         * @private\n         */\n        _getVariationKeyMap: function (items) {\n            this._variationKeyMap = {};\n\n            _.each(items, function (row) {\n                this._variationKeyMap[row['entity_id']] = _.values(\n                    _.pick(row, this._getAttributesCodes())\n                ).sort().join('-');\n\n            }, this);\n\n            return this._variationKeyMap;\n        },\n\n        /**\n         * Set filter\n         * @private\n         */\n        _setFilter: function (filterData) {\n            this.productsProvider(function (provider) {\n                provider.params['filters_modifier'] = filterData['filters_modifier'];\n                provider.params['attributes_codes'] = this._getAttributesCodes();\n            }.bind(this));\n\n            this.productsFilter(function (filter) {\n                filter.set('filters', _.extend({\n                    'filters_modifier': filterData['filters_modifier']\n                }, filterData.filters))\n                    .apply();\n            });\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/variations/variations.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'jquery',\n    'ko',\n    'underscore',\n    'Magento_Ui/js/modal/alert',\n    'uiRegistry',\n    'mage/translate'\n], function (Component, $, ko, _, alert, registry, $t) {\n    'use strict';\n\n    /**\n     * @param {*} message\n     * @constructor\n     */\n    function UserException(message) {\n        this.message = message;\n        this.name = 'UserException';\n    }\n    UserException.prototype = Object.create(Error.prototype);\n\n    return Component.extend({\n        defaults: {\n            opened: false,\n            attributes: [],\n            usedAttributes: [],\n            attributeCodes: [],\n            attributesData: {},\n            productMatrix: [],\n            variations: [],\n            formSaveParams: [],\n            productAttributes: [],\n            disabledAttributes: [],\n            fullAttributes: [],\n            rowIndexToEdit: false,\n            productAttributesMap: null,\n            value: [],\n            modules: {\n                associatedProductGrid: '${ $.configurableProductGrid }',\n                wizardButtonElement: '${ $.wizardModalButtonName }',\n                formElement: '${ $.formName }',\n                attributeSetHandlerModal: '${ $.attributeSetHandler }'\n            },\n            imports: {\n                attributeSetName: '${ $.provider }:configurableNewAttributeSetName',\n                attributeSetId: '${ $.provider }:configurableExistingAttributeSetId',\n                attributeSetSelection: '${ $.provider }:configurableAffectedAttributeSet',\n                productPrice: '${ $.provider }:data.product.price'\n            },\n            links: {\n                value: '${ $.provider }:${ $.dataScopeVariations }',\n                usedAttributes: '${ $.provider }:${ $.dataScopeAttributes }',\n                attributesData: '${ $.provider }:${ $.dataScopeAttributesData }',\n                attributeCodes: '${ $.provider }:${ $.dataScopeAttributeCodes }',\n                skeletonAttributeSet: '${ $.provider }:data.new-variations-attribute-set-id'\n            }\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super();\n\n            this.changeButtonWizard();\n            this.initProductAttributesMap();\n            this.disableConfigurableAttributes(this.productAttributes);\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super().observe(\n                'actions opened attributes productMatrix value usedAttributes attributesData attributeCodes'\n            );\n\n            return this;\n        },\n\n        /**\n         * @param {Object} product\n         * @return {Object}\n         * @private\n         */\n        _makeProduct: function (product) {\n            var productId = product['entity_id'] || product.productId || null,\n                attributes = _.pick(product, this.attributes.pluck('code')),\n                options = _.map(attributes, function (option, attribute) {\n                    var oldOptions = _.findWhere(this.attributes(), {\n                            code: attribute\n                        }).options,\n                        result;\n\n                    if (_.isFunction(oldOptions)) {\n                        result = oldOptions.findWhere({\n                            value: option\n                        });\n                    } else {\n                        result = _.findWhere(oldOptions, {\n                            value: option\n                        });\n                    }\n\n                    return result;\n                }.bind(this));\n\n            return {\n                attribute: JSON.stringify(attributes),\n                editable: false,\n                images: {\n                    preview: product['thumbnail_src']\n                },\n                name: product.name || product.sku,\n                options: options,\n                price: parseFloat(Math.round(product.price.replace(/[^\\d.]+/g, '') + 'e+4') + 'e-4').toFixed(4),\n                productId: productId,\n                productUrl: this.buildProductUrl(productId),\n                quantity: product.quantity || null,\n                sku: product.sku,\n                status: product.status === undefined ? 1 : parseInt(product.status, 10),\n                variationKey: this.getVariationKey(options),\n                weight: product.weight || null\n            };\n        },\n\n        /**\n         * @param {String} name\n         * @return {String|Number|Array}\n         */\n        getProductValue: function (name) {\n            name = name.split('/').join('][');\n\n            return $('[name=\"product[' + name + ']\"]:enabled:not(.ignore-validate)', this.productForm).val();\n        },\n\n        /**\n         * @param {Object} data\n         * @param {String} field\n         * @return {String}\n         */\n        getRowId: function (data, field) {\n            var key = data.variationKey;\n\n            return 'variations-matrix-' + key + '-' + field;\n        },\n\n        /**\n         * @param {Object} variation\n         * @param {String} field\n         * @return {String}\n         */\n        getVariationRowName: function (variation, field) {\n            var result;\n\n            if (variation.productId) {\n                result = 'configurations[' + variation.productId + '][' + field.split('/').join('][') + ']';\n            } else {\n                result = 'variations-matrix[' + variation.variationKey + '][' + field.split('/').join('][') + ']';\n            }\n\n            return result;\n        },\n\n        /**\n         * @param {*} variations\n         * @param {*} attributes\n         */\n        render: function (variations, attributes) {\n            this.changeButtonWizard();\n            this.populateVariationMatrix(variations);\n            this.attributes(attributes);\n            this.disableConfigurableAttributes(attributes);\n            this.handleValue(variations);\n            this.handleAttributes();\n        },\n\n        /**\n         * Change button wizard.\n         */\n        changeButtonWizard: function () {\n            if (this.variations.length) {\n                this.wizardButtonElement().title(this.wizardModalButtonTitle);\n            }\n        },\n\n        /**\n         * @param {Array} variations\n         */\n        handleValue: function (variations) {\n            var tmpArray = [];\n\n            _.each(variations, function (variation) {\n                var attributes = _.reduce(variation.options, function (memo, option) {\n                    var attribute = {};\n\n                    attribute[option['attribute_code']] = option.value;\n\n                    return _.extend(memo, attribute);\n                }, {}),\n                    gallery = {\n                        images: {}\n                    },\n                    types = {};\n\n                _.each(variation.images.images, function (image) {\n                    gallery.images[image['file_id']] = {\n                        position: image.position,\n                        file: image.file,\n                        disabled: image.disabled,\n                        label: image.label || ''\n                    };\n                    _.each(image.galleryTypes, function (type) {\n                        types[type] = image.file;\n                    });\n                }, this);\n\n                tmpArray.push(_.extend(variation, types, {\n                    productId: variation.productId || null,\n                    name: variation.name || variation.sku,\n                    priceCurrency: this.currencySymbol,\n                    weight: variation.weight,\n                    attribute: JSON.stringify(attributes),\n                    variationKey: this.getVariationKey(variation.options),\n                    editable: variation.editable === undefined ? 0 : 1,\n                    productUrl: this.buildProductUrl(variation.productId),\n                    status: variation.status === undefined ? 1 : parseInt(variation.status, 10),\n                    newProduct: variation.productId ? 0 : 1,\n                    'media_gallery': gallery\n                }));\n            }, this);\n\n            this.value(tmpArray);\n        },\n\n        /**\n         * Handle attributes.\n         */\n        handleAttributes: function () {\n            var tmpArray = [],\n                codesArray = [],\n                tmpOptions = {},\n                option = {},\n                position = 0,\n                values = {};\n\n            _.each(this.attributes(), function (attribute) {\n                tmpArray.push(attribute.id);\n                codesArray.push(attribute.code);\n                values = {};\n                _.each(attribute.chosen, function (row) {\n                    values[row.value] = {\n                        'include': '1',\n                        'value_index': row.value\n                    };\n                }, this);\n                option = {\n                    'attribute_id': attribute.id,\n                    'code': attribute.code,\n                    'label': attribute.label,\n                    'position': position,\n                    'values': values\n                };\n                tmpOptions[attribute.id] = option;\n                position++;\n            }, this);\n\n            this.attributesData(tmpOptions);\n            this.usedAttributes(tmpArray);\n            this.attributeCodes(codesArray);\n        },\n\n        /**\n         * Get attributes options\n         * @see use in matrix.phtml\n         *\n         * @returns {Array}\n         */\n        getAttributesOptions: function () {\n            return this.showVariations() ? this.productMatrix()[0].options : [];\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        showVariations: function () {\n            return this.productMatrix().length > 0;\n        },\n\n        /**\n         * @param {Array} variations\n         */\n        populateVariationMatrix: function (variations) {\n            this.productMatrix([]);\n            _.each(variations, function (variation) {\n                var attributes = _.reduce(variation.options, function (memo, option) {\n                    var attribute = {};\n\n                    attribute[option['attribute_code']] = option.value;\n\n                    return _.extend(memo, attribute);\n                }, {});\n\n                this.productMatrix.push(_.extend(variation, {\n                    productId: variation.productId || null,\n                    name: variation.name || variation.sku,\n                    weight: variation.weight,\n                    attribute: JSON.stringify(attributes),\n                    variationKey: this.getVariationKey(variation.options),\n                    editable: variation.editable === undefined ? !variation.productId : variation.editable,\n                    productUrl: this.buildProductUrl(variation.productId),\n                    status: variation.status === undefined ? 1 : parseInt(variation.status, 10)\n                }));\n            }, this);\n        },\n\n        /**\n         * @param {*} productId\n         */\n        buildProductUrl: function (productId) {\n            return this.productUrl.replace('%id%', productId);\n        },\n\n        /**\n         * @param {Object} options\n         * @return {String}\n         */\n        getVariationKey: function (options) {\n            return _.pluck(options, 'value').sort().join('-');\n        },\n\n        /**\n         * @param {*} options\n         * @return {*|null}\n         */\n        getProductIdByOptions: function (options) {\n            return this.productAttributesMap[this.getVariationKey(options)] || null;\n        },\n\n        /**\n         * Init product attributes map\n         */\n        initProductAttributesMap: function () {\n            if (this.productAttributesMap === null) {\n                this.productAttributesMap = {};\n                _.each(this.variations, function (product) {\n                    this.productAttributesMap[this.getVariationKey(product.options)] = product.productId;\n                }.bind(this));\n            }\n        },\n\n        /**\n         * @param {Array} attributes\n         */\n        disableConfigurableAttributes: function (attributes) {\n            var element;\n\n            _.each(this.disabledAttributes, function (attribute) {\n                registry.get('inputName = ' + 'product[' + attribute + ']').disabled(false);\n            });\n            this.disabledAttributes = [];\n\n            _.each(attributes, function (attribute) {\n                element = registry.get('inputName = ' + 'product[' + attribute.code + ']');\n\n                if (!_.isUndefined(element)) {\n                    element.disabled(true);\n                    this.disabledAttributes.push(attribute.code);\n                }\n            }, this);\n        },\n\n        /**\n         * Get currency symbol\n         * @returns {String}\n         */\n        getCurrencySymbol: function () {\n            return this.currencySymbol;\n        },\n\n        /**\n         * Chose action for the form save button\n         */\n        saveFormHandler: function () {\n            this.formElement().validate();\n\n            if (this.formElement().source.get('params.invalid') === false) {\n                this.serializeData();\n            }\n\n            if (this.checkForNewAttributes()) {\n                this.formSaveParams = arguments;\n                this.attributeSetHandlerModal().openModal();\n            } else {\n                if (this.validateForm(this.formElement())) {\n                    this.clearOutdatedData();\n                }\n                this.formElement().save(arguments[0], arguments[1]);\n\n                if (this.formElement().source.get('params.invalid')) {\n                    this.unserializeData();\n                }\n            }\n        },\n\n        /**\n         * @param {Object} formElement\n         *\n         * Validates each form element and returns true, if all elements are valid.\n         */\n        validateForm: function (formElement) {\n            formElement.validate();\n\n            return !formElement.additionalInvalid && !formElement.source.get('params.invalid');\n        },\n\n        /**\n         * Serialize data for specific form fields\n         *\n         * Serializes some complex data fields\n         *\n         * Original fields:\n         *   - configurable-matrix;\n         *   - associated_product_ids.\n         *\n         * Serialized fields in request:\n         *   - configurable-matrix-serialized;\n         *   - associated_product_ids_serialized.\n         */\n        serializeData: function () {\n            if (this.source.data['configurable-matrix']) {\n                this.source.data['configurable-matrix-serialized'] =\n                    JSON.stringify(this.source.data['configurable-matrix']);\n            }\n\n            if (this.source.data['associated_product_ids']) {\n                this.source.data['associated_product_ids_serialized'] =\n                    JSON.stringify(this.source.data['associated_product_ids']);\n            }\n        },\n\n        /**\n         * Clear outdated data for specific form fields\n         *\n         * Outdated fields:\n         *   - configurable-matrix;\n         *   - associated_product_ids.\n         */\n        clearOutdatedData: function () {\n            if (this.source.data['configurable-matrix']) {\n                delete this.source.data['configurable-matrix'];\n            }\n\n            if (this.source.data['associated_product_ids']) {\n                delete this.source.data['associated_product_ids'];\n            }\n        },\n\n        /**\n         * Unserialize data for specific form fields\n         *\n         * Unserializes some fields that were serialized this.serializeData\n         */\n        unserializeData: function () {\n            if (this.source.data['configurable-matrix-serialized']) {\n                this.source.data['configurable-matrix'] =\n                    JSON.parse(this.source.data['configurable-matrix-serialized']);\n                delete this.source.data['configurable-matrix-serialized'];\n            }\n\n            if (this.source.data['associated_product_ids_serialized']) {\n                this.source.data['associated_product_ids'] =\n                    JSON.parse(this.source.data['associated_product_ids_serialized']);\n                delete this.source.data['associated_product_ids_serialized'];\n            }\n        },\n\n        /**\n         * Check for newly added attributes\n         * @returns {Boolean}\n         */\n        checkForNewAttributes: function () {\n            var element, newAttributes = false;\n\n            _.each(this.source.get('data.attribute_codes'), function (attribute) {\n                element = registry.get('index = ' + attribute);\n\n                if (_.isUndefined(element)) {\n                    newAttributes = true;\n                }\n            }, this);\n\n            return newAttributes;\n        },\n\n        /**\n         * New attributes handler\n         * @returns {Boolean}\n         */\n        addNewAttributeSetHandler: function () {\n            var chosenAttributeSetOption;\n\n            this.formElement().validate();\n\n            if (this.formElement().source.get('params.invalid') === false) {\n                chosenAttributeSetOption = this.attributeSetSelection;\n\n                if (chosenAttributeSetOption === 'new') {\n                    this.createNewAttributeSet();\n\n                    return false;\n                }\n\n                if (chosenAttributeSetOption === 'existing') {\n                    this.set(\n                        'skeletonAttributeSet',\n                        this.attributeSetId\n                    );\n                }\n\n                this.closeDialogAndProcessForm();\n\n                return true;\n            }\n\n            this.unserializeData();\n\n            return false;\n        },\n\n        /**\n         * Handles new attribute set creation\n         * @returns {Boolean}\n         */\n        createNewAttributeSet: function () {\n            var messageBoxElement = registry.get('index = affectedAttributeSetError');\n\n            messageBoxElement.visible(false);\n\n            $.ajax({\n                type: 'POST',\n                url: this.attributeSetCreationUrl,\n                data: {\n                    gotoEdit: 1,\n                    'attribute_set_name': this.attributeSetName,\n                    'skeleton_set': this.skeletonAttributeSet,\n                    'return_session_messages_only': 1\n                },\n                dataType: 'json',\n                showLoader: true,\n                context: this\n            }).done(function (data) {\n                if (!data.error) {\n                    this.set(\n                        'skeletonAttributeSet',\n                        data.id\n                    );\n                    messageBoxElement.content(data.messages);\n                    messageBoxElement.visible(true);\n                    this.closeDialogAndProcessForm();\n                } else {\n                    messageBoxElement.content(data.messages);\n                    messageBoxElement.visible(true);\n                }\n\n                return false;\n            }).fail(function (xhr) {\n                if (xhr.statusText === 'abort') {\n                    return;\n                }\n\n                alert({\n                    content: $t('Something went wrong.')\n                });\n            });\n\n            return false;\n        },\n\n        /**\n         * Closes attribute set handler modal and process product form\n         */\n        closeDialogAndProcessForm: function () {\n            this.attributeSetHandlerModal().closeModal();\n            this.formElement().save(this.formSaveParams[0], this.formSaveParams[1]);\n        },\n\n        /**\n         * Retrieves product price\n         * @returns {*}\n         */\n        getProductPrice: function () {\n            return this.productPrice;\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/variations/steps/bulk.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global FORM_KEY, byteConvert */\ndefine([\n    'uiComponent',\n    'jquery',\n    'ko',\n    'underscore',\n    'Magento_Ui/js/lib/collapsible',\n    'mage/template',\n    'Magento_Ui/js/modal/alert',\n    'Magento_Catalog/js/product-gallery',\n    'jquery/file-uploader',\n    'mage/translate',\n    'Magento_ConfigurableProduct/js/variations/variations'\n], function (Component, $, ko, _, Collapsible, mageTemplate, alert) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            modules: {\n                variationsComponent: '${ $.variationsComponent }'\n            },\n            countVariations: 0,\n            attributes: [],\n            sections: {},\n            images: null,\n            price: '',\n            quantity: '',\n            notificationMessage: {\n                text: null,\n                error: null\n            }\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super().observe('countVariations attributes sections');\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            var self = this;\n\n            this._super();\n            this.sections({\n                images: {\n                    label: 'images',\n                    type: ko.observable('none'),\n                    value: ko.observable(),\n                    attribute: ko.observable()\n                },\n                price: {\n                    label: 'price',\n                    type: ko.observable('none'),\n                    value: ko.observable(),\n                    attribute: ko.observable(),\n                    currencySymbol: ''\n                },\n                quantity: {\n                    label: 'quantity',\n                    type: ko.observable('none'),\n                    value: ko.observable(),\n                    attribute: ko.observable()\n                }\n            });\n\n            this.variationsComponent(function (variationsComponent) {\n                this.sections().price.currencySymbol = variationsComponent.getCurrencySymbol();\n            }.bind(this));\n\n            /**\n             * Make options sections.\n             */\n            this.makeOptionSections = function () {\n                return {\n                    images: new this.makeImages(null),\n                    price: this.price,\n                    quantity: this.quantity\n                };\n            }.bind(this);\n\n            /**\n             * @param {Object} images\n             * @param {*} typePreview\n             */\n            this.makeImages = function (images, typePreview) {\n                var preview;\n\n                if (!images) {\n                    this.images = [];\n                    this.preview = self.noImage;\n                    this.file = null;\n                } else {\n                    this.images = images;\n                    preview = _.find(this.images, function (image) {\n                        return _.contains(image.galleryTypes, typePreview);\n                    });\n\n                    if (preview) {\n                        this.file = preview.file;\n                        this.preview = preview.url;\n                    } else {\n                        this.file = null;\n                        this.preview = self.noImage;\n                    }\n                }\n            };\n            this.images = new this.makeImages();\n            _.each(this.sections(), function (section) {\n                section.type.subscribe(function () {\n                    this.setWizardNotifyMessageDependOnSectionType();\n                }.bind(this));\n            }, this);\n        },\n        types: ['each', 'single', 'none'],\n\n        /**\n         * Set Wizard notify message depend on section type\n         */\n        setWizardNotifyMessageDependOnSectionType: function () {\n            var flag = false;\n\n            _.each(this.sections(), function (section) {\n                if (section.type() !== 'none') {\n                    flag = true;\n                }\n            }, this);\n\n            if (flag) {\n                this.wizard.setNotificationMessage(\n                    $.mage.__('Choose this option to delete and replace extension data for all past configurations.')\n                );\n            } else {\n                this.wizard.cleanNotificationMessage();\n            }\n        },\n\n        /**\n         * @param {Object} wizard\n         */\n        render: function (wizard) {\n            this.wizard = wizard;\n            this.attributes(wizard.data.attributes());\n\n            if (this.mode === 'edit') {\n                this.setWizardNotifyMessageDependOnSectionType();\n            }\n            //fill option section data\n            this.attributes.each(function (attribute) {\n                attribute.chosen.each(function (option) {\n                    option.sections = ko.observable(this.makeOptionSections());\n                }, this);\n            }, this);\n            //reset section.attribute\n            _.each(this.sections(), function (section) {\n                section.attribute(null);\n            });\n\n            this.initCountVariations();\n            this.bindGalleries();\n        },\n\n        /**\n         * Init count variations.\n         */\n        initCountVariations: function () {\n            var variations = this.generateVariation(this.attributes()),\n                newVariations = _.map(variations, function (options) {\n                    return this.variationsComponent().getVariationKey(options);\n                }.bind(this)),\n                existingVariations = _.keys(this.variationsComponent().productAttributesMap);\n\n            this.countVariations(_.difference(newVariations, existingVariations).length);\n        },\n\n        /**\n         * @param {Object} attributes - example [['b1', 'b2'],['a1', 'a2', 'a3'],['c1', 'c2', 'c3'],['d1']]\n         * @returns {*} example [['b1','a1','c1','d1'],['b1','a1','c2','d1']...]\n         */\n        generateVariation: function (attributes) {\n            return _.reduce(attributes, function (matrix, attribute) {\n                var tmp = [];\n\n                _.each(matrix, function (variations) {\n                    _.each(attribute.chosen, function (option) {\n                        option['attribute_code'] = attribute.code;\n                        option['attribute_label'] = attribute.label;\n                        tmp.push(_.union(variations, [option]));\n                    });\n                });\n\n                if (!tmp.length) {\n                    return _.map(attribute.chosen, function (option) {\n                        option['attribute_code'] = attribute.code;\n                        option['attribute_label'] = attribute.label;\n\n                        return [option];\n                    });\n                }\n\n                return tmp;\n            }, []);\n        },\n\n        /**\n         * @param {*} section\n         * @param {Object} options\n         * @return {*}\n         */\n        getSectionValue: function (section, options) {\n            switch (this.sections()[section].type()) {\n                case 'each':\n                    return _.find(this.sections()[section].attribute().chosen, function (chosen) {\n                        return _.find(options, function (option) {\n                            return chosen.id == option.id; //eslint-disable-line eqeqeq\n                        });\n                    }).sections()[section];\n\n                case 'single':\n                    return this.sections()[section].value();\n\n                case 'none':\n                    return this[section];\n            }\n        },\n\n        /**\n         * @param {*} node\n         * @return {Promise|*}\n         */\n        getImageProperty: function (node) {\n            var types = node.find('[data-role=gallery]').productGallery('option').types,\n                images = _.map(node.find('[data-role=image]'), function (image) {\n                    var imageData = $(image).data('imageData');\n\n                    imageData.galleryTypes = _.pluck(_.filter(types, function (type) {\n                        return type.value === imageData.file;\n                    }), 'code');\n\n                    return imageData;\n                });\n\n            return _.reject(images, function (image) {\n                return !!image.isRemoved;\n            });\n        },\n\n        /**\n         * Fill images section.\n         */\n        fillImagesSection: function () {\n            switch (this.sections().images.type()) {\n                case 'each':\n                    if (this.sections().images.attribute()) {\n                        this.sections().images.attribute().chosen.each(function (option) {\n                            option.sections().images = new this.makeImages(\n                                this.getImageProperty($('[data-role=step-gallery-option-' + option.id + ']')),\n                                'thumbnail'\n                            );\n                        }, this);\n                    }\n                    break;\n\n                case 'single':\n                    this.sections().images.value(new this.makeImages(\n                        this.getImageProperty($('[data-role=step-gallery-single]')),\n                        'thumbnail'\n                    ));\n                    break;\n\n                default:\n                    this.sections().images.value(new this.makeImages());\n                    break;\n            }\n        },\n\n        /**\n         * @param {Object} wizard\n         */\n        force: function (wizard) {\n            this.fillImagesSection();\n            this.validate();\n            this.validateImage();\n            wizard.data.sections = this.sections;\n            wizard.data.sectionHelper = this.getSectionValue.bind(this);\n            wizard.data.variations = this.generateVariation(this.attributes());\n        },\n\n        /**\n         * Validate.\n         */\n        validate: function () {\n            var formValid;\n\n            _.each(this.sections(), function (section) {\n                switch (section.type()) {\n                    case 'each':\n                        if (!section.attribute()) {\n                            throw new Error($.mage.__('Please select attribute for {section} section.')\n                                .replace('{section}', section.label));\n                        }\n                        break;\n\n                    case 'single':\n                        if (!section.value()) {\n                            throw new Error($.mage.__('Please fill in the values for {section} section.')\n                                .replace('{section}', section.label));\n                        }\n                        break;\n                }\n            }, this);\n            formValid = true;\n            _.each($('[data-role=attributes-values-form]'), function (form) {\n                formValid = $(form).valid() && formValid;\n            });\n\n            if (!formValid) {\n                throw new Error($.mage.__('Please fill-in correct values.'));\n            }\n        },\n\n        /**\n         * Validate image.\n         */\n        validateImage: function () {\n            switch (this.sections().images.type()) {\n                case 'each':\n                    _.each(this.sections().images.attribute().chosen, function (option) {\n                        if (!option.sections().images.images.length) {\n                            throw new Error($.mage.__('Please select image(s) for your attribute.'));\n                        }\n                    });\n                    break;\n\n                case 'single':\n                    if (this.sections().images.value().file == null) {\n                        throw new Error($.mage.__('Please choose image(s).'));\n                    }\n                    break;\n            }\n        },\n\n        /**\n         * Back.\n         */\n        back: function () {\n            this.setWizardNotifyMessageDependOnSectionType();\n        },\n\n        /**\n         * Bind galleries.\n         */\n        bindGalleries: function () {\n            $('[data-role=bulk-step] [data-role=gallery]').each(function (index, element) {\n                var gallery = $(element),\n                    uploadInput = $(gallery.find('[name=image]')),\n                    dropZone = $(gallery).find('.image-placeholder');\n\n                if (!gallery.data('gallery-initialized')) {\n                    gallery.mage('productGallery', {\n                        template: '[data-template=gallery-content]',\n                        dialogTemplate: '.dialog-template',\n                        dialogContainerTmpl: '[data-role=img-dialog-container-tmpl]'\n                    });\n\n                    uploadInput.fileupload({\n                        dataType: 'json',\n                        dropZone: dropZone,\n                        process: [{\n                            action: 'load',\n                            fileTypes: /^image\\/(gif|jpeg|png)$/\n                        }, {\n                            action: 'resize',\n                            maxWidth: 1920,\n                            maxHeight: 1200\n                        }, {\n                            action: 'save'\n                        }],\n                        formData: {\n                            'form_key': FORM_KEY\n                        },\n                        sequentialUploads: true,\n                        acceptFileTypes: /(\\.|\\/)(gif|jpe?g|png)$/i,\n\n                        /**\n                         * @param {jQuery.Event} e\n                         * @param {Object} data\n                         */\n                        add: function (e, data) {\n                            var progressTmpl = mageTemplate('[data-template=uploader]'),\n                                fileSize,\n                                tmpl;\n\n                            $.each(data.files, function (i, file) {\n                                fileSize = typeof file.size == 'undefined' ?\n                                    $.mage.__('We could not detect a size.') :\n                                    byteConvert(file.size);\n\n                                data.fileId = Math.random().toString(33).substr(2, 18);\n\n                                tmpl = progressTmpl({\n                                    data: {\n                                        name: file.name,\n                                        size: fileSize,\n                                        id: data.fileId\n                                    }\n                                });\n\n                                $(tmpl).appendTo(gallery.find('[data-role=uploader]'));\n                            });\n\n                            $(this).fileupload('process', data).done(function () {\n                                data.submit();\n                            });\n                        },\n\n                        /**\n                         * @param {jQuery.Event} e\n                         * @param {Object} data\n                         */\n                        done: function (e, data) {\n                            if (data.result && !data.result.error) {\n                                gallery.trigger('addItem', data.result);\n                            } else {\n                                $('#' + data.fileId)\n                                    .delay(2000)\n                                    .hide('highlight');\n                                alert({\n                                    content: $.mage.__('We don\\'t recognize or support this file extension type.')\n                                });\n                            }\n                            $('#' + data.fileId).remove();\n                        },\n\n                        /**\n                         * @param {jQuery.Event} e\n                         * @param {Object} data\n                         */\n                        progress: function (e, data) {\n                            var progress = parseInt(data.loaded / data.total * 100, 10),\n                                progressSelector = '#' + data.fileId + ' .progressbar-container .progressbar';\n\n                            $(progressSelector).css('width', progress + '%');\n                        },\n\n                        /**\n                         * @param {jQuery.Event} e\n                         * @param {Object} data\n                         */\n                        fail: function (e, data) {\n                            var progressSelector = '#' + data.fileId;\n\n                            $(progressSelector).removeClass('upload-progress').addClass('upload-failure')\n                                .delay(2000)\n                                .hide('highlight')\n                                .remove();\n                        }\n                    });\n                    gallery.data('gallery-initialized', 1);\n                }\n            });\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/variations/steps/select_attributes.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'jquery',\n    'underscore',\n    'mage/translate'\n], function (Component, $, _) {\n    'use strict';\n\n    /**\n     * @param {Function} provider\n     */\n    var initNewAttributeListener = function (provider) {\n        $('[data-role=product-variations-matrix]').on('add', function () {\n            provider().reload();\n        });\n    };\n\n    return Component.extend({\n        attributesLabels: {},\n        stepInitialized: false,\n        defaults: {\n            modules: {\n                multiselect: '${ $.multiselectName }',\n                attributeProvider: '${ $.providerName }'\n            },\n            listens: {\n                '${ $.multiselectName }:selected': 'doSelectedAttributesLabels',\n                '${ $.multiselectName }:rows': 'doSelectSavedAttributes'\n            },\n            notificationMessage: {\n                text: null,\n                error: null\n            },\n            selectedAttributes: []\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super();\n            this.selected = [];\n\n            initNewAttributeListener(this.attributeProvider);\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super().observe(['selectedAttributes']);\n\n            return this;\n        },\n\n        /**\n         * @param {Object} wizard\n         */\n        render: function (wizard) {\n            this.wizard = wizard;\n            this.setNotificationMessage();\n        },\n\n        /**\n         * Set notification message.\n         */\n        setNotificationMessage: function () {\n            /*eslint-disable max-len*/\n            var msg = $.mage.__('When you remove or add an attribute, we automatically update all configurations and you will need to recreate current configurations manually.');\n\n            /*eslint-enable max-len*/\n\n            if (this.mode === 'edit') {\n                this.wizard.setNotificationMessage(msg);\n            }\n        },\n\n        /**\n         * Do select saved attributes.\n         */\n        doSelectSavedAttributes: function () {\n            if (this.stepInitialized === false) {\n                this.stepInitialized = true;\n                //cache attributes labels, which can be present on the 2nd page\n                _.each(this.initData.attributes, function (attribute) {\n                    this.attributesLabels[attribute.id] = attribute.label;\n                }.bind(this));\n                this.multiselect().selected(_.pluck(this.initData.attributes, 'id'));\n            }\n        },\n\n        /**\n         * @param {*} selected\n         */\n        doSelectedAttributesLabels: function (selected) {\n            var labels = [];\n\n            this.selected = selected;\n            _.each(selected, function (attributeId) {\n                var attribute;\n\n                if (!this.attributesLabels[attributeId]) {\n                    attribute = _.findWhere(this.multiselect().rows(), {\n                        'attribute_id': attributeId\n                    });\n\n                    if (attribute) {\n                        this.attributesLabels[attribute['attribute_id']] = attribute['frontend_label'];\n                    }\n                }\n                labels.push(this.attributesLabels[attributeId]);\n            }.bind(this));\n            this.selectedAttributes(labels.join(', '));\n        },\n\n        /**\n         * @param {Object} wizard\n         */\n        force: function (wizard) {\n            wizard.data.attributesIds = this.multiselect().selected;\n\n            if (!wizard.data.attributesIds() || wizard.data.attributesIds().length === 0) {\n                throw new Error($.mage.__('Please select attribute(s).'));\n            }\n            this.setNotificationMessage();\n        },\n\n        /**\n         * Back.\n         */\n        back: function () {\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/variations/steps/summary.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'jquery',\n    'ko',\n    'underscore',\n    'Magento_Ui/js/grid/paging/paging',\n    'mage/translate'\n], function (Component, $, ko, _, paging) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            modules: {\n                variationsComponent: '${ $.variationsComponent }',\n                modalComponent: '${ $.modalComponent }'\n            },\n            notificationMessage: {\n                text: null,\n                error: null\n            },\n            gridExisting: [],\n            gridNew: [],\n            gridDeleted: [],\n            variationsExisting: [],\n            variationsNew: [],\n            variationsDeleted: [],\n            pagingExisting: paging({\n                name: 'configurableWizard.pagingExisting',\n                sizesConfig: {\n                    component: 'Magento_ConfigurableProduct/js/variations/paging/sizes',\n                    name: 'configurableWizard.pagingExisting_sizes'\n                }\n            }),\n            pagingNew: paging({\n                name: 'configurableWizard.pagingNew',\n                sizesConfig: {\n                    component: 'Magento_ConfigurableProduct/js/variations/paging/sizes',\n                    name: 'configurableWizard.pagingNew_sizes'\n                }\n            }),\n            pagingDeleted: paging({\n                name: 'configurableWizard.pagingDeleted',\n                sizesConfig: {\n                    component: 'Magento_ConfigurableProduct/js/variations/paging/sizes',\n                    name: 'configurableWizard.pagingDeleted_sizes'\n                }\n            }),\n            attributes: [],\n            attributesName: [$.mage.__('Images'), $.mage.__('SKU'), $.mage.__('Quantity'), $.mage.__('Price')],\n            sections: [],\n            gridTemplate: 'Magento_ConfigurableProduct/variations/steps/summary-grid',\n            quantityFieldName: 'quantity'\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            var pagingObservables = {\n                currentNew: ko.getObservable(this.pagingNew, 'current'),\n                currentExisting: ko.getObservable(this.pagingExisting, 'current'),\n                currentDeleted: ko.getObservable(this.pagingDeleted, 'current'),\n                pageSizeNew: ko.getObservable(this.pagingNew, 'pageSize'),\n                pageSizeExisting: ko.getObservable(this.pagingExisting, 'pageSize'),\n                pageSizeDeleted: ko.getObservable(this.pagingDeleted, 'pageSize')\n            };\n\n            this._super().observe('gridExisting gridNew gridDeleted attributes sections');\n            this.gridExisting.columns = ko.observableArray();\n            this.gridNew.columns = ko.observableArray();\n            this.gridDeleted.columns = ko.observableArray();\n\n            _.each(pagingObservables, function (observable) {\n                observable.subscribe(function () {\n                    this.generateGrid();\n                }, this);\n            }, this);\n\n            return this;\n        },\n        nextLabelText: $.mage.__('Generate Products'),\n        variations: [],\n\n        /**\n         * @param {*} variations\n         * @param {Function} getSectionValue\n         */\n        calculate: function (variations, getSectionValue) {\n            var productSku = this.variationsComponent().getProductValue('sku'),\n                productPrice = this.variationsComponent().getProductPrice(),\n                productWeight = this.variationsComponent().getProductValue('weight'),\n                productName = this.variationsComponent().getProductValue('name'),\n                variationsKeys = [],\n                gridExisting = [],\n                gridNew = [],\n                gridDeleted = [];\n\n            this.variations = [];\n            _.each(variations, function (options) {\n                var product, images, sku, name, quantity, price, variation,\n                    productId = this.variationsComponent().getProductIdByOptions(options);\n\n                if (productId) {\n                    product = _.findWhere(this.variationsComponent().variations, {\n                        productId: productId\n                    });\n                }\n                images = getSectionValue('images', options);\n                sku = productSku + _.reduce(options, function (memo, option) {\n                    return memo + '-' + option.label;\n                }, '');\n                name = productName + _.reduce(options, function (memo, option) {\n                    return memo + '-' + option.label;\n                }, '');\n                quantity = getSectionValue(this.quantityFieldName, options);\n\n                if (!quantity && productId) {\n                    quantity = product[this.quantityFieldName];\n                }\n                price = getSectionValue('price', options);\n\n                if (!price) {\n                    price = productId ? product.price : productPrice;\n                }\n\n                if (productId && !images.file) {\n                    images = product.images;\n                }\n                variation = {\n                    options: options,\n                    images: images,\n                    sku: sku,\n                    name: name,\n                    price: price,\n                    productId: productId,\n                    weight: productWeight,\n                    editable: true\n                };\n                variation[this.quantityFieldName] = quantity;\n\n                if (productId) {\n                    variation.sku = product.sku;\n                    variation.weight = product.weight;\n                    variation.name = product.name;\n                    gridExisting.push(this.prepareRowForGrid(variation));\n                } else {\n                    gridNew.push(this.prepareRowForGrid(variation));\n                }\n                this.variations.push(variation);\n                variationsKeys.push(this.variationsComponent().getVariationKey(options));\n            }, this);\n\n            _.each(_.omit(this.variationsComponent().productAttributesMap, variationsKeys), function (productId) {\n                gridDeleted.push(this.prepareRowForGrid(\n                    _.findWhere(this.variationsComponent().variations, {\n                        productId: productId\n                    })\n                ));\n            }.bind(this));\n\n            this.variationsExisting = gridExisting;\n            this.variationsNew = gridNew;\n            this.variationsDeleted = gridDeleted;\n        },\n\n        /**\n         * Generate grid.\n         */\n        generateGrid: function () {\n            var pageExisting = this.pagingExisting.pageSize * this.pagingExisting.current,\n                pageNew = this.pagingNew.pageSize * this.pagingNew.current,\n                pageDeleted = this.pagingDeleted.pageSize * this.pagingDeleted.current;\n\n            this.pagingExisting.totalRecords = this.variationsExisting.length;\n            this.gridExisting(this.variationsExisting.slice(pageExisting - this.pagingExisting.pageSize, pageExisting));\n\n            this.pagingNew.totalRecords = this.variationsNew.length;\n            this.gridNew(this.variationsNew.slice(pageNew - this.pagingNew.pageSize, pageNew));\n\n            this.pagingDeleted.totalRecords = this.variationsDeleted.length;\n            this.gridDeleted(this.variationsDeleted.slice(pageDeleted - this.pagingDeleted.pageSize, pageDeleted));\n        },\n\n        /**\n         * @param {Object} variation\n         * @return {Array}\n         */\n        prepareRowForGrid: function (variation) {\n            var row = [];\n\n            row.push(_.extend({\n                images: []\n            }, variation.images));\n            row.push(variation.sku);\n            row.push(variation[this.quantityFieldName]);\n            _.each(variation.options, function (option) {\n                row.push(option.label);\n            });\n            row.push(this.variationsComponent().getCurrencySymbol() +  ' ' + variation.price);\n\n            return row;\n        },\n\n        /**\n         * @return {String|*}\n         */\n        getGridTemplate: function () {\n            return this.gridTemplate;\n        },\n\n        /**\n         * @return {*|String}\n         */\n        getGridId: function () {\n            return _.uniqueId('grid_');\n        },\n\n        /**\n         * @param {*} attributes\n         * @return {Array}\n         */\n        getColumnsName: function (attributes) {\n            var columns = this.attributesName.slice(0);\n\n            attributes.each(function (attribute, index) {\n                columns.splice(3 + index, 0, attribute.label);\n            }, this);\n\n            return columns;\n        },\n\n        /**\n         * @param {Object} wizard\n         */\n        render: function (wizard) {\n            this.wizard = wizard;\n            this.sections(wizard.data.sections());\n            this.attributes(wizard.data.attributes());\n            this.gridNew([]);\n            this.gridExisting([]);\n            this.gridDeleted([]);\n            this.gridExisting.columns(this.getColumnsName(this.wizard.data.attributes));\n            this.gridNew.columns(this.getColumnsName(this.wizard.data.attributes));\n            this.gridDeleted.columns(this.getColumnsName(this.variationsComponent().productAttributes));\n            this.calculate(wizard.data.variations, wizard.data.sectionHelper);\n            this.generateGrid();\n        },\n\n        /**\n         * Force.\n         */\n        force: function () {\n            this.variationsComponent().render(this.variations, this.attributes());\n            this.modalComponent().closeModal();\n        },\n\n        /**\n         * Back.\n         */\n        back: function () {\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/variations/steps/attributes_values.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'jquery',\n    'ko',\n    'underscore',\n    'mageUtils',\n    'Magento_Ui/js/lib/collapsible',\n    'mage/translate'\n], function (Component, $, ko, _, utils, Collapsible) {\n    'use strict';\n\n    //connect items with observableArrays\n    ko.bindingHandlers.sortableList = {\n        /** @inheritdoc */\n        init: function (element, valueAccessor) {\n            var list = valueAccessor();\n\n            $(element).sortable({\n                axis: 'y',\n                handle: '[data-role=\"draggable\"]',\n                tolerance: 'pointer',\n\n                /** @inheritdoc */\n                update: function (event, ui) {\n                    var item = ko.contextFor(ui.item[0]).$data,\n                        position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);\n\n                    if (ko.contextFor(ui.item[0]).$index() != position) { //eslint-disable-line eqeqeq\n                        if (position >= 0) {\n                            list.remove(item);\n                            list.splice(position, 0, item);\n                        }\n                        ui.item.remove();\n                    }\n                }\n            });\n        }\n    };\n\n    return Collapsible.extend({\n        defaults: {\n            notificationMessage: {\n                text: null,\n                error: null\n            },\n            createOptionsUrl: null,\n            attributes: [],\n            stepInitialized: false\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super();\n            this.createAttribute = _.wrap(this.createAttribute, function () {\n                var args = _.toArray(arguments),\n                    createAttribute = args.shift();\n\n                return this.doInitSavedOptions(createAttribute.apply(this, args));\n            });\n            this.createAttribute = _.memoize(this.createAttribute.bind(this), _.property('id'));\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super().observe(['attributes']);\n\n            return this;\n        },\n\n        /**\n         * Create option.\n         */\n        createOption: function () {\n            // this - current attribute\n            this.options.push({\n                value: 0,\n                label: '',\n                id: utils.uniqueid(),\n                'attribute_id': this.id,\n                'is_new': true\n            });\n        },\n\n        /**\n         * @param {Object} option\n         */\n        saveOption: function (option) {\n            if (!_.isEmpty(option.label)) {\n                this.options.remove(option);\n                this.options.push(option);\n                this.chosenOptions.push(option.id);\n            }\n        },\n\n        /**\n         * @param {Object} option\n         */\n        removeOption: function (option) {\n            this.options.remove(option);\n        },\n\n        /**\n         * @param {String} attribute\n         */\n        removeAttribute: function (attribute) {\n            this.attributes.remove(attribute);\n            this.wizard.setNotificationMessage(\n                $.mage.__('An attribute has been removed. This attribute will no longer appear in your configurations.')\n            );\n        },\n\n        /**\n         * @param {Object} attribute\n         * @param {*} index\n         * @return {Object}\n         */\n        createAttribute: function (attribute, index) {\n            attribute.chosenOptions = ko.observableArray([]);\n            attribute.options = ko.observableArray(_.map(attribute.options, function (option) {\n                option.id = utils.uniqueid();\n\n                return option;\n            }));\n            attribute.opened = ko.observable(this.initialOpened(index));\n            attribute.collapsible = ko.observable(true);\n\n            return attribute;\n        },\n\n        /**\n         * First 3 attribute panels must be open.\n         *\n         * @param {Number} index\n         * @return {Boolean}\n         */\n        initialOpened: function (index) {\n            return index < 3;\n        },\n\n        /**\n         * Save attribute.\n         */\n        saveAttribute: function () {\n            var errorMessage = $.mage.__('Select options for all attributes or remove unused attributes.');\n\n            this.attributes.each(function (attribute) {\n                attribute.chosen = [];\n\n                if (!attribute.chosenOptions.getLength()) {\n                    throw new Error(errorMessage);\n                }\n                attribute.chosenOptions.each(function (id) {\n                    attribute.chosen.push(attribute.options.findWhere({\n                        id: id\n                    }));\n                });\n            });\n\n            if (!this.attributes().length) {\n                throw new Error(errorMessage);\n            }\n        },\n\n        /**\n         * @param {Object} attribute\n         */\n        selectAllAttributes: function (attribute) {\n            this.chosenOptions(_.pluck(attribute.options(), 'id'));\n        },\n\n        /**\n         * @param {Object} attribute\n         */\n        deSelectAllAttributes: function (attribute) {\n            attribute.chosenOptions.removeAll();\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        saveOptions: function () {\n            var options = [];\n\n            this.attributes.each(function (attribute) {\n                attribute.chosenOptions.each(function (id) {\n                    var option = attribute.options.findWhere({\n                        id: id,\n                        'is_new': true\n                    });\n\n                    if (option) {\n                        options.push(option);\n                    }\n                });\n            });\n\n            if (!options.length) {\n                return false;\n            }\n            $.ajax({\n                type: 'POST',\n                url: this.createOptionsUrl,\n                data: {\n                    options: options\n                },\n                showLoader: true\n            }).done(function (savedOptions) {\n                this.attributes.each(function (attribute) {\n                    _.each(savedOptions, function (newOptionId, oldOptionId) {\n                        var option = attribute.options.findWhere({\n                            id: oldOptionId\n                        });\n\n                        if (option) {\n                            attribute.options.remove(option);\n                            option['is_new'] = false;\n                            option.value = newOptionId;\n                            attribute.options.push(option);\n                        }\n                    });\n                });\n\n            }.bind(this));\n        },\n\n        /**\n         * @param {*} attributeIds\n         */\n        requestAttributes: function (attributeIds) {\n            $.ajax({\n                type: 'GET',\n                url: this.optionsUrl,\n                data: {\n                    attributes: attributeIds\n                },\n                showLoader: true\n            }).done(function (attributes) {\n                attributes = _.sortBy(attributes, function (attribute) {\n                    return this.wizard.data.attributesIds.indexOf(attribute.id);\n                }.bind(this));\n                this.attributes(_.map(attributes, this.createAttribute));\n            }.bind(this));\n        },\n\n        /**\n         * @param {*} attribute\n         * @return {*}\n         */\n        doInitSavedOptions: function (attribute) {\n            var selectedOptions, selectedOptionsIds, selectedAttribute = _.findWhere(this.initData.attributes, {\n                id: attribute.id\n            });\n\n            if (selectedAttribute) {\n                selectedOptions = _.pluck(selectedAttribute.chosen, 'value');\n                selectedOptionsIds = _.pluck(_.filter(attribute.options(), function (option) {\n                    return _.contains(selectedOptions, option.value);\n                }), 'id');\n                attribute.chosenOptions(selectedOptionsIds);\n                this.initData.attributes = _.without(this.initData.attributes, selectedAttribute);\n            }\n\n            return attribute;\n        },\n\n        /**\n         * @param {Object} wizard\n         */\n        render: function (wizard) {\n            this.wizard = wizard;\n            this.requestAttributes(wizard.data.attributesIds());\n        },\n\n        /**\n         * @param {Object} wizard\n         */\n        force: function (wizard) {\n            this.saveOptions();\n            this.saveAttribute(wizard);\n\n            wizard.data.attributes = this.attributes;\n        },\n\n        /**\n         * @param {Object} wizard\n         */\n        back: function (wizard) {\n            wizard.data.attributesIds(this.attributes().pluck('id'));\n        }\n    });\n});\n","Magento_ConfigurableProduct/js/variations/paging/sizes.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'Magento_Ui/js/grid/paging/sizes'\n], function (Sizes) {\n    'use strict';\n\n    return Sizes.extend({\n        defaults: {\n            excludedOptions: ['100', '200']\n        },\n\n        /**\n         * @override\n         */\n        initialize: function () {\n            this._super();\n\n            this.excludedOptions.forEach(function (excludedOption) {\n                delete this.options[excludedOption];\n            }, this);\n            this.updateArray();\n\n            return this;\n        }\n    });\n});\n","Magento_User/app-config.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\nrequire.config({\n    'waitSeconds': 0,\n    'shim': {\n        'jquery/jstree/jquery.hotkeys': ['jquery'],\n        'jquery/hover-intent': ['jquery'],\n        'mage/adminhtml/backup': ['prototype'],\n        'mage/captcha': ['prototype'],\n        'mage/common': ['jquery'],\n        'mage/webapi': ['jquery'],\n        'ko': {\n            exports: 'ko'\n        },\n        'moment': {\n            exports: 'moment'\n        }\n    },\n    'paths': {\n        'jquery/ui': 'jquery/jquery-ui-1.9.2',\n        'jquery/validate': 'jquery/jquery.validate',\n        'jquery/hover-intent': 'jquery/jquery.hoverIntent',\n        'jquery/file-uploader': 'jquery/fileUploader/jquery.fileupload-fp',\n        'prototype': 'prototype/prototype-amd',\n        'text': 'requirejs/text',\n        'domReady': 'requirejs/domReady',\n        'ko': 'ko/ko'\n    }\n});\n\nrequire(['jquery'], function (jQuery) {\n    'use strict';\n\n    jQuery.noConflict();\n});\n","Magento_User/js/delete-user-account.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 postData;\n\n    return function (params, elem) {\n\n        elem.on('click', function () {\n\n            postData = {\n                'data': {\n                    'user_id': params.objId,\n                    'current_password': $('[name=\"current_password\"]').val()\n                }\n            };\n\n            if ($.validator.validateElement($('[name=\"current_password\"]'))) {\n                window.deleteConfirm(params.message, params.url, postData);\n            }\n        });\n    };\n});\n","Magento_User/js/roles-tree.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'jquery/ui',\n    'jquery/jstree/jquery.jstree'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.rolesTree', {\n        options: {\n            treeInitData: {},\n            treeInitSelectedData: {}\n        },\n\n        /** @inheritdoc */\n        _create: function () {\n            this.element.jstree({\n                plugins: ['themes', 'json_data', 'ui', 'crrm', 'types', 'vcheckbox', 'hotkeys'],\n                vcheckbox: {\n                    'two_state': true,\n                    'real_checkboxes': true,\n\n                    /**\n                     * @param {*} n\n                     * @return {Array}\n                     */\n                    'real_checkboxes_names': function (n) {\n                        return ['resource[]', $(n).data('id')];\n                    }\n                },\n                'json_data': {\n                    data: this.options.treeInitData\n                },\n                ui: {\n                    'select_limit': 0\n                },\n                hotkeys: {\n                    space: this._changeState,\n                    'return': this._changeState\n                },\n                types: {\n                    'types': {\n                        'disabled': {\n                            'check_node': false,\n                            'uncheck_node': false\n                        }\n                    }\n                }\n            });\n            this._bind();\n        },\n\n        /**\n         * @private\n         */\n        _destroy: function () {\n            this.element.jstree('destroy');\n        },\n\n        /**\n         * @private\n         */\n        _bind: function () {\n            this.element.on('loaded.jstree', $.proxy(this._checkNodes, this));\n            this.element.on('click.jstree', 'a', $.proxy(this._checkNode, this));\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _checkNode: function (event) {\n            event.stopPropagation();\n            this.element.jstree(\n                'change_state',\n                event.currentTarget,\n                this.element.jstree('is_checked', event.currentTarget)\n            );\n        },\n\n        /**\n         * @private\n         */\n        _checkNodes: function () {\n            var $items = $('[data-id=\"' + this.options.treeInitSelectedData.join('\"],[data-id=\"') + '\"]');\n\n            $items.removeClass('jstree-unchecked').addClass('jstree-checked');\n            $items.children(':checkbox').prop('checked', true);\n        },\n\n        /**\n         * @return {Boolean}\n         * @private\n         */\n        _changeState: function () {\n            var element;\n\n            if (this.data.ui.hovered) {\n                element = this.data.ui.hovered;\n                this['change_state'](element, this['is_checked'](element));\n            }\n\n            return false;\n        }\n    });\n\n    return $.mage.rolesTree;\n});\n","Magento_Paypal/js/rules.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'uiClass',\n    'Magento_Ui/js/modal/alert'\n], function (Class, alert) {\n    'use strict';\n\n    /**\n     * Check is solution enabled\n     *\n     * @param {*} solution\n     * @param {String} enabler\n     * @returns {Boolean}\n     */\n    var isSolutionEnabled = function (solution, enabler) {\n            return solution.find(enabler).val() === '1';\n        },\n\n        /**\n         * Check is solution has related solutions enabled\n         *\n         * @param {Object} data\n         * @returns {Boolean}\n         */\n        hasRelationsEnabled = function (data) {\n            var name;\n\n            for (name in data.argument) {\n                if (\n                    data.solutionsElements[name] &&\n                    isSolutionEnabled(data.solutionsElements[name], data.enableButton)\n                ) {\n                    return true;\n                }\n            }\n\n            return false;\n        },\n\n        /**\n         * Set solution select-enabler to certain option\n         *\n         * @param {*} solution\n         * @param {String} enabler\n         * @param {Boolean} enabled\n         */\n        setSolutionSelectEnabled = function (solution, enabler, enabled) {\n            enabled = !(enabled || typeof enabled === 'undefined') ? '0' : '1';\n\n            solution.find(enabler + ' option[value=' + enabled + ']')\n            .prop('selected', true);\n        },\n\n        /**\n         * Set solution property 'disabled' value\n         *\n         * @param {*} solution\n         * @param {String} enabler\n         * @param {Boolean} enabled\n         */\n        setSolutionPropEnabled = function (solution, enabler, enabled) {\n            enabled = !(enabled || typeof enabled === 'undefined');\n\n            solution.find(enabler).prop('disabled', enabled);\n        },\n\n        /**\n         * Set/unset solution select-enabler label\n         *\n         * @param {*} solution\n         * @param {String} enabler\n         * @param {Boolean} enabled\n         */\n        setSolutionMarkEnabled = function (solution, enabler, enabled) {\n            var solutionEnabler = solution.find('label[for=\"' + solution.find(enabler).attr('id') + '\"]');\n\n            enabled || typeof enabled === 'undefined' ?\n                solutionEnabler.addClass('enabled') :\n                solutionEnabler.removeClass('enabled');\n        },\n\n        /**\n         * Set/unset solution section label\n         *\n         * @param {*} solution\n         * @param {Boolean} enabled\n         */\n        setSolutionSectionMarkEnabled = function (solution, enabled) {\n            var solutionSection = solution.find('.section-config');\n\n            enabled || typeof enabled === 'undefined' ?\n                solutionSection.addClass('enabled') :\n                solutionSection.removeClass('enabled');\n        },\n\n        /**\n         * Set/unset solution section inner labels\n         *\n         * @param {*} solution\n         * @param {Boolean} enabled\n         */\n        setSolutionLabelsMarkEnabled = function (solution, enabled) {\n            var solutionLabels = solution.find('label.enabled');\n\n            enabled || typeof enabled === 'undefined' ?\n                solutionLabels.addClass('enabled') :\n                solutionLabels.removeClass('enabled');\n        },\n\n        /**\n         * Set/unset solution usedefault checkbox\n         *\n         * @param {*} solution\n         * @param {String} enabler\n         * @param {Boolean} checked\n         */\n        setSolutionUsedefaultEnabled = function (solution, enabler, checked) {\n            checked = !(checked || typeof checked === 'undefined');\n\n            solution.find('input[id=\"' + solution.find(enabler).attr('id') + '_inherit\"]')\n            .prop('checked', checked);\n        },\n\n        /**\n         * Set solution as disabled\n         *\n         * @param {*} solution\n         * @param {String} enabler\n         */\n        disableSolution = function (solution, enabler) {\n            setSolutionUsedefaultEnabled(solution, enabler);\n            setSolutionMarkEnabled(solution, enabler, false);\n            setSolutionSelectEnabled(solution, enabler, false);\n            setSolutionPropEnabled(solution, enabler, false);\n        },\n\n        /**\n         * Set solution as enabled\n         *\n         * @param {*} solution\n         * @param {String} enabler\n         */\n        enableSolution = function (solution, enabler) {\n            setSolutionUsedefaultEnabled(solution, enabler);\n            setSolutionPropEnabled(solution, enabler);\n            setSolutionSelectEnabled(solution, enabler);\n            setSolutionMarkEnabled(solution, enabler);\n        },\n\n        /**\n         * Lock/unlock solution configuration button\n         *\n         * @param {*} solution\n         * @param {String} buttonConfiguration\n         * @param {Boolean} unlock\n         */\n        setSolutionConfigurationUnlock = function (solution, buttonConfiguration, unlock) {\n            var solutionConfiguration = solution.find(buttonConfiguration);\n\n            unlock || typeof unlock === 'undefined' ?\n                solutionConfiguration.removeClass('disabled').removeAttr('disabled') :\n                solutionConfiguration.addClass('disabled').attr('disabled', 'disabled');\n        },\n\n        /**\n         * Forward solution select-enabler changes\n         *\n         * @param {*} solution\n         * @param {String} enabler\n         */\n        forwardSolutionChange = function (solution, enabler) {\n            solution.find(enabler).change();\n        },\n\n        /**\n         * Show/hide dependent fields\n         *\n         * @param {*} solution\n         * @param {String} identifier\n         * @param {Boolean} show\n         */\n        showDependsField = function (solution, identifier, show) {\n            show = show || typeof show === 'undefined';\n\n            solution.find(identifier).toggle(show);\n            solution.find(identifier).closest('tr').toggle(show);\n            solution.find(identifier).attr('disabled', !show);\n        };\n\n    return Class.extend({\n        defaults: {\n            /**\n             * Payment conflicts checker\n             */\n            executed: false\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        simpleDisable: function ($target, $owner, data) {\n            setSolutionSelectEnabled($target, data.enableButton, false);\n            setSolutionLabelsMarkEnabled($target, false);\n            setSolutionSectionMarkEnabled($target, false);\n        },\n\n        /**\n         * @param {*} $target\n         */\n        simpleMarkEnable: function ($target) {\n            setSolutionSectionMarkEnabled($target);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        disable: function ($target, $owner, data) {\n            this.simpleDisable($target, $owner, data);\n            forwardSolutionChange($target, data.enableButton);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalExpressDisable: function ($target, $owner, data) {\n            setSolutionSelectEnabled($target, data.enableButton, false);\n            setSolutionLabelsMarkEnabled($target, false);\n            forwardSolutionChange($target, data.enableButton);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalExpressLockConfiguration: function ($target, $owner, data) {\n            setSolutionConfigurationUnlock($target, data.buttonConfiguration, false);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalExpressLockConfigurationConditional: function ($target, $owner, data) {\n            if (\n                !isSolutionEnabled($target, data.enableInContextPayPal) &&\n                hasRelationsEnabled(data)\n            ) {\n                this.paypalExpressLockConfiguration($target, $owner, data);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalExpressMarkDisable: function ($target, $owner, data) {\n            if (!hasRelationsEnabled(data)) {\n                this.simpleDisable($target, $owner, data);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalExpressUnlockConfiguration: function ($target, $owner, data) {\n            if (!hasRelationsEnabled(data)) {\n                setSolutionConfigurationUnlock($target, data.buttonConfiguration);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalBmlDisable: function ($target, $owner, data) {\n            disableSolution($target, data.enableBmlPayPal);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalBmlDisableConditional: function ($target, $owner, data) {\n            if (!isSolutionEnabled($target, data.enableButton)) {\n                this.paypalBmlDisable($target, $owner, data);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalBmlEnable: function ($target, $owner, data) {\n            enableSolution($target, data.enableBmlPayPal);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowExpressDisable: function ($target, $owner, data) {\n            disableSolution($target, data.enableExpress);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowExpressDisableConditional: function ($target, $owner, data) {\n            if (\n                !isSolutionEnabled($target, data.enableButton) ||\n                hasRelationsEnabled(data)\n            ) {\n                this.payflowExpressDisable($target, $owner, data);\n                forwardSolutionChange($target, data.enableExpress);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowExpressEnable: function ($target, $owner, data) {\n            enableSolution($target, data.enableExpress);\n            forwardSolutionChange($target, data.enableExpress);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowExpressEnableConditional: function ($target, $owner, data) {\n            if (hasRelationsEnabled(data)) {\n                setSolutionPropEnabled($target, data.enableExpress, false);\n                setSolutionSelectEnabled($target, data.enableExpress);\n                setSolutionMarkEnabled($target, data.enableExpress);\n            } else {\n                disableSolution($target, data.enableExpress);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowExpressLockConditional: function ($target, $owner, data) {\n            if (!isSolutionEnabled($target, data.enableButton)) {\n                setSolutionPropEnabled($target, data.enableExpress, false);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowExpressUsedefaultDisable: function ($target, $owner, data) {\n            setSolutionUsedefaultEnabled($target, data.enableExpress, false);\n            this.payflowExpressEnable($target, $owner, data);\n            forwardSolutionChange($target, data.enableExpress);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowExpressUsedefaultEnable: function ($target, $owner, data) {\n            setSolutionUsedefaultEnabled($target, data.enableExpress);\n            this.payflowExpressDisable($target, $owner, data);\n            forwardSolutionChange($target, data.enableExpress);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowBmlDisable: function ($target, $owner, data) {\n            disableSolution($target, data.enableBml);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowBmlDisableConditional: function ($target, $owner, data) {\n            if (\n                !isSolutionEnabled($target, data.enableButton) ||\n                hasRelationsEnabled(data)\n            ) {\n                this.payflowBmlDisable($target, $owner, data);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowBmlDisableConditionalExpress: function ($target, $owner, data) {\n            if (!isSolutionEnabled($target, data.enableExpress)) {\n                this.payflowBmlDisable($target, $owner, data);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowBmlEnable: function ($target, $owner, data) {\n            enableSolution($target, data.enableBml);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowBmlEnableConditional: function ($target, $owner, data) {\n            if (hasRelationsEnabled(data)) {\n                setSolutionPropEnabled($target, data.enableBml, false);\n                setSolutionSelectEnabled($target, data.enableBml);\n                setSolutionMarkEnabled($target, data.enableBml);\n            } else {\n                disableSolution($target, data.enableBml);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowBmlLockConditional: function ($target, $owner, data) {\n            if (!isSolutionEnabled($target, data.enableButton)) {\n                setSolutionPropEnabled($target, data.enableBml, false);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        inContextEnable: function ($target, $owner, data) {\n            enableSolution($target, data.enableInContextPayPal);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        inContextDisable: function ($target, $owner, data) {\n            disableSolution($target, data.enableInContextPayPal);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        inContextShowMerchantId: function ($target, $owner, data) {\n            showDependsField($target, data.dependsMerchantId);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        inContextHideMerchantId: function ($target, $owner, data) {\n            showDependsField($target, data.dependsMerchantId, false);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowShowSortOrder: function ($target, $owner, data) {\n            showDependsField($target, data.dependsBmlSortOrder);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        payflowHideSortOrder: function ($target, $owner, data) {\n            showDependsField($target, data.dependsBmlSortOrder, false);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalShowSortOrder: function ($target, $owner, data) {\n            showDependsField($target, data.dependsBmlApiSortOrder);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        paypalHideSortOrder: function ($target, $owner, data) {\n            showDependsField($target, data.dependsBmlApiSortOrder, false);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        inContextActivate: function ($target, $owner, data) {\n            setSolutionMarkEnabled($target, data.enableInContextPayPal);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        inContextDeactivate: function ($target, $owner, data) {\n            setSolutionMarkEnabled($target, data.enableInContextPayPal, false);\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        inContextDisableConditional: function ($target, $owner, data) {\n            if (!isSolutionEnabled($target, data.enableButton)) {\n                this.inContextDisable($target, $owner, data);\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        conflict: function ($target, $owner, data) {\n            var newLine = String.fromCharCode(10, 13);\n\n            if (\n                isSolutionEnabled($owner, data.enableButton) &&\n                hasRelationsEnabled(data) &&\n                !this.executed\n            ) {\n                this.executed = true;\n                alert({\n                    content: 'The following error(s) occurred:' +\n                    newLine +\n                    'Some PayPal solutions conflict.' +\n                    newLine +\n                    'Please re-enable the previously enabled payment solutions.'\n                });\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        removeCreditOption: function ($target, $owner, data) {\n            if ($target.find(data.dependsButtonLabel + ' option[value=\"credit\"]').length > 0) {\n                $target.find(data.dependsButtonLabel + ' option[value=\"credit\"]').remove();\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        addCreditOption: function ($target, $owner, data) {\n            if ($target.find(data.dependsButtonLabel + ' option[value=\"credit\"]').length === 0) {\n                $target.find(data.dependsButtonLabel).append('<option value=\"credit\">Credit</option>');\n            }\n        },\n\n        /**\n         * @param {*} $target\n         * @param {*} $owner\n         * @param {Object} data\n         */\n        removeCreditOptionConditional: function ($target, $owner, data) {\n            if ($target.find(data.dependsDisableFundingOptions + ' option[value=\"CREDIT\"]').length === 0 ||\n                $target.find(data.dependsDisableFundingOptions + ' option[value=\"CREDIT\"]:selected').length > 0\n            ) {\n                this.removeCreditOption($target, $owner, data);\n            }\n        }\n    });\n});\n","Magento_Paypal/js/solution.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'uiClass',\n    'Magento_Paypal/js/rule',\n    'mageUtils',\n    'underscore'\n], function ($, Class, Rule, utils, _) {\n    'use strict';\n\n    return Class.extend({\n        defaults: {\n\n            /**\n             * The event corresponding to the state change\n             */\n            systemEvent: 'change',\n\n            /**\n             * The rules applied after the page is loaded\n             */\n            afterLoadRules: [],\n\n            /**\n             * An attribute of the element responsible for the activation of the payment method (data attribute)\n             */\n            enableButton:   '[data-enable=\"payment\"]',\n\n            /**\n             * An attribute of the element responsible for the activation of the Payflow Express (data attribute)\n             */\n            enableExpress:  '[data-enable=\"express\"]',\n\n            /**\n             * An attribute of the element responsible for the activation of the\n             * PayPal Express In-Context Checkout Experience (data attribute)\n             */\n            enableInContextPayPal: '[data-enable=\"in-context-api\"]',\n\n            /**\n             * An attribute of the element responsible for the activation of the Payflow Bml (data attribute)\n             */\n            enableBml:      '[data-enable=\"bml\"]',\n\n            /**\n             * An attribute of the element responsible for the activation of the PayPal Bml (data attribute)\n             */\n            enableBmlPayPal:      '[data-enable=\"bml-api\"]',\n\n            /**\n             * An attribute of the element responsible for the visibility of the PayPal Merchant Id (data attribute)\n             */\n            dependsMerchantId:  '[data-enable=\"merchant-id\"]',\n\n            /**\n             * An attribute of the element responsible for the visibility of the Payflow Bml Sort Order (data attribute)\n             */\n            dependsBmlSortOrder:    '[data-enable=\"bml-sort-order\"]',\n\n            /**\n             * An attribute of the element responsible for the visibility of the PayPal Bml Sort Order (data attribute)\n             */\n            dependsBmlApiSortOrder:    '[data-enable=\"bml-api-sort-order\"]',\n\n            /**\n             * An attribute of the element responsible for the visibility of the\n             * button Label credit option (data attribute)\n             */\n            dependsButtonLabel: '[data-enable=\"button-label\"]',\n\n            /**\n             * An attribute of the element responsible for the visibility of the\n             * button Label credit option on load (data attribute)\n             */\n            dependsDisableFundingOptions: '[data-enable=\"disable-funding-options\"]',\n\n            /**\n             * Templates element selectors\n             */\n            templates: {\n                elementSelector: 'div.section-config tr[id$=\"${ $.identifier }\"]:first'\n            }\n        },\n\n        /**\n         * Constructor\n         *\n         * @param {Object} config\n         * @param {String} identifier\n         * @returns {exports.initialize}\n         */\n        initialize: function (config, identifier) {\n            this.initConfig(config);\n            this.$self = this.createElement(identifier);\n\n            return this;\n        },\n\n        /**\n         * Initialization events\n         *\n         * @returns {exports.initEvents}\n         */\n        initEvents: function () {\n            _.each(this.config.events, function (elementEvents, selector) {\n\n                var solution = this,\n                    selectorButton = solution.$self.find(selector),\n                    $self = solution.$self,\n                    events = elementEvents;\n\n                selectorButton.on(solution.systemEvent, function () {\n                    _.each(events, function (elementEvent, name) {\n\n                        var predicate = elementEvent.predicate,\n                            result = true,\n\n                            /**\n                             * @param {Function} functionPredicate\n                             */\n                            predicateCallback = function (functionPredicate) {\n                                result = functionPredicate(solution, predicate.message, predicate.argument);\n\n                                if (result) {\n                                    $self.trigger(name);\n                                } else {\n                                    $self.trigger(predicate.event);\n                                }\n                            };\n\n                        if (solution.getValue($(this)) === elementEvent.value ||\n                            $(this).prop('multiple') && solution.checkMultiselectValue($(this), elementEvent)\n                        ) {\n                            if (predicate.name) {\n                                require([\n                                    'Magento_Paypal/js/predicate/' + predicate.name\n                                ], predicateCallback);\n                            } else {\n                                $self.trigger(name);\n                            }\n                        }\n                    }, this);\n                });\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * @param {Object} $element\n         * @returns {*}\n         */\n        getValue: function ($element) {\n            if ($element.is(':checkbox')) {\n                return $element.prop('checked') ? '1' : '0';\n            }\n\n            return $element.val();\n        },\n\n        /**\n         * Check multiselect value based on include value\n         *\n         * @param {Object} $element\n         * @param {Object} elementEvent\n         * @returns {Boolean}\n         */\n        checkMultiselectValue: function ($element, elementEvent) {\n            var isValueSelected = $.inArray(elementEvent.value, $element.val()) >= 0;\n\n            if (elementEvent.include) {\n                isValueSelected = (isValueSelected ? 'true' : 'false') === elementEvent.include;\n            }\n\n            return isValueSelected;\n        },\n\n        /**\n         * Adding event listeners\n         *\n         * @returns {exports.addListeners}\n         */\n        addListeners: function () {\n\n            _.each(this.config.relations, function (rules, targetName) {\n\n                var $target = this.createElement(targetName);\n\n                _.each(rules, function (instances, instanceName) {\n\n                    _.each(instances, function (instance) {\n                        var handler = new Rule({\n                            name: instanceName,\n                            $target: $target,\n                            $owner: this.$self,\n                            data: {\n                                buttonConfiguration: this.buttonConfiguration,\n                                enableButton: this.enableButton,\n                                enableExpress: this.enableExpress,\n                                enableInContextPayPal: this.enableInContextPayPal,\n                                enableBml: this.enableBml,\n                                enableBmlPayPal: this.enableBmlPayPal,\n                                dependsMerchantId: this.dependsMerchantId,\n                                dependsBmlSortOrder: this.dependsBmlSortOrder,\n                                dependsBmlApiSortOrder: this.dependsBmlApiSortOrder,\n                                dependsButtonLabel: this.dependsButtonLabel,\n                                dependsDisableFundingOptions: this.dependsDisableFundingOptions,\n                                solutionsElements: this.solutionsElements,\n                                argument: instance.argument\n                            }\n                        });\n\n                        if (instance.event === ':load') {\n                            this.afterLoadRules.push(handler);\n\n                            return;\n                        }\n\n                        this.$self.on(instance.event, _.bind(handler.apply, handler));\n                    }, this);\n                }, this);\n            }, this);\n\n            return this;\n        },\n\n        /**\n         * Create a jQuery element according to selector\n         *\n         * @param {String} identifier\n         * @returns {*}\n         */\n        createElement: function (identifier) {\n            if (identifier === ':self') {\n                return this.$self;\n            }\n\n            return $(utils.template(this.templates.elementSelector, {\n                'identifier': identifier\n            }));\n        },\n\n        /**\n         * Assign solutions elements\n         *\n         * @param {Object} elements\n         * @returns {exports.setSolutionsElements}\n         */\n        setSolutionsElements: function (elements) {\n            this.solutionsElements = elements;\n\n            return this;\n        }\n    });\n});\n","Magento_Paypal/js/solutions.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'uiClass',\n    'Magento_Paypal/js/solution',\n    'underscore'\n], function ($, Class, Solution, _) {\n    'use strict';\n\n    return Class.extend({\n        defaults: {\n\n            /**\n             * Initialized solutions\n             */\n            solutions: {},\n\n            /**\n             * The elements of created solutions\n             */\n            solutionsElements: {},\n\n            /**\n             * The selector element responsible for configuration of payment method (CSS class)\n             */\n            buttonConfiguration: '.button.action-configure'\n        },\n\n        /**\n         * Constructor\n         *\n         * @param {Object} config\n         * @returns {exports.initialize}\n         */\n        initialize: function (config) {\n            this.initConfig(config)\n                .initSolutions();\n\n            return this;\n        },\n\n        /**\n         * Initialization and configuration solutions\n         *\n         * @returns {exports.initSolutions}\n         */\n        initSolutions: function () {\n            _.each(this.config.solutions, this.addSolution, this);\n            this.initializeSolutions()\n                .wipeButtonsConfiguration();\n            _.each(this.solutions, this.applicationRules);\n\n            return this;\n        },\n\n        /**\n         * The creation and addition of the solution according to the configuration\n         *\n         * @param {Object} solution\n         * @param {String} identifier\n         */\n        addSolution: function (solution, identifier) {\n            this.solutions[identifier] = new Solution({\n                config: solution,\n                buttonConfiguration: this.buttonConfiguration\n            }, identifier);\n            this.solutionsElements[identifier] = this.solutions[identifier].$self;\n        },\n\n        /**\n         * Wiping buttons configuration of the payment method\n         */\n        wipeButtonsConfiguration: function () {\n            $(this.buttonConfiguration).removeClass('disabled')\n                .removeAttr('disabled');\n        },\n\n        /**\n         * Application of the rules\n         *\n         * @param {Object} solution\n         */\n        applicationRules: function (solution) {\n            _.each(solution.afterLoadRules, function (rule) {\n                rule.apply();\n            });\n        },\n\n        /**\n         * Initialize solutions\n         *\n         * @returns {exports.initializeSolutions}\n         */\n        initializeSolutions: function () {\n            _.each(this.solutions, function (solution) {\n                solution.setSolutionsElements(this.solutionsElements)\n                    .initEvents()\n                    .addListeners();\n            }, this);\n\n            return this;\n        }\n    });\n});\n","Magento_Paypal/js/rule.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'uiClass',\n    'Magento_Paypal/js/rules'\n], function (Class, Rules) {\n    'use strict';\n\n    return Class.extend({\n\n        /**\n         * Constructor\n         *\n         * @param {Object} config\n         * @returns {exports.initialize}\n         */\n        initialize: function (config) {\n            this.rules = new Rules();\n            this.initConfig(config);\n\n            return this;\n        },\n\n        /**\n         * To apply the rule\n         */\n        apply: function () {\n            this.rules[this.name](this.$target, this.$owner, this.data);\n        }\n    });\n});\n","Magento_Paypal/js/predicate/confirm.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['underscore'], function (_) {\n    'use strict';\n\n    return function (solution, message, argument) {\n        var isConfirm = false;\n\n        _.every(argument, function (name) {\n            if (solution.solutionsElements[name] &&\n                solution.solutionsElements[name].find(solution.enableButton).val() == 1 //eslint-disable-line eqeqeq\n            ) {\n                isConfirm = true;\n\n                return !isConfirm;\n            }\n\n            return !isConfirm;\n        }, this);\n\n        if (isConfirm) {\n            return confirm(message); //eslint-disable-line no-alert\n        }\n\n        return true;\n    };\n});\n","Magento_Paypal/js/payflowpro/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    'uiComponent'\n], function ($, Class) {\n    'use strict';\n\n    return Class.extend({\n        defaults: {\n            $selector: null,\n            selector: 'edit_form'\n        },\n\n        /**\n         * Set list of observable attributes\n         * @returns {exports.initObservable}\n         */\n        initObservable: function () {\n            var self = this;\n\n            self.$selector = $('#' + self.selector);\n            this._super();\n\n            this.initEventHandlers();\n\n            return this;\n        },\n\n        /**\n         * Get payment code\n         * @returns {String}\n         */\n        getCode: function () {\n            return 'payflowpro';\n        },\n\n        /**\n         * Init event handlers\n         */\n        initEventHandlers: function () {\n            $('#' + this.container).find('[name=\"payment[token_switcher]\"]')\n                .on('click', this.setPaymentDetails.bind(this));\n        },\n\n        /**\n         * Store payment details\n         */\n        setPaymentDetails: function () {\n            this.$selector.find('[name=\"payment[public_hash]\"]').val(this.publicHash);\n        }\n    });\n});\n","Magento_Variable/variables.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global Variables, updateElementAtCursor, MagentovariablePlugin, Base64 */\ndefine([\n    'jquery',\n    'mage/backend/notification',\n    'mage/translate',\n    'wysiwygAdapter',\n    'uiRegistry',\n    'mage/apply/main',\n    'mageUtils',\n    'Magento_Variable/js/config-directive-generator',\n    'Magento_Variable/js/custom-directive-generator',\n    'Magento_Ui/js/lib/spinner',\n    'jquery/ui',\n    'prototype'\n], function (jQuery, notification, $t, wysiwyg, registry, mageApply, utils, configGenerator, customGenerator, loader) {\n    'use strict';\n\n    window.Variables = {\n        textareaElementId: null,\n        variablesContent: null,\n        dialogWindow: null,\n        dialogWindowId: 'variables-chooser',\n        overlayShowEffectOptions: null,\n        overlayHideEffectOptions: null,\n        insertFunction: 'Variables.insertVariable',\n        selectedPlaceholder: null,\n        isEditMode: null,\n        editor: null,\n\n        /**\n         * Initialize Variables handler.\n         *\n         * @param {*} textareaElementId\n         * @param {Function} insertFunction\n         * @param {Object} editor\n         * @param {Object} selectedPlaceholder\n         */\n        init: function (textareaElementId, insertFunction, editor, selectedPlaceholder) {\n            if ($(textareaElementId)) {\n                this.textareaElementId = textareaElementId;\n            }\n\n            if (insertFunction) {\n                this.insertFunction = insertFunction;\n            }\n\n            if (selectedPlaceholder) {\n                this.selectedPlaceholder = selectedPlaceholder;\n            }\n\n            if (editor) {\n                this.editor = editor;\n            }\n        },\n\n        /**\n         * Reset data.\n         */\n        resetData: function () {\n            this.variablesContent = null;\n            this.dialogWindow = null;\n        },\n\n        /**\n         * Open variables chooser slideout.\n         *\n         * @param {Object} variables\n         */\n        openVariableChooser: function (variables) {\n            if (variables) {\n                this.openDialogWindow(variables);\n            }\n        },\n\n        /**\n         * Close variables chooser slideout dialog window.\n         */\n        closeDialogWindow: function () {\n            jQuery('#' + this.dialogWindowId).modal('closeModal');\n        },\n\n        /**\n         * Init ui component grid on the form\n         *\n         * @return void\n         */\n        initUiGrid: function () {\n            mageApply.apply(document.getElementById(this.dialogWindow));\n            jQuery('#' + this.dialogWindowId).applyBindings();\n            loader.get('variables_modal.variables_modal.variables').hide();\n        },\n\n        /**\n         * Open slideout dialog window.\n         *\n         * @param {*} variablesContent\n         * @param {Object} selectedElement\n         */\n        openDialogWindow: function (variablesContent, selectedElement) {\n\n            var html = utils.copy(variablesContent),\n                self = this;\n\n            jQuery('<div id=\"' + this.dialogWindowId + '\">' + html + '</div>').modal({\n                title: self.isEditMode ? $t('Edit Variable') : $t('Insert Variable'),\n                type: 'slide',\n                buttons: self.getButtonsConfig(self.isEditMode),\n\n                /**\n                 * @param {jQuery.Event} e\n                 * @param {Object} modal\n                 */\n                closed: function (e, modal) {\n                    modal.modal.remove();\n                    registry.get(\n                        'variables_modal.variables_modal.variables.variable_selector',\n                        function (radioSelect) {\n                            radioSelect.selectedVariableCode('');\n                        }\n                    );\n                }\n            });\n\n            this.selectedPlaceholder = selectedElement;\n\n            this.addNotAvailableMessage(selectedElement);\n\n            jQuery('#' + this.dialogWindowId).modal('openModal');\n\n            if (typeof selectedElement !== 'undefined') {\n                registry.get(\n                    'variables_modal.variables_modal.variables.variable_selector',\n                    function (radioSelect) {\n                        radioSelect.selectedVariableCode(MagentovariablePlugin.getElementVariablePath(selectedElement));\n                    }\n                );\n            }\n        },\n\n        /**\n         * Add message to slide out that variable is no longer available\n         *\n         * @param {Object} selectedElement\n         */\n        addNotAvailableMessage: function (selectedElement) {\n            var name,\n                msg,\n                variablePath,\n                $wrapper,\n                lostVariableClass = 'magento-placeholder-error';\n\n            if (\n                this.isEditMode &&\n                typeof selectedElement !== 'undefined' &&\n                jQuery(selectedElement).hasClass(lostVariableClass)\n            ) {\n\n                variablePath = MagentovariablePlugin.getElementVariablePath(selectedElement);\n                name = variablePath.split(':');\n                msg = $t('The variable %1 is no longer available. Select a different variable.')\n                    .replace('%1', name[1]);\n\n                jQuery('body').notification('clear')\n                    .notification('add', {\n                        error: true,\n                        message: msg,\n\n                        /**\n                         * @param {String} message\n                         */\n                        insertMethod: function (message) {\n                            $wrapper = jQuery('<div/>').html(message);\n\n                            jQuery('.modal-header .page-main-actions').after($wrapper);\n                        }\n                    });\n            }\n        },\n\n        /**\n         * Get selected variable directive.\n         *\n         * @returns {*}\n         */\n        getVariableCode: function () {\n            var code = registry.get('variables_modal.variables_modal.variables.variable_selector')\n                    .selectedVariableCode(),\n                directive = code;\n\n            // processing switch here as content must contain only path/code without type\n            if (typeof code !== 'undefined') {\n                if (code.match('^default:')) {\n                    directive = configGenerator.processConfig(code.replace('default:', ''));\n                } else if (code.match('^custom:')) {\n                    directive = customGenerator.processConfig(code.replace('custom:', ''));\n                }\n\n                return directive;\n            }\n        },\n\n        /**\n         * Get buttons configuration for slideout dialog.\n         *\n         * @param {Boolean} isEditMode\n         *\n         * @returns {Array}\n         */\n        getButtonsConfig: function (isEditMode) {\n\n            var self = this,\n                buttonsData;\n\n            buttonsData = [\n                {\n\n                    text: $t('Cancel'),\n                    'class': 'action-scalable cancel',\n\n                    /**\n                     * @param {jQuery.Event} event\n                     */\n                    click: function (event) {\n                        this.closeModal(event);\n                    }\n                },\n                {\n\n                    text: isEditMode ? $t('Save') : $t('Insert Variable'),\n                    class: 'action-primary ' + (isEditMode ? '' : 'disabled'),\n                    attr: {\n                        'id': 'insert_variable'\n                    },\n\n                    /**\n                     * Insert Variable\n                     */\n                    click: function () {\n                        self.insertVariable(self.getVariableCode());\n                    }\n                }\n            ];\n\n            return buttonsData;\n        },\n\n        /**\n         * Prepare variables row.\n         *\n         * @param {String} varValue\n         * @param {*} varLabel\n         * @return {String}\n         * @deprecated This method isn't relevant after ui changes\n         */\n        prepareVariableRow: function (varValue, varLabel) {\n            var value = varValue.replace(/\"/g, '&quot;').replace(/'/g, '\\\\&#39;');\n\n            return '<a href=\"#\" onclick=\"' +\n                this.insertFunction +\n                '(\\'' +\n                value +\n                '\\');return false;\">' +\n                varLabel +\n                '</a>';\n        },\n\n        /**\n         * Insert variable into WYSIWYG editor.\n         *\n         * @param {*} value\n         * @return {Object}\n         */\n        insertVariable: function (value) {\n            var windowId = this.dialogWindowId,\n                textareaElm, scrollPos, wysiwygEditorFocused;\n\n            jQuery('#' + windowId).modal('closeModal');\n            textareaElm = $(this.textareaElementId);\n\n            //to support switching between wysiwyg editors\n            wysiwygEditorFocused = wysiwyg && wysiwyg.activeEditor();\n\n            if (wysiwygEditorFocused && wysiwyg.get(this.textareaElementId)) {\n                if (jQuery(this.selectedPlaceholder).hasClass('magento-placeholder')) {\n                    wysiwyg.setCaretOnElement(this.selectedPlaceholder, 1);\n                }\n                wysiwyg.insertContent(value, false);\n\n                if (this.selectedPlaceholder && jQuery(this.selectedPlaceholder).hasClass('magento-placeholder')) {\n                    this.selectedPlaceholder.remove();\n                }\n\n            } else if (textareaElm) {\n                scrollPos = textareaElm.scrollTop;\n                updateElementAtCursor(textareaElm, value);\n                textareaElm.focus();\n                textareaElm.scrollTop = scrollPos;\n                jQuery(textareaElm).change();\n                textareaElm = null;\n            }\n\n            return this;\n        }\n\n    };\n\n    window.MagentovariablePlugin = {\n        editor: null,\n        variables: null,\n        textareaId: null,\n\n        /**\n         * Bind editor.\n         *\n         * @param {*} editor\n         */\n        setEditor: function (editor) {\n            this.editor = editor;\n        },\n\n        /**\n         * Load variables chooser.\n         *\n         * @param {String} url\n         * @param {*} textareaId\n         * @param {Object} selectedElement\n         *\n         * @return {Object}\n         */\n        loadChooser: function (url, textareaId, selectedElement) {\n            this.textareaId = textareaId;\n\n            new Ajax.Request(url, {\n                parameters: {},\n                onComplete: function (transport) {\n                    Variables.init(this.textareaId, 'MagentovariablePlugin.insertVariable', this.editor);\n                    Variables.isEditMode = !!this.getElementVariablePath(selectedElement);\n                    this.variablesContent = transport.responseText;\n                    Variables.openDialogWindow(this.variablesContent, selectedElement);\n                    Variables.initUiGrid();\n                }.bind(this)\n            });\n\n            return this;\n        },\n\n        /**\n         * Open variables chooser window.\n         *\n         * @param {*} variables\n         * @deprecated This method isn't relevant after ui changes\n         */\n        openChooser: function (variables) {\n            Variables.openVariableChooser(variables);\n        },\n\n        /**\n         * Insert variable.\n         *\n         * @param {*} value\n         *\n         * @return {Object}\n         */\n        insertVariable: function (value) {\n            if (this.textareaId) {\n                Variables.init(this.textareaId);\n                Variables.insertVariable(value);\n            } else {\n                Variables.closeDialogWindow();\n                Variables.insertVariable(value);\n            }\n\n            return this;\n        },\n\n        /**\n         * Get element variable path.\n         *\n         * @param {Object} element\n         * @returns {String}\n         */\n        getElementVariablePath: function (element) {\n            var type, code;\n\n            if (!element || !jQuery(element).hasClass('magento-variable')) {\n                return '';\n            }\n            type = jQuery(element).hasClass('magento-custom-var') ? 'custom' : 'default';\n            code = Base64.idDecode(element.getAttribute('id'));\n\n            return type + ':' + code;\n        }\n    };\n});\n","Magento_Variable/js/custom-directive-generator.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 _.extend({\n        directiveTemplate: '{{customVar code=%s}}',\n\n        /**\n         * @param {String} path\n         * @return {String}\n         */\n        processConfig: function (path) {\n            return this.directiveTemplate.replace('%s', path);\n        }\n\n    });\n\n});\n","Magento_Variable/js/config-directive-generator.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 _.extend({\n        directiveTemplate: '{{config path=\"%s\"}}',\n\n        /**\n         * @param {String} path\n         * @return {String}\n         */\n        processConfig: function (path) {\n            return this.directiveTemplate.replace('%s', path);\n\n        }\n\n    });\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","Magefan_Blog/js/components/new-category.js":"/**\n * Copyright \u00a9 2016 Ihor Vansach (ihor@magefan.com). All rights reserved.\n * See LICENSE.txt for license details (http://opensource.org/licenses/osl-3.0.php).\n *\n * Glory to Ukraine! Glory to the heroes!\n */\n\ndefine([\n    'Magefan_Blog/js/components/new-tag'\n], function (Select) {\n    'use strict';\n\n    return Select.extend({\n\n        /**\n         * Normalize option object.\n         *\n         * @param {Object} data - Option object.\n         * @returns {Object}\n         */\n        parseData: function (data) {\n            return {\n                'is_active': data.model['is_active'],\n                level: data.model['level'],\n                value: data.model['category_id'],\n                label: data.model['title'],\n                parent: data.model['parent_id']\n            };\n        }\n    });\n});\n","Magefan_Blog/js/components/new-tag.js":"/**\n * Copyright \u00a9 2016 Ihor Vansach (ihor@magefan.com). All rights reserved.\n * See LICENSE.txt for license details (http://opensource.org/licenses/osl-3.0.php).\n *\n * Glory to Ukraine! Glory to the heroes!\n */\n\ndefine([\n    'underscore',\n    'Magento_Ui/js/form/element/ui-select'\n], function (_, Select) {\n    'use strict';\n\n    function flatten(a, s, cr) {\n        var i = 0, c;\n        a = _.compact(a);\n        cr = cr || [];\n        for (i; i < a.length; i++) {\n            cr.push(a[i]);\n            if (a[i].hasOwnProperty(s)) {\n                c = a[i][s];\n                delete a[i][s];\n                flatten.call(this, c, s, cr);\n            }\n        }\n        return cr;\n    }\n\n    return Select.extend({\n\n        /**\n         * Parse data and set it to options.\n         *\n         * @param {Object} data - Response data object.\n         * @returns {Object}\n         */\n        setParsed: function (data) {\n            var option = this.parseData(data),\n                copyOptionsTree\n            if (data.error) {\n                return this;\n            }\n\n            this.options([]);\n            if (!option.parent) {\n                this.cacheOptions.tree.push(option);\n                copyOptionsTree = JSON.parse(JSON.stringify(this.cacheOptions.tree));\n                this.cacheOptions.plain = flatten(copyOptionsTree, this.separator);\n                this.options(this.cacheOptions.tree);\n            } else {\n                this.setOption(option);\n            }\n            this.set('newOption', option);\n        },\n\n        /**\n         * Normalize option object.\n         *\n         * @param {Object} data - Option object.\n         * @returns {Object}\n         */\n        parseData: function (data) {\n            return {\n                'is_active': \"1\",\n                level: 0,\n                value: data.model['tag_id'],\n                label: data.model['title'],\n                parent: 0\n            };\n        }\n    });\n});\n","Magento_Swatches/js/type-change.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\nrequire([\n    'jquery',\n    'mage/translate'\n], function ($) {\n    'use strict';\n\n    $(function () {\n\n        // disabled select only\n        $('select#frontend_input:disabled').each(function () {\n            var select = $(this),\n                currentValue = select.find('option:selected').val(),\n                enabledTypes = ['select', 'swatch_visual', 'swatch_text'],\n                warning = $('<label>')\n                    .hide()\n                    .text($.mage.__('These changes affect all related products.'))\n                    .addClass('mage-error')\n                    .attr({\n                        generated: true, for: select.attr('id')\n                    }),\n\n                /**\n                 * Toggle hint about changes types\n                 */\n                toggleWarning = function () {\n                    if (select.find('option:selected').val() === currentValue) {\n                        warning.hide();\n                    } else {\n                        warning.show();\n                    }\n                },\n\n                /**\n                 * Remove unsupported options\n                 */\n                removeOption = function () {\n                    if (!~enabledTypes.indexOf($(this).val())) {\n                        $(this).remove();\n                    }\n                };\n\n            // Check current type (allow only: select, swatch_visual, swatch_text)\n            if (!~enabledTypes.indexOf(currentValue)) {\n                return;\n            }\n\n            // Enable select and keep only available options (all other will be removed)\n            select.removeAttr('disabled').find('option').each(removeOption);\n\n            // Add warning on page and event for show/hide it\n            select.after(warning).on('change', toggleWarning);\n        });\n    });\n});\n","Magento_Swatches/js/product-attributes.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/alert',\n    'Magento_Ui/js/modal/prompt',\n    'uiRegistry',\n    'collapsable'\n], function ($, alert, prompt, rg) {\n    'use strict';\n\n    return function (optionConfig) {\n        var activePanelClass = 'selected-type-options',\n            swatchProductAttributes = {\n                frontendInput: $('#frontend_input'),\n                isFilterable: $('#is_filterable'),\n                isFilterableInSearch: $('#is_filterable_in_search'),\n                backendType: $('#backend_type'),\n                usedForSortBy: $('#used_for_sort_by'),\n                frontendClass: $('#frontend_class'),\n                isWysiwygEnabled: $('#is_wysiwyg_enabled'),\n                isHtmlAllowedOnFront: $('#is_html_allowed_on_front'),\n                isRequired: $('#is_required'),\n                isUnique: $('#is_unique'),\n                defaultValueText: $('#default_value_text'),\n                defaultValueTextarea: $('#default_value_textarea'),\n                defaultValueDate: $('#default_value_date'),\n                defaultValueYesno: $('#default_value_yesno'),\n                isGlobal: $('#is_global'),\n                useProductImageForSwatch: $('#use_product_image_for_swatch'),\n                updateProductPreviewImage: $('#update_product_preview_image'),\n                usedInProductListing: $('#used_in_product_listing'),\n                isVisibleOnFront: $('#is_visible_on_front'),\n                position: $('#position'),\n                attrTabsFront: $('#product_attribute_tabs_front'),\n\n                /**\n                 * @returns {*|jQuery|HTMLElement}\n                 */\n                get tabsFront() {\n                    return this.attrTabsFront.length ? this.attrTabsFront.closest('li') : $('#front_fieldset-wrapper');\n                },\n                selectFields: ['boolean', 'select', 'multiselect', 'price', 'swatch_text', 'swatch_visual'],\n\n                /**\n                 * @this {swatchProductAttributes}\n                 */\n                toggleApplyVisibility: function (select) {\n                    if ($(select).val() === 1) {\n                        $(select).next('select').removeClass('no-display');\n                        $(select).next('select').removeClass('ignore-validate');\n                    } else {\n                        $(select).next('select').addClass('no-display');\n                        $(select).next('select').addClass('ignore-validate');\n                        $(select).next('select option:selected').each(function () {\n                            this.selected = false;\n                        });\n                    }\n                },\n\n                /**\n                 * @this {swatchProductAttributes}\n                 */\n                checkOptionsPanelVisibility: function () {\n                    var selectOptionsPanel = $('#manage-options-panel'),\n                        visualOptionsPanel = $('#swatch-visual-options-panel'),\n                        textOptionsPanel = $('#swatch-text-options-panel');\n\n                    this._hidePanel(selectOptionsPanel);\n                    this._hidePanel(visualOptionsPanel);\n                    this._hidePanel(textOptionsPanel);\n\n                    switch (this.frontendInput.val()) {\n                        case 'swatch_visual':\n                            this._showPanel(visualOptionsPanel);\n                            break;\n\n                        case 'swatch_text':\n                            this._showPanel(textOptionsPanel);\n                            break;\n\n                        case 'select':\n                        case 'multiselect':\n                            this._showPanel(selectOptionsPanel);\n                            break;\n                    }\n                },\n\n                /**\n                 * @this {swatchProductAttributes}\n                 */\n                bindAttributeInputType: function () {\n                    this.checkOptionsPanelVisibility();\n                    this.switchDefaultValueField();\n\n                    if (!~$.inArray(this.frontendInput.val(), this.selectFields)) {\n                        // not in array\n                        this.isFilterable.selectedIndex = 0;\n                        this._disable(this.isFilterable);\n                        this._disable(this.isFilterableInSearch);\n                    } else {\n                        // in array\n                        this._enable(this.isFilterable);\n                        this._enable(this.isFilterableInSearch);\n                        this.backendType.val('int');\n                    }\n\n                    if (this.frontendInput.val() === 'multiselect' ||\n                        this.frontendInput.val() === 'gallery' ||\n                        this.frontendInput.val() === 'textarea'\n                    ) {\n                        this._disable(this.usedForSortBy);\n                    } else {\n                        this._enable(this.usedForSortBy);\n                    }\n\n                    if (this.frontendInput.val() === 'swatch_text') {\n                        $('.swatch-text-field-0').addClass('required-option');\n                    } else {\n                        $('.swatch-text-field-0').removeClass('required-option');\n                    }\n\n                    this.setRowVisibility(this.isWysiwygEnabled, false);\n                    this.setRowVisibility(this.isHtmlAllowedOnFront, false);\n\n                    switch (this.frontendInput.val()) {\n                        case 'textarea':\n                            this.setRowVisibility(this.isWysiwygEnabled, true);\n\n                            if (this.isWysiwygEnabled.val() === '0') {\n                                this._enable(this.isHtmlAllowedOnFront);\n                            }\n                            this.frontendClass.val('');\n                            this._disable(this.frontendClass);\n                            break;\n\n                        case 'text':\n                            this.setRowVisibility(this.isHtmlAllowedOnFront, true);\n                            this._enable(this.frontendClass);\n                            break;\n\n                        case 'select':\n                        case 'multiselect':\n                            this.setRowVisibility(this.isHtmlAllowedOnFront, true);\n                            this.frontendClass.val('');\n                            this._disable(this.frontendClass);\n                            break;\n                        default:\n                            this.frontendClass.val('');\n                            this._disable(this.frontendClass);\n                    }\n\n                    this.switchIsFilterable();\n                },\n\n                /**\n                 * @this {swatchProductAttributes}\n                 */\n                switchIsFilterable: function () {\n                    if (this.isFilterable.selectedIndex === 0) {\n                        this._disable(this.position);\n                    } else {\n                        this._enable(this.position);\n                    }\n                },\n\n                /**\n                 * @this {swatchProductAttributes}\n                 */\n                switchDefaultValueField: function () {\n                    var currentValue = this.frontendInput.val(),\n                        defaultValueTextVisibility = false,\n                        defaultValueTextareaVisibility = false,\n                        defaultValueDateVisibility = false,\n                        defaultValueYesnoVisibility = false,\n                        scopeVisibility = true,\n                        useProductImageForSwatch = false,\n                        defaultValueUpdateImage = false,\n                        optionDefaultInputType = '',\n                        isFrontTabHidden = false,\n                        thing = this;\n\n                    if (!this.frontendInput.length) {\n                        return;\n                    }\n\n                    switch (currentValue) {\n                        case 'select':\n                            optionDefaultInputType = 'radio';\n                            break;\n\n                        case 'multiselect':\n                            optionDefaultInputType = 'checkbox';\n                            break;\n\n                        case 'date':\n                            defaultValueDateVisibility = true;\n                            break;\n\n                        case 'boolean':\n                            defaultValueYesnoVisibility = true;\n                            break;\n\n                        case 'textarea':\n                        case 'texteditor':\n                            defaultValueTextareaVisibility = true;\n                            break;\n\n                        case 'media_image':\n                            defaultValueTextVisibility = false;\n                            break;\n\n                        case 'price':\n                            scopeVisibility = false;\n                            break;\n\n                        case 'swatch_visual':\n                            useProductImageForSwatch = true;\n                            defaultValueUpdateImage = true;\n                            defaultValueTextVisibility = false;\n                            break;\n\n                        case 'swatch_text':\n                            useProductImageForSwatch = false;\n                            defaultValueUpdateImage = true;\n                            defaultValueTextVisibility = false;\n                            break;\n                        default:\n                            defaultValueTextVisibility = true;\n                            break;\n                    }\n\n                    delete optionConfig.hiddenFields['swatch_visual'];\n                    delete optionConfig.hiddenFields['swatch_text'];\n\n                    if (currentValue === 'media_image') {\n                        this.tabsFront.hide();\n                        this.setRowVisibility(this.isRequired, false);\n                        this.setRowVisibility(this.isUnique, false);\n                        this.setRowVisibility(this.frontendClass, false);\n                    } else if (optionConfig.hiddenFields[currentValue]) {\n                        $.each(optionConfig.hiddenFields[currentValue], function (key, option) {\n                            switch (option) {\n                                case '_front_fieldset':\n                                    thing.tabsFront.hide();\n                                    isFrontTabHidden = true;\n                                    break;\n\n                                case '_default_value':\n                                    defaultValueTextVisibility = false;\n                                    defaultValueTextareaVisibility = false;\n                                    defaultValueDateVisibility = false;\n                                    defaultValueYesnoVisibility = false;\n                                    break;\n\n                                case '_scope':\n                                    scopeVisibility = false;\n                                    break;\n                                default:\n                                    thing.setRowVisibility($('#' + option), false);\n                            }\n                        });\n\n                        if (!isFrontTabHidden) {\n                            thing.tabsFront.show();\n                        }\n\n                    } else {\n                        this.tabsFront.show();\n                        this.showDefaultRows();\n                    }\n\n                    this.setRowVisibility(this.defaultValueText, defaultValueTextVisibility);\n                    this.setRowVisibility(this.defaultValueTextarea, defaultValueTextareaVisibility);\n                    this.setRowVisibility(this.defaultValueDate, defaultValueDateVisibility);\n                    this.setRowVisibility(this.defaultValueYesno, defaultValueYesnoVisibility);\n                    this.setRowVisibility(this.isGlobal, scopeVisibility);\n\n                    /* swatch attributes */\n                    this.setRowVisibility(this.useProductImageForSwatch, useProductImageForSwatch);\n                    this.setRowVisibility(this.updateProductPreviewImage, defaultValueUpdateImage);\n\n                    $('input[name=\\'default[]\\']').each(function () {\n                        $(this).attr('type', optionDefaultInputType);\n                    });\n                },\n\n                /**\n                 * @this {swatchProductAttributes}\n                 */\n                showDefaultRows: function () {\n                    this.setRowVisibility(this.isRequired, true);\n                    this.setRowVisibility(this.isUnique, true);\n                    this.setRowVisibility(this.frontendClass, true);\n                },\n\n                /**\n                 * @param {Object} el\n                 * @param {Boolean} isVisible\n                 * @this {swatchProductAttributes}\n                 */\n                setRowVisibility: function (el, isVisible) {\n                    if (isVisible) {\n                        el.show();\n                        el.closest('.field').show();\n                    } else {\n                        el.hide();\n                        el.closest('.field').hide();\n                    }\n                },\n\n                /**\n                 * @param {Object} el\n                 * @this {swatchProductAttributes}\n                 */\n                _disable: function (el) {\n                    el.attr('disabled', 'disabled');\n                },\n\n                /**\n                 * @param {Object} el\n                 * @this {swatchProductAttributes}\n                 */\n                _enable: function (el) {\n                    if (!el.attr('readonly')) {\n                        el.removeAttr('disabled');\n                    }\n                },\n\n                /**\n                 * @param {Object} el\n                 * @this {swatchProductAttributes}\n                 */\n                _showPanel: function (el) {\n                    el.closest('.fieldset').show();\n                    el.addClass(activePanelClass);\n                    this._render(el.attr('id'));\n                },\n\n                /**\n                 * @param {Object} el\n                 * @this {swatchProductAttributes}\n                 */\n                _hidePanel: function (el) {\n                    el.closest('.fieldset').hide();\n                    el.removeClass(activePanelClass);\n                },\n\n                /**\n                 * @param {String} id\n                 * @this {swatchProductAttributes}\n                 */\n                _render: function (id) {\n                    rg.get(id, function () {\n                        $('#' + id).trigger('render');\n                    });\n                },\n\n                /**\n                 * @param {String} promptMessage\n                 * @this {swatchProductAttributes}\n                 */\n                saveAttributeInNewSet: function (promptMessage) {\n\n                    prompt({\n                        content: promptMessage,\n                        actions: {\n\n                            /**\n                             * @param {String} val\n                             * @this {actions}\n                             */\n                            confirm: function (val) {\n                                var rules = ['required-entry', 'validate-no-html-tags'],\n                                    newAttributeSetNameInputId = $('#new_attribute_set_name'),\n                                    editForm = $('#edit_form'),\n                                    newAttributeSetName = val,\n                                    i;\n\n                                if (!newAttributeSetName) {\n                                    return;\n                                }\n\n                                for (i = 0; i < rules.length; i++) {\n                                    if (!$.validator.methods[rules[i]](newAttributeSetName)) {\n                                        alert({\n                                            content: $.validator.messages[rules[i]]\n                                        });\n\n                                        return;\n                                    }\n                                }\n\n                                if (newAttributeSetNameInputId.length) {\n                                    newAttributeSetNameInputId.val(newAttributeSetName);\n                                } else {\n                                    editForm.append(new Element('input', {\n                                            type: 'hidden',\n                                            id: newAttributeSetNameInputId,\n                                            name: 'new_attribute_set_name',\n                                            value: newAttributeSetName\n                                        })\n                                    );\n                                }\n                                // Temporary solution will replaced after refactoring of attributes functionality\n                                editForm.triggerHandler('save');\n                            }\n                        }\n                    });\n                }\n            };\n\n        $(function () {\n            var editForm = $('#edit_form'),\n                swatchVisualPanel = $('#swatch-visual-options-panel'),\n                swatchTextPanel = $('#swatch-text-options-panel'),\n                tableBody = $(),\n                activePanel = $();\n\n            $('#frontend_input').bind('change', function () {\n                swatchProductAttributes.bindAttributeInputType();\n            });\n            $('#is_filterable').bind('change', function () {\n                swatchProductAttributes.switchIsFilterable();\n            });\n\n            swatchProductAttributes.bindAttributeInputType();\n\n            // @todo: refactor collapsible component\n            $('.attribute-popup .collapse, [data-role=\"advanced_fieldset-content\"]')\n                .collapsable()\n                .collapse('hide');\n\n            editForm.on('beforeSubmit', function () {\n                var optionContainer, optionsValues;\n\n                activePanel = swatchTextPanel.hasClass(activePanelClass) ? swatchTextPanel : swatchVisualPanel;\n                optionContainer = activePanel.find('table tbody');\n\n                if (activePanel.hasClass(activePanelClass)) {\n                    optionsValues = $.map(\n                        optionContainer.find('tr'),\n                        function (row) {\n                            return $(row).find('input, select, textarea').serialize();\n                        }\n                    );\n                    $('<input>')\n                        .attr({\n                            type: 'hidden',\n                            name: 'serialized_options'\n                        })\n                        .val(JSON.stringify(optionsValues))\n                        .prependTo(editForm);\n                }\n\n                tableBody = optionContainer.detach();\n            });\n\n            editForm.on('afterValidate.error highlight.validate', function () {\n                if (activePanel.hasClass(activePanelClass)) {\n                    activePanel.find('table').append(tableBody);\n                    $('input[name=\"serialized_options\"]').remove();\n                }\n            });\n        });\n\n        window.saveAttributeInNewSet = swatchProductAttributes.saveAttributeInNewSet;\n        window.toggleApplyVisibility = swatchProductAttributes.toggleApplyVisibility;\n    };\n});\n","Magento_Swatches/js/visual.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global $break $ $$ FORM_KEY */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'mage/template',\n    'uiRegistry',\n    'jquery/colorpicker/js/colorpicker',\n    'prototype',\n    'jquery/ui'\n], function (jQuery, mageTemplate, rg) {\n    'use strict';\n\n    return function (config) {\n        var swatchOptionVisualDefaultInputType = 'radio',\n            swatchVisualOption = {\n                table: $('swatch-visual-options-table'),\n                itemCount: 0,\n                totalItems: 0,\n                rendered: 0,\n                isReadOnly: config.isReadOnly,\n                template: mageTemplate('#swatch-visual-row-template'),\n\n                /**\n                 * Add new option using template\n                 *\n                 * @param {Object} data\n                 * @param {Object} render\n                 */\n                add: function (data, render) {\n                    var isNewOption = false,\n                        element;\n\n                    if (typeof data.id == 'undefined') {\n                        data = {\n                            'id': 'option_' + this.itemCount,\n                            'sort_order': this.itemCount + 1,\n                            'empty_class': 'unavailable'\n                        };\n                        isNewOption = true;\n                    } else if (data.defaultswatch0 === '') {\n                        data['empty_class'] = 'unavailable';\n                    }\n\n                    if (!data.intype) {\n                        data.intype = swatchOptionVisualDefaultInputType;\n                    }\n\n                    element = this.template({\n                        data: data\n                    });\n\n                    if (isNewOption && !this.isReadOnly) {\n                        this.enableNewOptionDeleteButton(data.id);\n                    }\n                    this.itemCount++;\n                    this.totalItems++;\n                    this.elements += element;\n\n                    if (render) {\n                        this.render();\n                    }\n                },\n\n                /**\n                 * ColorPicker initialization process\n                 */\n                initColorPicker: function () {\n                    var element = this,\n                        hiddenColorPicker = !jQuery(element).data('colorpickerId');\n\n                    jQuery(this).ColorPicker({\n\n                        /**\n                         * ColorPicker onShow action\n                         */\n                        onShow: function () {\n                            var color = jQuery(element).parent().parent().prev().prev('input').val(),\n                                menu = jQuery(this).parents('.swatch_sub-menu_container');\n\n                            menu.hide();\n                            jQuery(element).ColorPickerSetColor(color);\n                        },\n\n                        /**\n                         * ColorPicker onSubmit action\n                         *\n                         * @param {String} hsb\n                         * @param {String} hex\n                         * @param {String} rgb\n                         * @param {String} el\n                         */\n                        onSubmit: function (hsb, hex, rgb, el) {\n                            var container = jQuery(el).parent().parent().prev();\n\n                            jQuery(el).ColorPickerHide();\n                            container.parent().removeClass('unavailable');\n                            container.prev('input').val('#' + hex);\n                            container.css('background', '#' + hex);\n                        }\n                    });\n\n                    if (hiddenColorPicker) {\n                        jQuery(this).ColorPickerShow();\n                    }\n                },\n\n                /**\n                 * Remove action\n                 *\n                 * @param {Object} event\n                 */\n                remove: function (event) {\n                    var element = $(Event.findElement(event, 'tr')),\n                        elementFlags; // !!! Button already have table parent in safari\n\n                    // Safari workaround\n                    element.ancestors().each(function (parentItem) {\n                        if (parentItem.hasClassName('option-row')) {\n                            element = parentItem;\n                            throw $break;\n                        } else if (parentItem.hasClassName('box')) {\n                            throw $break;\n                        }\n                    });\n\n                    if (element) {\n                        elementFlags = element.getElementsByClassName('delete-flag');\n\n                        if (elementFlags[0]) {\n                            elementFlags[0].value = 1;\n                        }\n\n                        element.addClassName('no-display');\n                        element.addClassName('template');\n                        element.hide();\n                        this.totalItems--;\n                        this.updateItemsCountField();\n                    }\n                },\n\n                /**\n                 * Update items count field\n                 */\n                updateItemsCountField: function () {\n                    $('swatch-visual-option-count-check').value = this.totalItems > 0 ? '1' : '';\n                },\n\n                /**\n                 * Enable delete button for new option\n                 *\n                 * @param {String} id\n                 */\n                enableNewOptionDeleteButton: function (id) {\n                    $$('#delete_button_swatch_container_' + id + ' button').each(function (button) {\n                        button.enable();\n                        button.removeClassName('disabled');\n                    });\n                },\n\n                /**\n                 * Bind remove button\n                 */\n                bindRemoveButtons: function () {\n                    jQuery('#swatch-visual-options-panel').on('click', '.delete-option', this.remove.bind(this));\n                },\n\n                /**\n                 * Render options\n                 */\n                render: function () {\n                    Element.insert($$('[data-role=swatch-visual-options-container]')[0], this.elements);\n                    this.elements = '';\n                },\n\n                /**\n                 * Render elements with delay (performance fix)\n                 *\n                 * @param {Object} data\n                 * @param {Number} from\n                 * @param {Number} step\n                 * @param {Number} delay\n                 * @returns {Boolean}\n                 */\n                renderWithDelay: function (data, from, step, delay) {\n                    var arrayLength = data.length,\n                        len;\n\n                    for (len = from + step; from < len && from < arrayLength; from++) {\n                        this.add(data[from]);\n                    }\n                    this.render();\n\n                    if (from === arrayLength) {\n                        this.updateItemsCountField();\n                        this.rendered = 1;\n                        jQuery('body').trigger('processStop');\n\n                        return true;\n                    }\n                    setTimeout(this.renderWithDelay.bind(this, data, from, step, delay), delay);\n                },\n\n                /**\n                 * Ignore validate action\n                 */\n                ignoreValidate: function () {\n                    var ignore = '.ignore-validate input, ' +\n                        '.ignore-validate select, ' +\n                        '.ignore-validate textarea';\n\n                    jQuery('#edit_form').data('validator').settings.forceIgnore = ignore;\n                }\n            };\n\n        if ($('add_new_swatch_visual_option_button')) {\n            Event.observe(\n                'add_new_swatch_visual_option_button',\n                'click',\n                swatchVisualOption.add.bind(swatchVisualOption, {}, true)\n            );\n        }\n\n        jQuery('#swatch-visual-options-panel').on('render', function () {\n            swatchVisualOption.ignoreValidate();\n\n            if (swatchVisualOption.rendered) {\n                return false;\n            }\n            jQuery('body').trigger('processStart');\n            swatchVisualOption.renderWithDelay(config.attributesData, 0, 100, 300);\n            swatchVisualOption.bindRemoveButtons();\n            jQuery('#swatch-visual-options-panel').on(\n                'click',\n                '.colorpicker_handler',\n                swatchVisualOption.initColorPicker\n            );\n        });\n        jQuery('body').on('click', function (event) {\n            var element = jQuery(event.target);\n\n            if (\n                element.parents('.swatch_sub-menu_container').length === 1 ||\n                element.next('div.swatch_sub-menu_container').length === 1\n            ) {\n                return true;\n            }\n            jQuery('.swatch_sub-menu_container').hide();\n        });\n\n        if (config.isSortable) {\n            jQuery(function ($) {\n                $('[data-role=swatch-visual-options-container]').sortable({\n                    distance: 8,\n                    tolerance: 'pointer',\n                    cancel: 'input, button',\n                    axis: 'y',\n\n                    /**\n                     * Update component\n                     */\n                    update: function () {\n                        $('[data-role=swatch-visual-options-container] [data-role=order]').each(\n                            function (index, element) {\n                                $(element).val(index + 1);\n                            }\n                        );\n                    }\n                });\n            });\n        }\n\n        window.swatchVisualOption = swatchVisualOption;\n        window.swatchOptionVisualDefaultInputType = swatchOptionVisualDefaultInputType;\n\n        rg.set('swatch-visual-options-panel', swatchVisualOption);\n\n        jQuery(function ($) {\n\n            var swatchComponents = {\n\n                /**\n                 * div wrapper for to hide all evement\n                 */\n                wrapper: null,\n\n                /**\n                 * iframe component to perform file upload without page reload\n                 */\n                iframe: null,\n\n                /**\n                 * form component for upload image\n                 */\n                form: null,\n\n                /**\n                 * Input file component for upload image\n                 */\n                inputFile: null,\n\n                /**\n                 * Create swatch component for upload files\n                 *\n                 * @this {swatchComponents}\n                 * @public\n                 */\n                create: function () {\n                    this.wrapper = $('<div>').css({\n                        display: 'none'\n                    }).appendTo($('body'));\n\n                    this.iframe = $('<iframe />', {\n                        id:  'upload_iframe',\n                        name: 'upload_iframe'\n                    }).appendTo(this.wrapper);\n\n                    this.form = $('<form />', {\n                        id: 'swatch_form_image_upload',\n                        name: 'swatch_form_image_upload',\n                        target: 'upload_iframe',\n                        method: 'post',\n                        enctype: 'multipart/form-data',\n                        class: 'ignore-validate',\n                        action: config.uploadActionUrl\n                    }).appendTo(this.wrapper);\n\n                    this.inputFile = $('<input />', {\n                        type: 'file',\n                        name: 'datafile',\n                        class: 'swatch_option_file'\n                    }).appendTo(this.form);\n\n                    $('<input />', {\n                        type: 'hidden',\n                        name: 'form_key',\n                        value: FORM_KEY\n                    }).appendTo(this.form);\n                }\n            };\n\n            /**\n             * Create swatch components\n             */\n            swatchComponents.create();\n\n            /**\n             * Register event for swatch input[type=file] change\n             */\n            swatchComponents.inputFile.change(function () {\n                var container = $('#' + $(this).attr('data-called-by')).parents().eq(2).children('.swatch_window'),\n\n                    /**\n                     * @this {iframe}\n                     */\n                    iframeHandler = function () {\n                        var imageParams = $.parseJSON($(this).contents().find('body').html()),\n                            fullMediaUrl = imageParams['swatch_path'] + imageParams['file_path'];\n\n                        container.prev('input').val(imageParams['file_path']);\n                        container.css({\n                            'background-image': 'url(' + fullMediaUrl + ')',\n                            'background-size': 'cover'\n                        });\n                        container.parent().removeClass('unavailable');\n                    };\n\n                swatchComponents.iframe.off('load');\n                swatchComponents.iframe.load(iframeHandler);\n                swatchComponents.form.submit();\n                $(this).val('');\n            });\n\n            /**\n             * Register event for choose \"upload image\" option\n             */\n            $(document).on('click', '.btn_choose_file_upload', function () {\n                swatchComponents.inputFile.attr('data-called-by', $(this).attr('id'));\n                swatchComponents.inputFile.click();\n            });\n\n            /**\n             * Register event for remove option\n             */\n            $(document).on('click', '.btn_remove_swatch', function () {\n                var optionPanel = $(this).parents().eq(2);\n\n                optionPanel.children('input').val('');\n                optionPanel.children('.swatch_window').css('background', '');\n\n                optionPanel.addClass('unavailable');\n\n                jQuery('.swatch_sub-menu_container').hide();\n            });\n\n            /**\n             * Toggle color upload chooser\n             */\n            $(document).on('click', '.swatch_window', function () {\n                $(this).next('div').toggle();\n            });\n        });\n    };\n});\n","Magento_Swatches/js/text.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global $break $ $$ */\n\n/**\n *  @api\n */\ndefine([\n    'jquery',\n    'mage/template',\n    'uiRegistry',\n    'jquery/ui',\n    'prototype'\n], function (jQuery, mageTemplate, rg) {\n    'use strict';\n\n    return function (config) {\n        var swatchOptionTextDefaultInputType = 'radio',\n            swatchTextOption = {\n                table: $('swatch-text-options-table'),\n                itemCount: 0,\n                totalItems: 0,\n                rendered: 0,\n                isReadOnly: config.isReadOnly,\n                template: mageTemplate('#swatch-text-row-template'),\n\n                /**\n                 * Add option\n                 *\n                 * @param {Object} data\n                 * @param {Object} render\n                 */\n                add: function (data, render) {\n                    var isNewOption = false,\n                        element;\n\n                    if (typeof data.id == 'undefined') {\n                        data = {\n                            'id': 'option_' + this.itemCount,\n                            'sort_order': this.itemCount + 1\n                        };\n                        isNewOption = true;\n                    }\n\n                    if (!data.intype) {\n                        data.intype = swatchOptionTextDefaultInputType;\n                    }\n\n                    element = this.template({\n                        data: data\n                    });\n\n                    if (isNewOption && !this.isReadOnly) {\n                        this.enableNewOptionDeleteButton(data.id);\n                    }\n                    this.itemCount++;\n                    this.totalItems++;\n                    this.elements += element;\n\n                    if (render) {\n                        this.render();\n                    }\n                },\n\n                /**\n                 * Remove option\n                 *\n                 * @param {Object} event\n                 */\n                remove: function (event) {\n                    var element = $(Event.findElement(event, 'tr')),\n                        elementFlags; // !!! Button already have table parent in safari\n\n                    // Safari workaround\n                    element.ancestors().each(function (parentItem) {\n                        if (parentItem.hasClassName('option-row')) {\n                            element = parentItem;\n                            throw $break;\n                        } else if (parentItem.hasClassName('box')) {\n                            throw $break;\n                        }\n                    });\n\n                    if (element) {\n                        elementFlags = element.getElementsByClassName('delete-flag');\n\n                        if (elementFlags[0]) {\n                            elementFlags[0].value = 1;\n                        }\n\n                        element.addClassName('no-display');\n                        element.addClassName('template');\n                        element.hide();\n                        this.totalItems--;\n                        this.updateItemsCountField();\n                    }\n                },\n\n                /**\n                 * Update items count field\n                 */\n                updateItemsCountField: function () {\n                    $('swatch-text-option-count-check').value = this.totalItems > 0 ? '1' : '';\n                },\n\n                /**\n                 * Enable delete button for new option\n                 *\n                 * @param {String} id\n                 */\n                enableNewOptionDeleteButton: function (id) {\n                    $$('#delete_button_swatch_container_' + id + ' button').each(function (button) {\n                        button.enable();\n                        button.removeClassName('disabled');\n                    });\n                },\n\n                /**\n                 * Bind remove button\n                 */\n                bindRemoveButtons: function () {\n                    jQuery('#swatch-text-options-panel').on('click', '.delete-option', this.remove.bind(this));\n                },\n\n                /**\n                 * Render action\n                 */\n                render: function () {\n                    Element.insert($$('[data-role=swatch-text-options-container]')[0], this.elements);\n                    this.elements = '';\n                },\n\n                /**\n                 * Render action with delay (performance fix)\n                 *\n                 * @param {Object} data\n                 * @param {Number} from\n                 * @param {Number} step\n                 * @param {Number} delay\n                 * @returns {Boolean}\n                 */\n                renderWithDelay: function (data, from, step, delay) {\n                    var arrayLength = data.length,\n                        len;\n\n                    for (len = from + step; from < len && from < arrayLength; from++) {\n                        this.add(data[from]);\n                    }\n                    this.render();\n\n                    if (from === arrayLength) {\n                        this.updateItemsCountField();\n                        this.rendered = 1;\n                        jQuery('body').trigger('processStop');\n\n                        return true;\n                    }\n                    setTimeout(this.renderWithDelay.bind(this, data, from, step, delay), delay);\n                },\n\n                /**\n                 * Ignore validate action\n                 */\n                ignoreValidate: function () {\n                    var ignore = '.ignore-validate input, ' +\n                        '.ignore-validate select, ' +\n                        '.ignore-validate textarea';\n\n                    jQuery('#edit_form').data('validator').settings.forceIgnore = ignore;\n                }\n            };\n\n        if ($('add_new_swatch_text_option_button')) {\n            Event.observe(\n                'add_new_swatch_text_option_button',\n                'click',\n                swatchTextOption.add.bind(swatchTextOption, true)\n            );\n        }\n        jQuery('#swatch-text-options-panel').on('render', function () {\n            swatchTextOption.ignoreValidate();\n\n            if (swatchTextOption.rendered) {\n                return false;\n            }\n            jQuery('body').trigger('processStart');\n            swatchTextOption.renderWithDelay(config.attributesData, 0, 100, 300);\n            swatchTextOption.bindRemoveButtons();\n        });\n\n        if (config.isSortable) {\n            jQuery(function ($) {\n                $('[data-role=swatch-text-options-container]').sortable({\n                    distance: 8,\n                    tolerance: 'pointer',\n                    cancel: 'input, button',\n                    axis: 'y',\n\n                    /**\n                     * Update components\n                     */\n                    update: function () {\n                        $('[data-role=swatch-text-options-container] [data-role=order]').each(\n                            function (index, element) {\n                                $(element).val(index + 1);\n                            }\n                        );\n                    }\n                });\n            });\n        }\n\n        jQuery(document).ready(function () {\n            if (jQuery('#frontend_input').val() !== 'swatch_text') {\n                jQuery('.swatch-text-field-0').removeClass('required-option');\n            }\n        });\n\n        window.swatchTextOption = swatchTextOption;\n        window.swatchOptionTextDefaultInputType = swatchOptionTextDefaultInputType;\n\n        rg.set('swatch-text-options-panel', swatchTextOption);\n    };\n});\n","Magento_Swatches/js/form/element/swatch-visual.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global $break $ FORM_KEY */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'Magento_Ui/js/lib/view/utils/async',\n    'mage/template',\n    'uiRegistry',\n    'prototype',\n    'Magento_Ui/js/form/element/abstract',\n    'jquery/colorpicker/js/colorpicker',\n    'jquery/ui'\n], function (_, jQuery, mageTemplate, rg, prototype, Abstract) {\n    'use strict';\n\n    /**\n     * Former implementation.\n     *\n     * @param {*} value\n     * @param {Object} container\n     * @param {String} uploadUrl\n     * @param {String} elementName\n     */\n    function oldCode(value, container, uploadUrl, elementName) {\n        var swatchVisualOption = {\n            itemCount: 0,\n            totalItems: 0,\n            rendered: 0,\n            isReadOnly: false,\n\n            /**\n             * Initialize.\n             */\n            initialize: function () {\n                if (_.isEmpty(value)) {\n                    container.addClassName('unavailable');\n                }\n\n                jQuery(container).on(\n                    'click',\n                    '.colorpicker_handler',\n                    this.initColorPicker\n                );\n            },\n\n            /**\n             * ColorPicker initialization process\n             */\n            initColorPicker: function () {\n                var element = this,\n                    hiddenColorPicker = !jQuery(element).data('colorpickerId');\n\n                jQuery(this).ColorPicker({\n\n                    /**\n                     * ColorPicker onShow action\n                     */\n                    onShow: function () {\n                        var color = jQuery(element).parent().parent().prev().prev('input').val(),\n                            menu = jQuery(this).parents('.swatch_sub-menu_container');\n\n                        menu.hide();\n                        jQuery(element).ColorPickerSetColor(color);\n                    },\n\n                    /**\n                     * ColorPicker onSubmit action\n                     *\n                     * @param {String} hsb\n                     * @param {String} hex\n                     * @param {String} rgb\n                     * @param {String} el\n                     */\n                    onSubmit: function (hsb, hex, rgb, el) {\n                        var localContainer = jQuery(el).parent().parent().prev();\n\n                        jQuery(el).ColorPickerHide();\n                        localContainer.parent().removeClass('unavailable');\n                        localContainer.prev('input').val('#' + hex).trigger('change');\n                        localContainer.css('background', '#' + hex);\n                    }\n                });\n\n                if (hiddenColorPicker) {\n                    jQuery(this).ColorPickerShow();\n                }\n            },\n\n            /**\n             * Remove action\n             *\n             * @param {Object} event\n             */\n            remove: function (event) {\n                var element = $(Event.findElement(event, 'tr')),\n                    elementFlags; // !!! Button already have table parent in safari\n\n                // Safari workaround\n                element.ancestors().each(function (parentItem) {\n                    if (parentItem.hasClassName('option-row')) {\n                        element = parentItem;\n                        throw $break;\n                    } else if (parentItem.hasClassName('box')) {\n                        throw $break;\n                    }\n                });\n\n                if (element) {\n                    elementFlags = element.getElementsByClassName('delete-flag');\n\n                    if (elementFlags[0]) {\n                        elementFlags[0].value = 1;\n                    }\n\n                    element.addClassName('no-display');\n                    element.addClassName('template');\n                    element.hide();\n                    this.totalItems--;\n                    this.updateItemsCountField();\n                }\n            },\n\n            /**\n             * Update items count field\n             */\n            updateItemsCountField: function () {\n                $('swatch-visual-option-count-check').value = this.totalItems > 0 ? '1' : '';\n            }\n        };\n\n        //swatchVisualOption.initColorPicker();\n\n        jQuery('body').on('click', function (event) {\n            var element = jQuery(event.target);\n\n            if (\n                element.parents('.swatch_sub-menu_container').length === 1 ||\n                element.next('div.swatch_sub-menu_container').length === 1\n            ) {\n                return true;\n            }\n            jQuery('.swatch_sub-menu_container').hide();\n        });\n\n        jQuery(function ($) {\n\n            var swatchComponents = {\n\n                /**\n                 * div wrapper for to hide all evement\n                 */\n                wrapper: null,\n\n                /**\n                 * iframe component to perform file upload without page reload\n                 */\n                iframe: null,\n\n                /**\n                 * form component for upload image\n                 */\n                form: null,\n\n                /**\n                 * Input file component for upload image\n                 */\n                inputFile: null,\n\n                /**\n                 * Create swatch component for upload files\n                 *\n                 * @this {swatchComponents}\n                 * @public\n                 */\n                create: function () {\n                    this.wrapper = $('<div>').css({\n                        display: 'none'\n                    }).appendTo($('body'));\n\n                    this.iframe = $('<iframe />', {\n                        name: 'upload_iframe_' + elementName\n                    }).appendTo(this.wrapper);\n\n                    this.form = $('<form />', {\n                        name: 'swatch_form_image_upload_' + elementName,\n                        target: 'upload_iframe_' + elementName,\n                        method: 'post',\n                        enctype: 'multipart/form-data',\n                        class: 'ignore-validate',\n                        action: uploadUrl\n                    }).appendTo(this.wrapper);\n\n                    this.inputFile = $('<input />', {\n                        type: 'file',\n                        name: 'datafile',\n                        class: 'swatch_option_file'\n                    }).appendTo(this.form);\n\n                    $('<input />', {\n                        type: 'hidden',\n                        name: 'form_key',\n                        value: FORM_KEY\n                    }).appendTo(this.form);\n                }\n            };\n\n            swatchVisualOption.initialize();\n\n            /**\n             * Create swatch components\n             */\n            swatchComponents.create();\n\n            /**\n             * Register event for swatch input[type=file] change\n             */\n            swatchComponents.inputFile.change(function () {\n                var localContainer = $('.' + $(this).attr('data-called-by')).parents().eq(2).children('.swatch_window'),\n\n                    /**\n                     * @this {iframe}\n                     */\n                    iframeHandler = function () {\n                        var imageParams = $.parseJSON($(this).contents().find('body').html()),\n                            fullMediaUrl = imageParams['swatch_path'] + imageParams['file_path'];\n\n                        localContainer.prev('input').val(imageParams['file_path']).trigger('change');\n                        localContainer.css({\n                            'background-image': 'url(' + fullMediaUrl + ')',\n                            'background-size': 'cover'\n                        });\n                        localContainer.parent().removeClass('unavailable');\n                    };\n\n                swatchComponents.iframe.off('load');\n                swatchComponents.iframe.load(iframeHandler);\n                swatchComponents.form.submit();\n                $(this).val('');\n            });\n\n            /**\n             * Register event for choose \"upload image\" option\n             */\n            $(container).on('click', '.btn_choose_file_upload', function () {\n                swatchComponents.inputFile.attr('data-called-by', $(this).data('class'));\n                swatchComponents.inputFile.click();\n            });\n\n            /**\n             * Register event for remove option\n             */\n            $(container).on('click', '.btn_remove_swatch', function () {\n                var optionPanel = $(this).parents().eq(2);\n\n                optionPanel.children('input').val('').trigger('change');\n                optionPanel.children('.swatch_window').css('background', '');\n                optionPanel.addClass('unavailable');\n                jQuery('.swatch_sub-menu_container').hide();\n            });\n\n            /**\n             * Toggle color upload chooser\n             */\n            $(container).on('click', '.swatch_window', function () {\n                jQuery('.swatch_sub-menu_container').hide();\n                $(this).next('div').toggle();\n            });\n        });\n    }\n\n    return Abstract.extend({\n        defaults: {\n            elementId: 0,\n            prefixName: '',\n            prefixElementName: '',\n            elementName: '',\n            value: '',\n            uploadUrl: ''\n        },\n\n        /**\n         * Parses options and merges the result with instance\n         *\n         * @returns {Object} Chainable.\n         */\n        initConfig: function () {\n            this._super();\n\n            this.configureDataScope();\n\n            return this;\n        },\n\n        /**\n         * Initialize.\n         *\n         * @returns {Object} Chainable.\n         */\n        initialize: function () {\n            this._super()\n                .initOldCode()\n                .on('value', this.onChangeColor.bind(this));\n\n            return this;\n        },\n\n        /**\n         * Handler function that execute when color changes.\n         *\n         * @param {String} data - color\n         */\n        onChangeColor: function (data) {\n            if (!data) {\n                jQuery('.' + this.elementName).parent().removeClass('unavailable');\n            }\n        },\n\n        /**\n         * Initialize wrapped former implementation.\n         *\n         * @returns {Object} Chainable.\n         */\n        initOldCode: function () {\n            jQuery.async('.' + this.elementName, this.name, function (elem) {\n                oldCode(this.value(), elem.parentElement, this.uploadUrl, this.elementName);\n            }.bind(this));\n\n            return this;\n        },\n\n        /**\n         * Configure data scope.\n         */\n        configureDataScope: function () {\n            var recordId, prefixName;\n\n            // Get recordId\n            recordId = this.parentName.split('.').last();\n\n            prefixName = this.dataScopeToHtmlArray(this.prefixName);\n            this.elementName = this.prefixElementName + recordId;\n\n            this.inputName = prefixName + '[' + this.elementName + ']';\n            this.exportDataLink = 'data.' + this.prefixName + '.' + this.elementName;\n            this.exports.value = this.provider + ':' + this.exportDataLink;\n        },\n\n        /** @inheritdoc */\n        destroy: function () {\n            this._super();\n\n            this.source.remove(this.exportDataLink);\n        },\n\n        /**\n         * Get HTML array from data scope.\n         *\n         * @param {String} dataScopeString\n         * @returns {String}\n         */\n        dataScopeToHtmlArray: function (dataScopeString) {\n            var dataScopeArray, dataScope, reduceFunction;\n\n            /**\n             * Add new level of nesting.\n             *\n             * @param {String} prev\n             * @param {String} curr\n             * @returns {String}\n             */\n            reduceFunction = function (prev, curr) {\n                return prev + '[' + curr + ']';\n            };\n\n            dataScopeArray = dataScopeString.split('.');\n\n            dataScope = dataScopeArray.shift();\n            dataScope += dataScopeArray.reduce(reduceFunction, '');\n\n            return dataScope;\n        }\n    });\n});\n","Amazon_Core/js/simplepath.js":"/**\n * Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\").\n * You may not use this file except in compliance with the License.\n * A copy of the License is located at\n *\n *  http://aws.amazon.com/apache2.0\n *\n * or in the \"license\" file accompanying this file. This file is distributed\n * on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either\n * express or implied. See the License for the specific language governing\n * permissions and limitations under the License.\n */\n/*browser:true*/\n/*global define*/\ndefine(\n    [\n        'jquery',\n        'uiComponent',\n        'mage/translate',\n        'jquery/ui',\n        'jquery/validate'\n    ],\n    function ($, Class, $t) {\n        'use strict';\n        var pollTimer, windowOpen = false;\n\n        return Class.extend({\n\n                defaults: {\n                    $amazonFields: null,\n                    $amazonCredentialJson: null,\n                    $amazonSpBack: null,\n                    $amazonMerchantId: null,\n                    selector: 'amazon_payment',\n                    $container: null,\n                    pollInterval: 1500,\n                    $form: null,\n                    apSimplePathSelector: '#amazon_simplepath',\n                    apSimplePathBackSelector: '#amazon_simplepath_back',\n                },\n\n                /**\n                 * Set list of observable attributes\n                 * @returns {exports.initObservable}\n                 */\n                initObservable: function () {\n                    var self = this;\n\n                    self.$amazonSimplepath = $(self.apSimplePathSelector);\n                    self.$amazonFields = $('#payment_' + self.getCountry() + '_' + self.selector + ' .form-list');\n                    self.$amazonCredentialsHeader = $('#payment_' + self.getCountry() + '_' + self.selector\n                        + '_credentials-head');\n                    self.$amazonCredentialJson = $('#payment_' + self.getCountry() + '_' + self.selector\n                        + '_credentials_credentials_json');\n                    self.$amazonMerchantId = $('#payment_' + self.getCountry() + '_' + self.selector\n                        + '_credentials_merchant_id').val();\n                    self.$amazonSpBack = $(self.apSimplePathBackSelector);\n                    self.$container = $(self.apSimplePathSelector);\n\n                    if (this.isMultiCurrencyRegion) {\n                        $('#row_payment_' + self.getCountry() + '_amazon_payment_advanced_sales_options_multicurrency').show();\n                        $('#row_payment_other_amazon_payment_advanced_sales_options_multicurrency').show();\n                    }\n                    else {\n                        $('#row_payment_' + self.getCountry() + '_amazon_payment_advanced_sales_options_multicurrency').hide();\n                        $('#row_payment_other_amazon_payment_advanced_sales_options_multicurrency').hide();\n                    }\n                    \n                    if (self.$amazonMerchantId) {\n                        self.hideAmazonConfig();\n                    }\n                    else {\n                        self.showAmazonConfig();\n                    }\n\n                    if (!self.$form) {\n                        self.generateSimplePathForm();\n                    }\n\n                    self._super();\n\n                    self.initEventHandlers();\n\n                    return self;\n                },\n\n                /**\n                 * Init event handlers\n                 */\n                initEventHandlers: function () {\n                    var self = this;\n\n                    self.$amazonSpBack.click(function () {\n                        self.showAmazonConfig();\n                        return false;\n                    });\n\n                    $('#simplepath-skip').click(function () {\n                        self.hideAmazonConfig();\n                        return false;\n                    });\n\n                    $('#simplepath_form').on('submit', function () {\n                        self.setupWindowLaunch();\n                    });\n\n                    self.$amazonCredentialJson.on('input', function () {\n                        self.updateCredentials(self);\n                    });\n                },\n\n                /**\n                 * Detects when a properly formatted JSON block is pasted into the Credentials JSON field\n                 * and auto populates specified fields.\n                 *\n                 * @param self\n                 */\n                updateCredentials: function (self) {\n                    var elJson = self.$amazonCredentialJson.val(), obj = null, success = true, item = null;\n\n                    try {\n                        obj = $.parseJSON($.trim(elJson));\n                    }\n                    catch (err) {\n                        obj = null;\n                        self.$amazonCredentialJson.val('').attr(\n                            'placeholder',\n                            $t('Invalid JSON credentials entered, please try again.')\n                        ).focus();\n                    }\n\n                    if (obj && typeof obj === 'object') {\n\n                        for (var prop in obj) {\n                            if (obj.hasOwnProperty(prop)) {\n                                item = $('#payment_' + self.getCountry() + '_amazon_payment_credentials_'\n                                    + $.trim(prop));\n\n                                if (item && item.length) {\n                                    $('#payment_' + self.getCountry() + '_amazon_payment_credentials_'\n                                        + $.trim(prop)).val($.trim(obj[prop]));\n                                }\n                                else {\n                                    success = false;\n                                }\n                            }\n                        }\n\n                        if (success) {\n                            self.$amazonCredentialJson.val('').attr(\n                                'placeholder',\n                                $t('Credential fields successfully updated and being saved.')\n                            ).focus();\n                            $('#save').click();\n                        }\n                        else {\n                            self.$amazonCredentialJson.val('').attr(\n                                'placeholder',\n                                $t('One or more of your credential fields did not parse correctly. ' +\n                                    'Please review your entry and try again.')\n                            ).focus();\n                        }\n                    }\n                },\n\n                /**\n                 * Sets up Amazon merchant key popup and polls for data update upon user completion.\n                 */\n                setupWindowLaunch: function () {\n                    var self = this,\n                        heights = [660, 720, 810, 900],\n                        popupWidth = this.getCountry() !== 'us' ? 768 : 1050, popupHeight = heights[0],\n                        region = self.region,\n                        elCheckDefault = $('#payment_' + self.getCountry()\n                            + '_amazon_payment_credentials_payment_region_inherit:checked'),\n                        elRegion = $('payment_' + self.getCountry() + '_amazon_payment_credentials_payment_region'),\n                        elJson = self.$amazonCredentialJson.val();\n\n                    for (var i in heights) {\n                        if (heights.hasOwnProperty(i)) {\n                            popupHeight = window.innerHeight >= heights[i] ? heights[i] : popupHeight;\n                        }\n                    }\n\n                    self.launchPopup(self.amazonUrl, popupWidth, popupHeight);\n\n                    // flags that popup is open and poll timer can proceed\n                    windowOpen = true;\n\n                    // begin polling for feedback\n                    pollTimer = setTimeout(self.pollForKeys(self), self.pollInterval);\n\n                    // Save JSON\n                    $('#save-json').click(function (e) {\n                        e.stop();\n                        var json = $('#json-import').value;\n\n                        if (!json || !json.isJSON()) {\n                            return;\n                        }\n                        elJson.value = json;\n                        $('#save').click();\n                    });\n\n                    // Autoset payment region (for EU/UK)\n                    if (self.region.indexOf('eu') !== -1) {\n                        region = 'de';\n                    }\n\n                    if (elCheckDefault && elCheckDefault.length) {\n                        elCheckDefault[0].click();\n                    }\n\n                    if (elRegion) {\n                        elRegion.value = region;\n                    }\n                },\n\n                /**\n                 * Perform Ajax request looking for new keys.\n                 */\n                pollForKeys: function (self) {\n                    clearTimeout(pollTimer);\n                    if (windowOpen) {\n                        $.ajax({\n                            url: self.pollUrl,\n                            data: {},\n                            type: 'GET',\n                            cache: true,\n                            dataType: 'json',\n                            context: this,\n\n                            /**\n                             * Response handler\n                             * @param {Object} response\n                             */\n                            success: function (response) {\n                                // poll controller returns a 0 if invalid and a 1 if valid\n                                if (response) {\n                                    $('#amazon_reload').show();\n                                    document.location.replace(document.location + '#payment_amazon_payments-head');\n                                    location.reload();\n                                }\n                                else {\n                                    pollTimer = setTimeout(self.pollForKeys(self), self.pollInterval);\n                                }\n                            }\n                        });\n                    }\n                },\n\n                /**\n                 * Sets up dynamic form for capturing popup/form input for simple path setup.\n                 */\n                generateSimplePathForm: function () {\n\n                    this.$form = new Element('form', {\n                        method: 'post',\n                        action: this.amazonUrl,\n                        id: 'simplepath_form',\n                        target: 'simplepath',\n                        novalidate: 'novalidate',\n                    });\n\n                    this.$container.wrap(this.$form);\n\n                    // Convert formParams JSON to hidden inputs\n                    for (var key in this.formParams) {\n                        if ( $.isPlainObject(this.formParams[key]) || $.isArray(this.formParams[key])) {\n                            for (var i in this.formParams[key]) {\n                                if (typeof this.formParams[key][i] !== 'function') {\n                                    $(new Element('input', {\n                                        type: 'hidden',\n                                        name: key,\n                                        value: this.formParams[key][i],\n                                        novalidate: 'novalidate'\n                                    })).appendTo($(\"#simplepath_form\"));\n                                }\n                            }\n                        } else {\n                            $(new Element('input', {\n                                type: 'hidden',\n                                name: key,\n                                novalidate: 'novalidate',\n                                value: this.formParams[key]\n                            })).appendTo($(\"#simplepath_form\"));\n                        }\n                    }\n\n                    // unable to use this.form, had to resort to direct call\n                    $('#simplepath_form').validate({});\n                },\n\n                /**\n                 * display amazon simple path config section\n                 */\n                showAmazonConfig: function () {\n                    this.$amazonSimplepath.show();\n                    this.$amazonSpBack.hide();\n                    if (this.$amazonCredentialsHeader.hasClass('open')) {\n                        this.$amazonCredentialsHeader.click();\n                    }\n                },\n\n                /**\n                 * hide amazon simple path config.\n                 */\n                hideAmazonConfig: function () {\n                    this.$amazonSimplepath.hide();\n                    this.$amazonSpBack.show();\n                    if (!this.$amazonCredentialsHeader.hasClass('open')) {\n                        this.$amazonCredentialsHeader.click();\n                    }\n                },\n\n                /**\n                 * Get payment code\n                 * @returns {String}\n                 */\n                getCountry: function () {\n                    return this.co.toLowerCase();\n                },\n\n                /**\n                 * Generate popup window for simple path process\n                 * @param url\n                 * @param requestedWidth\n                 * @param requestedHeight\n                 */\n                launchPopup: function (url, requestedWidth, requestedHeight) {\n                    var leftOffset = this.getLeftOffset(requestedWidth),\n                        topOffset = this.getTopOffset(requestedHeight),\n                        newWindow = window.open(url, 'simplepath', 'scrollbars=yes, width=' + requestedWidth\n                            + ', height=' + requestedHeight + ', top=' + topOffset + ', left=' + leftOffset);\n\n                    if (window.focus) {\n                        newWindow.focus();\n                    }\n\n                    // Set interval to check when this popup window is closed so timeout can be suspended.\n                    var winTimer = window.setInterval(function () {\n                        if (newWindow.closed !== false) {\n                            window.clearInterval(winTimer);\n                            windowOpen = false;\n                        }\n                    });\n                },\n\n                /**\n                 * Determine left offset for popup window\n                 * @param requestedWidth\n                 * @returns {number}\n                 */\n                getLeftOffset: function (requestedWidth) {\n                    var dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;\n\n                    return (this.windowWidth() / 2) - (requestedWidth / 2) + dualScreenLeft;\n                },\n\n                /**\n                 * Determine top offset for popup window\n                 * @param requestedHeight\n                 * @returns {number}\n                 */\n                getTopOffset: function (requestedHeight) {\n                    var dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;\n\n                    return (this.windowHeight() / 2) - (requestedHeight / 2) + dualScreenTop;\n                },\n\n                /**\n                 * Determine width of popup window\n                 * @returns {number}\n                 */\n                windowWidth: function () {\n                    return window.innerWidth\n                        || document.documentElement.clientWidth\n                        || screen.width;\n                },\n\n                /**\n                 * Determine window height of popup\n                 * @returns {number}\n                 */\n                windowHeight: function () {\n                    return window.innerHeight\n                        || document.documentElement.clientHeight\n                        || screen.height;\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/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_UrlRewrite/js/url-rewrite-validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/backend/form',\n    'mage/backend/validation'\n], function ($) {\n    'use strict';\n\n    return function (data, element) {\n\n        $(element).form().validation({\n            validationUrl: data.url\n        });\n    };\n});\n","Magento_Sales/js/bootstrap/order-create-index.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\nrequire([\n    'Magento_Sales/order/create/giftmessage'\n]);\n","Magento_Sales/js/bootstrap/order-post-action.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\nrequire([\n    'Magento_Sales/order/view/post-wrapper'\n]);\n","Magento_Sales/order/giftoptions_tooltip.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'prototype'\n], function () {\n    'use strict';\n\n    var GiftOptionsTooltip = Class.create();\n\n    GiftOptionsTooltip.prototype = {\n        _tooltipLines: [],\n        _tooltipWindow: null,\n        _tooltipWindowContent: null,\n        _targetLinks: [],\n        _eventMouseOver: null,\n        _eventMouseOut: null,\n        _styleOptions: null,\n        _tooltipContentLoaderFunction: null,\n\n        /**\n         * Initialize tooltip object\n         */\n        initialize: function () {\n            var options = Object.extend({\n                'delta_x': 30,\n                'delta_y': 0,\n                zindex: 1000\n            });\n\n            this._styleOptions = options;\n            this._eventMouseOver = this.showTooltip.bindAsEventListener(this);\n            this._eventMouseOut = this.hideTooltip.bindAsEventListener(this);\n        },\n\n        /**\n         * Set gift options tooltip window\n         *\n         * @param {String} windowId\n         * @param {String} contentId\n         *\n         * @return boolean success\n         */\n        setTooltipWindow: function (windowId, contentId) {\n            if (!$(windowId) || !$(contentId)) {\n                return false;\n            }\n            this._tooltipWindow = $(windowId);\n            this._tooltipWindowContent = $(contentId);\n            $(document.body).insert({\n                bottom: this._tooltipWindow\n            });\n            this.hideTooltip();\n\n            return true;\n        },\n\n        /**\n         * Add tooltip to specified link\n         *\n         * @param {String} linkId\n         * @param {String} itemId - identifier of the item related to link\n         *\n         * @return boolean success\n         */\n        addTargetLink: function (linkId, itemId) {\n            if ($(linkId)) {\n                this._targetLinks[linkId] = [];\n                this._targetLinks[linkId].object = $(linkId);\n                this._targetLinks[linkId].itemId = itemId;\n                this._registerEvents(this._targetLinks[linkId].object);\n\n                return true;\n            }\n\n            return false;\n        },\n\n        /**\n         * Detach event listeners from target links when tooltip is destroyed\n         */\n        destroy: function () {\n            var linkId;\n\n            for (linkId in this._targetLinks) { //eslint-disable-line guard-for-in\n                Event.stopObserving(this._targetLinks[linkId].object, 'mouseover', this._eventMouseOver);\n                Event.stopObserving(this._targetLinks[linkId].object, 'mouseout', this._eventMouseOut);\n            }\n        },\n\n        /**\n         *  Register event listeners\n         *\n         *  @param {HTMLElement} element\n         */\n        _registerEvents: function (element) {\n            Event.observe(element, 'mouseover', this._eventMouseOver);\n            Event.observe(element, 'mouseout', this._eventMouseOut);\n        },\n\n        /**\n         * Move tooltip to mouse position\n         *\n         * @param {Prototype.Event} event\n         */\n        _moveTooltip: function (event) {\n            var mouseX, mouseY;\n\n            Event.stop(event);\n            mouseX = Event.pointerX(event);\n            mouseY = Event.pointerY(event);\n\n            this.setStyles(mouseX, mouseY);\n        },\n\n        /**\n         * Show tooltip\n         *\n         * @param {Object} event\n         *\n         * @return boolean success\n         */\n        showTooltip: function (event) {\n            var link, itemId, tooltipContent;\n\n            Event.stop(event);\n\n            if (this._tooltipWindow) {\n                link = Event.element(event);\n                itemId = this._targetLinks[link.id].itemId;\n                tooltipContent = '';\n\n                if (Object.isFunction(this._tooltipContentLoaderFunction)) {\n                    tooltipContent = this._tooltipContentLoaderFunction(itemId);\n                }\n\n                if (tooltipContent != '') { //eslint-disable-line eqeqeq\n                    this._updateTooltipWindowContent(tooltipContent);\n                    this._moveTooltip(event);\n                    new Element.show(this._tooltipWindow);\n\n                    return true;\n                }\n            }\n\n            return false;\n        },\n\n        /**\n         * Set tooltip window styles\n         *\n         * @param {Number} x\n         * @param {Number} y\n         */\n        setStyles: function (x, y) {\n            Element.setStyle(this._tooltipWindow, {\n                position: 'absolute',\n                top: y + this._styleOptions['delta_y'] + 'px',\n                left: x + this._styleOptions['delta_x'] + 'px',\n                zindex: this._styleOptions.zindex\n            });\n        },\n\n        /**\n         * Hide tooltip\n         */\n        hideTooltip: function () {\n            if (this._tooltipWindow) {\n                new Element.hide(this._tooltipWindow);\n            }\n        },\n\n        /**\n         * Set gift options tooltip content loader function\n         * This function should accept at least one parameter that will serve as an item ID\n         *\n         * @param {Function} loaderFunction - loader function\n         */\n        setTooltipContentLoaderFunction: function (loaderFunction) {\n            this._tooltipContentLoaderFunction = loaderFunction;\n        },\n\n        /**\n         * Update tooltip window content\n         *\n         * @param {String} content\n         */\n        _updateTooltipWindowContent: function (content) {\n            this._tooltipWindowContent.update(content);\n        }\n    };\n\n    window.giftOptionsTooltip = new GiftOptionsTooltip();\n});\n","Magento_Sales/order/create/scripts.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/confirm',\n    'Magento_Ui/js/modal/alert',\n    'mage/template',\n    'text!Magento_Sales/templates/order/create/shipping/reload.html',\n    'text!Magento_Sales/templates/order/create/payment/reload.html',\n    'mage/translate',\n    'prototype',\n    'Magento_Catalog/catalog/product/composite/configure',\n    'Magento_Ui/js/lib/view/utils/async'\n], function (jQuery, confirm, alert, template, shippingTemplate, paymentTemplate) {\n\n    window.AdminOrder = new Class.create();\n\n    AdminOrder.prototype = {\n        initialize : function(data){\n            if(!data) data = {};\n            this.loadBaseUrl    = false;\n            this.customerId     = data.customer_id ? data.customer_id : false;\n            this.storeId        = data.store_id ? data.store_id : false;\n            this.quoteId        = data['quote_id'] ? data['quote_id'] : false;\n            this.currencyId     = false;\n            this.currencySymbol = data.currency_symbol ? data.currency_symbol : '';\n            this.addresses      = data.addresses ? data.addresses : $H({});\n            this.shippingAsBilling = data.shippingAsBilling ? data.shippingAsBilling : false;\n            this.gridProducts   = $H({});\n            this.gridProductsGift = $H({});\n            this.billingAddressContainer = '';\n            this.shippingAddressContainer = '';\n            this.isShippingMethodReseted = data.shipping_method_reseted ? data.shipping_method_reseted : false;\n            this.overlayData = $H({});\n            this.giftMessageDataChanged = false;\n            this.productConfigureAddFields = {};\n            this.productPriceBase = {};\n            this.collectElementsValue = true;\n            this.isOnlyVirtualProduct = false;\n            this.excludedPaymentMethods = [];\n            this.summarizePrice = true;\n            this.shippingTemplate = template(shippingTemplate, {\n                data: {\n                    title: jQuery.mage.__('Shipping Method'),\n                    linkText: jQuery.mage.__('Get shipping methods and rates')\n                }\n            });\n            this.paymentTemplate = template(paymentTemplate, {\n                data: {\n                    title: jQuery.mage.__('Payment Method'),\n                    linkText: jQuery.mage.__('Get available payment methods')\n                }\n            });\n\n            jQuery.async('#order-items', (function(){\n                this.dataArea = new OrderFormArea('data', $(this.getAreaId('data')), this);\n                this.itemsArea = Object.extend(new OrderFormArea('items', $(this.getAreaId('items')), this), {\n                    addControlButton: function(button){\n                        var controlButtonArea = $(this.node).select('.actions')[0];\n                        if (typeof controlButtonArea != 'undefined') {\n                            var buttons = controlButtonArea.childElements();\n                            for (var i = 0; i < buttons.length; i++) {\n                                if (buttons[i].innerHTML.include(button.getLabel())) {\n                                    return;\n                                }\n                            }\n                            button.insertIn(controlButtonArea, 'top');\n                        }\n                    }\n                });\n\n                var searchButtonId = 'add_products',\n                    searchButton = new ControlButton(jQuery.mage.__('Add Products'), searchButtonId),\n                    searchAreaId = this.getAreaId('search');\n                searchButton.onClick = function() {\n                    $(searchAreaId).show();\n                    var el = this;\n                    window.setTimeout(function () {\n                        el.remove();\n                    }, 10);\n                };\n\n                if (jQuery('#' + this.getAreaId('items')).is(':visible')) {\n                    this.dataArea.onLoad = this.dataArea.onLoad.wrap(function(proceed) {\n                        proceed();\n                        this._parent.itemsArea.setNode($(this._parent.getAreaId('items')));\n                        this._parent.itemsArea.onLoad();\n                    });\n\n                    this.itemsArea.onLoad = this.itemsArea.onLoad.wrap(function(proceed) {\n                        proceed();\n                        if ($(searchAreaId) && !$(searchAreaId).visible() && !$(searchButtonId)) {\n                            this.addControlButton(searchButton);\n                        }\n                    });\n                    this.areasLoaded();\n                    this.itemsArea.onLoad();\n                }\n            }).bind(this));\n\n            jQuery('#edit_form')\n                .on('submitOrder', function(){\n                    jQuery(this).trigger('realOrder');\n                })\n                .on('realOrder', this._realSubmit.bind(this));\n        },\n\n        areasLoaded: function(){\n        },\n\n        itemsLoaded: function(){\n        },\n\n        dataLoaded: function(){\n            this.dataShow();\n        },\n\n        setLoadBaseUrl : function(url){\n            this.loadBaseUrl = url;\n        },\n\n        setAddresses : function(addresses){\n            this.addresses = addresses;\n        },\n\n        addExcludedPaymentMethod : function(method){\n            this.excludedPaymentMethods.push(method);\n        },\n\n        setCustomerId : function(id){\n            this.customerId = id;\n            this.loadArea('header', true);\n            $(this.getAreaId('header')).callback = 'setCustomerAfter';\n            $('back_order_top_button').hide();\n            $('reset_order_top_button').show();\n        },\n\n        setCustomerAfter : function () {\n            this.customerSelectorHide();\n            if (this.storeId) {\n                $(this.getAreaId('data')).callback = 'dataLoaded';\n                this.loadArea(['data'], true);\n            }\n            else {\n                this.storeSelectorShow();\n            }\n        },\n\n        setStoreId : function(id){\n            this.storeId = id;\n            this.storeSelectorHide();\n            this.sidebarShow();\n            //this.loadArea(['header', 'sidebar','data'], true);\n            this.dataShow();\n            this.loadArea(['header', 'data'], true);\n        },\n\n        setCurrencyId : function(id){\n            this.currencyId = id;\n            //this.loadArea(['sidebar', 'data'], true);\n            this.loadArea(['data'], true);\n        },\n\n        setCurrencySymbol : function(symbol){\n            this.currencySymbol = symbol;\n        },\n\n        selectAddress : function(el, container){\n            id = el.value;\n            if (id.length == 0) {\n                id = '0';\n            }\n            if(this.addresses[id]){\n                this.fillAddressFields(container, this.addresses[id]);\n\n            }\n            else{\n                this.fillAddressFields(container, {});\n            }\n\n            var data = this.serializeData(container);\n            data[el.name] = id;\n\n            this.resetPaymentMethod();\n            if (this.isShippingField(container) && !this.isShippingMethodReseted) {\n                this.resetShippingMethod(data);\n            } else{\n                this.saveData(data);\n            }\n        },\n\n        /**\n         * Checks if the field belongs to the shipping address.\n         *\n         * @param {String} fieldId\n         * @return {Boolean}\n         */\n        isShippingField: function (fieldId) {\n            if (this.shippingAsBilling) {\n                return fieldId.include('billing');\n            }\n\n            return fieldId.include('shipping');\n        },\n\n        /**\n         * Checks if the field belongs to the billing address.\n         *\n         * @param {String} fieldId\n         * @return {Boolean}\n         */\n        isBillingField: function (fieldId) {\n            return fieldId.include('billing');\n        },\n\n        /**\n         * Binds events on container form fields.\n         *\n         * @param {String} container\n         */\n        bindAddressFields: function (container) {\n            var fields = $(container).select('input', 'select', 'textarea'),\n                i;\n\n            for (i = 0; i < fields.length; i++) {\n                jQuery(fields[i]).change(this.changeAddressField.bind(this));\n            }\n        },\n\n        /**\n         * Triggers on each form's element changes.\n         *\n         * @param {Event} event\n         */\n        changeAddressField: function (event) {\n            var field = Event.element(event),\n                re = /[^\\[]*\\[([^\\]]*)_address\\]\\[([^\\]]*)\\](\\[(\\d)\\])?/,\n                matchRes = field.name.match(re),\n                type,\n                name,\n                data,\n                resetShipping = false;\n\n            if (!matchRes) {\n                return;\n            }\n\n            type = matchRes[1];\n            name = matchRes[2];\n\n            if (this.isBillingField(field.id)) {\n                data = this.serializeData(this.billingAddressContainer);\n            } else {\n                data = this.serializeData(this.shippingAddressContainer);\n            }\n            data = data.toObject();\n\n            if (type === 'billing' && this.shippingAsBilling) {\n                this.syncAddressField(this.shippingAddressContainer, field.name, field.value);\n                resetShipping = true;\n            }\n\n            if (type === 'shipping' && !this.shippingAsBilling) {\n                resetShipping = true;\n            }\n\n            if (resetShipping) {\n                data['reset_shipping'] = true;\n            }\n\n            data['order[' + type + '_address][customer_address_id]'] = null;\n            data['shipping_as_billing'] = +this.shippingAsBilling;\n\n            if (name === 'customer_address_id') {\n                data['order[' + type + '_address][customer_address_id]'] =\n                    $('order-' + type + '_address_customer_address_id').value;\n            }\n\n            this.resetPaymentMethod();\n\n            if (data['reset_shipping']) {\n                this.resetShippingMethod();\n            } else {\n                this.saveData(data);\n\n                if (name === 'country_id' || name === 'customer_address_id') {\n                    this.loadArea(['shipping_method', 'billing_method', 'totals', 'items'], true, data);\n                }\n            }\n        },\n\n        /**\n         * Set address container form field value.\n         *\n         * @param {String} container - container ID\n         * @param {String} fieldName - form field name\n         * @param {*} fieldValue - form field value\n         */\n        syncAddressField: function (container, fieldName, fieldValue) {\n            var syncName;\n\n            if (this.isBillingField(fieldName)) {\n                syncName = fieldName.replace('billing', 'shipping');\n            }\n\n            $(container).select('[name=\"' + syncName + '\"]').each(function (element) {\n                if (~['input', 'textarea', 'select'].indexOf(element.tagName.toLowerCase())) {\n                    element.value = fieldValue;\n                }\n            });\n        },\n\n        fillAddressFields: function(container, data){\n            var regionIdElem = false;\n            var regionIdElemValue = false;\n\n            var fields = $(container).select('input', 'select', 'textarea');\n            var re = /[^\\[]*\\[[^\\]]*\\]\\[([^\\]]*)\\](\\[(\\d)\\])?/;\n            for(var i=0;i<fields.length;i++){\n                // skip input type file @Security error code: 1000\n                if (fields[i].tagName.toLowerCase() == 'input' && fields[i].type.toLowerCase() == 'file') {\n                    continue;\n                }\n                var matchRes = fields[i].name.match(re);\n                if (matchRes === null) {\n                    continue;\n                }\n                var name = matchRes[1];\n                var index = matchRes[3];\n\n                if (index){\n                    // multiply line\n                    if (data[name]){\n                        var values = data[name].split(\"\\n\");\n                        fields[i].value = values[index] ? values[index] : '';\n                    } else {\n                        fields[i].value = '';\n                    }\n                } else if (fields[i].tagName.toLowerCase() == 'select' && fields[i].multiple) {\n                    // multiselect\n                    if (data[name]) {\n                        values = [''];\n                        if (Object.isString(data[name])) {\n                            values = data[name].split(',');\n                        } else if (Object.isArray(data[name])) {\n                            values = data[name];\n                        }\n                        fields[i].setValue(values);\n                    }\n                } else {\n                    fields[i].setValue(data[name] ? data[name] : '');\n                }\n\n                if (fields[i].changeUpdater) {\n                    fields[i].changeUpdater();\n                }\n\n                if (name == 'region' && data['region_id'] && !data['region']){\n                    fields[i].value = data['region_id'];\n                }\n\n                jQuery(fields[i]).trigger('change');\n            }\n        },\n\n        disableShippingAddress : function(flag) {\n            this.shippingAsBilling = flag;\n            if ($('order-shipping_address_customer_address_id')) {\n                $('order-shipping_address_customer_address_id').disabled = flag;\n            }\n            if ($(this.shippingAddressContainer)) {\n                var dataFields = $(this.shippingAddressContainer).select('input', 'select', 'textarea');\n                for (var i = 0; i < dataFields.length; i++) {\n                    dataFields[i].disabled = flag;\n\n                    if(this.isOnlyVirtualProduct) {\n                        dataFields[i].setValue('');\n                    }\n                }\n                var buttons = $(this.shippingAddressContainer).select('button');\n                // Add corresponding class to buttons while disabling them\n                for (i = 0; i < buttons.length; i++) {\n                    buttons[i].disabled = flag;\n                    if (flag) {\n                        buttons[i].addClassName('disabled');\n                    } else {\n                        buttons[i].removeClassName('disabled');\n                    }\n                }\n            }\n        },\n\n        /**\n         * Equals shipping and billing addresses.\n         *\n         * @param {Boolean} flag\n         */\n        setShippingAsBilling: function (flag) {\n            var data,\n                areasToLoad = ['billing_method', 'shipping_address', 'shipping_method', 'totals', 'giftmessage'];\n\n            this.disableShippingAddress(flag);\n            data = this.serializeData(flag ? this.billingAddressContainer : this.shippingAddressContainer);\n            data = data.toObject();\n            data['shipping_as_billing'] = flag ? 1 : 0;\n            data['reset_shipping'] = 1;\n            this.loadArea(areasToLoad, true, data);\n        },\n\n        /**\n         * Replace shipping method area.\n         */\n        resetShippingMethod: function () {\n            if (!this.isOnlyVirtualProduct) {\n                $(this.getAreaId('shipping_method')).update(this.shippingTemplate);\n            }\n        },\n\n        /**\n         * Replace payment method area.\n         */\n        resetPaymentMethod: function () {\n            $(this.getAreaId('billing_method')).update(this.paymentTemplate);\n        },\n\n        /**\n         * Loads shipping options according to address data.\n         *\n         * @return {Boolean}\n         */\n        loadShippingRates: function () {\n            var addressContainer = this.shippingAsBilling ?\n                    'billingAddressContainer' :\n                    'shippingAddressContainer',\n                data = this.serializeData(this[addressContainer]).toObject();\n\n            data['collect_shipping_rates'] = 1;\n            this.isShippingMethodReseted = false;\n            this.loadArea(['shipping_method', 'totals'], true, data);\n\n            return false;\n        },\n\n        setShippingMethod: function(method) {\n            var data = {};\n\n            data['order[shipping_method]'] = method;\n            this.loadArea([\n                'shipping_method',\n                'totals',\n                'billing_method'\n            ], true, data);\n        },\n\n        /**\n         * Updates available payment\n         * methods list according to order data.\n         *\n         * @return boolean\n         */\n        loadPaymentMethods: function() {\n            var data = this.serializeData(this.billingAddressContainer).toObject();\n\n            this.loadArea(['billing_method','totals'], true, data);\n\n            return false;\n        },\n\n        switchPaymentMethod: function(method){\n            jQuery('#edit_form')\n                .off('submitOrder')\n                .on('submitOrder', function(){\n                    jQuery(this).trigger('realOrder');\n                });\n            jQuery('#edit_form').trigger('changePaymentMethod', [method]);\n            this.setPaymentMethod(method);\n            var data = {};\n            data['order[payment_method]'] = method;\n            this.loadArea(['card_validation'], true, data);\n        },\n\n        setPaymentMethod : function(method){\n            if (this.paymentMethod && $('payment_form_'+this.paymentMethod)) {\n                var form = 'payment_form_'+this.paymentMethod;\n                [form + '_before', form, form + '_after'].each(function(el) {\n                    var block = $(el);\n                    if (block) {\n                        block.hide();\n                        block.select('input', 'select', 'textarea').each(function(field) {\n                            field.disabled = true;\n                        });\n                    }\n                });\n            }\n\n            if(!this.paymentMethod || method){\n                $('order-billing_method_form').select('input', 'select', 'textarea').each(function(elem){\n                    if(elem.type != 'radio') elem.disabled = true;\n                })\n            }\n\n            if ($('payment_form_'+method)){\n                jQuery('#' + this.getAreaId('billing_method')).trigger('contentUpdated');\n                this.paymentMethod = method;\n                var form = 'payment_form_'+method;\n                [form + '_before', form, form + '_after'].each(function(el) {\n                    var block = $(el);\n                    if (block) {\n                        block.show();\n                        block.select('input', 'select', 'textarea').each(function(field) {\n                            field.disabled = false;\n                            if (!el.include('_before') && !el.include('_after') && !field.bindChange) {\n                                field.bindChange = true;\n                                field.paymentContainer = form;\n                                field.method = method;\n                                field.observe('change', this.changePaymentData.bind(this))\n                            }\n                        },this);\n                    }\n                },this);\n            }\n        },\n\n        changePaymentData : function(event){\n            var elem = Event.element(event);\n            if(elem && elem.method){\n                var data = this.getPaymentData(elem.method);\n                if (data) {\n                    this.loadArea(['card_validation'], true, data);\n                } else {\n                    return;\n                }\n            }\n        },\n\n        getPaymentData : function(currentMethod){\n            if (typeof(currentMethod) == 'undefined') {\n                if (this.paymentMethod) {\n                    currentMethod = this.paymentMethod;\n                } else {\n                    return false;\n                }\n            }\n            if (this.isPaymentValidationAvailable() == false) {\n                return false;\n            }\n            var data = {};\n            var fields = $('payment_form_' + currentMethod).select('input', 'select');\n            for(var i=0;i<fields.length;i++){\n                data[fields[i].name] = fields[i].getValue();\n            }\n            if ((typeof data['payment[cc_type]']) != 'undefined' && (!data['payment[cc_type]'] || !data['payment[cc_number]'])) {\n                return false;\n            }\n            return data;\n        },\n\n        applyCoupon : function(code){\n            this.loadArea(['items', 'shipping_method', 'totals', 'billing_method'], true, {'order[coupon][code]':code, reset_shipping: 0});\n            this.orderItemChanged = false;\n        },\n\n        addProduct : function(id){\n            this.loadArea(['items', 'shipping_method', 'totals', 'billing_method'], true, {add_product:id, reset_shipping: true});\n        },\n\n        removeQuoteItem : function(id){\n            this.loadArea(['items', 'shipping_method', 'totals', 'billing_method'], true,\n                {remove_item:id, from:'quote',reset_shipping: true});\n        },\n\n        moveQuoteItem : function(id, to){\n            this.loadArea(['sidebar_'+to, 'items', 'shipping_method', 'totals', 'billing_method'], this.getAreaId('items'),\n                {move_item:id, to:to, reset_shipping: true});\n        },\n\n        productGridShow : function(buttonElement){\n            this.productGridShowButton = buttonElement;\n            Element.hide(buttonElement);\n            this.showArea('search');\n        },\n\n        productGridRowInit : function(grid, row){\n            var checkbox = $(row).select('.checkbox')[0];\n            var inputs = $(row).select('.input-text');\n            if (checkbox && inputs.length > 0) {\n                checkbox.inputElements = inputs;\n                for (var i = 0; i < inputs.length; i++) {\n                    var input = inputs[i];\n                    input.checkboxElement = checkbox;\n\n                    var product = this.gridProducts.get(checkbox.value);\n                    if (product) {\n                        var defaultValue = product[input.name];\n                        if (defaultValue) {\n                            if (input.name == 'giftmessage') {\n                                input.checked = true;\n                            } else {\n                                input.value = defaultValue;\n                            }\n                        }\n                    }\n\n                    input.disabled = !checkbox.checked || input.hasClassName('input-inactive');\n\n                    Event.observe(input,'keyup', this.productGridRowInputChange.bind(this));\n                    Event.observe(input,'change',this.productGridRowInputChange.bind(this));\n                }\n            }\n        },\n\n        productGridRowInputChange : function(event){\n            var element = Event.element(event);\n            if (element && element.checkboxElement && element.checkboxElement.checked){\n                if (element.name!='giftmessage' || element.checked) {\n                    this.gridProducts.get(element.checkboxElement.value)[element.name] = element.value;\n                } else if (element.name=='giftmessage' && this.gridProducts.get(element.checkboxElement.value)[element.name]) {\n                    delete(this.gridProducts.get(element.checkboxElement.value)[element.name]);\n                }\n            }\n        },\n\n        productGridRowClick : function(grid, event){\n            var trElement = Event.findElement(event, 'tr');\n            var qtyElement = trElement.select('input[name=\"qty\"]')[0];\n            var eventElement = Event.element(event);\n            var isInputCheckbox = eventElement.tagName == 'INPUT' && eventElement.type == 'checkbox';\n            var isInputQty = eventElement.tagName == 'INPUT' && eventElement.name == 'qty';\n            if (trElement && !isInputQty) {\n                var checkbox = Element.select(trElement, 'input[type=\"checkbox\"]')[0];\n                var confLink = Element.select(trElement, 'a')[0];\n                var priceColl = Element.select(trElement, '.price')[0];\n                if (checkbox) {\n                    // processing non composite product\n                    if (confLink.readAttribute('disabled')) {\n                        var checked = isInputCheckbox ? checkbox.checked : !checkbox.checked;\n                        grid.setCheckboxChecked(checkbox, checked);\n                        // processing composite product\n                    } else if (isInputCheckbox && !checkbox.checked) {\n                        grid.setCheckboxChecked(checkbox, false);\n                        // processing composite product\n                    } else if (!isInputCheckbox || (isInputCheckbox && checkbox.checked)) {\n                        var listType = confLink.readAttribute('list_type');\n                        var productId = confLink.readAttribute('product_id');\n                        if (typeof this.productPriceBase[productId] == 'undefined') {\n                            var priceBase = priceColl.innerHTML.match(/.*?([\\d,]+\\.?\\d*)/);\n                            if (!priceBase) {\n                                this.productPriceBase[productId] = 0;\n                            } else {\n                                this.productPriceBase[productId] = parseFloat(priceBase[1].replace(/,/g,''));\n                            }\n                        }\n                        productConfigure.setConfirmCallback(listType, function() {\n                            // sync qty of popup and qty of grid\n                            var confirmedCurrentQty = productConfigure.getCurrentConfirmedQtyElement();\n                            if (qtyElement && confirmedCurrentQty && !isNaN(confirmedCurrentQty.value)) {\n                                qtyElement.value = confirmedCurrentQty.value;\n                            }\n                            // calc and set product price\n                            var productPrice = this._calcProductPrice();\n                            if (this._isSummarizePrice()) {\n                                productPrice += this.productPriceBase[productId];\n                            }\n                            productPrice = parseFloat(Math.round(productPrice + \"e+2\") + \"e-2\");\n                            priceColl.innerHTML = this.currencySymbol + productPrice.toFixed(2);\n                            // and set checkbox checked\n                            grid.setCheckboxChecked(checkbox, true);\n                        }.bind(this));\n                        productConfigure.setCancelCallback(listType, function() {\n                            if (!$(productConfigure.confirmedCurrentId) || !$(productConfigure.confirmedCurrentId).innerHTML) {\n                                grid.setCheckboxChecked(checkbox, false);\n                            }\n                        });\n                        productConfigure.setShowWindowCallback(listType, function() {\n                            // sync qty of grid and qty of popup\n                            var formCurrentQty = productConfigure.getCurrentFormQtyElement();\n                            if (formCurrentQty && qtyElement && !isNaN(qtyElement.value)) {\n                                formCurrentQty.value = qtyElement.value;\n                            }\n                        }.bind(this));\n                        productConfigure.showItemConfiguration(listType, productId);\n                    }\n                }\n            }\n        },\n\n        /**\n         * Is need to summarize price\n         */\n        _isSummarizePrice: function(elm) {\n            if (elm && elm.hasAttribute('summarizePrice')) {\n                this.summarizePrice = parseInt(elm.readAttribute('summarizePrice'));\n            }\n            return this.summarizePrice;\n        },\n        /**\n         * Calc product price through its options\n         */\n        _calcProductPrice: function () {\n            var productPrice = 0;\n            var getPriceFields = function (elms) {\n                var productPrice = 0;\n                var getPrice = function (elm) {\n                    var optQty = 1;\n                    if (elm.hasAttribute('qtyId')) {\n                        if (!$(elm.getAttribute('qtyId')).value) {\n                            return 0;\n                        } else {\n                            optQty = parseFloat($(elm.getAttribute('qtyId')).value);\n                        }\n                    }\n                    if (elm.hasAttribute('price') && !elm.disabled) {\n                        return parseFloat(elm.readAttribute('price')) * optQty;\n                    }\n                    return 0;\n                };\n                for(var i = 0; i < elms.length; i++) {\n                    if (elms[i].type == 'select-one' || elms[i].type == 'select-multiple') {\n                        for(var ii = 0; ii < elms[i].options.length; ii++) {\n                            if (elms[i].options[ii].selected) {\n                                if (this._isSummarizePrice(elms[i].options[ii])) {\n                                    productPrice += getPrice(elms[i].options[ii]);\n                                } else {\n                                    productPrice = getPrice(elms[i].options[ii]);\n                                }\n                            }\n                        }\n                    }\n                    else if (((elms[i].type == 'checkbox' || elms[i].type == 'radio') && elms[i].checked)\n                        || ((elms[i].type == 'file' || elms[i].type == 'text' || elms[i].type == 'textarea' || elms[i].type == 'hidden')\n                            && Form.Element.getValue(elms[i]))\n                    ) {\n                        if (this._isSummarizePrice(elms[i])) {\n                            productPrice += getPrice(elms[i]);\n                        } else {\n                            productPrice = getPrice(elms[i]);\n                        }\n                    }\n                }\n                return productPrice;\n            }.bind(this);\n            productPrice += getPriceFields($(productConfigure.confirmedCurrentId).getElementsByTagName('input'));\n            productPrice += getPriceFields($(productConfigure.confirmedCurrentId).getElementsByTagName('select'));\n            productPrice += getPriceFields($(productConfigure.confirmedCurrentId).getElementsByTagName('textarea'));\n            return productPrice;\n        },\n\n        productGridCheckboxCheck : function(grid, element, checked){\n            if (checked) {\n                if(element.inputElements) {\n                    this.gridProducts.set(element.value, {});\n                    var product = this.gridProducts.get(element.value);\n                    for (var i = 0; i < element.inputElements.length; i++) {\n                        var input = element.inputElements[i];\n                        if (!input.hasClassName('input-inactive')) {\n                            input.disabled = false;\n                            if (input.name == 'qty' && !input.value) {\n                                input.value = 1;\n                            }\n                        }\n\n                        if (input.checked || input.name != 'giftmessage') {\n                            product[input.name] = input.value;\n                        } else if (product[input.name]) {\n                            delete(product[input.name]);\n                        }\n                    }\n                }\n            } else {\n                if(element.inputElements){\n                    for(var i = 0; i < element.inputElements.length; i++) {\n                        element.inputElements[i].disabled = true;\n                    }\n                }\n                this.gridProducts.unset(element.value);\n            }\n            grid.reloadParams = {'products[]':this.gridProducts.keys()};\n        },\n\n        /**\n         * Submit configured products to quote\n         */\n        productGridAddSelected : function(){\n            if(this.productGridShowButton) Element.show(this.productGridShowButton);\n            var area = ['search', 'items', 'shipping_method', 'totals', 'giftmessage','billing_method'];\n            // prepare additional fields and filtered items of products\n            var fieldsPrepare = {};\n            var itemsFilter = [];\n            var products = this.gridProducts.toObject();\n            for (var productId in products) {\n                itemsFilter.push(productId);\n                var paramKey = 'item['+productId+']';\n                for (var productParamKey in products[productId]) {\n                    paramKey += '['+productParamKey+']';\n                    fieldsPrepare[paramKey] = products[productId][productParamKey];\n                }\n            }\n            this.productConfigureSubmit('product_to_add', area, fieldsPrepare, itemsFilter);\n            productConfigure.clean('quote_items');\n            this.hideArea('search');\n            this.gridProducts = $H({});\n        },\n\n        selectCustomer : function(grid, event){\n            var element = Event.findElement(event, 'tr');\n            if (element.title){\n                this.setCustomerId(element.title);\n            }\n        },\n\n        customerSelectorHide : function(){\n            this.hideArea('customer-selector');\n        },\n\n        customerSelectorShow : function(){\n            this.showArea('customer-selector');\n        },\n\n        storeSelectorHide : function(){\n            this.hideArea('store-selector');\n        },\n\n        storeSelectorShow : function(){\n            this.showArea('store-selector');\n        },\n\n        dataHide : function(){\n            this.hideArea('data');\n        },\n\n        dataShow : function(){\n            if ($('submit_order_top_button')) {\n                $('submit_order_top_button').show();\n            }\n            this.showArea('data');\n        },\n\n        clearShoppingCart : function(confirmMessage){\n            var self = this;\n\n            confirm({\n                content: confirmMessage,\n                actions: {\n                    confirm: function() {\n                        self.collectElementsValue = false;\n                        order.sidebarApplyChanges({'sidebar[empty_customer_cart]': 1});\n                        self.collectElementsValue = true;\n                    }\n                }\n            });\n        },\n\n        sidebarApplyChanges : function(auxiliaryParams) {\n            if ($(this.getAreaId('sidebar'))) {\n                var data = {};\n                if (this.collectElementsValue) {\n                    var elems = $(this.getAreaId('sidebar')).select('input');\n                    for (var i=0; i < elems.length; i++) {\n                        if (elems[i].getValue()) {\n                            data[elems[i].name] = elems[i].getValue();\n                        }\n                    }\n                }\n                if (auxiliaryParams instanceof Object) {\n                    for (var paramName in auxiliaryParams) {\n                        data[paramName] = String(auxiliaryParams[paramName]);\n                    }\n                }\n                data.reset_shipping = true;\n                this.loadArea(['sidebar', 'items', 'shipping_method', 'billing_method','totals', 'giftmessage'], true, data);\n            }\n        },\n\n        sidebarHide : function(){\n            if(this.storeId === false && $('page:left') && $('page:container')){\n                $('page:left').hide();\n                $('page:container').removeClassName('container');\n                $('page:container').addClassName('container-collapsed');\n            }\n        },\n\n        sidebarShow : function(){\n            if($('page:left') && $('page:container')){\n                $('page:left').show();\n                $('page:container').removeClassName('container-collapsed');\n                $('page:container').addClassName('container');\n            }\n        },\n\n        /**\n         * Show configuration of product and add handlers on submit form\n         *\n         * @param productId\n         */\n        sidebarConfigureProduct: function (listType, productId, itemId) {\n            // create additional fields\n            var params = {};\n            params.reset_shipping = true;\n            params.add_product = productId;\n            this.prepareParams(params);\n            for (var i in params) {\n                if (params[i] === null) {\n                    unset(params[i]);\n                } else if (typeof(params[i]) == 'boolean') {\n                    params[i] = params[i] ? 1 : 0;\n                }\n            }\n            var fields = [];\n            for (var name in params) {\n                fields.push(new Element('input', {type: 'hidden', name: name, value: params[name]}));\n            }\n            // add additional fields before triggered submit\n            productConfigure.setBeforeSubmitCallback(listType, function() {\n                productConfigure.addFields(fields);\n            }.bind(this));\n            // response handler\n            productConfigure.setOnLoadIFrameCallback(listType, function(response) {\n                if (!response.ok) {\n                    return;\n                }\n                this.loadArea(['items', 'shipping_method', 'billing_method','totals', 'giftmessage'], true);\n            }.bind(this));\n            // show item configuration\n            itemId = itemId ? itemId : productId;\n            productConfigure.showItemConfiguration(listType, itemId);\n            return false;\n        },\n\n        removeSidebarItem : function(id, from){\n            this.loadArea(['sidebar_'+from], 'sidebar_data_'+from, {remove_item:id, from:from});\n        },\n\n        itemsUpdate : function(){\n            var area = ['sidebar', 'items', 'shipping_method', 'billing_method','totals', 'giftmessage'];\n            // prepare additional fields\n            var fieldsPrepare = {update_items: 1};\n            var info = $('order-items_grid').select('input', 'select', 'textarea');\n            for(var i=0; i<info.length; i++){\n                if(!info[i].disabled && (info[i].type != 'checkbox' || info[i].checked)) {\n                    fieldsPrepare[info[i].name] = info[i].getValue();\n                }\n            }\n            fieldsPrepare = Object.extend(fieldsPrepare, this.productConfigureAddFields);\n            this.productConfigureSubmit('quote_items', area, fieldsPrepare);\n            this.orderItemChanged = false;\n        },\n\n        itemsOnchangeBind : function(){\n            var elems = $('order-items_grid').select('input', 'select', 'textarea');\n            for(var i=0; i<elems.length; i++){\n                if(!elems[i].bindOnchange){\n                    elems[i].bindOnchange = true;\n                    elems[i].observe('change', this.itemChange.bind(this))\n                }\n            }\n        },\n\n        itemChange : function(event){\n            this.giftmessageOnItemChange(event);\n            this.orderItemChanged = true;\n        },\n\n        /**\n         * Submit batch of configured products\n         *\n         * @param listType\n         * @param area\n         * @param fieldsPrepare\n         * @param itemsFilter\n         */\n        productConfigureSubmit : function(listType, area, fieldsPrepare, itemsFilter) {\n            // prepare loading areas and build url\n            area = this.prepareArea(area);\n            this.loadingAreas = area;\n            var url = this.loadBaseUrl + 'block/' + area + '?isAjax=true';\n\n            // prepare additional fields\n            fieldsPrepare = this.prepareParams(fieldsPrepare);\n            fieldsPrepare.reset_shipping = 1;\n            fieldsPrepare.json = 1;\n\n            // create fields\n            var fields = [];\n            for (var name in fieldsPrepare) {\n                fields.push(new Element('input', {type: 'hidden', name: name, value: fieldsPrepare[name]}));\n            }\n            productConfigure.addFields(fields);\n\n            // filter items\n            if (itemsFilter) {\n                productConfigure.addItemsFilter(listType, itemsFilter);\n            }\n\n            // prepare and do submit\n            productConfigure.addListType(listType, {urlSubmit: url});\n            productConfigure.setOnLoadIFrameCallback(listType, function(response){\n                this.loadAreaResponseHandler(response);\n            }.bind(this));\n            productConfigure.submit(listType);\n            // clean\n            this.productConfigureAddFields = {};\n        },\n\n        /**\n         * Show configuration of quote item\n         *\n         * @param itemId\n         */\n        showQuoteItemConfiguration: function(itemId){\n            var listType = 'quote_items';\n            var qtyElement = $('order-items_grid').select('input[name=\"item\\['+itemId+'\\]\\[qty\\]\"]')[0];\n            productConfigure.setConfirmCallback(listType, function() {\n                // sync qty of popup and qty of grid\n                var confirmedCurrentQty = productConfigure.getCurrentConfirmedQtyElement();\n                if (qtyElement && confirmedCurrentQty && !isNaN(confirmedCurrentQty.value)) {\n                    qtyElement.value = confirmedCurrentQty.value;\n                }\n                this.productConfigureAddFields['item['+itemId+'][configured]'] = 1;\n                this.itemsUpdate();\n\n            }.bind(this));\n            productConfigure.setShowWindowCallback(listType, function() {\n                // sync qty of grid and qty of popup\n                var formCurrentQty = productConfigure.getCurrentFormQtyElement();\n                if (formCurrentQty && qtyElement && !isNaN(qtyElement.value)) {\n                    formCurrentQty.value = qtyElement.value;\n                }\n            }.bind(this));\n            productConfigure.showItemConfiguration(listType, itemId);\n        },\n\n        accountFieldsBind : function(container){\n            if($(container)){\n                var fields = $(container).select('input', 'select', 'textarea');\n                for(var i=0; i<fields.length; i++){\n                    if(fields[i].id == 'group_id'){\n                        fields[i].observe('change', this.accountGroupChange.bind(this))\n                    }\n                    else{\n                        fields[i].observe('change', this.accountFieldChange.bind(this))\n                    }\n                }\n            }\n        },\n\n        accountGroupChange : function(){\n            this.loadArea(['data'], true, this.serializeData('order-form_account').toObject());\n        },\n\n        accountFieldChange : function(){\n            this.saveData(this.serializeData('order-form_account'));\n        },\n\n        commentFieldsBind : function(container){\n            if($(container)){\n                var fields = $(container).select('input', 'textarea');\n                for(var i=0; i<fields.length; i++)\n                    fields[i].observe('change', this.commentFieldChange.bind(this))\n            }\n        },\n\n        commentFieldChange : function(){\n            this.saveData(this.serializeData('order-comment'));\n        },\n\n        giftmessageFieldsBind : function(container){\n            if($(container)){\n                var fields = $(container).select('input', 'textarea');\n                for(var i=0; i<fields.length; i++)\n                    fields[i].observe('change', this.giftmessageFieldChange.bind(this))\n            }\n        },\n\n        giftmessageFieldChange : function(){\n            this.giftMessageDataChanged = true;\n        },\n\n        giftmessageOnItemChange : function(event) {\n            var element = Event.element(event);\n            if(element.name.indexOf(\"giftmessage\") != -1 && element.type == \"checkbox\" && !element.checked) {\n                var messages = $(\"order-giftmessage\").select('textarea');\n                var name;\n                for(var i=0; i<messages.length; i++) {\n                    name = messages[i].id.split(\"_\");\n                    if(name.length < 2) continue;\n                    if (element.name.indexOf(\"[\" + name[1] + \"]\") != -1 && messages[i].value != \"\") {\n                        alert({\n                            content: \"First, clean the Message field in Gift Message form\"\n                        });\n                        element.checked = true;\n                    }\n                }\n            }\n        },\n\n        loadArea : function(area, indicator, params){\n            var deferred = new jQuery.Deferred();\n            var url = this.loadBaseUrl;\n            if (area) {\n                area = this.prepareArea(area);\n                url += 'block/' + area;\n            }\n            if (indicator === true) indicator = 'html-body';\n            params = this.prepareParams(params);\n            params.json = true;\n            if (!this.loadingAreas) this.loadingAreas = [];\n            if (indicator) {\n                this.loadingAreas = area;\n                new Ajax.Request(url, {\n                    parameters:params,\n                    loaderArea: indicator,\n                    onSuccess: function(transport) {\n                        var response = transport.responseText.evalJSON();\n                        this.loadAreaResponseHandler(response);\n                        deferred.resolve();\n                    }.bind(this)\n                });\n            }\n            else {\n                new Ajax.Request(url, {\n                    parameters:params,\n                    loaderArea: indicator,\n                    onSuccess: function(transport) {\n                        deferred.resolve();\n                    }\n                });\n            }\n            if (typeof productConfigure != 'undefined' && area instanceof Array && area.indexOf('items') != -1) {\n                productConfigure.clean('quote_items');\n            }\n            return deferred.promise();\n        },\n\n        loadAreaResponseHandler : function (response) {\n            if (response.error) {\n                alert({\n                    content: response.message\n                });\n            }\n            if (response.ajaxExpired && response.ajaxRedirect) {\n                setLocation(response.ajaxRedirect);\n            }\n            if (!this.loadingAreas) {\n                this.loadingAreas = [];\n            }\n            if (typeof this.loadingAreas == 'string') {\n                this.loadingAreas = [this.loadingAreas];\n            }\n            if (this.loadingAreas.indexOf('message') == -1) {\n                this.loadingAreas.push('message');\n            }\n            if (response.header) {\n                jQuery('.page-actions-inner').attr('data-title', response.header);\n            }\n\n            for (var i = 0; i < this.loadingAreas.length; i++) {\n                var id = this.loadingAreas[i];\n                if ($(this.getAreaId(id))) {\n                    if ('message' != id || response[id]) {\n                        $(this.getAreaId(id)).update(response[id]);\n                    }\n                    if ($(this.getAreaId(id)).callback) {\n                        this[$(this.getAreaId(id)).callback]();\n                    }\n                }\n            }\n        },\n\n        prepareArea : function(area) {\n            if (this.giftMessageDataChanged) {\n                return area.without('giftmessage');\n            }\n            return area;\n        },\n\n        saveData : function(data){\n            this.loadArea(false, false, data);\n        },\n\n        showArea : function(area){\n            var id = this.getAreaId(area);\n            if($(id)) {\n                $(id).show();\n                this.areaOverlay();\n            }\n        },\n\n        hideArea : function(area){\n            var id = this.getAreaId(area);\n            if($(id)) {\n                $(id).hide();\n                this.areaOverlay();\n            }\n        },\n\n        areaOverlay : function()\n        {\n            $H(order.overlayData).each(function(e){\n                e.value.fx();\n            });\n        },\n\n        getAreaId : function(area){\n            return 'order-'+area;\n        },\n\n        prepareParams : function(params){\n            if (!params) {\n                params = {};\n            }\n            if (!params.customer_id) {\n                params.customer_id = this.customerId;\n            }\n            if (!params.store_id) {\n                params.store_id = this.storeId;\n            }\n            if (!params.currency_id) {\n                params.currency_id = this.currencyId;\n            }\n            if (!params.form_key) {\n                params.form_key = FORM_KEY;\n            }\n\n            if (this.isPaymentValidationAvailable()) {\n                var data = this.serializeData('order-billing_method');\n                if (data) {\n                    data.each(function(value) {\n                        params[value[0]] = value[1];\n                    });\n                }\n            } else {\n                params['payment[method]'] = this.paymentMethod;\n            }\n            return params;\n        },\n\n        /**\n         * Prevent from sending credit card information to server for some payment methods\n         *\n         * @returns {boolean}\n         */\n        isPaymentValidationAvailable : function(){\n            return ((typeof this.paymentMethod) == 'undefined'\n                || this.excludedPaymentMethods.indexOf(this.paymentMethod) == -1);\n        },\n\n        /**\n         * Serializes container form elements data.\n         *\n         * @param {String} container\n         * @return {Object}\n         */\n        serializeData: function (container) {\n            var fields = $(container).select('input', 'select', 'textarea'),\n                data = Form.serializeElements(fields, true);\n\n            return $H(data);\n        },\n\n        toggleCustomPrice: function(checkbox, elemId, tierBlock) {\n            if (checkbox.checked) {\n                $(elemId).disabled = false;\n                $(elemId).show();\n                if($(tierBlock)) $(tierBlock).hide();\n            }\n            else {\n                $(elemId).disabled = true;\n                $(elemId).hide();\n                if($(tierBlock)) $(tierBlock).show();\n            }\n        },\n\n        submit : function()\n        {\n            var $editForm = jQuery('#edit_form');\n\n            if ($editForm.valid()) {\n                $editForm.trigger('processStart');\n                $editForm.trigger('submitOrder');\n            }\n        },\n\n        _realSubmit: function () {\n            var disableAndSave = function() {\n                disableElements('save');\n                jQuery('#edit_form').on('invalid-form.validate', function() {\n                    enableElements('save');\n                    jQuery('#edit_form').trigger('processStop');\n                    jQuery('#edit_form').off('invalid-form.validate');\n                });\n                jQuery('#edit_form').triggerHandler('save');\n            }\n            if (this.orderItemChanged) {\n                var self = this;\n\n                jQuery('#edit_form').trigger('processStop');\n\n                confirm({\n                    content: jQuery.mage.__('You have item changes'),\n                    actions: {\n                        confirm: function() {\n                            jQuery('#edit_form').trigger('processStart');\n                            disableAndSave();\n                        },\n                        cancel: function() {\n                            self.itemsUpdate();\n                        }\n                    }\n                });\n            } else {\n                disableAndSave();\n            }\n        },\n\n        overlay : function(elId, show, observe) {\n            if (typeof(show) == 'undefined') { show = true; }\n\n            var orderObj = this;\n            var obj = this.overlayData.get(elId);\n            if (!obj) {\n                obj = {\n                    show: show,\n                    el: elId,\n                    order: orderObj,\n                    fx: function(event) {\n                        this.order.processOverlay(this.el, this.show);\n                    }\n                };\n                obj.bfx = obj.fx.bindAsEventListener(obj);\n                this.overlayData.set(elId, obj);\n            } else {\n                obj.show = show;\n                Event.stopObserving(window, 'resize', obj.bfx);\n            }\n\n            Event.observe(window, 'resize', obj.bfx);\n\n            this.processOverlay(elId, show);\n        },\n\n        processOverlay : function(elId, show) {\n            var el = $(elId);\n\n            if (!el) {\n                return;\n            }\n\n            var parentEl = el.up(1);\n            if (show) {\n                parentEl.removeClassName('ignore-validate');\n            } else {\n                parentEl.addClassName('ignore-validate');\n            }\n\n            if (Prototype.Browser.IE) {\n                parentEl.select('select').each(function (elem) {\n                    if (show) {\n                        elem.needShowOnSuccess = false;\n                        elem.style.visibility = '';\n                    } else {\n                        elem.style.visibility = 'hidden';\n                        elem.needShowOnSuccess = true;\n                    }\n                });\n            }\n\n            parentEl.setStyle({position: 'relative'});\n            el.setStyle({\n                display: show ? 'none' : ''\n            });\n        },\n\n        validateVat: function(parameters)\n        {\n            var params = {\n                country: $(parameters.countryElementId).value,\n                vat: $(parameters.vatElementId).value\n            };\n\n            if (this.storeId !== false) {\n                params.store_id = this.storeId;\n            }\n\n            var currentCustomerGroupId = $(parameters.groupIdHtmlId)\n                ? $(parameters.groupIdHtmlId).value : '';\n\n            new Ajax.Request(parameters.validateUrl, {\n                parameters: params,\n                onSuccess: function(response) {\n                    var message = '';\n                    var groupActionRequired = null;\n                    try {\n                        response = response.responseText.evalJSON();\n\n                        if (null === response.group) {\n                            if (true === response.valid) {\n                                message = parameters.vatValidMessage;\n                            } else if (true === response.success) {\n                                message = parameters.vatInvalidMessage.replace(/%s/, params.vat);\n                            } else {\n                                message = parameters.vatValidationFailedMessage;\n                            }\n                        } else {\n                            if (true === response.valid) {\n                                message = parameters.vatValidAndGroupValidMessage;\n                                if (0 === response.group) {\n                                    message = parameters.vatValidAndGroupInvalidMessage;\n                                    groupActionRequired = 'inform';\n                                } else if (currentCustomerGroupId != response.group) {\n                                    message = parameters.vatValidAndGroupChangeMessage;\n                                    groupActionRequired = 'change';\n                                }\n                            } else if (response.success) {\n                                message = parameters.vatInvalidMessage.replace(/%s/, params.vat);\n                                groupActionRequired = 'inform';\n                            } else {\n                                message = parameters.vatValidationFailedMessage;\n                                groupActionRequired = 'inform';\n                            }\n                        }\n                    } catch (e) {\n                        message = parameters.vatValidationFailedMessage;\n                    }\n                    if (null === groupActionRequired) {\n                        alert({\n                            content: message\n                        });\n                    }\n                    else {\n                        this.processCustomerGroupChange(\n                            parameters.groupIdHtmlId,\n                            message,\n                            parameters.vatCustomerGroupMessage,\n                            parameters.vatGroupErrorMessage,\n                            response.group,\n                            groupActionRequired\n                        );\n                    }\n                }.bind(this)\n            });\n        },\n\n        processCustomerGroupChange: function(groupIdHtmlId, message, customerGroupMessage, errorMessage, groupId, action)\n        {\n            var groupMessage = '';\n            try {\n                var currentCustomerGroupId = $(groupIdHtmlId).value;\n                var currentCustomerGroupTitle =\n                    $$('#' + groupIdHtmlId + ' > option[value=' + currentCustomerGroupId + ']')[0].text;\n                var customerGroupOption = $$('#' + groupIdHtmlId + ' > option[value=' + groupId + ']')[0];\n                groupMessage = customerGroupMessage.replace(/%s/, customerGroupOption.text);\n            } catch (e) {\n                groupMessage = errorMessage;\n                if (action === 'change') {\n                    message = '';\n                    action = 'inform';\n                }\n            }\n\n            if (action === 'change') {\n                var confirmText = message.replace(/%s/, customerGroupOption.text);\n                confirmText = confirmText.replace(/%s/, currentCustomerGroupTitle);\n                if (confirm(confirmText)) {\n                    $$('#' + groupIdHtmlId + ' option').each(function (o) {\n                        o.selected = o.readAttribute('value') == groupId;\n                    });\n                    this.accountGroupChange();\n                }\n            } else if (action === 'inform') {\n                alert({\n                    content: message + '\\n' + groupMessage\n                });\n            }\n        }\n    };\n\n    window.OrderFormArea = Class.create();\n    OrderFormArea.prototype = {\n        _name: null,\n        _node: null,\n        _parent: null,\n        _callbackName: null,\n\n        initialize: function(name, node, parent){\n            if(!node)\n                return;\n            this._name = name;\n            this._parent = parent;\n            this._callbackName = node.callback;\n            if (typeof this._callbackName == 'undefined') {\n                this._callbackName = name + 'Loaded';\n                node.callback = this._callbackName;\n            }\n            parent[this._callbackName] = parent[this._callbackName].wrap((function (proceed){\n                proceed();\n                this.onLoad();\n            }).bind(this));\n\n            this.setNode(node);\n        },\n\n        setNode: function(node){\n            if (!node.callback) {\n                node.callback = this._callbackName;\n            }\n            this.node = node;\n        },\n\n        onLoad: function(){\n        }\n    };\n\n    window.ControlButton = Class.create();\n\n    ControlButton.prototype = {\n        _label: '',\n        _node: null,\n\n        initialize: function(label, id){\n            this._label = label;\n            this._node = new Element('button', {\n                'class': 'action-secondary action-add',\n                'type':  'button'\n            });\n            if (typeof id !== 'undefined') {\n                this._node.setAttribute('id', id)\n            }\n        },\n\n        onClick: function(){\n        },\n\n        insertIn: function(element, position){\n            var node = Object.extend(this._node),\n                content = {};\n            node.observe('click', this.onClick);\n            node.update('<span>' + this._label + '</span>');\n            content[position] = node;\n            Element.insert(element, content);\n        },\n\n        getLabel: function(){\n            return this._label;\n        }\n    };\n});\n","Magento_Sales/order/create/giftmessage.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/********************* GIFT OPTIONS POPUP ***********************/\n/********************* GIFT OPTIONS SET ***********************/\n\ndefine([\n    'jquery',\n    'jquery/ui',\n    'mage/translate',\n    'mage/validation',\n    'prototype'\n], function (jQuery) {\n\n    window.giftMessagesController = {\n        toogleRequired: function (source, objects) {\n            if (!$(source).value.blank()) {\n                objects.each(function (item) {\n                    $(item).addClassName('required-entry');\n                    var label = findFieldLabel($(item));\n\n                    if (label) {\n                        var span = label.down('span');\n\n                        if (!span) {\n                            Element.insert(label, {\n                                bottom: '&nbsp;<span class=\"required\">*</span>'\n                            });\n                        }\n                    }\n                });\n            } else {\n                objects.each(function (item) {\n                    if ($(source).formObj && $(source).formObj.validator) {\n                        $(source).formObj.validator.reset(item);\n                    }\n                    $(item).removeClassName('required-entry');\n                    var label = findFieldLabel($(item));\n\n                    if (label) {\n                        var span = label.down('span');\n\n                        if (span) {\n                            Element.remove(span);\n                        }\n                    }\n                    // Hide validation advices if exist\n                    if ($(item) && $(item).advices) {\n                        $(item).advices.each(function (pair) {\n                            if (pair.value != null) pair.value.hide();\n                        });\n                    }\n                });\n            }\n        },\n        toogleGiftMessage: function (container) {\n            if (!$(container).toogleGiftMessage) {\n                $(container).toogleGiftMessage = true;\n                $(this.getFieldId(container, 'edit')).show();\n                $(container).down('.action-link').addClassName('open');\n                $(container).down('.default-text').hide();\n                $(container).down('.close-text').show();\n            } else {\n                $(container).toogleGiftMessage = false;\n                $(this.getFieldId(container, 'message')).formObj = $(this.getFieldId(container, 'form'));\n                var form = jQuery('#' + this.getFieldId(container, 'form'));\n\n                jQuery('#' + this.getFieldId(container, 'form')).validate({\n                    errorClass: 'mage-error'\n                });\n\n                if (!form.valid()) {\n                    return false;\n                }\n\n                new Ajax.Request($(this.getFieldId(container, 'form')).action, {\n                    parameters: Form.serialize($(this.getFieldId(container, 'form')), true),\n                    loaderArea: container,\n                    onComplete: function (transport) {\n\n                        $(container).down('.action-link').removeClassName('open');\n                        $(container).down('.default-text').show();\n                        $(container).down('.close-text').hide();\n                        $(this.getFieldId(container, 'edit')).hide();\n\n                        if (transport.responseText.match(/YES/g)) {\n                            $(container).down('.default-text').down('.edit').show();\n                            $(container).down('.default-text').down('.add').hide();\n                        } else {\n                            $(container).down('.default-text').down('.add').show();\n                            $(container).down('.default-text').down('.edit').hide();\n                        }\n\n                    }.bind(this)\n                });\n            }\n\n            return false;\n        },\n        saveGiftMessage: function (container) {\n            $(this.getFieldId(container, 'message')).formObj = $(this.getFieldId(container, 'form'));\n\n            var form = jQuery('#' + this.getFieldId(container, 'form'));\n\n            form.validate({\n                errorClass: 'mage-error'\n            });\n\n            if (!form.valid()) {\n                return;\n            }\n\n            new Ajax.Request($(this.getFieldId(container, 'form')).action, {\n                parameters: Form.serialize($(this.getFieldId(container, 'form')), true),\n                loaderArea: container,\n                onSuccess: function (response) {\n                    var message = '<div class=\"messages\"><div class=\"message message-success success\">' +\n                        response.responseText +\n                        '<div data-ui-id=\"messages-message-success\"></div></div></div>';\n\n                    jQuery('#messages').html(message);\n                    jQuery(document).scrollTop(0);\n                }\n            });\n        },\n        getFieldId: function (container, name) {\n            return container + '_' + name;\n        }\n    };\n\n    function findFieldLabel(field) {\n        var tdField = $(field).up('td');\n\n        if (tdField) {\n            var tdLabel = tdField.previous('td');\n\n            if (tdLabel) {\n                var label = tdLabel.down('label');\n\n                if (label) {\n                    return label;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    window.findFieldLabel = findFieldLabel;\n\n    window.GiftOptionsPopup = Class.create();\n    GiftOptionsPopup.prototype = {\n        //giftOptionsWindowMask: null,\n        giftOptionsWindow: null,\n\n        initialize: function () {\n            $$('.action-link').each(function (el) {\n                Event.observe(el, 'click', this.showItemGiftOptions.bind(this));\n            }, this);\n\n            // Move gift options popup to start of body, because soon it will contain FORM tag that can break DOM layout if within other FORM\n            var oldPopupContainer = $('gift_options_configure');\n\n            if (oldPopupContainer) {\n                oldPopupContainer.remove();\n            }\n\n            var newPopupContainer = $('gift_options_configure_new');\n\n            $(document.body).insert({\n                top: newPopupContainer\n            });\n            newPopupContainer.id = 'gift_options_configure';\n\n            // Put controls container inside a FORM tag so we can use Validator\n            var form = new Element('form', {\n                action: '#', id: 'gift_options_configuration_form', method: 'post'\n            });\n            var formContents = $('gift_options_form_contents');\n\n            if (formContents) {\n                formContents.parentNode.appendChild(form);\n                form.appendChild(formContents);\n            }\n\n            this.giftOptionsWindow = $('gift_options_configure');\n\n            jQuery(this.giftOptionsWindow).dialog({\n                autoOpen:   false,\n                modal:      true,\n                resizable:  false,\n                dialogClass: 'gift-options-popup',\n                minWidth:   500,\n                width:      '75%',\n                position: {\n                    my: 'left+12.5% top',\n                    at: 'center top',\n                    of: 'body'\n                },\n                open: function () {\n                    jQuery(this).closest('.ui-dialog').addClass('ui-dialog-active');\n\n                    var topMargin = jQuery(this).closest('.ui-dialog').children('.ui-dialog-titlebar').outerHeight() + 30;\n\n                    jQuery(this).closest('.ui-dialog').css('margin-top', topMargin);\n                },\n                close: function () {\n                    jQuery(this).closest('.ui-dialog').removeClass('ui-dialog-active');\n                }\n            });\n        },\n\n        showItemGiftOptions: function (event) {\n            var element = Event.element(event).id;\n            var itemId = element.sub('gift_options_link_', '');\n\n            jQuery(this.giftOptionsWindow).dialog('open');\n\n            this.setTitle(itemId);\n\n            Event.observe($('gift_options_cancel_button'), 'click', this.onCloseButton.bind(this));\n            Event.observe($('gift_options_ok_button'), 'click', this.onOkButton.bind(this));\n            Event.stop(event);\n        },\n\n        setTitle: function (itemId) {\n            var productTitleElement = $('order_item_' + itemId + '_title');\n            var productTitle = '';\n\n            if (productTitleElement) {\n                productTitle = productTitleElement.innerHTML;\n            }\n            jQuery(this.giftOptionsWindow).dialog({\n                title: jQuery.mage.__('Gift Options for ') + productTitle\n            });\n        },\n\n        onOkButton: function () {\n            var giftOptionsForm = jQuery('#gift_options_configuration_form');\n\n            if (!giftOptionsForm.validate({\n                errorClass: 'mage-error'\n            }).valid()) {\n                return false;\n            }\n\n            if (jQuery.isFunction(giftOptionsForm[0].reset)) {\n                giftOptionsForm[0].reset();\n            }\n            this.closeWindow();\n\n            return true;\n        },\n\n        onCloseButton: function () {\n            this.closeWindow();\n        },\n\n        closeWindow: function () {\n            jQuery(this.giftOptionsWindow).dialog('close');\n        }\n    };\n\n    window.GiftMessageSet = Class.create();\n\n    GiftMessageSet.prototype = {\n        destPrefix: 'current_item_giftmessage_',\n        sourcePrefix: 'giftmessage_',\n        fields: ['sender', 'recipient', 'message'],\n        isObserved: false,\n        callback: null,\n\n        initialize: function () {\n            $$('.action-link').each(function (el) {\n                Event.observe(el, 'click', this.setData.bind(this));\n            }, this);\n        },\n\n        setData: function (event) {\n            var element = Event.element(event).id;\n\n            this.id = element.sub('gift_options_link_', '');\n\n            if ($('gift-message-form-data-' + this.id)) {\n                this.fields.each(function (el) {\n                    if ($(this.sourcePrefix + this.id + '_' + el) && $(this.destPrefix + el)) {\n                        $(this.destPrefix + el).value = $(this.sourcePrefix + this.id + '_' + el).value;\n                    }\n                }, this);\n                $('gift_options_giftmessage').show();\n            } else if ($('gift_options_giftmessage')) {\n                $('gift_options_giftmessage').hide();\n            }\n\n            if (!this.isObserved) {\n                Event.observe('gift_options_ok_button', 'click', this.saveData.bind(this));\n                this.isObserved = true;\n            }\n        },\n\n        prepareSaveData: function () {\n            var hash = $H();\n\n            $$('div[id^=gift_options_data_]').each(function (el) {\n                var fields = el.select('input', 'select', 'textarea');\n                var data = Form.serializeElements(fields, true);\n\n                hash.update(data);\n            });\n\n            return hash;\n        },\n\n        setSaveCallback: function (callback) {\n            if (typeof callback == 'function') {\n                this.callback = callback;\n            }\n        },\n\n        saveData: function (event) {\n            this.fields.each(function (el) {\n                if ($(this.sourcePrefix + this.id + '_' + el) && $(this.destPrefix + el)) {\n                    $(this.sourcePrefix + this.id + '_' + el).value = $(this.destPrefix + el).value;\n                }\n            }, this);\n\n            if ($(this.sourcePrefix + this.id + '_form')) {\n                $(this.sourcePrefix + this.id + '_form').request();\n            } else if (typeof order != 'undefined') {\n                var data = this.prepareSaveData();\n                var self = this;\n\n                jQuery.when(order.loadArea(['items'], true, data.toObject())).done(function () {\n                    if (self.callback !== null) {\n                        self.callback();\n                    }\n                });\n            }\n        }\n    };\n\n});\n","Magento_Sales/order/create/form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global AdminOrder */\ndefine([\n    'jquery',\n    'Magento_Sales/order/create/scripts'\n], function (jQuery) {\n    'use strict';\n\n    var $el = jQuery('#edit_form'),\n        config,\n        baseUrl,\n        order,\n        payment;\n\n    if (!$el.length || !$el.data('order-config')) {\n        return;\n    }\n\n    config = $el.data('order-config');\n    baseUrl = $el.data('load-base-url');\n\n    order = new AdminOrder(config);\n    order.setLoadBaseUrl(baseUrl);\n\n    payment = {\n        switchMethod: order.switchPaymentMethod.bind(order)\n    };\n\n    window.order = order;\n    window.payment = payment;\n});\n","Magento_Sales/order/edit/message.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery/ui',\n    'Magento_Ui/js/modal/modal',\n    'mage/translate'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.orderEditDialog', {\n        options: {\n            url:     null,\n            message: null,\n            modal:  null\n        },\n\n        /**\n         * @protected\n         */\n        _create: function () {\n            this._prepareDialog();\n        },\n\n        /**\n         * Show modal\n         */\n        showDialog: function () {\n            this.options.dialog.html(this.options.message).modal('openModal');\n        },\n\n        /**\n         * Redirect to edit page\n         */\n        redirect: function () {\n            window.location = this.options.url;\n        },\n\n        /**\n         * Prepare modal\n         * @protected\n         */\n        _prepareDialog: function () {\n            var self = this;\n\n            this.options.dialog = $('<div class=\"ui-dialog-content ui-widget-content\"></div>').modal({\n                type: 'popup',\n                modalClass: 'edit-order-popup',\n                title: $.mage.__('Edit Order'),\n                buttons: [{\n                    text: $.mage.__('Ok'),\n                    'class': 'action-primary',\n\n                    /** @inheritdoc */\n                    click: function () {\n                        self.redirect();\n                    }\n                }]\n            });\n        }\n    });\n\n    return $.mage.orderEditDialog;\n});\n","Magento_Sales/order/edit/address/form.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    /**\n     * Currently Magento App stores both  region_id and region (as text) values.\n     * To prevent missing region (as text) we need to copy it in hidden field.\n     * @param {Array} config\n     * @param {String} element\n     */\n    return function (config, element) {\n        var form = $(element),\n            regionId = form.find('#region_id'),\n\n            /**\n             * Set region callback\n             */\n            setRegion = function () {\n                form.find('#region').val(regionId.filter(':visible').find(':selected').text());\n            };\n\n        if (regionId.is('visible')) {\n            setRegion();\n        }\n\n        regionId.on('change', setRegion);\n        form.find('#country_id').on('change', setRegion);\n    };\n});\n","Magento_Sales/order/view/post-wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/confirm',\n    'mage/translate'\n], function ($, confirm) {\n    'use strict';\n\n    /**\n     * @param {String} url\n     * @returns {Object}\n     */\n    function getForm(url) {\n        return $('<form>', {\n            'action': url,\n            'method': 'POST'\n        }).append($('<input>', {\n            'name': 'form_key',\n            'value': window.FORM_KEY,\n            'type': 'hidden'\n        }));\n    }\n\n    $('#order-view-cancel-button').click(function () {\n        var msg = $.mage.__('Are you sure you want to cancel this order?'),\n            url = $('#order-view-cancel-button').data('url');\n\n        confirm({\n            'content': msg,\n            'actions': {\n\n                /**\n                 * 'Confirm' action handler.\n                 */\n                confirm: function () {\n                    getForm(url).appendTo('body').submit();\n                }\n            }\n        });\n\n        return false;\n    });\n\n    $('#order-view-hold-button').click(function () {\n        var url = $('#order-view-hold-button').data('url');\n\n        getForm(url).appendTo('body').submit();\n    });\n\n    $('#order-view-unhold-button').click(function () {\n        var url = $('#order-view-unhold-button').data('url');\n\n        getForm(url).appendTo('body').submit();\n    });\n});\n","jquery/jquery.tabs.js":"/* ========================================================\n * bootstrap-tab.js v2.0.4\n * http://twitter.github.com/bootstrap/javascript.html#tabs\n * ========================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================== */\n\ndefine([\n  \"jquery\"\n], function(jQuery){\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* TAB CLASS DEFINITION\n  * ==================== */\n\n  var Tab = function ( element ) {\n    this.element = $(element)\n  };\n\n  Tab.prototype = {\n\n    constructor: Tab\n\n  , show: function () {\n      var $this = this.element\n        , $ul = $this.closest('ul:not(.dropdown-menu)')\n        , selector = $this.attr('data-target')\n        , previous\n        , $target\n        , e;\n\n      if (!selector) {\n        selector = $this.attr('href');\n        selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, ''); //strip for ie7\n      }\n\n      if ( $this.parent('li').hasClass('active') ) return;\n\n      previous = $ul.find('.active a').last()[0];\n\n      e = $.Event('show', {\n        relatedTarget: previous\n      });\n\n      $this.trigger(e);\n\n      if (e.isDefaultPrevented()) return;\n\n      $target = $(selector);\n\n      this.activate($this.parent('li'), $ul);\n      this.activate($target, $target.parent(), function () {\n        $this.trigger({\n          type: 'shown'\n        , relatedTarget: previous\n        })\n      })\n    }\n\n  , activate: function ( element, container, callback) {\n      var $active = container.find('> .active')\n        , transition = callback\n            && $.support.transition\n            && $active.hasClass('fade');\n\n      function next() {\n        $active\n          .removeClass('active')\n          .find('> .dropdown-menu > .active')\n          .removeClass('active');\n\n        element.addClass('active');\n\n        if (transition) {\n          element[0].offsetWidth; // reflow for transition\n          element.addClass('in');\n        } else {\n          element.removeClass('fade')\n        }\n\n        if ( element.parent('.dropdown-menu') ) {\n          element.closest('li.dropdown').addClass('active')\n        }\n\n        callback && callback()\n      }\n\n      transition ?\n        $active.one($.support.transition.end, next) :\n        next();\n\n      $active.removeClass('in')\n    }\n  };\n\n\n /* TAB PLUGIN DEFINITION\n  * ===================== */\n\n  $.fn.tab = function ( option ) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('tab');\n      if (!data) $this.data('tab', (data = new Tab(this)));\n      if (typeof option == 'string') data[option]()\n    })\n  };\n\n  $.fn.tab.Constructor = Tab;\n\n\n /* TAB DATA-API\n  * ============ */\n\n  $(function () {\n    $('body').on('click.tab.data-api', '[data-toggle=\"tab\"], [data-toggle=\"pill\"]', function (e) {\n      e.preventDefault();\n      $(this).tab('show')\n    })\n  })\n\n}(jQuery);\n\n/* =============================================================\n * bootstrap-collapse.js v2.0.4\n * http://twitter.github.com/bootstrap/javascript.html#collapse\n * =============================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ============================================================ */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* COLLAPSE PUBLIC CLASS DEFINITION\n  * ================================ */\n\n  var Collapse = function (element, options) {\n    this.$element = $(element);\n    this.options = $.extend({}, $.fn.collapse.defaults, options);\n\n    if (this.options.parent) {\n      this.$parent = $(this.options.parent)\n    }\n\n    this.options.toggle && this.toggle()\n  };\n\n  Collapse.prototype = {\n\n    constructor: Collapse\n\n  , dimension: function () {\n      var hasWidth = this.$element.hasClass('width');\n      return hasWidth ? 'width' : 'height'\n    }\n\n  , show: function () {\n      var dimension\n        , scroll\n        , actives\n        , hasData;\n\n      if (this.transitioning) return;\n\n      dimension = this.dimension();\n      scroll = $.camelCase(['scroll', dimension].join('-'));\n      actives = this.$parent && this.$parent.find('> .accordion-group > .in');\n\n      if (actives && actives.length) {\n        hasData = actives.data('collapse');\n        if (hasData && hasData.transitioning) return;\n        actives.collapse('hide');\n        hasData || actives.data('collapse', null)\n      }\n\n      this.$element[dimension](0);\n      this.transition('addClass', $.Event('show'), 'shown');\n      this.$element[dimension](this.$element[0][scroll]);\n    }\n\n  , hide: function () {\n      var dimension;\n      if (this.transitioning) return;\n      dimension = this.dimension();\n      this.reset(this.$element[dimension]());\n      this.transition('removeClass', $.Event('hide'), 'hidden');\n      this.$element[dimension](0)\n    }\n\n  , reset: function (size) {\n      var dimension = this.dimension();\n\n      this.$element\n        .removeClass('collapse')\n        [dimension](size || 'auto')\n        [0].offsetWidth;\n\n      this.$element[size !== null ? 'addClass' : 'removeClass']('collapse');\n\n      return this\n    }\n\n  , transition: function (method, startEvent, completeEvent) {\n      var that = this\n        , complete = function () {\n            if (startEvent.type == 'show') that.reset();\n            that.transitioning = 0;\n            that.$element.trigger(completeEvent)\n          };\n\n      this.$element.trigger(startEvent);\n\n      if (startEvent.isDefaultPrevented()) return;\n\n      this.transitioning = 1;\n\n      this.$element[method]('in');\n\n      $.support.transition && this.$element.hasClass('collapse') ?\n        this.$element.one($.support.transition.end, complete) :\n        complete()\n    }\n\n  , toggle: function () {\n      this[this.$element.hasClass('in') ? 'hide' : 'show']();\n    }\n\n  };\n\n\n /* COLLAPSIBLE PLUGIN DEFINITION\n  * ============================== */\n\n  $.fn.collapse = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('collapse')\n        , options = typeof option == 'object' && option;\n      if (!data) $this.data('collapse', (data = new Collapse(this, options)));\n      if (typeof option == 'string') data[option]()\n    })\n  };\n\n  $.fn.collapse.defaults = {\n    toggle: true\n  };\n\n  $.fn.collapse.Constructor = Collapse;\n\n\n /* COLLAPSIBLE DATA-API\n  * ==================== */\n\n  $(function () {\n    $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) {\n      var $this = $(this), href\n        , target = $this.attr('data-target')\n          || e.preventDefault()\n          || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') //strip for ie7\n        , option = $(target).data('collapse') ? 'toggle' : $this.data();\n      $(target).collapse(option);\n        $(this).toggleClass('active');\n    })\n  })\n\n}(jQuery);\n\n});","jquery/jquery-ui-timepicker-addon.js":"/*! jQuery Timepicker Addon - v1.4.3 - 2013-11-30\n* http://trentrichardson.com/examples/timepicker\n* Copyright (c) 2013 Trent Richardson; Licensed MIT */\n(function (factory) {\n    if (typeof define === 'function' && define.amd) {\n        define([\n            \"jquery\",\n            \"jquery/ui\"\n        ], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($) {\n\n\t/*\n\t* Lets not redefine timepicker, Prevent \"Uncaught RangeError: Maximum call stack size exceeded\"\n\t*/\n\t$.ui.timepicker = $.ui.timepicker || {};\n\tif ($.ui.timepicker.version) {\n\t\treturn;\n\t}\n\n\t/*\n\t* Extend jQueryUI, get it started with our version number\n\t*/\n\t$.extend($.ui, {\n\t\ttimepicker: {\n\t\t\tversion: \"1.4.3\"\n\t\t}\n\t});\n\n\t/* \n\t* Timepicker manager.\n\t* Use the singleton instance of this class, $.timepicker, to interact with the time picker.\n\t* Settings for (groups of) time pickers are maintained in an instance object,\n\t* allowing multiple different settings on the same page.\n\t*/\n\tvar Timepicker = function () {\n\t\tthis.regional = []; // Available regional settings, indexed by language code\n\t\tthis.regional[''] = { // Default regional settings\n\t\t\tcurrentText: 'Now',\n\t\t\tcloseText: 'Done',\n\t\t\tamNames: ['AM', 'A'],\n\t\t\tpmNames: ['PM', 'P'],\n\t\t\ttimeFormat: 'HH:mm',\n\t\t\ttimeSuffix: '',\n\t\t\ttimeOnlyTitle: 'Choose Time',\n\t\t\ttimeText: 'Time',\n\t\t\thourText: 'Hour',\n\t\t\tminuteText: 'Minute',\n\t\t\tsecondText: 'Second',\n\t\t\tmillisecText: 'Millisecond',\n\t\t\tmicrosecText: 'Microsecond',\n\t\t\ttimezoneText: 'Time Zone',\n\t\t\tisRTL: false\n\t\t};\n\t\tthis._defaults = { // Global defaults for all the datetime picker instances\n\t\t\tshowButtonPanel: true,\n\t\t\ttimeOnly: false,\n\t\t\tshowHour: null,\n\t\t\tshowMinute: null,\n\t\t\tshowSecond: null,\n\t\t\tshowMillisec: null,\n\t\t\tshowMicrosec: null,\n\t\t\tshowTimezone: null,\n\t\t\tshowTime: true,\n\t\t\tstepHour: 1,\n\t\t\tstepMinute: 1,\n\t\t\tstepSecond: 1,\n\t\t\tstepMillisec: 1,\n\t\t\tstepMicrosec: 1,\n\t\t\thour: 0,\n\t\t\tminute: 0,\n\t\t\tsecond: 0,\n\t\t\tmillisec: 0,\n\t\t\tmicrosec: 0,\n\t\t\ttimezone: null,\n\t\t\thourMin: 0,\n\t\t\tminuteMin: 0,\n\t\t\tsecondMin: 0,\n\t\t\tmillisecMin: 0,\n\t\t\tmicrosecMin: 0,\n\t\t\thourMax: 23,\n\t\t\tminuteMax: 59,\n\t\t\tsecondMax: 59,\n\t\t\tmillisecMax: 999,\n\t\t\tmicrosecMax: 999,\n\t\t\tminDateTime: null,\n\t\t\tmaxDateTime: null,\n\t\t\tonSelect: null,\n\t\t\thourGrid: 0,\n\t\t\tminuteGrid: 0,\n\t\t\tsecondGrid: 0,\n\t\t\tmillisecGrid: 0,\n\t\t\tmicrosecGrid: 0,\n\t\t\talwaysSetTime: true,\n\t\t\tseparator: ' ',\n\t\t\taltFieldTimeOnly: true,\n\t\t\taltTimeFormat: null,\n\t\t\taltSeparator: null,\n\t\t\taltTimeSuffix: null,\n\t\t\tpickerTimeFormat: null,\n\t\t\tpickerTimeSuffix: null,\n\t\t\tshowTimepicker: true,\n\t\t\ttimezoneList: null,\n\t\t\taddSliderAccess: false,\n\t\t\tsliderAccessArgs: null,\n\t\t\tcontrolType: 'slider',\n\t\t\tdefaultValue: null,\n\t\t\tparse: 'strict'\n\t\t};\n\t\t$.extend(this._defaults, this.regional['']);\n\t};\n\n\t$.extend(Timepicker.prototype, {\n\t\t$input: null,\n\t\t$altInput: null,\n\t\t$timeObj: null,\n\t\tinst: null,\n\t\thour_slider: null,\n\t\tminute_slider: null,\n\t\tsecond_slider: null,\n\t\tmillisec_slider: null,\n\t\tmicrosec_slider: null,\n\t\ttimezone_select: null,\n\t\thour: 0,\n\t\tminute: 0,\n\t\tsecond: 0,\n\t\tmillisec: 0,\n\t\tmicrosec: 0,\n\t\ttimezone: null,\n\t\thourMinOriginal: null,\n\t\tminuteMinOriginal: null,\n\t\tsecondMinOriginal: null,\n\t\tmillisecMinOriginal: null,\n\t\tmicrosecMinOriginal: null,\n\t\thourMaxOriginal: null,\n\t\tminuteMaxOriginal: null,\n\t\tsecondMaxOriginal: null,\n\t\tmillisecMaxOriginal: null,\n\t\tmicrosecMaxOriginal: null,\n\t\tampm: '',\n\t\tformattedDate: '',\n\t\tformattedTime: '',\n\t\tformattedDateTime: '',\n\t\ttimezoneList: null,\n\t\tunits: ['hour', 'minute', 'second', 'millisec', 'microsec'],\n\t\tsupport: {},\n\t\tcontrol: null,\n\n\t\t/* \n\t\t* Override the default settings for all instances of the time picker.\n\t\t* @param  {Object} settings  object - the new settings to use as defaults (anonymous object)\n\t\t* @return {Object} the manager object\n\t\t*/\n\t\tsetDefaults: function (settings) {\n\t\t\textendRemove(this._defaults, settings || {});\n\t\t\treturn this;\n\t\t},\n\n\t\t/*\n\t\t* Create a new Timepicker instance\n\t\t*/\n\t\t_newInst: function ($input, opts) {\n\t\t\tvar tp_inst = new Timepicker(),\n\t\t\t\tinlineSettings = {},\n\t\t\t\tfns = {},\n\t\t\t\toverrides, i;\n\n\t\t\tfor (var attrName in this._defaults) {\n\t\t\t\tif (this._defaults.hasOwnProperty(attrName)) {\n\t\t\t\t\tvar attrValue = $input.attr('time:' + attrName);\n\t\t\t\t\tif (attrValue) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tinlineSettings[attrName] = eval(attrValue);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tinlineSettings[attrName] = attrValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toverrides = {\n\t\t\t\tbeforeShow: function (input, dp_inst) {\n\t\t\t\t\tif ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {\n\t\t\t\t\t\treturn tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonChangeMonthYear: function (year, month, dp_inst) {\n\t\t\t\t\t// Update the time as well : this prevents the time from disappearing from the $input field.\n\t\t\t\t\ttp_inst._updateDateTime(dp_inst);\n\t\t\t\t\tif ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {\n\t\t\t\t\t\ttp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonClose: function (dateText, dp_inst) {\n\t\t\t\t\tif (tp_inst.timeDefined === true && $input.val() !== '') {\n\t\t\t\t\t\ttp_inst._updateDateTime(dp_inst);\n\t\t\t\t\t}\n\t\t\t\t\tif ($.isFunction(tp_inst._defaults.evnts.onClose)) {\n\t\t\t\t\t\ttp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t\tfor (i in overrides) {\n\t\t\t\tif (overrides.hasOwnProperty(i)) {\n\t\t\t\t\tfns[i] = opts[i] || null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttp_inst._defaults = $.extend({}, this._defaults, inlineSettings, opts, overrides, {\n\t\t\t\tevnts: fns,\n\t\t\t\ttimepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');\n\t\t\t});\n\t\t\ttp_inst.amNames = $.map(tp_inst._defaults.amNames, function (val) {\n\t\t\t\treturn val.toUpperCase();\n\t\t\t});\n\t\t\ttp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function (val) {\n\t\t\t\treturn val.toUpperCase();\n\t\t\t});\n\n\t\t\t// detect which units are supported\n\t\t\ttp_inst.support = detectSupport(\n\t\t\t\t\ttp_inst._defaults.timeFormat + \n\t\t\t\t\t(tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') +\n\t\t\t\t\t(tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : ''));\n\n\t\t\t// controlType is string - key to our this._controls\n\t\t\tif (typeof(tp_inst._defaults.controlType) === 'string') {\n\t\t\t\tif (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') {\n\t\t\t\t\ttp_inst._defaults.controlType = 'select';\n\t\t\t\t}\n\t\t\t\ttp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];\n\t\t\t}\n\t\t\t// controlType is an object and must implement create, options, value methods\n\t\t\telse {\n\t\t\t\ttp_inst.control = tp_inst._defaults.controlType;\n\t\t\t}\n\n\t\t\t// prep the timezone options\n\t\t\tvar timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60,\n\t\t\t\t\t0, 60, 120, 180, 210, 240, 270, 300, 330, 345, 360, 390, 420, 480, 525, 540, 570, 600, 630, 660, 690, 720, 765, 780, 840];\n\t\t\tif (tp_inst._defaults.timezoneList !== null) {\n\t\t\t\ttimezoneList = tp_inst._defaults.timezoneList;\n\t\t\t}\n\t\t\tvar tzl = timezoneList.length, tzi = 0, tzv = null;\n\t\t\tif (tzl > 0 && typeof timezoneList[0] !== 'object') {\n\t\t\t\tfor (; tzi < tzl; tzi++) {\n\t\t\t\t\ttzv = timezoneList[tzi];\n\t\t\t\t\ttimezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) };\n\t\t\t\t}\n\t\t\t}\n\t\t\ttp_inst._defaults.timezoneList = timezoneList;\n\n\t\t\t// set the default units\n\t\t\ttp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) :\n\t\t\t\t\t\t\t((new Date()).getTimezoneOffset() * -1);\n\t\t\ttp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin :\n\t\t\t\t\t\t\ttp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour;\n\t\t\ttp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin :\n\t\t\t\t\t\t\ttp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute;\n\t\t\ttp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin :\n\t\t\t\t\t\t\ttp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second;\n\t\t\ttp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin :\n\t\t\t\t\t\t\ttp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec;\n\t\t\ttp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin :\n\t\t\t\t\t\t\ttp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec;\n\t\t\ttp_inst.ampm = '';\n\t\t\ttp_inst.$input = $input;\n\n\t\t\tif (tp_inst._defaults.altField) {\n\t\t\t\ttp_inst.$altInput = $(tp_inst._defaults.altField).css({\n\t\t\t\t\tcursor: 'pointer'\n\t\t\t\t}).focus(function () {\n\t\t\t\t\t$input.trigger(\"focus\");\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {\n\t\t\t\ttp_inst._defaults.minDate = new Date();\n\t\t\t}\n\t\t\tif (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {\n\t\t\t\ttp_inst._defaults.maxDate = new Date();\n\t\t\t}\n\n\t\t\t// datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..\n\t\t\tif (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {\n\t\t\t\ttp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());\n\t\t\t}\n\t\t\tif (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {\n\t\t\t\ttp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());\n\t\t\t}\n\t\t\tif (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {\n\t\t\t\ttp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());\n\t\t\t}\n\t\t\tif (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {\n\t\t\t\ttp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());\n\t\t\t}\n\t\t\ttp_inst.$input.bind('focus', function () {\n\t\t\t\ttp_inst._onFocus();\n\t\t\t});\n\n\t\t\treturn tp_inst;\n\t\t},\n\n\t\t/*\n\t\t* add our sliders to the calendar\n\t\t*/\n\t\t_addTimePicker: function (dp_inst) {\n\t\t\tvar currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val();\n\n\t\t\tthis.timeDefined = this._parseTime(currDT);\n\t\t\tthis._limitMinMaxDateTime(dp_inst, false);\n\t\t\tthis._injectTimePicker();\n\t\t},\n\n\t\t/*\n\t\t* parse the time string from input value or _setTime\n\t\t*/\n\t\t_parseTime: function (timeString, withDate) {\n\t\t\tif (!this.inst) {\n\t\t\t\tthis.inst = $.datepicker._getInst(this.$input[0]);\n\t\t\t}\n\n\t\t\tif (withDate || !this._defaults.timeOnly) {\n\t\t\t\tvar dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');\n\t\t\t\ttry {\n\t\t\t\t\tvar parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);\n\t\t\t\t\tif (!parseRes.timeObj) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t$.extend(this, parseRes.timeObj);\n\t\t\t\t} catch (err) {\n\t\t\t\t\t$.timepicker.log(\"Error parsing the date/time string: \" + err +\n\t\t\t\t\t\t\t\t\t\"\\ndate/time string = \" + timeString +\n\t\t\t\t\t\t\t\t\t\"\\ntimeFormat = \" + this._defaults.timeFormat +\n\t\t\t\t\t\t\t\t\t\"\\ndateFormat = \" + dp_dateFormat);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\tvar timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);\n\t\t\t\tif (!timeObj) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t$.extend(this, timeObj);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t},\n\n\t\t/*\n\t\t* generate and inject html for timepicker into ui datepicker\n\t\t*/\n\t\t_injectTimePicker: function () {\n\t\t\tvar $dp = this.inst.dpDiv,\n\t\t\t\to = this.inst.settings,\n\t\t\t\ttp_inst = this,\n\t\t\t\tlitem = '',\n\t\t\t\tuitem = '',\n\t\t\t\tshow = null,\n\t\t\t\tmax = {},\n\t\t\t\tgridSize = {},\n\t\t\t\tsize = null,\n\t\t\t\ti = 0,\n\t\t\t\tl = 0;\n\n\t\t\t// Prevent displaying twice\n\t\t\tif ($dp.find(\"div.ui-timepicker-div\").length === 0 && o.showTimepicker) {\n\t\t\t\tvar noDisplay = ' style=\"display:none;\"',\n\t\t\t\t\thtml = '<div class=\"ui-timepicker-div' + (o.isRTL ? ' ui-timepicker-rtl' : '') + '\"><dl>' + '<dt class=\"ui_tpicker_time_label\"' + ((o.showTime) ? '' : noDisplay) + '>' + o.timeText + '</dt>' +\n\t\t\t\t\t\t\t\t'<dd class=\"ui_tpicker_time\"' + ((o.showTime) ? '' : noDisplay) + '></dd>';\n\n\t\t\t\t// Create the markup\n\t\t\t\tfor (i = 0, l = this.units.length; i < l; i++) {\n\t\t\t\t\tlitem = this.units[i];\n\t\t\t\t\tuitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);\n\t\t\t\t\tshow = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];\n\n\t\t\t\t\t// Added by Peter Medeiros:\n\t\t\t\t\t// - Figure out what the hour/minute/second max should be based on the step values.\n\t\t\t\t\t// - Example: if stepMinute is 15, then minMax is 45.\n\t\t\t\t\tmax[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10);\n\t\t\t\t\tgridSize[litem] = 0;\n\n\t\t\t\t\thtml += '<dt class=\"ui_tpicker_' + litem + '_label\"' + (show ? '' : noDisplay) + '>' + o[litem + 'Text'] + '</dt>' +\n\t\t\t\t\t\t\t\t'<dd class=\"ui_tpicker_' + litem + '\"><div class=\"ui_tpicker_' + litem + '_slider\"' + (show ? '' : noDisplay) + '></div>';\n\n\t\t\t\t\tif (show && o[litem + 'Grid'] > 0) {\n\t\t\t\t\t\thtml += '<div style=\"padding-left: 1px\"><table class=\"ui-tpicker-grid-label\"><tr>';\n\n\t\t\t\t\t\tif (litem === 'hour') {\n\t\t\t\t\t\t\tfor (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) {\n\t\t\t\t\t\t\t\tgridSize[litem]++;\n\t\t\t\t\t\t\t\tvar tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o);\n\t\t\t\t\t\t\t\thtml += '<td data-for=\"' + litem + '\">' + tmph + '</td>';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tfor (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) {\n\t\t\t\t\t\t\t\tgridSize[litem]++;\n\t\t\t\t\t\t\t\thtml += '<td data-for=\"' + litem + '\">' + ((m < 10) ? '0' : '') + m + '</td>';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\thtml += '</tr></table></div>';\n\t\t\t\t\t}\n\t\t\t\t\thtml += '</dd>';\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Timezone\n\t\t\t\tvar showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone;\n\t\t\t\thtml += '<dt class=\"ui_tpicker_timezone_label\"' + (showTz ? '' : noDisplay) + '>' + o.timezoneText + '</dt>';\n\t\t\t\thtml += '<dd class=\"ui_tpicker_timezone\" ' + (showTz ? '' : noDisplay) + '></dd>';\n\n\t\t\t\t// Create the elements from string\n\t\t\t\thtml += '</dl></div>';\n\t\t\t\tvar $tp = $(html);\n\n\t\t\t\t// if we only want time picker...\n\t\t\t\tif (o.timeOnly === true) {\n\t\t\t\t\t$tp.prepend('<div class=\"ui-widget-header ui-helper-clearfix ui-corner-all\">' + '<div class=\"ui-datepicker-title\">' + o.timeOnlyTitle + '</div>' + '</div>');\n\t\t\t\t\t$dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// add sliders, adjust grids, add events\n\t\t\t\tfor (i = 0, l = tp_inst.units.length; i < l; i++) {\n\t\t\t\t\tlitem = tp_inst.units[i];\n\t\t\t\t\tuitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);\n\t\t\t\t\tshow = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];\n\n\t\t\t\t\t// add the slider\n\t\t\t\t\ttp_inst[litem + '_slider'] = tp_inst.control.create(tp_inst, $tp.find('.ui_tpicker_' + litem + '_slider'), litem, tp_inst[litem], o[litem + 'Min'], max[litem], o['step' + uitem]);\n\n\t\t\t\t\t// adjust the grid and add click event\n\t\t\t\t\tif (show && o[litem + 'Grid'] > 0) {\n\t\t\t\t\t\tsize = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']);\n\t\t\t\t\t\t$tp.find('.ui_tpicker_' + litem + ' table').css({\n\t\t\t\t\t\t\twidth: size + \"%\",\n\t\t\t\t\t\t\tmarginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + \"%\"),\n\t\t\t\t\t\t\tmarginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + \"%\") : '0',\n\t\t\t\t\t\t\tborderCollapse: 'collapse'\n\t\t\t\t\t\t}).find(\"td\").click(function (e) {\n\t\t\t\t\t\t\t\tvar $t = $(this),\n\t\t\t\t\t\t\t\t\th = $t.html(),\n\t\t\t\t\t\t\t\t\tn = parseInt(h.replace(/[^0-9]/g), 10),\n\t\t\t\t\t\t\t\t\tap = h.replace(/[^apm]/ig),\n\t\t\t\t\t\t\t\t\tf = $t.data('for'); // loses scope, so we use data-for\n\n\t\t\t\t\t\t\t\tif (f === 'hour') {\n\t\t\t\t\t\t\t\t\tif (ap.indexOf('p') !== -1 && n < 12) {\n\t\t\t\t\t\t\t\t\t\tn += 12;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tif (ap.indexOf('a') !== -1 && n === 12) {\n\t\t\t\t\t\t\t\t\t\t\tn = 0;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\ttp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n);\n\n\t\t\t\t\t\t\t\ttp_inst._onTimeChange();\n\t\t\t\t\t\t\t\ttp_inst._onSelectHandler();\n\t\t\t\t\t\t\t}).css({\n\t\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t\t\twidth: (100 / gridSize[litem]) + '%',\n\t\t\t\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t\t\t\t\toverflow: 'hidden'\n\t\t\t\t\t\t\t});\n\t\t\t\t\t} // end if grid > 0\n\t\t\t\t} // end for loop\n\n\t\t\t\t// Add timezone options\n\t\t\t\tthis.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find(\"select\");\n\t\t\t\t$.fn.append.apply(this.timezone_select,\n\t\t\t\t$.map(o.timezoneList, function (val, idx) {\n\t\t\t\t\treturn $(\"<option />\").val(typeof val === \"object\" ? val.value : val).text(typeof val === \"object\" ? val.label : val);\n\t\t\t\t}));\n\t\t\t\tif (typeof(this.timezone) !== \"undefined\" && this.timezone !== null && this.timezone !== \"\") {\n\t\t\t\t\tvar local_timezone = (new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12)).getTimezoneOffset() * -1;\n\t\t\t\t\tif (local_timezone === this.timezone) {\n\t\t\t\t\t\tselectLocalTimezone(tp_inst);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.timezone_select.val(this.timezone);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (typeof(this.hour) !== \"undefined\" && this.hour !== null && this.hour !== \"\") {\n\t\t\t\t\t\tthis.timezone_select.val(o.timezone);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselectLocalTimezone(tp_inst);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.timezone_select.change(function () {\n\t\t\t\t\ttp_inst._onTimeChange();\n\t\t\t\t\ttp_inst._onSelectHandler();\n\t\t\t\t});\n\t\t\t\t// End timezone options\n\t\t\t\t\n\t\t\t\t// inject timepicker into datepicker\n\t\t\t\tvar $buttonPanel = $dp.find('.ui-datepicker-buttonpane');\n\t\t\t\tif ($buttonPanel.length) {\n\t\t\t\t\t$buttonPanel.before($tp);\n\t\t\t\t} else {\n\t\t\t\t\t$dp.append($tp);\n\t\t\t\t}\n\n\t\t\t\tthis.$timeObj = $tp.find('.ui_tpicker_time');\n\n\t\t\t\tif (this.inst !== null) {\n\t\t\t\t\tvar timeDefined = this.timeDefined;\n\t\t\t\t\tthis._onTimeChange();\n\t\t\t\t\tthis.timeDefined = timeDefined;\n\t\t\t\t}\n\n\t\t\t\t// slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/\n\t\t\t\tif (this._defaults.addSliderAccess) {\n\t\t\t\t\tvar sliderAccessArgs = this._defaults.sliderAccessArgs,\n\t\t\t\t\t\trtl = this._defaults.isRTL;\n\t\t\t\t\tsliderAccessArgs.isRTL = rtl;\n\t\t\t\t\t\t\n\t\t\t\t\tsetTimeout(function () { // fix for inline mode\n\t\t\t\t\t\tif ($tp.find('.ui-slider-access').length === 0) {\n\t\t\t\t\t\t\t$tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);\n\n\t\t\t\t\t\t\t// fix any grids since sliders are shorter\n\t\t\t\t\t\t\tvar sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);\n\t\t\t\t\t\t\tif (sliderAccessWidth) {\n\t\t\t\t\t\t\t\t$tp.find('table:visible').each(function () {\n\t\t\t\t\t\t\t\t\tvar $g = $(this),\n\t\t\t\t\t\t\t\t\t\toldWidth = $g.outerWidth(),\n\t\t\t\t\t\t\t\t\t\toldMarginLeft = $g.css(rtl ? 'marginRight' : 'marginLeft').toString().replace('%', ''),\n\t\t\t\t\t\t\t\t\t\tnewWidth = oldWidth - sliderAccessWidth,\n\t\t\t\t\t\t\t\t\t\tnewMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',\n\t\t\t\t\t\t\t\t\t\tcss = { width: newWidth, marginRight: 0, marginLeft: 0 };\n\t\t\t\t\t\t\t\t\tcss[rtl ? 'marginRight' : 'marginLeft'] = newMarginLeft;\n\t\t\t\t\t\t\t\t\t$g.css(css);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 10);\n\t\t\t\t}\n\t\t\t\t// end slideAccess integration\n\n\t\t\t\ttp_inst._limitMinMaxDateTime(this.inst, true);\n\t\t\t}\n\t\t},\n\n\t\t/*\n\t\t* This function tries to limit the ability to go outside the\n\t\t* min/max date range\n\t\t*/\n\t\t_limitMinMaxDateTime: function (dp_inst, adjustSliders) {\n\t\t\tvar o = this._defaults,\n\t\t\t\tdp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);\n\n\t\t\tif (!this._defaults.showTimepicker) {\n\t\t\t\treturn;\n\t\t\t} // No time so nothing to check here\n\n\t\t\tif ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {\n\t\t\t\tvar minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),\n\t\t\t\t\tminDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);\n\n\t\t\t\tif (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null || this.microsecMinOriginal === null) {\n\t\t\t\t\tthis.hourMinOriginal = o.hourMin;\n\t\t\t\t\tthis.minuteMinOriginal = o.minuteMin;\n\t\t\t\t\tthis.secondMinOriginal = o.secondMin;\n\t\t\t\t\tthis.millisecMinOriginal = o.millisecMin;\n\t\t\t\t\tthis.microsecMinOriginal = o.microsecMin;\n\t\t\t\t}\n\n\t\t\t\tif (dp_inst.settings.timeOnly || minDateTimeDate.getTime() === dp_date.getTime()) {\n\t\t\t\t\tthis._defaults.hourMin = minDateTime.getHours();\n\t\t\t\t\tif (this.hour <= this._defaults.hourMin) {\n\t\t\t\t\t\tthis.hour = this._defaults.hourMin;\n\t\t\t\t\t\tthis._defaults.minuteMin = minDateTime.getMinutes();\n\t\t\t\t\t\tif (this.minute <= this._defaults.minuteMin) {\n\t\t\t\t\t\t\tthis.minute = this._defaults.minuteMin;\n\t\t\t\t\t\t\tthis._defaults.secondMin = minDateTime.getSeconds();\n\t\t\t\t\t\t\tif (this.second <= this._defaults.secondMin) {\n\t\t\t\t\t\t\t\tthis.second = this._defaults.secondMin;\n\t\t\t\t\t\t\t\tthis._defaults.millisecMin = minDateTime.getMilliseconds();\n\t\t\t\t\t\t\t\tif (this.millisec <= this._defaults.millisecMin) {\n\t\t\t\t\t\t\t\t\tthis.millisec = this._defaults.millisecMin;\n\t\t\t\t\t\t\t\t\tthis._defaults.microsecMin = minDateTime.getMicroseconds();\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif (this.microsec < this._defaults.microsecMin) {\n\t\t\t\t\t\t\t\t\t\tthis.microsec = this._defaults.microsecMin;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tthis._defaults.microsecMin = this.microsecMinOriginal;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis._defaults.millisecMin = this.millisecMinOriginal;\n\t\t\t\t\t\t\t\tthis._defaults.microsecMin = this.microsecMinOriginal;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis._defaults.secondMin = this.secondMinOriginal;\n\t\t\t\t\t\t\tthis._defaults.millisecMin = this.millisecMinOriginal;\n\t\t\t\t\t\t\tthis._defaults.microsecMin = this.microsecMinOriginal;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._defaults.minuteMin = this.minuteMinOriginal;\n\t\t\t\t\t\tthis._defaults.secondMin = this.secondMinOriginal;\n\t\t\t\t\t\tthis._defaults.millisecMin = this.millisecMinOriginal;\n\t\t\t\t\t\tthis._defaults.microsecMin = this.microsecMinOriginal;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis._defaults.hourMin = this.hourMinOriginal;\n\t\t\t\t\tthis._defaults.minuteMin = this.minuteMinOriginal;\n\t\t\t\t\tthis._defaults.secondMin = this.secondMinOriginal;\n\t\t\t\t\tthis._defaults.millisecMin = this.millisecMinOriginal;\n\t\t\t\t\tthis._defaults.microsecMin = this.microsecMinOriginal;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {\n\t\t\t\tvar maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),\n\t\t\t\t\tmaxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);\n\n\t\t\t\tif (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null || this.millisecMaxOriginal === null) {\n\t\t\t\t\tthis.hourMaxOriginal = o.hourMax;\n\t\t\t\t\tthis.minuteMaxOriginal = o.minuteMax;\n\t\t\t\t\tthis.secondMaxOriginal = o.secondMax;\n\t\t\t\t\tthis.millisecMaxOriginal = o.millisecMax;\n\t\t\t\t\tthis.microsecMaxOriginal = o.microsecMax;\n\t\t\t\t}\n\n\t\t\t\tif (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() === dp_date.getTime()) {\n\t\t\t\t\tthis._defaults.hourMax = maxDateTime.getHours();\n\t\t\t\t\tif (this.hour >= this._defaults.hourMax) {\n\t\t\t\t\t\tthis.hour = this._defaults.hourMax;\n\t\t\t\t\t\tthis._defaults.minuteMax = maxDateTime.getMinutes();\n\t\t\t\t\t\tif (this.minute >= this._defaults.minuteMax) {\n\t\t\t\t\t\t\tthis.minute = this._defaults.minuteMax;\n\t\t\t\t\t\t\tthis._defaults.secondMax = maxDateTime.getSeconds();\n\t\t\t\t\t\t\tif (this.second >= this._defaults.secondMax) {\n\t\t\t\t\t\t\t\tthis.second = this._defaults.secondMax;\n\t\t\t\t\t\t\t\tthis._defaults.millisecMax = maxDateTime.getMilliseconds();\n\t\t\t\t\t\t\t\tif (this.millisec >= this._defaults.millisecMax) {\n\t\t\t\t\t\t\t\t\tthis.millisec = this._defaults.millisecMax;\n\t\t\t\t\t\t\t\t\tthis._defaults.microsecMax = maxDateTime.getMicroseconds();\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif (this.microsec > this._defaults.microsecMax) {\n\t\t\t\t\t\t\t\t\t\tthis.microsec = this._defaults.microsecMax;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tthis._defaults.microsecMax = this.microsecMaxOriginal;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis._defaults.millisecMax = this.millisecMaxOriginal;\n\t\t\t\t\t\t\t\tthis._defaults.microsecMax = this.microsecMaxOriginal;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis._defaults.secondMax = this.secondMaxOriginal;\n\t\t\t\t\t\t\tthis._defaults.millisecMax = this.millisecMaxOriginal;\n\t\t\t\t\t\t\tthis._defaults.microsecMax = this.microsecMaxOriginal;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._defaults.minuteMax = this.minuteMaxOriginal;\n\t\t\t\t\t\tthis._defaults.secondMax = this.secondMaxOriginal;\n\t\t\t\t\t\tthis._defaults.millisecMax = this.millisecMaxOriginal;\n\t\t\t\t\t\tthis._defaults.microsecMax = this.microsecMaxOriginal;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis._defaults.hourMax = this.hourMaxOriginal;\n\t\t\t\t\tthis._defaults.minuteMax = this.minuteMaxOriginal;\n\t\t\t\t\tthis._defaults.secondMax = this.secondMaxOriginal;\n\t\t\t\t\tthis._defaults.millisecMax = this.millisecMaxOriginal;\n\t\t\t\t\tthis._defaults.microsecMax = this.microsecMaxOriginal;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (adjustSliders !== undefined && adjustSliders === true) {\n\t\t\t\tvar hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),\n\t\t\t\t\tminMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),\n\t\t\t\t\tsecMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),\n\t\t\t\t\tmillisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10),\n\t\t\t\t\tmicrosecMax = parseInt((this._defaults.microsecMax - ((this._defaults.microsecMax - this._defaults.microsecMin) % this._defaults.stepMicrosec)), 10);\n\n\t\t\t\tif (this.hour_slider) {\n\t\t\t\t\tthis.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax });\n\t\t\t\t\tthis.control.value(this, this.hour_slider, 'hour', this.hour - (this.hour % this._defaults.stepHour));\n\t\t\t\t}\n\t\t\t\tif (this.minute_slider) {\n\t\t\t\t\tthis.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax });\n\t\t\t\t\tthis.control.value(this, this.minute_slider, 'minute', this.minute - (this.minute % this._defaults.stepMinute));\n\t\t\t\t}\n\t\t\t\tif (this.second_slider) {\n\t\t\t\t\tthis.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax });\n\t\t\t\t\tthis.control.value(this, this.second_slider, 'second', this.second - (this.second % this._defaults.stepSecond));\n\t\t\t\t}\n\t\t\t\tif (this.millisec_slider) {\n\t\t\t\t\tthis.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax });\n\t\t\t\t\tthis.control.value(this, this.millisec_slider, 'millisec', this.millisec - (this.millisec % this._defaults.stepMillisec));\n\t\t\t\t}\n\t\t\t\tif (this.microsec_slider) {\n\t\t\t\t\tthis.control.options(this, this.microsec_slider, 'microsec', { min: this._defaults.microsecMin, max: microsecMax });\n\t\t\t\t\tthis.control.value(this, this.microsec_slider, 'microsec', this.microsec - (this.microsec % this._defaults.stepMicrosec));\n\t\t\t\t}\n\t\t\t}\n\n\t\t},\n\n\t\t/*\n\t\t* when a slider moves, set the internal time...\n\t\t* on time change is also called when the time is updated in the text field\n\t\t*/\n\t\t_onTimeChange: function () {\n\t\t\tif (!this._defaults.showTimepicker) {\n                                return;\n\t\t\t}\n\t\t\tvar hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,\n\t\t\t\tminute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,\n\t\t\t\tsecond = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,\n\t\t\t\tmillisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,\n\t\t\t\tmicrosec = (this.microsec_slider) ? this.control.value(this, this.microsec_slider, 'microsec') : false,\n\t\t\t\ttimezone = (this.timezone_select) ? this.timezone_select.val() : false,\n\t\t\t\to = this._defaults,\n\t\t\t\tpickerTimeFormat = o.pickerTimeFormat || o.timeFormat,\n\t\t\t\tpickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;\n\n\t\t\tif (typeof(hour) === 'object') {\n\t\t\t\thour = false;\n\t\t\t}\n\t\t\tif (typeof(minute) === 'object') {\n\t\t\t\tminute = false;\n\t\t\t}\n\t\t\tif (typeof(second) === 'object') {\n\t\t\t\tsecond = false;\n\t\t\t}\n\t\t\tif (typeof(millisec) === 'object') {\n\t\t\t\tmillisec = false;\n\t\t\t}\n\t\t\tif (typeof(microsec) === 'object') {\n\t\t\t\tmicrosec = false;\n\t\t\t}\n\t\t\tif (typeof(timezone) === 'object') {\n\t\t\t\ttimezone = false;\n\t\t\t}\n\n\t\t\tif (hour !== false) {\n\t\t\t\thour = parseInt(hour, 10);\n\t\t\t}\n\t\t\tif (minute !== false) {\n\t\t\t\tminute = parseInt(minute, 10);\n\t\t\t}\n\t\t\tif (second !== false) {\n\t\t\t\tsecond = parseInt(second, 10);\n\t\t\t}\n\t\t\tif (millisec !== false) {\n\t\t\t\tmillisec = parseInt(millisec, 10);\n\t\t\t}\n\t\t\tif (microsec !== false) {\n\t\t\t\tmicrosec = parseInt(microsec, 10);\n\t\t\t}\n\t\t\tif (timezone !== false) {\n\t\t\t\ttimezone = timezone.toString();\n\t\t\t}\n\n\t\t\tvar ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];\n\n\t\t\t// If the update was done in the input field, the input field should not be updated.\n\t\t\t// If the update was done using the sliders, update the input field.\n\t\t\tvar hasChanged = (\n\t\t\t\t\t\thour !== parseInt(this.hour,10) || // sliders should all be numeric\n\t\t\t\t\t\tminute !== parseInt(this.minute,10) || \n\t\t\t\t\t\tsecond !== parseInt(this.second,10) || \n\t\t\t\t\t\tmillisec !== parseInt(this.millisec,10) || \n\t\t\t\t\t\tmicrosec !== parseInt(this.microsec,10) || \n\t\t\t\t\t\t(this.ampm.length > 0 && (hour < 12) !== ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) || \n\t\t\t\t\t\t(this.timezone !== null && timezone !== this.timezone.toString()) // could be numeric or \"EST\" format, so use toString()\n\t\t\t\t\t);\n\n\t\t\tif (hasChanged) {\n\n\t\t\t\tif (hour !== false) {\n\t\t\t\t\tthis.hour = hour;\n\t\t\t\t}\n\t\t\t\tif (minute !== false) {\n\t\t\t\t\tthis.minute = minute;\n\t\t\t\t}\n\t\t\t\tif (second !== false) {\n\t\t\t\t\tthis.second = second;\n\t\t\t\t}\n\t\t\t\tif (millisec !== false) {\n\t\t\t\t\tthis.millisec = millisec;\n\t\t\t\t}\n\t\t\t\tif (microsec !== false) {\n\t\t\t\t\tthis.microsec = microsec;\n\t\t\t\t}\n\t\t\t\tif (timezone !== false) {\n\t\t\t\t\tthis.timezone = timezone;\n\t\t\t\t}\n\n\t\t\t\tif (!this.inst) {\n\t\t\t\t\tthis.inst = $.datepicker._getInst(this.$input[0]);\n\t\t\t\t}\n\n\t\t\t\tthis._limitMinMaxDateTime(this.inst, true);\n\t\t\t}\n\t\t\tif (this.support.ampm) {\n\t\t\t\tthis.ampm = ampm;\n\t\t\t}\n\n\t\t\t// Updates the time within the timepicker\n\t\t\tthis.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);\n\t\t\tif (this.$timeObj) {\n\t\t\t\tif (pickerTimeFormat === o.timeFormat) {\n\t\t\t\t\tthis.$timeObj.text(this.formattedTime + pickerTimeSuffix);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.$timeObj.text($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.timeDefined = true;\n\t\t\tif (hasChanged) {\n\t\t\t\tthis._updateDateTime();\n\t\t\t\tthis.$input.focus();\n\t\t\t}\n\t\t},\n\n\t\t/*\n\t\t* call custom onSelect.\n\t\t* bind to sliders slidestop, and grid click.\n\t\t*/\n\t\t_onSelectHandler: function () {\n\t\t\tvar onSelect = this._defaults.onSelect || this.inst.settings.onSelect;\n\t\t\tvar inputEl = this.$input ? this.$input[0] : null;\n\t\t\tif (onSelect && inputEl) {\n\t\t\t\tonSelect.apply(inputEl, [this.formattedDateTime, this]);\n\t\t\t}\n\t\t},\n\n\t\t/*\n\t\t* update our input with the new date time..\n\t\t*/\n\t\t_updateDateTime: function (dp_inst) {\n\t\t\tdp_inst = this.inst || dp_inst;\n\t\t\tvar dtTmp = (dp_inst.currentYear > 0? \n\t\t\t\t\t\t\tnew Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay) : \n\t\t\t\t\t\t\tnew Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),\n\t\t\t\tdt = $.datepicker._daylightSavingAdjust(dtTmp),\n\t\t\t\t//dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),\n\t\t\t\t//dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay)),\n\t\t\t\tdateFmt = $.datepicker._get(dp_inst, 'dateFormat'),\n\t\t\t\tformatCfg = $.datepicker._getFormatConfig(dp_inst),\n\t\t\t\ttimeAvailable = dt !== null && this.timeDefined;\n\t\t\tthis.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);\n\t\t\tvar formattedDateTime = this.formattedDate;\n\t\t\t\n\t\t\t// if a slider was changed but datepicker doesn't have a value yet, set it\n\t\t\tif (dp_inst.lastVal === \"\") {\n                dp_inst.currentYear = dp_inst.selectedYear;\n                dp_inst.currentMonth = dp_inst.selectedMonth;\n                dp_inst.currentDay = dp_inst.selectedDay;\n            }\n\n\t\t\t/*\n\t\t\t* remove following lines to force every changes in date picker to change the input value\n\t\t\t* Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker. \n\t\t\t* If the user manually empty the value in the input field, the date picker will never change selected value.\n\t\t\t*/\n\t\t\t//if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {\n\t\t\t//\treturn;\n\t\t\t//}\n\n\t\t\tif (this._defaults.timeOnly === true) {\n\t\t\t\tformattedDateTime = this.formattedTime;\n\t\t\t} else if (this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) {\n\t\t\t\tformattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;\n\t\t\t}\n\n\t\t\tthis.formattedDateTime = formattedDateTime;\n\n\t\t\tif (!this._defaults.showTimepicker) {\n\t\t\t\tthis.$input.val(this.formattedDate);\n\t\t\t} else if (this.$altInput && this._defaults.timeOnly === false && this._defaults.altFieldTimeOnly === true) {\n\t\t\t\tthis.$altInput.val(this.formattedTime);\n\t\t\t\tthis.$input.val(this.formattedDate);\n\t\t\t} else if (this.$altInput) {\n\t\t\t\tthis.$input.val(formattedDateTime);\n\t\t\t\tvar altFormattedDateTime = '',\n\t\t\t\t\taltSeparator = this._defaults.altSeparator ? this._defaults.altSeparator : this._defaults.separator,\n\t\t\t\t\taltTimeSuffix = this._defaults.altTimeSuffix ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;\n\t\t\t\t\n\t\t\t\tif (!this._defaults.timeOnly) {\n\t\t\t\t\tif (this._defaults.altFormat) {\n\t\t\t\t\t\taltFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\taltFormattedDateTime = this.formattedDate;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (altFormattedDateTime) {\n\t\t\t\t\t\taltFormattedDateTime += altSeparator;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (this._defaults.altTimeFormat) {\n\t\t\t\t\taltFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\taltFormattedDateTime += this.formattedTime + altTimeSuffix;\n\t\t\t\t}\n\t\t\t\tthis.$altInput.val(altFormattedDateTime);\n\t\t\t} else {\n\t\t\t\tthis.$input.val(formattedDateTime);\n\t\t\t}\n\n\t\t\tthis.$input.trigger(\"change\");\n\t\t},\n\n\t\t_onFocus: function () {\n\t\t\tif (!this.$input.val() && this._defaults.defaultValue) {\n\t\t\t\tthis.$input.val(this._defaults.defaultValue);\n\t\t\t\tvar inst = $.datepicker._getInst(this.$input.get(0)),\n\t\t\t\t\ttp_inst = $.datepicker._get(inst, 'timepicker');\n\t\t\t\tif (tp_inst) {\n\t\t\t\t\tif (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t$.datepicker._updateDatepicker(inst);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t$.timepicker.log(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/*\n\t\t* Small abstraction to control types\n\t\t* We can add more, just be sure to follow the pattern: create, options, value\n\t\t*/\n\t\t_controls: {\n\t\t\t// slider methods\n\t\t\tslider: {\n\t\t\t\tcreate: function (tp_inst, obj, unit, val, min, max, step) {\n\t\t\t\t\tvar rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60\n\t\t\t\t\treturn obj.prop('slide', null).slider({\n\t\t\t\t\t\torientation: \"horizontal\",\n\t\t\t\t\t\tvalue: rtl ? val * -1 : val,\n\t\t\t\t\t\tmin: rtl ? max * -1 : min,\n\t\t\t\t\t\tmax: rtl ? min * -1 : max,\n\t\t\t\t\t\tstep: step,\n\t\t\t\t\t\tslide: function (event, ui) {\n\t\t\t\t\t\t\ttp_inst.control.value(tp_inst, $(this), unit, rtl ? ui.value * -1 : ui.value);\n\t\t\t\t\t\t\ttp_inst._onTimeChange();\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstop: function (event, ui) {\n\t\t\t\t\t\t\ttp_inst._onSelectHandler();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\t\n\t\t\t\t},\n\t\t\t\toptions: function (tp_inst, obj, unit, opts, val) {\n\t\t\t\t\tif (tp_inst._defaults.isRTL) {\n\t\t\t\t\t\tif (typeof(opts) === 'string') {\n\t\t\t\t\t\t\tif (opts === 'min' || opts === 'max') {\n\t\t\t\t\t\t\t\tif (val !== undefined) {\n\t\t\t\t\t\t\t\t\treturn obj.slider(opts, val * -1);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn Math.abs(obj.slider(opts));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn obj.slider(opts);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar min = opts.min, \n\t\t\t\t\t\t\tmax = opts.max;\n\t\t\t\t\t\topts.min = opts.max = null;\n\t\t\t\t\t\tif (min !== undefined) {\n\t\t\t\t\t\t\topts.max = min * -1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (max !== undefined) {\n\t\t\t\t\t\t\topts.min = max * -1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn obj.slider(opts);\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof(opts) === 'string' && val !== undefined) {\n\t\t\t\t\t\treturn obj.slider(opts, val);\n\t\t\t\t\t}\n\t\t\t\t\treturn obj.slider(opts);\n\t\t\t\t},\n\t\t\t\tvalue: function (tp_inst, obj, unit, val) {\n\t\t\t\t\tif (tp_inst._defaults.isRTL) {\n\t\t\t\t\t\tif (val !== undefined) {\n\t\t\t\t\t\t\treturn obj.slider('value', val * -1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn Math.abs(obj.slider('value'));\n\t\t\t\t\t}\n\t\t\t\t\tif (val !== undefined) {\n\t\t\t\t\t\treturn obj.slider('value', val);\n\t\t\t\t\t}\n\t\t\t\t\treturn obj.slider('value');\n\t\t\t\t}\n\t\t\t},\n\t\t\t// select methods\n\t\t\tselect: {\n\t\t\t\tcreate: function (tp_inst, obj, unit, val, min, max, step) {\n\t\t\t\t\tvar sel = '<select class=\"ui-timepicker-select\" data-unit=\"' + unit + '\" data-min=\"' + min + '\" data-max=\"' + max + '\" data-step=\"' + step + '\">',\n\t\t\t\t\t\tformat = tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat;\n\n\t\t\t\t\tfor (var i = min; i <= max; i += step) {\n\t\t\t\t\t\tsel += '<option value=\"' + i + '\"' + (i === val ? ' selected' : '') + '>';\n\t\t\t\t\t\tif (unit === 'hour') {\n\t\t\t\t\t\t\tsel += $.datepicker.formatTime($.trim(format.replace(/[^ht ]/ig, '')), {hour: i}, tp_inst._defaults);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (unit === 'millisec' || unit === 'microsec' || i >= 10) { sel += i; }\n\t\t\t\t\t\telse {sel += '0' + i.toString(); }\n\t\t\t\t\t\tsel += '</option>';\n\t\t\t\t\t}\n\t\t\t\t\tsel += '</select>';\n\n\t\t\t\t\tobj.children('select').remove();\n\n\t\t\t\t\t$(sel).appendTo(obj).change(function (e) {\n\t\t\t\t\t\ttp_inst._onTimeChange();\n\t\t\t\t\t\ttp_inst._onSelectHandler();\n\t\t\t\t\t});\n\n\t\t\t\t\treturn obj;\n\t\t\t\t},\n\t\t\t\toptions: function (tp_inst, obj, unit, opts, val) {\n\t\t\t\t\tvar o = {},\n\t\t\t\t\t\t$t = obj.children('select');\n\t\t\t\t\tif (typeof(opts) === 'string') {\n\t\t\t\t\t\tif (val === undefined) {\n\t\t\t\t\t\t\treturn $t.data(opts);\n\t\t\t\t\t\t}\n\t\t\t\t\t\to[opts] = val;\t\n\t\t\t\t\t}\n\t\t\t\t\telse { o = opts; }\n\t\t\t\t\treturn tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min || $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step'));\n\t\t\t\t},\n\t\t\t\tvalue: function (tp_inst, obj, unit, val) {\n\t\t\t\t\tvar $t = obj.children('select');\n\t\t\t\t\tif (val !== undefined) {\n\t\t\t\t\t\treturn $t.val(val);\n\t\t\t\t\t}\n\t\t\t\t\treturn $t.val();\n\t\t\t\t}\n\t\t\t}\n\t\t} // end _controls\n\n\t});\n\n\t$.fn.extend({\n\t\t/*\n\t\t* shorthand just to use timepicker.\n\t\t*/\n\t\ttimepicker: function (o) {\n\t\t\to = o || {};\n\t\t\tvar tmp_args = Array.prototype.slice.call(arguments);\n\n\t\t\tif (typeof o === 'object') {\n\t\t\t\ttmp_args[0] = $.extend(o, {\n\t\t\t\t\ttimeOnly: true\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn $(this).each(function () {\n\t\t\t\t$.fn.datetimepicker.apply($(this), tmp_args);\n\t\t\t});\n\t\t},\n\n\t\t/*\n\t\t* extend timepicker to datepicker\n\t\t*/\n\t\tdatetimepicker: function (o) {\n\t\t\to = o || {};\n\t\t\tvar tmp_args = arguments;\n\n\t\t\tif (typeof(o) === 'string') {\n\t\t\t\tif (o === 'getDate') {\n\t\t\t\t\treturn $.fn.datepicker.apply($(this[0]), tmp_args);\n\t\t\t\t} else {\n\t\t\t\t\treturn this.each(function () {\n\t\t\t\t\t\tvar $t = $(this);\n\t\t\t\t\t\t$t.datepicker.apply($t, tmp_args);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn this.each(function () {\n\t\t\t\t\tvar $t = $(this);\n\t\t\t\t\t$t.datepicker($.timepicker._newInst($t, o)._defaults);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\n\t/*\n\t* Public Utility to parse date and time\n\t*/\n\t$.datepicker.parseDateTime = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {\n\t\tvar parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);\n\t\tif (parseRes.timeObj) {\n\t\t\tvar t = parseRes.timeObj;\n\t\t\tparseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);\n\t\t\tparseRes.date.setMicroseconds(t.microsec);\n\t\t}\n\n\t\treturn parseRes.date;\n\t};\n\n\t/*\n\t* Public utility to parse time\n\t*/\n\t$.datepicker.parseTime = function (timeFormat, timeString, options) {\n\t\tvar o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}),\n\t\t\tiso8601 = (timeFormat.replace(/\\'.*?\\'/g, '').indexOf('Z') !== -1);\n\n\t\t// Strict parse requires the timeString to match the timeFormat exactly\n\t\tvar strictParse = function (f, s, o) {\n\n\t\t\t// pattern for standard and localized AM/PM markers\n\t\t\tvar getPatternAmpm = function (amNames, pmNames) {\n\t\t\t\tvar markers = [];\n\t\t\t\tif (amNames) {\n\t\t\t\t\t$.merge(markers, amNames);\n\t\t\t\t}\n\t\t\t\tif (pmNames) {\n\t\t\t\t\t$.merge(markers, pmNames);\n\t\t\t\t}\n\t\t\t\tmarkers = $.map(markers, function (val) {\n\t\t\t\t\treturn val.replace(/[.*+?|()\\[\\]{}\\\\]/g, '\\\\$&');\n\t\t\t\t});\n\t\t\t\treturn '(' + markers.join('|') + ')?';\n\t\t\t};\n\n\t\t\t// figure out position of time elements.. cause js cant do named captures\n\t\t\tvar getFormatPositions = function (timeFormat) {\n\t\t\t\tvar finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),\n\t\t\t\t\torders = {\n\t\t\t\t\t\th: -1,\n\t\t\t\t\t\tm: -1,\n\t\t\t\t\t\ts: -1,\n\t\t\t\t\t\tl: -1,\n\t\t\t\t\t\tc: -1,\n\t\t\t\t\t\tt: -1,\n\t\t\t\t\t\tz: -1\n\t\t\t\t\t};\n\n\t\t\t\tif (finds) {\n\t\t\t\t\tfor (var i = 0; i < finds.length; i++) {\n\t\t\t\t\t\tif (orders[finds[i].toString().charAt(0)] === -1) {\n\t\t\t\t\t\t\torders[finds[i].toString().charAt(0)] = i + 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn orders;\n\t\t\t};\n\n\t\t\tvar regstr = '^' + f.toString()\n\t\t\t\t\t.replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {\n\t\t\t\t\t\t\tvar ml = match.length;\n\t\t\t\t\t\t\tswitch (match.charAt(0).toLowerCase()) {\n\t\t\t\t\t\t\tcase 'h':\n\t\t\t\t\t\t\t\treturn ml === 1 ? '(\\\\d?\\\\d)' : '(\\\\d{' + ml + '})';\n\t\t\t\t\t\t\tcase 'm':\n\t\t\t\t\t\t\t\treturn ml === 1 ? '(\\\\d?\\\\d)' : '(\\\\d{' + ml + '})';\n\t\t\t\t\t\t\tcase 's':\n\t\t\t\t\t\t\t\treturn ml === 1 ? '(\\\\d?\\\\d)' : '(\\\\d{' + ml + '})';\n\t\t\t\t\t\t\tcase 'l':\n\t\t\t\t\t\t\t\treturn '(\\\\d?\\\\d?\\\\d)';\n\t\t\t\t\t\t\tcase 'c':\n\t\t\t\t\t\t\t\treturn '(\\\\d?\\\\d?\\\\d)';\n\t\t\t\t\t\t\tcase 'z':\n\t\t\t\t\t\t\t\treturn '(z|[-+]\\\\d\\\\d:?\\\\d\\\\d|\\\\S+)?';\n\t\t\t\t\t\t\tcase 't':\n\t\t\t\t\t\t\t\treturn getPatternAmpm(o.amNames, o.pmNames);\n\t\t\t\t\t\t\tdefault:    // literal escaped in quotes\n\t\t\t\t\t\t\t\treturn '(' + match.replace(/\\'/g, \"\").replace(/(\\.|\\$|\\^|\\\\|\\/|\\(|\\)|\\[|\\]|\\?|\\+|\\*)/g, function (m) { return \"\\\\\" + m; }) + ')?';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t.replace(/\\s/g, '\\\\s?') +\n\t\t\t\t\to.timeSuffix + '$',\n\t\t\t\torder = getFormatPositions(f),\n\t\t\t\tampm = '',\n\t\t\t\ttreg;\n\n\t\t\ttreg = s.match(new RegExp(regstr, 'i'));\n\n\t\t\tvar resTime = {\n\t\t\t\thour: 0,\n\t\t\t\tminute: 0,\n\t\t\t\tsecond: 0,\n\t\t\t\tmillisec: 0,\n\t\t\t\tmicrosec: 0\n\t\t\t};\n\n\t\t\tif (treg) {\n\t\t\t\tif (order.t !== -1) {\n\t\t\t\t\tif (treg[order.t] === undefined || treg[order.t].length === 0) {\n\t\t\t\t\t\tampm = '';\n\t\t\t\t\t\tresTime.ampm = '';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tampm = $.inArray(treg[order.t].toUpperCase(), o.amNames) !== -1 ? 'AM' : 'PM';\n\t\t\t\t\t\tresTime.ampm = o[ampm === 'AM' ? 'amNames' : 'pmNames'][0];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (order.h !== -1) {\n\t\t\t\t\tif (ampm === 'AM' && treg[order.h] === '12') {\n\t\t\t\t\t\tresTime.hour = 0; // 12am = 0 hour\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (ampm === 'PM' && treg[order.h] !== '12') {\n\t\t\t\t\t\t\tresTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 12\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresTime.hour = Number(treg[order.h]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (order.m !== -1) {\n\t\t\t\t\tresTime.minute = Number(treg[order.m]);\n\t\t\t\t}\n\t\t\t\tif (order.s !== -1) {\n\t\t\t\t\tresTime.second = Number(treg[order.s]);\n\t\t\t\t}\n\t\t\t\tif (order.l !== -1) {\n\t\t\t\t\tresTime.millisec = Number(treg[order.l]);\n\t\t\t\t}\n\t\t\t\tif (order.c !== -1) {\n\t\t\t\t\tresTime.microsec = Number(treg[order.c]);\n\t\t\t\t}\n\t\t\t\tif (order.z !== -1 && treg[order.z] !== undefined) {\n\t\t\t\t\tresTime.timezone = $.timepicker.timezoneOffsetNumber(treg[order.z]);\n\t\t\t\t}\n\n\n\t\t\t\treturn resTime;\n\t\t\t}\n\t\t\treturn false;\n\t\t};// end strictParse\n\n\t\t// First try JS Date, if that fails, use strictParse\n\t\tvar looseParse = function (f, s, o) {\n\t\t\ttry {\n\t\t\t\tvar d = new Date('2012-01-01 ' + s);\n\t\t\t\tif (isNaN(d.getTime())) {\n\t\t\t\t\td = new Date('2012-01-01T' + s);\n\t\t\t\t\tif (isNaN(d.getTime())) {\n\t\t\t\t\t\td = new Date('01/01/2012 ' + s);\n\t\t\t\t\t\tif (isNaN(d.getTime())) {\n\t\t\t\t\t\t\tthrow \"Unable to parse time with native Date: \" + s;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\thour: d.getHours(),\n\t\t\t\t\tminute: d.getMinutes(),\n\t\t\t\t\tsecond: d.getSeconds(),\n\t\t\t\t\tmillisec: d.getMilliseconds(),\n\t\t\t\t\tmicrosec: d.getMicroseconds(),\n\t\t\t\t\ttimezone: d.getTimezoneOffset() * -1\n\t\t\t\t};\n\t\t\t}\n\t\t\tcatch (err) {\n\t\t\t\ttry {\n\t\t\t\t\treturn strictParse(f, s, o);\n\t\t\t\t}\n\t\t\t\tcatch (err2) {\n\t\t\t\t\t$.timepicker.log(\"Unable to parse \\ntimeString: \" + s + \"\\ntimeFormat: \" + f);\n\t\t\t\t}\t\t\t\t\n\t\t\t}\n\t\t\treturn false;\n\t\t}; // end looseParse\n\t\t\n\t\tif (typeof o.parse === \"function\") {\n\t\t\treturn o.parse(timeFormat, timeString, o);\n\t\t}\n\t\tif (o.parse === 'loose') {\n\t\t\treturn looseParse(timeFormat, timeString, o);\n\t\t}\n\t\treturn strictParse(timeFormat, timeString, o);\n\t};\n\n\t/**\n\t * Public utility to format the time\n\t * @param {string} format format of the time\n\t * @param {Object} time Object not a Date for timezones\n\t * @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm\n\t * @returns {string} the formatted time\n\t */\n\t$.datepicker.formatTime = function (format, time, options) {\n\t\toptions = options || {};\n\t\toptions = $.extend({}, $.timepicker._defaults, options);\n\t\ttime = $.extend({\n\t\t\thour: 0,\n\t\t\tminute: 0,\n\t\t\tsecond: 0,\n\t\t\tmillisec: 0,\n\t\t\tmicrosec: 0,\n\t\t\ttimezone: null\n\t\t}, time);\n\n\t\tvar tmptime = format,\n\t\t\tampmName = options.amNames[0],\n\t\t\thour = parseInt(time.hour, 10);\n\n\t\tif (hour > 11) {\n\t\t\tampmName = options.pmNames[0];\n\t\t}\n\n\t\ttmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {\n\t\t\tswitch (match) {\n\t\t\tcase 'HH':\n\t\t\t\treturn ('0' + hour).slice(-2);\n\t\t\tcase 'H':\n\t\t\t\treturn hour;\n\t\t\tcase 'hh':\n\t\t\t\treturn ('0' + convert24to12(hour)).slice(-2);\n\t\t\tcase 'h':\n\t\t\t\treturn convert24to12(hour);\n\t\t\tcase 'mm':\n\t\t\t\treturn ('0' + time.minute).slice(-2);\n\t\t\tcase 'm':\n\t\t\t\treturn time.minute;\n\t\t\tcase 'ss':\n\t\t\t\treturn ('0' + time.second).slice(-2);\n\t\t\tcase 's':\n\t\t\t\treturn time.second;\n\t\t\tcase 'l':\n\t\t\t\treturn ('00' + time.millisec).slice(-3);\n\t\t\tcase 'c':\n\t\t\t\treturn ('00' + time.microsec).slice(-3);\n\t\t\tcase 'z':\n\t\t\t\treturn $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, false);\n\t\t\tcase 'Z':\n\t\t\t\treturn $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, true);\n\t\t\tcase 'T':\n\t\t\t\treturn ampmName.charAt(0).toUpperCase();\n\t\t\tcase 'TT':\n\t\t\t\treturn ampmName.toUpperCase();\n\t\t\tcase 't':\n\t\t\t\treturn ampmName.charAt(0).toLowerCase();\n\t\t\tcase 'tt':\n\t\t\t\treturn ampmName.toLowerCase();\n\t\t\tdefault:\n\t\t\t\treturn match.replace(/'/g, \"\");\n\t\t\t}\n\t\t});\n\n\t\treturn tmptime;\n\t};\n\n\t/*\n\t* the bad hack :/ override datepicker so it doesn't close on select\n\t// inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378\n\t*/\n\t$.datepicker._base_selectDate = $.datepicker._selectDate;\n\t$.datepicker._selectDate = function (id, dateStr) {\n\t\tvar inst = this._getInst($(id)[0]),\n\t\t\ttp_inst = this._get(inst, 'timepicker');\n\n\t\tif (tp_inst) {\n\t\t\ttp_inst._limitMinMaxDateTime(inst, true);\n\t\t\tinst.inline = inst.stay_open = true;\n\t\t\t//This way the onSelect handler called from calendarpicker get the full dateTime\n\t\t\tthis._base_selectDate(id, dateStr);\n\t\t\tinst.inline = inst.stay_open = false;\n\t\t\tthis._notifyChange(inst);\n\t\t\tthis._updateDatepicker(inst);\n\t\t} else {\n\t\t\tthis._base_selectDate(id, dateStr);\n\t\t}\n\t};\n\n\t/*\n\t* second bad hack :/ override datepicker so it triggers an event when changing the input field\n\t* and does not redraw the datepicker on every selectDate event\n\t*/\n\t$.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;\n\t$.datepicker._updateDatepicker = function (inst) {\n\n\t\t// don't popup the datepicker if there is another instance already opened\n\t\tvar input = inst.input[0];\n\t\tif ($.datepicker._curInst && $.datepicker._curInst !== inst && $.datepicker._datepickerShowing && $.datepicker._lastInput !== input) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {\n\n\t\t\tthis._base_updateDatepicker(inst);\n\n\t\t\t// Reload the time control when changing something in the input text field.\n\t\t\tvar tp_inst = this._get(inst, 'timepicker');\n\t\t\tif (tp_inst) {\n\t\t\t\ttp_inst._addTimePicker(inst);\n\t\t\t}\n\t\t}\n\t};\n\n\t/*\n\t* third bad hack :/ override datepicker so it allows spaces and colon in the input field\n\t*/\n\t$.datepicker._base_doKeyPress = $.datepicker._doKeyPress;\n\t$.datepicker._doKeyPress = function (event) {\n\t\tvar inst = $.datepicker._getInst(event.target),\n\t\t\ttp_inst = $.datepicker._get(inst, 'timepicker');\n\n\t\tif (tp_inst) {\n\t\t\tif ($.datepicker._get(inst, 'constrainInput')) {\n\t\t\t\tvar ampm = tp_inst.support.ampm,\n\t\t\t\t\ttz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone,\n\t\t\t\t\tdateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),\n\t\t\t\t\tdatetimeChars = tp_inst._defaults.timeFormat.toString()\n\t\t\t\t\t\t\t\t\t\t\t.replace(/[hms]/g, '')\n\t\t\t\t\t\t\t\t\t\t\t.replace(/TT/g, ampm ? 'APM' : '')\n\t\t\t\t\t\t\t\t\t\t\t.replace(/Tt/g, ampm ? 'AaPpMm' : '')\n\t\t\t\t\t\t\t\t\t\t\t.replace(/tT/g, ampm ? 'AaPpMm' : '')\n\t\t\t\t\t\t\t\t\t\t\t.replace(/T/g, ampm ? 'AP' : '')\n\t\t\t\t\t\t\t\t\t\t\t.replace(/tt/g, ampm ? 'apm' : '')\n\t\t\t\t\t\t\t\t\t\t\t.replace(/t/g, ampm ? 'ap' : '') + \n\t\t\t\t\t\t\t\t\t\t\t\" \" + tp_inst._defaults.separator + \n\t\t\t\t\t\t\t\t\t\t\ttp_inst._defaults.timeSuffix + \n\t\t\t\t\t\t\t\t\t\t\t(tz ? tp_inst._defaults.timezoneList.join('') : '') + \n\t\t\t\t\t\t\t\t\t\t\t(tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) + \n\t\t\t\t\t\t\t\t\t\t\tdateChars,\n\t\t\t\t\tchr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);\n\t\t\t\treturn event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);\n\t\t\t}\n\t\t}\n\n\t\treturn $.datepicker._base_doKeyPress(event);\n\t};\n\n\t/*\n\t* Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField\n\t* Update any alternate field to synchronise with the main field.\n\t*/\n\t$.datepicker._base_updateAlternate = $.datepicker._updateAlternate;\n\t$.datepicker._updateAlternate = function (inst) {\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\t\tif (tp_inst) {\n\t\t\tvar altField = tp_inst._defaults.altField;\n\t\t\tif (altField) { // update alternate field too\n\t\t\t\tvar altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,\n\t\t\t\t\tdate = this._getDate(inst),\n\t\t\t\t\tformatCfg = $.datepicker._getFormatConfig(inst),\n\t\t\t\t\taltFormattedDateTime = '', \n\t\t\t\t\taltSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator, \n\t\t\t\t\taltTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,\n\t\t\t\t\taltTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;\n\t\t\t\t\n\t\t\t\taltFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;\n\t\t\t\tif (!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null) {\n\t\t\t\t\tif (tp_inst._defaults.altFormat) {\n\t\t\t\t\t\taltFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\taltFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$(altField).val(altFormattedDateTime);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t$.datepicker._base_updateAlternate(inst);\n\t\t}\n\t};\n\n\t/*\n\t* Override key up event to sync manual input changes.\n\t*/\n\t$.datepicker._base_doKeyUp = $.datepicker._doKeyUp;\n\t$.datepicker._doKeyUp = function (event) {\n\t\tvar inst = $.datepicker._getInst(event.target),\n\t\t\ttp_inst = $.datepicker._get(inst, 'timepicker');\n\n\t\tif (tp_inst) {\n\t\t\tif (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {\n\t\t\t\ttry {\n\t\t\t\t\t$.datepicker._updateDatepicker(inst);\n\t\t\t\t} catch (err) {\n\t\t\t\t\t$.timepicker.log(err);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $.datepicker._base_doKeyUp(event);\n\t};\n\n\t/*\n\t* override \"Today\" button to also grab the time.\n\t*/\n\t$.datepicker._base_gotoToday = $.datepicker._gotoToday;\n\t$.datepicker._gotoToday = function (id) {\n\t\tvar inst = this._getInst($(id)[0]),\n\t\t\t$dp = inst.dpDiv;\n\t\tthis._base_gotoToday(id);\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\t\tselectLocalTimezone(tp_inst);\n\t\tvar now = new Date();\n\t\tthis._setTime(inst, now);\n\t\t$('.ui-datepicker-today', $dp).click();\n\t};\n\n\t/*\n\t* Disable & enable the Time in the datetimepicker\n\t*/\n\t$.datepicker._disableTimepickerDatepicker = function (target) {\n\t\tvar inst = this._getInst(target);\n\t\tif (!inst) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\t\t$(target).datepicker('getDate'); // Init selected[Year|Month|Day]\n\t\tif (tp_inst) {\n\t\t\tinst.settings.showTimepicker = false;\n\t\t\ttp_inst._defaults.showTimepicker = false;\n\t\t\ttp_inst._updateDateTime(inst);\n\t\t}\n\t};\n\n\t$.datepicker._enableTimepickerDatepicker = function (target) {\n\t\tvar inst = this._getInst(target);\n\t\tif (!inst) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\t\t$(target).datepicker('getDate'); // Init selected[Year|Month|Day]\n\t\tif (tp_inst) {\n\t\t\tinst.settings.showTimepicker = true;\n\t\t\ttp_inst._defaults.showTimepicker = true;\n\t\t\ttp_inst._addTimePicker(inst); // Could be disabled on page load\n\t\t\ttp_inst._updateDateTime(inst);\n\t\t}\n\t};\n\n\t/*\n\t* Create our own set time function\n\t*/\n\t$.datepicker._setTime = function (inst, date) {\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\t\tif (tp_inst) {\n\t\t\tvar defaults = tp_inst._defaults;\n\n\t\t\t// calling _setTime with no date sets time to defaults\n\t\t\ttp_inst.hour = date ? date.getHours() : defaults.hour;\n\t\t\ttp_inst.minute = date ? date.getMinutes() : defaults.minute;\n\t\t\ttp_inst.second = date ? date.getSeconds() : defaults.second;\n\t\t\ttp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;\n\t\t\ttp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec;\n\n\t\t\t//check if within min/max times.. \n\t\t\ttp_inst._limitMinMaxDateTime(inst, true);\n\n\t\t\ttp_inst._onTimeChange();\n\t\t\ttp_inst._updateDateTime(inst);\n\t\t}\n\t};\n\n\t/*\n\t* Create new public method to set only time, callable as $().datepicker('setTime', date)\n\t*/\n\t$.datepicker._setTimeDatepicker = function (target, date, withDate) {\n\t\tvar inst = this._getInst(target);\n\t\tif (!inst) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\n\t\tif (tp_inst) {\n\t\t\tthis._setDateFromField(inst);\n\t\t\tvar tp_date;\n\t\t\tif (date) {\n\t\t\t\tif (typeof date === \"string\") {\n\t\t\t\t\ttp_inst._parseTime(date, withDate);\n\t\t\t\t\ttp_date = new Date();\n\t\t\t\t\ttp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);\n\t\t\t\t\ttp_date.setMicroseconds(tp_inst.microsec);\n\t\t\t\t} else {\n\t\t\t\t\ttp_date = new Date(date.getTime());\n\t\t\t\t\ttp_date.setMicroseconds(date.getMicroseconds());\n\t\t\t\t}\n\t\t\t\tif (tp_date.toString() === 'Invalid Date') {\n\t\t\t\t\ttp_date = undefined;\n\t\t\t\t}\n\t\t\t\tthis._setTime(inst, tp_date);\n\t\t\t}\n\t\t}\n\n\t};\n\n\t/*\n\t* override setDate() to allow setting time too within Date object\n\t*/\n\t$.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;\n\t$.datepicker._setDateDatepicker = function (target, date) {\n\t\tvar inst = this._getInst(target);\n\t\tif (!inst) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof(date) === 'string') {\n\t\t\tdate = new Date(date);\n\t\t\tif (!date.getTime()) {\n\t\t\t\t$.timepicker.log(\"Error creating Date object from string.\");\n\t\t\t}\n\t\t}\n\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\t\tvar tp_date;\n\t\tif (date instanceof Date) {\n\t\t\ttp_date = new Date(date.getTime());\n\t\t\ttp_date.setMicroseconds(date.getMicroseconds());\n\t\t} else {\n\t\t\ttp_date = date;\n\t\t}\n\t\t\n\t\t// This is important if you are using the timezone option, javascript's Date \n\t\t// object will only return the timezone offset for the current locale, so we \n\t\t// adjust it accordingly.  If not using timezone option this won't matter..\n\t\t// If a timezone is different in tp, keep the timezone as is\n\t\tif (tp_inst && tp_date) {\n\t\t\t// look out for DST if tz wasn't specified\n\t\t\tif (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {\n\t\t\t\ttp_inst.timezone = tp_date.getTimezoneOffset() * -1;\n\t\t\t}\n\t\t\tdate = $.timepicker.timezoneAdjust(date, tp_inst.timezone);\n\t\t\ttp_date = $.timepicker.timezoneAdjust(tp_date, tp_inst.timezone);\n\t\t}\n\n\t\tthis._updateDatepicker(inst);\n\t\tthis._base_setDateDatepicker.apply(this, arguments);\n\t\tthis._setTimeDatepicker(target, tp_date, true);\n\t};\n\n\t/*\n\t* override getDate() to allow getting time too within Date object\n\t*/\n\t$.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;\n\t$.datepicker._getDateDatepicker = function (target, noDefault) {\n\t\tvar inst = this._getInst(target);\n\t\tif (!inst) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\n\t\tif (tp_inst) {\n\t\t\t// if it hasn't yet been defined, grab from field\n\t\t\tif (inst.lastVal === undefined) {\n\t\t\t\tthis._setDateFromField(inst, noDefault);\n\t\t\t}\n\n\t\t\tvar date = this._getDate(inst);\n\t\t\tif (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) {\n\t\t\t\tdate.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);\n\t\t\t\tdate.setMicroseconds(tp_inst.microsec);\n\n\t\t\t\t// This is important if you are using the timezone option, javascript's Date \n\t\t\t\t// object will only return the timezone offset for the current locale, so we \n\t\t\t\t// adjust it accordingly.  If not using timezone option this won't matter..\n\t\t\t\tif (tp_inst.timezone != null) {\n\t\t\t\t\t// look out for DST if tz wasn't specified\n\t\t\t\t\tif (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {\n\t\t\t\t\t\ttp_inst.timezone = date.getTimezoneOffset() * -1;\n\t\t\t\t\t}\n\t\t\t\t\tdate = $.timepicker.timezoneAdjust(date, tp_inst.timezone);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn date;\n\t\t}\n\t\treturn this._base_getDateDatepicker(target, noDefault);\n\t};\n\n\t/*\n\t* override parseDate() because UI 1.8.14 throws an error about \"Extra characters\"\n\t* An option in datapicker to ignore extra format characters would be nicer.\n\t*/\n\t$.datepicker._base_parseDate = $.datepicker.parseDate;\n\t$.datepicker.parseDate = function (format, value, settings) {\n\t\tvar date;\n\t\ttry {\n\t\t\tdate = this._base_parseDate(format, value, settings);\n\t\t} catch (err) {\n\t\t\t// Hack!  The error message ends with a colon, a space, and\n\t\t\t// the \"extra\" characters.  We rely on that instead of\n\t\t\t// attempting to perfectly reproduce the parsing algorithm.\n\t\t\tif (err.indexOf(\":\") >= 0) {\n\t\t\t\tdate = this._base_parseDate(format, value.substring(0, value.length - (err.length - err.indexOf(':') - 2)), settings);\n\t\t\t\t$.timepicker.log(\"Error parsing the date string: \" + err + \"\\ndate string = \" + value + \"\\ndate format = \" + format);\n\t\t\t} else {\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\t\treturn date;\n\t};\n\n\t/*\n\t* override formatDate to set date with time to the input\n\t*/\n\t$.datepicker._base_formatDate = $.datepicker._formatDate;\n\t$.datepicker._formatDate = function (inst, day, month, year) {\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\t\tif (tp_inst) {\n\t\t\ttp_inst._updateDateTime(inst);\n\t\t\treturn tp_inst.$input.val();\n\t\t}\n\t\treturn this._base_formatDate(inst);\n\t};\n\n\t/*\n\t* override options setter to add time to maxDate(Time) and minDate(Time). MaxDate\n\t*/\n\t$.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;\n\t$.datepicker._optionDatepicker = function (target, name, value) {\n\t\tvar inst = this._getInst(target),\n\t\t\tname_clone;\n\t\tif (!inst) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar tp_inst = this._get(inst, 'timepicker');\n\t\tif (tp_inst) {\n\t\t\tvar min = null,\n\t\t\t\tmax = null,\n\t\t\t\tonselect = null,\n\t\t\t\toverrides = tp_inst._defaults.evnts,\n\t\t\t\tfns = {},\n\t\t\t\tprop;\n\t\t\tif (typeof name === 'string') { // if min/max was set with the string\n\t\t\t\tif (name === 'minDate' || name === 'minDateTime') {\n\t\t\t\t\tmin = value;\n\t\t\t\t} else if (name === 'maxDate' || name === 'maxDateTime') {\n\t\t\t\t\tmax = value;\n\t\t\t\t} else if (name === 'onSelect') {\n\t\t\t\t\tonselect = value;\n\t\t\t\t} else if (overrides.hasOwnProperty(name)) {\n\t\t\t\t\tif (typeof (value) === 'undefined') {\n\t\t\t\t\t\treturn overrides[name];\n\t\t\t\t\t}\n\t\t\t\t\tfns[name] = value;\n\t\t\t\t\tname_clone = {}; //empty results in exiting function after overrides updated\n\t\t\t\t}\n\t\t\t} else if (typeof name === 'object') { //if min/max was set with the JSON\n\t\t\t\tif (name.minDate) {\n\t\t\t\t\tmin = name.minDate;\n\t\t\t\t} else if (name.minDateTime) {\n\t\t\t\t\tmin = name.minDateTime;\n\t\t\t\t} else if (name.maxDate) {\n\t\t\t\t\tmax = name.maxDate;\n\t\t\t\t} else if (name.maxDateTime) {\n\t\t\t\t\tmax = name.maxDateTime;\n\t\t\t\t}\n\t\t\t\tfor (prop in overrides) {\n\t\t\t\t\tif (overrides.hasOwnProperty(prop) && name[prop]) {\n\t\t\t\t\t\tfns[prop] = name[prop];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (prop in fns) {\n\t\t\t\tif (fns.hasOwnProperty(prop)) {\n\t\t\t\t\toverrides[prop] = fns[prop];\n\t\t\t\t\tif (!name_clone) { name_clone = $.extend({}, name); }\n\t\t\t\t\tdelete name_clone[prop];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (name_clone && isEmptyObject(name_clone)) { return; }\n\t\t\tif (min) { //if min was set\n\t\t\t\tif (min === 0) {\n\t\t\t\t\tmin = new Date();\n\t\t\t\t} else {\n\t\t\t\t\tmin = new Date(min);\n\t\t\t\t}\n\t\t\t\ttp_inst._defaults.minDate = min;\n\t\t\t\ttp_inst._defaults.minDateTime = min;\n\t\t\t} else if (max) { //if max was set\n\t\t\t\tif (max === 0) {\n\t\t\t\t\tmax = new Date();\n\t\t\t\t} else {\n\t\t\t\t\tmax = new Date(max);\n\t\t\t\t}\n\t\t\t\ttp_inst._defaults.maxDate = max;\n\t\t\t\ttp_inst._defaults.maxDateTime = max;\n\t\t\t} else if (onselect) {\n\t\t\t\ttp_inst._defaults.onSelect = onselect;\n\t\t\t}\n\t\t}\n\t\tif (value === undefined) {\n\t\t\treturn this._base_optionDatepicker.call($.datepicker, target, name);\n\t\t}\n\t\treturn this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);\n\t};\n\t\n\t/*\n\t* jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,\n\t* it will return false for all objects\n\t*/\n\tvar isEmptyObject = function (obj) {\n\t\tvar prop;\n\t\tfor (prop in obj) {\n\t\t\tif (obj.hasOwnProperty(prop)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t};\n\n\t/*\n\t* jQuery extend now ignores nulls!\n\t*/\n\tvar extendRemove = function (target, props) {\n\t\t$.extend(target, props);\n\t\tfor (var name in props) {\n\t\t\tif (props[name] === null || props[name] === undefined) {\n\t\t\t\ttarget[name] = props[name];\n\t\t\t}\n\t\t}\n\t\treturn target;\n\t};\n\n\t/*\n\t* Determine by the time format which units are supported\n\t* Returns an object of booleans for each unit\n\t*/\n\tvar detectSupport = function (timeFormat) {\n\t\tvar tf = timeFormat.replace(/'.*?'/g, '').toLowerCase(), // removes literals\n\t\t\tisIn = function (f, t) { // does the format contain the token?\n\t\t\t\t\treturn f.indexOf(t) !== -1 ? true : false;\n\t\t\t\t};\n\t\treturn {\n\t\t\t\thour: isIn(tf, 'h'),\n\t\t\t\tminute: isIn(tf, 'm'),\n\t\t\t\tsecond: isIn(tf, 's'),\n\t\t\t\tmillisec: isIn(tf, 'l'),\n\t\t\t\tmicrosec: isIn(tf, 'c'),\n\t\t\t\ttimezone: isIn(tf, 'z'),\n\t\t\t\tampm: isIn(tf, 't') && isIn(timeFormat, 'h'),\n\t\t\t\tiso8601: isIn(timeFormat, 'Z')\n\t\t\t};\n\t};\n\n\t/*\n\t* Converts 24 hour format into 12 hour\n\t* Returns 12 hour without leading 0\n\t*/\n\tvar convert24to12 = function (hour) {\n\t\thour %= 12;\n\n\t\tif (hour === 0) {\n\t\t\thour = 12;\n\t\t}\n\n\t\treturn String(hour);\n\t};\n\n\tvar computeEffectiveSetting = function (settings, property) {\n\t\treturn settings && settings[property] ? settings[property] : $.timepicker._defaults[property];\n\t};\n\n\t/*\n\t* Splits datetime string into date and time substrings.\n\t* Throws exception when date can't be parsed\n\t* Returns {dateString: dateString, timeString: timeString}\n\t*/\n\tvar splitDateTime = function (dateTimeString, timeSettings) {\n\t\t// The idea is to get the number separator occurrences in datetime and the time format requested (since time has\n\t\t// fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.\n\t\tvar separator = computeEffectiveSetting(timeSettings, 'separator'),\n\t\t\tformat = computeEffectiveSetting(timeSettings, 'timeFormat'),\n\t\t\ttimeParts = format.split(separator), // how many occurrences of separator may be in our format?\n\t\t\ttimePartsLen = timeParts.length,\n\t\t\tallParts = dateTimeString.split(separator),\n\t\t\tallPartsLen = allParts.length;\n\n\t\tif (allPartsLen > 1) {\n\t\t\treturn {\n\t\t\t\tdateString: allParts.splice(0, allPartsLen - timePartsLen).join(separator),\n\t\t\t\ttimeString: allParts.splice(0, timePartsLen).join(separator)\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tdateString: dateTimeString,\n\t\t\ttimeString: ''\n\t\t};\n\t};\n\n\t/*\n\t* Internal function to parse datetime interval\n\t* Returns: {date: Date, timeObj: Object}, where\n\t*   date - parsed date without time (type Date)\n\t*   timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional\n\t*/\n\tvar parseDateTimeInternal = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {\n\t\tvar date,\n\t\t\tparts,\n\t\t\tparsedTime;\n\n\t\tparts = splitDateTime(dateTimeString, timeSettings);\n\t\tdate = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings);\n\n\t\tif (parts.timeString === '') {\n\t\t\treturn {\n\t\t\t\tdate: date\n\t\t\t};\n\t\t}\n\n\t\tparsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings);\n\n\t\tif (!parsedTime) {\n\t\t\tthrow 'Wrong time format';\n\t\t}\n\n\t\treturn {\n\t\t\tdate: date,\n\t\t\ttimeObj: parsedTime\n\t\t};\n\t};\n\n\t/*\n\t* Internal function to set timezone_select to the local timezone\n\t*/\n\tvar selectLocalTimezone = function (tp_inst, date) {\n\t\tif (tp_inst && tp_inst.timezone_select) {\n\t\t\tvar now = date || new Date();\n\t\t\ttp_inst.timezone_select.val(-now.getTimezoneOffset());\n\t\t}\n\t};\n\n\t/*\n\t* Create a Singleton Instance\n\t*/\n\t$.timepicker = new Timepicker();\n\n\t/**\n\t * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)\n\t * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned\n\t * @param {boolean} iso8601 if true formats in accordance to iso8601 \"+12:45\"\n\t * @return {string}\n\t */\n\t$.timepicker.timezoneOffsetString = function (tzMinutes, iso8601) {\n\t\tif (isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720) {\n\t\t\treturn tzMinutes;\n\t\t}\n\n\t\tvar off = tzMinutes,\n\t\t\tminutes = off % 60,\n\t\t\thours = (off - minutes) / 60,\n\t\t\tiso = iso8601 ? ':' : '',\n\t\t\ttz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2);\n\t\t\n\t\tif (tz === '+00:00') {\n\t\t\treturn 'Z';\n\t\t}\n\t\treturn tz;\n\t};\n\n\t/**\n\t * Get the number in minutes that represents a timezone string\n\t * @param  {string} tzString formatted like \"+0500\", \"-1245\", \"Z\"\n\t * @return {number} the offset minutes or the original string if it doesn't match expectations\n\t */\n\t$.timepicker.timezoneOffsetNumber = function (tzString) {\n\t\tvar normalized = tzString.toString().replace(':', ''); // excuse any iso8601, end up with \"+1245\"\n\n\t\tif (normalized.toUpperCase() === 'Z') { // if iso8601 with Z, its 0 minute offset\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (!/^(\\-|\\+)\\d{4}$/.test(normalized)) { // possibly a user defined tz, so just give it back\n\t\t\treturn tzString;\n\t\t}\n\n\t\treturn ((normalized.substr(0, 1) === '-' ? -1 : 1) * // plus or minus\n\t\t\t\t\t((parseInt(normalized.substr(1, 2), 10) * 60) + // hours (converted to minutes)\n\t\t\t\t\tparseInt(normalized.substr(3, 2), 10))); // minutes\n\t};\n\n\t/**\n\t * No way to set timezone in js Date, so we must adjust the minutes to compensate. (think setDate, getDate)\n\t * @param  {Date} date\n\t * @param  {string} toTimezone formatted like \"+0500\", \"-1245\"\n\t * @return {Date}\n\t */\n\t$.timepicker.timezoneAdjust = function (date, toTimezone) {\n\t\tvar toTz = $.timepicker.timezoneOffsetNumber(toTimezone);\n\t\tif (!isNaN(toTz)) {\n\t\t\tdate.setMinutes(date.getMinutes() + -date.getTimezoneOffset() - toTz);\n\t\t}\n\t\treturn date;\n\t};\n\n\t/**\n\t * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to\n\t * enforce date range limits.\n\t * n.b. The input value must be correctly formatted (reformatting is not supported)\n\t * @param  {Element} startTime\n\t * @param  {Element} endTime\n\t * @param  {Object} options Options for the timepicker() call\n\t * @return {jQuery}\n\t */\n\t$.timepicker.timeRange = function (startTime, endTime, options) {\n\t\treturn $.timepicker.handleRange('timepicker', startTime, endTime, options);\n\t};\n\n\t/**\n\t * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to\n\t * enforce date range limits.\n\t * @param  {Element} startTime\n\t * @param  {Element} endTime\n\t * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,\n\t *   a boolean value that can be used to reformat the input values to the `dateFormat`.\n\t * @param  {string} method Can be used to specify the type of picker to be added\n\t * @return {jQuery}\n\t */\n\t$.timepicker.datetimeRange = function (startTime, endTime, options) {\n\t\t$.timepicker.handleRange('datetimepicker', startTime, endTime, options);\n\t};\n\n\t/**\n\t * Calls `datepicker` on the `startTime` and `endTime` elements, and configures them to\n\t * enforce date range limits.\n\t * @param  {Element} startTime\n\t * @param  {Element} endTime\n\t * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,\n\t *   a boolean value that can be used to reformat the input values to the `dateFormat`.\n\t * @return {jQuery}\n\t */\n\t$.timepicker.dateRange = function (startTime, endTime, options) {\n\t\t$.timepicker.handleRange('datepicker', startTime, endTime, options);\n\t};\n\n\t/**\n\t * Calls `method` on the `startTime` and `endTime` elements, and configures them to\n\t * enforce date range limits.\n\t * @param  {string} method Can be used to specify the type of picker to be added\n\t * @param  {Element} startTime\n\t * @param  {Element} endTime\n\t * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,\n\t *   a boolean value that can be used to reformat the input values to the `dateFormat`.\n\t * @return {jQuery}\n\t */\n\t$.timepicker.handleRange = function (method, startTime, endTime, options) {\n\t\toptions = $.extend({}, {\n\t\t\tminInterval: 0, // min allowed interval in milliseconds\n\t\t\tmaxInterval: 0, // max allowed interval in milliseconds\n\t\t\tstart: {},      // options for start picker\n\t\t\tend: {}         // options for end picker\n\t\t}, options);\n\n\t\tfunction checkDates(changed, other) {\n\t\t\tvar startdt = startTime[method]('getDate'),\n\t\t\t\tenddt = endTime[method]('getDate'),\n\t\t\t\tchangeddt = changed[method]('getDate');\n\n\t\t\tif (startdt !== null) {\n\t\t\t\tvar minDate = new Date(startdt.getTime()),\n\t\t\t\t\tmaxDate = new Date(startdt.getTime());\n\n\t\t\t\tminDate.setMilliseconds(minDate.getMilliseconds() + options.minInterval);\n\t\t\t\tmaxDate.setMilliseconds(maxDate.getMilliseconds() + options.maxInterval);\n\n\t\t\t\tif (options.minInterval > 0 && minDate > enddt) { // minInterval check\n\t\t\t\t\tendTime[method]('setDate', minDate);\n\t\t\t\t}\n\t\t\t\telse if (options.maxInterval > 0 && maxDate < enddt) { // max interval check\n\t\t\t\t\tendTime[method]('setDate', maxDate);\n\t\t\t\t}\n\t\t\t\telse if (startdt > enddt) {\n\t\t\t\t\tother[method]('setDate', changeddt);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction selected(changed, other, option) {\n\t\t\tif (!changed.val()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar date = changed[method].call(changed, 'getDate');\n\t\t\tif (date !== null && options.minInterval > 0) {\n\t\t\t\tif (option === 'minDate') {\n\t\t\t\t\tdate.setMilliseconds(date.getMilliseconds() + options.minInterval);\n\t\t\t\t}\n\t\t\t\tif (option === 'maxDate') {\n\t\t\t\t\tdate.setMilliseconds(date.getMilliseconds() - options.minInterval);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (date.getTime) {\n\t\t\t\tother[method].call(other, 'option', option, date);\n\t\t\t}\n\t\t}\n\n\t\t$.fn[method].call(startTime, $.extend({\n\t\t\tonClose: function (dateText, inst) {\n\t\t\t\tcheckDates($(this), endTime);\n\t\t\t},\n\t\t\tonSelect: function (selectedDateTime) {\n\t\t\t\tselected($(this), endTime, 'minDate');\n\t\t\t}\n\t\t}, options, options.start));\n\t\t$.fn[method].call(endTime, $.extend({\n\t\t\tonClose: function (dateText, inst) {\n\t\t\t\tcheckDates($(this), startTime);\n\t\t\t},\n\t\t\tonSelect: function (selectedDateTime) {\n\t\t\t\tselected($(this), startTime, 'maxDate');\n\t\t\t}\n\t\t}, options, options.end));\n\n\t\tcheckDates(startTime, endTime);\n\t\tselected(startTime, endTime, 'minDate');\n\t\tselected(endTime, startTime, 'maxDate');\n\t\treturn $([startTime.get(0), endTime.get(0)]);\n\t};\n\n\t/**\n\t * Log error or data to the console during error or debugging\n\t * @param  {Object} err pass any type object to log to the console during error or debugging\n\t * @return {void}\n\t */\n\t$.timepicker.log = function (err) {\n\t\tif (window.console) {\n\t\t\twindow.console.log(err);\n\t\t}\n\t};\n\n\t/*\n\t * Add util object to allow access to private methods for testability.\n\t */\n\t$.timepicker._util = {\n\t\t_extendRemove: extendRemove,\n\t\t_isEmptyObject: isEmptyObject,\n\t\t_convert24to12: convert24to12,\n\t\t_detectSupport: detectSupport,\n\t\t_selectLocalTimezone: selectLocalTimezone,\n\t\t_computeEffectiveSetting: computeEffectiveSetting,\n\t\t_splitDateTime: splitDateTime,\n\t\t_parseDateTimeInternal: parseDateTimeInternal\n\t};\n\n\t/*\n\t* Microsecond support\n\t*/\n\tif (!Date.prototype.getMicroseconds) {\n\t\tDate.prototype.microseconds = 0;\n\t\tDate.prototype.getMicroseconds = function () { return this.microseconds; };\n\t\tDate.prototype.setMicroseconds = function (m) {\n\t\t\tthis.setMilliseconds(this.getMilliseconds() + Math.floor(m / 1000));\n\t\t\tthis.microseconds = m % 1000;\n\t\t\treturn this;\n\t\t};\n\t}\n\n\t/*\n\t* Keep up with the version\n\t*/\n\t$.timepicker.version = \"1.4.3\";\n\n}));","jquery/jquery-migrate.js":"/*!\n * jQuery Migrate - v1.4.1 - 2016-05-19\n * Copyright jQuery Foundation and other contributors\n */\n(function( jQuery, window, undefined ) {\n// See http://bugs.jquery.com/ticket/13335\n// \"use strict\";\n\n\njQuery.migrateVersion = \"1.4.1\";\n\n\nvar warnedAbout = {};\n\n// List of warnings already given; public read only\njQuery.migrateWarnings = [];\n\n// Set to true to prevent console output; migrateWarnings still maintained\n// jQuery.migrateMute = false;\n\n// Show a message on the console so devs know we're active\nif ( window.console && window.console.log ) {\n\twindow.console.log( \"JQMIGRATE: Migrate is installed\" +\n\t\t( jQuery.migrateMute ? \"\" : \" with logging active\" ) +\n\t\t\", version \" + jQuery.migrateVersion );\n}\n\n// Set to false to disable traces that appear with warnings\nif ( jQuery.migrateTrace === undefined ) {\n\tjQuery.migrateTrace = true;\n}\n\n// Forget any warnings we've already given; public\njQuery.migrateReset = function() {\n\twarnedAbout = {};\n\tjQuery.migrateWarnings.length = 0;\n};\n\nfunction migrateWarn( msg) {\n\tvar console = window.console;\n\tif ( !warnedAbout[ msg ] ) {\n\t\twarnedAbout[ msg ] = true;\n\t\tjQuery.migrateWarnings.push( msg );\n\t\tif ( console && console.warn && !jQuery.migrateMute ) {\n\t\t\tconsole.warn( \"JQMIGRATE: \" + msg );\n\t\t\tif ( jQuery.migrateTrace && console.trace ) {\n\t\t\t\tconsole.trace();\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction migrateWarnProp( obj, prop, value, msg ) {\n\tif ( Object.defineProperty ) {\n\t\t// On ES5 browsers (non-oldIE), warn if the code tries to get prop;\n\t\t// allow property to be overwritten in case some other plugin wants it\n\t\ttry {\n\t\t\tObject.defineProperty( obj, prop, {\n\t\t\t\tconfigurable: true,\n\t\t\t\tenumerable: true,\n\t\t\t\tget: function() {\n\t\t\t\t\tmigrateWarn( msg );\n\t\t\t\t\treturn value;\n\t\t\t\t},\n\t\t\t\tset: function( newValue ) {\n\t\t\t\t\tmigrateWarn( msg );\n\t\t\t\t\tvalue = newValue;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t} catch( err ) {\n\t\t\t// IE8 is a dope about Object.defineProperty, can't warn there\n\t\t}\n\t}\n\n\t// Non-ES5 (or broken) browser; just set the property\n\tjQuery._definePropertyBroken = true;\n\tobj[ prop ] = value;\n}\n\nif ( document.compatMode === \"BackCompat\" ) {\n\t// jQuery has never supported or tested Quirks Mode\n\tmigrateWarn( \"jQuery is not compatible with Quirks Mode\" );\n}\n\n\nvar attrFn = jQuery( \"<input/>\", { size: 1 } ).attr(\"size\") && jQuery.attrFn,\n\toldAttr = jQuery.attr,\n\tvalueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||\n\t\tfunction() { return null; },\n\tvalueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||\n\t\tfunction() { return undefined; },\n\trnoType = /^(?:input|button)$/i,\n\trnoAttrNodeType = /^[238]$/,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\truseDefault = /^(?:checked|selected)$/i;\n\n// jQuery.attrFn\nmigrateWarnProp( jQuery, \"attrFn\", attrFn || {}, \"jQuery.attrFn is deprecated\" );\n\njQuery.attr = function( elem, name, value, pass ) {\n\tvar lowerName = name.toLowerCase(),\n\t\tnType = elem && elem.nodeType;\n\n\tif ( pass ) {\n\t\t// Since pass is used internally, we only warn for new jQuery\n\t\t// versions where there isn't a pass arg in the formal params\n\t\tif ( oldAttr.length < 4 ) {\n\t\t\tmigrateWarn(\"jQuery.fn.attr( props, pass ) is deprecated\");\n\t\t}\n\t\tif ( elem && !rnoAttrNodeType.test( nType ) &&\n\t\t\t(attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\t}\n\n\t// Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking\n\t// for disconnected elements we don't warn on $( \"<button>\", { type: \"button\" } ).\n\tif ( name === \"type\" && value !== undefined && rnoType.test( elem.nodeName ) && elem.parentNode ) {\n\t\tmigrateWarn(\"Can't change the 'type' of an input or button in IE 6/7/8\");\n\t}\n\n\t// Restore boolHook for boolean property/attribute synchronization\n\tif ( !jQuery.attrHooks[ lowerName ] && rboolean.test( lowerName ) ) {\n\t\tjQuery.attrHooks[ lowerName ] = {\n\t\t\tget: function( elem, name ) {\n\t\t\t\t// Align boolean attributes with corresponding properties\n\t\t\t\t// Fall back to attribute presence where some booleans are not supported\n\t\t\t\tvar attrNode,\n\t\t\t\t\tproperty = jQuery.prop( elem, name );\n\t\t\t\treturn property === true || typeof property !== \"boolean\" &&\n\t\t\t\t\t( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tundefined;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tvar propName;\n\t\t\t\tif ( value === false ) {\n\t\t\t\t\t// Remove boolean attributes when set to false\n\t\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\t} else {\n\t\t\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tif ( propName in elem ) {\n\t\t\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\t\t\telem[ propName ] = true;\n\t\t\t\t\t}\n\n\t\t\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t\t\t}\n\t\t\t\treturn name;\n\t\t\t}\n\t\t};\n\n\t\t// Warn only for attributes that can remain distinct from their properties post-1.9\n\t\tif ( ruseDefault.test( lowerName ) ) {\n\t\t\tmigrateWarn( \"jQuery.fn.attr('\" + lowerName + \"') might use property instead of attribute\" );\n\t\t}\n\t}\n\n\treturn oldAttr.call( jQuery, elem, name, value );\n};\n\n// attrHooks: value\njQuery.attrHooks.value = {\n\tget: function( elem, name ) {\n\t\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\t\tif ( nodeName === \"button\" ) {\n\t\t\treturn valueAttrGet.apply( this, arguments );\n\t\t}\n\t\tif ( nodeName !== \"input\" && nodeName !== \"option\" ) {\n\t\t\tmigrateWarn(\"jQuery.fn.attr('value') no longer gets properties\");\n\t\t}\n\t\treturn name in elem ?\n\t\t\telem.value :\n\t\t\tnull;\n\t},\n\tset: function( elem, value ) {\n\t\tvar nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n\t\tif ( nodeName === \"button\" ) {\n\t\t\treturn valueAttrSet.apply( this, arguments );\n\t\t}\n\t\tif ( nodeName !== \"input\" && nodeName !== \"option\" ) {\n\t\t\tmigrateWarn(\"jQuery.fn.attr('value', val) no longer sets properties\");\n\t\t}\n\t\t// Does not return so that setAttribute is also used\n\t\telem.value = value;\n\t}\n};\n\n\nvar matched, browser,\n\toldInit = jQuery.fn.init,\n\toldFind = jQuery.find,\n\toldParseJSON = jQuery.parseJSON,\n\trspaceAngle = /^\\s*</,\n\trattrHashTest = /\\[(\\s*[-\\w]+\\s*)([~|^$*]?=)\\s*([-\\w#]*?#[-\\w#]*)\\s*\\]/,\n\trattrHashGlob = /\\[(\\s*[-\\w]+\\s*)([~|^$*]?=)\\s*([-\\w#]*?#[-\\w#]*)\\s*\\]/g,\n\t// Note: XSS check is done below after string is trimmed\n\trquickExpr = /^([^<]*)(<[\\w\\W]+>)([^>]*)$/;\n\n// $(html) \"looks like html\" rule change\njQuery.fn.init = function( selector, context, rootjQuery ) {\n\tvar match, ret;\n\n\tif ( selector && typeof selector === \"string\" ) {\n\t\tif ( !jQuery.isPlainObject( context ) &&\n\t\t\t\t(match = rquickExpr.exec( jQuery.trim( selector ) )) && match[ 0 ] ) {\n\n\t\t\t// This is an HTML string according to the \"old\" rules; is it still?\n\t\t\tif ( !rspaceAngle.test( selector ) ) {\n\t\t\t\tmigrateWarn(\"$(html) HTML strings must start with '<' character\");\n\t\t\t}\n\t\t\tif ( match[ 3 ] ) {\n\t\t\t\tmigrateWarn(\"$(html) HTML text after last tag is ignored\");\n\t\t\t}\n\n\t\t\t// Consistently reject any HTML-like string starting with a hash (gh-9521)\n\t\t\t// Note that this may break jQuery 1.6.x code that otherwise would work.\n\t\t\tif ( match[ 0 ].charAt( 0 ) === \"#\" ) {\n\t\t\t\tmigrateWarn(\"HTML string cannot start with a '#' character\");\n\t\t\t\tjQuery.error(\"JQMIGRATE: Invalid selector string (XSS)\");\n\t\t\t}\n\n\t\t\t// Now process using loose rules; let pre-1.8 play too\n\t\t\t// Is this a jQuery context? parseHTML expects a DOM element (#178)\n\t\t\tif ( context && context.context && context.context.nodeType ) {\n\t\t\t\tcontext = context.context;\n\t\t\t}\n\n\t\t\tif ( jQuery.parseHTML ) {\n\t\t\t\treturn oldInit.call( this,\n\t\t\t\t\t\tjQuery.parseHTML( match[ 2 ], context && context.ownerDocument ||\n\t\t\t\t\t\t\tcontext || document, true ), context, rootjQuery );\n\t\t\t}\n\t\t}\n\t}\n\n\tret = oldInit.apply( this, arguments );\n\n\t// Fill in selector and context properties so .live() works\n\tif ( selector && selector.selector !== undefined ) {\n\t\t// A jQuery object, copy its properties\n\t\tret.selector = selector.selector;\n\t\tret.context = selector.context;\n\n\t} else {\n\t\tret.selector = typeof selector === \"string\" ? selector : \"\";\n\t\tif ( selector ) {\n\t\t\tret.context = selector.nodeType? selector : context || document;\n\t\t}\n\t}\n\n\treturn ret;\n};\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.find = function( selector ) {\n\tvar args = Array.prototype.slice.call( arguments );\n\n\t// Support: PhantomJS 1.x\n\t// String#match fails to match when used with a //g RegExp, only on some strings\n\tif ( typeof selector === \"string\" && rattrHashTest.test( selector ) ) {\n\n\t\t// The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0\n\t\t// First see if qS thinks it's a valid selector, if so avoid a false positive\n\t\ttry {\n\t\t\tdocument.querySelector( selector );\n\t\t} catch ( err1 ) {\n\n\t\t\t// Didn't *look* valid to qSA, warn and try quoting what we think is the value\n\t\t\tselector = selector.replace( rattrHashGlob, function( _, attr, op, value ) {\n\t\t\t\treturn \"[\" + attr + op + \"\\\"\" + value + \"\\\"]\";\n\t\t\t} );\n\n\t\t\t// If the regexp *may* have created an invalid selector, don't update it\n\t\t\t// Note that there may be false alarms if selector uses jQuery extensions\n\t\t\ttry {\n\t\t\t\tdocument.querySelector( selector );\n\t\t\t\tmigrateWarn( \"Attribute selector with '#' must be quoted: \" + args[ 0 ] );\n\t\t\t\targs[ 0 ] = selector;\n\t\t\t} catch ( err2 ) {\n\t\t\t\tmigrateWarn( \"Attribute selector with '#' was not fixed: \" + args[ 0 ] );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn oldFind.apply( this, args );\n};\n\n// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML)\nvar findProp;\nfor ( findProp in oldFind ) {\n\tif ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) {\n\t\tjQuery.find[ findProp ] = oldFind[ findProp ];\n\t}\n}\n\n// Let $.parseJSON(falsy_value) return null\njQuery.parseJSON = function( json ) {\n\tif ( !json ) {\n\t\tmigrateWarn(\"jQuery.parseJSON requires a valid JSON string\");\n\t\treturn null;\n\t}\n\treturn oldParseJSON.apply( this, arguments );\n};\n\njQuery.uaMatch = function( ua ) {\n\tua = ua.toLowerCase();\n\n\tvar match = /(chrome)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(webkit)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(msie) ([\\w.]+)/.exec( ua ) ||\n\t\tua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec( ua ) ||\n\t\t[];\n\n\treturn {\n\t\tbrowser: match[ 1 ] || \"\",\n\t\tversion: match[ 2 ] || \"0\"\n\t};\n};\n\n// Don't clobber any existing jQuery.browser in case it's different\nif ( !jQuery.browser ) {\n\tmatched = jQuery.uaMatch( navigator.userAgent );\n\tbrowser = {};\n\n\tif ( matched.browser ) {\n\t\tbrowser[ matched.browser ] = true;\n\t\tbrowser.version = matched.version;\n\t}\n\n\t// Chrome is Webkit, but Webkit is also Safari.\n\tif ( browser.chrome ) {\n\t\tbrowser.webkit = true;\n\t} else if ( browser.webkit ) {\n\t\tbrowser.safari = true;\n\t}\n\n\tjQuery.browser = browser;\n}\n\n// Warn if the code tries to get jQuery.browser\nmigrateWarnProp( jQuery, \"browser\", jQuery.browser, \"jQuery.browser is deprecated\" );\n\n// jQuery.boxModel deprecated in 1.3, jQuery.support.boxModel deprecated in 1.7\njQuery.boxModel = jQuery.support.boxModel = (document.compatMode === \"CSS1Compat\");\nmigrateWarnProp( jQuery, \"boxModel\", jQuery.boxModel, \"jQuery.boxModel is deprecated\" );\nmigrateWarnProp( jQuery.support, \"boxModel\", jQuery.support.boxModel, \"jQuery.support.boxModel is deprecated\" );\n\njQuery.sub = function() {\n\tfunction jQuerySub( selector, context ) {\n\t\treturn new jQuerySub.fn.init( selector, context );\n\t}\n\tjQuery.extend( true, jQuerySub, this );\n\tjQuerySub.superclass = this;\n\tjQuerySub.fn = jQuerySub.prototype = this();\n\tjQuerySub.fn.constructor = jQuerySub;\n\tjQuerySub.sub = this.sub;\n\tjQuerySub.fn.init = function init( selector, context ) {\n\t\tvar instance = jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t\treturn instance instanceof jQuerySub ?\n\t\t\tinstance :\n\t\t\tjQuerySub( instance );\n\t};\n\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\tvar rootjQuerySub = jQuerySub(document);\n\tmigrateWarn( \"jQuery.sub() is deprecated\" );\n\treturn jQuerySub;\n};\n\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\tmigrateWarn( \"jQuery.fn.size() is deprecated; use the .length property\" );\n\treturn this.length;\n};\n\n\nvar internalSwapCall = false;\n\n// If this version of jQuery has .swap(), don't false-alarm on internal uses\nif ( jQuery.swap ) {\n\tjQuery.each( [ \"height\", \"width\", \"reliableMarginRight\" ], function( _, name ) {\n\t\tvar oldHook = jQuery.cssHooks[ name ] && jQuery.cssHooks[ name ].get;\n\n\t\tif ( oldHook ) {\n\t\t\tjQuery.cssHooks[ name ].get = function() {\n\t\t\t\tvar ret;\n\n\t\t\t\tinternalSwapCall = true;\n\t\t\t\tret = oldHook.apply( this, arguments );\n\t\t\t\tinternalSwapCall = false;\n\t\t\t\treturn ret;\n\t\t\t};\n\t\t}\n\t});\n}\n\njQuery.swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\tif ( !internalSwapCall ) {\n\t\tmigrateWarn( \"jQuery.swap() is undocumented and deprecated\" );\n\t}\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\n// Ensure that $.ajax gets the new parseJSON defined in core.js\njQuery.ajaxSetup({\n\tconverters: {\n\t\t\"text json\": jQuery.parseJSON\n\t}\n});\n\n\nvar oldFnData = jQuery.fn.data;\n\njQuery.fn.data = function( name ) {\n\tvar ret, evt,\n\t\telem = this[0];\n\n\t// Handles 1.7 which has this behavior and 1.8 which doesn't\n\tif ( elem && name === \"events\" && arguments.length === 1 ) {\n\t\tret = jQuery.data( elem, name );\n\t\tevt = jQuery._data( elem, name );\n\t\tif ( ( ret === undefined || ret === evt ) && evt !== undefined ) {\n\t\t\tmigrateWarn(\"Use of jQuery.fn.data('events') is deprecated\");\n\t\t\treturn evt;\n\t\t}\n\t}\n\treturn oldFnData.apply( this, arguments );\n};\n\n\nvar rscriptType = /\\/(java|ecma)script/i;\n\n// Since jQuery.clean is used internally on older versions, we only shim if it's missing\nif ( !jQuery.clean ) {\n\tjQuery.clean = function( elems, context, fragment, scripts ) {\n\t\t// Set context per 1.8 logic\n\t\tcontext = context || document;\n\t\tcontext = !context.nodeType && context[0] || context;\n\t\tcontext = context.ownerDocument || context;\n\n\t\tmigrateWarn(\"jQuery.clean() is deprecated\");\n\n\t\tvar i, elem, handleScript, jsTags,\n\t\t\tret = [];\n\n\t\tjQuery.merge( ret, jQuery.buildFragment( elems, context ).childNodes );\n\n\t\t// Complex logic lifted directly from jQuery 1.8\n\t\tif ( fragment ) {\n\t\t\t// Special handling of each script element\n\t\t\thandleScript = function( elem ) {\n\t\t\t\t// Check if we consider it executable\n\t\t\t\tif ( !elem.type || rscriptType.test( elem.type ) ) {\n\t\t\t\t\t// Detach the script and store it in the scripts array (if provided) or the fragment\n\t\t\t\t\t// Return truthy to indicate that it has been handled\n\t\t\t\t\treturn scripts ?\n\t\t\t\t\t\tscripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :\n\t\t\t\t\t\tfragment.appendChild( elem );\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor ( i = 0; (elem = ret[i]) != null; i++ ) {\n\t\t\t\t// Check if we're done after handling an executable script\n\t\t\t\tif ( !( jQuery.nodeName( elem, \"script\" ) && handleScript( elem ) ) ) {\n\t\t\t\t\t// Append to fragment and handle embedded scripts\n\t\t\t\t\tfragment.appendChild( elem );\n\t\t\t\t\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\t\t\t// handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration\n\t\t\t\t\t\tjsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName(\"script\") ), handleScript );\n\n\t\t\t\t\t\t// Splice the scripts into ret after their former ancestor and advance our index beyond them\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t\ti += jsTags.length;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar eventAdd = jQuery.event.add,\n\teventRemove = jQuery.event.remove,\n\teventTrigger = jQuery.event.trigger,\n\toldToggle = jQuery.fn.toggle,\n\toldLive = jQuery.fn.live,\n\toldDie = jQuery.fn.die,\n\toldLoad = jQuery.fn.load,\n\tajaxEvents = \"ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess\",\n\trajaxEvent = new RegExp( \"\\\\b(?:\" + ajaxEvents + \")\\\\b\" ),\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+|)\\b/,\n\thoverHack = function( events ) {\n\t\tif ( typeof( events ) !== \"string\" || jQuery.event.special.hover ) {\n\t\t\treturn events;\n\t\t}\n\t\tif ( rhoverHack.test( events ) ) {\n\t\t\tmigrateWarn(\"'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'\");\n\t\t}\n\t\treturn events && events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n// Event props removed in 1.9, put them back if needed; no practical way to warn them\nif ( jQuery.event.props && jQuery.event.props[ 0 ] !== \"attrChange\" ) {\n\tjQuery.event.props.unshift( \"attrChange\", \"attrName\", \"relatedNode\", \"srcElement\" );\n}\n\n// Undocumented jQuery.event.handle was \"deprecated\" in jQuery 1.7\nif ( jQuery.event.dispatch ) {\n\tmigrateWarnProp( jQuery.event, \"handle\", jQuery.event.dispatch, \"jQuery.event.handle is undocumented and deprecated\" );\n}\n\n// Support for 'hover' pseudo-event and ajax event warnings\njQuery.event.add = function( elem, types, handler, data, selector ){\n\tif ( elem !== document && rajaxEvent.test( types ) ) {\n\t\tmigrateWarn( \"AJAX events should be attached to document: \" + types );\n\t}\n\teventAdd.call( this, elem, hoverHack( types || \"\" ), handler, data, selector );\n};\njQuery.event.remove = function( elem, types, handler, selector, mappedTypes ){\n\teventRemove.call( this, elem, hoverHack( types ) || \"\", handler, selector, mappedTypes );\n};\n\njQuery.each( [ \"load\", \"unload\", \"error\" ], function( _, name ) {\n\n\tjQuery.fn[ name ] = function() {\n\t\tvar args = Array.prototype.slice.call( arguments, 0 );\n\n\t\t// If this is an ajax load() the first arg should be the string URL;\n\t\t// technically this could also be the \"Anything\" arg of the event .load()\n\t\t// which just goes to show why this dumb signature has been deprecated!\n\t\t// jQuery custom builds that exclude the Ajax module justifiably die here.\n\t\tif ( name === \"load\" && typeof args[ 0 ] === \"string\" ) {\n\t\t\treturn oldLoad.apply( this, args );\n\t\t}\n\n\t\tmigrateWarn( \"jQuery.fn.\" + name + \"() is deprecated\" );\n\n\t\targs.splice( 0, 0, name );\n\t\tif ( arguments.length ) {\n\t\t\treturn this.bind.apply( this, args );\n\t\t}\n\n\t\t// Use .triggerHandler here because:\n\t\t// - load and unload events don't need to bubble, only applied to window or image\n\t\t// - error event should not bubble to window, although it does pre-1.7\n\t\t// See http://bugs.jquery.com/ticket/11820\n\t\tthis.triggerHandler.apply( this, args );\n\t\treturn this;\n\t};\n\n});\n\njQuery.fn.toggle = function( fn, fn2 ) {\n\n\t// Don't mess with animation or css toggles\n\tif ( !jQuery.isFunction( fn ) || !jQuery.isFunction( fn2 ) ) {\n\t\treturn oldToggle.apply( this, arguments );\n\t}\n\tmigrateWarn(\"jQuery.fn.toggle(handler, handler...) is deprecated\");\n\n\t// Save reference to arguments for access in closure\n\tvar args = arguments,\n\t\tguid = fn.guid || jQuery.guid++,\n\t\ti = 0,\n\t\ttoggler = function( event ) {\n\t\t\t// Figure out which function to execute\n\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t// Make sure that clicks stop\n\t\t\tevent.preventDefault();\n\n\t\t\t// and execute the function\n\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t};\n\n\t// link all the functions, so any of them can unbind this click handler\n\ttoggler.guid = guid;\n\twhile ( i < args.length ) {\n\t\targs[ i++ ].guid = guid;\n\t}\n\n\treturn this.click( toggler );\n};\n\njQuery.fn.live = function( types, data, fn ) {\n\tmigrateWarn(\"jQuery.fn.live() is deprecated\");\n\tif ( oldLive ) {\n\t\treturn oldLive.apply( this, arguments );\n\t}\n\tjQuery( this.context ).on( types, this.selector, data, fn );\n\treturn this;\n};\n\njQuery.fn.die = function( types, fn ) {\n\tmigrateWarn(\"jQuery.fn.die() is deprecated\");\n\tif ( oldDie ) {\n\t\treturn oldDie.apply( this, arguments );\n\t}\n\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\treturn this;\n};\n\n// Turn global events into document-triggered events\njQuery.event.trigger = function( event, data, elem, onlyHandlers  ){\n\tif ( !elem && !rajaxEvent.test( event ) ) {\n\t\tmigrateWarn( \"Global events are undocumented and deprecated\" );\n\t}\n\treturn eventTrigger.call( this,  event, data, elem || document, onlyHandlers  );\n};\njQuery.each( ajaxEvents.split(\"|\"),\n\tfunction( _, name ) {\n\t\tjQuery.event.special[ name ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\t// The document needs no shimming; must be !== for oldIE\n\t\t\t\tif ( elem !== document ) {\n\t\t\t\t\tjQuery.event.add( document, name + \".\" + jQuery.guid, function() {\n\t\t\t\t\t\tjQuery.event.trigger( name, Array.prototype.slice.call( arguments, 1 ), elem, true );\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( this, name, jQuery.guid++ );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( this !== document ) {\n\t\t\t\t\tjQuery.event.remove( document, name + \".\" + jQuery._data( this, name ) );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\t}\n);\n\njQuery.event.special.ready = {\n\tsetup: function() {\n\t\tif ( this === document ) {\n\t\t\tmigrateWarn( \"'ready' event is deprecated\" );\n\t\t}\n\t}\n};\n\nvar oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack,\n\toldFnFind = jQuery.fn.find;\n\njQuery.fn.andSelf = function() {\n\tmigrateWarn(\"jQuery.fn.andSelf() replaced by jQuery.fn.addBack()\");\n\treturn oldSelf.apply( this, arguments );\n};\n\njQuery.fn.find = function( selector ) {\n\tvar ret = oldFnFind.apply( this, arguments );\n\tret.context = this.context;\n\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\treturn ret;\n};\n\n\n// jQuery 1.6 did not support Callbacks, do not warn there\nif ( jQuery.Callbacks ) {\n\n\tvar oldDeferred = jQuery.Deferred,\n\t\ttuples = [\n\t\t\t// action, add listener, callbacks, .then handlers, final state\n\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"),\n\t\t\t\tjQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"),\n\t\t\t\tjQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\"),\n\t\t\t\tjQuery.Callbacks(\"memory\") ]\n\t\t];\n\n\tjQuery.Deferred = function( func ) {\n\t\tvar deferred = oldDeferred(),\n\t\t\tpromise = deferred.promise();\n\n\t\tdeferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\tvar fns = arguments;\n\n\t\t\tmigrateWarn( \"deferred.pipe() is deprecated\" );\n\n\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\tthis === promise ? newDefer.promise() : this,\n\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tfns = null;\n\t\t\t}).promise();\n\n\t\t};\n\n\t\tdeferred.isResolved = function() {\n\t\t\tmigrateWarn( \"deferred.isResolved is deprecated\" );\n\t\t\treturn deferred.state() === \"resolved\";\n\t\t};\n\n\t\tdeferred.isRejected = function() {\n\t\t\tmigrateWarn( \"deferred.isRejected is deprecated\" );\n\t\t\treturn deferred.state() === \"rejected\";\n\t\t};\n\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\treturn deferred;\n\t};\n\n}\n\n})( jQuery, window );\n\n","jquery/jquery.details.js":"/*! http://mths.be/details v0.0.6 by @mathias | includes http://mths.be/noselect v1.0.3 */\ndefine([\n    \"jquery\",\n    \"modernizr/modernizr.details\"\n], function($){\n\n    var proto = $.fn,\n        details,\n        // :'(\n        isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]',\n        // Feature test for native `<details>` support\n        isDetailsSupported = $('html').hasClass('details'),\n        toggleOpen = function($details, $detailsSummary, $detailsNotSummary, toggle) {\n            var isOpen = typeof $details.attr('open') == 'string',\n                close = isOpen && toggle || !isOpen && !toggle;\n            if (close) {\n                $details.removeClass('open').prop('open', false).triggerHandler('close.details');\n                $detailsSummary.attr('aria-expanded', false);\n                $detailsNotSummary.hide();\n            } else {\n                $details.addClass('open').prop('open', true).triggerHandler('open.details');\n                $detailsSummary.attr('aria-expanded', true);\n                $detailsNotSummary.show();\n            }\n        };\n\n    /* http://mths.be/noselect v1.0.3 */\n    proto.noSelect = function() {\n\n        // Since the string 'none' is used three times, storing it in a variable gives better results after minification\n        var none = 'none';\n\n        // onselectstart and ondragstart for WebKit & IE\n        // onmousedown for WebKit & Opera\n        return this.bind('selectstart dragstart mousedown', function() {\n            return false;\n        }).css({\n            'MozUserSelect': none,\n            'msUserSelect': none,\n            'webkitUserSelect': none,\n            'userSelect': none\n        });\n\n    };\n\n    // Execute the fallback only if there\u2019s no native `details` support\n    if (isDetailsSupported) {\n        details = proto.details = function() {\n\n            return this.each(function() {\n                var $details = $(this),\n                    $summary = $('summary', $details).first();\n                $summary.attr({\n                    'role': 'button',\n                    'aria-expanded': $details.prop('open')\n                }).on('click.xxx', function() {\n                    // the value of the `open` property is the old value\n                    var close = $details.prop('open');\n                    $summary.attr('aria-expanded', !close);\n                    $details.triggerHandler((close ? 'close' : 'open') + '.details');\n                });\n            });\n\n        };\n\n        details.support = isDetailsSupported;\n\n    } else {\n        details = proto.details = function() {\n\n            // Loop through all `details` elements\n            return this.each(function() {\n\n                // Store a reference to the current `details` element in a variable\n                var $details = $(this),\n                    // Store a reference to the `summary` element of the current `details` element (if any) in a variable\n                    $detailsSummary = $('summary', $details).first(),\n                    // Do the same for the info within the `details` element\n                    $detailsNotSummary = $details.children(':not(summary)'),\n                    // This will be used later to look for direct child text nodes\n                    $detailsNotSummaryContents = $details.contents(':not(summary)');\n\n                // If there is no `summary` in the current `details` element\u2026\n                if (!$detailsSummary.length) {\n                    // \u2026create one with default text\n                    $detailsSummary = $('<summary>').text($.mage.__('Details')).prependTo($details);\n                }\n\n                // Look for direct child text nodes\n                if ($detailsNotSummary.length != $detailsNotSummaryContents.length) {\n                    // Wrap child text nodes in a `span` element\n                    $detailsNotSummaryContents.filter(function() {\n                        // Only keep the node in the collection if it\u2019s a text node containing more than only whitespace\n                        // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#space-character\n                        return this.nodeType == 3 && /[^ \\t\\n\\f\\r]/.test(this.data);\n                    }).wrap('<span>');\n                    // There are now no direct child text nodes anymore \u2014 they\u2019re wrapped in `span` elements\n                    $detailsNotSummary = $details.children(':not(summary)');\n                }\n\n                // Hide content unless there\u2019s an `open` attribute\n                toggleOpen($details, $detailsSummary, $detailsNotSummary);\n\n                // Add `role=button` and set the `tabindex` of the `summary` element to `0` to make it keyboard accessible\n                $detailsSummary.attr('role', 'button').noSelect().prop('tabIndex', 0).off('click').on('click.details', function() {\n                    // Focus on the `summary` element\n                    $detailsSummary.focus();\n                    // Toggle the `open` and `aria-expanded` attributes and the `open` property of the `details` element and display the additional info\n                    toggleOpen($details, $detailsSummary, $detailsNotSummary, true);\n                }).keyup(function(event) {\n                    if (32 == event.keyCode || (13 == event.keyCode && !isOpera)) {\n                        // Space or Enter is pressed \u2014 trigger the `click` event on the `summary` element\n                        // Opera already seems to trigger the `click` event when Enter is pressed\n                        event.preventDefault();\n                        $detailsSummary.click();\n                    }\n                });\n\n            });\n\n        };\n\n        details.support = isDetailsSupported;\n\n    }\n\n});\n"}
}});