Spamworldpro Mini Shell
Spamworldpro


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

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/corals/cartforge.co/pub/static/adminhtml/Magento/backend/en_US/js/bundle/bundle2.js
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*/\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget',\n    'jquery-ui-modules/datepicker',\n    'jquery-ui-modules/timepicker'\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                                    '\" data-date=\"' + printDate.getDate() + '\" href=\"#\">' +\n                                        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            .trigger('blur').trigger('change');\n    };\n\n    return {\n        dateRange:  $.mage.dateRange,\n        calendar:   $.mage.calendar\n    };\n});\n","mage/multiselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'jquery',\n    'text!mage/multiselect.html',\n    'Magento_Ui/js/modal/alert',\n    'jquery-ui-modules/widget',\n    'jquery/editableMultiselect/js/jquery.multiselect'\n], function (_, $, searchTemplate, alert) {\n    'use strict';\n\n    $.widget('mage.multiselect2', {\n        options: {\n            mselectContainer: 'section.mselect-list',\n            mselectItemsWrapperClass: 'mselect-items-wrapper',\n            mselectCheckedClass: 'mselect-checked',\n            containerClass: 'paginated',\n            searchInputClass: 'admin__action-multiselect-search',\n            selectedItemsCountClass: 'admin__action-multiselect-items-selected',\n            currentPage: 1,\n            lastAppendValue: 0,\n            updateDelay: 1000,\n            optionsLoaded: false\n        },\n\n        /** @inheritdoc */\n        _create: function () {\n            $.fn.multiselect.call(this.element, this.options);\n        },\n\n        /** @inheritdoc */\n        _init: function () {\n            this.domElement = this.element.get(0);\n\n            this.$container = $(this.options.mselectContainer);\n            this.$wrapper = this.$container.find('.' + this.options.mselectItemsWrapperClass);\n            this.$item = this.$wrapper.find('div').first();\n            this.selectedValues = [];\n            this.values = {};\n\n            this.$container.addClass(this.options.containerClass).prepend(searchTemplate);\n            this.$input = this.$container.find('.' + this.options.searchInputClass);\n            this.$selectedCounter = this.$container.find('.' + this.options.selectedItemsCountClass);\n            this.filter = '';\n\n            if (this.domElement.options.length) {\n                this._setLastAppendOption(this.domElement.options[this.domElement.options.length - 1].value);\n            }\n\n            this._initElement();\n            this._events();\n        },\n\n        /**\n         * Leave only saved/selected options in select element.\n         *\n         * @private\n         */\n        _initElement: function () {\n            this.element.empty();\n            _.each(this.options.selectedValues, function (value) {\n                this._createSelectedOption({\n                    value: value,\n                    label: value\n                });\n            }, this);\n        },\n\n        /**\n         * Attach required events.\n         *\n         * @private\n         */\n        _events: function () {\n            var onKeyUp = _.debounce(this.onKeyUp, this.options.updateDelay);\n\n            _.bindAll(this, 'onScroll', 'onCheck', 'onOptionsChange');\n\n            this.$wrapper.on('scroll', this.onScroll);\n            this.$wrapper.on('change.mselectCheck', '[type=checkbox]', this.onCheck);\n            this.$input.on('keyup', _.bind(onKeyUp, this));\n            this.element.on('change.hiddenSelect', this.onOptionsChange);\n        },\n\n        /**\n         * Behaves multiselect scroll.\n         */\n        onScroll: function () {\n            var height = this.$wrapper.height(),\n                scrollHeight = this.$wrapper.prop('scrollHeight'),\n                scrollTop = Math.ceil(this.$wrapper.prop('scrollTop'));\n\n            if (!this.options.optionsLoaded && scrollHeight - height <= scrollTop) {\n                this.loadOptions();\n            }\n        },\n\n        /**\n         * Behaves keyup event on input search\n         */\n        onKeyUp: function () {\n            if (this.getSearchCriteria() === this.filter) {\n                return false;\n            }\n\n            this.setFilter();\n            this.clearMultiselectOptions();\n            this.setCurrentPage(0);\n            this.loadOptions();\n        },\n\n        /**\n         * Callback for select change event\n         */\n        onOptionsChange: function () {\n            this.selectedValues = _.map(this.domElement.options, function (option) {\n                this.values[option.value] = true;\n\n                return option.value;\n            }, this);\n\n            this._updateSelectedCounter();\n        },\n\n        /**\n         * Overrides native check behaviour.\n         *\n         * @param {Event} event\n         */\n        onCheck: function (event) {\n            var checkbox = event.target,\n                option = {\n                    value: checkbox.value,\n                    label: $(checkbox).parent('label').text()\n                };\n\n            checkbox.checked ? this._createSelectedOption(option) : this._removeSelectedOption(option);\n            event.stopPropagation();\n        },\n\n        /**\n         * Show error message.\n         *\n         * @param {String} message\n         */\n        onError: function (message) {\n            alert({\n                content: message\n            });\n        },\n\n        /**\n         * Updates current filter state.\n         */\n        setFilter: function () {\n            this.filter = this.getSearchCriteria() || '';\n        },\n\n        /**\n         * Reads search input value.\n         *\n         * @return {String}\n         */\n        getSearchCriteria: function () {\n            return this.$input.val().trim();\n        },\n\n        /**\n         * Load options data.\n         */\n        loadOptions: function () {\n            var nextPage = this.getCurrentPage() + 1;\n\n            this.$wrapper.trigger('processStart');\n            this.$input.prop('disabled', true);\n\n            $.get(this.options.nextPageUrl, {\n                p: nextPage,\n                s: this.filter\n            })\n            .done(function (response) {\n                if (response.success) {\n                    this.appendOptions(response.result);\n                    this.setCurrentPage(nextPage);\n                } else {\n                    this.onError(response.errorMessage);\n                }\n            }.bind(this))\n            .always(function () {\n                this.$wrapper.trigger('processStop');\n                this.$input.prop('disabled', false);\n\n                if (this.filter) {\n                    this.$input.focus();\n                }\n            }.bind(this));\n        },\n\n        /**\n         * Append loaded options\n         *\n         * @param {Array} options\n         */\n        appendOptions: function (options) {\n            var divOptions = [];\n\n            if (!options.length) {\n                return false;\n            }\n\n            if (this.isOptionsLoaded(options)) {\n                return;\n            }\n\n            options.forEach(function (option) {\n                if (!this.values[option.value]) {\n                    this.values[option.value] = true;\n                    option.selected = this._isOptionSelected(option);\n                    divOptions.push(this._createMultiSelectOption(option));\n                    this._setLastAppendOption(option.value);\n                }\n            }, this);\n\n            this.$wrapper.append(divOptions);\n        },\n\n        /**\n         * Clear multiselect options\n         */\n        clearMultiselectOptions: function () {\n            this._setLastAppendOption(0);\n            this.values = {};\n            this.$wrapper.empty();\n        },\n\n        /**\n         * Checks if all options are already loaded\n         *\n         * @return {Boolean}\n         */\n        isOptionsLoaded: function (options) {\n            this.options.optionsLoaded = this.options.lastAppendValue === options[options.length - 1].value;\n\n            return this.options.optionsLoaded;\n        },\n\n        /**\n         * Setter for current page.\n         *\n         * @param {Number} page\n         */\n        setCurrentPage: function (page) {\n            this.options.currentPage = page;\n        },\n\n        /**\n         * Getter for current page.\n         *\n         * @return {Number}\n         */\n        getCurrentPage: function () {\n            return this.options.currentPage;\n        },\n\n        /**\n         * Creates new selected option for select element\n         *\n         * @param {Object} option - option object\n         * @param {String} option.value - option value\n         * @param {String} option.label - option label\n         * @private\n         */\n        _createSelectedOption: function (option) {\n            var selectOption = new Option(option.label, option.value, false, true);\n\n            this.element.append(selectOption);\n            this.selectedValues.push(option.value);\n            this._updateSelectedCounter();\n\n            return selectOption;\n        },\n\n        /**\n         * Remove passed option from select element\n         *\n         * @param {Object} option - option object\n         * @param {String} option.value - option value\n         * @param {String} option.label - option label\n         * @return {Object} option\n         * @private\n         */\n        _removeSelectedOption: function (option) {\n            var unselectedOption = _.findWhere(this.domElement.options, {\n                value: option.value\n            });\n\n            if (!_.isUndefined(unselectedOption)) {\n                this.domElement.remove(unselectedOption.index);\n                this.selectedValues.splice(_.indexOf(this.selectedValues, option.value), 1);\n                this._updateSelectedCounter();\n            }\n\n            return unselectedOption;\n        },\n\n        /**\n         * Creates new DIV option for multiselect widget\n         *\n         * @param {Object} option - option object\n         * @param {String} option.value - option value\n         * @param {String} option.label - option label\n         * @param {Boolean} option.selected - is option selected\n         * @private\n         */\n        _createMultiSelectOption: function (option) {\n            var item = this.$item.clone(),\n                checkbox = item.find('input'),\n                isSelected = !!option.selected;\n\n            checkbox.val(option.value)\n                .prop('checked', isSelected)\n                .toggleClass(this.options.mselectCheckedClass, isSelected);\n\n            item.find('label > span').text(option.label);\n\n            return item;\n        },\n\n        /**\n         * Checks if passed option should be selected\n         *\n         * @param {Object} option - option object\n         * @param {String} option.value - option value\n         * @param {String} option.label - option label\n         * @param {Boolean} option.selected - is option selected\n         * @return {Boolean}\n         * @private\n         */\n        _isOptionSelected: function (option) {\n            return !!~this.selectedValues.indexOf(option.value);\n        },\n\n        /**\n         * Saves last added option value.\n         *\n         * @param {Number} value\n         * @private\n         */\n        _setLastAppendOption: function (value) {\n            this.options.lastAppendValue = value;\n        },\n\n        /**\n         * Updates counter of selected items.\n         *\n         * @private\n         */\n        _updateSelectedCounter: function () {\n            this.$selectedCounter.text(this.selectedValues.length);\n        }\n    });\n\n    return $.mage.multiselect2;\n});\n","mage/polyfill.js":"(function (root, doc) {\n    'use strict';\n\n    var Storage;\n\n    try {\n        if (!root.localStorage || !root.sessionStorage) {\n            throw new Error();\n        }\n\n        localStorage.setItem('storage_test', 1);\n        localStorage.removeItem('storage_test');\n    } catch (e) {\n        /**\n         * Returns a storage object to shim local or sessionStorage\n         * @param {String} type - either 'local' or 'session'\n         */\n        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                doc.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 = doc.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 (!root.name) {\n                    root.name = new Date().getTime();\n                }\n\n                return 'sessionStorage' + root.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        root.localStorage.prototype = root.localStorage = new Storage('local');\n        root.sessionStorage.prototype = root.sessionStorage = new Storage('session');\n    }\n})(window, document);\n","mage/accordion.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/tabs'\n], function ($, tabs) {\n    'use strict';\n\n    $.widget('mage.accordion', tabs, {\n        options: {\n            active: [0],\n            multipleCollapsible: false,\n            openOnFocus: false\n        },\n\n        /**\n         * @private\n         */\n        _callCollapsible: function () {\n            var self = this,\n                disabled = false,\n                active = false;\n\n            if (typeof this.options.active === 'string') {\n                this.options.active = this.options.active.split(' ').map(function (item) {\n                    return parseInt(item, 10);\n                });\n            }\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 ($.inArray(i, self.options.active) !== -1) {\n                    active = true;\n                }\n                self._instantiateCollapsible(this, i, active, disabled);\n            });\n        },\n\n        /**\n         * Overwrites default functionality to provide the option to activate/deactivate multiple sections simultaneous\n         * @param {*} action\n         * @param {*} index\n         * @private\n         */\n        _toggleActivate: function (action, index) {\n            var self = this;\n\n            if (Array.isArray(index && this.options.multipleCollapsible)) {\n                $.each(index, function () {\n                    self.collapsibles.eq(this).collapsible(action);\n                });\n            } else if (index === undefined && this.options.multipleCollapsible) {\n                this.collapsibles.collapsible(action);\n            } else {\n                this._super(action, index);\n            }\n        },\n\n        /**\n         * If the Accordion allows multiple section to be active at the same time, if deep linking is used\n         * sections that don't contain the id from anchor shouldn't be closed, otherwise the accordion uses the\n         * tabs behavior\n         * @private\n         */\n        _handleDeepLinking: function () {\n            if (!this.options.multipleCollapsible) {\n                this._super();\n            }\n        },\n\n        /**\n         * Prevent default behavior that closes the other sections when one gets activated if the Accordion allows\n         * multiple sections simultaneous\n         * @private\n         */\n        _closeOthers: function () {\n            var self = this;\n\n            if (!this.options.multipleCollapsible) {\n                $.each(this.collapsibles, function () {\n                    $(this).on('beforeOpen', function () {\n                        self.collapsibles.not(this).collapsible('deactivate');\n                    });\n                });\n            }\n            $.each(this.collapsibles, function () {\n                $(this).on('beforeOpen', function () {\n                    var section = $(this);\n\n                    section.addClass('allow').prevAll().addClass('allow');\n                    section.nextAll().removeClass('allow');\n                });\n            });\n        }\n    });\n\n    return $.mage.accordion;\n});\n","mage/bootstrap.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/apply/main',\n    'Magento_Ui/js/lib/knockout/bootstrap'\n], function ($, mage) {\n    'use strict';\n\n    $.ajaxSetup({\n        cache: false\n    });\n\n    /**\n     * Init all components defined via data-mage-init attribute.\n     * Execute in a separate task to prevent main thread blocking.\n     */\n    setTimeout(mage.apply);\n});\n","mage/template.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    /**\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/translate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/mage',\n    'mageTranslationDictionary',\n    'underscore'\n], function ($, mage, dictionary, _) {\n    'use strict';\n\n    $.extend(true, $, {\n        mage: {\n            translate: (function () {\n                /**\n                 * Key-value translations storage\n                 * @type {Object}\n                 * @private\n                 */\n                var _data = dictionary;\n\n                return {\n                    /**\n                     * Add new translation (two string parameters) or several translations (object)\n                     */\n                    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                    translate: function (text) {\n                        return typeof _data[text] !== 'undefined' ? _data[text] : text;\n                    }\n                };\n            }())\n        }\n    });\n    $.mage.__ = $.proxy($.mage.translate.translate, $.mage.translate);\n\n    // Provide i18n wrapper to be used in underscore templates for translation\n    _.extend(_, {\n        /**\n         * Make a translation using $.mage.__\n         *\n         * @param {String} text\n         * @return {String}\n         */\n        i18n: function (text) {\n            return $.mage.__(text);\n        }\n    });\n\n    return $.mage.__;\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-modules/widget',\n    'jquery/ui-modules/widgets/tabs',\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 || $(this).find('#' + anchorId).length) {\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            var isNotNested = this._isNotNested.bind(this);\n\n            this.contents = this.element\n                .find(this.options.content)\n                .filter(isNotNested);\n\n            this.collapsibles =  this.element\n                .find(this.options.collapsibleElement)\n                .filter(isNotNested);\n\n            this.collapsibles\n                .attr('role', 'presentation')\n                .parent()\n                .attr('role', 'tablist');\n\n            this.headers = this.element\n                .find(this.options.header)\n                .filter(isNotNested);\n\n            if (this.headers.length === 0) {\n                this.headers = this.collapsibles;\n            }\n            this.triggers = this.element\n                .find(this.options.trigger)\n                .filter(isNotNested);\n\n            if (this.triggers.length === 0) {\n                this.triggers = this.headers;\n            }\n            this._callCollapsible();\n        },\n\n        /**\n         * Checks if element is not in nested container to keep the correct scope of collapsible\n         * @param {Number} index\n         * @param {HTMLElement} element\n         * @private\n         * @return {Boolean}\n         */\n        _isNotNested: function (index, element) {\n            var parentContent = $(element).parents(this.options.content);\n\n            return !parentContent.length || !this.element.find(parentContent).length;\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 (Array.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/popup-window.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.popupWindow', {\n        options: {\n            centerBrowser: 0, // center window over browser window? {1 (YES) or 0 (NO)}. overrides top and left\n            centerScreen: 0, // center window over entire screen? {1 (YES) or 0 (NO)}. overrides top and left\n            height: 500, // sets the height in pixels of the window.\n            left: 0, // left position when the window appears.\n            location: 0, // determines whether the address bar is displayed {1 (YES) or 0 (NO)}.\n            menubar: 0, // determines whether the menu bar is displayed {1 (YES) or 0 (NO)}.\n            resizable: 0, // whether the window can be resized {1 (YES) or 0 (NO)}.\n            scrollbars: 0, // determines whether scrollbars appear on the window {1 (YES) or 0 (NO)}.\n            status: 0, // whether a status line appears at the bottom of the window {1 (YES) or 0 (NO)}.\n            width: 500, // sets the width in pixels of the window.\n            windowName: null, // name of window set from the name attribute of the element that invokes the click\n            windowURL: null, // url used for the popup\n            top: 0, // top position when the window appears.\n            toolbar: 0 // determines whether a toolbar is displayed {1 (YES) or 0 (NO)}.\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            this.element.on('click', $.proxy(this._openPopupWindow, this));\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _openPopupWindow: function (event) {\n            var element = $(event.target),\n                settings = this.options,\n                windowFeatures =\n                    'height=' + settings.height +\n                        ',width=' + settings.width +\n                        ',toolbar=' + settings.toolbar +\n                        ',scrollbars=' + settings.scrollbars +\n                        ',status=' + settings.status +\n                        ',resizable=' + settings.resizable +\n                        ',location=' + settings.location +\n                        ',menuBar=' + settings.menubar,\n                centeredX,\n                centeredY;\n\n            settings.windowName = settings.windowName || element.attr('name');\n            settings.windowURL = settings.windowURL || element.attr('href');\n\n            if (settings.centerBrowser) {\n                centeredY = window.screenY + (window.outerHeight / 2 - settings.height / 2);\n                centeredX = window.screenX + (window.outerWidth / 2 - settings.width / 2);\n                windowFeatures += ',left=' + centeredX + ',top=' + centeredY;\n            } else if (settings.centerScreen) {\n                centeredY = (screen.height - settings.height) / 2;\n                centeredX = (screen.width - settings.width) / 2;\n                windowFeatures += ',left=' + centeredX + ',top=' + centeredY;\n            } else {\n                windowFeatures += ',left=' + settings.left + ',top=' + settings.top;\n            }\n\n            window.open(settings.windowURL, settings.windowName, windowFeatures).focus();\n            event.preventDefault();\n        }\n    });\n\n    return $.mage.popupWindow;\n});\n","mage/loader_old.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-modules/widget',\n    'mage/translate'\n], function ($, mageTemplate) {\n    'use strict';\n\n    $.widget('mage.loader', {\n        loaderStarted: 0,\n        spinner: $(undefined),\n        options: {\n            icon: '',\n            texts: {\n                loaderText: $.mage.__('Please wait...'),\n                imgAlt: $.mage.__('Loading...')\n            },\n            template: '<div class=\"loading-mask\" data-role=\"loader\">' +\n                '<div class=\"popup popup-loading\">' +\n                '<div class=\"popup-inner\">' +\n                '<% if (data.icon) { %>' +\n                    '<img ' +\n                        '<% if (data.texts.imgAlt) { %>alt=\"<%- data.texts.imgAlt %>\"<% } %> ' +\n                        'src=\"<%- data.icon %>\"><% } %>' +\n                '<% if (data.texts.loaderText) { %><%- data.texts.loaderText %><% } %>' +\n                '</div>' +\n                '</div>' +\n                '</div>'\n        },\n\n        /**\n         * Loader creation\n         * @protected\n         */\n        _create: function () {\n            this._bind();\n        },\n\n        /**\n         * Bind on ajax events\n         * @protected\n         */\n        _bind: function () {\n            this._on({\n                'processStop': 'hide',\n                'processStart': 'show',\n                'show.loader': 'show',\n                'hide.loader': 'hide',\n                'contentUpdated.loader': '_contentUpdated'\n            });\n        },\n\n        /**\n         * Verify loader present after content updated\n         *\n         * This will be cleaned up by the task MAGETWO-11070\n         *\n         * @param {jQuery.Event} e\n         * @private\n         */\n        _contentUpdated: function (e) {\n            this.show(e);\n        },\n\n        /**\n         * Show loader\n         */\n        show: function (e, ctx) {\n            this._render();\n            this.loaderStarted++;\n            this.spinner.show();\n\n            if (ctx) {\n                this.spinner\n                    .css({\n                        width: ctx.outerWidth(),\n                        height: ctx.outerHeight(),\n                        position: 'absolute'\n                    })\n                    .position({\n                        my: 'top left',\n                        at: 'top left',\n                        of: ctx\n                    });\n            }\n\n            return false;\n        },\n\n        /**\n         * Hide loader\n         */\n        hide: function () {\n            if (this.loaderStarted > 0) {\n                this.loaderStarted--;\n\n                if (this.loaderStarted === 0) {\n                    this.spinner.hide();\n                }\n            }\n\n            return false;\n        },\n\n        /**\n         * Render loader\n         * @protected\n         */\n        _render: function () {\n            var tmpl;\n\n            if (this.spinner.length === 0) {\n                tmpl = mageTemplate(this.options.template, {\n                    data: this.options\n                });\n\n                this.spinner = $(tmpl);\n            }\n\n            this.element.prepend(this.spinner);\n        },\n\n        /**\n         * Destroy loader\n         */\n        _destroy: function () {\n            this.spinner.remove();\n        }\n    });\n\n    /**\n     * This widget takes care of registering the needed loader listeners on the body\n     */\n    $.widget('mage.loaderAjax', {\n        options: {\n            defaultContainer: '[data-container=body]'\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            this._bind();\n            // There should only be one instance of this widget, and it should be attached\n            // to the body only. Having it on the page twice will trigger multiple processStarts.\n            if (window.console && !this.element.is(this.options.defaultContainer) && $.mage.isDevMode(undefined)) {\n                console.warn('This widget is intended to be attached to the body, not below.');\n            }\n        },\n\n        /**\n         * @private\n         */\n        _bind: function () {\n            $(document).on({\n                'ajaxSend': this._onAjaxSend.bind(this),\n                'ajaxComplete': this._onAjaxComplete.bind(this)\n            });\n        },\n\n        /**\n         * @param {Object} loaderContext\n         * @return {*}\n         * @private\n         */\n        _getJqueryObj: function (loaderContext) {\n            var ctx;\n\n            // Check to see if context is jQuery object or not.\n            if (loaderContext) {\n                if (loaderContext.jquery) {\n                    ctx = loaderContext;\n                } else {\n                    ctx = $(loaderContext);\n                }\n            } else {\n                ctx = $('[data-container=\"body\"]');\n            }\n\n            return ctx;\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @param {Object} jqxhr\n         * @param {Object} settings\n         * @private\n         */\n        _onAjaxSend: function (e, jqxhr, settings) {\n            var ctx;\n\n            if (settings && settings.showLoader) {\n                ctx = this._getJqueryObj(settings.loaderContext);\n                ctx.trigger('processStart');\n\n                // Check to make sure the loader is there on the page if not report it on the console.\n                // NOTE that this check should be removed before going live. It is just an aid to help\n                // in finding the uses of the loader that maybe broken.\n                if (window.console && !ctx.parents('[data-role=\"loader\"]').length) {\n                    console.warn('Expected to start loader but did not find one in the dom');\n                }\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @param {Object} jqxhr\n         * @param {Object} settings\n         * @private\n         */\n        _onAjaxComplete: function (e, jqxhr, settings) {\n            if (settings && settings.showLoader && !settings.dontHide) {\n                this._getJqueryObj(settings.loaderContext).trigger('processStop');\n            }\n        }\n    });\n\n    return {\n        loader: $.mage.loader,\n        loaderAjax: $.mage.loaderAjax\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/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 compatibility 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/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        $(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.sortedRegions = this.getSortedRegions();\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, selectElement, def, regionId, region;\n\n            selectElement = this.regionSelectEl;\n\n            if (this.sortedRegions[this.countryEl.value]) {\n                if (this.lastCountryId != this.countryEl.value) { //eslint-disable-line eqeqeq\n                    def = selectElement.getAttribute('defaultValue');\n\n                    if (this.regionTextEl) {\n                        if (!def) {\n                            def = this.regionTextEl.value.toLowerCase();\n                        }\n                        this.regionTextEl.value = '';\n                    }\n\n                    selectElement.options.length = 1;\n\n                    this.sortedRegions[this.countryEl.value].forEach(function (item) {\n                        regionId = item[0];\n                        region = item[1];\n\n                        option = document.createElement('OPTION');\n                        option.value = regionId;\n                        option.text = region.name.stripTags();\n                        option.title = region.name;\n\n                        if (selectElement.options.add) {\n                            selectElement.options.add(option);\n                        } else {\n                            selectElement.appendChild(option);\n                        }\n\n                        if (regionId == def || region.name.toLowerCase() == def || region.code.toLowerCase() == def) { //eslint-disable-line\n                            selectElement.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         * Sort regions from JSON by name\n         *\n         * @returns {*[]}\n         */\n        getSortedRegions: function () {\n            var country, regionsEntries, regionsByCountry;\n\n            regionsByCountry = [];\n\n            for (country in this.regions) { //eslint-disable-line guard-for-in\n                regionsEntries = Object.entries(this.regions[country]);\n                regionsEntries.sort(function (a, b) {\n                    return a[1].name > b[1].name ? 1 : -1;\n                });\n\n                regionsByCountry[country] = regionsEntries;\n            }\n\n            return regionsByCountry;\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, targetArray, isChooser;\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 = jQuery('#' + idTo + '-head');\n            isInheritCheckboxChecked = $(idTo + '_inherit') && $(idTo + '_inherit').checked;\n            target = $(idTo);\n\n            // Account for the chooser style parameters.\n            if (target === null && headElement.length === 0 && idTo.substring(0, 16) === 'options_fieldset') {\n                targetArray = $$('input[id*=\"' + idTo + '\"]');\n                isChooser = true;\n\n                if (targetArray !== null && targetArray.length > 0) {\n                    target = targetArray[0];\n                }\n                headElement = jQuery('.field-' + idTo).add('.field-chooser' + idTo);\n            }\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                            !item.getAttribute('readonly') || isChooser //eslint-disable-line\n                        ) {\n                            item.disabled = false;\n                            jQuery(item).removeClass('ignore-validate');\n                        }\n                    });\n                }\n\n                if (headElement.length > 0) {\n                    headElement.show();\n\n                    if (headElement.hasClass('open') && target) {\n                        target.show();\n                    } else if (target) {\n                        target.hide();\n                    }\n                } else {\n                    if (target) {\n                        target.show();\n                        headElement = jQuery('.field-' + idTo).add('.field-chooser' + idTo);\n                        headElement.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.length > 0) {\n                    headElement.hide();\n                } else {\n                    headElement = jQuery('.field-' + idTo).add('.field-chooser' + idTo);\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/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/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            this.hidePopups();\n            this.showPopup('backup-options');\n\n            if (this.type === 'snapshot') {\n                jQuery('#exclude-media-checkbox-container').removeClass('no-display');\n            }\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></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/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            this.targetElement = undefined;\n            this.filterKeyPressCallback = false;\n\n            this.reloadParams = false;\n\n            this.trOnMouseOver = this.rowMouseOver.bindAsEventListener(this);\n            this.trOnMouseOut = this.rowMouseOut.bindAsEventListener(this);\n            this.trOnMouseDown = this.rowMouseDown.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], 'mousedown', this.trOnMouseDown);\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                } 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        rowMouseDown: function (event) {\n            this.targetElement = event.target;\n        },\n\n        /**\n         * @param {*} event\n         */\n        rowMouseClick: function (event) {\n            if (this.rowClickCallback) {\n                try {\n                    this.rowClickCallback(this, event);\n                } catch (e) {\n                }\n            }\n            varienGlobalEvents.fireEvent('gridRowClick', event);\n            this.targetElement = undefined;\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        /**\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         * Builds the form with fields containing the and submits\n         *\n         * @param {String} url\n         * @param {String} varName\n         * @param {String} varValue\n         * @private\n         */\n        _buildFormAndSubmit: function (url, varName, varValue) {\n            var re = new RegExp('\\/(' + varName + '\\/.*?\\/)'),\n                parts = url.split(new RegExp('\\\\?')),\n                form = jQuery('<form></form>'),\n                inputProps = [\n                    {\n                        name: varName,\n                        value: varValue\n                    },\n                    {\n                        name: 'form_key',\n                        value: window.FORM_KEY\n                    }\n                ],\n                input;\n\n            url = parts[0].replace(re, '/');\n\n            if (parts.size() > 1) {\n                url += '?' + parts[1];\n            }\n\n            form.attr('action', url);\n            form.attr('method', 'POST');\n\n            inputProps.forEach(function (item) {\n                input = jQuery('<input/>');\n                input.attr('name', item.name);\n                input.attr('type', 'hidden');\n                input.val(item.value);\n                form.append(input);\n            });\n            jQuery('[data-container=\"body\"]').append(form);\n            form.submit();\n            form.remove();\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                    this._buildFormAndSubmit(\n                        exportUrl,\n                        this.massaction.formFieldNameInternal,\n                        this.massaction.checkedString\n                    );\n                } else {\n                    location.href = exportUrl;\n                }\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            // eslint-disable-next-line jquery-no-input-event-shorthand\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                    },\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            if (this.filterKeyPressCallback) {\n                this.filterKeyPressCallback(this, event);\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         * @param {*} lastId\n         */\n        inputPage: function (event, lastId) {\n            var element = Event.element(event),\n                keyCode = event.keyCode || event.which,\n                enteredValue = parseInt(element.value, 10),\n                pageId = parseInt(lastId, 10);\n\n            if (keyCode == Event.KEY_RETURN) { //eslint-disable-line eqeqeq\n                if (enteredValue > pageId) {\n                    this.setPage(pageId);\n                } else {\n                    this.setPage(enteredValue);\n                }\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        /**\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                // eslint-disable-next-line jquery-no-input-event-shorthand\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                // eslint-disable-next-line jquery-no-input-event-shorthand\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/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/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    'underscore',\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        modalLoaded: false,\n        targetElementId: false,\n        pathId: '',\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\n            if (this.modalLoaded) {\n\n                if (!_.isUndefined(options)) {\n                    this.modal.modal('option', 'closed', options.closed);\n                }\n\n                this.modal.modal('openModal');\n                this.setTargetElementId(options, url);\n                this.setPathId(url);\n                $(window).trigger('reload.MediaGallery');\n\n                return;\n            }\n\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\n            $.ajax({\n                url: url,\n                type: 'get',\n                context: $(this),\n                showLoader: true\n\n            }).done(function (data) {\n                this.modal.html(data).trigger('contentUpdated');\n                this.modalLoaded = true;\n                this.setTargetElementId(options, url);\n                this.setPathId(url);\n            }.bind(this));\n\n        },\n\n        /**\n         * Setter for endcoded path id\n         */\n        setPathId: function (url) {\n            this.pathId = url.match(/(&|\\/|%26)current_tree_path(=|\\/)([\\s\\S].*?)(\\/|$)/)[3];\n        },\n\n        /**\n         * Setter for targetElementId property\n         *\n         * @param {Object} options\n         * @param {String} url\n         */\n        setTargetElementId: function (options, url) {\n            this.targetElementId = options && options.targetElementId ?\n                options.targetElementId\n                : url.match(/\\/target_element_id\\/([\\s\\S].*?)\\//)[1];\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            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\n            $(window).on('reload.MediaGallery', $.proxy(this.reload, this));\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.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 ? node.id : null\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').trigger('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').trigger('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': typeof targetEl !== 'function' && targetEl.is('textarea') ? 1 : 0,\n                    'force_static_path': typeof targetEl !== 'function' && 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 (typeof targetEl === 'function') {\n                    targetEl(data, {text: fileRow.find('img').attr('alt')});\n                } else 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                }\n                MediabrowserUtility.closeDialog();\n\n                if (typeof targetEl !== 'function') {\n                    targetEl.focus();\n                    jQuery(targetEl).trigger('change');\n                }\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 mediaBrowser = window.MediabrowserUtility;\n\n            if (!_.isUndefined(wysiwyg) && wysiwyg.get(mediaBrowser.targetElementId)) {\n                return this.getMediaBrowserOpener() || window;\n            }\n\n            return $('#' + mediaBrowser.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            var targetElementId = window.MediabrowserUtility.targetElementId;\n\n            if (!_.isUndefined(wysiwyg) && wysiwyg.get(targetElementId) && !_.isUndefined(tinyMceEditors)) {\n                return tinyMceEditors.get(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                        $.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_node',\n                                    self.element.find('[data-id=\"' + self.activeNode.id + '\"]')\n                                );\n                            }\n                        }, this));\n\n                        return true;\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 (data) {\n                            if (data.error) {\n                                alert({\n                                    content: data.message\n                                });\n                            } else {\n                                self.tree.jstree('refresh', self.activeNode.id);\n                                self.reload();\n                                $(window).trigger('fileDeleted.mediabrowser', {\n                                    ids: self.activeNode.id\n                                });\n                            }\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 (data) {\n                            if (data.error) {\n                                alert({\n                                    content: data.message\n                                });\n                            } else {\n                                self.reload();\n                                self.element.find('#delete_files, #insert_files').toggleClass(\n                                    self.options.hidden, true\n                                );\n\n                                $(window).trigger('fileDeleted.mediabrowser', {\n                                    ids: ids\n                                });\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.node;\n\n            if (node.id === 'root') { //eslint-disable-line eqeqeq\n                return;\n            }\n            breadcrumbs = $('<ul class=\"breadcrumbs\" id=\"breadcrumbs\"></ul>');\n            // jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n            data.instance.get_path(node).each(function (name, index) {\n                if (index > 0) {\n                    breadcrumbs.append($('<li>\\/</li>')); //eslint-disable-line\n                }\n                breadcrumbs.append($('<li />').attr('data-row', 'breadcrumb').text(name));\n\n            });\n            // jscs:enable requireCamelCaseOrUpperCaseIdentifiers\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            var container = $(containerId);\n\n            container.select('.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            container.removeClassName('no-display');\n        },\n\n        /**\n         * @param {*} containerId\n         */\n        disableOptionsContainer: function (containerId) {\n            var container = $(containerId);\n\n            if (container.hasClassName('no-display')) {\n                return;\n            }\n            container.select('.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            container.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 (jQuery(e).closest('.skip-submit, .no-display').length === 0) {\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.get(this.widgetTargetId);\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                                    editor.fire('Change');\n                                } else if (this.bMark) {\n                                    editor.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).trigger('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.get(this.widgetTargetId);\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/tinymce5Adapter.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    'tinymce',\n    'mage/adminhtml/events',\n    'mage/adminhtml/wysiwyg/events',\n    'mage/translate',\n    'prototype',\n    'jquery/ui'\n], function (jQuery, _, tinyMCE, varienGlobalEvents, wysiwygEvents) {\n    'use strict';\n\n    var tinyMceWysiwyg = Class.create();\n\n    tinyMceWysiwyg.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 TinyMCE 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                        tinyMCE.PluginManager.load(plugin.name, plugin.src);\n                        deferred.resolve();\n                    });\n                });\n            }\n\n            if (jQuery.isReady) {\n                tinyMCE.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                    tinyMCE.ui.FloatPanel.zIndex = settings.toolbarZIndex;\n                }\n\n                this.removeEvents(self.id);\n            }\n\n            jQuery.when.apply(jQuery, deferreds).done(function () {\n                tinyMCE.init(settings);\n                this.getPluginButtons().hide();\n                varienGlobalEvents.clearEventHandlers('open_browser_callback');\n                this.eventBus.clearEventHandlers('open_browser_callback');\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.tinymce.plugins.split(' '),\n                toolbar = this.config.tinymce.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.tinymce.plugins = plugins.join(' ');\n            this.config.tinymce.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').addBack().removeAttr('style');\n                    } else {\n                        jQuery(controlId.getEl()).children('button').addBack().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: 'silver',\n                skin: 'oxide',\n                'toolbar_mode': 'wrap',\n                'entity_encoding': 'raw',\n                'convert_urls': false,\n                'content_css': this.config.tinymce['content_css'],\n                'relative_urls': true,\n                'valid_children': '+body[style]',\n                menubar: false,\n                plugins: this.config.tinymce.plugins,\n                toolbar: this.config.tinymce.toolbar,\n                adapter: this,\n                'body_id': 'html-body',\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            // Set default initial height\n            settings['min_height'] = this.config.tinymce['min_height'] ? this.config.tinymce['min_height'] : 250;\n\n            if (this.config.skin) {\n                settings.skin = this.config.skin;\n            }\n\n            if (this.config['toolbar_mode']) {\n                settings['toolbar_mode'] = this.config['toolbar_mode'];\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                settings['file_picker_callback_types'] = 'file image media';\n\n                /**\n                 * @param {*} callback\n                 * @param {*} value\n                 * @param {*} meta\n                 */\n                settings['file_picker_callback'] = function (callback, value, meta) {\n                    var payload = {\n                        callback: callback,\n                        value: value,\n                        meta: meta\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 tinyMCE.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 tinyMCE.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'] ? this.config['store_id'] : 0,\n                frameDialog = jQuery('div.mce-container[role=\"dialog\"]'),\n                self = this,\n                wUrl = this.config['files_browser_window_url'] +\n                    'target_element_id/' + this.getId() + '/' +\n                    'store/' + storeId + '/';\n\n            this.mediaBrowserOpener = o.callback;\n\n            if (typeof o.meta.filetype !== 'undefined' && o.meta.filetype !== '') { //eslint-disable-line eqeqeq\n                wUrl = wUrl + 'type/' + o.meta.filetype + '/';\n            }\n\n            frameDialog.hide();\n            jQuery('.tox-tinymce-aux').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('.tox-tinymce-aux').show();\n                        },\n\n                        targetElementId: self.activeEditor() ? self.activeEditor().id : null\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            tinyMCE.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            tinyMCE.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            var content;\n\n            if (!tinyMCE.get(this.getId())) {\n                this.turnOn();\n\n                return true;\n            }\n\n            content = this.get(this.getId()) ? this.get(this.getId()).getContent() : this.getTextArea().val();\n\n            this.turnOff();\n\n            if (content.match(/{{.+?}}/g)) {\n                this.getTextArea().val(content.replace(/&quot;/g, '\"'));\n            }\n\n            return false;\n        },\n\n        /**\n         * On form validation.\n         */\n        onFormValidation: function () {\n            if (tinyMCE.get(this.getId())) {\n                $(this.getId()).value = tinyMCE.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 tinyMceWysiwyg;\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\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().prop('disabled', false);\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, '\"') + m[4]));\n\n                    return m[1] + '=\"' + m[2] + this.makeDirectiveUrl(decodedDirectiveString) + '\"';\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         * Calls the save method on all editor instances in the collection.\n         */\n        triggerSave: function () {\n            tinyMCE.triggerSave();\n        }\n    };\n\n    return tinyMceWysiwyg.prototype;\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/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/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, 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             */\n            init: function (editor) {\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.ui.registry.addIcon(\n                    'magentowidget',\n                    '<svg width=\"24\" height=\"24\" viewBox=\"0 0 32.000000 32.000000\" ' +\n                    'preserveAspectRatio=\"xMidYMid meet\"> <g transform=\"translate(0.000000,32.000000) ' +\n                    'scale(0.100000,-0.100000)\" fill=\"#000000\" stroke=\"none\"> <path d=\"M130 290 c0 -5 13 -10 30 ' +\n                    '-10 22 0 28 -4 24 -15 -5 -11 2 -15 26 -15 21 0 30 -4 28 -12 -7 -20 -40 -22 -50 -4 -5 9 -14 16 ' +\n                    '-20 16 -6 0 -19 7 -28 15 -9 8 -25 12 -38 8 -33 -8 -27 -26 8 -21 34 5 40 -6 12 -21 -14 -7 -25 -6 ' +\n                    '-40 5 -12 8 -23 10 -27 5 -5 -8 88 -71 105 -71 3 0 29 14 58 31 l53 30 -23 18 c-13 10 -31 20 -40 ' +\n                    '24 -10 3 -18 11 -18 17 0 5 -13 10 -30 10 -16 0 -30 -4 -30 -10z m58 -82 c-3 -7 -15 -13 -28 -13 ' +\n                    '-13 0 -25 6 -27 13 -3 8 6 12 27 12 21 0 30 -4 28 -12z\"/> <path d=\"M30 151 l0 -60 61 -36 c33 ' +\n                    '-19 64 -35 69 -35 5 0 36 16 69 35 l61 36 0 60 0 61 -65 -37 -65 -36 -65 36 -65 37 0 -61z\"/> </g>' +\n                    '</svg>'\n                );\n                editor.ui.registry.addToggleButton('magentowidget', {\n                    icon: 'magentowidget',\n                    tooltip: jQuery.mage.__('Insert Widget'),\n\n                    /**\n                     * execute openVariablesSlideout for onAction callback\n                     */\n                    onAction: function () {\n                        editor.execCommand('mceMagentowidget');\n                    },\n\n                    /**\n                     * Add a node change handler, selects the button in the UI when a image is selected\n                     * @param {ToolbarToggleButtonInstanceApi} api\n                     */\n                    onSetup: function (api) {\n                        /**\n                         * NodeChange handler\n                         */\n                        editor.on('NodeChange', function (e) {\n                            var placeholder = e.element;\n\n                            if (self.isWidgetPlaceholderSelected(placeholder)) {\n                                widgetTools.setEditMode(true);\n                                api.setActive(true);\n                            } else {\n                                widgetTools.setEditMode(false);\n                                api.setActive(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([\\S\\s]*?)\\}\\}/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 (imageSrc) {\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 (config.types[attributes.type]) {\n                            imageHtml += config.types[attributes.type];\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                            result = match[0];\n\n                        if (attributes.id) {\n                            try {\n                                widgetCode = Base64.idDecode(attributes.id);\n                            } catch (e) {\n                                // Ignore and continue.\n                            }\n\n                            if (widgetCode && widgetCode.indexOf('{{widget') !== -1) {\n                                result = widgetCode;\n                            }\n                        }\n\n                        return result;\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, returnval = '';\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                returnval += doc.head ? doc.head.innerHTML.replace(/&amp;quot;/g, '&quot;') : '';\n                returnval += doc.body ? doc.body.innerHTML.replace(/&amp;quot;/g, '&quot;') : '';\n\n                return returnval ? returnval : 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    'mage/adminhtml/tools'\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             */\n            init: function (editor) {\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.ui.registry.addIcon(\n                    'magentovariable',\n                    '<svg width=\"24\" height=\"24\" viewBox=\"0 0 32.000000 32.000000\" ' +\n                    'preserveAspectRatio=\"xMidYMid meet\"><g transform=\"translate(0.000000,32.000000) ' +\n                    'scale(0.100000,-0.100000)\" fill=\"#000000\" stroke=\"none\"><path d=\"M68 250 c-56 -44 -75 -136 -37 ' +\n                    '-184 27 -34 42 -33 23 2 -26 50 -9 129 38 179 26 28 10 30 -24 3z\"/><path d=\"M266 253 c5 -10 9 ' +\n                    '-41 9 -70 0 -42 -6 -60 -32 -97 -36 -51 -35 -56 7 -26 54 39 78 139 44 188 -18 26 -40 30 -28 5z\"/>' +\n                    '<path d=\"M128 223 c-15 -4 -15 -6 0 -33 16 -28 16 -30 -11 -58 -30 -31 -34 -42 -13 -42 8 0 17 11 ' +\n                    '20 25 4 14 11 25 16 25 5 0 12 -11 16 -25 6 -25 37 -35 49 -15 3 5 2 10 -3 10 -23 0 -20 44 5 76 ' +\n                    '25 34 25 34 4 34 -12 0 -20 -4 -17  -8 2 -4 0 -14 -5 -22 -7 -10 -12 -11 -15 -4 -10 25 -30 40 ' +\n                    '-46 37z\"/></g>' +\n                    '</svg>'\n                );\n                editor.ui.registry.addToggleButton('magentovariable', {\n                    icon: 'magentovariable',\n                    tooltip: jQuery.mage.__('Insert Variable'),\n\n                    /**\n                     * execute openVariablesSlideout for onAction callback\n                     */\n                    onAction: function () {\n                        editor.execCommand('openVariablesSlideout');\n                    },\n\n                    /**\n                     * Highlight or dismiss Insert Variable button when variable is selected or deselected.\n                     */\n                    onSetup: function (api) {\n                        /**\n                         * Toggle active state of Insert Variable button.\n                         *\n                         * @param {Object} e\n                         */\n                        var toggleVariableButton = function (e) {\n                            api.setActive(false);\n\n                            if (jQuery(e.target).hasClass('magento-variable')) {\n                                api.setActive(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                    returnval = '';\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                returnval += doc.head ? doc.head.innerHTML.replace(/&amp;quot;/g, '&quot;') : '';\n                returnval += doc.body ? doc.body.innerHTML.replace(/&amp;quot;/g, '&quot;') : '';\n\n                return returnval ? returnval : 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/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/menu.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.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                .on('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/tree-suggest.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    'jquery/jstree/jquery.jstree',\n    'mage/backend/suggest'\n], 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 (typeof 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.core.prototype.hover_node;\n    dehover_node = $.jstree.core.prototype.dehover_node;\n    select_node = $.jstree.core.prototype.select_node;\n    init = $.jstree.core.prototype.init;\n\n    $.extend(true, $.jstree.core.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/validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global BASE_URL, alertAlreadyDisplayed */\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_Ui/js/modal/alert',\n    'jquery/ui',\n    'jquery/validate',\n    'mage/translate',\n    'mage/validation'\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                        .trigger('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 && typeof $.validator.defaults.highlight === 'function') {\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 && typeof $.validator.defaults.unhighlight === 'function') {\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 && typeof 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/form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'jquery/ui'\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 (typeof data === 'object') {\n                return this._buildURL(this.oldAttributes.action, data.args);\n            }\n\n            return typeof 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/button.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('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","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\"></button>',\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                            .addClass(options.mselectCheckedClass)\n                            .prop('checked', true)\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/suggest.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    'mage/mage',\n    'jquery/ui',\n    'mage/backend/menu',\n    'mage/translate'\n], 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 this.element[this.element.is(':input') ? 'val' : 'text']().trim();\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 && typeof 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 (typeof 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 (typeof 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 (Array.isArray(o.source)) {\n                response(this.filter(o.source, term));\n            } else if (typeof 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 (typeof 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 = Array.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 = Array.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></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/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 (typeof 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 = JSON.parse(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></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/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></div>', {\n                'class': 'page-actions-buttons'\n            }));\n            this.element.wrapInner($('<div></div>', {\n                'class': 'page-actions-inner', 'data-title': title\n            }));\n            this.element.removeClass('floating-header');\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            if (this._placeholder) {\n                this._placeholder.remove();\n            }\n            this._off($(window));\n        }\n    });\n\n    return $.mage.floatingHeader;\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/tabs.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    'jquery/ui',\n    'jquery/ui-modules/widgets/tabs'\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 = tab.attr('aria-controls') || $({}).uniqueId()[ 0 ].id;\n                    selector = '#' + panelId;\n                    panel = that.element.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            /**\n             * Add form key to ajax call\n             * @param {Object} event - event object\n             * @param {Object} ui\n             */\n            beforeLoad: function (event, ui) {\n                ui.ajaxSettings.type = 'POST';\n                ui.ajaxSettings.hasContent = true;\n                ui.jqXHR.setRequestHeader('Content-Type', ui.ajaxSettings.contentType);\n                ui.ajaxSettings.data = jQuery.param(\n                    {\n                        isAjax: true,\n                        'form_key': typeof FORM_KEY !== 'undefined' ? FORM_KEY : null\n                    },\n                    ui.ajaxSettings.traditional\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        }\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/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/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[index] === value;\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/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    'mage/utils/objects'\n], function (_, $, utils) {\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(\n                    new RegExp(mage + '(?=([^\\u0027]*\\u0027[^\\u0027]*\\u0027)*[^\\u0027]*$)'),\n                    moment\n                );\n            });\n            result = result.replace(/'(.*?)'/g, '[$1]');\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        = utils.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                    if (config.response) {\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                })\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(utils.serialize(data), function (val, name) {\n                    formData.append(name, val);\n                });\n            } else if (type === 'simple') {\n                formData = utils.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) && !Array.isArray(value)) {\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 special characters with their corresponding HTML entities.\n         *\n         * @param {String} string - Text to escape.\n         * @returns {String} Escaped text.\n         */\n        escape: function (string) {\n            return string ? $('<p></p>').text(string).html().replace(/\"/g, '&quot;') : string;\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    'mage/utils/strings'\n], function (ko, $, _, stringUtils) {\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            if (!data) {\n                return result;\n            }\n\n            // UnderscoreJS each breaks when an object has a length property so we use Object.keys\n            _.each(Object.keys(data), function (name) {\n                var node = data[name];\n\n                if ({}.toString.call(node) === '[object Function]') {\n                    return;\n                }\n\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 = stringUtils.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\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    /**\n     * Objects can specify how to use templating for their properties - getting that configuration.\n     *\n     * To disable rendering for all properties of your object add __disableTmpl: true.\n     * To disable for specific property add __disableTmpl: {propertyName: true}.\n     * To limit recursion for a specific property add __disableTmpl: {propertyName: numberOfCycles}.\n     *\n     * @param {String} tmpl\n     * @param {Object | undefined} target\n     * @returns {Boolean|Object}\n     */\n    function isTmplIgnored(tmpl, target) {\n        var parsedTmpl;\n\n        try {\n            parsedTmpl = JSON.parse(tmpl);\n\n            if (typeof parsedTmpl === 'object') {\n                return tmpl.includes('__disableTmpl');\n            }\n        } catch (e) {\n        }\n\n        if (typeof target !== 'undefined') {\n            if (typeof target === 'object' && target.hasOwnProperty('__disableTmpl')) {\n                return target.__disableTmpl;\n            }\n        }\n\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     * @param {Number|undefined} maxCycles - Maximum number of rendering cycles, can be 0.\n     * @returns {*} Compiled template.\n     */\n    function render(tmpl, data, castString, maxCycles) {\n        var last = tmpl,\n            cycles = 0;\n\n        while (~tmpl.indexOf(opener) && (typeof maxCycles === 'undefined' || cycles < maxCycles)) {\n            if (!isTmplIgnored(tmpl)) {\n                tmpl = template(tmpl, data);\n            }\n\n            if (tmpl === last) {\n                break;\n            }\n\n            last = tmpl;\n            cycles++;\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                var disabled,\n                    maxCycles;\n\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                    //Getting template disabling settings, can be true for all disabled and separate settings\n                    //for each property.\n                    disabled = isTmplIgnored(value, list);\n\n                    if (typeof disabled === 'object' && disabled.hasOwnProperty(key) && disabled[key] !== false) {\n                        //Checking if specific settings for a property provided.\n                        maxCycles = disabled[key];\n                    }\n\n                    if (disabled === true || maxCycles === true) {\n                        //Rendering for all properties is disabled.\n                        maxCycles = 0;\n                    }\n\n                    list[key] = render(value, tmpl, castString, maxCycles);\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/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/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        root = typeof self == 'object' && self.self === self && self ||\n            typeof global == 'object' && global.global === global && global ||\n            Function('return this')() || {};\n\n    root._ = _;\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/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            var $el;\n\n            if (typeof fn === 'object') {\n                fn = fn[component].bind(fn);\n            }\n\n            if (_.isFunction(fn)) {\n                fn = fn.bind(null, config, el);\n            } else {\n                $el = $(el);\n\n                if ($el[component]) {\n                    // eslint-disable-next-line jquery-no-bind-unbind\n                    fn = $el[component].bind($el, config);\n                }\n            }\n            // Init module in separate task to prevent blocking main thread.\n            setTimeout(fn);\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/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 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/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/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 had path fallback triggered.\n     *\n     * @param {Object} module - Module to be checked.\n     * @return {Boolean}\n     */\n    function isPathFallback(module) {\n        return registry[module.id] && registry[module.id].events.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 >\n            _.filter(module.depMaps, isRejected).length + _.filter(module.depMaps, isPathFallback).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/msie/file-reader.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     * Init \"readAsBinaryString\" function for FileReader class.\n     * It need for IE11\n     * @param {Blob} fileData\n     */\n    var readAsBinaryStringIEFunc = function (fileData) {\n        var binary = '',\n            self = this,\n            reader = new FileReader();\n\n        /**\n         * Read file as binary string\n         */\n        reader.onload = function () {\n            var bytes, length, index;\n\n            /* eslint-disable no-undef */\n            bytes = new Uint8Array(reader.result);\n            /* eslint-enable */\n            length = bytes.length;\n\n            for (index = 0; index < length; index++) {\n                binary += String.fromCharCode(bytes[index]);\n            }\n            //self.result  - readonly so assign binary\n            self.content = binary;\n            $(self).trigger('onload');\n        };\n        reader.readAsArrayBuffer(fileData);\n    };\n\n    if (typeof FileReader.prototype.readAsBinaryString === 'undefined') {\n        FileReader.prototype.readAsBinaryString = readAsBinaryStringIEFunc;\n    }\n});\n","chartjs/chartjs-adapter-moment.js":"/*!\n  * chartjs-adapter-moment v1.0.0\n  * https://www.chartjs.org\n  * (c) 2021 chartjs-adapter-moment Contributors\n  * Released under the MIT license\n  */\n(function (global, factory) {\ntypeof exports === 'object' && typeof module !== 'undefined' ? factory(require('moment'), require('chart.js')) :\ntypeof define === 'function' && define.amd ? define(['moment', 'chart.js'], factory) :\n(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.moment, global.Chart));\n}(this, (function (moment, chart_js) { 'use strict';\n\nfunction _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }\n\nvar moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);\n\nconst FORMATS = {\n  datetime: 'MMM D, YYYY, h:mm:ss a',\n  millisecond: 'h:mm:ss.SSS a',\n  second: 'h:mm:ss a',\n  minute: 'h:mm a',\n  hour: 'hA',\n  day: 'MMM D',\n  week: 'll',\n  month: 'MMM YYYY',\n  quarter: '[Q]Q - YYYY',\n  year: 'YYYY'\n};\n\nchart_js._adapters._date.override(typeof moment__default['default'] === 'function' ? {\n  _id: 'moment', // DEBUG ONLY\n\n  formats: function() {\n    return FORMATS;\n  },\n\n  parse: function(value, format) {\n    if (typeof value === 'string' && typeof format === 'string') {\n      value = moment__default['default'](value, format);\n    } else if (!(value instanceof moment__default['default'])) {\n      value = moment__default['default'](value);\n    }\n    return value.isValid() ? value.valueOf() : null;\n  },\n\n  format: function(time, format) {\n    return moment__default['default'](time).format(format);\n  },\n\n  add: function(time, amount, unit) {\n    return moment__default['default'](time).add(amount, unit).valueOf();\n  },\n\n  diff: function(max, min, unit) {\n    return moment__default['default'](max).diff(moment__default['default'](min), unit);\n  },\n\n  startOf: function(time, unit, weekday) {\n    time = moment__default['default'](time);\n    if (unit === 'isoWeek') {\n      weekday = Math.trunc(Math.min(Math.max(0, weekday), 6));\n      return time.isoWeekday(weekday).startOf('day').valueOf();\n    }\n    return time.startOf(unit).valueOf();\n  },\n\n  endOf: function(time, unit) {\n    return moment__default['default'](time).endOf(unit).valueOf();\n  }\n} : {});\n\n})));\n","chartjs/Chart.min.js":"/*!\n * Chart.js v3.9.1\n * https://www.chartjs.org\n * (c) 2022 Chart.js Contributors\n * Released under the MIT License\n */\n!function(t,e){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=e():\"function\"==typeof define&&define.amd?define(e):(t=\"undefined\"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){\"use strict\";function t(){}const e=function(){let t=0;return function(){return t++}}();function i(t){return null==t}function s(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return\"[object\"===e.slice(0,7)&&\"Array]\"===e.slice(-6)}function n(t){return null!==t&&\"[object Object]\"===Object.prototype.toString.call(t)}const o=t=>(\"number\"==typeof t||t instanceof Number)&&isFinite(+t);function a(t,e){return o(t)?t:e}function r(t,e){return void 0===t?e:t}const l=(t,e)=>\"string\"==typeof t&&t.endsWith(\"%\")?parseFloat(t)/100:t/e,h=(t,e)=>\"string\"==typeof t&&t.endsWith(\"%\")?parseFloat(t)/100*e:+t;function c(t,e,i){if(t&&\"function\"==typeof t.call)return t.apply(i,e)}function d(t,e,i,o){let a,r,l;if(s(t))if(r=t.length,o)for(a=r-1;a>=0;a--)e.call(i,t[a],a);else for(a=0;a<r;a++)e.call(i,t[a],a);else if(n(t))for(l=Object.keys(t),r=l.length,a=0;a<r;a++)e.call(i,t[l[a]],l[a])}function u(t,e){let i,s,n,o;if(!t||!e||t.length!==e.length)return!1;for(i=0,s=t.length;i<s;++i)if(n=t[i],o=e[i],n.datasetIndex!==o.datasetIndex||n.index!==o.index)return!1;return!0}function f(t){if(s(t))return t.map(f);if(n(t)){const e=Object.create(null),i=Object.keys(t),s=i.length;let n=0;for(;n<s;++n)e[i[n]]=f(t[i[n]]);return e}return t}function g(t){return-1===[\"__proto__\",\"prototype\",\"constructor\"].indexOf(t)}function p(t,e,i,s){if(!g(t))return;const o=e[t],a=i[t];n(o)&&n(a)?m(o,a,s):e[t]=f(a)}function m(t,e,i){const o=s(e)?e:[e],a=o.length;if(!n(t))return t;const r=(i=i||{}).merger||p;for(let s=0;s<a;++s){if(!n(e=o[s]))continue;const a=Object.keys(e);for(let s=0,n=a.length;s<n;++s)r(a[s],t,e,i)}return t}function b(t,e){return m(t,e,{merger:x})}function x(t,e,i){if(!g(t))return;const s=e[t],o=i[t];n(s)&&n(o)?b(s,o):Object.prototype.hasOwnProperty.call(e,t)||(e[t]=f(o))}const _={\"\":t=>t,x:t=>t.x,y:t=>t.y};function y(t,e){const i=_[e]||(_[e]=function(t){const e=v(t);return t=>{for(const i of e){if(\"\"===i)break;t=t&&t[i]}return t}}(e));return i(t)}function v(t){const e=t.split(\".\"),i=[];let s=\"\";for(const t of e)s+=t,s.endsWith(\"\\\\\")?s=s.slice(0,-1)+\".\":(i.push(s),s=\"\");return i}function w(t){return t.charAt(0).toUpperCase()+t.slice(1)}const M=t=>void 0!==t,k=t=>\"function\"==typeof t,S=(t,e)=>{if(t.size!==e.size)return!1;for(const i of t)if(!e.has(i))return!1;return!0};function P(t){return\"mouseup\"===t.type||\"click\"===t.type||\"contextmenu\"===t.type}const D=Math.PI,O=2*D,C=O+D,A=Number.POSITIVE_INFINITY,T=D/180,L=D/2,E=D/4,R=2*D/3,I=Math.log10,z=Math.sign;function F(t){const e=Math.round(t);t=N(t,e,t/1e3)?e:t;const i=Math.pow(10,Math.floor(I(t))),s=t/i;return(s<=1?1:s<=2?2:s<=5?5:10)*i}function V(t){const e=[],i=Math.sqrt(t);let s;for(s=1;s<i;s++)t%s==0&&(e.push(s),e.push(t/s));return i===(0|i)&&e.push(i),e.sort(((t,e)=>t-e)).pop(),e}function B(t){return!isNaN(parseFloat(t))&&isFinite(t)}function N(t,e,i){return Math.abs(t-e)<i}function W(t,e){const i=Math.round(t);return i-e<=t&&i+e>=t}function j(t,e,i){let s,n,o;for(s=0,n=t.length;s<n;s++)o=t[s][i],isNaN(o)||(e.min=Math.min(e.min,o),e.max=Math.max(e.max,o))}function H(t){return t*(D/180)}function $(t){return t*(180/D)}function Y(t){if(!o(t))return;let e=1,i=0;for(;Math.round(t*e)/e!==t;)e*=10,i++;return i}function U(t,e){const i=e.x-t.x,s=e.y-t.y,n=Math.sqrt(i*i+s*s);let o=Math.atan2(s,i);return o<-.5*D&&(o+=O),{angle:o,distance:n}}function X(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function q(t,e){return(t-e+C)%O-D}function K(t){return(t%O+O)%O}function G(t,e,i,s){const n=K(t),o=K(e),a=K(i),r=K(o-n),l=K(a-n),h=K(n-o),c=K(n-a);return n===o||n===a||s&&o===a||r>l&&h<c}function Z(t,e,i){return Math.max(e,Math.min(i,t))}function J(t){return Z(t,-32768,32767)}function Q(t,e,i,s=1e-6){return t>=Math.min(e,i)-s&&t<=Math.max(e,i)+s}function tt(t,e,i){i=i||(i=>t[i]<e);let s,n=t.length-1,o=0;for(;n-o>1;)s=o+n>>1,i(s)?o=s:n=s;return{lo:o,hi:n}}const et=(t,e,i,s)=>tt(t,i,s?s=>t[s][e]<=i:s=>t[s][e]<i),it=(t,e,i)=>tt(t,i,(s=>t[s][e]>=i));function st(t,e,i){let s=0,n=t.length;for(;s<n&&t[s]<e;)s++;for(;n>s&&t[n-1]>i;)n--;return s>0||n<t.length?t.slice(s,n):t}const nt=[\"push\",\"pop\",\"shift\",\"splice\",\"unshift\"];function ot(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,\"_chartjs\",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),nt.forEach((e=>{const i=\"_onData\"+w(e),s=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value(...e){const n=s.apply(this,e);return t._chartjs.listeners.forEach((t=>{\"function\"==typeof t[i]&&t[i](...e)})),n}})})))}function at(t,e){const i=t._chartjs;if(!i)return;const s=i.listeners,n=s.indexOf(e);-1!==n&&s.splice(n,1),s.length>0||(nt.forEach((e=>{delete t[e]})),delete t._chartjs)}function rt(t){const e=new Set;let i,s;for(i=0,s=t.length;i<s;++i)e.add(t[i]);return e.size===s?t:Array.from(e)}const lt=\"undefined\"==typeof window?function(t){return t()}:window.requestAnimationFrame;function ht(t,e,i){const s=i||(t=>Array.prototype.slice.call(t));let n=!1,o=[];return function(...i){o=s(i),n||(n=!0,lt.call(window,(()=>{n=!1,t.apply(e,o)})))}}function ct(t,e){let i;return function(...s){return e?(clearTimeout(i),i=setTimeout(t,e,s)):t.apply(this,s),e}}const dt=t=>\"start\"===t?\"left\":\"end\"===t?\"right\":\"center\",ut=(t,e,i)=>\"start\"===t?e:\"end\"===t?i:(e+i)/2,ft=(t,e,i,s)=>t===(s?\"left\":\"right\")?i:\"center\"===t?(e+i)/2:e;function gt(t,e,i){const s=e.length;let n=0,o=s;if(t._sorted){const{iScale:a,_parsed:r}=t,l=a.axis,{min:h,max:c,minDefined:d,maxDefined:u}=a.getUserBounds();d&&(n=Z(Math.min(et(r,a.axis,h).lo,i?s:et(e,l,a.getPixelForValue(h)).lo),0,s-1)),o=u?Z(Math.max(et(r,a.axis,c,!0).hi+1,i?0:et(e,l,a.getPixelForValue(c),!0).hi+1),n,s)-n:s-n}return{start:n,count:o}}function pt(t){const{xScale:e,yScale:i,_scaleRanges:s}=t,n={xmin:e.min,xmax:e.max,ymin:i.min,ymax:i.max};if(!s)return t._scaleRanges=n,!0;const o=s.xmin!==e.min||s.xmax!==e.max||s.ymin!==i.min||s.ymax!==i.max;return Object.assign(s,n),o}var mt=new class{constructor(){this._request=null,this._charts=new Map,this._running=!1,this._lastDate=void 0}_notify(t,e,i,s){const n=e.listeners[s],o=e.duration;n.forEach((s=>s({chart:t,initial:e.initial,numSteps:o,currentStep:Math.min(i-e.start,o)})))}_refresh(){this._request||(this._running=!0,this._request=lt.call(window,(()=>{this._update(),this._request=null,this._running&&this._refresh()})))}_update(t=Date.now()){let e=0;this._charts.forEach(((i,s)=>{if(!i.running||!i.items.length)return;const n=i.items;let o,a=n.length-1,r=!1;for(;a>=0;--a)o=n[a],o._active?(o._total>i.duration&&(i.duration=o._total),o.tick(t),r=!0):(n[a]=n[n.length-1],n.pop());r&&(s.draw(),this._notify(s,i,t,\"progress\")),n.length||(i.running=!1,this._notify(s,i,t,\"complete\"),i.initial=!1),e+=n.length})),this._lastDate=t,0===e&&(this._running=!1)}_getAnims(t){const e=this._charts;let i=e.get(t);return i||(i={running:!1,initial:!0,items:[],listeners:{complete:[],progress:[]}},e.set(t,i)),i}listen(t,e,i){this._getAnims(t).listeners[e].push(i)}add(t,e){e&&e.length&&this._getAnims(t).items.push(...e)}has(t){return this._getAnims(t).items.length>0}start(t){const e=this._charts.get(t);e&&(e.running=!0,e.start=Date.now(),e.duration=e.items.reduce(((t,e)=>Math.max(t,e._duration)),0),this._refresh())}running(t){if(!this._running)return!1;const e=this._charts.get(t);return!!(e&&e.running&&e.items.length)}stop(t){const e=this._charts.get(t);if(!e||!e.items.length)return;const i=e.items;let s=i.length-1;for(;s>=0;--s)i[s].cancel();e.items=[],this._notify(t,e,Date.now(),\"complete\")}remove(t){return this._charts.delete(t)}};\n    /*!\n     * @kurkle/color v0.2.1\n     * https://github.com/kurkle/color#readme\n     * (c) 2022 Jukka Kurkela\n     * Released under the MIT License\n     */function bt(t){return t+.5|0}const xt=(t,e,i)=>Math.max(Math.min(t,i),e);function _t(t){return xt(bt(2.55*t),0,255)}function yt(t){return xt(bt(255*t),0,255)}function vt(t){return xt(bt(t/2.55)/100,0,1)}function wt(t){return xt(bt(100*t),0,100)}const Mt={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},kt=[...\"0123456789ABCDEF\"],St=t=>kt[15&t],Pt=t=>kt[(240&t)>>4]+kt[15&t],Dt=t=>(240&t)>>4==(15&t);function Ot(t){var e=(t=>Dt(t.r)&&Dt(t.g)&&Dt(t.b)&&Dt(t.a))(t)?St:Pt;return t?\"#\"+e(t.r)+e(t.g)+e(t.b)+((t,e)=>t<255?e(t):\"\")(t.a,e):void 0}const Ct=/^(hsla?|hwb|hsv)\\(\\s*([-+.e\\d]+)(?:deg)?[\\s,]+([-+.e\\d]+)%[\\s,]+([-+.e\\d]+)%(?:[\\s,]+([-+.e\\d]+)(%)?)?\\s*\\)$/;function At(t,e,i){const s=e*Math.min(i,1-i),n=(e,n=(e+t/30)%12)=>i-s*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]}function Tt(t,e,i){const s=(s,n=(s+t/60)%6)=>i-i*e*Math.max(Math.min(n,4-n,1),0);return[s(5),s(3),s(1)]}function Lt(t,e,i){const s=At(t,1,.5);let n;for(e+i>1&&(n=1/(e+i),e*=n,i*=n),n=0;n<3;n++)s[n]*=1-e-i,s[n]+=e;return s}function Et(t){const e=t.r/255,i=t.g/255,s=t.b/255,n=Math.max(e,i,s),o=Math.min(e,i,s),a=(n+o)/2;let r,l,h;return n!==o&&(h=n-o,l=a>.5?h/(2-n-o):h/(n+o),r=function(t,e,i,s,n){return t===n?(e-i)/s+(e<i?6:0):e===n?(i-t)/s+2:(t-e)/s+4}(e,i,s,h,n),r=60*r+.5),[0|r,l||0,a]}function Rt(t,e,i,s){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,s)).map(yt)}function It(t,e,i){return Rt(At,t,e,i)}function zt(t){return(t%360+360)%360}function Ft(t){const e=Ct.exec(t);let i,s=255;if(!e)return;e[5]!==i&&(s=e[6]?_t(+e[5]):yt(+e[5]));const n=zt(+e[2]),o=+e[3]/100,a=+e[4]/100;return i=\"hwb\"===e[1]?function(t,e,i){return Rt(Lt,t,e,i)}(n,o,a):\"hsv\"===e[1]?function(t,e,i){return Rt(Tt,t,e,i)}(n,o,a):It(n,o,a),{r:i[0],g:i[1],b:i[2],a:s}}const Vt={x:\"dark\",Z:\"light\",Y:\"re\",X:\"blu\",W:\"gr\",V:\"medium\",U:\"slate\",A:\"ee\",T:\"ol\",S:\"or\",B:\"ra\",C:\"lateg\",D:\"ights\",R:\"in\",Q:\"turquois\",E:\"hi\",P:\"ro\",O:\"al\",N:\"le\",M:\"de\",L:\"yello\",F:\"en\",K:\"ch\",G:\"arks\",H:\"ea\",I:\"ightg\",J:\"wh\"},Bt={OiceXe:\"f0f8ff\",antiquewEte:\"faebd7\",aqua:\"ffff\",aquamarRe:\"7fffd4\",azuY:\"f0ffff\",beige:\"f5f5dc\",bisque:\"ffe4c4\",black:\"0\",blanKedOmond:\"ffebcd\",Xe:\"ff\",XeviTet:\"8a2be2\",bPwn:\"a52a2a\",burlywood:\"deb887\",caMtXe:\"5f9ea0\",KartYuse:\"7fff00\",KocTate:\"d2691e\",cSO:\"ff7f50\",cSnflowerXe:\"6495ed\",cSnsilk:\"fff8dc\",crimson:\"dc143c\",cyan:\"ffff\",xXe:\"8b\",xcyan:\"8b8b\",xgTMnPd:\"b8860b\",xWay:\"a9a9a9\",xgYF:\"6400\",xgYy:\"a9a9a9\",xkhaki:\"bdb76b\",xmagFta:\"8b008b\",xTivegYF:\"556b2f\",xSange:\"ff8c00\",xScEd:\"9932cc\",xYd:\"8b0000\",xsOmon:\"e9967a\",xsHgYF:\"8fbc8f\",xUXe:\"483d8b\",xUWay:\"2f4f4f\",xUgYy:\"2f4f4f\",xQe:\"ced1\",xviTet:\"9400d3\",dAppRk:\"ff1493\",dApskyXe:\"bfff\",dimWay:\"696969\",dimgYy:\"696969\",dodgerXe:\"1e90ff\",fiYbrick:\"b22222\",flSOwEte:\"fffaf0\",foYstWAn:\"228b22\",fuKsia:\"ff00ff\",gaRsbSo:\"dcdcdc\",ghostwEte:\"f8f8ff\",gTd:\"ffd700\",gTMnPd:\"daa520\",Way:\"808080\",gYF:\"8000\",gYFLw:\"adff2f\",gYy:\"808080\",honeyMw:\"f0fff0\",hotpRk:\"ff69b4\",RdianYd:\"cd5c5c\",Rdigo:\"4b0082\",ivSy:\"fffff0\",khaki:\"f0e68c\",lavFMr:\"e6e6fa\",lavFMrXsh:\"fff0f5\",lawngYF:\"7cfc00\",NmoncEffon:\"fffacd\",ZXe:\"add8e6\",ZcSO:\"f08080\",Zcyan:\"e0ffff\",ZgTMnPdLw:\"fafad2\",ZWay:\"d3d3d3\",ZgYF:\"90ee90\",ZgYy:\"d3d3d3\",ZpRk:\"ffb6c1\",ZsOmon:\"ffa07a\",ZsHgYF:\"20b2aa\",ZskyXe:\"87cefa\",ZUWay:\"778899\",ZUgYy:\"778899\",ZstAlXe:\"b0c4de\",ZLw:\"ffffe0\",lime:\"ff00\",limegYF:\"32cd32\",lRF:\"faf0e6\",magFta:\"ff00ff\",maPon:\"800000\",VaquamarRe:\"66cdaa\",VXe:\"cd\",VScEd:\"ba55d3\",VpurpN:\"9370db\",VsHgYF:\"3cb371\",VUXe:\"7b68ee\",VsprRggYF:\"fa9a\",VQe:\"48d1cc\",VviTetYd:\"c71585\",midnightXe:\"191970\",mRtcYam:\"f5fffa\",mistyPse:\"ffe4e1\",moccasR:\"ffe4b5\",navajowEte:\"ffdead\",navy:\"80\",Tdlace:\"fdf5e6\",Tive:\"808000\",TivedBb:\"6b8e23\",Sange:\"ffa500\",SangeYd:\"ff4500\",ScEd:\"da70d6\",pOegTMnPd:\"eee8aa\",pOegYF:\"98fb98\",pOeQe:\"afeeee\",pOeviTetYd:\"db7093\",papayawEp:\"ffefd5\",pHKpuff:\"ffdab9\",peru:\"cd853f\",pRk:\"ffc0cb\",plum:\"dda0dd\",powMrXe:\"b0e0e6\",purpN:\"800080\",YbeccapurpN:\"663399\",Yd:\"ff0000\",Psybrown:\"bc8f8f\",PyOXe:\"4169e1\",saddNbPwn:\"8b4513\",sOmon:\"fa8072\",sandybPwn:\"f4a460\",sHgYF:\"2e8b57\",sHshell:\"fff5ee\",siFna:\"a0522d\",silver:\"c0c0c0\",skyXe:\"87ceeb\",UXe:\"6a5acd\",UWay:\"708090\",UgYy:\"708090\",snow:\"fffafa\",sprRggYF:\"ff7f\",stAlXe:\"4682b4\",tan:\"d2b48c\",teO:\"8080\",tEstN:\"d8bfd8\",tomato:\"ff6347\",Qe:\"40e0d0\",viTet:\"ee82ee\",JHt:\"f5deb3\",wEte:\"ffffff\",wEtesmoke:\"f5f5f5\",Lw:\"ffff00\",LwgYF:\"9acd32\"};let Nt;function Wt(t){Nt||(Nt=function(){const t={},e=Object.keys(Bt),i=Object.keys(Vt);let s,n,o,a,r;for(s=0;s<e.length;s++){for(a=r=e[s],n=0;n<i.length;n++)o=i[n],r=r.replace(o,Vt[o]);o=parseInt(Bt[a],16),t[r]=[o>>16&255,o>>8&255,255&o]}return t}(),Nt.transparent=[0,0,0,0]);const e=Nt[t.toLowerCase()];return e&&{r:e[0],g:e[1],b:e[2],a:4===e.length?e[3]:255}}const jt=/^rgba?\\(\\s*([-+.\\d]+)(%)?[\\s,]+([-+.e\\d]+)(%)?[\\s,]+([-+.e\\d]+)(%)?(?:[\\s,/]+([-+.e\\d]+)(%)?)?\\s*\\)$/;const Ht=t=>t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055,$t=t=>t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4);function Yt(t,e,i){if(t){let s=Et(t);s[e]=Math.max(0,Math.min(s[e]+s[e]*i,0===e?360:1)),s=It(s),t.r=s[0],t.g=s[1],t.b=s[2]}}function Ut(t,e){return t?Object.assign(e||{},t):t}function Xt(t){var e={r:0,g:0,b:0,a:255};return Array.isArray(t)?t.length>=3&&(e={r:t[0],g:t[1],b:t[2],a:255},t.length>3&&(e.a=yt(t[3]))):(e=Ut(t,{r:0,g:0,b:0,a:1})).a=yt(e.a),e}function qt(t){return\"r\"===t.charAt(0)?function(t){const e=jt.exec(t);let i,s,n,o=255;if(e){if(e[7]!==i){const t=+e[7];o=e[8]?_t(t):xt(255*t,0,255)}return i=+e[1],s=+e[3],n=+e[5],i=255&(e[2]?_t(i):xt(i,0,255)),s=255&(e[4]?_t(s):xt(s,0,255)),n=255&(e[6]?_t(n):xt(n,0,255)),{r:i,g:s,b:n,a:o}}}(t):Ft(t)}class Kt{constructor(t){if(t instanceof Kt)return t;const e=typeof t;let i;var s,n,o;\"object\"===e?i=Xt(t):\"string\"===e&&(o=(s=t).length,\"#\"===s[0]&&(4===o||5===o?n={r:255&17*Mt[s[1]],g:255&17*Mt[s[2]],b:255&17*Mt[s[3]],a:5===o?17*Mt[s[4]]:255}:7!==o&&9!==o||(n={r:Mt[s[1]]<<4|Mt[s[2]],g:Mt[s[3]]<<4|Mt[s[4]],b:Mt[s[5]]<<4|Mt[s[6]],a:9===o?Mt[s[7]]<<4|Mt[s[8]]:255})),i=n||Wt(t)||qt(t)),this._rgb=i,this._valid=!!i}get valid(){return this._valid}get rgb(){var t=Ut(this._rgb);return t&&(t.a=vt(t.a)),t}set rgb(t){this._rgb=Xt(t)}rgbString(){return this._valid?(t=this._rgb)&&(t.a<255?`rgba(${t.r}, ${t.g}, ${t.b}, ${vt(t.a)})`:`rgb(${t.r}, ${t.g}, ${t.b})`):void 0;var t}hexString(){return this._valid?Ot(this._rgb):void 0}hslString(){return this._valid?function(t){if(!t)return;const e=Et(t),i=e[0],s=wt(e[1]),n=wt(e[2]);return t.a<255?`hsla(${i}, ${s}%, ${n}%, ${vt(t.a)})`:`hsl(${i}, ${s}%, ${n}%)`}(this._rgb):void 0}mix(t,e){if(t){const i=this.rgb,s=t.rgb;let n;const o=e===n?.5:e,a=2*o-1,r=i.a-s.a,l=((a*r==-1?a:(a+r)/(1+a*r))+1)/2;n=1-l,i.r=255&l*i.r+n*s.r+.5,i.g=255&l*i.g+n*s.g+.5,i.b=255&l*i.b+n*s.b+.5,i.a=o*i.a+(1-o)*s.a,this.rgb=i}return this}interpolate(t,e){return t&&(this._rgb=function(t,e,i){const s=$t(vt(t.r)),n=$t(vt(t.g)),o=$t(vt(t.b));return{r:yt(Ht(s+i*($t(vt(e.r))-s))),g:yt(Ht(n+i*($t(vt(e.g))-n))),b:yt(Ht(o+i*($t(vt(e.b))-o))),a:t.a+i*(e.a-t.a)}}(this._rgb,t._rgb,e)),this}clone(){return new Kt(this.rgb)}alpha(t){return this._rgb.a=yt(t),this}clearer(t){return this._rgb.a*=1-t,this}greyscale(){const t=this._rgb,e=bt(.3*t.r+.59*t.g+.11*t.b);return t.r=t.g=t.b=e,this}opaquer(t){return this._rgb.a*=1+t,this}negate(){const t=this._rgb;return t.r=255-t.r,t.g=255-t.g,t.b=255-t.b,this}lighten(t){return Yt(this._rgb,2,t),this}darken(t){return Yt(this._rgb,2,-t),this}saturate(t){return Yt(this._rgb,1,t),this}desaturate(t){return Yt(this._rgb,1,-t),this}rotate(t){return function(t,e){var i=Et(t);i[0]=zt(i[0]+e),i=It(i),t.r=i[0],t.g=i[1],t.b=i[2]}(this._rgb,t),this}}function Gt(t){return new Kt(t)}function Zt(t){if(t&&\"object\"==typeof t){const e=t.toString();return\"[object CanvasPattern]\"===e||\"[object CanvasGradient]\"===e}return!1}function Jt(t){return Zt(t)?t:Gt(t)}function Qt(t){return Zt(t)?t:Gt(t).saturate(.5).darken(.1).hexString()}const te=Object.create(null),ee=Object.create(null);function ie(t,e){if(!e)return t;const i=e.split(\".\");for(let e=0,s=i.length;e<s;++e){const s=i[e];t=t[s]||(t[s]=Object.create(null))}return t}function se(t,e,i){return\"string\"==typeof e?m(ie(t,e),i):m(ie(t,\"\"),e)}var ne=new class{constructor(t){this.animation=void 0,this.backgroundColor=\"rgba(0,0,0,0.1)\",this.borderColor=\"rgba(0,0,0,0.1)\",this.color=\"#666\",this.datasets={},this.devicePixelRatio=t=>t.chart.platform.getDevicePixelRatio(),this.elements={},this.events=[\"mousemove\",\"mouseout\",\"click\",\"touchstart\",\"touchmove\"],this.font={family:\"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",size:12,style:\"normal\",lineHeight:1.2,weight:null},this.hover={},this.hoverBackgroundColor=(t,e)=>Qt(e.backgroundColor),this.hoverBorderColor=(t,e)=>Qt(e.borderColor),this.hoverColor=(t,e)=>Qt(e.color),this.indexAxis=\"x\",this.interaction={mode:\"nearest\",intersect:!0,includeInvisible:!1},this.maintainAspectRatio=!0,this.onHover=null,this.onClick=null,this.parsing=!0,this.plugins={},this.responsive=!0,this.scale=void 0,this.scales={},this.showLine=!0,this.drawActiveElementsOnTop=!0,this.describe(t)}set(t,e){return se(this,t,e)}get(t){return ie(this,t)}describe(t,e){return se(ee,t,e)}override(t,e){return se(te,t,e)}route(t,e,i,s){const o=ie(this,t),a=ie(this,i),l=\"_\"+e;Object.defineProperties(o,{[l]:{value:o[e],writable:!0},[e]:{enumerable:!0,get(){const t=this[l],e=a[s];return n(t)?Object.assign({},e,t):r(t,e)},set(t){this[l]=t}}})}}({_scriptable:t=>!t.startsWith(\"on\"),_indexable:t=>\"events\"!==t,hover:{_fallback:\"interaction\"},interaction:{_scriptable:!1,_indexable:!1}});function oe(){return\"undefined\"!=typeof window&&\"undefined\"!=typeof document}function ae(t){let e=t.parentNode;return e&&\"[object ShadowRoot]\"===e.toString()&&(e=e.host),e}function re(t,e,i){let s;return\"string\"==typeof t?(s=parseInt(t,10),-1!==t.indexOf(\"%\")&&(s=s/100*e.parentNode[i])):s=t,s}const le=t=>window.getComputedStyle(t,null);function he(t,e){return le(t).getPropertyValue(e)}const ce=[\"top\",\"right\",\"bottom\",\"left\"];function de(t,e,i){const s={};i=i?\"-\"+i:\"\";for(let n=0;n<4;n++){const o=ce[n];s[o]=parseFloat(t[e+\"-\"+o+i])||0}return s.width=s.left+s.right,s.height=s.top+s.bottom,s}function ue(t,e){if(\"native\"in t)return t;const{canvas:i,currentDevicePixelRatio:s}=e,n=le(i),o=\"border-box\"===n.boxSizing,a=de(n,\"padding\"),r=de(n,\"border\",\"width\"),{x:l,y:h,box:c}=function(t,e){const i=t.touches,s=i&&i.length?i[0]:t,{offsetX:n,offsetY:o}=s;let a,r,l=!1;if(((t,e,i)=>(t>0||e>0)&&(!i||!i.shadowRoot))(n,o,t.target))a=n,r=o;else{const t=e.getBoundingClientRect();a=s.clientX-t.left,r=s.clientY-t.top,l=!0}return{x:a,y:r,box:l}}(t,i),d=a.left+(c&&r.left),u=a.top+(c&&r.top);let{width:f,height:g}=e;return o&&(f-=a.width+r.width,g-=a.height+r.height),{x:Math.round((l-d)/f*i.width/s),y:Math.round((h-u)/g*i.height/s)}}const fe=t=>Math.round(10*t)/10;function ge(t,e,i,s){const n=le(t),o=de(n,\"margin\"),a=re(n.maxWidth,t,\"clientWidth\")||A,r=re(n.maxHeight,t,\"clientHeight\")||A,l=function(t,e,i){let s,n;if(void 0===e||void 0===i){const o=ae(t);if(o){const t=o.getBoundingClientRect(),a=le(o),r=de(a,\"border\",\"width\"),l=de(a,\"padding\");e=t.width-l.width-r.width,i=t.height-l.height-r.height,s=re(a.maxWidth,o,\"clientWidth\"),n=re(a.maxHeight,o,\"clientHeight\")}else e=t.clientWidth,i=t.clientHeight}return{width:e,height:i,maxWidth:s||A,maxHeight:n||A}}(t,e,i);let{width:h,height:c}=l;if(\"content-box\"===n.boxSizing){const t=de(n,\"border\",\"width\"),e=de(n,\"padding\");h-=e.width+t.width,c-=e.height+t.height}return h=Math.max(0,h-o.width),c=Math.max(0,s?Math.floor(h/s):c-o.height),h=fe(Math.min(h,a,l.maxWidth)),c=fe(Math.min(c,r,l.maxHeight)),h&&!c&&(c=fe(h/2)),{width:h,height:c}}function pe(t,e,i){const s=e||1,n=Math.floor(t.height*s),o=Math.floor(t.width*s);t.height=n/s,t.width=o/s;const a=t.canvas;return a.style&&(i||!a.style.height&&!a.style.width)&&(a.style.height=`${t.height}px`,a.style.width=`${t.width}px`),(t.currentDevicePixelRatio!==s||a.height!==n||a.width!==o)&&(t.currentDevicePixelRatio=s,a.height=n,a.width=o,t.ctx.setTransform(s,0,0,s,0,0),!0)}const me=function(){let t=!1;try{const e={get passive(){return t=!0,!1}};window.addEventListener(\"test\",null,e),window.removeEventListener(\"test\",null,e)}catch(t){}return t}();function be(t,e){const i=he(t,e),s=i&&i.match(/^(\\d+)(\\.\\d+)?px$/);return s?+s[1]:void 0}function xe(t){return!t||i(t.size)||i(t.family)?null:(t.style?t.style+\" \":\"\")+(t.weight?t.weight+\" \":\"\")+t.size+\"px \"+t.family}function _e(t,e,i,s,n){let o=e[n];return o||(o=e[n]=t.measureText(n).width,i.push(n)),o>s&&(s=o),s}function ye(t,e,i,n){let o=(n=n||{}).data=n.data||{},a=n.garbageCollect=n.garbageCollect||[];n.font!==e&&(o=n.data={},a=n.garbageCollect=[],n.font=e),t.save(),t.font=e;let r=0;const l=i.length;let h,c,d,u,f;for(h=0;h<l;h++)if(u=i[h],null!=u&&!0!==s(u))r=_e(t,o,a,r,u);else if(s(u))for(c=0,d=u.length;c<d;c++)f=u[c],null==f||s(f)||(r=_e(t,o,a,r,f));t.restore();const g=a.length/2;if(g>i.length){for(h=0;h<g;h++)delete o[a[h]];a.splice(0,g)}return r}function ve(t,e,i){const s=t.currentDevicePixelRatio,n=0!==i?Math.max(i/2,.5):0;return Math.round((e-n)*s)/s+n}function we(t,e){(e=e||t.getContext(\"2d\")).save(),e.resetTransform(),e.clearRect(0,0,t.width,t.height),e.restore()}function Me(t,e,i,s){ke(t,e,i,s,null)}function ke(t,e,i,s,n){let o,a,r,l,h,c;const d=e.pointStyle,u=e.rotation,f=e.radius;let g=(u||0)*T;if(d&&\"object\"==typeof d&&(o=d.toString(),\"[object HTMLImageElement]\"===o||\"[object HTMLCanvasElement]\"===o))return t.save(),t.translate(i,s),t.rotate(g),t.drawImage(d,-d.width/2,-d.height/2,d.width,d.height),void t.restore();if(!(isNaN(f)||f<=0)){switch(t.beginPath(),d){default:n?t.ellipse(i,s,n/2,f,0,0,O):t.arc(i,s,f,0,O),t.closePath();break;case\"triangle\":t.moveTo(i+Math.sin(g)*f,s-Math.cos(g)*f),g+=R,t.lineTo(i+Math.sin(g)*f,s-Math.cos(g)*f),g+=R,t.lineTo(i+Math.sin(g)*f,s-Math.cos(g)*f),t.closePath();break;case\"rectRounded\":h=.516*f,l=f-h,a=Math.cos(g+E)*l,r=Math.sin(g+E)*l,t.arc(i-a,s-r,h,g-D,g-L),t.arc(i+r,s-a,h,g-L,g),t.arc(i+a,s+r,h,g,g+L),t.arc(i-r,s+a,h,g+L,g+D),t.closePath();break;case\"rect\":if(!u){l=Math.SQRT1_2*f,c=n?n/2:l,t.rect(i-c,s-l,2*c,2*l);break}g+=E;case\"rectRot\":a=Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+r,s-a),t.lineTo(i+a,s+r),t.lineTo(i-r,s+a),t.closePath();break;case\"crossRot\":g+=E;case\"cross\":a=Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+a,s+r),t.moveTo(i+r,s-a),t.lineTo(i-r,s+a);break;case\"star\":a=Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+a,s+r),t.moveTo(i+r,s-a),t.lineTo(i-r,s+a),g+=E,a=Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+a,s+r),t.moveTo(i+r,s-a),t.lineTo(i-r,s+a);break;case\"line\":a=n?n/2:Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+a,s+r);break;case\"dash\":t.moveTo(i,s),t.lineTo(i+Math.cos(g)*f,s+Math.sin(g)*f)}t.fill(),e.borderWidth>0&&t.stroke()}}function Se(t,e,i){return i=i||.5,!e||t&&t.x>e.left-i&&t.x<e.right+i&&t.y>e.top-i&&t.y<e.bottom+i}function Pe(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()}function De(t){t.restore()}function Oe(t,e,i,s,n){if(!e)return t.lineTo(i.x,i.y);if(\"middle\"===n){const s=(e.x+i.x)/2;t.lineTo(s,e.y),t.lineTo(s,i.y)}else\"after\"===n!=!!s?t.lineTo(e.x,i.y):t.lineTo(i.x,e.y);t.lineTo(i.x,i.y)}function Ce(t,e,i,s){if(!e)return t.lineTo(i.x,i.y);t.bezierCurveTo(s?e.cp1x:e.cp2x,s?e.cp1y:e.cp2y,s?i.cp2x:i.cp1x,s?i.cp2y:i.cp1y,i.x,i.y)}function Ae(t,e,n,o,a,r={}){const l=s(e)?e:[e],h=r.strokeWidth>0&&\"\"!==r.strokeColor;let c,d;for(t.save(),t.font=a.string,function(t,e){e.translation&&t.translate(e.translation[0],e.translation[1]);i(e.rotation)||t.rotate(e.rotation);e.color&&(t.fillStyle=e.color);e.textAlign&&(t.textAlign=e.textAlign);e.textBaseline&&(t.textBaseline=e.textBaseline)}(t,r),c=0;c<l.length;++c)d=l[c],h&&(r.strokeColor&&(t.strokeStyle=r.strokeColor),i(r.strokeWidth)||(t.lineWidth=r.strokeWidth),t.strokeText(d,n,o,r.maxWidth)),t.fillText(d,n,o,r.maxWidth),Te(t,n,o,d,r),o+=a.lineHeight;t.restore()}function Te(t,e,i,s,n){if(n.strikethrough||n.underline){const o=t.measureText(s),a=e-o.actualBoundingBoxLeft,r=e+o.actualBoundingBoxRight,l=i-o.actualBoundingBoxAscent,h=i+o.actualBoundingBoxDescent,c=n.strikethrough?(l+h)/2:h;t.strokeStyle=t.fillStyle,t.beginPath(),t.lineWidth=n.decorationWidth||2,t.moveTo(a,c),t.lineTo(r,c),t.stroke()}}function Le(t,e){const{x:i,y:s,w:n,h:o,radius:a}=e;t.arc(i+a.topLeft,s+a.topLeft,a.topLeft,-L,D,!0),t.lineTo(i,s+o-a.bottomLeft),t.arc(i+a.bottomLeft,s+o-a.bottomLeft,a.bottomLeft,D,L,!0),t.lineTo(i+n-a.bottomRight,s+o),t.arc(i+n-a.bottomRight,s+o-a.bottomRight,a.bottomRight,L,0,!0),t.lineTo(i+n,s+a.topRight),t.arc(i+n-a.topRight,s+a.topRight,a.topRight,0,-L,!0),t.lineTo(i+a.topLeft,s)}function Ee(t,e=[\"\"],i=t,s,n=(()=>t[0])){M(s)||(s=$e(\"_fallback\",t));const o={[Symbol.toStringTag]:\"Object\",_cacheable:!0,_scopes:t,_rootScopes:i,_fallback:s,_getTarget:n,override:n=>Ee([n,...t],e,i,s)};return new Proxy(o,{deleteProperty:(e,i)=>(delete e[i],delete e._keys,delete t[0][i],!0),get:(i,s)=>Ve(i,s,(()=>function(t,e,i,s){let n;for(const o of e)if(n=$e(ze(o,t),i),M(n))return Fe(t,n)?je(i,s,t,n):n}(s,e,t,i))),getOwnPropertyDescriptor:(t,e)=>Reflect.getOwnPropertyDescriptor(t._scopes[0],e),getPrototypeOf:()=>Reflect.getPrototypeOf(t[0]),has:(t,e)=>Ye(t).includes(e),ownKeys:t=>Ye(t),set(t,e,i){const s=t._storage||(t._storage=n());return t[e]=s[e]=i,delete t._keys,!0}})}function Re(t,e,i,o){const a={_cacheable:!1,_proxy:t,_context:e,_subProxy:i,_stack:new Set,_descriptors:Ie(t,o),setContext:e=>Re(t,e,i,o),override:s=>Re(t.override(s),e,i,o)};return new Proxy(a,{deleteProperty:(e,i)=>(delete e[i],delete t[i],!0),get:(t,e,i)=>Ve(t,e,(()=>function(t,e,i){const{_proxy:o,_context:a,_subProxy:r,_descriptors:l}=t;let h=o[e];k(h)&&l.isScriptable(e)&&(h=function(t,e,i,s){const{_proxy:n,_context:o,_subProxy:a,_stack:r}=i;if(r.has(t))throw new Error(\"Recursion detected: \"+Array.from(r).join(\"->\")+\"->\"+t);r.add(t),e=e(o,a||s),r.delete(t),Fe(t,e)&&(e=je(n._scopes,n,t,e));return e}(e,h,t,i));s(h)&&h.length&&(h=function(t,e,i,s){const{_proxy:o,_context:a,_subProxy:r,_descriptors:l}=i;if(M(a.index)&&s(t))e=e[a.index%e.length];else if(n(e[0])){const i=e,s=o._scopes.filter((t=>t!==i));e=[];for(const n of i){const i=je(s,o,t,n);e.push(Re(i,a,r&&r[t],l))}}return e}(e,h,t,l.isIndexable));Fe(e,h)&&(h=Re(h,a,r&&r[e],l));return h}(t,e,i))),getOwnPropertyDescriptor:(e,i)=>e._descriptors.allKeys?Reflect.has(t,i)?{enumerable:!0,configurable:!0}:void 0:Reflect.getOwnPropertyDescriptor(t,i),getPrototypeOf:()=>Reflect.getPrototypeOf(t),has:(e,i)=>Reflect.has(t,i),ownKeys:()=>Reflect.ownKeys(t),set:(e,i,s)=>(t[i]=s,delete e[i],!0)})}function Ie(t,e={scriptable:!0,indexable:!0}){const{_scriptable:i=e.scriptable,_indexable:s=e.indexable,_allKeys:n=e.allKeys}=t;return{allKeys:n,scriptable:i,indexable:s,isScriptable:k(i)?i:()=>i,isIndexable:k(s)?s:()=>s}}const ze=(t,e)=>t?t+w(e):e,Fe=(t,e)=>n(e)&&\"adapters\"!==t&&(null===Object.getPrototypeOf(e)||e.constructor===Object);function Ve(t,e,i){if(Object.prototype.hasOwnProperty.call(t,e))return t[e];const s=i();return t[e]=s,s}function Be(t,e,i){return k(t)?t(e,i):t}const Ne=(t,e)=>!0===t?e:\"string\"==typeof t?y(e,t):void 0;function We(t,e,i,s,n){for(const o of e){const e=Ne(i,o);if(e){t.add(e);const o=Be(e._fallback,i,n);if(M(o)&&o!==i&&o!==s)return o}else if(!1===e&&M(s)&&i!==s)return null}return!1}function je(t,e,i,o){const a=e._rootScopes,r=Be(e._fallback,i,o),l=[...t,...a],h=new Set;h.add(o);let c=He(h,l,i,r||i,o);return null!==c&&((!M(r)||r===i||(c=He(h,l,r,c,o),null!==c))&&Ee(Array.from(h),[\"\"],a,r,(()=>function(t,e,i){const o=t._getTarget();e in o||(o[e]={});const a=o[e];if(s(a)&&n(i))return i;return a}(e,i,o))))}function He(t,e,i,s,n){for(;i;)i=We(t,e,i,s,n);return i}function $e(t,e){for(const i of e){if(!i)continue;const e=i[t];if(M(e))return e}}function Ye(t){let e=t._keys;return e||(e=t._keys=function(t){const e=new Set;for(const i of t)for(const t of Object.keys(i).filter((t=>!t.startsWith(\"_\"))))e.add(t);return Array.from(e)}(t._scopes)),e}function Ue(t,e,i,s){const{iScale:n}=t,{key:o=\"r\"}=this._parsing,a=new Array(s);let r,l,h,c;for(r=0,l=s;r<l;++r)h=r+i,c=e[h],a[r]={r:n.parse(y(c,o),h)};return a}const Xe=Number.EPSILON||1e-14,qe=(t,e)=>e<t.length&&!t[e].skip&&t[e],Ke=t=>\"x\"===t?\"y\":\"x\";function Ge(t,e,i,s){const n=t.skip?e:t,o=e,a=i.skip?e:i,r=X(o,n),l=X(a,o);let h=r/(r+l),c=l/(r+l);h=isNaN(h)?0:h,c=isNaN(c)?0:c;const d=s*h,u=s*c;return{previous:{x:o.x-d*(a.x-n.x),y:o.y-d*(a.y-n.y)},next:{x:o.x+u*(a.x-n.x),y:o.y+u*(a.y-n.y)}}}function Ze(t,e=\"x\"){const i=Ke(e),s=t.length,n=Array(s).fill(0),o=Array(s);let a,r,l,h=qe(t,0);for(a=0;a<s;++a)if(r=l,l=h,h=qe(t,a+1),l){if(h){const t=h[e]-l[e];n[a]=0!==t?(h[i]-l[i])/t:0}o[a]=r?h?z(n[a-1])!==z(n[a])?0:(n[a-1]+n[a])/2:n[a-1]:n[a]}!function(t,e,i){const s=t.length;let n,o,a,r,l,h=qe(t,0);for(let c=0;c<s-1;++c)l=h,h=qe(t,c+1),l&&h&&(N(e[c],0,Xe)?i[c]=i[c+1]=0:(n=i[c]/e[c],o=i[c+1]/e[c],r=Math.pow(n,2)+Math.pow(o,2),r<=9||(a=3/Math.sqrt(r),i[c]=n*a*e[c],i[c+1]=o*a*e[c])))}(t,n,o),function(t,e,i=\"x\"){const s=Ke(i),n=t.length;let o,a,r,l=qe(t,0);for(let h=0;h<n;++h){if(a=r,r=l,l=qe(t,h+1),!r)continue;const n=r[i],c=r[s];a&&(o=(n-a[i])/3,r[`cp1${i}`]=n-o,r[`cp1${s}`]=c-o*e[h]),l&&(o=(l[i]-n)/3,r[`cp2${i}`]=n+o,r[`cp2${s}`]=c+o*e[h])}}(t,o,e)}function Je(t,e,i){return Math.max(Math.min(t,i),e)}function Qe(t,e,i,s,n){let o,a,r,l;if(e.spanGaps&&(t=t.filter((t=>!t.skip))),\"monotone\"===e.cubicInterpolationMode)Ze(t,n);else{let i=s?t[t.length-1]:t[0];for(o=0,a=t.length;o<a;++o)r=t[o],l=Ge(i,r,t[Math.min(o+1,a-(s?0:1))%a],e.tension),r.cp1x=l.previous.x,r.cp1y=l.previous.y,r.cp2x=l.next.x,r.cp2y=l.next.y,i=r}e.capBezierPoints&&function(t,e){let i,s,n,o,a,r=Se(t[0],e);for(i=0,s=t.length;i<s;++i)a=o,o=r,r=i<s-1&&Se(t[i+1],e),o&&(n=t[i],a&&(n.cp1x=Je(n.cp1x,e.left,e.right),n.cp1y=Je(n.cp1y,e.top,e.bottom)),r&&(n.cp2x=Je(n.cp2x,e.left,e.right),n.cp2y=Je(n.cp2y,e.top,e.bottom)))}(t,i)}const ti=t=>0===t||1===t,ei=(t,e,i)=>-Math.pow(2,10*(t-=1))*Math.sin((t-e)*O/i),ii=(t,e,i)=>Math.pow(2,-10*t)*Math.sin((t-e)*O/i)+1,si={linear:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>-t*(t-2),easeInOutQuad:t=>(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1),easeInCubic:t=>t*t*t,easeOutCubic:t=>(t-=1)*t*t+1,easeInOutCubic:t=>(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2),easeInQuart:t=>t*t*t*t,easeOutQuart:t=>-((t-=1)*t*t*t-1),easeInOutQuart:t=>(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2),easeInQuint:t=>t*t*t*t*t,easeOutQuint:t=>(t-=1)*t*t*t*t+1,easeInOutQuint:t=>(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2),easeInSine:t=>1-Math.cos(t*L),easeOutSine:t=>Math.sin(t*L),easeInOutSine:t=>-.5*(Math.cos(D*t)-1),easeInExpo:t=>0===t?0:Math.pow(2,10*(t-1)),easeOutExpo:t=>1===t?1:1-Math.pow(2,-10*t),easeInOutExpo:t=>ti(t)?t:t<.5?.5*Math.pow(2,10*(2*t-1)):.5*(2-Math.pow(2,-10*(2*t-1))),easeInCirc:t=>t>=1?t:-(Math.sqrt(1-t*t)-1),easeOutCirc:t=>Math.sqrt(1-(t-=1)*t),easeInOutCirc:t=>(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1),easeInElastic:t=>ti(t)?t:ei(t,.075,.3),easeOutElastic:t=>ti(t)?t:ii(t,.075,.3),easeInOutElastic(t){const e=.1125;return ti(t)?t:t<.5?.5*ei(2*t,e,.45):.5+.5*ii(2*t-1,e,.45)},easeInBack(t){const e=1.70158;return t*t*((e+1)*t-e)},easeOutBack(t){const e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack(t){let e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:t=>1-si.easeOutBounce(1-t),easeOutBounce(t){const e=7.5625,i=2.75;return t<1/i?e*t*t:t<2/i?e*(t-=1.5/i)*t+.75:t<2.5/i?e*(t-=2.25/i)*t+.9375:e*(t-=2.625/i)*t+.984375},easeInOutBounce:t=>t<.5?.5*si.easeInBounce(2*t):.5*si.easeOutBounce(2*t-1)+.5};function ni(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:t.y+i*(e.y-t.y)}}function oi(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:\"middle\"===s?i<.5?t.y:e.y:\"after\"===s?i<1?t.y:e.y:i>0?e.y:t.y}}function ai(t,e,i,s){const n={x:t.cp2x,y:t.cp2y},o={x:e.cp1x,y:e.cp1y},a=ni(t,n,i),r=ni(n,o,i),l=ni(o,e,i),h=ni(a,r,i),c=ni(r,l,i);return ni(h,c,i)}const ri=new Map;function li(t,e,i){return function(t,e){e=e||{};const i=t+JSON.stringify(e);let s=ri.get(i);return s||(s=new Intl.NumberFormat(t,e),ri.set(i,s)),s}(e,i).format(t)}const hi=new RegExp(/^(normal|(\\d+(?:\\.\\d+)?)(px|em|%)?)$/),ci=new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/);function di(t,e){const i=(\"\"+t).match(hi);if(!i||\"normal\"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case\"px\":return t;case\"%\":t/=100}return e*t}function ui(t,e){const i={},s=n(e),o=s?Object.keys(e):e,a=n(t)?s?i=>r(t[i],t[e[i]]):e=>t[e]:()=>t;for(const t of o)i[t]=+a(t)||0;return i}function fi(t){return ui(t,{top:\"y\",right:\"x\",bottom:\"y\",left:\"x\"})}function gi(t){return ui(t,[\"topLeft\",\"topRight\",\"bottomLeft\",\"bottomRight\"])}function pi(t){const e=fi(t);return e.width=e.left+e.right,e.height=e.top+e.bottom,e}function mi(t,e){t=t||{},e=e||ne.font;let i=r(t.size,e.size);\"string\"==typeof i&&(i=parseInt(i,10));let s=r(t.style,e.style);s&&!(\"\"+s).match(ci)&&(console.warn('Invalid font style specified: \"'+s+'\"'),s=\"\");const n={family:r(t.family,e.family),lineHeight:di(r(t.lineHeight,e.lineHeight),i),size:i,style:s,weight:r(t.weight,e.weight),string:\"\"};return n.string=xe(n),n}function bi(t,e,i,n){let o,a,r,l=!0;for(o=0,a=t.length;o<a;++o)if(r=t[o],void 0!==r&&(void 0!==e&&\"function\"==typeof r&&(r=r(e),l=!1),void 0!==i&&s(r)&&(r=r[i%r.length],l=!1),void 0!==r))return n&&!l&&(n.cacheable=!1),r}function xi(t,e,i){const{min:s,max:n}=t,o=h(e,(n-s)/2),a=(t,e)=>i&&0===t?0:t+e;return{min:a(s,-Math.abs(o)),max:a(n,o)}}function _i(t,e){return Object.assign(Object.create(t),e)}function yi(t,e,i){return t?function(t,e){return{x:i=>t+t+e-i,setWidth(t){e=t},textAlign:t=>\"center\"===t?t:\"right\"===t?\"left\":\"right\",xPlus:(t,e)=>t-e,leftForLtr:(t,e)=>t-e}}(e,i):{x:t=>t,setWidth(t){},textAlign:t=>t,xPlus:(t,e)=>t+e,leftForLtr:(t,e)=>t}}function vi(t,e){let i,s;\"ltr\"!==e&&\"rtl\"!==e||(i=t.canvas.style,s=[i.getPropertyValue(\"direction\"),i.getPropertyPriority(\"direction\")],i.setProperty(\"direction\",e,\"important\"),t.prevTextDirection=s)}function wi(t,e){void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty(\"direction\",e[0],e[1]))}function Mi(t){return\"angle\"===t?{between:G,compare:q,normalize:K}:{between:Q,compare:(t,e)=>t-e,normalize:t=>t}}function ki({start:t,end:e,count:i,loop:s,style:n}){return{start:t%i,end:e%i,loop:s&&(e-t+1)%i==0,style:n}}function Si(t,e,i){if(!i)return[t];const{property:s,start:n,end:o}=i,a=e.length,{compare:r,between:l,normalize:h}=Mi(s),{start:c,end:d,loop:u,style:f}=function(t,e,i){const{property:s,start:n,end:o}=i,{between:a,normalize:r}=Mi(s),l=e.length;let h,c,{start:d,end:u,loop:f}=t;if(f){for(d+=l,u+=l,h=0,c=l;h<c&&a(r(e[d%l][s]),n,o);++h)d--,u--;d%=l,u%=l}return u<d&&(u+=l),{start:d,end:u,loop:f,style:t.style}}(t,e,i),g=[];let p,m,b,x=!1,_=null;const y=()=>x||l(n,b,p)&&0!==r(n,b),v=()=>!x||0===r(o,p)||l(o,b,p);for(let t=c,i=c;t<=d;++t)m=e[t%a],m.skip||(p=h(m[s]),p!==b&&(x=l(p,n,o),null===_&&y()&&(_=0===r(p,n)?t:i),null!==_&&v()&&(g.push(ki({start:_,end:t,loop:u,count:a,style:f})),_=null),i=t,b=p));return null!==_&&g.push(ki({start:_,end:d,loop:u,count:a,style:f})),g}function Pi(t,e){const i=[],s=t.segments;for(let n=0;n<s.length;n++){const o=Si(s[n],t.points,e);o.length&&i.push(...o)}return i}function Di(t,e){const i=t.points,s=t.options.spanGaps,n=i.length;if(!n)return[];const o=!!t._loop,{start:a,end:r}=function(t,e,i,s){let n=0,o=e-1;if(i&&!s)for(;n<e&&!t[n].skip;)n++;for(;n<e&&t[n].skip;)n++;for(n%=e,i&&(o+=n);o>n&&t[o%e].skip;)o--;return o%=e,{start:n,end:o}}(i,n,o,s);if(!0===s)return Oi(t,[{start:a,end:r,loop:o}],i,e);return Oi(t,function(t,e,i,s){const n=t.length,o=[];let a,r=e,l=t[e];for(a=e+1;a<=i;++a){const i=t[a%n];i.skip||i.stop?l.skip||(s=!1,o.push({start:e%n,end:(a-1)%n,loop:s}),e=r=i.stop?a:null):(r=a,l.skip&&(e=a)),l=i}return null!==r&&o.push({start:e%n,end:r%n,loop:s}),o}(i,a,r<a?r+n:r,!!t._fullLoop&&0===a&&r===n-1),i,e)}function Oi(t,e,i,s){return s&&s.setContext&&i?function(t,e,i,s){const n=t._chart.getContext(),o=Ci(t.options),{_datasetIndex:a,options:{spanGaps:r}}=t,l=i.length,h=[];let c=o,d=e[0].start,u=d;function f(t,e,s,n){const o=r?-1:1;if(t!==e){for(t+=l;i[t%l].skip;)t-=o;for(;i[e%l].skip;)e+=o;t%l!=e%l&&(h.push({start:t%l,end:e%l,loop:s,style:n}),c=n,d=e%l)}}for(const t of e){d=r?d:t.start;let e,o=i[d%l];for(u=d+1;u<=t.end;u++){const r=i[u%l];e=Ci(s.setContext(_i(n,{type:\"segment\",p0:o,p1:r,p0DataIndex:(u-1)%l,p1DataIndex:u%l,datasetIndex:a}))),Ai(e,c)&&f(d,u-1,t.loop,c),o=r,c=e}d<u-1&&f(d,u-1,t.loop,c)}return h}(t,e,i,s):e}function Ci(t){return{backgroundColor:t.backgroundColor,borderCapStyle:t.borderCapStyle,borderDash:t.borderDash,borderDashOffset:t.borderDashOffset,borderJoinStyle:t.borderJoinStyle,borderWidth:t.borderWidth,borderColor:t.borderColor}}function Ai(t,e){return e&&JSON.stringify(t)!==JSON.stringify(e)}var Ti=Object.freeze({__proto__:null,easingEffects:si,isPatternOrGradient:Zt,color:Jt,getHoverColor:Qt,noop:t,uid:e,isNullOrUndef:i,isArray:s,isObject:n,isFinite:o,finiteOrDefault:a,valueOrDefault:r,toPercentage:l,toDimension:h,callback:c,each:d,_elementsEqual:u,clone:f,_merger:p,merge:m,mergeIf:b,_mergerIf:x,_deprecated:function(t,e,i,s){void 0!==e&&console.warn(t+': \"'+i+'\" is deprecated. Please use \"'+s+'\" instead')},resolveObjectKey:y,_splitKey:v,_capitalize:w,defined:M,isFunction:k,setsEqual:S,_isClickEvent:P,toFontString:xe,_measureText:_e,_longestText:ye,_alignPixel:ve,clearCanvas:we,drawPoint:Me,drawPointLegend:ke,_isPointInArea:Se,clipArea:Pe,unclipArea:De,_steppedLineTo:Oe,_bezierCurveTo:Ce,renderText:Ae,addRoundedRectPath:Le,_lookup:tt,_lookupByKey:et,_rlookupByKey:it,_filterBetween:st,listenArrayEvents:ot,unlistenArrayEvents:at,_arrayUnique:rt,_createResolver:Ee,_attachContext:Re,_descriptors:Ie,_parseObjectDataRadialScale:Ue,splineCurve:Ge,splineCurveMonotone:Ze,_updateBezierControlPoints:Qe,_isDomSupported:oe,_getParentNode:ae,getStyle:he,getRelativePosition:ue,getMaximumSize:ge,retinaScale:pe,supportsEventListenerOptions:me,readUsedSize:be,fontString:function(t,e,i){return e+\" \"+t+\"px \"+i},requestAnimFrame:lt,throttled:ht,debounce:ct,_toLeftRightCenter:dt,_alignStartEnd:ut,_textX:ft,_getStartAndCountOfVisiblePoints:gt,_scaleRangesChanged:pt,_pointInLine:ni,_steppedInterpolation:oi,_bezierInterpolation:ai,formatNumber:li,toLineHeight:di,_readValueToProps:ui,toTRBL:fi,toTRBLCorners:gi,toPadding:pi,toFont:mi,resolve:bi,_addGrace:xi,createContext:_i,PI:D,TAU:O,PITAU:C,INFINITY:A,RAD_PER_DEG:T,HALF_PI:L,QUARTER_PI:E,TWO_THIRDS_PI:R,log10:I,sign:z,niceNum:F,_factorize:V,isNumber:B,almostEquals:N,almostWhole:W,_setMinAndMaxByKey:j,toRadians:H,toDegrees:$,_decimalPlaces:Y,getAngleFromPoint:U,distanceBetweenPoints:X,_angleDiff:q,_normalizeAngle:K,_angleBetween:G,_limitValue:Z,_int16Range:J,_isBetween:Q,getRtlAdapter:yi,overrideTextDirection:vi,restoreTextDirection:wi,_boundSegment:Si,_boundSegments:Pi,_computeSegments:Di});function Li(t,e,i,s){const{controller:n,data:o,_sorted:a}=t,r=n._cachedMeta.iScale;if(r&&e===r.axis&&\"r\"!==e&&a&&o.length){const t=r._reversePixels?it:et;if(!s)return t(o,e,i);if(n._sharedOptions){const s=o[0],n=\"function\"==typeof s.getRange&&s.getRange(e);if(n){const s=t(o,e,i-n),a=t(o,e,i+n);return{lo:s.lo,hi:a.hi}}}}return{lo:0,hi:o.length-1}}function Ei(t,e,i,s,n){const o=t.getSortedVisibleDatasetMetas(),a=i[e];for(let t=0,i=o.length;t<i;++t){const{index:i,data:r}=o[t],{lo:l,hi:h}=Li(o[t],e,a,n);for(let t=l;t<=h;++t){const e=r[t];e.skip||s(e,i,t)}}}function Ri(t,e,i,s,n){const o=[];if(!n&&!t.isPointInArea(e))return o;return Ei(t,i,e,(function(i,a,r){(n||Se(i,t.chartArea,0))&&i.inRange(e.x,e.y,s)&&o.push({element:i,datasetIndex:a,index:r})}),!0),o}function Ii(t,e,i,s,n,o){let a=[];const r=function(t){const e=-1!==t.indexOf(\"x\"),i=-1!==t.indexOf(\"y\");return function(t,s){const n=e?Math.abs(t.x-s.x):0,o=i?Math.abs(t.y-s.y):0;return Math.sqrt(Math.pow(n,2)+Math.pow(o,2))}}(i);let l=Number.POSITIVE_INFINITY;return Ei(t,i,e,(function(i,h,c){const d=i.inRange(e.x,e.y,n);if(s&&!d)return;const u=i.getCenterPoint(n);if(!(!!o||t.isPointInArea(u))&&!d)return;const f=r(e,u);f<l?(a=[{element:i,datasetIndex:h,index:c}],l=f):f===l&&a.push({element:i,datasetIndex:h,index:c})})),a}function zi(t,e,i,s,n,o){return o||t.isPointInArea(e)?\"r\"!==i||s?Ii(t,e,i,s,n,o):function(t,e,i,s){let n=[];return Ei(t,i,e,(function(t,i,o){const{startAngle:a,endAngle:r}=t.getProps([\"startAngle\",\"endAngle\"],s),{angle:l}=U(t,{x:e.x,y:e.y});G(l,a,r)&&n.push({element:t,datasetIndex:i,index:o})})),n}(t,e,i,n):[]}function Fi(t,e,i,s,n){const o=[],a=\"x\"===i?\"inXRange\":\"inYRange\";let r=!1;return Ei(t,i,e,((t,s,l)=>{t[a](e[i],n)&&(o.push({element:t,datasetIndex:s,index:l}),r=r||t.inRange(e.x,e.y,n))})),s&&!r?[]:o}var Vi={evaluateInteractionItems:Ei,modes:{index(t,e,i,s){const n=ue(e,t),o=i.axis||\"x\",a=i.includeInvisible||!1,r=i.intersect?Ri(t,n,o,s,a):zi(t,n,o,!1,s,a),l=[];return r.length?(t.getSortedVisibleDatasetMetas().forEach((t=>{const e=r[0].index,i=t.data[e];i&&!i.skip&&l.push({element:i,datasetIndex:t.index,index:e})})),l):[]},dataset(t,e,i,s){const n=ue(e,t),o=i.axis||\"xy\",a=i.includeInvisible||!1;let r=i.intersect?Ri(t,n,o,s,a):zi(t,n,o,!1,s,a);if(r.length>0){const e=r[0].datasetIndex,i=t.getDatasetMeta(e).data;r=[];for(let t=0;t<i.length;++t)r.push({element:i[t],datasetIndex:e,index:t})}return r},point:(t,e,i,s)=>Ri(t,ue(e,t),i.axis||\"xy\",s,i.includeInvisible||!1),nearest(t,e,i,s){const n=ue(e,t),o=i.axis||\"xy\",a=i.includeInvisible||!1;return zi(t,n,o,i.intersect,s,a)},x:(t,e,i,s)=>Fi(t,ue(e,t),\"x\",i.intersect,s),y:(t,e,i,s)=>Fi(t,ue(e,t),\"y\",i.intersect,s)}};const Bi=[\"left\",\"top\",\"right\",\"bottom\"];function Ni(t,e){return t.filter((t=>t.pos===e))}function Wi(t,e){return t.filter((t=>-1===Bi.indexOf(t.pos)&&t.box.axis===e))}function ji(t,e){return t.sort(((t,i)=>{const s=e?i:t,n=e?t:i;return s.weight===n.weight?s.index-n.index:s.weight-n.weight}))}function Hi(t,e){const i=function(t){const e={};for(const i of t){const{stack:t,pos:s,stackWeight:n}=i;if(!t||!Bi.includes(s))continue;const o=e[t]||(e[t]={count:0,placed:0,weight:0,size:0});o.count++,o.weight+=n}return e}(t),{vBoxMaxWidth:s,hBoxMaxHeight:n}=e;let o,a,r;for(o=0,a=t.length;o<a;++o){r=t[o];const{fullSize:a}=r.box,l=i[r.stack],h=l&&r.stackWeight/l.weight;r.horizontal?(r.width=h?h*s:a&&e.availableWidth,r.height=n):(r.width=s,r.height=h?h*n:a&&e.availableHeight)}return i}function $i(t,e,i,s){return Math.max(t[i],e[i])+Math.max(t[s],e[s])}function Yi(t,e){t.top=Math.max(t.top,e.top),t.left=Math.max(t.left,e.left),t.bottom=Math.max(t.bottom,e.bottom),t.right=Math.max(t.right,e.right)}function Ui(t,e,i,s){const{pos:o,box:a}=i,r=t.maxPadding;if(!n(o)){i.size&&(t[o]-=i.size);const e=s[i.stack]||{size:0,count:1};e.size=Math.max(e.size,i.horizontal?a.height:a.width),i.size=e.size/e.count,t[o]+=i.size}a.getPadding&&Yi(r,a.getPadding());const l=Math.max(0,e.outerWidth-$i(r,t,\"left\",\"right\")),h=Math.max(0,e.outerHeight-$i(r,t,\"top\",\"bottom\")),c=l!==t.w,d=h!==t.h;return t.w=l,t.h=h,i.horizontal?{same:c,other:d}:{same:d,other:c}}function Xi(t,e){const i=e.maxPadding;function s(t){const s={left:0,top:0,right:0,bottom:0};return t.forEach((t=>{s[t]=Math.max(e[t],i[t])})),s}return s(t?[\"left\",\"right\"]:[\"top\",\"bottom\"])}function qi(t,e,i,s){const n=[];let o,a,r,l,h,c;for(o=0,a=t.length,h=0;o<a;++o){r=t[o],l=r.box,l.update(r.width||e.w,r.height||e.h,Xi(r.horizontal,e));const{same:a,other:d}=Ui(e,i,r,s);h|=a&&n.length,c=c||d,l.fullSize||n.push(r)}return h&&qi(n,e,i,s)||c}function Ki(t,e,i,s,n){t.top=i,t.left=e,t.right=e+s,t.bottom=i+n,t.width=s,t.height=n}function Gi(t,e,i,s){const n=i.padding;let{x:o,y:a}=e;for(const r of t){const t=r.box,l=s[r.stack]||{count:1,placed:0,weight:1},h=r.stackWeight/l.weight||1;if(r.horizontal){const s=e.w*h,o=l.size||t.height;M(l.start)&&(a=l.start),t.fullSize?Ki(t,n.left,a,i.outerWidth-n.right-n.left,o):Ki(t,e.left+l.placed,a,s,o),l.start=a,l.placed+=s,a=t.bottom}else{const s=e.h*h,a=l.size||t.width;M(l.start)&&(o=l.start),t.fullSize?Ki(t,o,n.top,a,i.outerHeight-n.bottom-n.top):Ki(t,o,e.top+l.placed,a,s),l.start=o,l.placed+=s,o=t.right}}e.x=o,e.y=a}ne.set(\"layout\",{autoPadding:!0,padding:{top:0,right:0,bottom:0,left:0}});var Zi={addBox(t,e){t.boxes||(t.boxes=[]),e.fullSize=e.fullSize||!1,e.position=e.position||\"top\",e.weight=e.weight||0,e._layers=e._layers||function(){return[{z:0,draw(t){e.draw(t)}}]},t.boxes.push(e)},removeBox(t,e){const i=t.boxes?t.boxes.indexOf(e):-1;-1!==i&&t.boxes.splice(i,1)},configure(t,e,i){e.fullSize=i.fullSize,e.position=i.position,e.weight=i.weight},update(t,e,i,s){if(!t)return;const n=pi(t.options.layout.padding),o=Math.max(e-n.width,0),a=Math.max(i-n.height,0),r=function(t){const e=function(t){const e=[];let i,s,n,o,a,r;for(i=0,s=(t||[]).length;i<s;++i)n=t[i],({position:o,options:{stack:a,stackWeight:r=1}}=n),e.push({index:i,box:n,pos:o,horizontal:n.isHorizontal(),weight:n.weight,stack:a&&o+a,stackWeight:r});return e}(t),i=ji(e.filter((t=>t.box.fullSize)),!0),s=ji(Ni(e,\"left\"),!0),n=ji(Ni(e,\"right\")),o=ji(Ni(e,\"top\"),!0),a=ji(Ni(e,\"bottom\")),r=Wi(e,\"x\"),l=Wi(e,\"y\");return{fullSize:i,leftAndTop:s.concat(o),rightAndBottom:n.concat(l).concat(a).concat(r),chartArea:Ni(e,\"chartArea\"),vertical:s.concat(n).concat(l),horizontal:o.concat(a).concat(r)}}(t.boxes),l=r.vertical,h=r.horizontal;d(t.boxes,(t=>{\"function\"==typeof t.beforeLayout&&t.beforeLayout()}));const c=l.reduce(((t,e)=>e.box.options&&!1===e.box.options.display?t:t+1),0)||1,u=Object.freeze({outerWidth:e,outerHeight:i,padding:n,availableWidth:o,availableHeight:a,vBoxMaxWidth:o/2/c,hBoxMaxHeight:a/2}),f=Object.assign({},n);Yi(f,pi(s));const g=Object.assign({maxPadding:f,w:o,h:a,x:n.left,y:n.top},n),p=Hi(l.concat(h),u);qi(r.fullSize,g,u,p),qi(l,g,u,p),qi(h,g,u,p)&&qi(l,g,u,p),function(t){const e=t.maxPadding;function i(i){const s=Math.max(e[i]-t[i],0);return t[i]+=s,s}t.y+=i(\"top\"),t.x+=i(\"left\"),i(\"right\"),i(\"bottom\")}(g),Gi(r.leftAndTop,g,u,p),g.x+=g.w,g.y+=g.h,Gi(r.rightAndBottom,g,u,p),t.chartArea={left:g.left,top:g.top,right:g.left+g.w,bottom:g.top+g.h,height:g.h,width:g.w},d(r.chartArea,(e=>{const i=e.box;Object.assign(i,t.chartArea),i.update(g.w,g.h,{left:0,top:0,right:0,bottom:0})}))}};class Ji{acquireContext(t,e){}releaseContext(t){return!1}addEventListener(t,e,i){}removeEventListener(t,e,i){}getDevicePixelRatio(){return 1}getMaximumSize(t,e,i,s){return e=Math.max(0,e||t.width),i=i||t.height,{width:e,height:Math.max(0,s?Math.floor(e/s):i)}}isAttached(t){return!0}updateConfig(t){}}class Qi extends Ji{acquireContext(t){return t&&t.getContext&&t.getContext(\"2d\")||null}updateConfig(t){t.options.animation=!1}}const ts={touchstart:\"mousedown\",touchmove:\"mousemove\",touchend:\"mouseup\",pointerenter:\"mouseenter\",pointerdown:\"mousedown\",pointermove:\"mousemove\",pointerup:\"mouseup\",pointerleave:\"mouseout\",pointerout:\"mouseout\"},es=t=>null===t||\"\"===t;const is=!!me&&{passive:!0};function ss(t,e,i){t.canvas.removeEventListener(e,i,is)}function ns(t,e){for(const i of t)if(i===e||i.contains(e))return!0}function os(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||ns(i.addedNodes,s),e=e&&!ns(i.removedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}function as(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||ns(i.removedNodes,s),e=e&&!ns(i.addedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}const rs=new Map;let ls=0;function hs(){const t=window.devicePixelRatio;t!==ls&&(ls=t,rs.forEach(((e,i)=>{i.currentDevicePixelRatio!==t&&e()})))}function cs(t,e,i){const s=t.canvas,n=s&&ae(s);if(!n)return;const o=ht(((t,e)=>{const s=n.clientWidth;i(t,e),s<n.clientWidth&&i()}),window),a=new ResizeObserver((t=>{const e=t[0],i=e.contentRect.width,s=e.contentRect.height;0===i&&0===s||o(i,s)}));return a.observe(n),function(t,e){rs.size||window.addEventListener(\"resize\",hs),rs.set(t,e)}(t,o),a}function ds(t,e,i){i&&i.disconnect(),\"resize\"===e&&function(t){rs.delete(t),rs.size||window.removeEventListener(\"resize\",hs)}(t)}function us(t,e,i){const s=t.canvas,n=ht((e=>{null!==t.ctx&&i(function(t,e){const i=ts[t.type]||t.type,{x:s,y:n}=ue(t,e);return{type:i,chart:e,native:t,x:void 0!==s?s:null,y:void 0!==n?n:null}}(e,t))}),t,(t=>{const e=t[0];return[e,e.offsetX,e.offsetY]}));return function(t,e,i){t.addEventListener(e,i,is)}(s,e,n),n}class fs extends Ji{acquireContext(t,e){const i=t&&t.getContext&&t.getContext(\"2d\");return i&&i.canvas===t?(function(t,e){const i=t.style,s=t.getAttribute(\"height\"),n=t.getAttribute(\"width\");if(t.$chartjs={initial:{height:s,width:n,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||\"block\",i.boxSizing=i.boxSizing||\"border-box\",es(n)){const e=be(t,\"width\");void 0!==e&&(t.width=e)}if(es(s))if(\"\"===t.style.height)t.height=t.width/(e||2);else{const e=be(t,\"height\");void 0!==e&&(t.height=e)}}(t,e),i):null}releaseContext(t){const e=t.canvas;if(!e.$chartjs)return!1;const s=e.$chartjs.initial;[\"height\",\"width\"].forEach((t=>{const n=s[t];i(n)?e.removeAttribute(t):e.setAttribute(t,n)}));const n=s.style||{};return Object.keys(n).forEach((t=>{e.style[t]=n[t]})),e.width=e.width,delete e.$chartjs,!0}addEventListener(t,e,i){this.removeEventListener(t,e);const s=t.$proxies||(t.$proxies={}),n={attach:os,detach:as,resize:cs}[e]||us;s[e]=n(t,e,i)}removeEventListener(t,e){const i=t.$proxies||(t.$proxies={}),s=i[e];if(!s)return;({attach:ds,detach:ds,resize:ds}[e]||ss)(t,e,s),i[e]=void 0}getDevicePixelRatio(){return window.devicePixelRatio}getMaximumSize(t,e,i,s){return ge(t,e,i,s)}isAttached(t){const e=ae(t);return!(!e||!e.isConnected)}}function gs(t){return!oe()||\"undefined\"!=typeof OffscreenCanvas&&t instanceof OffscreenCanvas?Qi:fs}var ps=Object.freeze({__proto__:null,_detectPlatform:gs,BasePlatform:Ji,BasicPlatform:Qi,DomPlatform:fs});const ms=\"transparent\",bs={boolean:(t,e,i)=>i>.5?e:t,color(t,e,i){const s=Jt(t||ms),n=s.valid&&Jt(e||ms);return n&&n.valid?n.mix(s,i).hexString():e},number:(t,e,i)=>t+(e-t)*i};class xs{constructor(t,e,i,s){const n=e[i];s=bi([t.to,s,n,t.from]);const o=bi([t.from,n,s]);this._active=!0,this._fn=t.fn||bs[t.type||typeof o],this._easing=si[t.easing]||si.linear,this._start=Math.floor(Date.now()+(t.delay||0)),this._duration=this._total=Math.floor(t.duration),this._loop=!!t.loop,this._target=e,this._prop=i,this._from=o,this._to=s,this._promises=void 0}active(){return this._active}update(t,e,i){if(this._active){this._notify(!1);const s=this._target[this._prop],n=i-this._start,o=this._duration-n;this._start=i,this._duration=Math.floor(Math.max(o,t.duration)),this._total+=n,this._loop=!!t.loop,this._to=bi([t.to,e,s,t.from]),this._from=bi([t.from,s,e])}}cancel(){this._active&&(this.tick(Date.now()),this._active=!1,this._notify(!1))}tick(t){const e=t-this._start,i=this._duration,s=this._prop,n=this._from,o=this._loop,a=this._to;let r;if(this._active=n!==a&&(o||e<i),!this._active)return this._target[s]=a,void this._notify(!0);e<0?this._target[s]=n:(r=e/i%2,r=o&&r>1?2-r:r,r=this._easing(Math.min(1,Math.max(0,r))),this._target[s]=this._fn(n,a,r))}wait(){const t=this._promises||(this._promises=[]);return new Promise(((e,i)=>{t.push({res:e,rej:i})}))}_notify(t){const e=t?\"res\":\"rej\",i=this._promises||[];for(let t=0;t<i.length;t++)i[t][e]()}}ne.set(\"animation\",{delay:void 0,duration:1e3,easing:\"easeOutQuart\",fn:void 0,from:void 0,loop:void 0,to:void 0,type:void 0});const _s=Object.keys(ne.animation);ne.describe(\"animation\",{_fallback:!1,_indexable:!1,_scriptable:t=>\"onProgress\"!==t&&\"onComplete\"!==t&&\"fn\"!==t}),ne.set(\"animations\",{colors:{type:\"color\",properties:[\"color\",\"borderColor\",\"backgroundColor\"]},numbers:{type:\"number\",properties:[\"x\",\"y\",\"borderWidth\",\"radius\",\"tension\"]}}),ne.describe(\"animations\",{_fallback:\"animation\"}),ne.set(\"transitions\",{active:{animation:{duration:400}},resize:{animation:{duration:0}},show:{animations:{colors:{from:\"transparent\"},visible:{type:\"boolean\",duration:0}}},hide:{animations:{colors:{to:\"transparent\"},visible:{type:\"boolean\",easing:\"linear\",fn:t=>0|t}}}});class ys{constructor(t,e){this._chart=t,this._properties=new Map,this.configure(e)}configure(t){if(!n(t))return;const e=this._properties;Object.getOwnPropertyNames(t).forEach((i=>{const o=t[i];if(!n(o))return;const a={};for(const t of _s)a[t]=o[t];(s(o.properties)&&o.properties||[i]).forEach((t=>{t!==i&&e.has(t)||e.set(t,a)}))}))}_animateOptions(t,e){const i=e.options,s=function(t,e){if(!e)return;let i=t.options;if(!i)return void(t.options=e);i.$shared&&(t.options=i=Object.assign({},i,{$shared:!1,$animations:{}}));return i}(t,i);if(!s)return[];const n=this._createAnimations(s,i);return i.$shared&&function(t,e){const i=[],s=Object.keys(e);for(let e=0;e<s.length;e++){const n=t[s[e]];n&&n.active()&&i.push(n.wait())}return Promise.all(i)}(t.options.$animations,i).then((()=>{t.options=i}),(()=>{})),n}_createAnimations(t,e){const i=this._properties,s=[],n=t.$animations||(t.$animations={}),o=Object.keys(e),a=Date.now();let r;for(r=o.length-1;r>=0;--r){const l=o[r];if(\"$\"===l.charAt(0))continue;if(\"options\"===l){s.push(...this._animateOptions(t,e));continue}const h=e[l];let c=n[l];const d=i.get(l);if(c){if(d&&c.active()){c.update(d,h,a);continue}c.cancel()}d&&d.duration?(n[l]=c=new xs(d,t,l,h),s.push(c)):t[l]=h}return s}update(t,e){if(0===this._properties.size)return void Object.assign(t,e);const i=this._createAnimations(t,e);return i.length?(mt.add(this._chart,i),!0):void 0}}function vs(t,e){const i=t&&t.options||{},s=i.reverse,n=void 0===i.min?e:0,o=void 0===i.max?e:0;return{start:s?o:n,end:s?n:o}}function ws(t,e){const i=[],s=t._getSortedDatasetMetas(e);let n,o;for(n=0,o=s.length;n<o;++n)i.push(s[n].index);return i}function Ms(t,e,i,s={}){const n=t.keys,a=\"single\"===s.mode;let r,l,h,c;if(null!==e){for(r=0,l=n.length;r<l;++r){if(h=+n[r],h===i){if(s.all)continue;break}c=t.values[h],o(c)&&(a||0===e||z(e)===z(c))&&(e+=c)}return e}}function ks(t,e){const i=t&&t.options.stacked;return i||void 0===i&&void 0!==e.stack}function Ss(t,e,i){const s=t[e]||(t[e]={});return s[i]||(s[i]={})}function Ps(t,e,i,s){for(const n of e.getMatchingVisibleMetas(s).reverse()){const e=t[n.index];if(i&&e>0||!i&&e<0)return n.index}return null}function Ds(t,e){const{chart:i,_cachedMeta:s}=t,n=i._stacks||(i._stacks={}),{iScale:o,vScale:a,index:r}=s,l=o.axis,h=a.axis,c=function(t,e,i){return`${t.id}.${e.id}.${i.stack||i.type}`}(o,a,s),d=e.length;let u;for(let t=0;t<d;++t){const i=e[t],{[l]:o,[h]:d}=i;u=(i._stacks||(i._stacks={}))[h]=Ss(n,c,o),u[r]=d,u._top=Ps(u,a,!0,s.type),u._bottom=Ps(u,a,!1,s.type)}}function Os(t,e){const i=t.scales;return Object.keys(i).filter((t=>i[t].axis===e)).shift()}function Cs(t,e){const i=t.controller.index,s=t.vScale&&t.vScale.axis;if(s){e=e||t._parsed;for(const t of e){const e=t._stacks;if(!e||void 0===e[s]||void 0===e[s][i])return;delete e[s][i]}}}const As=t=>\"reset\"===t||\"none\"===t,Ts=(t,e)=>e?t:Object.assign({},t);class Ls{constructor(t,e){this.chart=t,this._ctx=t.ctx,this.index=e,this._cachedDataOpts={},this._cachedMeta=this.getMeta(),this._type=this._cachedMeta.type,this.options=void 0,this._parsing=!1,this._data=void 0,this._objectData=void 0,this._sharedOptions=void 0,this._drawStart=void 0,this._drawCount=void 0,this.enableOptionSharing=!1,this.supportsDecimation=!1,this.$context=void 0,this._syncList=[],this.initialize()}initialize(){const t=this._cachedMeta;this.configure(),this.linkScales(),t._stacked=ks(t.vScale,t),this.addElements()}updateIndex(t){this.index!==t&&Cs(this._cachedMeta),this.index=t}linkScales(){const t=this.chart,e=this._cachedMeta,i=this.getDataset(),s=(t,e,i,s)=>\"x\"===t?e:\"r\"===t?s:i,n=e.xAxisID=r(i.xAxisID,Os(t,\"x\")),o=e.yAxisID=r(i.yAxisID,Os(t,\"y\")),a=e.rAxisID=r(i.rAxisID,Os(t,\"r\")),l=e.indexAxis,h=e.iAxisID=s(l,n,o,a),c=e.vAxisID=s(l,o,n,a);e.xScale=this.getScaleForId(n),e.yScale=this.getScaleForId(o),e.rScale=this.getScaleForId(a),e.iScale=this.getScaleForId(h),e.vScale=this.getScaleForId(c)}getDataset(){return this.chart.data.datasets[this.index]}getMeta(){return this.chart.getDatasetMeta(this.index)}getScaleForId(t){return this.chart.scales[t]}_getOtherScale(t){const e=this._cachedMeta;return t===e.iScale?e.vScale:e.iScale}reset(){this._update(\"reset\")}_destroy(){const t=this._cachedMeta;this._data&&at(this._data,this),t._stacked&&Cs(t)}_dataCheck(){const t=this.getDataset(),e=t.data||(t.data=[]),i=this._data;if(n(e))this._data=function(t){const e=Object.keys(t),i=new Array(e.length);let s,n,o;for(s=0,n=e.length;s<n;++s)o=e[s],i[s]={x:o,y:t[o]};return i}(e);else if(i!==e){if(i){at(i,this);const t=this._cachedMeta;Cs(t),t._parsed=[]}e&&Object.isExtensible(e)&&ot(e,this),this._syncList=[],this._data=e}}addElements(){const t=this._cachedMeta;this._dataCheck(),this.datasetElementType&&(t.dataset=new this.datasetElementType)}buildOrUpdateElements(t){const e=this._cachedMeta,i=this.getDataset();let s=!1;this._dataCheck();const n=e._stacked;e._stacked=ks(e.vScale,e),e.stack!==i.stack&&(s=!0,Cs(e),e.stack=i.stack),this._resyncElements(t),(s||n!==e._stacked)&&Ds(this,e._parsed)}configure(){const t=this.chart.config,e=t.datasetScopeKeys(this._type),i=t.getOptionScopes(this.getDataset(),e,!0);this.options=t.createResolver(i,this.getContext()),this._parsing=this.options.parsing,this._cachedDataOpts={}}parse(t,e){const{_cachedMeta:i,_data:o}=this,{iScale:a,_stacked:r}=i,l=a.axis;let h,c,d,u=0===t&&e===o.length||i._sorted,f=t>0&&i._parsed[t-1];if(!1===this._parsing)i._parsed=o,i._sorted=!0,d=o;else{d=s(o[t])?this.parseArrayData(i,o,t,e):n(o[t])?this.parseObjectData(i,o,t,e):this.parsePrimitiveData(i,o,t,e);const a=()=>null===c[l]||f&&c[l]<f[l];for(h=0;h<e;++h)i._parsed[h+t]=c=d[h],u&&(a()&&(u=!1),f=c);i._sorted=u}r&&Ds(this,d)}parsePrimitiveData(t,e,i,s){const{iScale:n,vScale:o}=t,a=n.axis,r=o.axis,l=n.getLabels(),h=n===o,c=new Array(s);let d,u,f;for(d=0,u=s;d<u;++d)f=d+i,c[d]={[a]:h||n.parse(l[f],f),[r]:o.parse(e[f],f)};return c}parseArrayData(t,e,i,s){const{xScale:n,yScale:o}=t,a=new Array(s);let r,l,h,c;for(r=0,l=s;r<l;++r)h=r+i,c=e[h],a[r]={x:n.parse(c[0],h),y:o.parse(c[1],h)};return a}parseObjectData(t,e,i,s){const{xScale:n,yScale:o}=t,{xAxisKey:a=\"x\",yAxisKey:r=\"y\"}=this._parsing,l=new Array(s);let h,c,d,u;for(h=0,c=s;h<c;++h)d=h+i,u=e[d],l[h]={x:n.parse(y(u,a),d),y:o.parse(y(u,r),d)};return l}getParsed(t){return this._cachedMeta._parsed[t]}getDataElement(t){return this._cachedMeta.data[t]}applyStack(t,e,i){const s=this.chart,n=this._cachedMeta,o=e[t.axis];return Ms({keys:ws(s,!0),values:e._stacks[t.axis]},o,n.index,{mode:i})}updateRangeFromParsed(t,e,i,s){const n=i[e.axis];let o=null===n?NaN:n;const a=s&&i._stacks[e.axis];s&&a&&(s.values=a,o=Ms(s,n,this._cachedMeta.index)),t.min=Math.min(t.min,o),t.max=Math.max(t.max,o)}getMinMax(t,e){const i=this._cachedMeta,s=i._parsed,n=i._sorted&&t===i.iScale,a=s.length,r=this._getOtherScale(t),l=((t,e,i)=>t&&!e.hidden&&e._stacked&&{keys:ws(i,!0),values:null})(e,i,this.chart),h={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY},{min:c,max:d}=function(t){const{min:e,max:i,minDefined:s,maxDefined:n}=t.getUserBounds();return{min:s?e:Number.NEGATIVE_INFINITY,max:n?i:Number.POSITIVE_INFINITY}}(r);let u,f;function g(){f=s[u];const e=f[r.axis];return!o(f[t.axis])||c>e||d<e}for(u=0;u<a&&(g()||(this.updateRangeFromParsed(h,t,f,l),!n));++u);if(n)for(u=a-1;u>=0;--u)if(!g()){this.updateRangeFromParsed(h,t,f,l);break}return h}getAllParsedValues(t){const e=this._cachedMeta._parsed,i=[];let s,n,a;for(s=0,n=e.length;s<n;++s)a=e[s][t.axis],o(a)&&i.push(a);return i}getMaxOverflow(){return!1}getLabelAndValue(t){const e=this._cachedMeta,i=e.iScale,s=e.vScale,n=this.getParsed(t);return{label:i?\"\"+i.getLabelForValue(n[i.axis]):\"\",value:s?\"\"+s.getLabelForValue(n[s.axis]):\"\"}}_update(t){const e=this._cachedMeta;this.update(t||\"default\"),e._clip=function(t){let e,i,s,o;return n(t)?(e=t.top,i=t.right,s=t.bottom,o=t.left):e=i=s=o=t,{top:e,right:i,bottom:s,left:o,disabled:!1===t}}(r(this.options.clip,function(t,e,i){if(!1===i)return!1;const s=vs(t,i),n=vs(e,i);return{top:n.end,right:s.end,bottom:n.start,left:s.start}}(e.xScale,e.yScale,this.getMaxOverflow())))}update(t){}draw(){const t=this._ctx,e=this.chart,i=this._cachedMeta,s=i.data||[],n=e.chartArea,o=[],a=this._drawStart||0,r=this._drawCount||s.length-a,l=this.options.drawActiveElementsOnTop;let h;for(i.dataset&&i.dataset.draw(t,n,a,r),h=a;h<a+r;++h){const e=s[h];e.hidden||(e.active&&l?o.push(e):e.draw(t,n))}for(h=0;h<o.length;++h)o[h].draw(t,n)}getStyle(t,e){const i=e?\"active\":\"default\";return void 0===t&&this._cachedMeta.dataset?this.resolveDatasetElementOptions(i):this.resolveDataElementOptions(t||0,i)}getContext(t,e,i){const s=this.getDataset();let n;if(t>=0&&t<this._cachedMeta.data.length){const e=this._cachedMeta.data[t];n=e.$context||(e.$context=function(t,e,i){return _i(t,{active:!1,dataIndex:e,parsed:void 0,raw:void 0,element:i,index:e,mode:\"default\",type:\"data\"})}(this.getContext(),t,e)),n.parsed=this.getParsed(t),n.raw=s.data[t],n.index=n.dataIndex=t}else n=this.$context||(this.$context=function(t,e){return _i(t,{active:!1,dataset:void 0,datasetIndex:e,index:e,mode:\"default\",type:\"dataset\"})}(this.chart.getContext(),this.index)),n.dataset=s,n.index=n.datasetIndex=this.index;return n.active=!!e,n.mode=i,n}resolveDatasetElementOptions(t){return this._resolveElementOptions(this.datasetElementType.id,t)}resolveDataElementOptions(t,e){return this._resolveElementOptions(this.dataElementType.id,e,t)}_resolveElementOptions(t,e=\"default\",i){const s=\"active\"===e,n=this._cachedDataOpts,o=t+\"-\"+e,a=n[o],r=this.enableOptionSharing&&M(i);if(a)return Ts(a,r);const l=this.chart.config,h=l.datasetElementScopeKeys(this._type,t),c=s?[`${t}Hover`,\"hover\",t,\"\"]:[t,\"\"],d=l.getOptionScopes(this.getDataset(),h),u=Object.keys(ne.elements[t]),f=l.resolveNamedOptions(d,u,(()=>this.getContext(i,s)),c);return f.$shared&&(f.$shared=r,n[o]=Object.freeze(Ts(f,r))),f}_resolveAnimations(t,e,i){const s=this.chart,n=this._cachedDataOpts,o=`animation-${e}`,a=n[o];if(a)return a;let r;if(!1!==s.options.animation){const s=this.chart.config,n=s.datasetAnimationScopeKeys(this._type,e),o=s.getOptionScopes(this.getDataset(),n);r=s.createResolver(o,this.getContext(t,i,e))}const l=new ys(s,r&&r.animations);return r&&r._cacheable&&(n[o]=Object.freeze(l)),l}getSharedOptions(t){if(t.$shared)return this._sharedOptions||(this._sharedOptions=Object.assign({},t))}includeOptions(t,e){return!e||As(t)||this.chart._animationsDisabled}_getSharedOptions(t,e){const i=this.resolveDataElementOptions(t,e),s=this._sharedOptions,n=this.getSharedOptions(i),o=this.includeOptions(e,n)||n!==s;return this.updateSharedOptions(n,e,i),{sharedOptions:n,includeOptions:o}}updateElement(t,e,i,s){As(s)?Object.assign(t,i):this._resolveAnimations(e,s).update(t,i)}updateSharedOptions(t,e,i){t&&!As(e)&&this._resolveAnimations(void 0,e).update(t,i)}_setStyle(t,e,i,s){t.active=s;const n=this.getStyle(e,s);this._resolveAnimations(e,i,s).update(t,{options:!s&&this.getSharedOptions(n)||n})}removeHoverStyle(t,e,i){this._setStyle(t,i,\"active\",!1)}setHoverStyle(t,e,i){this._setStyle(t,i,\"active\",!0)}_removeDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,\"active\",!1)}_setDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,\"active\",!0)}_resyncElements(t){const e=this._data,i=this._cachedMeta.data;for(const[t,e,i]of this._syncList)this[t](e,i);this._syncList=[];const s=i.length,n=e.length,o=Math.min(n,s);o&&this.parse(0,o),n>s?this._insertElements(s,n-s,t):n<s&&this._removeElements(n,s-n)}_insertElements(t,e,i=!0){const s=this._cachedMeta,n=s.data,o=t+e;let a;const r=t=>{for(t.length+=e,a=t.length-1;a>=o;a--)t[a]=t[a-e]};for(r(n),a=t;a<o;++a)n[a]=new this.dataElementType;this._parsing&&r(s._parsed),this.parse(t,e),i&&this.updateElements(n,t,e,\"reset\")}updateElements(t,e,i,s){}_removeElements(t,e){const i=this._cachedMeta;if(this._parsing){const s=i._parsed.splice(t,e);i._stacked&&Cs(i,s)}i.data.splice(t,e)}_sync(t){if(this._parsing)this._syncList.push(t);else{const[e,i,s]=t;this[e](i,s)}this.chart._dataChanges.push([this.index,...t])}_onDataPush(){const t=arguments.length;this._sync([\"_insertElements\",this.getDataset().data.length-t,t])}_onDataPop(){this._sync([\"_removeElements\",this._cachedMeta.data.length-1,1])}_onDataShift(){this._sync([\"_removeElements\",0,1])}_onDataSplice(t,e){e&&this._sync([\"_removeElements\",t,e]);const i=arguments.length-2;i&&this._sync([\"_insertElements\",t,i])}_onDataUnshift(){this._sync([\"_insertElements\",0,arguments.length])}}Ls.defaults={},Ls.prototype.datasetElementType=null,Ls.prototype.dataElementType=null;class Es{constructor(){this.x=void 0,this.y=void 0,this.active=!1,this.options=void 0,this.$animations=void 0}tooltipPosition(t){const{x:e,y:i}=this.getProps([\"x\",\"y\"],t);return{x:e,y:i}}hasValue(){return B(this.x)&&B(this.y)}getProps(t,e){const i=this.$animations;if(!e||!i)return this;const s={};return t.forEach((t=>{s[t]=i[t]&&i[t].active()?i[t]._to:this[t]})),s}}Es.defaults={},Es.defaultRoutes=void 0;const Rs={values:t=>s(t)?t:\"\"+t,numeric(t,e,i){if(0===t)return\"0\";const s=this.chart.options.locale;let n,o=t;if(i.length>1){const e=Math.max(Math.abs(i[0].value),Math.abs(i[i.length-1].value));(e<1e-4||e>1e15)&&(n=\"scientific\"),o=function(t,e){let i=e.length>3?e[2].value-e[1].value:e[1].value-e[0].value;Math.abs(i)>=1&&t!==Math.floor(t)&&(i=t-Math.floor(t));return i}(t,i)}const a=I(Math.abs(o)),r=Math.max(Math.min(-1*Math.floor(a),20),0),l={notation:n,minimumFractionDigits:r,maximumFractionDigits:r};return Object.assign(l,this.options.ticks.format),li(t,s,l)},logarithmic(t,e,i){if(0===t)return\"0\";const s=t/Math.pow(10,Math.floor(I(t)));return 1===s||2===s||5===s?Rs.numeric.call(this,t,e,i):\"\"}};var Is={formatters:Rs};function zs(t,e){const s=t.options.ticks,n=s.maxTicksLimit||function(t){const e=t.options.offset,i=t._tickSize(),s=t._length/i+(e?0:1),n=t._maxLength/i;return Math.floor(Math.min(s,n))}(t),o=s.major.enabled?function(t){const e=[];let i,s;for(i=0,s=t.length;i<s;i++)t[i].major&&e.push(i);return e}(e):[],a=o.length,r=o[0],l=o[a-1],h=[];if(a>n)return function(t,e,i,s){let n,o=0,a=i[0];for(s=Math.ceil(s),n=0;n<t.length;n++)n===a&&(e.push(t[n]),o++,a=i[o*s])}(e,h,o,a/n),h;const c=function(t,e,i){const s=function(t){const e=t.length;let i,s;if(e<2)return!1;for(s=t[0],i=1;i<e;++i)if(t[i]-t[i-1]!==s)return!1;return s}(t),n=e.length/i;if(!s)return Math.max(n,1);const o=V(s);for(let t=0,e=o.length-1;t<e;t++){const e=o[t];if(e>n)return e}return Math.max(n,1)}(o,e,n);if(a>0){let t,s;const n=a>1?Math.round((l-r)/(a-1)):null;for(Fs(e,h,c,i(n)?0:r-n,r),t=0,s=a-1;t<s;t++)Fs(e,h,c,o[t],o[t+1]);return Fs(e,h,c,l,i(n)?e.length:l+n),h}return Fs(e,h,c),h}function Fs(t,e,i,s,n){const o=r(s,0),a=Math.min(r(n,t.length),t.length);let l,h,c,d=0;for(i=Math.ceil(i),n&&(l=n-s,i=l/Math.floor(l/i)),c=o;c<0;)d++,c=Math.round(o+d*i);for(h=Math.max(o,0);h<a;h++)h===c&&(e.push(t[h]),d++,c=Math.round(o+d*i))}ne.set(\"scale\",{display:!0,offset:!1,reverse:!1,beginAtZero:!1,bounds:\"ticks\",grace:0,grid:{display:!0,lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickLength:8,tickWidth:(t,e)=>e.lineWidth,tickColor:(t,e)=>e.color,offset:!1,borderDash:[],borderDashOffset:0,borderWidth:1},title:{display:!1,text:\"\",padding:{top:4,bottom:4}},ticks:{minRotation:0,maxRotation:50,mirror:!1,textStrokeWidth:0,textStrokeColor:\"\",padding:3,display:!0,autoSkip:!0,autoSkipPadding:3,labelOffset:0,callback:Is.formatters.values,minor:{},major:{},align:\"center\",crossAlign:\"near\",showLabelBackdrop:!1,backdropColor:\"rgba(255, 255, 255, 0.75)\",backdropPadding:2}}),ne.route(\"scale.ticks\",\"color\",\"\",\"color\"),ne.route(\"scale.grid\",\"color\",\"\",\"borderColor\"),ne.route(\"scale.grid\",\"borderColor\",\"\",\"borderColor\"),ne.route(\"scale.title\",\"color\",\"\",\"color\"),ne.describe(\"scale\",{_fallback:!1,_scriptable:t=>!t.startsWith(\"before\")&&!t.startsWith(\"after\")&&\"callback\"!==t&&\"parser\"!==t,_indexable:t=>\"borderDash\"!==t&&\"tickBorderDash\"!==t}),ne.describe(\"scales\",{_fallback:\"scale\"}),ne.describe(\"scale.ticks\",{_scriptable:t=>\"backdropPadding\"!==t&&\"callback\"!==t,_indexable:t=>\"backdropPadding\"!==t});const Vs=(t,e,i)=>\"top\"===e||\"left\"===e?t[e]+i:t[e]-i;function Bs(t,e){const i=[],s=t.length/e,n=t.length;let o=0;for(;o<n;o+=s)i.push(t[Math.floor(o)]);return i}function Ns(t,e,i){const s=t.ticks.length,n=Math.min(e,s-1),o=t._startPixel,a=t._endPixel,r=1e-6;let l,h=t.getPixelForTick(n);if(!(i&&(l=1===s?Math.max(h-o,a-h):0===e?(t.getPixelForTick(1)-h)/2:(h-t.getPixelForTick(n-1))/2,h+=n<e?l:-l,h<o-r||h>a+r)))return h}function Ws(t){return t.drawTicks?t.tickLength:0}function js(t,e){if(!t.display)return 0;const i=mi(t.font,e),n=pi(t.padding);return(s(t.text)?t.text.length:1)*i.lineHeight+n.height}function Hs(t,e,i){let s=dt(t);return(i&&\"right\"!==e||!i&&\"right\"===e)&&(s=(t=>\"left\"===t?\"right\":\"right\"===t?\"left\":t)(s)),s}class $s extends Es{constructor(t){super(),this.id=t.id,this.type=t.type,this.options=void 0,this.ctx=t.ctx,this.chart=t.chart,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this._margins={left:0,right:0,top:0,bottom:0},this.maxWidth=void 0,this.maxHeight=void 0,this.paddingTop=void 0,this.paddingBottom=void 0,this.paddingLeft=void 0,this.paddingRight=void 0,this.axis=void 0,this.labelRotation=void 0,this.min=void 0,this.max=void 0,this._range=void 0,this.ticks=[],this._gridLineItems=null,this._labelItems=null,this._labelSizes=null,this._length=0,this._maxLength=0,this._longestTextCache={},this._startPixel=void 0,this._endPixel=void 0,this._reversePixels=!1,this._userMax=void 0,this._userMin=void 0,this._suggestedMax=void 0,this._suggestedMin=void 0,this._ticksLength=0,this._borderValue=0,this._cache={},this._dataLimitsCached=!1,this.$context=void 0}init(t){this.options=t.setContext(this.getContext()),this.axis=t.axis,this._userMin=this.parse(t.min),this._userMax=this.parse(t.max),this._suggestedMin=this.parse(t.suggestedMin),this._suggestedMax=this.parse(t.suggestedMax)}parse(t,e){return t}getUserBounds(){let{_userMin:t,_userMax:e,_suggestedMin:i,_suggestedMax:s}=this;return t=a(t,Number.POSITIVE_INFINITY),e=a(e,Number.NEGATIVE_INFINITY),i=a(i,Number.POSITIVE_INFINITY),s=a(s,Number.NEGATIVE_INFINITY),{min:a(t,i),max:a(e,s),minDefined:o(t),maxDefined:o(e)}}getMinMax(t){let e,{min:i,max:s,minDefined:n,maxDefined:o}=this.getUserBounds();if(n&&o)return{min:i,max:s};const r=this.getMatchingVisibleMetas();for(let a=0,l=r.length;a<l;++a)e=r[a].controller.getMinMax(this,t),n||(i=Math.min(i,e.min)),o||(s=Math.max(s,e.max));return i=o&&i>s?s:i,s=n&&i>s?i:s,{min:a(i,a(s,i)),max:a(s,a(i,s))}}getPadding(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}}getTicks(){return this.ticks}getLabels(){const t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]}beforeLayout(){this._cache={},this._dataLimitsCached=!1}beforeUpdate(){c(this.options.beforeUpdate,[this])}update(t,e,i){const{beginAtZero:s,grace:n,ticks:o}=this.options,a=o.sampleSize;this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this._margins=i=Object.assign({left:0,right:0,top:0,bottom:0},i),this.ticks=null,this._labelSizes=null,this._gridLineItems=null,this._labelItems=null,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this._maxLength=this.isHorizontal()?this.width+i.left+i.right:this.height+i.top+i.bottom,this._dataLimitsCached||(this.beforeDataLimits(),this.determineDataLimits(),this.afterDataLimits(),this._range=xi(this,n,s),this._dataLimitsCached=!0),this.beforeBuildTicks(),this.ticks=this.buildTicks()||[],this.afterBuildTicks();const r=a<this.ticks.length;this._convertTicksToLabels(r?Bs(this.ticks,a):this.ticks),this.configure(),this.beforeCalculateLabelRotation(),this.calculateLabelRotation(),this.afterCalculateLabelRotation(),o.display&&(o.autoSkip||\"auto\"===o.source)&&(this.ticks=zs(this,this.ticks),this._labelSizes=null,this.afterAutoSkip()),r&&this._convertTicksToLabels(this.ticks),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate()}configure(){let t,e,i=this.options.reverse;this.isHorizontal()?(t=this.left,e=this.right):(t=this.top,e=this.bottom,i=!i),this._startPixel=t,this._endPixel=e,this._reversePixels=i,this._length=e-t,this._alignToPixels=this.options.alignToPixels}afterUpdate(){c(this.options.afterUpdate,[this])}beforeSetDimensions(){c(this.options.beforeSetDimensions,[this])}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0}afterSetDimensions(){c(this.options.afterSetDimensions,[this])}_callHooks(t){this.chart.notifyPlugins(t,this.getContext()),c(this.options[t],[this])}beforeDataLimits(){this._callHooks(\"beforeDataLimits\")}determineDataLimits(){}afterDataLimits(){this._callHooks(\"afterDataLimits\")}beforeBuildTicks(){this._callHooks(\"beforeBuildTicks\")}buildTicks(){return[]}afterBuildTicks(){this._callHooks(\"afterBuildTicks\")}beforeTickToLabelConversion(){c(this.options.beforeTickToLabelConversion,[this])}generateTickLabels(t){const e=this.options.ticks;let i,s,n;for(i=0,s=t.length;i<s;i++)n=t[i],n.label=c(e.callback,[n.value,i,t],this)}afterTickToLabelConversion(){c(this.options.afterTickToLabelConversion,[this])}beforeCalculateLabelRotation(){c(this.options.beforeCalculateLabelRotation,[this])}calculateLabelRotation(){const t=this.options,e=t.ticks,i=this.ticks.length,s=e.minRotation||0,n=e.maxRotation;let o,a,r,l=s;if(!this._isVisible()||!e.display||s>=n||i<=1||!this.isHorizontal())return void(this.labelRotation=s);const h=this._getLabelSizes(),c=h.widest.width,d=h.highest.height,u=Z(this.chart.width-c,0,this.maxWidth);o=t.offset?this.maxWidth/i:u/(i-1),c+6>o&&(o=u/(i-(t.offset?.5:1)),a=this.maxHeight-Ws(t.grid)-e.padding-js(t.title,this.chart.options.font),r=Math.sqrt(c*c+d*d),l=$(Math.min(Math.asin(Z((h.highest.height+6)/o,-1,1)),Math.asin(Z(a/r,-1,1))-Math.asin(Z(d/r,-1,1)))),l=Math.max(s,Math.min(n,l))),this.labelRotation=l}afterCalculateLabelRotation(){c(this.options.afterCalculateLabelRotation,[this])}afterAutoSkip(){}beforeFit(){c(this.options.beforeFit,[this])}fit(){const t={width:0,height:0},{chart:e,options:{ticks:i,title:s,grid:n}}=this,o=this._isVisible(),a=this.isHorizontal();if(o){const o=js(s,e.options.font);if(a?(t.width=this.maxWidth,t.height=Ws(n)+o):(t.height=this.maxHeight,t.width=Ws(n)+o),i.display&&this.ticks.length){const{first:e,last:s,widest:n,highest:o}=this._getLabelSizes(),r=2*i.padding,l=H(this.labelRotation),h=Math.cos(l),c=Math.sin(l);if(a){const e=i.mirror?0:c*n.width+h*o.height;t.height=Math.min(this.maxHeight,t.height+e+r)}else{const e=i.mirror?0:h*n.width+c*o.height;t.width=Math.min(this.maxWidth,t.width+e+r)}this._calculatePadding(e,s,c,h)}}this._handleMargins(),a?(this.width=this._length=e.width-this._margins.left-this._margins.right,this.height=t.height):(this.width=t.width,this.height=this._length=e.height-this._margins.top-this._margins.bottom)}_calculatePadding(t,e,i,s){const{ticks:{align:n,padding:o},position:a}=this.options,r=0!==this.labelRotation,l=\"top\"!==a&&\"x\"===this.axis;if(this.isHorizontal()){const a=this.getPixelForTick(0)-this.left,h=this.right-this.getPixelForTick(this.ticks.length-1);let c=0,d=0;r?l?(c=s*t.width,d=i*e.height):(c=i*t.height,d=s*e.width):\"start\"===n?d=e.width:\"end\"===n?c=t.width:\"inner\"!==n&&(c=t.width/2,d=e.width/2),this.paddingLeft=Math.max((c-a+o)*this.width/(this.width-a),0),this.paddingRight=Math.max((d-h+o)*this.width/(this.width-h),0)}else{let i=e.height/2,s=t.height/2;\"start\"===n?(i=0,s=t.height):\"end\"===n&&(i=e.height,s=0),this.paddingTop=i+o,this.paddingBottom=s+o}}_handleMargins(){this._margins&&(this._margins.left=Math.max(this.paddingLeft,this._margins.left),this._margins.top=Math.max(this.paddingTop,this._margins.top),this._margins.right=Math.max(this.paddingRight,this._margins.right),this._margins.bottom=Math.max(this.paddingBottom,this._margins.bottom))}afterFit(){c(this.options.afterFit,[this])}isHorizontal(){const{axis:t,position:e}=this.options;return\"top\"===e||\"bottom\"===e||\"x\"===t}isFullSize(){return this.options.fullSize}_convertTicksToLabels(t){let e,s;for(this.beforeTickToLabelConversion(),this.generateTickLabels(t),e=0,s=t.length;e<s;e++)i(t[e].label)&&(t.splice(e,1),s--,e--);this.afterTickToLabelConversion()}_getLabelSizes(){let t=this._labelSizes;if(!t){const e=this.options.ticks.sampleSize;let i=this.ticks;e<i.length&&(i=Bs(i,e)),this._labelSizes=t=this._computeLabelSizes(i,i.length)}return t}_computeLabelSizes(t,e){const{ctx:n,_longestTextCache:o}=this,a=[],r=[];let l,h,c,u,f,g,p,m,b,x,_,y=0,v=0;for(l=0;l<e;++l){if(u=t[l].label,f=this._resolveTickFontOptions(l),n.font=g=f.string,p=o[g]=o[g]||{data:{},gc:[]},m=f.lineHeight,b=x=0,i(u)||s(u)){if(s(u))for(h=0,c=u.length;h<c;++h)_=u[h],i(_)||s(_)||(b=_e(n,p.data,p.gc,b,_),x+=m)}else b=_e(n,p.data,p.gc,b,u),x=m;a.push(b),r.push(x),y=Math.max(b,y),v=Math.max(x,v)}!function(t,e){d(t,(t=>{const i=t.gc,s=i.length/2;let n;if(s>e){for(n=0;n<s;++n)delete t.data[i[n]];i.splice(0,s)}}))}(o,e);const w=a.indexOf(y),M=r.indexOf(v),k=t=>({width:a[t]||0,height:r[t]||0});return{first:k(0),last:k(e-1),widest:k(w),highest:k(M),widths:a,heights:r}}getLabelForValue(t){return t}getPixelForValue(t,e){return NaN}getValueForPixel(t){}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getPixelForDecimal(t){this._reversePixels&&(t=1-t);const e=this._startPixel+t*this._length;return J(this._alignToPixels?ve(this.chart,e,0):e)}getDecimalForPixel(t){const e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e}getBasePixel(){return this.getPixelForValue(this.getBaseValue())}getBaseValue(){const{min:t,max:e}=this;return t<0&&e<0?e:t>0&&e>0?t:0}getContext(t){const e=this.ticks||[];if(t>=0&&t<e.length){const i=e[t];return i.$context||(i.$context=function(t,e,i){return _i(t,{tick:i,index:e,type:\"tick\"})}(this.getContext(),t,i))}return this.$context||(this.$context=_i(this.chart.getContext(),{scale:this,type:\"scale\"}))}_tickSize(){const t=this.options.ticks,e=H(this.labelRotation),i=Math.abs(Math.cos(e)),s=Math.abs(Math.sin(e)),n=this._getLabelSizes(),o=t.autoSkipPadding||0,a=n?n.widest.width+o:0,r=n?n.highest.height+o:0;return this.isHorizontal()?r*i>a*s?a/i:r/s:r*s<a*i?r/i:a/s}_isVisible(){const t=this.options.display;return\"auto\"!==t?!!t:this.getMatchingVisibleMetas().length>0}_computeGridLineItems(t){const e=this.axis,i=this.chart,s=this.options,{grid:o,position:a}=s,l=o.offset,h=this.isHorizontal(),c=this.ticks.length+(l?1:0),d=Ws(o),u=[],f=o.setContext(this.getContext()),g=f.drawBorder?f.borderWidth:0,p=g/2,m=function(t){return ve(i,t,g)};let b,x,_,y,v,w,M,k,S,P,D,O;if(\"top\"===a)b=m(this.bottom),w=this.bottom-d,k=b-p,P=m(t.top)+p,O=t.bottom;else if(\"bottom\"===a)b=m(this.top),P=t.top,O=m(t.bottom)-p,w=b+p,k=this.top+d;else if(\"left\"===a)b=m(this.right),v=this.right-d,M=b-p,S=m(t.left)+p,D=t.right;else if(\"right\"===a)b=m(this.left),S=t.left,D=m(t.right)-p,v=b+p,M=this.left+d;else if(\"x\"===e){if(\"center\"===a)b=m((t.top+t.bottom)/2+.5);else if(n(a)){const t=Object.keys(a)[0],e=a[t];b=m(this.chart.scales[t].getPixelForValue(e))}P=t.top,O=t.bottom,w=b+p,k=w+d}else if(\"y\"===e){if(\"center\"===a)b=m((t.left+t.right)/2);else if(n(a)){const t=Object.keys(a)[0],e=a[t];b=m(this.chart.scales[t].getPixelForValue(e))}v=b-p,M=v-d,S=t.left,D=t.right}const C=r(s.ticks.maxTicksLimit,c),A=Math.max(1,Math.ceil(c/C));for(x=0;x<c;x+=A){const t=o.setContext(this.getContext(x)),e=t.lineWidth,s=t.color,n=t.borderDash||[],a=t.borderDashOffset,r=t.tickWidth,c=t.tickColor,d=t.tickBorderDash||[],f=t.tickBorderDashOffset;_=Ns(this,x,l),void 0!==_&&(y=ve(i,_,e),h?v=M=S=D=y:w=k=P=O=y,u.push({tx1:v,ty1:w,tx2:M,ty2:k,x1:S,y1:P,x2:D,y2:O,width:e,color:s,borderDash:n,borderDashOffset:a,tickWidth:r,tickColor:c,tickBorderDash:d,tickBorderDashOffset:f}))}return this._ticksLength=c,this._borderValue=b,u}_computeLabelItems(t){const e=this.axis,i=this.options,{position:o,ticks:a}=i,r=this.isHorizontal(),l=this.ticks,{align:h,crossAlign:c,padding:d,mirror:u}=a,f=Ws(i.grid),g=f+d,p=u?-d:g,m=-H(this.labelRotation),b=[];let x,_,y,v,w,M,k,S,P,D,O,C,A=\"middle\";if(\"top\"===o)M=this.bottom-p,k=this._getXAxisLabelAlignment();else if(\"bottom\"===o)M=this.top+p,k=this._getXAxisLabelAlignment();else if(\"left\"===o){const t=this._getYAxisLabelAlignment(f);k=t.textAlign,w=t.x}else if(\"right\"===o){const t=this._getYAxisLabelAlignment(f);k=t.textAlign,w=t.x}else if(\"x\"===e){if(\"center\"===o)M=(t.top+t.bottom)/2+g;else if(n(o)){const t=Object.keys(o)[0],e=o[t];M=this.chart.scales[t].getPixelForValue(e)+g}k=this._getXAxisLabelAlignment()}else if(\"y\"===e){if(\"center\"===o)w=(t.left+t.right)/2-g;else if(n(o)){const t=Object.keys(o)[0],e=o[t];w=this.chart.scales[t].getPixelForValue(e)}k=this._getYAxisLabelAlignment(f).textAlign}\"y\"===e&&(\"start\"===h?A=\"top\":\"end\"===h&&(A=\"bottom\"));const T=this._getLabelSizes();for(x=0,_=l.length;x<_;++x){y=l[x],v=y.label;const t=a.setContext(this.getContext(x));S=this.getPixelForTick(x)+a.labelOffset,P=this._resolveTickFontOptions(x),D=P.lineHeight,O=s(v)?v.length:1;const e=O/2,i=t.color,n=t.textStrokeColor,h=t.textStrokeWidth;let d,f=k;if(r?(w=S,\"inner\"===k&&(f=x===_-1?this.options.reverse?\"left\":\"right\":0===x?this.options.reverse?\"right\":\"left\":\"center\"),C=\"top\"===o?\"near\"===c||0!==m?-O*D+D/2:\"center\"===c?-T.highest.height/2-e*D+D:-T.highest.height+D/2:\"near\"===c||0!==m?D/2:\"center\"===c?T.highest.height/2-e*D:T.highest.height-O*D,u&&(C*=-1)):(M=S,C=(1-O)*D/2),t.showLabelBackdrop){const e=pi(t.backdropPadding),i=T.heights[x],s=T.widths[x];let n=M+C-e.top,o=w-e.left;switch(A){case\"middle\":n-=i/2;break;case\"bottom\":n-=i}switch(k){case\"center\":o-=s/2;break;case\"right\":o-=s}d={left:o,top:n,width:s+e.width,height:i+e.height,color:t.backdropColor}}b.push({rotation:m,label:v,font:P,color:i,strokeColor:n,strokeWidth:h,textOffset:C,textAlign:f,textBaseline:A,translation:[w,M],backdrop:d})}return b}_getXAxisLabelAlignment(){const{position:t,ticks:e}=this.options;if(-H(this.labelRotation))return\"top\"===t?\"left\":\"right\";let i=\"center\";return\"start\"===e.align?i=\"left\":\"end\"===e.align?i=\"right\":\"inner\"===e.align&&(i=\"inner\"),i}_getYAxisLabelAlignment(t){const{position:e,ticks:{crossAlign:i,mirror:s,padding:n}}=this.options,o=t+n,a=this._getLabelSizes().widest.width;let r,l;return\"left\"===e?s?(l=this.right+n,\"near\"===i?r=\"left\":\"center\"===i?(r=\"center\",l+=a/2):(r=\"right\",l+=a)):(l=this.right-o,\"near\"===i?r=\"right\":\"center\"===i?(r=\"center\",l-=a/2):(r=\"left\",l=this.left)):\"right\"===e?s?(l=this.left+n,\"near\"===i?r=\"right\":\"center\"===i?(r=\"center\",l-=a/2):(r=\"left\",l-=a)):(l=this.left+o,\"near\"===i?r=\"left\":\"center\"===i?(r=\"center\",l+=a/2):(r=\"right\",l=this.right)):r=\"right\",{textAlign:r,x:l}}_computeLabelArea(){if(this.options.ticks.mirror)return;const t=this.chart,e=this.options.position;return\"left\"===e||\"right\"===e?{top:0,left:this.left,bottom:t.height,right:this.right}:\"top\"===e||\"bottom\"===e?{top:this.top,left:0,bottom:this.bottom,right:t.width}:void 0}drawBackground(){const{ctx:t,options:{backgroundColor:e},left:i,top:s,width:n,height:o}=this;e&&(t.save(),t.fillStyle=e,t.fillRect(i,s,n,o),t.restore())}getLineWidthForValue(t){const e=this.options.grid;if(!this._isVisible()||!e.display)return 0;const i=this.ticks.findIndex((e=>e.value===t));if(i>=0){return e.setContext(this.getContext(i)).lineWidth}return 0}drawGrid(t){const e=this.options.grid,i=this.ctx,s=this._gridLineItems||(this._gridLineItems=this._computeGridLineItems(t));let n,o;const a=(t,e,s)=>{s.width&&s.color&&(i.save(),i.lineWidth=s.width,i.strokeStyle=s.color,i.setLineDash(s.borderDash||[]),i.lineDashOffset=s.borderDashOffset,i.beginPath(),i.moveTo(t.x,t.y),i.lineTo(e.x,e.y),i.stroke(),i.restore())};if(e.display)for(n=0,o=s.length;n<o;++n){const t=s[n];e.drawOnChartArea&&a({x:t.x1,y:t.y1},{x:t.x2,y:t.y2},t),e.drawTicks&&a({x:t.tx1,y:t.ty1},{x:t.tx2,y:t.ty2},{color:t.tickColor,width:t.tickWidth,borderDash:t.tickBorderDash,borderDashOffset:t.tickBorderDashOffset})}}drawBorder(){const{chart:t,ctx:e,options:{grid:i}}=this,s=i.setContext(this.getContext()),n=i.drawBorder?s.borderWidth:0;if(!n)return;const o=i.setContext(this.getContext(0)).lineWidth,a=this._borderValue;let r,l,h,c;this.isHorizontal()?(r=ve(t,this.left,n)-n/2,l=ve(t,this.right,o)+o/2,h=c=a):(h=ve(t,this.top,n)-n/2,c=ve(t,this.bottom,o)+o/2,r=l=a),e.save(),e.lineWidth=s.borderWidth,e.strokeStyle=s.borderColor,e.beginPath(),e.moveTo(r,h),e.lineTo(l,c),e.stroke(),e.restore()}drawLabels(t){if(!this.options.ticks.display)return;const e=this.ctx,i=this._computeLabelArea();i&&Pe(e,i);const s=this._labelItems||(this._labelItems=this._computeLabelItems(t));let n,o;for(n=0,o=s.length;n<o;++n){const t=s[n],i=t.font,o=t.label;t.backdrop&&(e.fillStyle=t.backdrop.color,e.fillRect(t.backdrop.left,t.backdrop.top,t.backdrop.width,t.backdrop.height)),Ae(e,o,0,t.textOffset,i,t)}i&&De(e)}drawTitle(){const{ctx:t,options:{position:e,title:i,reverse:o}}=this;if(!i.display)return;const a=mi(i.font),r=pi(i.padding),l=i.align;let h=a.lineHeight/2;\"bottom\"===e||\"center\"===e||n(e)?(h+=r.bottom,s(i.text)&&(h+=a.lineHeight*(i.text.length-1))):h+=r.top;const{titleX:c,titleY:d,maxWidth:u,rotation:f}=function(t,e,i,s){const{top:o,left:a,bottom:r,right:l,chart:h}=t,{chartArea:c,scales:d}=h;let u,f,g,p=0;const m=r-o,b=l-a;if(t.isHorizontal()){if(f=ut(s,a,l),n(i)){const t=Object.keys(i)[0],s=i[t];g=d[t].getPixelForValue(s)+m-e}else g=\"center\"===i?(c.bottom+c.top)/2+m-e:Vs(t,i,e);u=l-a}else{if(n(i)){const t=Object.keys(i)[0],s=i[t];f=d[t].getPixelForValue(s)-b+e}else f=\"center\"===i?(c.left+c.right)/2-b+e:Vs(t,i,e);g=ut(s,r,o),p=\"left\"===i?-L:L}return{titleX:f,titleY:g,maxWidth:u,rotation:p}}(this,h,e,l);Ae(t,i.text,0,0,a,{color:i.color,maxWidth:u,rotation:f,textAlign:Hs(l,e,o),textBaseline:\"middle\",translation:[c,d]})}draw(t){this._isVisible()&&(this.drawBackground(),this.drawGrid(t),this.drawBorder(),this.drawTitle(),this.drawLabels(t))}_layers(){const t=this.options,e=t.ticks&&t.ticks.z||0,i=r(t.grid&&t.grid.z,-1);return this._isVisible()&&this.draw===$s.prototype.draw?[{z:i,draw:t=>{this.drawBackground(),this.drawGrid(t),this.drawTitle()}},{z:i+1,draw:()=>{this.drawBorder()}},{z:e,draw:t=>{this.drawLabels(t)}}]:[{z:e,draw:t=>{this.draw(t)}}]}getMatchingVisibleMetas(t){const e=this.chart.getSortedVisibleDatasetMetas(),i=this.axis+\"AxisID\",s=[];let n,o;for(n=0,o=e.length;n<o;++n){const o=e[n];o[i]!==this.id||t&&o.type!==t||s.push(o)}return s}_resolveTickFontOptions(t){return mi(this.options.ticks.setContext(this.getContext(t)).font)}_maxDigits(){const t=this._resolveTickFontOptions(0).lineHeight;return(this.isHorizontal()?this.width:this.height)/t}}class Ys{constructor(t,e,i){this.type=t,this.scope=e,this.override=i,this.items=Object.create(null)}isForType(t){return Object.prototype.isPrototypeOf.call(this.type.prototype,t.prototype)}register(t){const e=Object.getPrototypeOf(t);let i;(function(t){return\"id\"in t&&\"defaults\"in t})(e)&&(i=this.register(e));const s=this.items,n=t.id,o=this.scope+\".\"+n;if(!n)throw new Error(\"class does not have id: \"+t);return n in s||(s[n]=t,function(t,e,i){const s=m(Object.create(null),[i?ne.get(i):{},ne.get(e),t.defaults]);ne.set(e,s),t.defaultRoutes&&function(t,e){Object.keys(e).forEach((i=>{const s=i.split(\".\"),n=s.pop(),o=[t].concat(s).join(\".\"),a=e[i].split(\".\"),r=a.pop(),l=a.join(\".\");ne.route(o,n,l,r)}))}(e,t.defaultRoutes);t.descriptors&&ne.describe(e,t.descriptors)}(t,o,i),this.override&&ne.override(t.id,t.overrides)),o}get(t){return this.items[t]}unregister(t){const e=this.items,i=t.id,s=this.scope;i in e&&delete e[i],s&&i in ne[s]&&(delete ne[s][i],this.override&&delete te[i])}}var Us=new class{constructor(){this.controllers=new Ys(Ls,\"datasets\",!0),this.elements=new Ys(Es,\"elements\"),this.plugins=new Ys(Object,\"plugins\"),this.scales=new Ys($s,\"scales\"),this._typedRegistries=[this.controllers,this.scales,this.elements]}add(...t){this._each(\"register\",t)}remove(...t){this._each(\"unregister\",t)}addControllers(...t){this._each(\"register\",t,this.controllers)}addElements(...t){this._each(\"register\",t,this.elements)}addPlugins(...t){this._each(\"register\",t,this.plugins)}addScales(...t){this._each(\"register\",t,this.scales)}getController(t){return this._get(t,this.controllers,\"controller\")}getElement(t){return this._get(t,this.elements,\"element\")}getPlugin(t){return this._get(t,this.plugins,\"plugin\")}getScale(t){return this._get(t,this.scales,\"scale\")}removeControllers(...t){this._each(\"unregister\",t,this.controllers)}removeElements(...t){this._each(\"unregister\",t,this.elements)}removePlugins(...t){this._each(\"unregister\",t,this.plugins)}removeScales(...t){this._each(\"unregister\",t,this.scales)}_each(t,e,i){[...e].forEach((e=>{const s=i||this._getRegistryForType(e);i||s.isForType(e)||s===this.plugins&&e.id?this._exec(t,s,e):d(e,(e=>{const s=i||this._getRegistryForType(e);this._exec(t,s,e)}))}))}_exec(t,e,i){const s=w(t);c(i[\"before\"+s],[],i),e[t](i),c(i[\"after\"+s],[],i)}_getRegistryForType(t){for(let e=0;e<this._typedRegistries.length;e++){const i=this._typedRegistries[e];if(i.isForType(t))return i}return this.plugins}_get(t,e,i){const s=e.get(t);if(void 0===s)throw new Error('\"'+t+'\" is not a registered '+i+\".\");return s}};class Xs{constructor(){this._init=[]}notify(t,e,i,s){\"beforeInit\"===e&&(this._init=this._createDescriptors(t,!0),this._notify(this._init,t,\"install\"));const n=s?this._descriptors(t).filter(s):this._descriptors(t),o=this._notify(n,t,e,i);return\"afterDestroy\"===e&&(this._notify(n,t,\"stop\"),this._notify(this._init,t,\"uninstall\")),o}_notify(t,e,i,s){s=s||{};for(const n of t){const t=n.plugin;if(!1===c(t[i],[e,s,n.options],t)&&s.cancelable)return!1}return!0}invalidate(){i(this._cache)||(this._oldCache=this._cache,this._cache=void 0)}_descriptors(t){if(this._cache)return this._cache;const e=this._cache=this._createDescriptors(t);return this._notifyStateChanges(t),e}_createDescriptors(t,e){const i=t&&t.config,s=r(i.options&&i.options.plugins,{}),n=function(t){const e={},i=[],s=Object.keys(Us.plugins.items);for(let t=0;t<s.length;t++)i.push(Us.getPlugin(s[t]));const n=t.plugins||[];for(let t=0;t<n.length;t++){const s=n[t];-1===i.indexOf(s)&&(i.push(s),e[s.id]=!0)}return{plugins:i,localIds:e}}(i);return!1!==s||e?function(t,{plugins:e,localIds:i},s,n){const o=[],a=t.getContext();for(const r of e){const e=r.id,l=qs(s[e],n);null!==l&&o.push({plugin:r,options:Ks(t.config,{plugin:r,local:i[e]},l,a)})}return o}(t,n,s,e):[]}_notifyStateChanges(t){const e=this._oldCache||[],i=this._cache,s=(t,e)=>t.filter((t=>!e.some((e=>t.plugin.id===e.plugin.id))));this._notify(s(e,i),t,\"stop\"),this._notify(s(i,e),t,\"start\")}}function qs(t,e){return e||!1!==t?!0===t?{}:t:null}function Ks(t,{plugin:e,local:i},s,n){const o=t.pluginScopeKeys(e),a=t.getOptionScopes(s,o);return i&&e.defaults&&a.push(e.defaults),t.createResolver(a,n,[\"\"],{scriptable:!1,indexable:!1,allKeys:!0})}function Gs(t,e){const i=ne.datasets[t]||{};return((e.datasets||{})[t]||{}).indexAxis||e.indexAxis||i.indexAxis||\"x\"}function Zs(t,e){return\"x\"===t||\"y\"===t?t:e.axis||(\"top\"===(i=e.position)||\"bottom\"===i?\"x\":\"left\"===i||\"right\"===i?\"y\":void 0)||t.charAt(0).toLowerCase();var i}function Js(t){const e=t.options||(t.options={});e.plugins=r(e.plugins,{}),e.scales=function(t,e){const i=te[t.type]||{scales:{}},s=e.scales||{},o=Gs(t.type,e),a=Object.create(null),r=Object.create(null);return Object.keys(s).forEach((t=>{const e=s[t];if(!n(e))return console.error(`Invalid scale configuration for scale: ${t}`);if(e._proxy)return console.warn(`Ignoring resolver passed as options for scale: ${t}`);const l=Zs(t,e),h=function(t,e){return t===e?\"_index_\":\"_value_\"}(l,o),c=i.scales||{};a[l]=a[l]||t,r[t]=b(Object.create(null),[{axis:l},e,c[l],c[h]])})),t.data.datasets.forEach((i=>{const n=i.type||t.type,o=i.indexAxis||Gs(n,e),l=(te[n]||{}).scales||{};Object.keys(l).forEach((t=>{const e=function(t,e){let i=t;return\"_index_\"===t?i=e:\"_value_\"===t&&(i=\"x\"===e?\"y\":\"x\"),i}(t,o),n=i[e+\"AxisID\"]||a[e]||e;r[n]=r[n]||Object.create(null),b(r[n],[{axis:e},s[n],l[t]])}))})),Object.keys(r).forEach((t=>{const e=r[t];b(e,[ne.scales[e.type],ne.scale])})),r}(t,e)}function Qs(t){return(t=t||{}).datasets=t.datasets||[],t.labels=t.labels||[],t}const tn=new Map,en=new Set;function sn(t,e){let i=tn.get(t);return i||(i=e(),tn.set(t,i),en.add(i)),i}const nn=(t,e,i)=>{const s=y(e,i);void 0!==s&&t.add(s)};class on{constructor(t){this._config=function(t){return(t=t||{}).data=Qs(t.data),Js(t),t}(t),this._scopeCache=new Map,this._resolverCache=new Map}get platform(){return this._config.platform}get type(){return this._config.type}set type(t){this._config.type=t}get data(){return this._config.data}set data(t){this._config.data=Qs(t)}get options(){return this._config.options}set options(t){this._config.options=t}get plugins(){return this._config.plugins}update(){const t=this._config;this.clearCache(),Js(t)}clearCache(){this._scopeCache.clear(),this._resolverCache.clear()}datasetScopeKeys(t){return sn(t,(()=>[[`datasets.${t}`,\"\"]]))}datasetAnimationScopeKeys(t,e){return sn(`${t}.transition.${e}`,(()=>[[`datasets.${t}.transitions.${e}`,`transitions.${e}`],[`datasets.${t}`,\"\"]]))}datasetElementScopeKeys(t,e){return sn(`${t}-${e}`,(()=>[[`datasets.${t}.elements.${e}`,`datasets.${t}`,`elements.${e}`,\"\"]]))}pluginScopeKeys(t){const e=t.id;return sn(`${this.type}-plugin-${e}`,(()=>[[`plugins.${e}`,...t.additionalOptionScopes||[]]]))}_cachedScopes(t,e){const i=this._scopeCache;let s=i.get(t);return s&&!e||(s=new Map,i.set(t,s)),s}getOptionScopes(t,e,i){const{options:s,type:n}=this,o=this._cachedScopes(t,i),a=o.get(e);if(a)return a;const r=new Set;e.forEach((e=>{t&&(r.add(t),e.forEach((e=>nn(r,t,e)))),e.forEach((t=>nn(r,s,t))),e.forEach((t=>nn(r,te[n]||{},t))),e.forEach((t=>nn(r,ne,t))),e.forEach((t=>nn(r,ee,t)))}));const l=Array.from(r);return 0===l.length&&l.push(Object.create(null)),en.has(e)&&o.set(e,l),l}chartOptionScopes(){const{options:t,type:e}=this;return[t,te[e]||{},ne.datasets[e]||{},{type:e},ne,ee]}resolveNamedOptions(t,e,i,n=[\"\"]){const o={$shared:!0},{resolver:a,subPrefixes:r}=an(this._resolverCache,t,n);let l=a;if(function(t,e){const{isScriptable:i,isIndexable:n}=Ie(t);for(const o of e){const e=i(o),a=n(o),r=(a||e)&&t[o];if(e&&(k(r)||rn(r))||a&&s(r))return!0}return!1}(a,e)){o.$shared=!1;l=Re(a,i=k(i)?i():i,this.createResolver(t,i,r))}for(const t of e)o[t]=l[t];return o}createResolver(t,e,i=[\"\"],s){const{resolver:o}=an(this._resolverCache,t,i);return n(e)?Re(o,e,void 0,s):o}}function an(t,e,i){let s=t.get(e);s||(s=new Map,t.set(e,s));const n=i.join();let o=s.get(n);if(!o){o={resolver:Ee(e,i),subPrefixes:i.filter((t=>!t.toLowerCase().includes(\"hover\")))},s.set(n,o)}return o}const rn=t=>n(t)&&Object.getOwnPropertyNames(t).reduce(((e,i)=>e||k(t[i])),!1);const ln=[\"top\",\"bottom\",\"left\",\"right\",\"chartArea\"];function hn(t,e){return\"top\"===t||\"bottom\"===t||-1===ln.indexOf(t)&&\"x\"===e}function cn(t,e){return function(i,s){return i[t]===s[t]?i[e]-s[e]:i[t]-s[t]}}function dn(t){const e=t.chart,i=e.options.animation;e.notifyPlugins(\"afterRender\"),c(i&&i.onComplete,[t],e)}function un(t){const e=t.chart,i=e.options.animation;c(i&&i.onProgress,[t],e)}function fn(t){return oe()&&\"string\"==typeof t?t=document.getElementById(t):t&&t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas),t}const gn={},pn=t=>{const e=fn(t);return Object.values(gn).filter((t=>t.canvas===e)).pop()};function mn(t,e,i){const s=Object.keys(t);for(const n of s){const s=+n;if(s>=e){const o=t[n];delete t[n],(i>0||s>e)&&(t[s+i]=o)}}}class bn{constructor(t,i){const s=this.config=new on(i),n=fn(t),o=pn(n);if(o)throw new Error(\"Canvas is already in use. Chart with ID '\"+o.id+\"' must be destroyed before the canvas with ID '\"+o.canvas.id+\"' can be reused.\");const a=s.createResolver(s.chartOptionScopes(),this.getContext());this.platform=new(s.platform||gs(n)),this.platform.updateConfig(s);const r=this.platform.acquireContext(n,a.aspectRatio),l=r&&r.canvas,h=l&&l.height,c=l&&l.width;this.id=e(),this.ctx=r,this.canvas=l,this.width=c,this.height=h,this._options=a,this._aspectRatio=this.aspectRatio,this._layers=[],this._metasets=[],this._stacks=void 0,this.boxes=[],this.currentDevicePixelRatio=void 0,this.chartArea=void 0,this._active=[],this._lastEvent=void 0,this._listeners={},this._responsiveListeners=void 0,this._sortedMetasets=[],this.scales={},this._plugins=new Xs,this.$proxies={},this._hiddenIndices={},this.attached=!1,this._animationsDisabled=void 0,this.$context=void 0,this._doResize=ct((t=>this.update(t)),a.resizeDelay||0),this._dataChanges=[],gn[this.id]=this,r&&l?(mt.listen(this,\"complete\",dn),mt.listen(this,\"progress\",un),this._initialize(),this.attached&&this.update()):console.error(\"Failed to create chart: can't acquire context from the given item\")}get aspectRatio(){const{options:{aspectRatio:t,maintainAspectRatio:e},width:s,height:n,_aspectRatio:o}=this;return i(t)?e&&o?o:n?s/n:null:t}get data(){return this.config.data}set data(t){this.config.data=t}get options(){return this._options}set options(t){this.config.options=t}_initialize(){return this.notifyPlugins(\"beforeInit\"),this.options.responsive?this.resize():pe(this,this.options.devicePixelRatio),this.bindEvents(),this.notifyPlugins(\"afterInit\"),this}clear(){return we(this.canvas,this.ctx),this}stop(){return mt.stop(this),this}resize(t,e){mt.running(this)?this._resizeBeforeDraw={width:t,height:e}:this._resize(t,e)}_resize(t,e){const i=this.options,s=this.canvas,n=i.maintainAspectRatio&&this.aspectRatio,o=this.platform.getMaximumSize(s,t,e,n),a=i.devicePixelRatio||this.platform.getDevicePixelRatio(),r=this.width?\"resize\":\"attach\";this.width=o.width,this.height=o.height,this._aspectRatio=this.aspectRatio,pe(this,a,!0)&&(this.notifyPlugins(\"resize\",{size:o}),c(i.onResize,[this,o],this),this.attached&&this._doResize(r)&&this.render())}ensureScalesHaveIDs(){d(this.options.scales||{},((t,e)=>{t.id=e}))}buildOrUpdateScales(){const t=this.options,e=t.scales,i=this.scales,s=Object.keys(i).reduce(((t,e)=>(t[e]=!1,t)),{});let n=[];e&&(n=n.concat(Object.keys(e).map((t=>{const i=e[t],s=Zs(t,i),n=\"r\"===s,o=\"x\"===s;return{options:i,dposition:n?\"chartArea\":o?\"bottom\":\"left\",dtype:n?\"radialLinear\":o?\"category\":\"linear\"}})))),d(n,(e=>{const n=e.options,o=n.id,a=Zs(o,n),l=r(n.type,e.dtype);void 0!==n.position&&hn(n.position,a)===hn(e.dposition)||(n.position=e.dposition),s[o]=!0;let h=null;if(o in i&&i[o].type===l)h=i[o];else{h=new(Us.getScale(l))({id:o,type:l,ctx:this.ctx,chart:this}),i[h.id]=h}h.init(n,t)})),d(s,((t,e)=>{t||delete i[e]})),d(i,(t=>{Zi.configure(this,t,t.options),Zi.addBox(this,t)}))}_updateMetasets(){const t=this._metasets,e=this.data.datasets.length,i=t.length;if(t.sort(((t,e)=>t.index-e.index)),i>e){for(let t=e;t<i;++t)this._destroyDatasetMeta(t);t.splice(e,i-e)}this._sortedMetasets=t.slice(0).sort(cn(\"order\",\"index\"))}_removeUnreferencedMetasets(){const{_metasets:t,data:{datasets:e}}=this;t.length>e.length&&delete this._stacks,t.forEach(((t,i)=>{0===e.filter((e=>e===t._dataset)).length&&this._destroyDatasetMeta(i)}))}buildOrUpdateControllers(){const t=[],e=this.data.datasets;let i,s;for(this._removeUnreferencedMetasets(),i=0,s=e.length;i<s;i++){const s=e[i];let n=this.getDatasetMeta(i);const o=s.type||this.config.type;if(n.type&&n.type!==o&&(this._destroyDatasetMeta(i),n=this.getDatasetMeta(i)),n.type=o,n.indexAxis=s.indexAxis||Gs(o,this.options),n.order=s.order||0,n.index=i,n.label=\"\"+s.label,n.visible=this.isDatasetVisible(i),n.controller)n.controller.updateIndex(i),n.controller.linkScales();else{const e=Us.getController(o),{datasetElementType:s,dataElementType:a}=ne.datasets[o];Object.assign(e.prototype,{dataElementType:Us.getElement(a),datasetElementType:s&&Us.getElement(s)}),n.controller=new e(this,i),t.push(n.controller)}}return this._updateMetasets(),t}_resetElements(){d(this.data.datasets,((t,e)=>{this.getDatasetMeta(e).controller.reset()}),this)}reset(){this._resetElements(),this.notifyPlugins(\"reset\")}update(t){const e=this.config;e.update();const i=this._options=e.createResolver(e.chartOptionScopes(),this.getContext()),s=this._animationsDisabled=!i.animation;if(this._updateScales(),this._checkEventBindings(),this._updateHiddenIndices(),this._plugins.invalidate(),!1===this.notifyPlugins(\"beforeUpdate\",{mode:t,cancelable:!0}))return;const n=this.buildOrUpdateControllers();this.notifyPlugins(\"beforeElementsUpdate\");let o=0;for(let t=0,e=this.data.datasets.length;t<e;t++){const{controller:e}=this.getDatasetMeta(t),i=!s&&-1===n.indexOf(e);e.buildOrUpdateElements(i),o=Math.max(+e.getMaxOverflow(),o)}o=this._minPadding=i.layout.autoPadding?o:0,this._updateLayout(o),s||d(n,(t=>{t.reset()})),this._updateDatasets(t),this.notifyPlugins(\"afterUpdate\",{mode:t}),this._layers.sort(cn(\"z\",\"_idx\"));const{_active:a,_lastEvent:r}=this;r?this._eventHandler(r,!0):a.length&&this._updateHoverStyles(a,a,!0),this.render()}_updateScales(){d(this.scales,(t=>{Zi.removeBox(this,t)})),this.ensureScalesHaveIDs(),this.buildOrUpdateScales()}_checkEventBindings(){const t=this.options,e=new Set(Object.keys(this._listeners)),i=new Set(t.events);S(e,i)&&!!this._responsiveListeners===t.responsive||(this.unbindEvents(),this.bindEvents())}_updateHiddenIndices(){const{_hiddenIndices:t}=this,e=this._getUniformDataChanges()||[];for(const{method:i,start:s,count:n}of e){mn(t,s,\"_removeElements\"===i?-n:n)}}_getUniformDataChanges(){const t=this._dataChanges;if(!t||!t.length)return;this._dataChanges=[];const e=this.data.datasets.length,i=e=>new Set(t.filter((t=>t[0]===e)).map(((t,e)=>e+\",\"+t.splice(1).join(\",\")))),s=i(0);for(let t=1;t<e;t++)if(!S(s,i(t)))return;return Array.from(s).map((t=>t.split(\",\"))).map((t=>({method:t[1],start:+t[2],count:+t[3]})))}_updateLayout(t){if(!1===this.notifyPlugins(\"beforeLayout\",{cancelable:!0}))return;Zi.update(this,this.width,this.height,t);const e=this.chartArea,i=e.width<=0||e.height<=0;this._layers=[],d(this.boxes,(t=>{i&&\"chartArea\"===t.position||(t.configure&&t.configure(),this._layers.push(...t._layers()))}),this),this._layers.forEach(((t,e)=>{t._idx=e})),this.notifyPlugins(\"afterLayout\")}_updateDatasets(t){if(!1!==this.notifyPlugins(\"beforeDatasetsUpdate\",{mode:t,cancelable:!0})){for(let t=0,e=this.data.datasets.length;t<e;++t)this.getDatasetMeta(t).controller.configure();for(let e=0,i=this.data.datasets.length;e<i;++e)this._updateDataset(e,k(t)?t({datasetIndex:e}):t);this.notifyPlugins(\"afterDatasetsUpdate\",{mode:t})}}_updateDataset(t,e){const i=this.getDatasetMeta(t),s={meta:i,index:t,mode:e,cancelable:!0};!1!==this.notifyPlugins(\"beforeDatasetUpdate\",s)&&(i.controller._update(e),s.cancelable=!1,this.notifyPlugins(\"afterDatasetUpdate\",s))}render(){!1!==this.notifyPlugins(\"beforeRender\",{cancelable:!0})&&(mt.has(this)?this.attached&&!mt.running(this)&&mt.start(this):(this.draw(),dn({chart:this})))}draw(){let t;if(this._resizeBeforeDraw){const{width:t,height:e}=this._resizeBeforeDraw;this._resize(t,e),this._resizeBeforeDraw=null}if(this.clear(),this.width<=0||this.height<=0)return;if(!1===this.notifyPlugins(\"beforeDraw\",{cancelable:!0}))return;const e=this._layers;for(t=0;t<e.length&&e[t].z<=0;++t)e[t].draw(this.chartArea);for(this._drawDatasets();t<e.length;++t)e[t].draw(this.chartArea);this.notifyPlugins(\"afterDraw\")}_getSortedDatasetMetas(t){const e=this._sortedMetasets,i=[];let s,n;for(s=0,n=e.length;s<n;++s){const n=e[s];t&&!n.visible||i.push(n)}return i}getSortedVisibleDatasetMetas(){return this._getSortedDatasetMetas(!0)}_drawDatasets(){if(!1===this.notifyPlugins(\"beforeDatasetsDraw\",{cancelable:!0}))return;const t=this.getSortedVisibleDatasetMetas();for(let e=t.length-1;e>=0;--e)this._drawDataset(t[e]);this.notifyPlugins(\"afterDatasetsDraw\")}_drawDataset(t){const e=this.ctx,i=t._clip,s=!i.disabled,n=this.chartArea,o={meta:t,index:t.index,cancelable:!0};!1!==this.notifyPlugins(\"beforeDatasetDraw\",o)&&(s&&Pe(e,{left:!1===i.left?0:n.left-i.left,right:!1===i.right?this.width:n.right+i.right,top:!1===i.top?0:n.top-i.top,bottom:!1===i.bottom?this.height:n.bottom+i.bottom}),t.controller.draw(),s&&De(e),o.cancelable=!1,this.notifyPlugins(\"afterDatasetDraw\",o))}isPointInArea(t){return Se(t,this.chartArea,this._minPadding)}getElementsAtEventForMode(t,e,i,s){const n=Vi.modes[e];return\"function\"==typeof n?n(this,t,i,s):[]}getDatasetMeta(t){const e=this.data.datasets[t],i=this._metasets;let s=i.filter((t=>t&&t._dataset===e)).pop();return s||(s={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e&&e.order||0,index:t,_dataset:e,_parsed:[],_sorted:!1},i.push(s)),s}getContext(){return this.$context||(this.$context=_i(null,{chart:this,type:\"chart\"}))}getVisibleDatasetCount(){return this.getSortedVisibleDatasetMetas().length}isDatasetVisible(t){const e=this.data.datasets[t];if(!e)return!1;const i=this.getDatasetMeta(t);return\"boolean\"==typeof i.hidden?!i.hidden:!e.hidden}setDatasetVisibility(t,e){this.getDatasetMeta(t).hidden=!e}toggleDataVisibility(t){this._hiddenIndices[t]=!this._hiddenIndices[t]}getDataVisibility(t){return!this._hiddenIndices[t]}_updateVisibility(t,e,i){const s=i?\"show\":\"hide\",n=this.getDatasetMeta(t),o=n.controller._resolveAnimations(void 0,s);M(e)?(n.data[e].hidden=!i,this.update()):(this.setDatasetVisibility(t,i),o.update(n,{visible:i}),this.update((e=>e.datasetIndex===t?s:void 0)))}hide(t,e){this._updateVisibility(t,e,!1)}show(t,e){this._updateVisibility(t,e,!0)}_destroyDatasetMeta(t){const e=this._metasets[t];e&&e.controller&&e.controller._destroy(),delete this._metasets[t]}_stop(){let t,e;for(this.stop(),mt.remove(this),t=0,e=this.data.datasets.length;t<e;++t)this._destroyDatasetMeta(t)}destroy(){this.notifyPlugins(\"beforeDestroy\");const{canvas:t,ctx:e}=this;this._stop(),this.config.clearCache(),t&&(this.unbindEvents(),we(t,e),this.platform.releaseContext(e),this.canvas=null,this.ctx=null),this.notifyPlugins(\"destroy\"),delete gn[this.id],this.notifyPlugins(\"afterDestroy\")}toBase64Image(...t){return this.canvas.toDataURL(...t)}bindEvents(){this.bindUserEvents(),this.options.responsive?this.bindResponsiveEvents():this.attached=!0}bindUserEvents(){const t=this._listeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(t,e,i)=>{t.offsetX=e,t.offsetY=i,this._eventHandler(t)};d(this.options.events,(t=>i(t,s)))}bindResponsiveEvents(){this._responsiveListeners||(this._responsiveListeners={});const t=this._responsiveListeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(i,s)=>{t[i]&&(e.removeEventListener(this,i,s),delete t[i])},n=(t,e)=>{this.canvas&&this.resize(t,e)};let o;const a=()=>{s(\"attach\",a),this.attached=!0,this.resize(),i(\"resize\",n),i(\"detach\",o)};o=()=>{this.attached=!1,s(\"resize\",n),this._stop(),this._resize(0,0),i(\"attach\",a)},e.isAttached(this.canvas)?a():o()}unbindEvents(){d(this._listeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._listeners={},d(this._responsiveListeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._responsiveListeners=void 0}updateHoverStyle(t,e,i){const s=i?\"set\":\"remove\";let n,o,a,r;for(\"dataset\"===e&&(n=this.getDatasetMeta(t[0].datasetIndex),n.controller[\"_\"+s+\"DatasetHoverStyle\"]()),a=0,r=t.length;a<r;++a){o=t[a];const e=o&&this.getDatasetMeta(o.datasetIndex).controller;e&&e[s+\"HoverStyle\"](o.element,o.datasetIndex,o.index)}}getActiveElements(){return this._active||[]}setActiveElements(t){const e=this._active||[],i=t.map((({datasetIndex:t,index:e})=>{const i=this.getDatasetMeta(t);if(!i)throw new Error(\"No dataset found at index \"+t);return{datasetIndex:t,element:i.data[e],index:e}}));!u(i,e)&&(this._active=i,this._lastEvent=null,this._updateHoverStyles(i,e))}notifyPlugins(t,e,i){return this._plugins.notify(this,t,e,i)}_updateHoverStyles(t,e,i){const s=this.options.hover,n=(t,e)=>t.filter((t=>!e.some((e=>t.datasetIndex===e.datasetIndex&&t.index===e.index)))),o=n(e,t),a=i?t:n(t,e);o.length&&this.updateHoverStyle(o,s.mode,!1),a.length&&s.mode&&this.updateHoverStyle(a,s.mode,!0)}_eventHandler(t,e){const i={event:t,replay:e,cancelable:!0,inChartArea:this.isPointInArea(t)},s=e=>(e.options.events||this.options.events).includes(t.native.type);if(!1===this.notifyPlugins(\"beforeEvent\",i,s))return;const n=this._handleEvent(t,e,i.inChartArea);return i.cancelable=!1,this.notifyPlugins(\"afterEvent\",i,s),(n||i.changed)&&this.render(),this}_handleEvent(t,e,i){const{_active:s=[],options:n}=this,o=e,a=this._getActiveElements(t,s,i,o),r=P(t),l=function(t,e,i,s){return i&&\"mouseout\"!==t.type?s?e:t:null}(t,this._lastEvent,i,r);i&&(this._lastEvent=null,c(n.onHover,[t,a,this],this),r&&c(n.onClick,[t,a,this],this));const h=!u(a,s);return(h||e)&&(this._active=a,this._updateHoverStyles(a,s,e)),this._lastEvent=l,h}_getActiveElements(t,e,i,s){if(\"mouseout\"===t.type)return[];if(!i)return e;const n=this.options.hover;return this.getElementsAtEventForMode(t,n.mode,n,s)}}const xn=()=>d(bn.instances,(t=>t._plugins.invalidate())),_n=!0;function yn(){throw new Error(\"This method is not implemented: Check that a complete date adapter is provided.\")}Object.defineProperties(bn,{defaults:{enumerable:_n,value:ne},instances:{enumerable:_n,value:gn},overrides:{enumerable:_n,value:te},registry:{enumerable:_n,value:Us},version:{enumerable:_n,value:\"3.9.1\"},getChart:{enumerable:_n,value:pn},register:{enumerable:_n,value:(...t)=>{Us.add(...t),xn()}},unregister:{enumerable:_n,value:(...t)=>{Us.remove(...t),xn()}}});class vn{constructor(t){this.options=t||{}}init(t){}formats(){return yn()}parse(t,e){return yn()}format(t,e){return yn()}add(t,e,i){return yn()}diff(t,e,i){return yn()}startOf(t,e,i){return yn()}endOf(t,e){return yn()}}vn.override=function(t){Object.assign(vn.prototype,t)};var wn={_date:vn};function Mn(t){const e=t.iScale,i=function(t,e){if(!t._cache.$bar){const i=t.getMatchingVisibleMetas(e);let s=[];for(let e=0,n=i.length;e<n;e++)s=s.concat(i[e].controller.getAllParsedValues(t));t._cache.$bar=rt(s.sort(((t,e)=>t-e)))}return t._cache.$bar}(e,t.type);let s,n,o,a,r=e._length;const l=()=>{32767!==o&&-32768!==o&&(M(a)&&(r=Math.min(r,Math.abs(o-a)||r)),a=o)};for(s=0,n=i.length;s<n;++s)o=e.getPixelForValue(i[s]),l();for(a=void 0,s=0,n=e.ticks.length;s<n;++s)o=e.getPixelForTick(s),l();return r}function kn(t,e,i,n){return s(t)?function(t,e,i,s){const n=i.parse(t[0],s),o=i.parse(t[1],s),a=Math.min(n,o),r=Math.max(n,o);let l=a,h=r;Math.abs(a)>Math.abs(r)&&(l=r,h=a),e[i.axis]=h,e._custom={barStart:l,barEnd:h,start:n,end:o,min:a,max:r}}(t,e,i,n):e[i.axis]=i.parse(t,n),e}function Sn(t,e,i,s){const n=t.iScale,o=t.vScale,a=n.getLabels(),r=n===o,l=[];let h,c,d,u;for(h=i,c=i+s;h<c;++h)u=e[h],d={},d[n.axis]=r||n.parse(a[h],h),l.push(kn(u,d,o,h));return l}function Pn(t){return t&&void 0!==t.barStart&&void 0!==t.barEnd}function Dn(t,e,i,s){let n=e.borderSkipped;const o={};if(!n)return void(t.borderSkipped=o);if(!0===n)return void(t.borderSkipped={top:!0,right:!0,bottom:!0,left:!0});const{start:a,end:r,reverse:l,top:h,bottom:c}=function(t){let e,i,s,n,o;return t.horizontal?(e=t.base>t.x,i=\"left\",s=\"right\"):(e=t.base<t.y,i=\"bottom\",s=\"top\"),e?(n=\"end\",o=\"start\"):(n=\"start\",o=\"end\"),{start:i,end:s,reverse:e,top:n,bottom:o}}(t);\"middle\"===n&&i&&(t.enableBorderRadius=!0,(i._top||0)===s?n=h:(i._bottom||0)===s?n=c:(o[On(c,a,r,l)]=!0,n=h)),o[On(n,a,r,l)]=!0,t.borderSkipped=o}function On(t,e,i,s){var n,o,a;return s?(a=i,t=Cn(t=(n=t)===(o=e)?a:n===a?o:n,i,e)):t=Cn(t,e,i),t}function Cn(t,e,i){return\"start\"===t?e:\"end\"===t?i:t}function An(t,{inflateAmount:e},i){t.inflateAmount=\"auto\"===e?1===i?.33:0:e}class Tn extends Ls{parsePrimitiveData(t,e,i,s){return Sn(t,e,i,s)}parseArrayData(t,e,i,s){return Sn(t,e,i,s)}parseObjectData(t,e,i,s){const{iScale:n,vScale:o}=t,{xAxisKey:a=\"x\",yAxisKey:r=\"y\"}=this._parsing,l=\"x\"===n.axis?a:r,h=\"x\"===o.axis?a:r,c=[];let d,u,f,g;for(d=i,u=i+s;d<u;++d)g=e[d],f={},f[n.axis]=n.parse(y(g,l),d),c.push(kn(y(g,h),f,o,d));return c}updateRangeFromParsed(t,e,i,s){super.updateRangeFromParsed(t,e,i,s);const n=i._custom;n&&e===this._cachedMeta.vScale&&(t.min=Math.min(t.min,n.min),t.max=Math.max(t.max,n.max))}getMaxOverflow(){return 0}getLabelAndValue(t){const e=this._cachedMeta,{iScale:i,vScale:s}=e,n=this.getParsed(t),o=n._custom,a=Pn(o)?\"[\"+o.start+\", \"+o.end+\"]\":\"\"+s.getLabelForValue(n[s.axis]);return{label:\"\"+i.getLabelForValue(n[i.axis]),value:a}}initialize(){this.enableOptionSharing=!0,super.initialize();this._cachedMeta.stack=this.getDataset().stack}update(t){const e=this._cachedMeta;this.updateElements(e.data,0,e.data.length,t)}updateElements(t,e,s,n){const o=\"reset\"===n,{index:a,_cachedMeta:{vScale:r}}=this,l=r.getBasePixel(),h=r.isHorizontal(),c=this._getRuler(),{sharedOptions:d,includeOptions:u}=this._getSharedOptions(e,n);for(let f=e;f<e+s;f++){const e=this.getParsed(f),s=o||i(e[r.axis])?{base:l,head:l}:this._calculateBarValuePixels(f),g=this._calculateBarIndexPixels(f,c),p=(e._stacks||{})[r.axis],m={horizontal:h,base:s.base,enableBorderRadius:!p||Pn(e._custom)||a===p._top||a===p._bottom,x:h?s.head:g.center,y:h?g.center:s.head,height:h?g.size:Math.abs(s.size),width:h?Math.abs(s.size):g.size};u&&(m.options=d||this.resolveDataElementOptions(f,t[f].active?\"active\":n));const b=m.options||t[f].options;Dn(m,b,p,a),An(m,b,c.ratio),this.updateElement(t[f],f,m,n)}}_getStacks(t,e){const{iScale:s}=this._cachedMeta,n=s.getMatchingVisibleMetas(this._type).filter((t=>t.controller.options.grouped)),o=s.options.stacked,a=[],r=t=>{const s=t.controller.getParsed(e),n=s&&s[t.vScale.axis];if(i(n)||isNaN(n))return!0};for(const i of n)if((void 0===e||!r(i))&&((!1===o||-1===a.indexOf(i.stack)||void 0===o&&void 0===i.stack)&&a.push(i.stack),i.index===t))break;return a.length||a.push(void 0),a}_getStackCount(t){return this._getStacks(void 0,t).length}_getStackIndex(t,e,i){const s=this._getStacks(t,i),n=void 0!==e?s.indexOf(e):-1;return-1===n?s.length-1:n}_getRuler(){const t=this.options,e=this._cachedMeta,i=e.iScale,s=[];let n,o;for(n=0,o=e.data.length;n<o;++n)s.push(i.getPixelForValue(this.getParsed(n)[i.axis],n));const a=t.barThickness;return{min:a||Mn(e),pixels:s,start:i._startPixel,end:i._endPixel,stackCount:this._getStackCount(),scale:i,grouped:t.grouped,ratio:a?1:t.categoryPercentage*t.barPercentage}}_calculateBarValuePixels(t){const{_cachedMeta:{vScale:e,_stacked:s},options:{base:n,minBarLength:o}}=this,a=n||0,r=this.getParsed(t),l=r._custom,h=Pn(l);let c,d,u=r[e.axis],f=0,g=s?this.applyStack(e,r,s):u;g!==u&&(f=g-u,g=u),h&&(u=l.barStart,g=l.barEnd-l.barStart,0!==u&&z(u)!==z(l.barEnd)&&(f=0),f+=u);const p=i(n)||h?f:n;let m=e.getPixelForValue(p);if(c=this.chart.getDataVisibility(t)?e.getPixelForValue(f+g):m,d=c-m,Math.abs(d)<o){d=function(t,e,i){return 0!==t?z(t):(e.isHorizontal()?1:-1)*(e.min>=i?1:-1)}(d,e,a)*o,u===a&&(m-=d/2);const t=e.getPixelForDecimal(0),i=e.getPixelForDecimal(1),s=Math.min(t,i),n=Math.max(t,i);m=Math.max(Math.min(m,n),s),c=m+d}if(m===e.getPixelForValue(a)){const t=z(d)*e.getLineWidthForValue(a)/2;m+=t,d-=t}return{size:d,base:m,head:c,center:c+d/2}}_calculateBarIndexPixels(t,e){const s=e.scale,n=this.options,o=n.skipNull,a=r(n.maxBarThickness,1/0);let l,h;if(e.grouped){const s=o?this._getStackCount(t):e.stackCount,r=\"flex\"===n.barThickness?function(t,e,i,s){const n=e.pixels,o=n[t];let a=t>0?n[t-1]:null,r=t<n.length-1?n[t+1]:null;const l=i.categoryPercentage;null===a&&(a=o-(null===r?e.end-e.start:r-o)),null===r&&(r=o+o-a);const h=o-(o-Math.min(a,r))/2*l;return{chunk:Math.abs(r-a)/2*l/s,ratio:i.barPercentage,start:h}}(t,e,n,s):function(t,e,s,n){const o=s.barThickness;let a,r;return i(o)?(a=e.min*s.categoryPercentage,r=s.barPercentage):(a=o*n,r=1),{chunk:a/n,ratio:r,start:e.pixels[t]-a/2}}(t,e,n,s),c=this._getStackIndex(this.index,this._cachedMeta.stack,o?t:void 0);l=r.start+r.chunk*c+r.chunk/2,h=Math.min(a,r.chunk*r.ratio)}else l=s.getPixelForValue(this.getParsed(t)[s.axis],t),h=Math.min(a,e.min*e.ratio);return{base:l-h/2,head:l+h/2,center:l,size:h}}draw(){const t=this._cachedMeta,e=t.vScale,i=t.data,s=i.length;let n=0;for(;n<s;++n)null!==this.getParsed(n)[e.axis]&&i[n].draw(this._ctx)}}Tn.id=\"bar\",Tn.defaults={datasetElementType:!1,dataElementType:\"bar\",categoryPercentage:.8,barPercentage:.9,grouped:!0,animations:{numbers:{type:\"number\",properties:[\"x\",\"y\",\"base\",\"width\",\"height\"]}}},Tn.overrides={scales:{_index_:{type:\"category\",offset:!0,grid:{offset:!0}},_value_:{type:\"linear\",beginAtZero:!0}}};class Ln extends Ls{initialize(){this.enableOptionSharing=!0,super.initialize()}parsePrimitiveData(t,e,i,s){const n=super.parsePrimitiveData(t,e,i,s);for(let t=0;t<n.length;t++)n[t]._custom=this.resolveDataElementOptions(t+i).radius;return n}parseArrayData(t,e,i,s){const n=super.parseArrayData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=r(s[2],this.resolveDataElementOptions(t+i).radius)}return n}parseObjectData(t,e,i,s){const n=super.parseObjectData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=r(s&&s.r&&+s.r,this.resolveDataElementOptions(t+i).radius)}return n}getMaxOverflow(){const t=this._cachedMeta.data;let e=0;for(let i=t.length-1;i>=0;--i)e=Math.max(e,t[i].size(this.resolveDataElementOptions(i))/2);return e>0&&e}getLabelAndValue(t){const e=this._cachedMeta,{xScale:i,yScale:s}=e,n=this.getParsed(t),o=i.getLabelForValue(n.x),a=s.getLabelForValue(n.y),r=n._custom;return{label:e.label,value:\"(\"+o+\", \"+a+(r?\", \"+r:\"\")+\")\"}}update(t){const e=this._cachedMeta.data;this.updateElements(e,0,e.length,t)}updateElements(t,e,i,s){const n=\"reset\"===s,{iScale:o,vScale:a}=this._cachedMeta,{sharedOptions:r,includeOptions:l}=this._getSharedOptions(e,s),h=o.axis,c=a.axis;for(let d=e;d<e+i;d++){const e=t[d],i=!n&&this.getParsed(d),u={},f=u[h]=n?o.getPixelForDecimal(.5):o.getPixelForValue(i[h]),g=u[c]=n?a.getBasePixel():a.getPixelForValue(i[c]);u.skip=isNaN(f)||isNaN(g),l&&(u.options=r||this.resolveDataElementOptions(d,e.active?\"active\":s),n&&(u.options.radius=0)),this.updateElement(e,d,u,s)}}resolveDataElementOptions(t,e){const i=this.getParsed(t);let s=super.resolveDataElementOptions(t,e);s.$shared&&(s=Object.assign({},s,{$shared:!1}));const n=s.radius;return\"active\"!==e&&(s.radius=0),s.radius+=r(i&&i._custom,n),s}}Ln.id=\"bubble\",Ln.defaults={datasetElementType:!1,dataElementType:\"point\",animations:{numbers:{type:\"number\",properties:[\"x\",\"y\",\"borderWidth\",\"radius\"]}}},Ln.overrides={scales:{x:{type:\"linear\"},y:{type:\"linear\"}},plugins:{tooltip:{callbacks:{title:()=>\"\"}}}};class En extends Ls{constructor(t,e){super(t,e),this.enableOptionSharing=!0,this.innerRadius=void 0,this.outerRadius=void 0,this.offsetX=void 0,this.offsetY=void 0}linkScales(){}parse(t,e){const i=this.getDataset().data,s=this._cachedMeta;if(!1===this._parsing)s._parsed=i;else{let o,a,r=t=>+i[t];if(n(i[t])){const{key:t=\"value\"}=this._parsing;r=e=>+y(i[e],t)}for(o=t,a=t+e;o<a;++o)s._parsed[o]=r(o)}}_getRotation(){return H(this.options.rotation-90)}_getCircumference(){return H(this.options.circumference)}_getRotationExtents(){let t=O,e=-O;for(let i=0;i<this.chart.data.datasets.length;++i)if(this.chart.isDatasetVisible(i)){const s=this.chart.getDatasetMeta(i).controller,n=s._getRotation(),o=s._getCircumference();t=Math.min(t,n),e=Math.max(e,n+o)}return{rotation:t,circumference:e-t}}update(t){const e=this.chart,{chartArea:i}=e,s=this._cachedMeta,n=s.data,o=this.getMaxBorderWidth()+this.getMaxOffset(n)+this.options.spacing,a=Math.max((Math.min(i.width,i.height)-o)/2,0),r=Math.min(l(this.options.cutout,a),1),c=this._getRingWeight(this.index),{circumference:d,rotation:u}=this._getRotationExtents(),{ratioX:f,ratioY:g,offsetX:p,offsetY:m}=function(t,e,i){let s=1,n=1,o=0,a=0;if(e<O){const r=t,l=r+e,h=Math.cos(r),c=Math.sin(r),d=Math.cos(l),u=Math.sin(l),f=(t,e,s)=>G(t,r,l,!0)?1:Math.max(e,e*i,s,s*i),g=(t,e,s)=>G(t,r,l,!0)?-1:Math.min(e,e*i,s,s*i),p=f(0,h,d),m=f(L,c,u),b=g(D,h,d),x=g(D+L,c,u);s=(p-b)/2,n=(m-x)/2,o=-(p+b)/2,a=-(m+x)/2}return{ratioX:s,ratioY:n,offsetX:o,offsetY:a}}(u,d,r),b=(i.width-o)/f,x=(i.height-o)/g,_=Math.max(Math.min(b,x)/2,0),y=h(this.options.radius,_),v=(y-Math.max(y*r,0))/this._getVisibleDatasetWeightTotal();this.offsetX=p*y,this.offsetY=m*y,s.total=this.calculateTotal(),this.outerRadius=y-v*this._getRingWeightOffset(this.index),this.innerRadius=Math.max(this.outerRadius-v*c,0),this.updateElements(n,0,n.length,t)}_circumference(t,e){const i=this.options,s=this._cachedMeta,n=this._getCircumference();return e&&i.animation.animateRotate||!this.chart.getDataVisibility(t)||null===s._parsed[t]||s.data[t].hidden?0:this.calculateCircumference(s._parsed[t]*n/O)}updateElements(t,e,i,s){const n=\"reset\"===s,o=this.chart,a=o.chartArea,r=o.options.animation,l=(a.left+a.right)/2,h=(a.top+a.bottom)/2,c=n&&r.animateScale,d=c?0:this.innerRadius,u=c?0:this.outerRadius,{sharedOptions:f,includeOptions:g}=this._getSharedOptions(e,s);let p,m=this._getRotation();for(p=0;p<e;++p)m+=this._circumference(p,n);for(p=e;p<e+i;++p){const e=this._circumference(p,n),i=t[p],o={x:l+this.offsetX,y:h+this.offsetY,startAngle:m,endAngle:m+e,circumference:e,outerRadius:u,innerRadius:d};g&&(o.options=f||this.resolveDataElementOptions(p,i.active?\"active\":s)),m+=e,this.updateElement(i,p,o,s)}}calculateTotal(){const t=this._cachedMeta,e=t.data;let i,s=0;for(i=0;i<e.length;i++){const n=t._parsed[i];null===n||isNaN(n)||!this.chart.getDataVisibility(i)||e[i].hidden||(s+=Math.abs(n))}return s}calculateCircumference(t){const e=this._cachedMeta.total;return e>0&&!isNaN(t)?O*(Math.abs(t)/e):0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=li(e._parsed[t],i.options.locale);return{label:s[t]||\"\",value:n}}getMaxBorderWidth(t){let e=0;const i=this.chart;let s,n,o,a,r;if(!t)for(s=0,n=i.data.datasets.length;s<n;++s)if(i.isDatasetVisible(s)){o=i.getDatasetMeta(s),t=o.data,a=o.controller;break}if(!t)return 0;for(s=0,n=t.length;s<n;++s)r=a.resolveDataElementOptions(s),\"inner\"!==r.borderAlign&&(e=Math.max(e,r.borderWidth||0,r.hoverBorderWidth||0));return e}getMaxOffset(t){let e=0;for(let i=0,s=t.length;i<s;++i){const t=this.resolveDataElementOptions(i);e=Math.max(e,t.offset||0,t.hoverOffset||0)}return e}_getRingWeightOffset(t){let e=0;for(let i=0;i<t;++i)this.chart.isDatasetVisible(i)&&(e+=this._getRingWeight(i));return e}_getRingWeight(t){return Math.max(r(this.chart.data.datasets[t].weight,1),0)}_getVisibleDatasetWeightTotal(){return this._getRingWeightOffset(this.chart.data.datasets.length)||1}}En.id=\"doughnut\",En.defaults={datasetElementType:!1,dataElementType:\"arc\",animation:{animateRotate:!0,animateScale:!1},animations:{numbers:{type:\"number\",properties:[\"circumference\",\"endAngle\",\"innerRadius\",\"outerRadius\",\"startAngle\",\"x\",\"y\",\"offset\",\"borderWidth\",\"spacing\"]}},cutout:\"50%\",rotation:0,circumference:360,radius:\"100%\",spacing:0,indexAxis:\"r\"},En.descriptors={_scriptable:t=>\"spacing\"!==t,_indexable:t=>\"spacing\"!==t},En.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>\"\",label(t){let e=t.label;const i=\": \"+t.formattedValue;return s(e)?(e=e.slice(),e[0]+=i):e+=i,e}}}}};class Rn extends Ls{initialize(){this.enableOptionSharing=!0,this.supportsDecimation=!0,super.initialize()}update(t){const e=this._cachedMeta,{dataset:i,data:s=[],_dataset:n}=e,o=this.chart._animationsDisabled;let{start:a,count:r}=gt(e,s,o);this._drawStart=a,this._drawCount=r,pt(e)&&(a=0,r=s.length),i._chart=this.chart,i._datasetIndex=this.index,i._decimated=!!n._decimated,i.points=s;const l=this.resolveDatasetElementOptions(t);this.options.showLine||(l.borderWidth=0),l.segment=this.options.segment,this.updateElement(i,void 0,{animated:!o,options:l},t),this.updateElements(s,a,r,t)}updateElements(t,e,s,n){const o=\"reset\"===n,{iScale:a,vScale:r,_stacked:l,_dataset:h}=this._cachedMeta,{sharedOptions:c,includeOptions:d}=this._getSharedOptions(e,n),u=a.axis,f=r.axis,{spanGaps:g,segment:p}=this.options,m=B(g)?g:Number.POSITIVE_INFINITY,b=this.chart._animationsDisabled||o||\"none\"===n;let x=e>0&&this.getParsed(e-1);for(let g=e;g<e+s;++g){const e=t[g],s=this.getParsed(g),_=b?e:{},y=i(s[f]),v=_[u]=a.getPixelForValue(s[u],g),w=_[f]=o||y?r.getBasePixel():r.getPixelForValue(l?this.applyStack(r,s,l):s[f],g);_.skip=isNaN(v)||isNaN(w)||y,_.stop=g>0&&Math.abs(s[u]-x[u])>m,p&&(_.parsed=s,_.raw=h.data[g]),d&&(_.options=c||this.resolveDataElementOptions(g,e.active?\"active\":n)),b||this.updateElement(e,g,_,n),x=s}}getMaxOverflow(){const t=this._cachedMeta,e=t.dataset,i=e.options&&e.options.borderWidth||0,s=t.data||[];if(!s.length)return i;const n=s[0].size(this.resolveDataElementOptions(0)),o=s[s.length-1].size(this.resolveDataElementOptions(s.length-1));return Math.max(i,n,o)/2}draw(){const t=this._cachedMeta;t.dataset.updateControlPoints(this.chart.chartArea,t.iScale.axis),super.draw()}}Rn.id=\"line\",Rn.defaults={datasetElementType:\"line\",dataElementType:\"point\",showLine:!0,spanGaps:!1},Rn.overrides={scales:{_index_:{type:\"category\"},_value_:{type:\"linear\"}}};class In extends Ls{constructor(t,e){super(t,e),this.innerRadius=void 0,this.outerRadius=void 0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=li(e._parsed[t].r,i.options.locale);return{label:s[t]||\"\",value:n}}parseObjectData(t,e,i,s){return Ue.bind(this)(t,e,i,s)}update(t){const e=this._cachedMeta.data;this._updateRadius(),this.updateElements(e,0,e.length,t)}getMinMax(){const t=this._cachedMeta,e={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY};return t.data.forEach(((t,i)=>{const s=this.getParsed(i).r;!isNaN(s)&&this.chart.getDataVisibility(i)&&(s<e.min&&(e.min=s),s>e.max&&(e.max=s))})),e}_updateRadius(){const t=this.chart,e=t.chartArea,i=t.options,s=Math.min(e.right-e.left,e.bottom-e.top),n=Math.max(s/2,0),o=(n-Math.max(i.cutoutPercentage?n/100*i.cutoutPercentage:1,0))/t.getVisibleDatasetCount();this.outerRadius=n-o*this.index,this.innerRadius=this.outerRadius-o}updateElements(t,e,i,s){const n=\"reset\"===s,o=this.chart,a=o.options.animation,r=this._cachedMeta.rScale,l=r.xCenter,h=r.yCenter,c=r.getIndexAngle(0)-.5*D;let d,u=c;const f=360/this.countVisibleElements();for(d=0;d<e;++d)u+=this._computeAngle(d,s,f);for(d=e;d<e+i;d++){const e=t[d];let i=u,g=u+this._computeAngle(d,s,f),p=o.getDataVisibility(d)?r.getDistanceFromCenterForValue(this.getParsed(d).r):0;u=g,n&&(a.animateScale&&(p=0),a.animateRotate&&(i=g=c));const m={x:l,y:h,innerRadius:0,outerRadius:p,startAngle:i,endAngle:g,options:this.resolveDataElementOptions(d,e.active?\"active\":s)};this.updateElement(e,d,m,s)}}countVisibleElements(){const t=this._cachedMeta;let e=0;return t.data.forEach(((t,i)=>{!isNaN(this.getParsed(i).r)&&this.chart.getDataVisibility(i)&&e++})),e}_computeAngle(t,e,i){return this.chart.getDataVisibility(t)?H(this.resolveDataElementOptions(t,e).angle||i):0}}In.id=\"polarArea\",In.defaults={dataElementType:\"arc\",animation:{animateRotate:!0,animateScale:!0},animations:{numbers:{type:\"number\",properties:[\"x\",\"y\",\"startAngle\",\"endAngle\",\"innerRadius\",\"outerRadius\"]}},indexAxis:\"r\",startAngle:0},In.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>\"\",label:t=>t.chart.data.labels[t.dataIndex]+\": \"+t.formattedValue}}},scales:{r:{type:\"radialLinear\",angleLines:{display:!1},beginAtZero:!0,grid:{circular:!0},pointLabels:{display:!1},startAngle:0}}};class zn extends En{}zn.id=\"pie\",zn.defaults={cutout:0,rotation:0,circumference:360,radius:\"100%\"};class Fn extends Ls{getLabelAndValue(t){const e=this._cachedMeta.vScale,i=this.getParsed(t);return{label:e.getLabels()[t],value:\"\"+e.getLabelForValue(i[e.axis])}}parseObjectData(t,e,i,s){return Ue.bind(this)(t,e,i,s)}update(t){const e=this._cachedMeta,i=e.dataset,s=e.data||[],n=e.iScale.getLabels();if(i.points=s,\"resize\"!==t){const e=this.resolveDatasetElementOptions(t);this.options.showLine||(e.borderWidth=0);const o={_loop:!0,_fullLoop:n.length===s.length,options:e};this.updateElement(i,void 0,o,t)}this.updateElements(s,0,s.length,t)}updateElements(t,e,i,s){const n=this._cachedMeta.rScale,o=\"reset\"===s;for(let a=e;a<e+i;a++){const e=t[a],i=this.resolveDataElementOptions(a,e.active?\"active\":s),r=n.getPointPositionForValue(a,this.getParsed(a).r),l=o?n.xCenter:r.x,h=o?n.yCenter:r.y,c={x:l,y:h,angle:r.angle,skip:isNaN(l)||isNaN(h),options:i};this.updateElement(e,a,c,s)}}}Fn.id=\"radar\",Fn.defaults={datasetElementType:\"line\",dataElementType:\"point\",indexAxis:\"r\",showLine:!0,elements:{line:{fill:\"start\"}}},Fn.overrides={aspectRatio:1,scales:{r:{type:\"radialLinear\"}}};class Vn extends Ls{update(t){const e=this._cachedMeta,{data:i=[]}=e,s=this.chart._animationsDisabled;let{start:n,count:o}=gt(e,i,s);if(this._drawStart=n,this._drawCount=o,pt(e)&&(n=0,o=i.length),this.options.showLine){const{dataset:n,_dataset:o}=e;n._chart=this.chart,n._datasetIndex=this.index,n._decimated=!!o._decimated,n.points=i;const a=this.resolveDatasetElementOptions(t);a.segment=this.options.segment,this.updateElement(n,void 0,{animated:!s,options:a},t)}this.updateElements(i,n,o,t)}addElements(){const{showLine:t}=this.options;!this.datasetElementType&&t&&(this.datasetElementType=Us.getElement(\"line\")),super.addElements()}updateElements(t,e,s,n){const o=\"reset\"===n,{iScale:a,vScale:r,_stacked:l,_dataset:h}=this._cachedMeta,c=this.resolveDataElementOptions(e,n),d=this.getSharedOptions(c),u=this.includeOptions(n,d),f=a.axis,g=r.axis,{spanGaps:p,segment:m}=this.options,b=B(p)?p:Number.POSITIVE_INFINITY,x=this.chart._animationsDisabled||o||\"none\"===n;let _=e>0&&this.getParsed(e-1);for(let c=e;c<e+s;++c){const e=t[c],s=this.getParsed(c),p=x?e:{},y=i(s[g]),v=p[f]=a.getPixelForValue(s[f],c),w=p[g]=o||y?r.getBasePixel():r.getPixelForValue(l?this.applyStack(r,s,l):s[g],c);p.skip=isNaN(v)||isNaN(w)||y,p.stop=c>0&&Math.abs(s[f]-_[f])>b,m&&(p.parsed=s,p.raw=h.data[c]),u&&(p.options=d||this.resolveDataElementOptions(c,e.active?\"active\":n)),x||this.updateElement(e,c,p,n),_=s}this.updateSharedOptions(d,n,c)}getMaxOverflow(){const t=this._cachedMeta,e=t.data||[];if(!this.options.showLine){let t=0;for(let i=e.length-1;i>=0;--i)t=Math.max(t,e[i].size(this.resolveDataElementOptions(i))/2);return t>0&&t}const i=t.dataset,s=i.options&&i.options.borderWidth||0;if(!e.length)return s;const n=e[0].size(this.resolveDataElementOptions(0)),o=e[e.length-1].size(this.resolveDataElementOptions(e.length-1));return Math.max(s,n,o)/2}}Vn.id=\"scatter\",Vn.defaults={datasetElementType:!1,dataElementType:\"point\",showLine:!1,fill:!1},Vn.overrides={interaction:{mode:\"point\"},plugins:{tooltip:{callbacks:{title:()=>\"\",label:t=>\"(\"+t.label+\", \"+t.formattedValue+\")\"}}},scales:{x:{type:\"linear\"},y:{type:\"linear\"}}};var Bn=Object.freeze({__proto__:null,BarController:Tn,BubbleController:Ln,DoughnutController:En,LineController:Rn,PolarAreaController:In,PieController:zn,RadarController:Fn,ScatterController:Vn});function Nn(t,e,i){const{startAngle:s,pixelMargin:n,x:o,y:a,outerRadius:r,innerRadius:l}=e;let h=n/r;t.beginPath(),t.arc(o,a,r,s-h,i+h),l>n?(h=n/l,t.arc(o,a,l,i+h,s-h,!0)):t.arc(o,a,n,i+L,s-L),t.closePath(),t.clip()}function Wn(t,e,i,s){const n=ui(t.options.borderRadius,[\"outerStart\",\"outerEnd\",\"innerStart\",\"innerEnd\"]);const o=(i-e)/2,a=Math.min(o,s*e/2),r=t=>{const e=(i-Math.min(o,t))*s/2;return Z(t,0,Math.min(o,e))};return{outerStart:r(n.outerStart),outerEnd:r(n.outerEnd),innerStart:Z(n.innerStart,0,a),innerEnd:Z(n.innerEnd,0,a)}}function jn(t,e,i,s){return{x:i+t*Math.cos(e),y:s+t*Math.sin(e)}}function Hn(t,e,i,s,n,o){const{x:a,y:r,startAngle:l,pixelMargin:h,innerRadius:c}=e,d=Math.max(e.outerRadius+s+i-h,0),u=c>0?c+s+i+h:0;let f=0;const g=n-l;if(s){const t=((c>0?c-s:0)+(d>0?d-s:0))/2;f=(g-(0!==t?g*t/(t+s):g))/2}const p=(g-Math.max(.001,g*d-i/D)/d)/2,m=l+p+f,b=n-p-f,{outerStart:x,outerEnd:_,innerStart:y,innerEnd:v}=Wn(e,u,d,b-m),w=d-x,M=d-_,k=m+x/w,S=b-_/M,P=u+y,O=u+v,C=m+y/P,A=b-v/O;if(t.beginPath(),o){if(t.arc(a,r,d,k,S),_>0){const e=jn(M,S,a,r);t.arc(e.x,e.y,_,S,b+L)}const e=jn(O,b,a,r);if(t.lineTo(e.x,e.y),v>0){const e=jn(O,A,a,r);t.arc(e.x,e.y,v,b+L,A+Math.PI)}if(t.arc(a,r,u,b-v/u,m+y/u,!0),y>0){const e=jn(P,C,a,r);t.arc(e.x,e.y,y,C+Math.PI,m-L)}const i=jn(w,m,a,r);if(t.lineTo(i.x,i.y),x>0){const e=jn(w,k,a,r);t.arc(e.x,e.y,x,m-L,k)}}else{t.moveTo(a,r);const e=Math.cos(k)*d+a,i=Math.sin(k)*d+r;t.lineTo(e,i);const s=Math.cos(S)*d+a,n=Math.sin(S)*d+r;t.lineTo(s,n)}t.closePath()}function $n(t,e,i,s,n,o){const{options:a}=e,{borderWidth:r,borderJoinStyle:l}=a,h=\"inner\"===a.borderAlign;r&&(h?(t.lineWidth=2*r,t.lineJoin=l||\"round\"):(t.lineWidth=r,t.lineJoin=l||\"bevel\"),e.fullCircles&&function(t,e,i){const{x:s,y:n,startAngle:o,pixelMargin:a,fullCircles:r}=e,l=Math.max(e.outerRadius-a,0),h=e.innerRadius+a;let c;for(i&&Nn(t,e,o+O),t.beginPath(),t.arc(s,n,h,o+O,o,!0),c=0;c<r;++c)t.stroke();for(t.beginPath(),t.arc(s,n,l,o,o+O),c=0;c<r;++c)t.stroke()}(t,e,h),h&&Nn(t,e,n),Hn(t,e,i,s,n,o),t.stroke())}class Yn extends Es{constructor(t){super(),this.options=void 0,this.circumference=void 0,this.startAngle=void 0,this.endAngle=void 0,this.innerRadius=void 0,this.outerRadius=void 0,this.pixelMargin=0,this.fullCircles=0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.getProps([\"x\",\"y\"],i),{angle:n,distance:o}=U(s,{x:t,y:e}),{startAngle:a,endAngle:l,innerRadius:h,outerRadius:c,circumference:d}=this.getProps([\"startAngle\",\"endAngle\",\"innerRadius\",\"outerRadius\",\"circumference\"],i),u=this.options.spacing/2,f=r(d,l-a)>=O||G(n,a,l),g=Q(o,h+u,c+u);return f&&g}getCenterPoint(t){const{x:e,y:i,startAngle:s,endAngle:n,innerRadius:o,outerRadius:a}=this.getProps([\"x\",\"y\",\"startAngle\",\"endAngle\",\"innerRadius\",\"outerRadius\",\"circumference\"],t),{offset:r,spacing:l}=this.options,h=(s+n)/2,c=(o+a+l+r)/2;return{x:e+Math.cos(h)*c,y:i+Math.sin(h)*c}}tooltipPosition(t){return this.getCenterPoint(t)}draw(t){const{options:e,circumference:i}=this,s=(e.offset||0)/2,n=(e.spacing||0)/2,o=e.circular;if(this.pixelMargin=\"inner\"===e.borderAlign?.33:0,this.fullCircles=i>O?Math.floor(i/O):0,0===i||this.innerRadius<0||this.outerRadius<0)return;t.save();let a=0;if(s){a=s/2;const e=(this.startAngle+this.endAngle)/2;t.translate(Math.cos(e)*a,Math.sin(e)*a),this.circumference>=D&&(a=s)}t.fillStyle=e.backgroundColor,t.strokeStyle=e.borderColor;const r=function(t,e,i,s,n){const{fullCircles:o,startAngle:a,circumference:r}=e;let l=e.endAngle;if(o){Hn(t,e,i,s,a+O,n);for(let e=0;e<o;++e)t.fill();isNaN(r)||(l=a+r%O,r%O==0&&(l+=O))}return Hn(t,e,i,s,l,n),t.fill(),l}(t,this,a,n,o);$n(t,this,a,n,r,o),t.restore()}}function Un(t,e,i=e){t.lineCap=r(i.borderCapStyle,e.borderCapStyle),t.setLineDash(r(i.borderDash,e.borderDash)),t.lineDashOffset=r(i.borderDashOffset,e.borderDashOffset),t.lineJoin=r(i.borderJoinStyle,e.borderJoinStyle),t.lineWidth=r(i.borderWidth,e.borderWidth),t.strokeStyle=r(i.borderColor,e.borderColor)}function Xn(t,e,i){t.lineTo(i.x,i.y)}function qn(t,e,i={}){const s=t.length,{start:n=0,end:o=s-1}=i,{start:a,end:r}=e,l=Math.max(n,a),h=Math.min(o,r),c=n<a&&o<a||n>r&&o>r;return{count:s,start:l,loop:e.loop,ilen:h<l&&!c?s+h-l:h-l}}function Kn(t,e,i,s){const{points:n,options:o}=e,{count:a,start:r,loop:l,ilen:h}=qn(n,i,s),c=function(t){return t.stepped?Oe:t.tension||\"monotone\"===t.cubicInterpolationMode?Ce:Xn}(o);let d,u,f,{move:g=!0,reverse:p}=s||{};for(d=0;d<=h;++d)u=n[(r+(p?h-d:d))%a],u.skip||(g?(t.moveTo(u.x,u.y),g=!1):c(t,f,u,p,o.stepped),f=u);return l&&(u=n[(r+(p?h:0))%a],c(t,f,u,p,o.stepped)),!!l}function Gn(t,e,i,s){const n=e.points,{count:o,start:a,ilen:r}=qn(n,i,s),{move:l=!0,reverse:h}=s||{};let c,d,u,f,g,p,m=0,b=0;const x=t=>(a+(h?r-t:t))%o,_=()=>{f!==g&&(t.lineTo(m,g),t.lineTo(m,f),t.lineTo(m,p))};for(l&&(d=n[x(0)],t.moveTo(d.x,d.y)),c=0;c<=r;++c){if(d=n[x(c)],d.skip)continue;const e=d.x,i=d.y,s=0|e;s===u?(i<f?f=i:i>g&&(g=i),m=(b*m+e)/++b):(_(),t.lineTo(e,i),u=s,b=0,f=g=i),p=i}_()}function Zn(t){const e=t.options,i=e.borderDash&&e.borderDash.length;return!(t._decimated||t._loop||e.tension||\"monotone\"===e.cubicInterpolationMode||e.stepped||i)?Gn:Kn}Yn.id=\"arc\",Yn.defaults={borderAlign:\"center\",borderColor:\"#fff\",borderJoinStyle:void 0,borderRadius:0,borderWidth:2,offset:0,spacing:0,angle:void 0,circular:!0},Yn.defaultRoutes={backgroundColor:\"backgroundColor\"};const Jn=\"function\"==typeof Path2D;function Qn(t,e,i,s){Jn&&!e.options.segment?function(t,e,i,s){let n=e._path;n||(n=e._path=new Path2D,e.path(n,i,s)&&n.closePath()),Un(t,e.options),t.stroke(n)}(t,e,i,s):function(t,e,i,s){const{segments:n,options:o}=e,a=Zn(e);for(const r of n)Un(t,o,r.style),t.beginPath(),a(t,e,r,{start:i,end:i+s-1})&&t.closePath(),t.stroke()}(t,e,i,s)}class to extends Es{constructor(t){super(),this.animated=!0,this.options=void 0,this._chart=void 0,this._loop=void 0,this._fullLoop=void 0,this._path=void 0,this._points=void 0,this._segments=void 0,this._decimated=!1,this._pointsUpdated=!1,this._datasetIndex=void 0,t&&Object.assign(this,t)}updateControlPoints(t,e){const i=this.options;if((i.tension||\"monotone\"===i.cubicInterpolationMode)&&!i.stepped&&!this._pointsUpdated){const s=i.spanGaps?this._loop:this._fullLoop;Qe(this._points,i,t,s,e),this._pointsUpdated=!0}}set points(t){this._points=t,delete this._segments,delete this._path,this._pointsUpdated=!1}get points(){return this._points}get segments(){return this._segments||(this._segments=Di(this,this.options.segment))}first(){const t=this.segments,e=this.points;return t.length&&e[t[0].start]}last(){const t=this.segments,e=this.points,i=t.length;return i&&e[t[i-1].end]}interpolate(t,e){const i=this.options,s=t[e],n=this.points,o=Pi(this,{property:e,start:s,end:s});if(!o.length)return;const a=[],r=function(t){return t.stepped?oi:t.tension||\"monotone\"===t.cubicInterpolationMode?ai:ni}(i);let l,h;for(l=0,h=o.length;l<h;++l){const{start:h,end:c}=o[l],d=n[h],u=n[c];if(d===u){a.push(d);continue}const f=r(d,u,Math.abs((s-d[e])/(u[e]-d[e])),i.stepped);f[e]=t[e],a.push(f)}return 1===a.length?a[0]:a}pathSegment(t,e,i){return Zn(this)(t,this,e,i)}path(t,e,i){const s=this.segments,n=Zn(this);let o=this._loop;e=e||0,i=i||this.points.length-e;for(const a of s)o&=n(t,this,a,{start:e,end:e+i-1});return!!o}draw(t,e,i,s){const n=this.options||{};(this.points||[]).length&&n.borderWidth&&(t.save(),Qn(t,this,i,s),t.restore()),this.animated&&(this._pointsUpdated=!1,this._path=void 0)}}function eo(t,e,i,s){const n=t.options,{[i]:o}=t.getProps([i],s);return Math.abs(e-o)<n.radius+n.hitRadius}to.id=\"line\",to.defaults={borderCapStyle:\"butt\",borderDash:[],borderDashOffset:0,borderJoinStyle:\"miter\",borderWidth:3,capBezierPoints:!0,cubicInterpolationMode:\"default\",fill:!1,spanGaps:!1,stepped:!1,tension:0},to.defaultRoutes={backgroundColor:\"backgroundColor\",borderColor:\"borderColor\"},to.descriptors={_scriptable:!0,_indexable:t=>\"borderDash\"!==t&&\"fill\"!==t};class io extends Es{constructor(t){super(),this.options=void 0,this.parsed=void 0,this.skip=void 0,this.stop=void 0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.options,{x:n,y:o}=this.getProps([\"x\",\"y\"],i);return Math.pow(t-n,2)+Math.pow(e-o,2)<Math.pow(s.hitRadius+s.radius,2)}inXRange(t,e){return eo(this,t,\"x\",e)}inYRange(t,e){return eo(this,t,\"y\",e)}getCenterPoint(t){const{x:e,y:i}=this.getProps([\"x\",\"y\"],t);return{x:e,y:i}}size(t){let e=(t=t||this.options||{}).radius||0;e=Math.max(e,e&&t.hoverRadius||0);return 2*(e+(e&&t.borderWidth||0))}draw(t,e){const i=this.options;this.skip||i.radius<.1||!Se(this,e,this.size(i)/2)||(t.strokeStyle=i.borderColor,t.lineWidth=i.borderWidth,t.fillStyle=i.backgroundColor,Me(t,i,this.x,this.y))}getRange(){const t=this.options||{};return t.radius+t.hitRadius}}function so(t,e){const{x:i,y:s,base:n,width:o,height:a}=t.getProps([\"x\",\"y\",\"base\",\"width\",\"height\"],e);let r,l,h,c,d;return t.horizontal?(d=a/2,r=Math.min(i,n),l=Math.max(i,n),h=s-d,c=s+d):(d=o/2,r=i-d,l=i+d,h=Math.min(s,n),c=Math.max(s,n)),{left:r,top:h,right:l,bottom:c}}function no(t,e,i,s){return t?0:Z(e,i,s)}function oo(t){const e=so(t),i=e.right-e.left,s=e.bottom-e.top,o=function(t,e,i){const s=t.options.borderWidth,n=t.borderSkipped,o=fi(s);return{t:no(n.top,o.top,0,i),r:no(n.right,o.right,0,e),b:no(n.bottom,o.bottom,0,i),l:no(n.left,o.left,0,e)}}(t,i/2,s/2),a=function(t,e,i){const{enableBorderRadius:s}=t.getProps([\"enableBorderRadius\"]),o=t.options.borderRadius,a=gi(o),r=Math.min(e,i),l=t.borderSkipped,h=s||n(o);return{topLeft:no(!h||l.top||l.left,a.topLeft,0,r),topRight:no(!h||l.top||l.right,a.topRight,0,r),bottomLeft:no(!h||l.bottom||l.left,a.bottomLeft,0,r),bottomRight:no(!h||l.bottom||l.right,a.bottomRight,0,r)}}(t,i/2,s/2);return{outer:{x:e.left,y:e.top,w:i,h:s,radius:a},inner:{x:e.left+o.l,y:e.top+o.t,w:i-o.l-o.r,h:s-o.t-o.b,radius:{topLeft:Math.max(0,a.topLeft-Math.max(o.t,o.l)),topRight:Math.max(0,a.topRight-Math.max(o.t,o.r)),bottomLeft:Math.max(0,a.bottomLeft-Math.max(o.b,o.l)),bottomRight:Math.max(0,a.bottomRight-Math.max(o.b,o.r))}}}}function ao(t,e,i,s){const n=null===e,o=null===i,a=t&&!(n&&o)&&so(t,s);return a&&(n||Q(e,a.left,a.right))&&(o||Q(i,a.top,a.bottom))}function ro(t,e){t.rect(e.x,e.y,e.w,e.h)}function lo(t,e,i={}){const s=t.x!==i.x?-e:0,n=t.y!==i.y?-e:0,o=(t.x+t.w!==i.x+i.w?e:0)-s,a=(t.y+t.h!==i.y+i.h?e:0)-n;return{x:t.x+s,y:t.y+n,w:t.w+o,h:t.h+a,radius:t.radius}}io.id=\"point\",io.defaults={borderWidth:1,hitRadius:1,hoverBorderWidth:1,hoverRadius:4,pointStyle:\"circle\",radius:3,rotation:0},io.defaultRoutes={backgroundColor:\"backgroundColor\",borderColor:\"borderColor\"};class ho extends Es{constructor(t){super(),this.options=void 0,this.horizontal=void 0,this.base=void 0,this.width=void 0,this.height=void 0,this.inflateAmount=void 0,t&&Object.assign(this,t)}draw(t){const{inflateAmount:e,options:{borderColor:i,backgroundColor:s}}=this,{inner:n,outer:o}=oo(this),a=(r=o.radius).topLeft||r.topRight||r.bottomLeft||r.bottomRight?Le:ro;var r;t.save(),o.w===n.w&&o.h===n.h||(t.beginPath(),a(t,lo(o,e,n)),t.clip(),a(t,lo(n,-e,o)),t.fillStyle=i,t.fill(\"evenodd\")),t.beginPath(),a(t,lo(n,e)),t.fillStyle=s,t.fill(),t.restore()}inRange(t,e,i){return ao(this,t,e,i)}inXRange(t,e){return ao(this,t,null,e)}inYRange(t,e){return ao(this,null,t,e)}getCenterPoint(t){const{x:e,y:i,base:s,horizontal:n}=this.getProps([\"x\",\"y\",\"base\",\"horizontal\"],t);return{x:n?(e+s)/2:e,y:n?i:(i+s)/2}}getRange(t){return\"x\"===t?this.width/2:this.height/2}}ho.id=\"bar\",ho.defaults={borderSkipped:\"start\",borderWidth:0,borderRadius:0,inflateAmount:\"auto\",pointStyle:void 0},ho.defaultRoutes={backgroundColor:\"backgroundColor\",borderColor:\"borderColor\"};var co=Object.freeze({__proto__:null,ArcElement:Yn,LineElement:to,PointElement:io,BarElement:ho});function uo(t){if(t._decimated){const e=t._data;delete t._decimated,delete t._data,Object.defineProperty(t,\"data\",{value:e})}}function fo(t){t.data.datasets.forEach((t=>{uo(t)}))}var go={id:\"decimation\",defaults:{algorithm:\"min-max\",enabled:!1},beforeElementsUpdate:(t,e,s)=>{if(!s.enabled)return void fo(t);const n=t.width;t.data.datasets.forEach(((e,o)=>{const{_data:a,indexAxis:r}=e,l=t.getDatasetMeta(o),h=a||e.data;if(\"y\"===bi([r,t.options.indexAxis]))return;if(!l.controller.supportsDecimation)return;const c=t.scales[l.xAxisID];if(\"linear\"!==c.type&&\"time\"!==c.type)return;if(t.options.parsing)return;let{start:d,count:u}=function(t,e){const i=e.length;let s,n=0;const{iScale:o}=t,{min:a,max:r,minDefined:l,maxDefined:h}=o.getUserBounds();return l&&(n=Z(et(e,o.axis,a).lo,0,i-1)),s=h?Z(et(e,o.axis,r).hi+1,n,i)-n:i-n,{start:n,count:s}}(l,h);if(u<=(s.threshold||4*n))return void uo(e);let f;switch(i(a)&&(e._data=h,delete e.data,Object.defineProperty(e,\"data\",{configurable:!0,enumerable:!0,get:function(){return this._decimated},set:function(t){this._data=t}})),s.algorithm){case\"lttb\":f=function(t,e,i,s,n){const o=n.samples||s;if(o>=i)return t.slice(e,e+i);const a=[],r=(i-2)/(o-2);let l=0;const h=e+i-1;let c,d,u,f,g,p=e;for(a[l++]=t[p],c=0;c<o-2;c++){let s,n=0,o=0;const h=Math.floor((c+1)*r)+1+e,m=Math.min(Math.floor((c+2)*r)+1,i)+e,b=m-h;for(s=h;s<m;s++)n+=t[s].x,o+=t[s].y;n/=b,o/=b;const x=Math.floor(c*r)+1+e,_=Math.min(Math.floor((c+1)*r)+1,i)+e,{x:y,y:v}=t[p];for(u=f=-1,s=x;s<_;s++)f=.5*Math.abs((y-n)*(t[s].y-v)-(y-t[s].x)*(o-v)),f>u&&(u=f,d=t[s],g=s);a[l++]=d,p=g}return a[l++]=t[h],a}(h,d,u,n,s);break;case\"min-max\":f=function(t,e,s,n){let o,a,r,l,h,c,d,u,f,g,p=0,m=0;const b=[],x=e+s-1,_=t[e].x,y=t[x].x-_;for(o=e;o<e+s;++o){a=t[o],r=(a.x-_)/y*n,l=a.y;const e=0|r;if(e===h)l<f?(f=l,c=o):l>g&&(g=l,d=o),p=(m*p+a.x)/++m;else{const s=o-1;if(!i(c)&&!i(d)){const e=Math.min(c,d),i=Math.max(c,d);e!==u&&e!==s&&b.push({...t[e],x:p}),i!==u&&i!==s&&b.push({...t[i],x:p})}o>0&&s!==u&&b.push(t[s]),b.push(a),h=e,m=0,f=g=l,c=d=u=o}}return b}(h,d,u,n);break;default:throw new Error(`Unsupported decimation algorithm '${s.algorithm}'`)}e._decimated=f}))},destroy(t){fo(t)}};function po(t,e,i,s){if(s)return;let n=e[t],o=i[t];return\"angle\"===t&&(n=K(n),o=K(o)),{property:t,start:n,end:o}}function mo(t,e,i){for(;e>t;e--){const t=i[e];if(!isNaN(t.x)&&!isNaN(t.y))break}return e}function bo(t,e,i,s){return t&&e?s(t[i],e[i]):t?t[i]:e?e[i]:0}function xo(t,e){let i=[],n=!1;return s(t)?(n=!0,i=t):i=function(t,e){const{x:i=null,y:s=null}=t||{},n=e.points,o=[];return e.segments.forEach((({start:t,end:e})=>{e=mo(t,e,n);const a=n[t],r=n[e];null!==s?(o.push({x:a.x,y:s}),o.push({x:r.x,y:s})):null!==i&&(o.push({x:i,y:a.y}),o.push({x:i,y:r.y}))})),o}(t,e),i.length?new to({points:i,options:{tension:0},_loop:n,_fullLoop:n}):null}function _o(t){return t&&!1!==t.fill}function yo(t,e,i){let s=t[e].fill;const n=[e];let a;if(!i)return s;for(;!1!==s&&-1===n.indexOf(s);){if(!o(s))return s;if(a=t[s],!a)return!1;if(a.visible)return s;n.push(s),s=a.fill}return!1}function vo(t,e,i){const s=function(t){const e=t.options,i=e.fill;let s=r(i&&i.target,i);void 0===s&&(s=!!e.backgroundColor);if(!1===s||null===s)return!1;if(!0===s)return\"origin\";return s}(t);if(n(s))return!isNaN(s.value)&&s;let a=parseFloat(s);return o(a)&&Math.floor(a)===a?function(t,e,i,s){\"-\"!==t&&\"+\"!==t||(i=e+i);if(i===e||i<0||i>=s)return!1;return i}(s[0],e,a,i):[\"origin\",\"start\",\"end\",\"stack\",\"shape\"].indexOf(s)>=0&&s}function wo(t,e,i){const s=[];for(let n=0;n<i.length;n++){const o=i[n],{first:a,last:r,point:l}=Mo(o,e,\"x\");if(!(!l||a&&r))if(a)s.unshift(l);else if(t.push(l),!r)break}t.push(...s)}function Mo(t,e,i){const s=t.interpolate(e,i);if(!s)return{};const n=s[i],o=t.segments,a=t.points;let r=!1,l=!1;for(let t=0;t<o.length;t++){const e=o[t],s=a[e.start][i],h=a[e.end][i];if(Q(n,s,h)){r=n===s,l=n===h;break}}return{first:r,last:l,point:s}}class ko{constructor(t){this.x=t.x,this.y=t.y,this.radius=t.radius}pathSegment(t,e,i){const{x:s,y:n,radius:o}=this;return e=e||{start:0,end:O},t.arc(s,n,o,e.end,e.start,!0),!i.bounds}interpolate(t){const{x:e,y:i,radius:s}=this,n=t.angle;return{x:e+Math.cos(n)*s,y:i+Math.sin(n)*s,angle:n}}}function So(t){const{chart:e,fill:i,line:s}=t;if(o(i))return function(t,e){const i=t.getDatasetMeta(e);return i&&t.isDatasetVisible(e)?i.dataset:null}(e,i);if(\"stack\"===i)return function(t){const{scale:e,index:i,line:s}=t,n=[],o=s.segments,a=s.points,r=function(t,e){const i=[],s=t.getMatchingVisibleMetas(\"line\");for(let t=0;t<s.length;t++){const n=s[t];if(n.index===e)break;n.hidden||i.unshift(n.dataset)}return i}(e,i);r.push(xo({x:null,y:e.bottom},s));for(let t=0;t<o.length;t++){const e=o[t];for(let t=e.start;t<=e.end;t++)wo(n,a[t],r)}return new to({points:n,options:{}})}(t);if(\"shape\"===i)return!0;const a=function(t){if((t.scale||{}).getPointPositionForValue)return function(t){const{scale:e,fill:i}=t,s=e.options,o=e.getLabels().length,a=s.reverse?e.max:e.min,r=function(t,e,i){let s;return s=\"start\"===t?i:\"end\"===t?e.options.reverse?e.min:e.max:n(t)?t.value:e.getBaseValue(),s}(i,e,a),l=[];if(s.grid.circular){const t=e.getPointPositionForValue(0,a);return new ko({x:t.x,y:t.y,radius:e.getDistanceFromCenterForValue(r)})}for(let t=0;t<o;++t)l.push(e.getPointPositionForValue(t,r));return l}(t);return function(t){const{scale:e={},fill:i}=t,s=function(t,e){let i=null;return\"start\"===t?i=e.bottom:\"end\"===t?i=e.top:n(t)?i=e.getPixelForValue(t.value):e.getBasePixel&&(i=e.getBasePixel()),i}(i,e);if(o(s)){const t=e.isHorizontal();return{x:t?s:null,y:t?null:s}}return null}(t)}(t);return a instanceof ko?a:xo(a,s)}function Po(t,e,i){const s=So(e),{line:n,scale:o,axis:a}=e,r=n.options,l=r.fill,h=r.backgroundColor,{above:c=h,below:d=h}=l||{};s&&n.points.length&&(Pe(t,i),function(t,e){const{line:i,target:s,above:n,below:o,area:a,scale:r}=e,l=i._loop?\"angle\":e.axis;t.save(),\"x\"===l&&o!==n&&(Do(t,s,a.top),Oo(t,{line:i,target:s,color:n,scale:r,property:l}),t.restore(),t.save(),Do(t,s,a.bottom));Oo(t,{line:i,target:s,color:o,scale:r,property:l}),t.restore()}(t,{line:n,target:s,above:c,below:d,area:i,scale:o,axis:a}),De(t))}function Do(t,e,i){const{segments:s,points:n}=e;let o=!0,a=!1;t.beginPath();for(const r of s){const{start:s,end:l}=r,h=n[s],c=n[mo(s,l,n)];o?(t.moveTo(h.x,h.y),o=!1):(t.lineTo(h.x,i),t.lineTo(h.x,h.y)),a=!!e.pathSegment(t,r,{move:a}),a?t.closePath():t.lineTo(c.x,i)}t.lineTo(e.first().x,i),t.closePath(),t.clip()}function Oo(t,e){const{line:i,target:s,property:n,color:o,scale:a}=e,r=function(t,e,i){const s=t.segments,n=t.points,o=e.points,a=[];for(const t of s){let{start:s,end:r}=t;r=mo(s,r,n);const l=po(i,n[s],n[r],t.loop);if(!e.segments){a.push({source:t,target:l,start:n[s],end:n[r]});continue}const h=Pi(e,l);for(const e of h){const s=po(i,o[e.start],o[e.end],e.loop),r=Si(t,n,s);for(const t of r)a.push({source:t,target:e,start:{[i]:bo(l,s,\"start\",Math.max)},end:{[i]:bo(l,s,\"end\",Math.min)}})}}return a}(i,s,n);for(const{source:e,target:l,start:h,end:c}of r){const{style:{backgroundColor:r=o}={}}=e,d=!0!==s;t.save(),t.fillStyle=r,Co(t,a,d&&po(n,h,c)),t.beginPath();const u=!!i.pathSegment(t,e);let f;if(d){u?t.closePath():Ao(t,s,c,n);const e=!!s.pathSegment(t,l,{move:u,reverse:!0});f=u&&e,f||Ao(t,s,h,n)}t.closePath(),t.fill(f?\"evenodd\":\"nonzero\"),t.restore()}}function Co(t,e,i){const{top:s,bottom:n}=e.chart.chartArea,{property:o,start:a,end:r}=i||{};\"x\"===o&&(t.beginPath(),t.rect(a,s,r-a,n-s),t.clip())}function Ao(t,e,i,s){const n=e.interpolate(i,s);n&&t.lineTo(n.x,n.y)}var To={id:\"filler\",afterDatasetsUpdate(t,e,i){const s=(t.data.datasets||[]).length,n=[];let o,a,r,l;for(a=0;a<s;++a)o=t.getDatasetMeta(a),r=o.dataset,l=null,r&&r.options&&r instanceof to&&(l={visible:t.isDatasetVisible(a),index:a,fill:vo(r,a,s),chart:t,axis:o.controller.options.indexAxis,scale:o.vScale,line:r}),o.$filler=l,n.push(l);for(a=0;a<s;++a)l=n[a],l&&!1!==l.fill&&(l.fill=yo(n,a,i.propagate))},beforeDraw(t,e,i){const s=\"beforeDraw\"===i.drawTime,n=t.getSortedVisibleDatasetMetas(),o=t.chartArea;for(let e=n.length-1;e>=0;--e){const i=n[e].$filler;i&&(i.line.updateControlPoints(o,i.axis),s&&i.fill&&Po(t.ctx,i,o))}},beforeDatasetsDraw(t,e,i){if(\"beforeDatasetsDraw\"!==i.drawTime)return;const s=t.getSortedVisibleDatasetMetas();for(let e=s.length-1;e>=0;--e){const i=s[e].$filler;_o(i)&&Po(t.ctx,i,t.chartArea)}},beforeDatasetDraw(t,e,i){const s=e.meta.$filler;_o(s)&&\"beforeDatasetDraw\"===i.drawTime&&Po(t.ctx,s,t.chartArea)},defaults:{propagate:!0,drawTime:\"beforeDatasetDraw\"}};const Lo=(t,e)=>{let{boxHeight:i=e,boxWidth:s=e}=t;return t.usePointStyle&&(i=Math.min(i,e),s=t.pointStyleWidth||Math.min(s,e)),{boxWidth:s,boxHeight:i,itemHeight:Math.max(e,i)}};class Eo extends Es{constructor(t){super(),this._added=!1,this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1,this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this.legendItems=void 0,this.columnSizes=void 0,this.lineWidths=void 0,this.maxHeight=void 0,this.maxWidth=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.height=void 0,this.width=void 0,this._margins=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e,i){this.maxWidth=t,this.maxHeight=e,this._margins=i,this.setDimensions(),this.buildLabels(),this.fit()}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=this._margins.left,this.right=this.width):(this.height=this.maxHeight,this.top=this._margins.top,this.bottom=this.height)}buildLabels(){const t=this.options.labels||{};let e=c(t.generateLabels,[this.chart],this)||[];t.filter&&(e=e.filter((e=>t.filter(e,this.chart.data)))),t.sort&&(e=e.sort(((e,i)=>t.sort(e,i,this.chart.data)))),this.options.reverse&&e.reverse(),this.legendItems=e}fit(){const{options:t,ctx:e}=this;if(!t.display)return void(this.width=this.height=0);const i=t.labels,s=mi(i.font),n=s.size,o=this._computeTitleHeight(),{boxWidth:a,itemHeight:r}=Lo(i,n);let l,h;e.font=s.string,this.isHorizontal()?(l=this.maxWidth,h=this._fitRows(o,n,a,r)+10):(h=this.maxHeight,l=this._fitCols(o,n,a,r)+10),this.width=Math.min(l,t.maxWidth||this.maxWidth),this.height=Math.min(h,t.maxHeight||this.maxHeight)}_fitRows(t,e,i,s){const{ctx:n,maxWidth:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.lineWidths=[0],h=s+a;let c=t;n.textAlign=\"left\",n.textBaseline=\"middle\";let d=-1,u=-h;return this.legendItems.forEach(((t,f)=>{const g=i+e/2+n.measureText(t.text).width;(0===f||l[l.length-1]+g+2*a>o)&&(c+=h,l[l.length-(f>0?0:1)]=0,u+=h,d++),r[f]={left:0,top:u,row:d,width:g,height:s},l[l.length-1]+=g+a})),c}_fitCols(t,e,i,s){const{ctx:n,maxHeight:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.columnSizes=[],h=o-t;let c=a,d=0,u=0,f=0,g=0;return this.legendItems.forEach(((t,o)=>{const p=i+e/2+n.measureText(t.text).width;o>0&&u+s+2*a>h&&(c+=d+a,l.push({width:d,height:u}),f+=d+a,g++,d=u=0),r[o]={left:f,top:u,col:g,width:p,height:s},d=Math.max(d,p),u+=s+a})),c+=d,l.push({width:d,height:u}),c}adjustHitBoxes(){if(!this.options.display)return;const t=this._computeTitleHeight(),{legendHitBoxes:e,options:{align:i,labels:{padding:s},rtl:n}}=this,o=yi(n,this.left,this.width);if(this.isHorizontal()){let n=0,a=ut(i,this.left+s,this.right-this.lineWidths[n]);for(const r of e)n!==r.row&&(n=r.row,a=ut(i,this.left+s,this.right-this.lineWidths[n])),r.top+=this.top+t+s,r.left=o.leftForLtr(o.x(a),r.width),a+=r.width+s}else{let n=0,a=ut(i,this.top+t+s,this.bottom-this.columnSizes[n].height);for(const r of e)r.col!==n&&(n=r.col,a=ut(i,this.top+t+s,this.bottom-this.columnSizes[n].height)),r.top=a,r.left+=this.left+s,r.left=o.leftForLtr(o.x(r.left),r.width),a+=r.height+s}}isHorizontal(){return\"top\"===this.options.position||\"bottom\"===this.options.position}draw(){if(this.options.display){const t=this.ctx;Pe(t,this),this._draw(),De(t)}}_draw(){const{options:t,columnSizes:e,lineWidths:i,ctx:s}=this,{align:n,labels:o}=t,a=ne.color,l=yi(t.rtl,this.left,this.width),h=mi(o.font),{color:c,padding:d}=o,u=h.size,f=u/2;let g;this.drawTitle(),s.textAlign=l.textAlign(\"left\"),s.textBaseline=\"middle\",s.lineWidth=.5,s.font=h.string;const{boxWidth:p,boxHeight:m,itemHeight:b}=Lo(o,u),x=this.isHorizontal(),_=this._computeTitleHeight();g=x?{x:ut(n,this.left+d,this.right-i[0]),y:this.top+d+_,line:0}:{x:this.left+d,y:ut(n,this.top+_+d,this.bottom-e[0].height),line:0},vi(this.ctx,t.textDirection);const y=b+d;this.legendItems.forEach(((v,w)=>{s.strokeStyle=v.fontColor||c,s.fillStyle=v.fontColor||c;const M=s.measureText(v.text).width,k=l.textAlign(v.textAlign||(v.textAlign=o.textAlign)),S=p+f+M;let P=g.x,D=g.y;l.setWidth(this.width),x?w>0&&P+S+d>this.right&&(D=g.y+=y,g.line++,P=g.x=ut(n,this.left+d,this.right-i[g.line])):w>0&&D+y>this.bottom&&(P=g.x=P+e[g.line].width+d,g.line++,D=g.y=ut(n,this.top+_+d,this.bottom-e[g.line].height));!function(t,e,i){if(isNaN(p)||p<=0||isNaN(m)||m<0)return;s.save();const n=r(i.lineWidth,1);if(s.fillStyle=r(i.fillStyle,a),s.lineCap=r(i.lineCap,\"butt\"),s.lineDashOffset=r(i.lineDashOffset,0),s.lineJoin=r(i.lineJoin,\"miter\"),s.lineWidth=n,s.strokeStyle=r(i.strokeStyle,a),s.setLineDash(r(i.lineDash,[])),o.usePointStyle){const a={radius:m*Math.SQRT2/2,pointStyle:i.pointStyle,rotation:i.rotation,borderWidth:n},r=l.xPlus(t,p/2);ke(s,a,r,e+f,o.pointStyleWidth&&p)}else{const o=e+Math.max((u-m)/2,0),a=l.leftForLtr(t,p),r=gi(i.borderRadius);s.beginPath(),Object.values(r).some((t=>0!==t))?Le(s,{x:a,y:o,w:p,h:m,radius:r}):s.rect(a,o,p,m),s.fill(),0!==n&&s.stroke()}s.restore()}(l.x(P),D,v),P=ft(k,P+p+f,x?P+S:this.right,t.rtl),function(t,e,i){Ae(s,i.text,t,e+b/2,h,{strikethrough:i.hidden,textAlign:l.textAlign(i.textAlign)})}(l.x(P),D,v),x?g.x+=S+d:g.y+=y})),wi(this.ctx,t.textDirection)}drawTitle(){const t=this.options,e=t.title,i=mi(e.font),s=pi(e.padding);if(!e.display)return;const n=yi(t.rtl,this.left,this.width),o=this.ctx,a=e.position,r=i.size/2,l=s.top+r;let h,c=this.left,d=this.width;if(this.isHorizontal())d=Math.max(...this.lineWidths),h=this.top+l,c=ut(t.align,c,this.right-d);else{const e=this.columnSizes.reduce(((t,e)=>Math.max(t,e.height)),0);h=l+ut(t.align,this.top,this.bottom-e-t.labels.padding-this._computeTitleHeight())}const u=ut(a,c,c+d);o.textAlign=n.textAlign(dt(a)),o.textBaseline=\"middle\",o.strokeStyle=e.color,o.fillStyle=e.color,o.font=i.string,Ae(o,e.text,u,h,i)}_computeTitleHeight(){const t=this.options.title,e=mi(t.font),i=pi(t.padding);return t.display?e.lineHeight+i.height:0}_getLegendItemAt(t,e){let i,s,n;if(Q(t,this.left,this.right)&&Q(e,this.top,this.bottom))for(n=this.legendHitBoxes,i=0;i<n.length;++i)if(s=n[i],Q(t,s.left,s.left+s.width)&&Q(e,s.top,s.top+s.height))return this.legendItems[i];return null}handleEvent(t){const e=this.options;if(!function(t,e){if((\"mousemove\"===t||\"mouseout\"===t)&&(e.onHover||e.onLeave))return!0;if(e.onClick&&(\"click\"===t||\"mouseup\"===t))return!0;return!1}(t.type,e))return;const i=this._getLegendItemAt(t.x,t.y);if(\"mousemove\"===t.type||\"mouseout\"===t.type){const o=this._hoveredItem,a=(n=i,null!==(s=o)&&null!==n&&s.datasetIndex===n.datasetIndex&&s.index===n.index);o&&!a&&c(e.onLeave,[t,o,this],this),this._hoveredItem=i,i&&!a&&c(e.onHover,[t,i,this],this)}else i&&c(e.onClick,[t,i,this],this);var s,n}}var Ro={id:\"legend\",_element:Eo,start(t,e,i){const s=t.legend=new Eo({ctx:t.ctx,options:i,chart:t});Zi.configure(t,s,i),Zi.addBox(t,s)},stop(t){Zi.removeBox(t,t.legend),delete t.legend},beforeUpdate(t,e,i){const s=t.legend;Zi.configure(t,s,i),s.options=i},afterUpdate(t){const e=t.legend;e.buildLabels(),e.adjustHitBoxes()},afterEvent(t,e){e.replay||t.legend.handleEvent(e.event)},defaults:{display:!0,position:\"top\",align:\"center\",fullSize:!0,reverse:!1,weight:1e3,onClick(t,e,i){const s=e.datasetIndex,n=i.chart;n.isDatasetVisible(s)?(n.hide(s),e.hidden=!0):(n.show(s),e.hidden=!1)},onHover:null,onLeave:null,labels:{color:t=>t.chart.options.color,boxWidth:40,padding:10,generateLabels(t){const e=t.data.datasets,{labels:{usePointStyle:i,pointStyle:s,textAlign:n,color:o}}=t.legend.options;return t._getSortedDatasetMetas().map((t=>{const a=t.controller.getStyle(i?0:void 0),r=pi(a.borderWidth);return{text:e[t.index].label,fillStyle:a.backgroundColor,fontColor:o,hidden:!t.visible,lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:(r.width+r.height)/4,strokeStyle:a.borderColor,pointStyle:s||a.pointStyle,rotation:a.rotation,textAlign:n||a.textAlign,borderRadius:0,datasetIndex:t.index}}),this)}},title:{color:t=>t.chart.options.color,display:!1,position:\"center\",text:\"\"}},descriptors:{_scriptable:t=>!t.startsWith(\"on\"),labels:{_scriptable:t=>![\"generateLabels\",\"filter\",\"sort\"].includes(t)}}};class Io extends Es{constructor(t){super(),this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this._padding=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e){const i=this.options;if(this.left=0,this.top=0,!i.display)return void(this.width=this.height=this.right=this.bottom=0);this.width=this.right=t,this.height=this.bottom=e;const n=s(i.text)?i.text.length:1;this._padding=pi(i.padding);const o=n*mi(i.font).lineHeight+this._padding.height;this.isHorizontal()?this.height=o:this.width=o}isHorizontal(){const t=this.options.position;return\"top\"===t||\"bottom\"===t}_drawArgs(t){const{top:e,left:i,bottom:s,right:n,options:o}=this,a=o.align;let r,l,h,c=0;return this.isHorizontal()?(l=ut(a,i,n),h=e+t,r=n-i):(\"left\"===o.position?(l=i+t,h=ut(a,s,e),c=-.5*D):(l=n-t,h=ut(a,e,s),c=.5*D),r=s-e),{titleX:l,titleY:h,maxWidth:r,rotation:c}}draw(){const t=this.ctx,e=this.options;if(!e.display)return;const i=mi(e.font),s=i.lineHeight/2+this._padding.top,{titleX:n,titleY:o,maxWidth:a,rotation:r}=this._drawArgs(s);Ae(t,e.text,0,0,i,{color:e.color,maxWidth:a,rotation:r,textAlign:dt(e.align),textBaseline:\"middle\",translation:[n,o]})}}var zo={id:\"title\",_element:Io,start(t,e,i){!function(t,e){const i=new Io({ctx:t.ctx,options:e,chart:t});Zi.configure(t,i,e),Zi.addBox(t,i),t.titleBlock=i}(t,i)},stop(t){const e=t.titleBlock;Zi.removeBox(t,e),delete t.titleBlock},beforeUpdate(t,e,i){const s=t.titleBlock;Zi.configure(t,s,i),s.options=i},defaults:{align:\"center\",display:!1,font:{weight:\"bold\"},fullSize:!0,padding:10,position:\"top\",text:\"\",weight:2e3},defaultRoutes:{color:\"color\"},descriptors:{_scriptable:!0,_indexable:!1}};const Fo=new WeakMap;var Vo={id:\"subtitle\",start(t,e,i){const s=new Io({ctx:t.ctx,options:i,chart:t});Zi.configure(t,s,i),Zi.addBox(t,s),Fo.set(t,s)},stop(t){Zi.removeBox(t,Fo.get(t)),Fo.delete(t)},beforeUpdate(t,e,i){const s=Fo.get(t);Zi.configure(t,s,i),s.options=i},defaults:{align:\"center\",display:!1,font:{weight:\"normal\"},fullSize:!0,padding:0,position:\"top\",text:\"\",weight:1500},defaultRoutes:{color:\"color\"},descriptors:{_scriptable:!0,_indexable:!1}};const Bo={average(t){if(!t.length)return!1;let e,i,s=0,n=0,o=0;for(e=0,i=t.length;e<i;++e){const i=t[e].element;if(i&&i.hasValue()){const t=i.tooltipPosition();s+=t.x,n+=t.y,++o}}return{x:s/o,y:n/o}},nearest(t,e){if(!t.length)return!1;let i,s,n,o=e.x,a=e.y,r=Number.POSITIVE_INFINITY;for(i=0,s=t.length;i<s;++i){const s=t[i].element;if(s&&s.hasValue()){const t=X(e,s.getCenterPoint());t<r&&(r=t,n=s)}}if(n){const t=n.tooltipPosition();o=t.x,a=t.y}return{x:o,y:a}}};function No(t,e){return e&&(s(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function Wo(t){return(\"string\"==typeof t||t instanceof String)&&t.indexOf(\"\\n\")>-1?t.split(\"\\n\"):t}function jo(t,e){const{element:i,datasetIndex:s,index:n}=e,o=t.getDatasetMeta(s).controller,{label:a,value:r}=o.getLabelAndValue(n);return{chart:t,label:a,parsed:o.getParsed(n),raw:t.data.datasets[s].data[n],formattedValue:r,dataset:o.getDataset(),dataIndex:n,datasetIndex:s,element:i}}function Ho(t,e){const i=t.chart.ctx,{body:s,footer:n,title:o}=t,{boxWidth:a,boxHeight:r}=e,l=mi(e.bodyFont),h=mi(e.titleFont),c=mi(e.footerFont),u=o.length,f=n.length,g=s.length,p=pi(e.padding);let m=p.height,b=0,x=s.reduce(((t,e)=>t+e.before.length+e.lines.length+e.after.length),0);if(x+=t.beforeBody.length+t.afterBody.length,u&&(m+=u*h.lineHeight+(u-1)*e.titleSpacing+e.titleMarginBottom),x){m+=g*(e.displayColors?Math.max(r,l.lineHeight):l.lineHeight)+(x-g)*l.lineHeight+(x-1)*e.bodySpacing}f&&(m+=e.footerMarginTop+f*c.lineHeight+(f-1)*e.footerSpacing);let _=0;const y=function(t){b=Math.max(b,i.measureText(t).width+_)};return i.save(),i.font=h.string,d(t.title,y),i.font=l.string,d(t.beforeBody.concat(t.afterBody),y),_=e.displayColors?a+2+e.boxPadding:0,d(s,(t=>{d(t.before,y),d(t.lines,y),d(t.after,y)})),_=0,i.font=c.string,d(t.footer,y),i.restore(),b+=p.width,{width:b,height:m}}function $o(t,e,i,s){const{x:n,width:o}=i,{width:a,chartArea:{left:r,right:l}}=t;let h=\"center\";return\"center\"===s?h=n<=(r+l)/2?\"left\":\"right\":n<=o/2?h=\"left\":n>=a-o/2&&(h=\"right\"),function(t,e,i,s){const{x:n,width:o}=s,a=i.caretSize+i.caretPadding;return\"left\"===t&&n+o+a>e.width||\"right\"===t&&n-o-a<0||void 0}(h,t,e,i)&&(h=\"center\"),h}function Yo(t,e,i){const s=i.yAlign||e.yAlign||function(t,e){const{y:i,height:s}=e;return i<s/2?\"top\":i>t.height-s/2?\"bottom\":\"center\"}(t,i);return{xAlign:i.xAlign||e.xAlign||$o(t,e,i,s),yAlign:s}}function Uo(t,e,i,s){const{caretSize:n,caretPadding:o,cornerRadius:a}=t,{xAlign:r,yAlign:l}=i,h=n+o,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=gi(a);let g=function(t,e){let{x:i,width:s}=t;return\"right\"===e?i-=s:\"center\"===e&&(i-=s/2),i}(e,r);const p=function(t,e,i){let{y:s,height:n}=t;return\"top\"===e?s+=i:s-=\"bottom\"===e?n+i:n/2,s}(e,l,h);return\"center\"===l?\"left\"===r?g+=h:\"right\"===r&&(g-=h):\"left\"===r?g-=Math.max(c,u)+n:\"right\"===r&&(g+=Math.max(d,f)+n),{x:Z(g,0,s.width-e.width),y:Z(p,0,s.height-e.height)}}function Xo(t,e,i){const s=pi(i.padding);return\"center\"===e?t.x+t.width/2:\"right\"===e?t.x+t.width-s.right:t.x+s.left}function qo(t){return No([],Wo(t))}function Ko(t,e){const i=e&&e.dataset&&e.dataset.tooltip&&e.dataset.tooltip.callbacks;return i?t.override(i):t}class Go extends Es{constructor(t){super(),this.opacity=0,this._active=[],this._eventPosition=void 0,this._size=void 0,this._cachedAnimations=void 0,this._tooltipItems=[],this.$animations=void 0,this.$context=void 0,this.chart=t.chart||t._chart,this._chart=this.chart,this.options=t.options,this.dataPoints=void 0,this.title=void 0,this.beforeBody=void 0,this.body=void 0,this.afterBody=void 0,this.footer=void 0,this.xAlign=void 0,this.yAlign=void 0,this.x=void 0,this.y=void 0,this.height=void 0,this.width=void 0,this.caretX=void 0,this.caretY=void 0,this.labelColors=void 0,this.labelPointStyles=void 0,this.labelTextColors=void 0}initialize(t){this.options=t,this._cachedAnimations=void 0,this.$context=void 0}_resolveAnimations(){const t=this._cachedAnimations;if(t)return t;const e=this.chart,i=this.options.setContext(this.getContext()),s=i.enabled&&e.options.animation&&i.animations,n=new ys(this.chart,s);return s._cacheable&&(this._cachedAnimations=Object.freeze(n)),n}getContext(){return this.$context||(this.$context=(t=this.chart.getContext(),e=this,i=this._tooltipItems,_i(t,{tooltip:e,tooltipItems:i,type:\"tooltip\"})));var t,e,i}getTitle(t,e){const{callbacks:i}=e,s=i.beforeTitle.apply(this,[t]),n=i.title.apply(this,[t]),o=i.afterTitle.apply(this,[t]);let a=[];return a=No(a,Wo(s)),a=No(a,Wo(n)),a=No(a,Wo(o)),a}getBeforeBody(t,e){return qo(e.callbacks.beforeBody.apply(this,[t]))}getBody(t,e){const{callbacks:i}=e,s=[];return d(t,(t=>{const e={before:[],lines:[],after:[]},n=Ko(i,t);No(e.before,Wo(n.beforeLabel.call(this,t))),No(e.lines,n.label.call(this,t)),No(e.after,Wo(n.afterLabel.call(this,t))),s.push(e)})),s}getAfterBody(t,e){return qo(e.callbacks.afterBody.apply(this,[t]))}getFooter(t,e){const{callbacks:i}=e,s=i.beforeFooter.apply(this,[t]),n=i.footer.apply(this,[t]),o=i.afterFooter.apply(this,[t]);let a=[];return a=No(a,Wo(s)),a=No(a,Wo(n)),a=No(a,Wo(o)),a}_createItems(t){const e=this._active,i=this.chart.data,s=[],n=[],o=[];let a,r,l=[];for(a=0,r=e.length;a<r;++a)l.push(jo(this.chart,e[a]));return t.filter&&(l=l.filter(((e,s,n)=>t.filter(e,s,n,i)))),t.itemSort&&(l=l.sort(((e,s)=>t.itemSort(e,s,i)))),d(l,(e=>{const i=Ko(t.callbacks,e);s.push(i.labelColor.call(this,e)),n.push(i.labelPointStyle.call(this,e)),o.push(i.labelTextColor.call(this,e))})),this.labelColors=s,this.labelPointStyles=n,this.labelTextColors=o,this.dataPoints=l,l}update(t,e){const i=this.options.setContext(this.getContext()),s=this._active;let n,o=[];if(s.length){const t=Bo[i.position].call(this,s,this._eventPosition);o=this._createItems(i),this.title=this.getTitle(o,i),this.beforeBody=this.getBeforeBody(o,i),this.body=this.getBody(o,i),this.afterBody=this.getAfterBody(o,i),this.footer=this.getFooter(o,i);const e=this._size=Ho(this,i),a=Object.assign({},t,e),r=Yo(this.chart,i,a),l=Uo(i,a,r,this.chart);this.xAlign=r.xAlign,this.yAlign=r.yAlign,n={opacity:1,x:l.x,y:l.y,width:e.width,height:e.height,caretX:t.x,caretY:t.y}}else 0!==this.opacity&&(n={opacity:0});this._tooltipItems=o,this.$context=void 0,n&&this._resolveAnimations().update(this,n),t&&i.external&&i.external.call(this,{chart:this.chart,tooltip:this,replay:e})}drawCaret(t,e,i,s){const n=this.getCaretPosition(t,i,s);e.lineTo(n.x1,n.y1),e.lineTo(n.x2,n.y2),e.lineTo(n.x3,n.y3)}getCaretPosition(t,e,i){const{xAlign:s,yAlign:n}=this,{caretSize:o,cornerRadius:a}=i,{topLeft:r,topRight:l,bottomLeft:h,bottomRight:c}=gi(a),{x:d,y:u}=t,{width:f,height:g}=e;let p,m,b,x,_,y;return\"center\"===n?(_=u+g/2,\"left\"===s?(p=d,m=p-o,x=_+o,y=_-o):(p=d+f,m=p+o,x=_-o,y=_+o),b=p):(m=\"left\"===s?d+Math.max(r,h)+o:\"right\"===s?d+f-Math.max(l,c)-o:this.caretX,\"top\"===n?(x=u,_=x-o,p=m-o,b=m+o):(x=u+g,_=x+o,p=m+o,b=m-o),y=x),{x1:p,x2:m,x3:b,y1:x,y2:_,y3:y}}drawTitle(t,e,i){const s=this.title,n=s.length;let o,a,r;if(n){const l=yi(i.rtl,this.x,this.width);for(t.x=Xo(this,i.titleAlign,i),e.textAlign=l.textAlign(i.titleAlign),e.textBaseline=\"middle\",o=mi(i.titleFont),a=i.titleSpacing,e.fillStyle=i.titleColor,e.font=o.string,r=0;r<n;++r)e.fillText(s[r],l.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+a,r+1===n&&(t.y+=i.titleMarginBottom-a)}}_drawColorBox(t,e,i,s,o){const a=this.labelColors[i],r=this.labelPointStyles[i],{boxHeight:l,boxWidth:h,boxPadding:c}=o,d=mi(o.bodyFont),u=Xo(this,\"left\",o),f=s.x(u),g=l<d.lineHeight?(d.lineHeight-l)/2:0,p=e.y+g;if(o.usePointStyle){const e={radius:Math.min(h,l)/2,pointStyle:r.pointStyle,rotation:r.rotation,borderWidth:1},i=s.leftForLtr(f,h)+h/2,n=p+l/2;t.strokeStyle=o.multiKeyBackground,t.fillStyle=o.multiKeyBackground,Me(t,e,i,n),t.strokeStyle=a.borderColor,t.fillStyle=a.backgroundColor,Me(t,e,i,n)}else{t.lineWidth=n(a.borderWidth)?Math.max(...Object.values(a.borderWidth)):a.borderWidth||1,t.strokeStyle=a.borderColor,t.setLineDash(a.borderDash||[]),t.lineDashOffset=a.borderDashOffset||0;const e=s.leftForLtr(f,h-c),i=s.leftForLtr(s.xPlus(f,1),h-c-2),r=gi(a.borderRadius);Object.values(r).some((t=>0!==t))?(t.beginPath(),t.fillStyle=o.multiKeyBackground,Le(t,{x:e,y:p,w:h,h:l,radius:r}),t.fill(),t.stroke(),t.fillStyle=a.backgroundColor,t.beginPath(),Le(t,{x:i,y:p+1,w:h-2,h:l-2,radius:r}),t.fill()):(t.fillStyle=o.multiKeyBackground,t.fillRect(e,p,h,l),t.strokeRect(e,p,h,l),t.fillStyle=a.backgroundColor,t.fillRect(i,p+1,h-2,l-2))}t.fillStyle=this.labelTextColors[i]}drawBody(t,e,i){const{body:s}=this,{bodySpacing:n,bodyAlign:o,displayColors:a,boxHeight:r,boxWidth:l,boxPadding:h}=i,c=mi(i.bodyFont);let u=c.lineHeight,f=0;const g=yi(i.rtl,this.x,this.width),p=function(i){e.fillText(i,g.x(t.x+f),t.y+u/2),t.y+=u+n},m=g.textAlign(o);let b,x,_,y,v,w,M;for(e.textAlign=o,e.textBaseline=\"middle\",e.font=c.string,t.x=Xo(this,m,i),e.fillStyle=i.bodyColor,d(this.beforeBody,p),f=a&&\"right\"!==m?\"center\"===o?l/2+h:l+2+h:0,y=0,w=s.length;y<w;++y){for(b=s[y],x=this.labelTextColors[y],e.fillStyle=x,d(b.before,p),_=b.lines,a&&_.length&&(this._drawColorBox(e,t,y,g,i),u=Math.max(c.lineHeight,r)),v=0,M=_.length;v<M;++v)p(_[v]),u=c.lineHeight;d(b.after,p)}f=0,u=c.lineHeight,d(this.afterBody,p),t.y-=n}drawFooter(t,e,i){const s=this.footer,n=s.length;let o,a;if(n){const r=yi(i.rtl,this.x,this.width);for(t.x=Xo(this,i.footerAlign,i),t.y+=i.footerMarginTop,e.textAlign=r.textAlign(i.footerAlign),e.textBaseline=\"middle\",o=mi(i.footerFont),e.fillStyle=i.footerColor,e.font=o.string,a=0;a<n;++a)e.fillText(s[a],r.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+i.footerSpacing}}drawBackground(t,e,i,s){const{xAlign:n,yAlign:o}=this,{x:a,y:r}=t,{width:l,height:h}=i,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=gi(s.cornerRadius);e.fillStyle=s.backgroundColor,e.strokeStyle=s.borderColor,e.lineWidth=s.borderWidth,e.beginPath(),e.moveTo(a+c,r),\"top\"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+l-d,r),e.quadraticCurveTo(a+l,r,a+l,r+d),\"center\"===o&&\"right\"===n&&this.drawCaret(t,e,i,s),e.lineTo(a+l,r+h-f),e.quadraticCurveTo(a+l,r+h,a+l-f,r+h),\"bottom\"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+u,r+h),e.quadraticCurveTo(a,r+h,a,r+h-u),\"center\"===o&&\"left\"===n&&this.drawCaret(t,e,i,s),e.lineTo(a,r+c),e.quadraticCurveTo(a,r,a+c,r),e.closePath(),e.fill(),s.borderWidth>0&&e.stroke()}_updateAnimationTarget(t){const e=this.chart,i=this.$animations,s=i&&i.x,n=i&&i.y;if(s||n){const i=Bo[t.position].call(this,this._active,this._eventPosition);if(!i)return;const o=this._size=Ho(this,t),a=Object.assign({},i,this._size),r=Yo(e,t,a),l=Uo(t,a,r,e);s._to===l.x&&n._to===l.y||(this.xAlign=r.xAlign,this.yAlign=r.yAlign,this.width=o.width,this.height=o.height,this.caretX=i.x,this.caretY=i.y,this._resolveAnimations().update(this,l))}}_willRender(){return!!this.opacity}draw(t){const e=this.options.setContext(this.getContext());let i=this.opacity;if(!i)return;this._updateAnimationTarget(e);const s={width:this.width,height:this.height},n={x:this.x,y:this.y};i=Math.abs(i)<.001?0:i;const o=pi(e.padding),a=this.title.length||this.beforeBody.length||this.body.length||this.afterBody.length||this.footer.length;e.enabled&&a&&(t.save(),t.globalAlpha=i,this.drawBackground(n,t,s,e),vi(t,e.textDirection),n.y+=o.top,this.drawTitle(n,t,e),this.drawBody(n,t,e),this.drawFooter(n,t,e),wi(t,e.textDirection),t.restore())}getActiveElements(){return this._active||[]}setActiveElements(t,e){const i=this._active,s=t.map((({datasetIndex:t,index:e})=>{const i=this.chart.getDatasetMeta(t);if(!i)throw new Error(\"Cannot find a dataset at index \"+t);return{datasetIndex:t,element:i.data[e],index:e}})),n=!u(i,s),o=this._positionChanged(s,e);(n||o)&&(this._active=s,this._eventPosition=e,this._ignoreReplayEvents=!0,this.update(!0))}handleEvent(t,e,i=!0){if(e&&this._ignoreReplayEvents)return!1;this._ignoreReplayEvents=!1;const s=this.options,n=this._active||[],o=this._getActiveElements(t,n,e,i),a=this._positionChanged(o,t),r=e||!u(o,n)||a;return r&&(this._active=o,(s.enabled||s.external)&&(this._eventPosition={x:t.x,y:t.y},this.update(!0,e))),r}_getActiveElements(t,e,i,s){const n=this.options;if(\"mouseout\"===t.type)return[];if(!s)return e;const o=this.chart.getElementsAtEventForMode(t,n.mode,n,i);return n.reverse&&o.reverse(),o}_positionChanged(t,e){const{caretX:i,caretY:s,options:n}=this,o=Bo[n.position].call(this,t,e);return!1!==o&&(i!==o.x||s!==o.y)}}Go.positioners=Bo;var Zo={id:\"tooltip\",_element:Go,positioners:Bo,afterInit(t,e,i){i&&(t.tooltip=new Go({chart:t,options:i}))},beforeUpdate(t,e,i){t.tooltip&&t.tooltip.initialize(i)},reset(t,e,i){t.tooltip&&t.tooltip.initialize(i)},afterDraw(t){const e=t.tooltip;if(e&&e._willRender()){const i={tooltip:e};if(!1===t.notifyPlugins(\"beforeTooltipDraw\",i))return;e.draw(t.ctx),t.notifyPlugins(\"afterTooltipDraw\",i)}},afterEvent(t,e){if(t.tooltip){const i=e.replay;t.tooltip.handleEvent(e.event,i,e.inChartArea)&&(e.changed=!0)}},defaults:{enabled:!0,external:null,position:\"average\",backgroundColor:\"rgba(0,0,0,0.8)\",titleColor:\"#fff\",titleFont:{weight:\"bold\"},titleSpacing:2,titleMarginBottom:6,titleAlign:\"left\",bodyColor:\"#fff\",bodySpacing:2,bodyFont:{},bodyAlign:\"left\",footerColor:\"#fff\",footerSpacing:2,footerMarginTop:6,footerFont:{weight:\"bold\"},footerAlign:\"left\",padding:6,caretPadding:2,caretSize:5,cornerRadius:6,boxHeight:(t,e)=>e.bodyFont.size,boxWidth:(t,e)=>e.bodyFont.size,multiKeyBackground:\"#fff\",displayColors:!0,boxPadding:0,borderColor:\"rgba(0,0,0,0)\",borderWidth:0,animation:{duration:400,easing:\"easeOutQuart\"},animations:{numbers:{type:\"number\",properties:[\"x\",\"y\",\"width\",\"height\",\"caretX\",\"caretY\"]},opacity:{easing:\"linear\",duration:200}},callbacks:{beforeTitle:t,title(t){if(t.length>0){const e=t[0],i=e.chart.data.labels,s=i?i.length:0;if(this&&this.options&&\"dataset\"===this.options.mode)return e.dataset.label||\"\";if(e.label)return e.label;if(s>0&&e.dataIndex<s)return i[e.dataIndex]}return\"\"},afterTitle:t,beforeBody:t,beforeLabel:t,label(t){if(this&&this.options&&\"dataset\"===this.options.mode)return t.label+\": \"+t.formattedValue||t.formattedValue;let e=t.dataset.label||\"\";e&&(e+=\": \");const s=t.formattedValue;return i(s)||(e+=s),e},labelColor(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{borderColor:e.borderColor,backgroundColor:e.backgroundColor,borderWidth:e.borderWidth,borderDash:e.borderDash,borderDashOffset:e.borderDashOffset,borderRadius:0}},labelTextColor(){return this.options.bodyColor},labelPointStyle(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{pointStyle:e.pointStyle,rotation:e.rotation}},afterLabel:t,afterBody:t,beforeFooter:t,footer:t,afterFooter:t}},defaultRoutes:{bodyFont:\"font\",footerFont:\"font\",titleFont:\"font\"},descriptors:{_scriptable:t=>\"filter\"!==t&&\"itemSort\"!==t&&\"external\"!==t,_indexable:!1,callbacks:{_scriptable:!1,_indexable:!1},animation:{_fallback:!1},animations:{_fallback:\"animation\"}},additionalOptionScopes:[\"interaction\"]},Jo=Object.freeze({__proto__:null,Decimation:go,Filler:To,Legend:Ro,SubTitle:Vo,Title:zo,Tooltip:Zo});function Qo(t,e,i,s){const n=t.indexOf(e);if(-1===n)return((t,e,i,s)=>(\"string\"==typeof e?(i=t.push(e)-1,s.unshift({index:i,label:e})):isNaN(e)&&(i=null),i))(t,e,i,s);return n!==t.lastIndexOf(e)?i:n}class ta extends $s{constructor(t){super(t),this._startValue=void 0,this._valueRange=0,this._addedLabels=[]}init(t){const e=this._addedLabels;if(e.length){const t=this.getLabels();for(const{index:i,label:s}of e)t[i]===s&&t.splice(i,1);this._addedLabels=[]}super.init(t)}parse(t,e){if(i(t))return null;const s=this.getLabels();return((t,e)=>null===t?null:Z(Math.round(t),0,e))(e=isFinite(e)&&s[e]===t?e:Qo(s,t,r(e,t),this._addedLabels),s.length-1)}determineDataLimits(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let{min:i,max:s}=this.getMinMax(!0);\"ticks\"===this.options.bounds&&(t||(i=0),e||(s=this.getLabels().length-1)),this.min=i,this.max=s}buildTicks(){const t=this.min,e=this.max,i=this.options.offset,s=[];let n=this.getLabels();n=0===t&&e===n.length-1?n:n.slice(t,e+1),this._valueRange=Math.max(n.length-(i?0:1),1),this._startValue=this.min-(i?.5:0);for(let i=t;i<=e;i++)s.push({value:i});return s}getLabelForValue(t){const e=this.getLabels();return t>=0&&t<e.length?e[t]:t}configure(){super.configure(),this.isHorizontal()||(this._reversePixels=!this._reversePixels)}getPixelForValue(t){return\"number\"!=typeof t&&(t=this.parse(t)),null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getValueForPixel(t){return Math.round(this._startValue+this.getDecimalForPixel(t)*this._valueRange)}getBasePixel(){return this.bottom}}function ea(t,e,{horizontal:i,minRotation:s}){const n=H(s),o=(i?Math.sin(n):Math.cos(n))||.001,a=.75*e*(\"\"+t).length;return Math.min(e/o,a)}ta.id=\"category\",ta.defaults={ticks:{callback:ta.prototype.getLabelForValue}};class ia extends $s{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._endValue=void 0,this._valueRange=0}parse(t,e){return i(t)||(\"number\"==typeof t||t instanceof Number)&&!isFinite(+t)?null:+t}handleTickRangeOptions(){const{beginAtZero:t}=this.options,{minDefined:e,maxDefined:i}=this.getUserBounds();let{min:s,max:n}=this;const o=t=>s=e?s:t,a=t=>n=i?n:t;if(t){const t=z(s),e=z(n);t<0&&e<0?a(0):t>0&&e>0&&o(0)}if(s===n){let e=1;(n>=Number.MAX_SAFE_INTEGER||s<=Number.MIN_SAFE_INTEGER)&&(e=Math.abs(.05*n)),a(n+e),t||o(s-e)}this.min=s,this.max=n}getTickLimit(){const t=this.options.ticks;let e,{maxTicksLimit:i,stepSize:s}=t;return s?(e=Math.ceil(this.max/s)-Math.floor(this.min/s)+1,e>1e3&&(console.warn(`scales.${this.id}.ticks.stepSize: ${s} would result generating up to ${e} ticks. Limiting to 1000.`),e=1e3)):(e=this.computeTickLimit(),i=i||11),i&&(e=Math.min(i,e)),e}computeTickLimit(){return Number.POSITIVE_INFINITY}buildTicks(){const t=this.options,e=t.ticks;let s=this.getTickLimit();s=Math.max(2,s);const n=function(t,e){const s=[],{bounds:n,step:o,min:a,max:r,precision:l,count:h,maxTicks:c,maxDigits:d,includeBounds:u}=t,f=o||1,g=c-1,{min:p,max:m}=e,b=!i(a),x=!i(r),_=!i(h),y=(m-p)/(d+1);let v,w,M,k,S=F((m-p)/g/f)*f;if(S<1e-14&&!b&&!x)return[{value:p},{value:m}];k=Math.ceil(m/S)-Math.floor(p/S),k>g&&(S=F(k*S/g/f)*f),i(l)||(v=Math.pow(10,l),S=Math.ceil(S*v)/v),\"ticks\"===n?(w=Math.floor(p/S)*S,M=Math.ceil(m/S)*S):(w=p,M=m),b&&x&&o&&W((r-a)/o,S/1e3)?(k=Math.round(Math.min((r-a)/S,c)),S=(r-a)/k,w=a,M=r):_?(w=b?a:w,M=x?r:M,k=h-1,S=(M-w)/k):(k=(M-w)/S,k=N(k,Math.round(k),S/1e3)?Math.round(k):Math.ceil(k));const P=Math.max(Y(S),Y(w));v=Math.pow(10,i(l)?P:l),w=Math.round(w*v)/v,M=Math.round(M*v)/v;let D=0;for(b&&(u&&w!==a?(s.push({value:a}),w<a&&D++,N(Math.round((w+D*S)*v)/v,a,ea(a,y,t))&&D++):w<a&&D++);D<k;++D)s.push({value:Math.round((w+D*S)*v)/v});return x&&u&&M!==r?s.length&&N(s[s.length-1].value,r,ea(r,y,t))?s[s.length-1].value=r:s.push({value:r}):x&&M!==r||s.push({value:M}),s}({maxTicks:s,bounds:t.bounds,min:t.min,max:t.max,precision:e.precision,step:e.stepSize,count:e.count,maxDigits:this._maxDigits(),horizontal:this.isHorizontal(),minRotation:e.minRotation||0,includeBounds:!1!==e.includeBounds},this._range||this);return\"ticks\"===t.bounds&&j(n,this,\"value\"),t.reverse?(n.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),n}configure(){const t=this.ticks;let e=this.min,i=this.max;if(super.configure(),this.options.offset&&t.length){const s=(i-e)/Math.max(t.length-1,1)/2;e-=s,i+=s}this._startValue=e,this._endValue=i,this._valueRange=i-e}getLabelForValue(t){return li(t,this.chart.options.locale,this.options.ticks.format)}}class sa extends ia{determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=o(t)?t:0,this.max=o(e)?e:1,this.handleTickRangeOptions()}computeTickLimit(){const t=this.isHorizontal(),e=t?this.width:this.height,i=H(this.options.ticks.minRotation),s=(t?Math.sin(i):Math.cos(i))||.001,n=this._resolveTickFontOptions(0);return Math.ceil(e/Math.min(40,n.lineHeight/s))}getPixelForValue(t){return null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getValueForPixel(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange}}function na(t){return 1===t/Math.pow(10,Math.floor(I(t)))}sa.id=\"linear\",sa.defaults={ticks:{callback:Is.formatters.numeric}};class oa extends $s{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._valueRange=0}parse(t,e){const i=ia.prototype.parse.apply(this,[t,e]);if(0!==i)return o(i)&&i>0?i:null;this._zero=!0}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=o(t)?Math.max(0,t):null,this.max=o(e)?Math.max(0,e):null,this.options.beginAtZero&&(this._zero=!0),this.handleTickRangeOptions()}handleTickRangeOptions(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let i=this.min,s=this.max;const n=e=>i=t?i:e,o=t=>s=e?s:t,a=(t,e)=>Math.pow(10,Math.floor(I(t))+e);i===s&&(i<=0?(n(1),o(10)):(n(a(i,-1)),o(a(s,1)))),i<=0&&n(a(s,-1)),s<=0&&o(a(i,1)),this._zero&&this.min!==this._suggestedMin&&i===a(this.min,0)&&n(a(i,-1)),this.min=i,this.max=s}buildTicks(){const t=this.options,e=function(t,e){const i=Math.floor(I(e.max)),s=Math.ceil(e.max/Math.pow(10,i)),n=[];let o=a(t.min,Math.pow(10,Math.floor(I(e.min)))),r=Math.floor(I(o)),l=Math.floor(o/Math.pow(10,r)),h=r<0?Math.pow(10,Math.abs(r)):1;do{n.push({value:o,major:na(o)}),++l,10===l&&(l=1,++r,h=r>=0?1:h),o=Math.round(l*Math.pow(10,r)*h)/h}while(r<i||r===i&&l<s);const c=a(t.max,o);return n.push({value:c,major:na(o)}),n}({min:this._userMin,max:this._userMax},this);return\"ticks\"===t.bounds&&j(e,this,\"value\"),t.reverse?(e.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),e}getLabelForValue(t){return void 0===t?\"0\":li(t,this.chart.options.locale,this.options.ticks.format)}configure(){const t=this.min;super.configure(),this._startValue=I(t),this._valueRange=I(this.max)-I(t)}getPixelForValue(t){return void 0!==t&&0!==t||(t=this.min),null===t||isNaN(t)?NaN:this.getPixelForDecimal(t===this.min?0:(I(t)-this._startValue)/this._valueRange)}getValueForPixel(t){const e=this.getDecimalForPixel(t);return Math.pow(10,this._startValue+e*this._valueRange)}}function aa(t){const e=t.ticks;if(e.display&&t.display){const t=pi(e.backdropPadding);return r(e.font&&e.font.size,ne.font.size)+t.height}return 0}function ra(t,e,i,s,n){return t===s||t===n?{start:e-i/2,end:e+i/2}:t<s||t>n?{start:e-i,end:e}:{start:e,end:e+i}}function la(t){const e={l:t.left+t._padding.left,r:t.right-t._padding.right,t:t.top+t._padding.top,b:t.bottom-t._padding.bottom},i=Object.assign({},e),n=[],o=[],a=t._pointLabels.length,r=t.options.pointLabels,l=r.centerPointLabels?D/a:0;for(let u=0;u<a;u++){const a=r.setContext(t.getPointLabelContext(u));o[u]=a.padding;const f=t.getPointPosition(u,t.drawingArea+o[u],l),g=mi(a.font),p=(h=t.ctx,c=g,d=s(d=t._pointLabels[u])?d:[d],{w:ye(h,c.string,d),h:d.length*c.lineHeight});n[u]=p;const m=K(t.getIndexAngle(u)+l),b=Math.round($(m));ha(i,e,m,ra(b,f.x,p.w,0,180),ra(b,f.y,p.h,90,270))}var h,c,d;t.setCenterPoint(e.l-i.l,i.r-e.r,e.t-i.t,i.b-e.b),t._pointLabelItems=function(t,e,i){const s=[],n=t._pointLabels.length,o=t.options,a=aa(o)/2,r=t.drawingArea,l=o.pointLabels.centerPointLabels?D/n:0;for(let o=0;o<n;o++){const n=t.getPointPosition(o,r+a+i[o],l),h=Math.round($(K(n.angle+L))),c=e[o],d=ua(n.y,c.h,h),u=ca(h),f=da(n.x,c.w,u);s.push({x:n.x,y:d,textAlign:u,left:f,top:d,right:f+c.w,bottom:d+c.h})}return s}(t,n,o)}function ha(t,e,i,s,n){const o=Math.abs(Math.sin(i)),a=Math.abs(Math.cos(i));let r=0,l=0;s.start<e.l?(r=(e.l-s.start)/o,t.l=Math.min(t.l,e.l-r)):s.end>e.r&&(r=(s.end-e.r)/o,t.r=Math.max(t.r,e.r+r)),n.start<e.t?(l=(e.t-n.start)/a,t.t=Math.min(t.t,e.t-l)):n.end>e.b&&(l=(n.end-e.b)/a,t.b=Math.max(t.b,e.b+l))}function ca(t){return 0===t||180===t?\"center\":t<180?\"left\":\"right\"}function da(t,e,i){return\"right\"===i?t-=e:\"center\"===i&&(t-=e/2),t}function ua(t,e,i){return 90===i||270===i?t-=e/2:(i>270||i<90)&&(t-=e),t}function fa(t,e,i,s){const{ctx:n}=t;if(i)n.arc(t.xCenter,t.yCenter,e,0,O);else{let i=t.getPointPosition(0,e);n.moveTo(i.x,i.y);for(let o=1;o<s;o++)i=t.getPointPosition(o,e),n.lineTo(i.x,i.y)}}oa.id=\"logarithmic\",oa.defaults={ticks:{callback:Is.formatters.logarithmic,major:{enabled:!0}}};class ga extends ia{constructor(t){super(t),this.xCenter=void 0,this.yCenter=void 0,this.drawingArea=void 0,this._pointLabels=[],this._pointLabelItems=[]}setDimensions(){const t=this._padding=pi(aa(this.options)/2),e=this.width=this.maxWidth-t.width,i=this.height=this.maxHeight-t.height;this.xCenter=Math.floor(this.left+e/2+t.left),this.yCenter=Math.floor(this.top+i/2+t.top),this.drawingArea=Math.floor(Math.min(e,i)/2)}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!1);this.min=o(t)&&!isNaN(t)?t:0,this.max=o(e)&&!isNaN(e)?e:0,this.handleTickRangeOptions()}computeTickLimit(){return Math.ceil(this.drawingArea/aa(this.options))}generateTickLabels(t){ia.prototype.generateTickLabels.call(this,t),this._pointLabels=this.getLabels().map(((t,e)=>{const i=c(this.options.pointLabels.callback,[t,e],this);return i||0===i?i:\"\"})).filter(((t,e)=>this.chart.getDataVisibility(e)))}fit(){const t=this.options;t.display&&t.pointLabels.display?la(this):this.setCenterPoint(0,0,0,0)}setCenterPoint(t,e,i,s){this.xCenter+=Math.floor((t-e)/2),this.yCenter+=Math.floor((i-s)/2),this.drawingArea-=Math.min(this.drawingArea/2,Math.max(t,e,i,s))}getIndexAngle(t){return K(t*(O/(this._pointLabels.length||1))+H(this.options.startAngle||0))}getDistanceFromCenterForValue(t){if(i(t))return NaN;const e=this.drawingArea/(this.max-this.min);return this.options.reverse?(this.max-t)*e:(t-this.min)*e}getValueForDistanceFromCenter(t){if(i(t))return NaN;const e=t/(this.drawingArea/(this.max-this.min));return this.options.reverse?this.max-e:this.min+e}getPointLabelContext(t){const e=this._pointLabels||[];if(t>=0&&t<e.length){const i=e[t];return function(t,e,i){return _i(t,{label:i,index:e,type:\"pointLabel\"})}(this.getContext(),t,i)}}getPointPosition(t,e,i=0){const s=this.getIndexAngle(t)-L+i;return{x:Math.cos(s)*e+this.xCenter,y:Math.sin(s)*e+this.yCenter,angle:s}}getPointPositionForValue(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))}getBasePosition(t){return this.getPointPositionForValue(t||0,this.getBaseValue())}getPointLabelPosition(t){const{left:e,top:i,right:s,bottom:n}=this._pointLabelItems[t];return{left:e,top:i,right:s,bottom:n}}drawBackground(){const{backgroundColor:t,grid:{circular:e}}=this.options;if(t){const i=this.ctx;i.save(),i.beginPath(),fa(this,this.getDistanceFromCenterForValue(this._endValue),e,this._pointLabels.length),i.closePath(),i.fillStyle=t,i.fill(),i.restore()}}drawGrid(){const t=this.ctx,e=this.options,{angleLines:s,grid:n}=e,o=this._pointLabels.length;let a,r,l;if(e.pointLabels.display&&function(t,e){const{ctx:s,options:{pointLabels:n}}=t;for(let o=e-1;o>=0;o--){const e=n.setContext(t.getPointLabelContext(o)),a=mi(e.font),{x:r,y:l,textAlign:h,left:c,top:d,right:u,bottom:f}=t._pointLabelItems[o],{backdropColor:g}=e;if(!i(g)){const t=gi(e.borderRadius),i=pi(e.backdropPadding);s.fillStyle=g;const n=c-i.left,o=d-i.top,a=u-c+i.width,r=f-d+i.height;Object.values(t).some((t=>0!==t))?(s.beginPath(),Le(s,{x:n,y:o,w:a,h:r,radius:t}),s.fill()):s.fillRect(n,o,a,r)}Ae(s,t._pointLabels[o],r,l+a.lineHeight/2,a,{color:e.color,textAlign:h,textBaseline:\"middle\"})}}(this,o),n.display&&this.ticks.forEach(((t,e)=>{if(0!==e){r=this.getDistanceFromCenterForValue(t.value);!function(t,e,i,s){const n=t.ctx,o=e.circular,{color:a,lineWidth:r}=e;!o&&!s||!a||!r||i<0||(n.save(),n.strokeStyle=a,n.lineWidth=r,n.setLineDash(e.borderDash),n.lineDashOffset=e.borderDashOffset,n.beginPath(),fa(t,i,o,s),n.closePath(),n.stroke(),n.restore())}(this,n.setContext(this.getContext(e-1)),r,o)}})),s.display){for(t.save(),a=o-1;a>=0;a--){const i=s.setContext(this.getPointLabelContext(a)),{color:n,lineWidth:o}=i;o&&n&&(t.lineWidth=o,t.strokeStyle=n,t.setLineDash(i.borderDash),t.lineDashOffset=i.borderDashOffset,r=this.getDistanceFromCenterForValue(e.ticks.reverse?this.min:this.max),l=this.getPointPosition(a,r),t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(l.x,l.y),t.stroke())}t.restore()}}drawBorder(){}drawLabels(){const t=this.ctx,e=this.options,i=e.ticks;if(!i.display)return;const s=this.getIndexAngle(0);let n,o;t.save(),t.translate(this.xCenter,this.yCenter),t.rotate(s),t.textAlign=\"center\",t.textBaseline=\"middle\",this.ticks.forEach(((s,a)=>{if(0===a&&!e.reverse)return;const r=i.setContext(this.getContext(a)),l=mi(r.font);if(n=this.getDistanceFromCenterForValue(this.ticks[a].value),r.showLabelBackdrop){t.font=l.string,o=t.measureText(s.label).width,t.fillStyle=r.backdropColor;const e=pi(r.backdropPadding);t.fillRect(-o/2-e.left,-n-l.size/2-e.top,o+e.width,l.size+e.height)}Ae(t,s.label,0,-n,l,{color:r.color})})),t.restore()}drawTitle(){}}ga.id=\"radialLinear\",ga.defaults={display:!0,animate:!0,position:\"chartArea\",angleLines:{display:!0,lineWidth:1,borderDash:[],borderDashOffset:0},grid:{circular:!1},startAngle:0,ticks:{showLabelBackdrop:!0,callback:Is.formatters.numeric},pointLabels:{backdropColor:void 0,backdropPadding:2,display:!0,font:{size:10},callback:t=>t,padding:5,centerPointLabels:!1}},ga.defaultRoutes={\"angleLines.color\":\"borderColor\",\"pointLabels.color\":\"color\",\"ticks.color\":\"color\"},ga.descriptors={angleLines:{_fallback:\"grid\"}};const pa={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},ma=Object.keys(pa);function ba(t,e){return t-e}function xa(t,e){if(i(e))return null;const s=t._adapter,{parser:n,round:a,isoWeekday:r}=t._parseOpts;let l=e;return\"function\"==typeof n&&(l=n(l)),o(l)||(l=\"string\"==typeof n?s.parse(l,n):s.parse(l)),null===l?null:(a&&(l=\"week\"!==a||!B(r)&&!0!==r?s.startOf(l,a):s.startOf(l,\"isoWeek\",r)),+l)}function _a(t,e,i,s){const n=ma.length;for(let o=ma.indexOf(t);o<n-1;++o){const t=pa[ma[o]],n=t.steps?t.steps:Number.MAX_SAFE_INTEGER;if(t.common&&Math.ceil((i-e)/(n*t.size))<=s)return ma[o]}return ma[n-1]}function ya(t,e,i){if(i){if(i.length){const{lo:s,hi:n}=tt(i,e);t[i[s]>=e?i[s]:i[n]]=!0}}else t[e]=!0}function va(t,e,i){const s=[],n={},o=e.length;let a,r;for(a=0;a<o;++a)r=e[a],n[r]=a,s.push({value:r,major:!1});return 0!==o&&i?function(t,e,i,s){const n=t._adapter,o=+n.startOf(e[0].value,s),a=e[e.length-1].value;let r,l;for(r=o;r<=a;r=+n.add(r,1,s))l=i[r],l>=0&&(e[l].major=!0);return e}(t,s,n,i):s}class wa extends $s{constructor(t){super(t),this._cache={data:[],labels:[],all:[]},this._unit=\"day\",this._majorUnit=void 0,this._offsets={},this._normalized=!1,this._parseOpts=void 0}init(t,e){const i=t.time||(t.time={}),s=this._adapter=new wn._date(t.adapters.date);s.init(e),b(i.displayFormats,s.formats()),this._parseOpts={parser:i.parser,round:i.round,isoWeekday:i.isoWeekday},super.init(t),this._normalized=e.normalized}parse(t,e){return void 0===t?null:xa(this,t)}beforeLayout(){super.beforeLayout(),this._cache={data:[],labels:[],all:[]}}determineDataLimits(){const t=this.options,e=this._adapter,i=t.time.unit||\"day\";let{min:s,max:n,minDefined:a,maxDefined:r}=this.getUserBounds();function l(t){a||isNaN(t.min)||(s=Math.min(s,t.min)),r||isNaN(t.max)||(n=Math.max(n,t.max))}a&&r||(l(this._getLabelBounds()),\"ticks\"===t.bounds&&\"labels\"===t.ticks.source||l(this.getMinMax(!1))),s=o(s)&&!isNaN(s)?s:+e.startOf(Date.now(),i),n=o(n)&&!isNaN(n)?n:+e.endOf(Date.now(),i)+1,this.min=Math.min(s,n-1),this.max=Math.max(s+1,n)}_getLabelBounds(){const t=this.getLabelTimestamps();let e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;return t.length&&(e=t[0],i=t[t.length-1]),{min:e,max:i}}buildTicks(){const t=this.options,e=t.time,i=t.ticks,s=\"labels\"===i.source?this.getLabelTimestamps():this._generate();\"ticks\"===t.bounds&&s.length&&(this.min=this._userMin||s[0],this.max=this._userMax||s[s.length-1]);const n=this.min,o=st(s,n,this.max);return this._unit=e.unit||(i.autoSkip?_a(e.minUnit,this.min,this.max,this._getLabelCapacity(n)):function(t,e,i,s,n){for(let o=ma.length-1;o>=ma.indexOf(i);o--){const i=ma[o];if(pa[i].common&&t._adapter.diff(n,s,i)>=e-1)return i}return ma[i?ma.indexOf(i):0]}(this,o.length,e.minUnit,this.min,this.max)),this._majorUnit=i.major.enabled&&\"year\"!==this._unit?function(t){for(let e=ma.indexOf(t)+1,i=ma.length;e<i;++e)if(pa[ma[e]].common)return ma[e]}(this._unit):void 0,this.initOffsets(s),t.reverse&&o.reverse(),va(this,o,this._majorUnit)}afterAutoSkip(){this.options.offsetAfterAutoskip&&this.initOffsets(this.ticks.map((t=>+t.value)))}initOffsets(t){let e,i,s=0,n=0;this.options.offset&&t.length&&(e=this.getDecimalForValue(t[0]),s=1===t.length?1-e:(this.getDecimalForValue(t[1])-e)/2,i=this.getDecimalForValue(t[t.length-1]),n=1===t.length?i:(i-this.getDecimalForValue(t[t.length-2]))/2);const o=t.length<3?.5:.25;s=Z(s,0,o),n=Z(n,0,o),this._offsets={start:s,end:n,factor:1/(s+1+n)}}_generate(){const t=this._adapter,e=this.min,i=this.max,s=this.options,n=s.time,o=n.unit||_a(n.minUnit,e,i,this._getLabelCapacity(e)),a=r(n.stepSize,1),l=\"week\"===o&&n.isoWeekday,h=B(l)||!0===l,c={};let d,u,f=e;if(h&&(f=+t.startOf(f,\"isoWeek\",l)),f=+t.startOf(f,h?\"day\":o),t.diff(i,e,o)>1e5*a)throw new Error(e+\" and \"+i+\" are too far apart with stepSize of \"+a+\" \"+o);const g=\"data\"===s.ticks.source&&this.getDataTimestamps();for(d=f,u=0;d<i;d=+t.add(d,a,o),u++)ya(c,d,g);return d!==i&&\"ticks\"!==s.bounds&&1!==u||ya(c,d,g),Object.keys(c).sort(((t,e)=>t-e)).map((t=>+t))}getLabelForValue(t){const e=this._adapter,i=this.options.time;return i.tooltipFormat?e.format(t,i.tooltipFormat):e.format(t,i.displayFormats.datetime)}_tickFormatFunction(t,e,i,s){const n=this.options,o=n.time.displayFormats,a=this._unit,r=this._majorUnit,l=a&&o[a],h=r&&o[r],d=i[e],u=r&&h&&d&&d.major,f=this._adapter.format(t,s||(u?h:l)),g=n.ticks.callback;return g?c(g,[f,e,i],this):f}generateTickLabels(t){let e,i,s;for(e=0,i=t.length;e<i;++e)s=t[e],s.label=this._tickFormatFunction(s.value,e,t)}getDecimalForValue(t){return null===t?NaN:(t-this.min)/(this.max-this.min)}getPixelForValue(t){const e=this._offsets,i=this.getDecimalForValue(t);return this.getPixelForDecimal((e.start+i)*e.factor)}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return this.min+i*(this.max-this.min)}_getLabelSize(t){const e=this.options.ticks,i=this.ctx.measureText(t).width,s=H(this.isHorizontal()?e.maxRotation:e.minRotation),n=Math.cos(s),o=Math.sin(s),a=this._resolveTickFontOptions(0).size;return{w:i*n+a*o,h:i*o+a*n}}_getLabelCapacity(t){const e=this.options.time,i=e.displayFormats,s=i[e.unit]||i.millisecond,n=this._tickFormatFunction(t,0,va(this,[t],this._majorUnit),s),o=this._getLabelSize(n),a=Math.floor(this.isHorizontal()?this.width/o.w:this.height/o.h)-1;return a>0?a:1}getDataTimestamps(){let t,e,i=this._cache.data||[];if(i.length)return i;const s=this.getMatchingVisibleMetas();if(this._normalized&&s.length)return this._cache.data=s[0].controller.getAllParsedValues(this);for(t=0,e=s.length;t<e;++t)i=i.concat(s[t].controller.getAllParsedValues(this));return this._cache.data=this.normalize(i)}getLabelTimestamps(){const t=this._cache.labels||[];let e,i;if(t.length)return t;const s=this.getLabels();for(e=0,i=s.length;e<i;++e)t.push(xa(this,s[e]));return this._cache.labels=this._normalized?t:this.normalize(t)}normalize(t){return rt(t.sort(ba))}}function Ma(t,e,i){let s,n,o,a,r=0,l=t.length-1;i?(e>=t[r].pos&&e<=t[l].pos&&({lo:r,hi:l}=et(t,\"pos\",e)),({pos:s,time:o}=t[r]),({pos:n,time:a}=t[l])):(e>=t[r].time&&e<=t[l].time&&({lo:r,hi:l}=et(t,\"time\",e)),({time:s,pos:o}=t[r]),({time:n,pos:a}=t[l]));const h=n-s;return h?o+(a-o)*(e-s)/h:o}wa.id=\"time\",wa.defaults={bounds:\"data\",adapters:{},time:{parser:!1,unit:!1,round:!1,isoWeekday:!1,minUnit:\"millisecond\",displayFormats:{}},ticks:{source:\"auto\",major:{enabled:!1}}};class ka extends wa{constructor(t){super(t),this._table=[],this._minPos=void 0,this._tableRange=void 0}initOffsets(){const t=this._getTimestampsForTable(),e=this._table=this.buildLookupTable(t);this._minPos=Ma(e,this.min),this._tableRange=Ma(e,this.max)-this._minPos,super.initOffsets(t)}buildLookupTable(t){const{min:e,max:i}=this,s=[],n=[];let o,a,r,l,h;for(o=0,a=t.length;o<a;++o)l=t[o],l>=e&&l<=i&&s.push(l);if(s.length<2)return[{time:e,pos:0},{time:i,pos:1}];for(o=0,a=s.length;o<a;++o)h=s[o+1],r=s[o-1],l=s[o],Math.round((h+r)/2)!==l&&n.push({time:l,pos:o/(a-1)});return n}_getTimestampsForTable(){let t=this._cache.all||[];if(t.length)return t;const e=this.getDataTimestamps(),i=this.getLabelTimestamps();return t=e.length&&i.length?this.normalize(e.concat(i)):e.length?e:i,t=this._cache.all=t,t}getDecimalForValue(t){return(Ma(this._table,t)-this._minPos)/this._tableRange}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return Ma(this._table,i*this._tableRange+this._minPos,!0)}}ka.id=\"timeseries\",ka.defaults=wa.defaults;var Sa=Object.freeze({__proto__:null,CategoryScale:ta,LinearScale:sa,LogarithmicScale:oa,RadialLinearScale:ga,TimeScale:wa,TimeSeriesScale:ka});return bn.register(Bn,Sa,co,Jo),bn.helpers={...Ti},bn._adapters=wn,bn.Animation=xs,bn.Animations=ys,bn.animator=mt,bn.controllers=Us.controllers.items,bn.DatasetController=Ls,bn.Element=Es,bn.elements=co,bn.Interaction=Vi,bn.layouts=Zi,bn.platforms=ps,bn.Scale=$s,bn.Ticks=Is,Object.assign(bn,Bn,Sa,co,Jo,ps),bn.Chart=bn,\"undefined\"!=typeof window&&(window.Chart=bn),bn}));\n","chartjs/es6-shim.min.js":"/*!\n  * https://github.com/paulmillr/es6-shim\n  * @license es6-shim Copyright 2013-2014 by Paul Miller (http://paulmillr.com)\n  *   and contributors,  MIT License\n  * es6-shim: v0.25.0\n  * see https://github.com/paulmillr/es6-shim/blob/0.25.0/LICENSE\n  * Details and documentation:\n  * https://github.com/paulmillr/es6-shim/\n  */\n(function(e,t){if(typeof define===\"function\"&&define.amd){define(t)}else if(typeof exports===\"object\"){module.exports=t()}else{e.returnExports=t()}})(this,function(){\"use strict\";var e=function(e){try{e()}catch(t){return false}return true};var t=function(e,t){try{var r=function(){e.apply(this,arguments)};if(!r.__proto__){return false}Object.setPrototypeOf(r,e);r.prototype=Object.create(e.prototype,{constructor:{value:e}});return t(r)}catch(n){return false}};var r=function(){try{Object.defineProperty({},\"x\",{});return true}catch(e){return false}};var n=function(){var e=false;if(String.prototype.startsWith){try{\"/a/\".startsWith(/a/)}catch(t){e=true}}return e};var i=new Function(\"return this;\");var o=i();var a=o.isFinite;var u=!!Object.defineProperty&&r();var s=n();var f=Function.call.bind(String.prototype.indexOf);var c=Function.call.bind(Object.prototype.toString);var l=Function.call.bind(Object.prototype.hasOwnProperty);var p;var h=function(){};var v=o.Symbol||{};var y=v.species||\"@@species\";var b={string:function(e){return c(e)===\"[object String]\"},regex:function(e){return c(e)===\"[object RegExp]\"},symbol:function(e){return typeof o.Symbol===\"function\"&&typeof e===\"symbol\"}};var g=function(e,t,r,n){if(!n&&t in e){return}if(u){Object.defineProperty(e,t,{configurable:true,enumerable:false,writable:true,value:r})}else{e[t]=r}};var d={getter:function(e,t,r){if(!u){throw new TypeError(\"getters require true ES5 support\")}Object.defineProperty(e,t,{configurable:true,enumerable:false,get:r})},proxy:function(e,t,r){if(!u){throw new TypeError(\"getters require true ES5 support\")}var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,{configurable:n.configurable,enumerable:n.enumerable,get:function i(){return e[t]},set:function o(r){e[t]=r}})},redefine:function(e,t,r){if(u){var n=Object.getOwnPropertyDescriptor(e,t);n.value=r;Object.defineProperty(e,t,n)}else{e[t]=r}}};var m=function(e,t){Object.keys(t).forEach(function(r){var n=t[r];g(e,r,n,false)})};var w=Object.create||function(e,t){function r(){}r.prototype=e;var n=new r;if(typeof t!==\"undefined\"){m(n,t)}return n};var O=b.symbol(v.iterator)?v.iterator:\"_es6-shim iterator_\";if(o.Set&&typeof(new o.Set)[\"@@iterator\"]===\"function\"){O=\"@@iterator\"}var j=function(e,t){if(!t){t=function n(){return this}}var r={};r[O]=t;m(e,r);if(!e[O]&&b.symbol(O)){e[O]=t}};var I=function dt(e){var t=c(e);var r=t===\"[object Arguments]\";if(!r){r=t!==\"[object Array]\"&&e!==null&&typeof e===\"object\"&&typeof e.length===\"number\"&&e.length>=0&&c(e.callee)===\"[object Function]\"}return r};var T=Function.call.bind(Function.apply);var M={Call:function mt(e,t){var r=arguments.length>2?arguments[2]:[];if(!M.IsCallable(e)){throw new TypeError(e+\" is not a function\")}return T(e,t,r)},RequireObjectCoercible:function(e,t){if(e==null){throw new TypeError(t||\"Cannot call method on \"+e)}},TypeIsObject:function(e){return e!=null&&Object(e)===e},ToObject:function(e,t){M.RequireObjectCoercible(e,t);return Object(e)},IsCallable:function(e){return typeof e===\"function\"&&c(e)===\"[object Function]\"},ToInt32:function(e){return M.ToNumber(e)>>0},ToUint32:function(e){return M.ToNumber(e)>>>0},ToNumber:function(e){if(c(e)===\"[object Symbol]\"){throw new TypeError(\"Cannot convert a Symbol value to a number\")}return+e},ToInteger:function(e){var t=M.ToNumber(e);if(Number.isNaN(t)){return 0}if(t===0||!Number.isFinite(t)){return t}return(t>0?1:-1)*Math.floor(Math.abs(t))},ToLength:function(e){var t=M.ToInteger(e);if(t<=0){return 0}if(t>Number.MAX_SAFE_INTEGER){return Number.MAX_SAFE_INTEGER}return t},SameValue:function(e,t){if(e===t){if(e===0){return 1/e===1/t}return true}return Number.isNaN(e)&&Number.isNaN(t)},SameValueZero:function(e,t){return e===t||Number.isNaN(e)&&Number.isNaN(t)},IsIterable:function(e){return M.TypeIsObject(e)&&(typeof e[O]!==\"undefined\"||I(e))},GetIterator:function(e){if(I(e)){return new p(e,\"value\")}var t=e[O];if(!M.IsCallable(t)){throw new TypeError(\"value is not an iterable\")}var r=t.call(e);if(!M.TypeIsObject(r)){throw new TypeError(\"bad iterator\")}return r},IteratorNext:function(e){var t=arguments.length>1?e.next(arguments[1]):e.next();if(!M.TypeIsObject(t)){throw new TypeError(\"bad iterator\")}return t},Construct:function(e,t){var r;if(M.IsCallable(e[y])){r=e[y]()}else{r=w(e.prototype||null)}m(r,{_es6construct:true});var n=M.Call(e,r,t);return M.TypeIsObject(n)?n:r}};var N=function(e){if(!M.TypeIsObject(e)){throw new TypeError(\"bad object\")}if(!e._es6construct){if(e.constructor&&M.IsCallable(e.constructor[y])){e=e.constructor[y](e)}m(e,{_es6construct:true})}return e};var _=function(){function e(e){var t=Math.floor(e),r=e-t;if(r<.5){return t}if(r>.5){return t+1}return t%2?t+1:t}function t(t,r,n){var i=(1<<r-1)-1,o,a,u,s,f,c,l;if(t!==t){a=(1<<r)-1;u=Math.pow(2,n-1);o=0}else if(t===Infinity||t===-Infinity){a=(1<<r)-1;u=0;o=t<0?1:0}else if(t===0){a=0;u=0;o=1/t===-Infinity?1:0}else{o=t<0;t=Math.abs(t);if(t>=Math.pow(2,1-i)){a=Math.min(Math.floor(Math.log(t)/Math.LN2),1023);u=e(t/Math.pow(2,a)*Math.pow(2,n));if(u/Math.pow(2,n)>=2){a=a+1;u=1}if(a>i){a=(1<<r)-1;u=0}else{a=a+i;u=u-Math.pow(2,n)}}else{a=0;u=e(t/Math.pow(2,1-i-n))}}f=[];for(s=n;s;s-=1){f.push(u%2?1:0);u=Math.floor(u/2)}for(s=r;s;s-=1){f.push(a%2?1:0);a=Math.floor(a/2)}f.push(o?1:0);f.reverse();c=f.join(\"\");l=[];while(c.length){l.push(parseInt(c.slice(0,8),2));c=c.slice(8)}return l}function r(e,t,r){var n=[],i,o,a,u,s,f,c,l;for(i=e.length;i;i-=1){a=e[i-1];for(o=8;o;o-=1){n.push(a%2?1:0);a=a>>1}}n.reverse();u=n.join(\"\");s=(1<<t-1)-1;f=parseInt(u.slice(0,1),2)?-1:1;c=parseInt(u.slice(1,1+t),2);l=parseInt(u.slice(1+t),2);if(c===(1<<t)-1){return l!==0?NaN:f*Infinity}else if(c>0){return f*Math.pow(2,c-s)*(1+l/Math.pow(2,r))}else if(l!==0){return f*Math.pow(2,-(s-1))*(l/Math.pow(2,r))}else{return f<0?-0:0}}function n(e){return r(e,11,52)}function i(e){return t(e,11,52)}function o(e){return r(e,8,23)}function a(e){return t(e,8,23)}var u={toFloat32:function(e){return o(a(e))}};if(typeof Float32Array!==\"undefined\"){var s=new Float32Array(1);u.toFloat32=function(e){s[0]=e;return s[0]}}return u}();m(String,{fromCodePoint:function wt(e){var t=[];var r;for(var n=0,i=arguments.length;n<i;n++){r=Number(arguments[n]);if(!M.SameValue(r,M.ToInteger(r))||r<0||r>1114111){throw new RangeError(\"Invalid code point \"+r)}if(r<65536){t.push(String.fromCharCode(r))}else{r-=65536;t.push(String.fromCharCode((r>>10)+55296));t.push(String.fromCharCode(r%1024+56320))}}return t.join(\"\")},raw:function Ot(e){var t=M.ToObject(e,\"bad callSite\");var r=t.raw;var n=M.ToObject(r,\"bad raw value\");var i=n.length;var o=M.ToLength(i);if(o<=0){return\"\"}var a=[];var u=0;var s,f,c,l;while(u<o){s=String(u);f=n[s];c=String(f);a.push(c);if(u+1>=o){break}f=u+1<arguments.length?arguments[u+1]:\"\";l=String(f);a.push(l);u++}return a.join(\"\")}});if(String.fromCodePoint.length!==1){var E=Function.apply.bind(String.fromCodePoint);g(String,\"fromCodePoint\",function jt(e){return E(this,arguments)},true)}var x=function It(e,t){if(t<1){return\"\"}if(t%2){return It(e,t-1)+e}var r=It(e,t/2);return r+r};var S=Infinity;var P={repeat:function Tt(e){M.RequireObjectCoercible(this);var t=String(this);e=M.ToInteger(e);if(e<0||e>=S){throw new RangeError(\"repeat count must be less than infinity and not overflow maximum string size\")}return x(t,e)},startsWith:function(e){M.RequireObjectCoercible(this);var t=String(this);if(b.regex(e)){throw new TypeError('Cannot call method \"startsWith\" with a regex')}e=String(e);var r=arguments.length>1?arguments[1]:void 0;var n=Math.max(M.ToInteger(r),0);return t.slice(n,n+e.length)===e},endsWith:function(e){M.RequireObjectCoercible(this);var t=String(this);if(b.regex(e)){throw new TypeError('Cannot call method \"endsWith\" with a regex')}e=String(e);var r=t.length;var n=arguments.length>1?arguments[1]:void 0;var i=typeof n===\"undefined\"?r:M.ToInteger(n);var o=Math.min(Math.max(i,0),r);return t.slice(o-e.length,o)===e},includes:function Mt(e){var t=arguments.length>1?arguments[1]:void 0;return f(this,e,t)!==-1},codePointAt:function(e){M.RequireObjectCoercible(this);var t=String(this);var r=M.ToInteger(e);var n=t.length;if(r>=0&&r<n){var i=t.charCodeAt(r);var o=r+1===n;if(i<55296||i>56319||o){return i}var a=t.charCodeAt(r+1);if(a<56320||a>57343){return i}return(i-55296)*1024+(a-56320)+65536}}};m(String.prototype,P);var C=\"\\x85\".trim().length!==1;if(C){delete String.prototype.trim;var k=[\"\t\\n\u000b\\f\\r \\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\",\"\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\",\"\\u2029\\ufeff\"].join(\"\");var A=new RegExp(\"(^[\"+k+\"]+)|([\"+k+\"]+$)\",\"g\");m(String.prototype,{trim:function(){if(typeof this===\"undefined\"||this===null){throw new TypeError(\"can't convert \"+this+\" to object\")}return String(this).replace(A,\"\")}})}var R=function(e){M.RequireObjectCoercible(e);this._s=String(e);this._i=0};R.prototype.next=function(){var e=this._s,t=this._i;if(typeof e===\"undefined\"||t>=e.length){this._s=void 0;return{value:void 0,done:true}}var r=e.charCodeAt(t),n,i;if(r<55296||r>56319||t+1===e.length){i=1}else{n=e.charCodeAt(t+1);i=n<56320||n>57343?1:2}this._i=t+i;return{value:e.substr(t,i),done:false}};j(R.prototype);j(String.prototype,function(){return new R(this)});if(!s){g(String.prototype,\"startsWith\",P.startsWith,true);g(String.prototype,\"endsWith\",P.endsWith,true)}var F={from:function(e){var t=arguments.length>1?arguments[1]:void 0;var r=M.ToObject(e,\"bad iterable\");if(typeof t!==\"undefined\"&&!M.IsCallable(t)){throw new TypeError(\"Array.from: when provided, the second argument must be a function\")}var n=arguments.length>2;var i=n?arguments[2]:void 0;var o=M.IsIterable(r);var a;var u,s,f;if(o){s=0;u=M.IsCallable(this)?Object(new this):[];var c=o?M.GetIterator(r):null;var l;do{l=M.IteratorNext(c);if(!l.done){f=l.value;if(t){u[s]=n?t.call(i,f,s):t(f,s)}else{u[s]=f}s+=1}}while(!l.done);a=s}else{a=M.ToLength(r.length);u=M.IsCallable(this)?Object(new this(a)):new Array(a);for(s=0;s<a;++s){f=r[s];if(t){u[s]=n?t.call(i,f,s):t(f,s)}else{u[s]=f}}}u.length=a;return u},of:function(){return Array.from(arguments)}};m(Array,F);var D=function(){try{return Array.from({length:-1}).length===0}catch(e){return false}};if(!D()){g(Array,\"from\",F.from,true)}var z=function(e){return{value:e,done:arguments.length===0}};p=function(e,t){this.i=0;this.array=e;this.kind=t};m(p.prototype,{next:function(){var e=this.i,t=this.array;if(!(this instanceof p)){throw new TypeError(\"Not an ArrayIterator\")}if(typeof t!==\"undefined\"){var r=M.ToLength(t.length);for(;e<r;e++){var n=this.kind;var i;if(n===\"key\"){i=e}else if(n===\"value\"){i=t[e]}else if(n===\"entry\"){i=[e,t[e]]}this.i=e+1;return{value:i,done:false}}}this.array=void 0;return{value:void 0,done:true}}});j(p.prototype);var L=function(e,t){this.object=e;this.array=null;this.kind=t};function q(e){var t=[];for(var r in e){t.push(r)}return t}m(L.prototype,{next:function(){var e,t=this.array;if(!(this instanceof L)){throw new TypeError(\"Not an ObjectIterator\")}if(t===null){t=this.array=q(this.object)}while(M.ToLength(t.length)>0){e=t.shift();if(!(e in this.object)){continue}if(this.kind===\"key\"){return z(e)}else if(this.kind===\"value\"){return z(this.object[e])}else{return z([e,this.object[e]])}}return z()}});j(L.prototype);var G={copyWithin:function(e,t){var r=arguments[2];var n=M.ToObject(this);var i=M.ToLength(n.length);e=M.ToInteger(e);t=M.ToInteger(t);var o=e<0?Math.max(i+e,0):Math.min(e,i);var a=t<0?Math.max(i+t,0):Math.min(t,i);r=typeof r===\"undefined\"?i:M.ToInteger(r);var u=r<0?Math.max(i+r,0):Math.min(r,i);var s=Math.min(u-a,i-o);var f=1;if(a<o&&o<a+s){f=-1;a+=s-1;o+=s-1}while(s>0){if(l(n,a)){n[o]=n[a]}else{delete n[a]}a+=f;o+=f;s-=1}return n},fill:function(e){var t=arguments.length>1?arguments[1]:void 0;var r=arguments.length>2?arguments[2]:void 0;var n=M.ToObject(this);var i=M.ToLength(n.length);t=M.ToInteger(typeof t===\"undefined\"?0:t);r=M.ToInteger(typeof r===\"undefined\"?i:r);var o=t<0?Math.max(i+t,0):Math.min(t,i);var a=r<0?i+r:r;for(var u=o;u<i&&u<a;++u){n[u]=e}return n},find:function Nt(e){var t=M.ToObject(this);var r=M.ToLength(t.length);if(!M.IsCallable(e)){throw new TypeError(\"Array#find: predicate must be a function\")}var n=arguments.length>1?arguments[1]:null;for(var i=0,o;i<r;i++){o=t[i];if(n){if(e.call(n,o,i,t)){return o}}else if(e(o,i,t)){return o}}},findIndex:function _t(e){var t=M.ToObject(this);var r=M.ToLength(t.length);if(!M.IsCallable(e)){throw new TypeError(\"Array#findIndex: predicate must be a function\")}var n=arguments.length>1?arguments[1]:null;for(var i=0;i<r;i++){if(n){if(e.call(n,t[i],i,t)){return i}}else if(e(t[i],i,t)){return i}}return-1},keys:function(){return new p(this,\"key\")},values:function(){return new p(this,\"value\")},entries:function(){return new p(this,\"entry\")}};if(Array.prototype.keys&&!M.IsCallable([1].keys().next)){delete Array.prototype.keys}if(Array.prototype.entries&&!M.IsCallable([1].entries().next)){delete Array.prototype.entries}if(Array.prototype.keys&&Array.prototype.entries&&!Array.prototype.values&&Array.prototype[O]){m(Array.prototype,{values:Array.prototype[O]});if(b.symbol(v.unscopables)){Array.prototype[v.unscopables].values=true}}m(Array.prototype,G);j(Array.prototype,function(){return this.values()});if(Object.getPrototypeOf){j(Object.getPrototypeOf([].values()))}var W=Math.pow(2,53)-1;m(Number,{MAX_SAFE_INTEGER:W,MIN_SAFE_INTEGER:-W,EPSILON:2.220446049250313e-16,parseInt:o.parseInt,parseFloat:o.parseFloat,isFinite:function(e){return typeof e===\"number\"&&a(e)},isInteger:function(e){return Number.isFinite(e)&&M.ToInteger(e)===e},isSafeInteger:function(e){return Number.isInteger(e)&&Math.abs(e)<=Number.MAX_SAFE_INTEGER},isNaN:function(e){return e!==e}});if(![,1].find(function(e,t){return t===0})){g(Array.prototype,\"find\",G.find,true)}if([,1].findIndex(function(e,t){return t===0})!==0){g(Array.prototype,\"findIndex\",G.findIndex,true)}if(u){m(Object,{assign:function(e,t){if(!M.TypeIsObject(e)){throw new TypeError(\"target must be an object\")}return Array.prototype.reduce.call(arguments,function(e,t){return Object.keys(Object(t)).reduce(function(e,r){e[r]=t[r];return e},e)})},is:function(e,t){return M.SameValue(e,t)},setPrototypeOf:function(e,t){var r;var n=function(e,t){if(!M.TypeIsObject(e)){throw new TypeError(\"cannot set prototype on a non-object\")}if(!(t===null||M.TypeIsObject(t))){throw new TypeError(\"can only set prototype to an object or null\"+t)}};var i=function(e,t){n(e,t);r.call(e,t);return e};try{r=e.getOwnPropertyDescriptor(e.prototype,t).set;r.call({},null)}catch(o){if(e.prototype!=={}[t]){return}r=function(e){this[t]=e};i.polyfill=i(i({},null),e.prototype)instanceof e}return i}(Object,\"__proto__\")})}if(Object.setPrototypeOf&&Object.getPrototypeOf&&Object.getPrototypeOf(Object.setPrototypeOf({},null))!==null&&Object.getPrototypeOf(Object.create(null))===null){(function(){var e=Object.create(null);var t=Object.getPrototypeOf,r=Object.setPrototypeOf;Object.getPrototypeOf=function(r){var n=t(r);return n===e?null:n};Object.setPrototypeOf=function(t,n){if(n===null){n=e}return r(t,n)};Object.setPrototypeOf.polyfill=false})()}var V=function(){try{Object.keys(\"foo\");return true}catch(e){return false}}();if(!V){var U=Object.keys;g(Object,\"keys\",function Et(e){return U(M.ToObject(e))},true)}if(Object.getOwnPropertyNames){var X=function(){try{Object.getOwnPropertyNames(\"foo\");return true}catch(e){return false}}();if(!X){var Z=Object.getOwnPropertyNames;g(Object,\"getOwnPropertyNames\",function xt(e){return Z(M.ToObject(e))},true)}}if(!RegExp.prototype.flags&&u){var $=function St(){if(!M.TypeIsObject(this)){throw new TypeError(\"Method called on incompatible type: must be an object.\")}var e=\"\";if(this.global){e+=\"g\"}if(this.ignoreCase){e+=\"i\"}if(this.multiline){e+=\"m\"}if(this.unicode){e+=\"u\"}if(this.sticky){e+=\"y\"}return e};d.getter(RegExp.prototype,\"flags\",$)}var K=function(){try{return String(new RegExp(/a/g,\"i\"))===\"/a/i\"}catch(e){return false}}();if(!K&&u){var B=RegExp;var H=function Pt(e,t){if(b.regex(e)&&b.string(t)){return new Pt(e.source,t)}return new B(e,t)};g(H,\"toString\",B.toString.bind(B),true);if(Object.setPrototypeOf){Object.setPrototypeOf(B,H)}Object.getOwnPropertyNames(B).forEach(function(e){if(e===\"$input\"){return}if(e in h){return}d.proxy(B,e,H)});H.prototype=B.prototype;d.redefine(B.prototype,\"constructor\",H);RegExp=H;d.redefine(o,\"RegExp\",H)}var J={acosh:function(e){var t=Number(e);if(Number.isNaN(t)||e<1){return NaN}if(t===1){return 0}if(t===Infinity){return t}return Math.log(t/Math.E+Math.sqrt(t+1)*Math.sqrt(t-1)/Math.E)+1},asinh:function(e){e=Number(e);if(e===0||!a(e)){return e}return e<0?-Math.asinh(-e):Math.log(e+Math.sqrt(e*e+1))},atanh:function(e){e=Number(e);if(Number.isNaN(e)||e<-1||e>1){return NaN}if(e===-1){return-Infinity}if(e===1){return Infinity}if(e===0){return e}return.5*Math.log((1+e)/(1-e))},cbrt:function(e){e=Number(e);if(e===0){return e}var t=e<0,r;if(t){e=-e}r=Math.pow(e,1/3);return t?-r:r},clz32:function(e){e=Number(e);var t=M.ToUint32(e);if(t===0){return 32}return 32-t.toString(2).length},cosh:function(e){e=Number(e);if(e===0){return 1}if(Number.isNaN(e)){return NaN}if(!a(e)){return Infinity}if(e<0){e=-e}if(e>21){return Math.exp(e)/2}return(Math.exp(e)+Math.exp(-e))/2},expm1:function(e){var t=Number(e);if(t===-Infinity){return-1}if(!a(t)||e===0){return t}if(Math.abs(t)>.5){return Math.exp(t)-1}var r=t;var n=0;var i=1;while(n+r!==n){n+=r;i+=1;r*=t/i}return n},hypot:function(e,t){var r=false;var n=true;var i=false;var o=[];Array.prototype.every.call(arguments,function(e){var t=Number(e);if(Number.isNaN(t)){r=true}else if(t===Infinity||t===-Infinity){i=true}else if(t!==0){n=false}if(i){return false}else if(!r){o.push(Math.abs(t))}return true});if(i){return Infinity}if(r){return NaN}if(n){return 0}o.sort(function(e,t){return t-e});var a=o[0];var u=o.map(function(e){return e/a});var s=u.reduce(function(e,t){return e+t*t},0);return a*Math.sqrt(s)},log2:function(e){return Math.log(e)*Math.LOG2E},log10:function(e){return Math.log(e)*Math.LOG10E},log1p:function(e){var t=Number(e);if(t<-1||Number.isNaN(t)){return NaN}if(t===0||t===Infinity){return t}if(t===-1){return-Infinity}return 1+t-1===0?t:t*(Math.log(1+t)/(1+t-1))},sign:function(e){var t=+e;if(t===0){return t}if(Number.isNaN(t)){return t}return t<0?-1:1},sinh:function(e){var t=Number(e);if(!a(e)||e===0){return e}if(Math.abs(t)<1){return(Math.expm1(t)-Math.expm1(-t))/2}return(Math.exp(t-1)-Math.exp(-t-1))*Math.E/2},tanh:function(e){var t=Number(e);if(Number.isNaN(e)||t===0){return t}if(t===Infinity){return 1}if(t===-Infinity){return-1}var r=Math.expm1(t);var n=Math.expm1(-t);if(r===Infinity){return 1}if(n===Infinity){return-1}return(r-n)/(Math.exp(t)+Math.exp(-t))},trunc:function(e){var t=Number(e);return t<0?-Math.floor(-t):Math.floor(t)},imul:function(e,t){e=M.ToUint32(e);t=M.ToUint32(t);var r=e>>>16&65535;var n=e&65535;var i=t>>>16&65535;var o=t&65535;return n*o+(r*o+n*i<<16>>>0)|0},fround:function(e){if(e===0||e===Infinity||e===-Infinity||Number.isNaN(e)){return e}var t=Number(e);return _.toFloat32(t)}};m(Math,J);g(Math,\"tanh\",J.tanh,Math.tanh(-2e-17)!==-2e-17);g(Math,\"acosh\",J.acosh,Math.acosh(Number.MAX_VALUE)===Infinity);g(Math,\"sinh\",J.sinh,Math.sinh(-2e-17)!==-2e-17);var Q=Math.expm1(10);g(Math,\"expm1\",J.expm1,Q>22025.465794806718||Q<22025.465794806718);var Y=Math.round(.5-Number.EPSILON/4)===0&&Math.round(-.5+Number.EPSILON/3.99)===1;var et=Math.round;g(Math,\"round\",function Ct(e){if(-.5<=e&&e<.5&&e!==0){return Math.sign(e*0)}return et(e)},!Y);if(Math.imul(4294967295,5)!==-5){Math.imul=J.imul}var tt=function(){var e,t;M.IsPromise=function(e){if(!M.TypeIsObject(e)){return false}if(!e._promiseConstructor){return false}if(typeof e._status===\"undefined\"){return false}return true};var r=function(e){if(!M.IsCallable(e)){throw new TypeError(\"bad promise constructor\")}var t=this;var r=function(e,r){t.resolve=e;t.reject=r};t.promise=M.Construct(e,[r]);if(!t.promise._es6construct){throw new TypeError(\"bad promise constructor\")}if(!(M.IsCallable(t.resolve)&&M.IsCallable(t.reject))){throw new TypeError(\"bad promise constructor\")}};var n=o.setTimeout;var i;if(typeof window!==\"undefined\"&&M.IsCallable(window.postMessage)){i=function(){var e=[];var t=\"zero-timeout-message\";var r=function(r){e.push(r);window.postMessage(t,\"*\")};var n=function(r){if(r.source===window&&r.data===t){r.stopPropagation();if(e.length===0){return}var n=e.shift();n()}};window.addEventListener(\"message\",n,true);return r}}var a=function(){var e=o.Promise;return e&&e.resolve&&function(t){return e.resolve().then(t)}};var u=M.IsCallable(o.setImmediate)?o.setImmediate.bind(o):typeof process===\"object\"&&process.nextTick?process.nextTick:a()||(M.IsCallable(i)?i():function(e){n(e,0)});var s=function(e,t){if(!M.TypeIsObject(e)){return false}var r=t.resolve;var n=t.reject;try{var i=e.then;if(!M.IsCallable(i)){return false}i.call(e,r,n)}catch(o){n(o)}return true};var f=function(e,t){e.forEach(function(e){u(function(){var r=e.handler;var n=e.capability;var i=n.resolve;var o=n.reject;try{var a=r(t);if(a===n.promise){throw new TypeError(\"self resolution\")}var u=s(a,n);if(!u){i(a)}}catch(f){o(f)}})})};var c=function(e,t,n){return function(i){if(i===e){return n(new TypeError(\"self resolution\"))}var o=e._promiseConstructor;var a=new r(o);var u=s(i,a);if(u){return a.promise.then(t,n)}else{return t(i)}}};e=function(e){var t=this;t=N(t);if(!t._promiseConstructor){throw new TypeError(\"bad promise\")}if(typeof t._status!==\"undefined\"){throw new TypeError(\"promise already initialized\")}if(!M.IsCallable(e)){throw new TypeError(\"not a valid resolver\")}t._status=\"unresolved\";t._resolveReactions=[];t._rejectReactions=[];var r=function(e){if(t._status!==\"unresolved\"){return}var r=t._resolveReactions;t._result=e;t._resolveReactions=void 0;t._rejectReactions=void 0;t._status=\"has-resolution\";f(r,e)};var n=function(e){if(t._status!==\"unresolved\"){return}var r=t._rejectReactions;t._result=e;t._resolveReactions=void 0;t._rejectReactions=void 0;t._status=\"has-rejection\";f(r,e)};try{e(r,n)}catch(i){n(i)}return t};t=e.prototype;var l=function(e,t,r,n){var i=false;return function(o){if(i){return}i=true;t[e]=o;if(--n.count===0){var a=r.resolve;a(t)}}};g(e,y,function(e){var r=this;var n=r.prototype||t;e=e||w(n);m(e,{_status:void 0,_result:void 0,_resolveReactions:void 0,_rejectReactions:void 0,_promiseConstructor:void 0});e._promiseConstructor=r;return e});m(e,{all:function p(e){var t=this;var n=new r(t);var i=n.resolve;var o=n.reject;try{if(!M.IsIterable(e)){throw new TypeError(\"bad iterable\")}var a=M.GetIterator(e);var u=[],s={count:1};for(var f=0;;f++){var c=M.IteratorNext(a);if(c.done){break}var p=t.resolve(c.value);var h=l(f,u,n,s);s.count++;p.then(h,n.reject)}if(--s.count===0){i(u)}}catch(v){o(v)}return n.promise},race:function h(e){var t=this;var n=new r(t);var i=n.resolve;var o=n.reject;try{if(!M.IsIterable(e)){throw new TypeError(\"bad iterable\")}var a=M.GetIterator(e);while(true){var u=M.IteratorNext(a);if(u.done){break}var s=t.resolve(u.value);s.then(i,o)}}catch(f){o(f)}return n.promise},reject:function v(e){var t=this;var n=new r(t);var i=n.reject;i(e);return n.promise},resolve:function b(e){var t=this;if(M.IsPromise(e)){var n=e._promiseConstructor;if(n===t){return e}}var i=new r(t);var o=i.resolve;o(e);return i.promise}});m(t,{\"catch\":function(e){return this.then(void 0,e)},then:function d(e,t){var n=this;if(!M.IsPromise(n)){throw new TypeError(\"not a promise\")}var i=this.constructor;var o=new r(i);if(!M.IsCallable(t)){t=function(e){throw e}}if(!M.IsCallable(e)){e=function(e){return e}}var a=c(n,e,t);var u={capability:o,handler:a};var s={capability:o,handler:t};switch(n._status){case\"unresolved\":n._resolveReactions.push(u);n._rejectReactions.push(s);break;case\"has-resolution\":f([u],n._result);break;case\"has-rejection\":f([s],n._result);break;default:throw new TypeError(\"unexpected\")}return o.promise}});return e}();if(o.Promise){delete o.Promise.accept;delete o.Promise.defer;delete o.Promise.prototype.chain}m(o,{Promise:tt});var rt=t(o.Promise,function(e){return e.resolve(42)instanceof e});var nt=function(){try{o.Promise.reject(42).then(null,5).then(null,h);return true}catch(e){return false}}();var it=function(){try{Promise.call(3,h)}catch(e){return true}return false}();if(!rt||!nt||!it){Promise=tt;g(o,\"Promise\",tt,true)}var ot=function(e){var t=Object.keys(e.reduce(function(e,t){e[t]=true;return e},{}));return e.join(\":\")===t.join(\":\")};var at=ot([\"z\",\"a\",\"bb\"]);var ut=ot([\"z\",1,\"a\",\"3\",2]);if(u){var st=function kt(e){if(!at){return null}var t=typeof e;if(t===\"string\"){return\"$\"+e}else if(t===\"number\"){if(!ut){return\"n\"+e}return e}return null};var ft=function At(){return Object.create?Object.create(null):{}};var ct={Map:function(){var e={};function t(e,t){this.key=e;this.value=t;this.next=null;this.prev=null}t.prototype.isRemoved=function(){return this.key===e};function r(e,t){this.head=e._head;this.i=this.head;this.kind=t}r.prototype={next:function(){var e=this.i,t=this.kind,r=this.head,n;if(typeof this.i===\"undefined\"){return{value:void 0,done:true}}while(e.isRemoved()&&e!==r){e=e.prev}while(e.next!==r){e=e.next;if(!e.isRemoved()){if(t===\"key\"){n=e.key}else if(t===\"value\"){n=e.value}else{n=[e.key,e.value]}this.i=e;return{value:n,done:false}}}this.i=void 0;return{value:void 0,done:true}}};j(r.prototype);function n(e){var r=this;if(!M.TypeIsObject(r)){throw new TypeError(\"Map does not accept arguments when called as a function\")}r=N(r);if(!r._es6map){throw new TypeError(\"bad map\")}var n=new t(null,null);n.next=n.prev=n;m(r,{_head:n,_storage:ft(),_size:0});if(typeof e!==\"undefined\"&&e!==null){var i=M.GetIterator(e);var o=r.set;if(!M.IsCallable(o)){throw new TypeError(\"bad map\")}while(true){var a=M.IteratorNext(i);if(a.done){break}var u=a.value;if(!M.TypeIsObject(u)){throw new TypeError(\"expected iterable of pairs\")}o.call(r,u[0],u[1])}}return r}var i=n.prototype;g(n,y,function(e){var t=this;var r=t.prototype||i;e=e||w(r);m(e,{_es6map:true});return e});d.getter(n.prototype,\"size\",function(){if(typeof this._size===\"undefined\"){throw new TypeError(\"size method called on incompatible Map\")}return this._size});m(n.prototype,{get:function(e){var t=st(e);if(t!==null){var r=this._storage[t];if(r){return r.value}else{return}}var n=this._head,i=n;while((i=i.next)!==n){if(M.SameValueZero(i.key,e)){return i.value}}},has:function(e){var t=st(e);if(t!==null){return typeof this._storage[t]!==\"undefined\"}var r=this._head,n=r;while((n=n.next)!==r){if(M.SameValueZero(n.key,e)){return true}}return false},set:function(e,r){var n=this._head,i=n,o;var a=st(e);if(a!==null){if(typeof this._storage[a]!==\"undefined\"){this._storage[a].value=r;return this}else{o=this._storage[a]=new t(e,r);i=n.prev}}while((i=i.next)!==n){if(M.SameValueZero(i.key,e)){i.value=r;return this}}o=o||new t(e,r);if(M.SameValue(-0,e)){o.key=+0}o.next=this._head;o.prev=this._head.prev;o.prev.next=o;o.next.prev=o;this._size+=1;return this},\"delete\":function(t){var r=this._head,n=r;var i=st(t);if(i!==null){if(typeof this._storage[i]===\"undefined\"){return false}n=this._storage[i].prev;delete this._storage[i]}while((n=n.next)!==r){if(M.SameValueZero(n.key,t)){n.key=n.value=e;n.prev.next=n.next;n.next.prev=n.prev;this._size-=1;return true}}return false},clear:function(){this._size=0;this._storage=ft();var t=this._head,r=t,n=r.next;while((r=n)!==t){r.key=r.value=e;n=r.next;r.next=r.prev=t}t.next=t.prev=t},keys:function(){return new r(this,\"key\")},values:function(){return new r(this,\"value\")},entries:function(){return new r(this,\"key+value\")},forEach:function(e){var t=arguments.length>1?arguments[1]:null;var r=this.entries();for(var n=r.next();!n.done;n=r.next()){if(t){e.call(t,n.value[1],n.value[0],this)}else{e(n.value[1],n.value[0],this)}}}});j(n.prototype,function(){return this.entries()});return n}(),Set:function(){var e=function n(e){var t=this;if(!M.TypeIsObject(t)){throw new TypeError(\"Set does not accept arguments when called as a function\")}t=N(t);if(!t._es6set){throw new TypeError(\"bad set\")}m(t,{\"[[SetData]]\":null,_storage:ft()});if(typeof e!==\"undefined\"&&e!==null){var r=M.GetIterator(e);var n=t.add;if(!M.IsCallable(n)){throw new TypeError(\"bad set\")}while(true){var i=M.IteratorNext(r);if(i.done){break}var o=i.value;n.call(t,o)}}return t};var t=e.prototype;g(e,y,function(e){var r=this;var n=r.prototype||t;e=e||w(n);m(e,{_es6set:true});return e});var r=function i(e){if(!e[\"[[SetData]]\"]){var t=e[\"[[SetData]]\"]=new ct.Map;Object.keys(e._storage).forEach(function(e){if(e.charCodeAt(0)===36){e=e.slice(1)}else if(e.charAt(0)===\"n\"){e=+e.slice(1)}else{e=+e}t.set(e,e)});e._storage=null}};d.getter(e.prototype,\"size\",function(){if(typeof this._storage===\"undefined\"){throw new TypeError(\"size method called on incompatible Set\")}r(this);return this[\"[[SetData]]\"].size});m(e.prototype,{has:function(e){var t;if(this._storage&&(t=st(e))!==null){return!!this._storage[t]}r(this);return this[\"[[SetData]]\"].has(e)},add:function(e){var t;if(this._storage&&(t=st(e))!==null){this._storage[t]=true;return this}r(this);this[\"[[SetData]]\"].set(e,e);return this},\"delete\":function(e){var t;if(this._storage&&(t=st(e))!==null){var n=l(this._storage,t);return delete this._storage[t]&&n}r(this);return this[\"[[SetData]]\"][\"delete\"](e)},clear:function(){if(this._storage){this._storage=ft()}else{this[\"[[SetData]]\"].clear()}},values:function(){r(this);return this[\"[[SetData]]\"].values()},entries:function(){r(this);return this[\"[[SetData]]\"].entries()},forEach:function(e){var t=arguments.length>1?arguments[1]:null;var n=this;r(n);this[\"[[SetData]]\"].forEach(function(r,i){if(t){e.call(t,i,i,n)}else{e(i,i,n)}})}});g(e,\"keys\",e.values,true);j(e.prototype,function(){return this.values()});return e}()};m(o,ct);if(o.Map||o.Set){if(typeof o.Map.prototype.clear!==\"function\"||(new o.Set).size!==0||(new o.Map).size!==0||typeof o.Map.prototype.keys!==\"function\"||typeof o.Set.prototype.keys!==\"function\"||typeof o.Map.prototype.forEach!==\"function\"||typeof o.Set.prototype.forEach!==\"function\"||e(o.Map)||e(o.Set)||!t(o.Map,function(e){var t=new e([]);t.set(42,42);return t instanceof e})){o.Map=ct.Map;o.Set=ct.Set}}if(o.Set.prototype.keys!==o.Set.prototype.values){g(o.Set.prototype,\"keys\",o.Set.prototype.values,true)}j(Object.getPrototypeOf((new o.Map).keys()));j(Object.getPrototypeOf((new o.Set).keys()))}if(!o.Reflect){g(o,\"Reflect\",{})}var lt=o.Reflect;var pt=function Rt(e){if(!M.TypeIsObject(e)){throw new TypeError(\"target must be an object\")}};m(o.Reflect,{apply:function Ft(){return M.Call.apply(null,arguments)},construct:function Dt(e,t){if(!M.IsCallable(e)){throw new TypeError(\"First argument must be callable.\")}return M.Construct(e,t)},deleteProperty:function zt(e,t){pt(e);if(u){var r=Object.getOwnPropertyDescriptor(e,t);if(r&&!r.configurable){return false}}return delete e[t]},enumerate:function Lt(e){pt(e);return new L(e,\"key\")},has:function qt(e,t){pt(e);return t in e}});if(Object.getOwnPropertyNames){m(o.Reflect,{ownKeys:function Gt(e){pt(e);var t=Object.getOwnPropertyNames(e);if(M.IsCallable(Object.getOwnPropertySymbols)){t.push.apply(t,Object.getOwnPropertySymbols(e))}return t}})}if(Object.preventExtensions){m(o.Reflect,{isExtensible:function Wt(e){pt(e);return Object.isExtensible(e)},preventExtensions:function Vt(e){pt(e);return yt(function(){Object.preventExtensions(e)})}})}if(u){var ht=function Ut(e,t,r){var n=Object.getOwnPropertyDescriptor(e,t);if(!n){var i=Object.getPrototypeOf(e);if(i===null){return undefined}return ht(i,t,r)}if(\"value\"in n){return n.value}if(n.get){return n.get.call(r)}return undefined};var vt=function Xt(e,t,r,n){var i=Object.getOwnPropertyDescriptor(e,t);if(!i){var o=Object.getPrototypeOf(e);if(o!==null){return vt(o,t,r,n)}i={value:void 0,writable:true,enumerable:true,configurable:true}}if(\"value\"in i){if(!i.writable){return false}if(!M.TypeIsObject(n)){return false}var a=Object.getOwnPropertyDescriptor(n,t);if(a){return lt.defineProperty(n,t,{value:r})}else{return lt.defineProperty(n,t,{value:r,writable:true,enumerable:true,configurable:true})}}if(i.set){i.set.call(n,r);return true}return false\n};var yt=function Zt(e){try{e()}catch(t){return false}return true};m(o.Reflect,{defineProperty:function $t(e,t,r){pt(e);return yt(function(){Object.defineProperty(e,t,r)})},getOwnPropertyDescriptor:function Kt(e,t){pt(e);return Object.getOwnPropertyDescriptor(e,t)},get:function Bt(e,t){pt(e);var r=arguments.length>2?arguments[2]:e;return ht(e,t,r)},set:function Ht(e,t,r){pt(e);var n=arguments.length>3?arguments[3]:e;return vt(e,t,r,n)}})}if(Object.getPrototypeOf){var bt=Object.getPrototypeOf;m(o.Reflect,{getPrototypeOf:function Jt(e){pt(e);return bt(e)}})}if(Object.setPrototypeOf){var gt=function(e,t){while(t){if(e===t){return true}t=lt.getPrototypeOf(t)}return false};m(o.Reflect,{setPrototypeOf:function Qt(e,t){pt(e);if(t!==null&&!M.TypeIsObject(t)){throw new TypeError(\"proto must be an object or null\")}if(t===lt.getPrototypeOf(e)){return true}if(lt.isExtensible&&!lt.isExtensible(e)){return false}if(gt(e,t)){return false}Object.setPrototypeOf(e,t);return true}})}return o});\n\n","js-storage/storage-wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'js-storage/js.storage'\n], function ($, storage) {\n    'use strict';\n\n    if (window.cookieStorage) {\n        var cookiesConfig = window.cookiesConfig || {};\n\n        $.extend(window.cookieStorage, {\n            _secure: !!cookiesConfig.secure,\n            _samesite: cookiesConfig.samesite ? cookiesConfig.samesite : 'lax',\n\n            /**\n             * Set value under name\n             * @param {String} name\n             * @param {String} value\n             * @param {Object} [options]\n             */\n            setItem: function (name, value, options) {\n                var _default = {\n                    expires: this._expires,\n                    path: this._path,\n                    domain: this._domain,\n                    secure: this._secure,\n                    samesite: this._samesite\n                };\n\n                $.cookie(this._prefix + name, value, $.extend(_default, options || {}));\n            },\n\n            /**\n             * Set default options\n             * @param {Object} c\n             * @returns {storage}\n             */\n            setConf: function (c) {\n                if (c.path) {\n                    this._path = c.path;\n                }\n\n                if (c.domain) {\n                    this._domain = c.domain;\n                }\n\n                if (c.expires) {\n                    this._expires = c.expires;\n                }\n\n                if (typeof c.secure !== 'undefined') {\n                    this._secure = c.secure;\n                }\n\n                if (typeof c.samesite !== 'undefined') {\n                    this._samesite = c.samesite;\n                }\n\n                return this;\n            }\n        });\n    }\n\n    $.alwaysUseJsonInStorage = $.alwaysUseJsonInStorage || storage.alwaysUseJsonInStorage;\n    $.cookieStorage = $.cookieStorage || storage.cookieStorage;\n    $.initNamespaceStorage = $.initNamespaceStorage || storage.initNamespaceStorage;\n    $.localStorage = $.localStorage || storage.localStorage;\n    $.namespaceStorages = $.namespaceStorages || storage.namespaceStorages;\n    $.removeAllStorages = $.removeAllStorages || storage.removeAllStorages;\n    $.sessionStorage = $.sessionStorage || storage.sessionStorage;\n});\n","js-storage/js.storage.js":"/*\n * JS Storage Plugin\n *\n * Copyright (c) 2019 Julien Maurel\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/mit-license.php\n *\n * Project home:\n * https://github.com/julien-maurel/js-storage\n *\n * Version: 1.1.0\n */\n(function (factory) {\n    var registeredInModuleLoader = false;\n    if (typeof define === 'function' && define.amd) {\n        define(['jquery', 'jquery/jquery.cookie'], factory);\n        registeredInModuleLoader = true;\n    }\n    if (typeof exports === 'object') {\n        module.exports = factory();\n        registeredInModuleLoader = true;\n    }\n    if (!registeredInModuleLoader) {\n        var OldStorages = window.Storages;\n        var api = window.Storages = factory();\n        api.noConflict = function () {\n            window.Storages = OldStorages;\n            return api;\n        };\n    }\n}(function () {\n    // Variables used by utilities functions (like isPlainObject...)\n    var class2type = {};\n    var toString = class2type.toString;\n    var hasOwn = class2type.hasOwnProperty;\n    var fnToString = hasOwn.toString;\n    var ObjectFunctionString = fnToString.call(Object);\n    var getProto = Object.getPrototypeOf;\n    var apis = {};\n\n    // Prefix to use with cookie fallback\n    var cookie_local_prefix = \"ls_\";\n    var cookie_session_prefix = \"ss_\";\n\n    // Get items from a storage\n    function _get() {\n        var storage = this._type, l = arguments.length, s = window[storage], a = arguments, a0 = a[0], vi, ret, tmp, i, j;\n        if (l < 1) {\n            throw new Error('Minimum 1 argument must be given');\n        } else if (Array.isArray(a0)) {\n            // If second argument is an array, return an object with value of storage for each item in this array\n            ret = {};\n            for (i in a0) {\n                if (a0.hasOwnProperty(i)) {\n                    vi = a0[i];\n                    try {\n                        ret[vi] = JSON.parse(s.getItem(vi));\n                    } catch (e) {\n                        ret[vi] = s.getItem(vi);\n                    }\n                }\n            }\n            return ret;\n        } else if (l == 1) {\n            // If only 1 argument, return value directly\n            try {\n                return JSON.parse(s.getItem(a0));\n            } catch (e) {\n                return s.getItem(a0);\n            }\n        } else {\n            // If more than 1 argument, parse storage to retrieve final value to return it\n            // Get first level\n            try {\n                ret = JSON.parse(s.getItem(a0));\n                if (!ret) {\n                    throw new ReferenceError(a0 + ' is not defined in this storage');\n                }\n            } catch (e) {\n                throw new ReferenceError(a0 + ' is not defined in this storage');\n            }\n            // Parse next levels\n            for (i = 1; i < l - 1; i++) {\n                ret = ret[a[i]];\n                if (ret === undefined) {\n                    throw new ReferenceError([].slice.call(a, 0, i + 1).join('.') + ' is not defined in this storage');\n                }\n            }\n            // If last argument is an array, return an object with value for each item in this array\n            // Else return value normally\n            if (Array.isArray(a[i])) {\n                tmp = ret;\n                ret = {};\n                for (j in a[i]) {\n                    if (a[i].hasOwnProperty(j)) {\n                        ret[a[i][j]] = tmp[a[i][j]];\n                    }\n                }\n                return ret;\n            } else {\n                return ret[a[i]];\n            }\n        }\n    }\n\n    // Set items of a storage\n    function _set() {\n        var storage = this._type, l = arguments.length, s = window[storage], a = arguments, a0 = a[0], a1 = a[1], vi, to_store = isNaN(a1) ? {} : [], type, tmp, i;\n        if (l < 1 || !_isPlainObject(a0) && l < 2) {\n            throw new Error('Minimum 2 arguments must be given or first parameter must be an object');\n        } else if (_isPlainObject(a0)) {\n            // If first argument is an object, set values of storage for each property of this object\n            for (i in a0) {\n                if (a0.hasOwnProperty(i)) {\n                    vi = a0[i];\n                    if (!_isPlainObject(vi) && !this.alwaysUseJson) {\n                        s.setItem(i, vi);\n                    } else {\n                        s.setItem(i, JSON.stringify(vi));\n                    }\n                }\n            }\n            return a0;\n        } else if (l == 2) {\n            // If only 2 arguments, set value of storage directly\n            if (typeof a1 === 'object' || this.alwaysUseJson) {\n                s.setItem(a0, JSON.stringify(a1));\n            } else {\n                s.setItem(a0, a1);\n            }\n            return a1;\n        } else {\n            // If more than 3 arguments, parse storage to retrieve final node and set value\n            // Get first level\n            try {\n                tmp = s.getItem(a0);\n                if (tmp != null) {\n                    to_store = JSON.parse(tmp);\n                }\n            } catch (e) {\n            }\n            tmp = to_store;\n            // Parse next levels and set value\n            for (i = 1; i < l - 2; i++) {\n                vi = a[i];\n                type = isNaN(a[i + 1]) ? \"object\" : \"array\";\n                if (!tmp[vi] || type == \"object\" && !_isPlainObject(tmp[vi]) || type == \"array\" && !Array.isArray(tmp[vi])) {\n                    if (type == \"array\") tmp[vi] = [];\n                    else tmp[vi] = {};\n                }\n                tmp = tmp[vi];\n            }\n            tmp[a[i]] = a[i + 1];\n            s.setItem(a0, JSON.stringify(to_store));\n            return to_store;\n        }\n    }\n\n    // Remove items from a storage\n    function _remove() {\n        var storage = this._type, l = arguments.length, s = window[storage], a = arguments, a0 = a[0], to_store, tmp, i, j;\n        if (l < 1) {\n            throw new Error('Minimum 1 argument must be given');\n        } else if (Array.isArray(a0)) {\n            // If first argument is an array, remove values from storage for each item of this array\n            for (i in a0) {\n                if (a0.hasOwnProperty(i)) {\n                    s.removeItem(a0[i]);\n                }\n            }\n            return true;\n        } else if (l == 1) {\n            // If only 2 arguments, remove value from storage directly\n            s.removeItem(a0);\n            return true;\n        } else {\n            // If more than 2 arguments, parse storage to retrieve final node and remove value\n            // Get first level\n            try {\n                to_store = tmp = JSON.parse(s.getItem(a0));\n            } catch (e) {\n                throw new ReferenceError(a0 + ' is not defined in this storage');\n            }\n            // Parse next levels and remove value\n            for (i = 1; i < l - 1; i++) {\n                tmp = tmp[a[i]];\n                if (tmp === undefined) {\n                    throw new ReferenceError([].slice.call(a, 1, i).join('.') + ' is not defined in this storage');\n                }\n            }\n            // If last argument is an array,remove value for each item in this array\n            // Else remove value normally\n            if (Array.isArray(a[i])) {\n                for (j in a[i]) {\n                    if (a[i].hasOwnProperty(j)) {\n                        delete tmp[a[i][j]];\n                    }\n                }\n            } else {\n                delete tmp[a[i]];\n            }\n            s.setItem(a0, JSON.stringify(to_store));\n            return true;\n        }\n    }\n\n    // Remove all items from a storage\n    function _removeAll(reinit_ns) {\n        var keys = _keys.call(this), i;\n        for (i in keys) {\n            if (keys.hasOwnProperty(i)) {\n                _remove.call(this, keys[i]);\n            }\n        }\n        // Reinitialize all namespace storages\n        if (reinit_ns) {\n            for (i in apis.namespaceStorages) {\n                if (apis.namespaceStorages.hasOwnProperty(i)) {\n                    _createNamespace(i);\n                }\n            }\n        }\n    }\n\n    // Check if items of a storage are empty\n    function _isEmpty() {\n        var l = arguments.length, a = arguments, a0 = a[0], i;\n        if (l == 0) {\n            // If no argument, test if storage is empty\n            return (_keys.call(this).length == 0);\n        } else if (Array.isArray(a0)) {\n            // If first argument is an array, test each item of this array and return true only if all items are empty\n            for (i = 0; i < a0.length; i++) {\n                if (!_isEmpty.call(this, a0[i])) {\n                    return false;\n                }\n            }\n            return true;\n        } else {\n            // If at least 1 argument, try to get value and test it\n            try {\n                var v = _get.apply(this, arguments);\n                // Convert result to an object (if last argument is an array, _get return already an object) and test each item\n                if (!Array.isArray(a[l - 1])) {\n                    v = {'totest': v};\n                }\n                for (i in v) {\n                    if (v.hasOwnProperty(i) && !(\n                        (_isPlainObject(v[i]) && _isEmptyObject(v[i])) ||\n                        (Array.isArray(v[i]) && !v[i].length) ||\n                        (typeof v[i] !== 'boolean' && !v[i])\n                    )) {\n                        return false;\n                    }\n                }\n                return true;\n            } catch (e) {\n                return true;\n            }\n        }\n    }\n\n    // Check if items of a storage exist\n    function _isSet() {\n        var l = arguments.length, a = arguments, a0 = a[0], i;\n        if (l < 1) {\n            throw new Error('Minimum 1 argument must be given');\n        }\n        if (Array.isArray(a0)) {\n            // If first argument is an array, test each item of this array and return true only if all items exist\n            for (i = 0; i < a0.length; i++) {\n                if (!_isSet.call(this, a0[i])) {\n                    return false;\n                }\n            }\n            return true;\n        } else {\n            // For other case, try to get value and test it\n            try {\n                var v = _get.apply(this, arguments);\n                // Convert result to an object (if last argument is an array, _get return already an object) and test each item\n                if (!Array.isArray(a[l - 1])) {\n                    v = {'totest': v};\n                }\n                for (i in v) {\n                    if (v.hasOwnProperty(i) && !(v[i] !== undefined && v[i] !== null)) {\n                        return false;\n                    }\n                }\n                return true;\n            } catch (e) {\n                return false;\n            }\n        }\n    }\n\n    // Get keys of a storage or of an item of the storage\n    function _keys() {\n        var storage = this._type, l = arguments.length, s = window[storage], keys = [], o = {};\n        // If at least 1 argument, get value from storage to retrieve keys\n        // Else, use storage to retrieve keys\n        if (l > 0) {\n            o = _get.apply(this, arguments);\n        } else {\n            o = s;\n        }\n        if (o && o._cookie) {\n            // If storage is a cookie, use js-cookie to retrieve keys\n            var cookies = Cookies.get();\n            for (var key in cookies) {\n                if (cookies.hasOwnProperty(key) && key != '') {\n                    keys.push(key.replace(o._prefix, ''));\n                }\n            }\n        } else {\n            for (var i in o) {\n                if (o.hasOwnProperty(i)) {\n                    keys.push(i);\n                }\n            }\n        }\n        return keys;\n    }\n\n    // Create new namespace storage\n    function _createNamespace(name) {\n        if (!name || typeof name != \"string\") {\n            throw new Error('First parameter must be a string');\n        }\n        if (storage_available) {\n            if (!window.localStorage.getItem(name)) {\n                window.localStorage.setItem(name, '{}');\n            }\n            if (!window.sessionStorage.getItem(name)) {\n                window.sessionStorage.setItem(name, '{}');\n            }\n        } else {\n            if (!window.localCookieStorage.getItem(name)) {\n                window.localCookieStorage.setItem(name, '{}');\n            }\n            if (!window.sessionCookieStorage.getItem(name)) {\n                window.sessionCookieStorage.setItem(name, '{}');\n            }\n        }\n        var ns = {\n            localStorage: _extend({}, apis.localStorage, {_ns: name}),\n            sessionStorage: _extend({}, apis.sessionStorage, {_ns: name})\n        };\n        if (cookies_available) {\n            if (!window.cookieStorage.getItem(name)) {\n                window.cookieStorage.setItem(name, '{}');\n            }\n            ns.cookieStorage = _extend({}, apis.cookieStorage, {_ns: name});\n        }\n        apis.namespaceStorages[name] = ns;\n        return ns;\n    }\n\n    // Test if storage is natively available on browser\n    function _testStorage(name) {\n        var foo = 'jsapi';\n        try {\n            if (!window[name]) {\n                return false;\n            }\n            window[name].setItem(foo, foo);\n            window[name].removeItem(foo);\n            return true;\n        } catch (e) {\n            return false;\n        }\n    }\n\n    // Test if a variable is a plain object (from jQuery)\n    function _isPlainObject(obj) {\n        var proto, Ctor;\n\n        // Detect obvious negatives\n        // Use toString instead of jQuery.type to catch host objects\n        if (!obj || toString.call(obj) !== \"[object Object]\") {\n            return false;\n        }\n\n        proto = getProto(obj);\n\n        // Objects with no prototype (e.g., `Object.create( null )`) are plain\n        if (!proto) {\n            return true;\n        }\n\n        // Objects with prototype are plain iff they were constructed by a global Object function\n        Ctor = hasOwn.call(proto, \"constructor\") && proto.constructor;\n        return typeof Ctor === \"function\" && fnToString.call(Ctor) === ObjectFunctionString;\n    }\n\n    // Test if a variable is an empty object (from jQuery)\n    function _isEmptyObject(obj) {\n        var name;\n\n        for (name in obj) {\n            return false;\n        }\n        return true;\n    }\n\n    // Merge objects\n    function _extend() {\n        var i = 1;\n        var result = arguments[0];\n        for (; i < arguments.length; i++) {\n            var attributes = arguments[i];\n            for (var key in attributes) {\n                if (attributes.hasOwnProperty(key)) {\n                    result[key] = attributes[key];\n                }\n            }\n        }\n        return result;\n    }\n\n    // Check if storages are natively available on browser and check is js-cookie is present\n    var storage_available = _testStorage('localStorage');\n    var cookies_available = typeof Cookies !== 'undefined';\n\n    // Namespace object\n    var storage = {\n        _type: '',\n        _ns: '',\n        _callMethod: function (f, a) {\n            a = Array.prototype.slice.call(a);\n            var p = [], a0 = a[0];\n            if (this._ns) {\n                p.push(this._ns);\n            }\n            if (typeof a0 === 'string' && a0.indexOf('.') !== -1) {\n                a.shift();\n                [].unshift.apply(a, a0.split('.'));\n            }\n            [].push.apply(p, a);\n            return f.apply(this, p);\n        },\n        // Define if plugin always use JSON to store values (even to store simple values like string, int...) or not\n        alwaysUseJson: false,\n        // Get items. If no parameters and storage have a namespace, return all namespace\n        get: function () {\n            if (!storage_available && !cookies_available){\n                return null;\n            }\n            return this._callMethod(_get, arguments);\n        },\n        // Set items\n        set: function () {\n            var l = arguments.length, a = arguments, a0 = a[0];\n            if (l < 1 || !_isPlainObject(a0) && l < 2) {\n                throw new Error('Minimum 2 arguments must be given or first parameter must be an object');\n            }\n            if (!storage_available && !cookies_available){\n                return null;\n            }\n            // If first argument is an object and storage is a namespace storage, set values individually\n            if (_isPlainObject(a0) && this._ns) {\n                for (var i in a0) {\n                    if (a0.hasOwnProperty(i)) {\n                        this._callMethod(_set, [i, a0[i]]);\n                    }\n                }\n                return a0;\n            } else {\n                var r = this._callMethod(_set, a);\n                if (this._ns) {\n                    return r[a0.split('.')[0]];\n                } else {\n                    return r;\n                }\n            }\n        },\n        // Delete items\n        remove: function () {\n            if (arguments.length < 1) {\n                throw new Error('Minimum 1 argument must be given');\n            }\n            if (!storage_available && !cookies_available){\n                return null;\n            }\n            return this._callMethod(_remove, arguments);\n        },\n        // Delete all items\n        removeAll: function (reinit_ns) {\n            if (!storage_available && !cookies_available){\n                return null;\n            }\n            if (this._ns) {\n                this._callMethod(_set, [{}]);\n                return true;\n            } else {\n                return this._callMethod(_removeAll, [reinit_ns]);\n            }\n        },\n        // Items empty\n        isEmpty: function () {\n            if (!storage_available && !cookies_available){\n                return null;\n            }\n            return this._callMethod(_isEmpty, arguments);\n        },\n        // Items exists\n        isSet: function () {\n            if (arguments.length < 1) {\n                throw new Error('Minimum 1 argument must be given');\n            }\n            if (!storage_available && !cookies_available){\n                return null;\n            }\n            return this._callMethod(_isSet, arguments);\n        },\n        // Get keys of items\n        keys: function () {\n            if (!storage_available && !cookies_available){\n                return null;\n            }\n            return this._callMethod(_keys, arguments);\n        }\n    };\n\n    // Use js-cookie for compatibility with old browsers and give access to cookieStorage\n    if (cookies_available) {\n        // sessionStorage is valid for one window/tab. To simulate that with cookie, we set a name for the window and use it for the name of the cookie\n        if (!window.name) {\n            window.name = Math.floor(Math.random() * 100000000);\n        }\n        var cookie_storage = {\n            _cookie: true,\n            _prefix: '',\n            _expires: null,\n            _path: null,\n            _domain: null,\n            _secure: false,\n            setItem: function (n, v) {\n                Cookies.set(this._prefix + n, v, {expires: this._expires, path: this._path, domain: this._domain, secure: this._secure});\n            },\n            getItem: function (n) {\n                return Cookies.get(this._prefix + n);\n            },\n            removeItem: function (n) {\n                return Cookies.remove(this._prefix + n, {path: this._path});\n            },\n            clear: function () {\n                var cookies = Cookies.get();\n                for (var key in cookies) {\n                    if (cookies.hasOwnProperty(key) && key != '') {\n                        if (!this._prefix && key.indexOf(cookie_local_prefix) === -1 && key.indexOf(cookie_session_prefix) === -1 || this._prefix && key.indexOf(this._prefix) === 0) {\n                            Cookies.remove(key);\n                        }\n                    }\n                }\n            },\n            setExpires: function (e) {\n                this._expires = e;\n                return this;\n            },\n            setPath: function (p) {\n                this._path = p;\n                return this;\n            },\n            setDomain: function (d) {\n                this._domain = d;\n                return this;\n            },\n            setSecure: function (s) {\n                this._secure = s;\n                return this;\n            },\n            setConf: function (c) {\n                if (c.path) {\n                    this._path = c.path;\n                }\n                if (c.domain) {\n                    this._domain = c.domain;\n                }\n                if (c.secure) {\n                    this._secure = c.secure;\n                }\n                if (c.expires) {\n                    this._expires = c.expires;\n                }\n                return this;\n            },\n            setDefaultConf: function () {\n                this._path = this._domain = this._expires = null;\n                this._secure = false;\n            }\n        };\n        if (!storage_available) {\n            window.localCookieStorage = _extend({}, cookie_storage, {\n                _prefix: cookie_local_prefix,\n                _expires: 365 * 10,\n                _secure: true\n            });\n            window.sessionCookieStorage = _extend({}, cookie_storage, {\n                _prefix: cookie_session_prefix + window.name + '_',\n                _secure: true\n            });\n        }\n        window.cookieStorage = _extend({}, cookie_storage);\n        // cookieStorage API\n        apis.cookieStorage = _extend({}, storage, {\n            _type: 'cookieStorage',\n            setExpires: function (e) {\n                window.cookieStorage.setExpires(e);\n                return this;\n            },\n            setPath: function (p) {\n                window.cookieStorage.setPath(p);\n                return this;\n            },\n            setDomain: function (d) {\n                window.cookieStorage.setDomain(d);\n                return this;\n            },\n            setSecure: function (s) {\n                window.cookieStorage.setSecure(s);\n                return this;\n            },\n            setConf: function (c) {\n                window.cookieStorage.setConf(c);\n                return this;\n            },\n            setDefaultConf: function () {\n                window.cookieStorage.setDefaultConf();\n                return this;\n            }\n        });\n    }\n\n    // Get a new API on a namespace\n    apis.initNamespaceStorage = function (ns) {\n        return _createNamespace(ns);\n    };\n    if (storage_available) {\n        // localStorage API\n        apis.localStorage = _extend({}, storage, {_type: 'localStorage'});\n        // sessionStorage API\n        apis.sessionStorage = _extend({}, storage, {_type: 'sessionStorage'});\n    } else {\n        // localStorage API\n        apis.localStorage = _extend({}, storage, {_type: 'localCookieStorage'});\n        // sessionStorage API\n        apis.sessionStorage = _extend({}, storage, {_type: 'sessionCookieStorage'});\n    }\n    // List of all namespace storage\n    apis.namespaceStorages = {};\n    // Remove all items in all storages\n    apis.removeAllStorages = function (reinit_ns) {\n        apis.localStorage.removeAll(reinit_ns);\n        apis.sessionStorage.removeAll(reinit_ns);\n        if (apis.cookieStorage) {\n            apis.cookieStorage.removeAll(reinit_ns);\n        }\n        if (!reinit_ns) {\n            apis.namespaceStorages = {};\n        }\n    };\n    // About alwaysUseJson\n    // By default, all values are string on html storages and the plugin don't use json to store simple values (strings, int, float...)\n    // So by default, if you do storage.setItem('test',2), value in storage will be \"2\", not 2\n    // If you set this property to true, all values set with the plugin will be stored as json to have typed values in any cases\n    apis.alwaysUseJsonInStorage = function (value) {\n        storage.alwaysUseJson = value;\n        apis.localStorage.alwaysUseJson = value;\n        apis.sessionStorage.alwaysUseJson = value;\n        if (apis.cookieStorage) {\n            apis.cookieStorage.alwaysUseJson = value;\n        }\n    };\n\n    return apis;\n}));\n","jquery/compat.js":"// Import every plugin under the sun. Bad for performance,\n// but prevents the store from breaking in situations\n// where a dependency was missed during the migration from\n// a monolith build of jQueryUI to a modular one\n\ndefine([\n    'jquery-ui-modules/core',\n    'jquery-ui-modules/accordion',\n    'jquery-ui-modules/autocomplete',\n    'jquery-ui-modules/button',\n    'jquery-ui-modules/datepicker',\n    'jquery-ui-modules/dialog',\n    'jquery-ui-modules/draggable',\n    'jquery-ui-modules/droppable',\n    'jquery-ui-modules/effect-blind',\n    'jquery-ui-modules/effect-bounce',\n    'jquery-ui-modules/effect-clip',\n    'jquery-ui-modules/effect-drop',\n    'jquery-ui-modules/effect-explode',\n    'jquery-ui-modules/effect-fade',\n    'jquery-ui-modules/effect-fold',\n    'jquery-ui-modules/effect-highlight',\n    'jquery-ui-modules/effect-scale',\n    'jquery-ui-modules/effect-pulsate',\n    'jquery-ui-modules/effect-shake',\n    'jquery-ui-modules/effect-slide',\n    'jquery-ui-modules/effect-transfer',\n    'jquery-ui-modules/effect',\n    'jquery-ui-modules/menu',\n    'jquery-ui-modules/mouse',\n    'jquery-ui-modules/position',\n    'jquery-ui-modules/progressbar',\n    'jquery-ui-modules/resizable',\n    'jquery-ui-modules/selectable',\n    'jquery-ui-modules/slider',\n    'jquery-ui-modules/sortable',\n    'jquery-ui-modules/spinner',\n    'jquery-ui-modules/tabs',\n    'jquery-ui-modules/timepicker',\n    'jquery-ui-modules/tooltip',\n    'jquery-ui-modules/widget'\n], function() {\n    console.warn(\n        'Fallback to JQueryUI Compat activated. ' +\n        'Your store is missing a dependency for a ' +\n        'jQueryUI widget. Identifying and addressing the dependency ' +\n        'will drastically improve the performance of your site.'\n    );\n});\n","jquery/timepicker.js":"/*! jQuery Timepicker Addon - v1.6.3 - 2016-04-20\n* http://trentrichardson.com/examples/timepicker\n* Copyright (c) 2016 Trent Richardson; Licensed MIT */\n(function (factory) {\n    if (typeof define === 'function' && define.amd) {\n        define(['jquery', 'jquery-ui-modules/datepicker', 'jquery-ui-modules/slider'], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($) {\n\n    /*\n    * Lets not redefine timepicker, Prevent \"Uncaught RangeError: Maximum call stack size exceeded\"\n    */\n    $.ui.timepicker = $.ui.timepicker || {};\n    if ($.ui.timepicker.version) {\n        return;\n    }\n\n    /*\n    * Extend jQueryUI, get it started with our version number\n    */\n    $.extend($.ui, {\n        timepicker: {\n            version: \"1.6.3\"\n        }\n    });\n\n    /*\n    * Timepicker manager.\n    * Use the singleton instance of this class, $.timepicker, to interact with the time picker.\n    * Settings for (groups of) time pickers are maintained in an instance object,\n    * allowing multiple different settings on the same page.\n    */\n    var Timepicker = function () {\n        this.regional = []; // Available regional settings, indexed by language code\n        this.regional[''] = { // Default regional settings\n            currentText: 'Now',\n            closeText: 'Done',\n            amNames: ['AM', 'A'],\n            pmNames: ['PM', 'P'],\n            timeFormat: 'HH:mm',\n            timeSuffix: '',\n            timeOnlyTitle: 'Choose Time',\n            timeText: 'Time',\n            hourText: 'Hour',\n            minuteText: 'Minute',\n            secondText: 'Second',\n            millisecText: 'Millisecond',\n            microsecText: 'Microsecond',\n            timezoneText: 'Time Zone',\n            isRTL: false\n        };\n        this._defaults = { // Global defaults for all the datetime picker instances\n            showButtonPanel: true,\n            timeOnly: false,\n            timeOnlyShowDate: false,\n            showHour: null,\n            showMinute: null,\n            showSecond: null,\n            showMillisec: null,\n            showMicrosec: null,\n            showTimezone: null,\n            showTime: true,\n            stepHour: 1,\n            stepMinute: 1,\n            stepSecond: 1,\n            stepMillisec: 1,\n            stepMicrosec: 1,\n            hour: 0,\n            minute: 0,\n            second: 0,\n            millisec: 0,\n            microsec: 0,\n            timezone: null,\n            hourMin: 0,\n            minuteMin: 0,\n            secondMin: 0,\n            millisecMin: 0,\n            microsecMin: 0,\n            hourMax: 23,\n            minuteMax: 59,\n            secondMax: 59,\n            millisecMax: 999,\n            microsecMax: 999,\n            minDateTime: null,\n            maxDateTime: null,\n            maxTime: null,\n            minTime: null,\n            onSelect: null,\n            hourGrid: 0,\n            minuteGrid: 0,\n            secondGrid: 0,\n            millisecGrid: 0,\n            microsecGrid: 0,\n            alwaysSetTime: true,\n            separator: ' ',\n            altFieldTimeOnly: true,\n            altTimeFormat: null,\n            altSeparator: null,\n            altTimeSuffix: null,\n            altRedirectFocus: true,\n            pickerTimeFormat: null,\n            pickerTimeSuffix: null,\n            showTimepicker: true,\n            timezoneList: null,\n            addSliderAccess: false,\n            sliderAccessArgs: null,\n            controlType: 'slider',\n            oneLine: false,\n            defaultValue: null,\n            parse: 'strict',\n            afterInject: null\n        };\n        $.extend(this._defaults, this.regional['']);\n    };\n\n    $.extend(Timepicker.prototype, {\n        $input: null,\n        $altInput: null,\n        $timeObj: null,\n        inst: null,\n        hour_slider: null,\n        minute_slider: null,\n        second_slider: null,\n        millisec_slider: null,\n        microsec_slider: null,\n        timezone_select: null,\n        maxTime: null,\n        minTime: null,\n        hour: 0,\n        minute: 0,\n        second: 0,\n        millisec: 0,\n        microsec: 0,\n        timezone: null,\n        hourMinOriginal: null,\n        minuteMinOriginal: null,\n        secondMinOriginal: null,\n        millisecMinOriginal: null,\n        microsecMinOriginal: null,\n        hourMaxOriginal: null,\n        minuteMaxOriginal: null,\n        secondMaxOriginal: null,\n        millisecMaxOriginal: null,\n        microsecMaxOriginal: null,\n        ampm: '',\n        formattedDate: '',\n        formattedTime: '',\n        formattedDateTime: '',\n        timezoneList: null,\n        units: ['hour', 'minute', 'second', 'millisec', 'microsec'],\n        support: {},\n        control: null,\n\n        /*\n        * Override the default settings for all instances of the time picker.\n        * @param  {Object} settings  object - the new settings to use as defaults (anonymous object)\n        * @return {Object} the manager object\n        */\n        setDefaults: function (settings) {\n            extendRemove(this._defaults, settings || {});\n            return this;\n        },\n\n        /*\n        * Create a new Timepicker instance\n        */\n        _newInst: function ($input, opts) {\n            var tp_inst = new Timepicker(),\n                inlineSettings = {},\n                fns = {},\n                overrides, i;\n\n            for (var attrName in this._defaults) {\n                if (this._defaults.hasOwnProperty(attrName)) {\n                    var attrValue = $input.attr('time:' + attrName);\n                    if (attrValue) {\n                        try {\n                            inlineSettings[attrName] = eval(attrValue);\n                        } catch (err) {\n                            inlineSettings[attrName] = attrValue;\n                        }\n                    }\n                }\n            }\n\n            overrides = {\n                beforeShow: function (input, dp_inst) {\n                    if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {\n                        return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);\n                    }\n                },\n                onChangeMonthYear: function (year, month, dp_inst) {\n                    // Update the time as well : this prevents the time from disappearing from the $input field.\n                    // tp_inst._updateDateTime(dp_inst);\n                    if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {\n                        tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);\n                    }\n                },\n                onClose: function (dateText, dp_inst) {\n                    if (tp_inst.timeDefined === true && $input.val() !== '') {\n                        tp_inst._updateDateTime(dp_inst);\n                    }\n                    if ($.isFunction(tp_inst._defaults.evnts.onClose)) {\n                        tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);\n                    }\n                }\n            };\n            for (i in overrides) {\n                if (overrides.hasOwnProperty(i)) {\n                    fns[i] = opts[i] || this._defaults[i] || null;\n                }\n            }\n\n            tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, opts, overrides, {\n                evnts: fns,\n                timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');\n            });\n            tp_inst.amNames = $.map(tp_inst._defaults.amNames, function (val) {\n                return val.toUpperCase();\n            });\n            tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function (val) {\n                return val.toUpperCase();\n            });\n\n            // detect which units are supported\n            tp_inst.support = detectSupport(\n                tp_inst._defaults.timeFormat +\n                (tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') +\n                (tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : ''));\n\n            // controlType is string - key to our this._controls\n            if (typeof(tp_inst._defaults.controlType) === 'string') {\n                if (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') {\n                    tp_inst._defaults.controlType = 'select';\n                }\n                tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];\n            }\n            // controlType is an object and must implement create, options, value methods\n            else {\n                tp_inst.control = tp_inst._defaults.controlType;\n            }\n\n            // prep the timezone options\n            var timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60,\n                0, 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            if (tp_inst._defaults.timezoneList !== null) {\n                timezoneList = tp_inst._defaults.timezoneList;\n            }\n            var tzl = timezoneList.length, tzi = 0, tzv = null;\n            if (tzl > 0 && typeof timezoneList[0] !== 'object') {\n                for (; tzi < tzl; tzi++) {\n                    tzv = timezoneList[tzi];\n                    timezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) };\n                }\n            }\n            tp_inst._defaults.timezoneList = timezoneList;\n\n            // set the default units\n            tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) :\n                ((new Date()).getTimezoneOffset() * -1);\n            tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin :\n                tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour;\n            tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin :\n                tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute;\n            tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin :\n                tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second;\n            tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin :\n                tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec;\n            tp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin :\n                tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec;\n            tp_inst.ampm = '';\n            tp_inst.$input = $input;\n\n            if (tp_inst._defaults.altField) {\n                tp_inst.$altInput = $(tp_inst._defaults.altField);\n                if (tp_inst._defaults.altRedirectFocus === true) {\n                    tp_inst.$altInput.css({\n                        cursor: 'pointer'\n                    }).focus(function () {\n                        $input.trigger(\"focus\");\n                    });\n                }\n            }\n\n            if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {\n                tp_inst._defaults.minDate = new Date();\n            }\n            if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {\n                tp_inst._defaults.maxDate = new Date();\n            }\n\n            // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..\n            if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {\n                tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());\n            }\n            if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {\n                tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());\n            }\n            if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {\n                tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());\n            }\n            if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {\n                tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());\n            }\n            tp_inst.$input.bind('focus', function () {\n                tp_inst._onFocus();\n            });\n\n            return tp_inst;\n        },\n\n        /*\n        * add our sliders to the calendar\n        */\n        _addTimePicker: function (dp_inst) {\n            var currDT = $.trim((this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val());\n\n            this.timeDefined = this._parseTime(currDT);\n            this._limitMinMaxDateTime(dp_inst, false);\n            this._injectTimePicker();\n            this._afterInject();\n        },\n\n        /*\n        * parse the time string from input value or _setTime\n        */\n        _parseTime: function (timeString, withDate) {\n            if (!this.inst) {\n                this.inst = $.datepicker._getInst(this.$input[0]);\n            }\n\n            if (withDate || !this._defaults.timeOnly) {\n                var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');\n                try {\n                    var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);\n                    if (!parseRes.timeObj) {\n                        return false;\n                    }\n                    $.extend(this, parseRes.timeObj);\n                } catch (err) {\n                    $.timepicker.log(\"Error parsing the date/time string: \" + err +\n                        \"\\ndate/time string = \" + timeString +\n                        \"\\ntimeFormat = \" + this._defaults.timeFormat +\n                        \"\\ndateFormat = \" + dp_dateFormat);\n                    return false;\n                }\n                return true;\n            } else {\n                var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);\n                if (!timeObj) {\n                    return false;\n                }\n                $.extend(this, timeObj);\n                return true;\n            }\n        },\n\n        /*\n        * Handle callback option after injecting timepicker\n        */\n        _afterInject: function() {\n            var o = this.inst.settings;\n            if ($.isFunction(o.afterInject)) {\n                o.afterInject.call(this);\n            }\n        },\n\n        /*\n        * generate and inject html for timepicker into ui datepicker\n        */\n        _injectTimePicker: function () {\n            var $dp = this.inst.dpDiv,\n                o = this.inst.settings,\n                tp_inst = this,\n                litem = '',\n                uitem = '',\n                show = null,\n                max = {},\n                gridSize = {},\n                size = null,\n                i = 0,\n                l = 0;\n\n            // Prevent displaying twice\n            if ($dp.find(\"div.ui-timepicker-div\").length === 0 && o.showTimepicker) {\n                var noDisplay = ' ui_tpicker_unit_hide',\n                    html = '<div class=\"ui-timepicker-div' + (o.isRTL ? ' ui-timepicker-rtl' : '') + (o.oneLine && o.controlType === 'select' ? ' ui-timepicker-oneLine' : '') + '\"><dl>' + '<dt class=\"ui_tpicker_time_label' + ((o.showTime) ? '' : noDisplay) + '\">' + o.timeText + '</dt>' +\n                        '<dd class=\"ui_tpicker_time '+ ((o.showTime) ? '' : noDisplay) + '\"><input class=\"ui_tpicker_time_input\" ' + (o.timeInput ? '' : 'disabled') + '/></dd>';\n\n                // Create the markup\n                for (i = 0, l = this.units.length; i < l; i++) {\n                    litem = this.units[i];\n                    uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);\n                    show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];\n\n                    // Added by Peter Medeiros:\n                    // - Figure out what the hour/minute/second max should be based on the step values.\n                    // - Example: if stepMinute is 15, then minMax is 45.\n                    max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10);\n                    gridSize[litem] = 0;\n\n                    html += '<dt class=\"ui_tpicker_' + litem + '_label' + (show ? '' : noDisplay) + '\">' + o[litem + 'Text'] + '</dt>' +\n                        '<dd class=\"ui_tpicker_' + litem + (show ? '' : noDisplay) + '\"><div class=\"ui_tpicker_' + litem + '_slider' + (show ? '' : noDisplay) + '\"></div>';\n\n                    if (show && o[litem + 'Grid'] > 0) {\n                        html += '<div style=\"padding-left: 1px\"><table class=\"ui-tpicker-grid-label\"><tr>';\n\n                        if (litem === 'hour') {\n                            for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) {\n                                gridSize[litem]++;\n                                var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o);\n                                html += '<td data-for=\"' + litem + '\">' + tmph + '</td>';\n                            }\n                        }\n                        else {\n                            for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) {\n                                gridSize[litem]++;\n                                html += '<td data-for=\"' + litem + '\">' + ((m < 10) ? '0' : '') + m + '</td>';\n                            }\n                        }\n\n                        html += '</tr></table></div>';\n                    }\n                    html += '</dd>';\n                }\n\n                // Timezone\n                var showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone;\n                html += '<dt class=\"ui_tpicker_timezone_label' + (showTz ? '' : noDisplay) + '\">' + o.timezoneText + '</dt>';\n                html += '<dd class=\"ui_tpicker_timezone' + (showTz ? '' : noDisplay) + '\"></dd>';\n\n                // Create the elements from string\n                html += '</dl></div>';\n                var $tp = $(html);\n\n                // if we only want time picker...\n                if (o.timeOnly === true) {\n                    $tp.prepend('<div class=\"ui-widget-header ui-helper-clearfix ui-corner-all\">' + '<div class=\"ui-datepicker-title\">' + o.timeOnlyTitle + '</div>' + '</div>');\n                    $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();\n                }\n\n                // add sliders, adjust grids, add events\n                for (i = 0, l = tp_inst.units.length; i < l; i++) {\n                    litem = tp_inst.units[i];\n                    uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);\n                    show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];\n\n                    // add the slider\n                    tp_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                    // adjust the grid and add click event\n                    if (show && o[litem + 'Grid'] > 0) {\n                        size = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']);\n                        $tp.find('.ui_tpicker_' + litem + ' table').css({\n                            width: size + \"%\",\n                            marginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + \"%\"),\n                            marginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + \"%\") : '0',\n                            borderCollapse: 'collapse'\n                        }).find(\"td\").click(function (e) {\n                            var $t = $(this),\n                                h = $t.html(),\n                                n = parseInt(h.replace(/[^0-9]/g), 10),\n                                ap = h.replace(/[^apm]/ig),\n                                f = $t.data('for'); // loses scope, so we use data-for\n\n                            if (f === 'hour') {\n                                if (ap.indexOf('p') !== -1 && n < 12) {\n                                    n += 12;\n                                }\n                                else {\n                                    if (ap.indexOf('a') !== -1 && n === 12) {\n                                        n = 0;\n                                    }\n                                }\n                            }\n\n                            tp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n);\n\n                            tp_inst._onTimeChange();\n                            tp_inst._onSelectHandler();\n                        }).css({\n                            cursor: 'pointer',\n                            width: (100 / gridSize[litem]) + '%',\n                            textAlign: 'center',\n                            overflow: 'hidden'\n                        });\n                    } // end if grid > 0\n                } // end for loop\n\n                // Add timezone options\n                this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find(\"select\");\n                $.fn.append.apply(this.timezone_select,\n                    $.map(o.timezoneList, function (val, idx) {\n                        return $(\"<option />\").val(typeof val === \"object\" ? val.value : val).text(typeof val === \"object\" ? val.label : val);\n                    }));\n                if (typeof(this.timezone) !== \"undefined\" && this.timezone !== null && this.timezone !== \"\") {\n                    var local_timezone = (new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12)).getTimezoneOffset() * -1;\n                    if (local_timezone === this.timezone) {\n                        selectLocalTimezone(tp_inst);\n                    } else {\n                        this.timezone_select.val(this.timezone);\n                    }\n                } else {\n                    if (typeof(this.hour) !== \"undefined\" && this.hour !== null && this.hour !== \"\") {\n                        this.timezone_select.val(o.timezone);\n                    } else {\n                        selectLocalTimezone(tp_inst);\n                    }\n                }\n                this.timezone_select.change(function () {\n                    tp_inst._onTimeChange();\n                    tp_inst._onSelectHandler();\n                    tp_inst._afterInject();\n                });\n                // End timezone options\n\n                // inject timepicker into datepicker\n                var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');\n                if ($buttonPanel.length) {\n                    $buttonPanel.before($tp);\n                } else {\n                    $dp.append($tp);\n                }\n\n                this.$timeObj = $tp.find('.ui_tpicker_time_input');\n                this.$timeObj.change(function () {\n                    var timeFormat = tp_inst.inst.settings.timeFormat;\n                    var parsedTime = $.datepicker.parseTime(timeFormat, this.value);\n                    var update = new Date();\n                    if (parsedTime) {\n                        update.setHours(parsedTime.hour);\n                        update.setMinutes(parsedTime.minute);\n                        update.setSeconds(parsedTime.second);\n                        $.datepicker._setTime(tp_inst.inst, update);\n                    } else {\n                        this.value = tp_inst.formattedTime;\n                        this.blur();\n                    }\n                });\n\n                if (this.inst !== null) {\n                    var timeDefined = this.timeDefined;\n                    this._onTimeChange();\n                    this.timeDefined = timeDefined;\n                }\n\n                // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/\n                if (this._defaults.addSliderAccess) {\n                    var sliderAccessArgs = this._defaults.sliderAccessArgs,\n                        rtl = this._defaults.isRTL;\n                    sliderAccessArgs.isRTL = rtl;\n\n                    setTimeout(function () { // fix for inline mode\n                        if ($tp.find('.ui-slider-access').length === 0) {\n                            $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);\n\n                            // fix any grids since sliders are shorter\n                            var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);\n                            if (sliderAccessWidth) {\n                                $tp.find('table:visible').each(function () {\n                                    var $g = $(this),\n                                        oldWidth = $g.outerWidth(),\n                                        oldMarginLeft = $g.css(rtl ? 'marginRight' : 'marginLeft').toString().replace('%', ''),\n                                        newWidth = oldWidth - sliderAccessWidth,\n                                        newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',\n                                        css = { width: newWidth, marginRight: 0, marginLeft: 0 };\n                                    css[rtl ? 'marginRight' : 'marginLeft'] = newMarginLeft;\n                                    $g.css(css);\n                                });\n                            }\n                        }\n                    }, 10);\n                }\n                // end slideAccess integration\n\n                tp_inst._limitMinMaxDateTime(this.inst, true);\n            }\n        },\n\n        /*\n        * This function tries to limit the ability to go outside the\n        * min/max date range\n        */\n        _limitMinMaxDateTime: function (dp_inst, adjustSliders) {\n            var o = this._defaults,\n                dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);\n\n            if (!this._defaults.showTimepicker) {\n                return;\n            } // No time so nothing to check here\n\n            if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {\n                var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),\n                    minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);\n\n                if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null || this.microsecMinOriginal === null) {\n                    this.hourMinOriginal = o.hourMin;\n                    this.minuteMinOriginal = o.minuteMin;\n                    this.secondMinOriginal = o.secondMin;\n                    this.millisecMinOriginal = o.millisecMin;\n                    this.microsecMinOriginal = o.microsecMin;\n                }\n\n                if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() === dp_date.getTime()) {\n                    this._defaults.hourMin = minDateTime.getHours();\n                    if (this.hour <= this._defaults.hourMin) {\n                        this.hour = this._defaults.hourMin;\n                        this._defaults.minuteMin = minDateTime.getMinutes();\n                        if (this.minute <= this._defaults.minuteMin) {\n                            this.minute = this._defaults.minuteMin;\n                            this._defaults.secondMin = minDateTime.getSeconds();\n                            if (this.second <= this._defaults.secondMin) {\n                                this.second = this._defaults.secondMin;\n                                this._defaults.millisecMin = minDateTime.getMilliseconds();\n                                if (this.millisec <= this._defaults.millisecMin) {\n                                    this.millisec = this._defaults.millisecMin;\n                                    this._defaults.microsecMin = minDateTime.getMicroseconds();\n                                } else {\n                                    if (this.microsec < this._defaults.microsecMin) {\n                                        this.microsec = this._defaults.microsecMin;\n                                    }\n                                    this._defaults.microsecMin = this.microsecMinOriginal;\n                                }\n                            } else {\n                                this._defaults.millisecMin = this.millisecMinOriginal;\n                                this._defaults.microsecMin = this.microsecMinOriginal;\n                            }\n                        } else {\n                            this._defaults.secondMin = this.secondMinOriginal;\n                            this._defaults.millisecMin = this.millisecMinOriginal;\n                            this._defaults.microsecMin = this.microsecMinOriginal;\n                        }\n                    } else {\n                        this._defaults.minuteMin = this.minuteMinOriginal;\n                        this._defaults.secondMin = this.secondMinOriginal;\n                        this._defaults.millisecMin = this.millisecMinOriginal;\n                        this._defaults.microsecMin = this.microsecMinOriginal;\n                    }\n                } else {\n                    this._defaults.hourMin = this.hourMinOriginal;\n                    this._defaults.minuteMin = this.minuteMinOriginal;\n                    this._defaults.secondMin = this.secondMinOriginal;\n                    this._defaults.millisecMin = this.millisecMinOriginal;\n                    this._defaults.microsecMin = this.microsecMinOriginal;\n                }\n            }\n\n            if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {\n                var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),\n                    maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);\n\n                if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null || this.millisecMaxOriginal === null) {\n                    this.hourMaxOriginal = o.hourMax;\n                    this.minuteMaxOriginal = o.minuteMax;\n                    this.secondMaxOriginal = o.secondMax;\n                    this.millisecMaxOriginal = o.millisecMax;\n                    this.microsecMaxOriginal = o.microsecMax;\n                }\n\n                if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() === dp_date.getTime()) {\n                    this._defaults.hourMax = maxDateTime.getHours();\n                    if (this.hour >= this._defaults.hourMax) {\n                        this.hour = this._defaults.hourMax;\n                        this._defaults.minuteMax = maxDateTime.getMinutes();\n                        if (this.minute >= this._defaults.minuteMax) {\n                            this.minute = this._defaults.minuteMax;\n                            this._defaults.secondMax = maxDateTime.getSeconds();\n                            if (this.second >= this._defaults.secondMax) {\n                                this.second = this._defaults.secondMax;\n                                this._defaults.millisecMax = maxDateTime.getMilliseconds();\n                                if (this.millisec >= this._defaults.millisecMax) {\n                                    this.millisec = this._defaults.millisecMax;\n                                    this._defaults.microsecMax = maxDateTime.getMicroseconds();\n                                } else {\n                                    if (this.microsec > this._defaults.microsecMax) {\n                                        this.microsec = this._defaults.microsecMax;\n                                    }\n                                    this._defaults.microsecMax = this.microsecMaxOriginal;\n                                }\n                            } else {\n                                this._defaults.millisecMax = this.millisecMaxOriginal;\n                                this._defaults.microsecMax = this.microsecMaxOriginal;\n                            }\n                        } else {\n                            this._defaults.secondMax = this.secondMaxOriginal;\n                            this._defaults.millisecMax = this.millisecMaxOriginal;\n                            this._defaults.microsecMax = this.microsecMaxOriginal;\n                        }\n                    } else {\n                        this._defaults.minuteMax = this.minuteMaxOriginal;\n                        this._defaults.secondMax = this.secondMaxOriginal;\n                        this._defaults.millisecMax = this.millisecMaxOriginal;\n                        this._defaults.microsecMax = this.microsecMaxOriginal;\n                    }\n                } else {\n                    this._defaults.hourMax = this.hourMaxOriginal;\n                    this._defaults.minuteMax = this.minuteMaxOriginal;\n                    this._defaults.secondMax = this.secondMaxOriginal;\n                    this._defaults.millisecMax = this.millisecMaxOriginal;\n                    this._defaults.microsecMax = this.microsecMaxOriginal;\n                }\n            }\n\n            if (dp_inst.settings.minTime!==null) {\n                var tempMinTime=new Date(\"01/01/1970 \" + dp_inst.settings.minTime);\n                if (this.hour<tempMinTime.getHours()) {\n                    this.hour=this._defaults.hourMin=tempMinTime.getHours();\n                    this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();\n                } else if (this.hour===tempMinTime.getHours() && this.minute<tempMinTime.getMinutes()) {\n                    this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();\n                } else {\n                    if (this._defaults.hourMin<tempMinTime.getHours()) {\n                        this._defaults.hourMin=tempMinTime.getHours();\n                        this._defaults.minuteMin=tempMinTime.getMinutes();\n                    } else if (this._defaults.hourMin===tempMinTime.getHours()===this.hour && this._defaults.minuteMin<tempMinTime.getMinutes()) {\n                        this._defaults.minuteMin=tempMinTime.getMinutes();\n                    } else {\n                        this._defaults.minuteMin=0;\n                    }\n                }\n            }\n\n            if (dp_inst.settings.maxTime!==null) {\n                var tempMaxTime=new Date(\"01/01/1970 \" + dp_inst.settings.maxTime);\n                if (this.hour>tempMaxTime.getHours()) {\n                    this.hour=this._defaults.hourMax=tempMaxTime.getHours();\n                    this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();\n                } else if (this.hour===tempMaxTime.getHours() && this.minute>tempMaxTime.getMinutes()) {\n                    this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();\n                } else {\n                    if (this._defaults.hourMax>tempMaxTime.getHours()) {\n                        this._defaults.hourMax=tempMaxTime.getHours();\n                        this._defaults.minuteMax=tempMaxTime.getMinutes();\n                    } else if (this._defaults.hourMax===tempMaxTime.getHours()===this.hour && this._defaults.minuteMax>tempMaxTime.getMinutes()) {\n                        this._defaults.minuteMax=tempMaxTime.getMinutes();\n                    } else {\n                        this._defaults.minuteMax=59;\n                    }\n                }\n            }\n\n            if (adjustSliders !== undefined && adjustSliders === true) {\n                var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),\n                    minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),\n                    secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),\n                    millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10),\n                    microsecMax = parseInt((this._defaults.microsecMax - ((this._defaults.microsecMax - this._defaults.microsecMin) % this._defaults.stepMicrosec)), 10);\n\n                if (this.hour_slider) {\n                    this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax, step: this._defaults.stepHour });\n                    this.control.value(this, this.hour_slider, 'hour', this.hour - (this.hour % this._defaults.stepHour));\n                }\n                if (this.minute_slider) {\n                    this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax, step: this._defaults.stepMinute });\n                    this.control.value(this, this.minute_slider, 'minute', this.minute - (this.minute % this._defaults.stepMinute));\n                }\n                if (this.second_slider) {\n                    this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax, step: this._defaults.stepSecond });\n                    this.control.value(this, this.second_slider, 'second', this.second - (this.second % this._defaults.stepSecond));\n                }\n                if (this.millisec_slider) {\n                    this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax, step: this._defaults.stepMillisec });\n                    this.control.value(this, this.millisec_slider, 'millisec', this.millisec - (this.millisec % this._defaults.stepMillisec));\n                }\n                if (this.microsec_slider) {\n                    this.control.options(this, this.microsec_slider, 'microsec', { min: this._defaults.microsecMin, max: microsecMax, step: this._defaults.stepMicrosec });\n                    this.control.value(this, this.microsec_slider, 'microsec', this.microsec - (this.microsec % this._defaults.stepMicrosec));\n                }\n            }\n\n        },\n\n        /*\n        * when a slider moves, set the internal time...\n        * on time change is also called when the time is updated in the text field\n        */\n        _onTimeChange: function () {\n            if (!this._defaults.showTimepicker) {\n                return;\n            }\n            var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,\n                minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,\n                second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,\n                millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,\n                microsec = (this.microsec_slider) ? this.control.value(this, this.microsec_slider, 'microsec') : false,\n                timezone = (this.timezone_select) ? this.timezone_select.val() : false,\n                o = this._defaults,\n                pickerTimeFormat = o.pickerTimeFormat || o.timeFormat,\n                pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;\n\n            if (typeof(hour) === 'object') {\n                hour = false;\n            }\n            if (typeof(minute) === 'object') {\n                minute = false;\n            }\n            if (typeof(second) === 'object') {\n                second = false;\n            }\n            if (typeof(millisec) === 'object') {\n                millisec = false;\n            }\n            if (typeof(microsec) === 'object') {\n                microsec = false;\n            }\n            if (typeof(timezone) === 'object') {\n                timezone = false;\n            }\n\n            if (hour !== false) {\n                hour = parseInt(hour, 10);\n            }\n            if (minute !== false) {\n                minute = parseInt(minute, 10);\n            }\n            if (second !== false) {\n                second = parseInt(second, 10);\n            }\n            if (millisec !== false) {\n                millisec = parseInt(millisec, 10);\n            }\n            if (microsec !== false) {\n                microsec = parseInt(microsec, 10);\n            }\n            if (timezone !== false) {\n                timezone = timezone.toString();\n            }\n\n            var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];\n\n            // If the update was done in the input field, the input field should not be updated.\n            // If the update was done using the sliders, update the input field.\n            var hasChanged = (\n                hour !== parseInt(this.hour,10) || // sliders should all be numeric\n                minute !== parseInt(this.minute,10) ||\n                second !== parseInt(this.second,10) ||\n                millisec !== parseInt(this.millisec,10) ||\n                microsec !== parseInt(this.microsec,10) ||\n                (this.ampm.length > 0 && (hour < 12) !== ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) ||\n                (this.timezone !== null && timezone !== this.timezone.toString()) // could be numeric or \"EST\" format, so use toString()\n            );\n\n            if (hasChanged) {\n\n                if (hour !== false) {\n                    this.hour = hour;\n                }\n                if (minute !== false) {\n                    this.minute = minute;\n                }\n                if (second !== false) {\n                    this.second = second;\n                }\n                if (millisec !== false) {\n                    this.millisec = millisec;\n                }\n                if (microsec !== false) {\n                    this.microsec = microsec;\n                }\n                if (timezone !== false) {\n                    this.timezone = timezone;\n                }\n\n                if (!this.inst) {\n                    this.inst = $.datepicker._getInst(this.$input[0]);\n                }\n\n                this._limitMinMaxDateTime(this.inst, true);\n            }\n            if (this.support.ampm) {\n                this.ampm = ampm;\n            }\n\n            // Updates the time within the timepicker\n            this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);\n            if (this.$timeObj) {\n                if (pickerTimeFormat === o.timeFormat) {\n                    this.$timeObj.val(this.formattedTime + pickerTimeSuffix);\n                }\n                else {\n                    this.$timeObj.val($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);\n                }\n                if (this.$timeObj[0].setSelectionRange) {\n                    var sPos = this.$timeObj[0].selectionStart;\n                    var ePos = this.$timeObj[0].selectionEnd;\n                    this.$timeObj[0].setSelectionRange(sPos, ePos);\n                }\n            }\n\n            this.timeDefined = true;\n            if (hasChanged) {\n                this._updateDateTime();\n                //this.$input.focus(); // may automatically open the picker on setDate\n            }\n        },\n\n        /*\n        * call custom onSelect.\n        * bind to sliders slidestop, and grid click.\n        */\n        _onSelectHandler: function () {\n            var onSelect = this._defaults.onSelect || this.inst.settings.onSelect;\n            var inputEl = this.$input ? this.$input[0] : null;\n            if (onSelect && inputEl) {\n                onSelect.apply(inputEl, [this.formattedDateTime, this]);\n            }\n        },\n\n        /*\n        * update our input with the new date time..\n        */\n        _updateDateTime: function (dp_inst) {\n            dp_inst = this.inst || dp_inst;\n            var dtTmp = (dp_inst.currentYear > 0?\n                new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay) :\n                new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),\n                dt = $.datepicker._daylightSavingAdjust(dtTmp),\n                //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),\n                //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay)),\n                dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),\n                formatCfg = $.datepicker._getFormatConfig(dp_inst),\n                timeAvailable = dt !== null && this.timeDefined;\n            this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);\n            var formattedDateTime = this.formattedDate;\n\n            // if a slider was changed but datepicker doesn't have a value yet, set it\n            if (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            /*\n            * remove following lines to force every changes in date picker to change the input value\n            * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker.\n            * If the user manually empty the value in the input field, the date picker will never change selected value.\n            */\n            //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {\n            //\treturn;\n            //}\n\n            if (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === false) {\n                formattedDateTime = this.formattedTime;\n            } else if ((this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) || (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === true)) {\n                formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;\n            }\n\n            this.formattedDateTime = formattedDateTime;\n\n            if (!this._defaults.showTimepicker) {\n                this.$input.val(this.formattedDate);\n            } else if (this.$altInput && this._defaults.timeOnly === false && this._defaults.altFieldTimeOnly === true) {\n                this.$altInput.val(this.formattedTime);\n                this.$input.val(this.formattedDate);\n            } else if (this.$altInput) {\n                this.$input.val(formattedDateTime);\n                var altFormattedDateTime = '',\n                    altSeparator = this._defaults.altSeparator !== null ? this._defaults.altSeparator : this._defaults.separator,\n                    altTimeSuffix = this._defaults.altTimeSuffix !== null ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;\n\n                if (!this._defaults.timeOnly) {\n                    if (this._defaults.altFormat) {\n                        altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);\n                    }\n                    else {\n                        altFormattedDateTime = this.formattedDate;\n                    }\n\n                    if (altFormattedDateTime) {\n                        altFormattedDateTime += altSeparator;\n                    }\n                }\n\n                if (this._defaults.altTimeFormat !== null) {\n                    altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;\n                }\n                else {\n                    altFormattedDateTime += this.formattedTime + altTimeSuffix;\n                }\n                this.$altInput.val(altFormattedDateTime);\n            } else {\n                this.$input.val(formattedDateTime);\n            }\n\n            this.$input.trigger(\"change\");\n        },\n\n        _onFocus: function () {\n            if (!this.$input.val() && this._defaults.defaultValue) {\n                this.$input.val(this._defaults.defaultValue);\n                var inst = $.datepicker._getInst(this.$input.get(0)),\n                    tp_inst = $.datepicker._get(inst, 'timepicker');\n                if (tp_inst) {\n                    if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {\n                        try {\n                            $.datepicker._updateDatepicker(inst);\n                        } catch (err) {\n                            $.timepicker.log(err);\n                        }\n                    }\n                }\n            }\n        },\n\n        /*\n        * Small abstraction to control types\n        * We can add more, just be sure to follow the pattern: create, options, value\n        */\n        _controls: {\n            // slider methods\n            slider: {\n                create: function (tp_inst, obj, unit, val, min, max, step) {\n                    var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60\n                    return obj.prop('slide', null).slider({\n                        orientation: \"horizontal\",\n                        value: rtl ? val * -1 : val,\n                        min: rtl ? max * -1 : min,\n                        max: rtl ? min * -1 : max,\n                        step: step,\n                        slide: function (event, ui) {\n                            tp_inst.control.value(tp_inst, $(this), unit, rtl ? ui.value * -1 : ui.value);\n                            tp_inst._onTimeChange();\n                        },\n                        stop: function (event, ui) {\n                            tp_inst._onSelectHandler();\n                        }\n                    });\n                },\n                options: function (tp_inst, obj, unit, opts, val) {\n                    if (tp_inst._defaults.isRTL) {\n                        if (typeof(opts) === 'string') {\n                            if (opts === 'min' || opts === 'max') {\n                                if (val !== undefined) {\n                                    return obj.slider(opts, val * -1);\n                                }\n                                return Math.abs(obj.slider(opts));\n                            }\n                            return obj.slider(opts);\n                        }\n                        var min = opts.min,\n                            max = opts.max;\n                        opts.min = opts.max = null;\n                        if (min !== undefined) {\n                            opts.max = min * -1;\n                        }\n                        if (max !== undefined) {\n                            opts.min = max * -1;\n                        }\n                        return obj.slider(opts);\n                    }\n                    if (typeof(opts) === 'string' && val !== undefined) {\n                        return obj.slider(opts, val);\n                    }\n                    return obj.slider(opts);\n                },\n                value: function (tp_inst, obj, unit, val) {\n                    if (tp_inst._defaults.isRTL) {\n                        if (val !== undefined) {\n                            return obj.slider('value', val * -1);\n                        }\n                        return Math.abs(obj.slider('value'));\n                    }\n                    if (val !== undefined) {\n                        return obj.slider('value', val);\n                    }\n                    return obj.slider('value');\n                }\n            },\n            // select methods\n            select: {\n                create: function (tp_inst, obj, unit, val, min, max, step) {\n                    var sel = '<select class=\"ui-timepicker-select ui-state-default ui-corner-all\" data-unit=\"' + unit + '\" data-min=\"' + min + '\" data-max=\"' + max + '\" data-step=\"' + step + '\">',\n                        format = tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat;\n\n                    for (var i = min; i <= max; i += step) {\n                        sel += '<option value=\"' + i + '\"' + (i === val ? ' selected' : '') + '>';\n                        if (unit === 'hour') {\n                            sel += $.datepicker.formatTime($.trim(format.replace(/[^ht ]/ig, '')), {hour: i}, tp_inst._defaults);\n                        }\n                        else if (unit === 'millisec' || unit === 'microsec' || i >= 10) { sel += i; }\n                        else {sel += '0' + i.toString(); }\n                        sel += '</option>';\n                    }\n                    sel += '</select>';\n\n                    obj.children('select').remove();\n\n                    $(sel).appendTo(obj).change(function (e) {\n                        tp_inst._onTimeChange();\n                        tp_inst._onSelectHandler();\n                        tp_inst._afterInject();\n                    });\n\n                    return obj;\n                },\n                options: function (tp_inst, obj, unit, opts, val) {\n                    var o = {},\n                        $t = obj.children('select');\n                    if (typeof(opts) === 'string') {\n                        if (val === undefined) {\n                            return $t.data(opts);\n                        }\n                        o[opts] = val;\n                    }\n                    else { o = opts; }\n                    return tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min>=0 ? o.min : $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step'));\n                },\n                value: function (tp_inst, obj, unit, val) {\n                    var $t = obj.children('select');\n                    if (val !== undefined) {\n                        return $t.val(val);\n                    }\n                    return $t.val();\n                }\n            }\n        } // end _controls\n\n    });\n\n    $.fn.extend({\n        /*\n        * shorthand just to use timepicker.\n        */\n        timepicker: function (o) {\n            o = o || {};\n            var tmp_args = Array.prototype.slice.call(arguments);\n\n            if (typeof o === 'object') {\n                tmp_args[0] = $.extend(o, {\n                    timeOnly: true\n                });\n            }\n\n            return $(this).each(function () {\n                $.fn.datetimepicker.apply($(this), tmp_args);\n            });\n        },\n\n        /*\n        * extend timepicker to datepicker\n        */\n        datetimepicker: function (o) {\n            o = o || {};\n            var tmp_args = arguments;\n\n            if (typeof(o) === 'string') {\n                if (o === 'getDate'  || (o === 'option' && tmp_args.length === 2 && typeof (tmp_args[1]) === 'string')) {\n                    return $.fn.datepicker.apply($(this[0]), tmp_args);\n                } else {\n                    return this.each(function () {\n                        var $t = $(this);\n                        $t.datepicker.apply($t, tmp_args);\n                    });\n                }\n            } else {\n                return this.each(function () {\n                    var $t = $(this);\n                    $t.datepicker($.timepicker._newInst($t, o)._defaults);\n                });\n            }\n        }\n    });\n\n    /*\n    * Public Utility to parse date and time\n    */\n    $.datepicker.parseDateTime = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {\n        var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);\n        if (parseRes.timeObj) {\n            var t = parseRes.timeObj;\n            parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);\n            parseRes.date.setMicroseconds(t.microsec);\n        }\n\n        return parseRes.date;\n    };\n\n    /*\n    * Public utility to parse time\n    */\n    $.datepicker.parseTime = function (timeFormat, timeString, options) {\n        var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}),\n            iso8601 = (timeFormat.replace(/\\'.*?\\'/g, '').indexOf('Z') !== -1);\n\n        // Strict parse requires the timeString to match the timeFormat exactly\n        var strictParse = function (f, s, o) {\n\n            // pattern for standard and localized AM/PM markers\n            var getPatternAmpm = function (amNames, pmNames) {\n                var markers = [];\n                if (amNames) {\n                    $.merge(markers, amNames);\n                }\n                if (pmNames) {\n                    $.merge(markers, pmNames);\n                }\n                markers = $.map(markers, function (val) {\n                    return val.replace(/[.*+?|()\\[\\]{}\\\\]/g, '\\\\$&');\n                });\n                return '(' + markers.join('|') + ')?';\n            };\n\n            // figure out position of time elements.. cause js cant do named captures\n            var getFormatPositions = function (timeFormat) {\n                var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),\n                    orders = {\n                        h: -1,\n                        m: -1,\n                        s: -1,\n                        l: -1,\n                        c: -1,\n                        t: -1,\n                        z: -1\n                    };\n\n                if (finds) {\n                    for (var i = 0; i < finds.length; i++) {\n                        if (orders[finds[i].toString().charAt(0)] === -1) {\n                            orders[finds[i].toString().charAt(0)] = i + 1;\n                        }\n                    }\n                }\n                return orders;\n            };\n\n            var regstr = '^' + f.toString()\n                    .replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {\n                        var ml = match.length;\n                        switch (match.charAt(0).toLowerCase()) {\n                            case 'h':\n                                return ml === 1 ? '(\\\\d?\\\\d)' : '(\\\\d{' + ml + '})';\n                            case 'm':\n                                return ml === 1 ? '(\\\\d?\\\\d)' : '(\\\\d{' + ml + '})';\n                            case 's':\n                                return ml === 1 ? '(\\\\d?\\\\d)' : '(\\\\d{' + ml + '})';\n                            case 'l':\n                                return '(\\\\d?\\\\d?\\\\d)';\n                            case 'c':\n                                return '(\\\\d?\\\\d?\\\\d)';\n                            case 'z':\n                                return '(z|[-+]\\\\d\\\\d:?\\\\d\\\\d|\\\\S+)?';\n                            case 't':\n                                return getPatternAmpm(o.amNames, o.pmNames);\n                            default:    // literal escaped in quotes\n                                return '(' + match.replace(/\\'/g, \"\").replace(/(\\.|\\$|\\^|\\\\|\\/|\\(|\\)|\\[|\\]|\\?|\\+|\\*)/g, function (m) { return \"\\\\\" + m; }) + ')?';\n                        }\n                    })\n                    .replace(/\\s/g, '\\\\s?') +\n                o.timeSuffix + '$',\n                order = getFormatPositions(f),\n                ampm = '',\n                treg;\n\n            treg = s.match(new RegExp(regstr, 'i'));\n\n            var resTime = {\n                hour: 0,\n                minute: 0,\n                second: 0,\n                millisec: 0,\n                microsec: 0\n            };\n\n            if (treg) {\n                if (order.t !== -1) {\n                    if (treg[order.t] === undefined || treg[order.t].length === 0) {\n                        ampm = '';\n                        resTime.ampm = '';\n                    } else {\n                        ampm = $.inArray(treg[order.t].toUpperCase(), $.map(o.amNames, function (x,i) { return x.toUpperCase(); })) !== -1 ? 'AM' : 'PM';\n                        resTime.ampm = o[ampm === 'AM' ? 'amNames' : 'pmNames'][0];\n                    }\n                }\n\n                if (order.h !== -1) {\n                    if (ampm === 'AM' && treg[order.h] === '12') {\n                        resTime.hour = 0; // 12am = 0 hour\n                    } else {\n                        if (ampm === 'PM' && treg[order.h] !== '12') {\n                            resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 12\n                        } else {\n                            resTime.hour = Number(treg[order.h]);\n                        }\n                    }\n                }\n\n                if (order.m !== -1) {\n                    resTime.minute = Number(treg[order.m]);\n                }\n                if (order.s !== -1) {\n                    resTime.second = Number(treg[order.s]);\n                }\n                if (order.l !== -1) {\n                    resTime.millisec = Number(treg[order.l]);\n                }\n                if (order.c !== -1) {\n                    resTime.microsec = Number(treg[order.c]);\n                }\n                if (order.z !== -1 && treg[order.z] !== undefined) {\n                    resTime.timezone = $.timepicker.timezoneOffsetNumber(treg[order.z]);\n                }\n\n\n                return resTime;\n            }\n            return false;\n        };// end strictParse\n\n        // First try JS Date, if that fails, use strictParse\n        var looseParse = function (f, s, o) {\n            try {\n                var d = new Date('2012-01-01 ' + s);\n                if (isNaN(d.getTime())) {\n                    d = new Date('2012-01-01T' + s);\n                    if (isNaN(d.getTime())) {\n                        d = new Date('01/01/2012 ' + s);\n                        if (isNaN(d.getTime())) {\n                            throw \"Unable to parse time with native Date: \" + s;\n                        }\n                    }\n                }\n\n                return {\n                    hour: d.getHours(),\n                    minute: d.getMinutes(),\n                    second: d.getSeconds(),\n                    millisec: d.getMilliseconds(),\n                    microsec: d.getMicroseconds(),\n                    timezone: d.getTimezoneOffset() * -1\n                };\n            }\n            catch (err) {\n                try {\n                    return strictParse(f, s, o);\n                }\n                catch (err2) {\n                    $.timepicker.log(\"Unable to parse \\ntimeString: \" + s + \"\\ntimeFormat: \" + f);\n                }\n            }\n            return false;\n        }; // end looseParse\n\n        if (typeof o.parse === \"function\") {\n            return o.parse(timeFormat, timeString, o);\n        }\n        if (o.parse === 'loose') {\n            return looseParse(timeFormat, timeString, o);\n        }\n        return strictParse(timeFormat, timeString, o);\n    };\n\n    /**\n     * Public utility to format the time\n     * @param {string} format format of the time\n     * @param {Object} time Object not a Date for timezones\n     * @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm\n     * @returns {string} the formatted time\n     */\n    $.datepicker.formatTime = function (format, time, options) {\n        options = options || {};\n        options = $.extend({}, $.timepicker._defaults, options);\n        time = $.extend({\n            hour: 0,\n            minute: 0,\n            second: 0,\n            millisec: 0,\n            microsec: 0,\n            timezone: null\n        }, time);\n\n        var tmptime = format,\n            ampmName = options.amNames[0],\n            hour = parseInt(time.hour, 10);\n\n        if (hour > 11) {\n            ampmName = options.pmNames[0];\n        }\n\n        tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {\n            switch (match) {\n                case 'HH':\n                    return ('0' + hour).slice(-2);\n                case 'H':\n                    return hour;\n                case 'hh':\n                    return ('0' + convert24to12(hour)).slice(-2);\n                case 'h':\n                    return convert24to12(hour);\n                case 'mm':\n                    return ('0' + time.minute).slice(-2);\n                case 'm':\n                    return time.minute;\n                case 'ss':\n                    return ('0' + time.second).slice(-2);\n                case 's':\n                    return time.second;\n                case 'l':\n                    return ('00' + time.millisec).slice(-3);\n                case 'c':\n                    return ('00' + time.microsec).slice(-3);\n                case 'z':\n                    return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, false);\n                case 'Z':\n                    return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, true);\n                case 'T':\n                    return ampmName.charAt(0).toUpperCase();\n                case 'TT':\n                    return ampmName.toUpperCase();\n                case 't':\n                    return ampmName.charAt(0).toLowerCase();\n                case 'tt':\n                    return ampmName.toLowerCase();\n                default:\n                    return match.replace(/'/g, \"\");\n            }\n        });\n\n        return tmptime;\n    };\n\n    /*\n    * the bad hack :/ override datepicker so it doesn't close on select\n    // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378\n    */\n    $.datepicker._base_selectDate = $.datepicker._selectDate;\n    $.datepicker._selectDate = function (id, dateStr) {\n        var inst = this._getInst($(id)[0]),\n            tp_inst = this._get(inst, 'timepicker'),\n            was_inline;\n\n        if (tp_inst && inst.settings.showTimepicker) {\n            tp_inst._limitMinMaxDateTime(inst, true);\n            was_inline = inst.inline;\n            inst.inline = inst.stay_open = true;\n            //This way the onSelect handler called from calendarpicker get the full dateTime\n            this._base_selectDate(id, dateStr);\n            inst.inline = was_inline;\n            inst.stay_open = false;\n            this._notifyChange(inst);\n            this._updateDatepicker(inst);\n        } else {\n            this._base_selectDate(id, dateStr);\n        }\n    };\n\n    /*\n    * second bad hack :/ override datepicker so it triggers an event when changing the input field\n    * and does not redraw the datepicker on every selectDate event\n    */\n    $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;\n    $.datepicker._updateDatepicker = function (inst) {\n\n        // don't popup the datepicker if there is another instance already opened\n        var input = inst.input[0];\n        if ($.datepicker._curInst && $.datepicker._curInst !== inst && $.datepicker._datepickerShowing && $.datepicker._lastInput !== input) {\n            return;\n        }\n\n        if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {\n\n            this._base_updateDatepicker(inst);\n\n            // Reload the time control when changing something in the input text field.\n            var tp_inst = this._get(inst, 'timepicker');\n            if (tp_inst) {\n                tp_inst._addTimePicker(inst);\n            }\n        }\n    };\n\n    /*\n    * third bad hack :/ override datepicker so it allows spaces and colon in the input field\n    */\n    $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;\n    $.datepicker._doKeyPress = function (event) {\n        var inst = $.datepicker._getInst(event.target),\n            tp_inst = $.datepicker._get(inst, 'timepicker');\n\n        if (tp_inst) {\n            if ($.datepicker._get(inst, 'constrainInput')) {\n                var ampm = tp_inst.support.ampm,\n                    tz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone,\n                    dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),\n                    datetimeChars = tp_inst._defaults.timeFormat.toString()\n                            .replace(/[hms]/g, '')\n                            .replace(/TT/g, ampm ? 'APM' : '')\n                            .replace(/Tt/g, ampm ? 'AaPpMm' : '')\n                            .replace(/tT/g, ampm ? 'AaPpMm' : '')\n                            .replace(/T/g, ampm ? 'AP' : '')\n                            .replace(/tt/g, ampm ? 'apm' : '')\n                            .replace(/t/g, ampm ? 'ap' : '') +\n                        \" \" + tp_inst._defaults.separator +\n                        tp_inst._defaults.timeSuffix +\n                        (tz ? tp_inst._defaults.timezoneList.join('') : '') +\n                        (tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) +\n                        dateChars,\n                    chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);\n                return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);\n            }\n        }\n\n        return $.datepicker._base_doKeyPress(event);\n    };\n\n    /*\n    * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField\n    * Update any alternate field to synchronise with the main field.\n    */\n    $.datepicker._base_updateAlternate = $.datepicker._updateAlternate;\n    $.datepicker._updateAlternate = function (inst) {\n        var tp_inst = this._get(inst, 'timepicker');\n        if (tp_inst) {\n            var altField = tp_inst._defaults.altField;\n            if (altField) { // update alternate field too\n                var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,\n                    date = this._getDate(inst),\n                    formatCfg = $.datepicker._getFormatConfig(inst),\n                    altFormattedDateTime = '',\n                    altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator,\n                    altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,\n                    altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;\n\n                altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;\n                if (!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null) {\n                    if (tp_inst._defaults.altFormat) {\n                        altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;\n                    }\n                    else {\n                        altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;\n                    }\n                }\n                $(altField).val( inst.input.val() ? altFormattedDateTime : \"\");\n            }\n        }\n        else {\n            $.datepicker._base_updateAlternate(inst);\n        }\n    };\n\n    /*\n    * Override key up event to sync manual input changes.\n    */\n    $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;\n    $.datepicker._doKeyUp = function (event) {\n        var inst = $.datepicker._getInst(event.target),\n            tp_inst = $.datepicker._get(inst, 'timepicker');\n\n        if (tp_inst) {\n            if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {\n                try {\n                    $.datepicker._updateDatepicker(inst);\n                } catch (err) {\n                    $.timepicker.log(err);\n                }\n            }\n        }\n\n        return $.datepicker._base_doKeyUp(event);\n    };\n\n    /*\n    * override \"Today\" button to also grab the time and set it to input field.\n    */\n    $.datepicker._base_gotoToday = $.datepicker._gotoToday;\n    $.datepicker._gotoToday = function (id) {\n        var inst = this._getInst($(id)[0]);\n        this._base_gotoToday(id);\n        var tp_inst = this._get(inst, 'timepicker');\n        if (!tp_inst) {\n            return;\n        }\n\n        var tzoffset = $.timepicker.timezoneOffsetNumber(tp_inst.timezone);\n        var now = new Date();\n        now.setMinutes(now.getMinutes() + now.getTimezoneOffset() + parseInt(tzoffset, 10));\n        this._setTime(inst, now);\n        this._setDate(inst, now);\n        tp_inst._onSelectHandler();\n    };\n\n    /*\n    * Disable & enable the Time in the datetimepicker\n    */\n    $.datepicker._disableTimepickerDatepicker = function (target) {\n        var inst = this._getInst(target);\n        if (!inst) {\n            return;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n        $(target).datepicker('getDate'); // Init selected[Year|Month|Day]\n        if (tp_inst) {\n            inst.settings.showTimepicker = false;\n            tp_inst._defaults.showTimepicker = false;\n            tp_inst._updateDateTime(inst);\n        }\n    };\n\n    $.datepicker._enableTimepickerDatepicker = function (target) {\n        var inst = this._getInst(target);\n        if (!inst) {\n            return;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n        $(target).datepicker('getDate'); // Init selected[Year|Month|Day]\n        if (tp_inst) {\n            inst.settings.showTimepicker = true;\n            tp_inst._defaults.showTimepicker = true;\n            tp_inst._addTimePicker(inst); // Could be disabled on page load\n            tp_inst._updateDateTime(inst);\n        }\n    };\n\n    /*\n    * Create our own set time function\n    */\n    $.datepicker._setTime = function (inst, date) {\n        var tp_inst = this._get(inst, 'timepicker');\n        if (tp_inst) {\n            var defaults = tp_inst._defaults;\n\n            // calling _setTime with no date sets time to defaults\n            tp_inst.hour = date ? date.getHours() : defaults.hour;\n            tp_inst.minute = date ? date.getMinutes() : defaults.minute;\n            tp_inst.second = date ? date.getSeconds() : defaults.second;\n            tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;\n            tp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec;\n\n            //check if within min/max times..\n            tp_inst._limitMinMaxDateTime(inst, true);\n\n            tp_inst._onTimeChange();\n            tp_inst._updateDateTime(inst);\n        }\n    };\n\n    /*\n    * Create new public method to set only time, callable as $().datepicker('setTime', date)\n    */\n    $.datepicker._setTimeDatepicker = function (target, date, withDate) {\n        var inst = this._getInst(target);\n        if (!inst) {\n            return;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n\n        if (tp_inst) {\n            this._setDateFromField(inst);\n            var tp_date;\n            if (date) {\n                if (typeof date === \"string\") {\n                    tp_inst._parseTime(date, withDate);\n                    tp_date = new Date();\n                    tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);\n                    tp_date.setMicroseconds(tp_inst.microsec);\n                } else {\n                    tp_date = new Date(date.getTime());\n                    tp_date.setMicroseconds(date.getMicroseconds());\n                }\n                if (tp_date.toString() === 'Invalid Date') {\n                    tp_date = undefined;\n                }\n                this._setTime(inst, tp_date);\n            }\n        }\n\n    };\n\n    /*\n    * override setDate() to allow setting time too within Date object\n    */\n    $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;\n    $.datepicker._setDateDatepicker = function (target, _date) {\n        var inst = this._getInst(target);\n        var date = _date;\n        if (!inst) {\n            return;\n        }\n\n        if (typeof(_date) === 'string') {\n            date = new Date(_date);\n            if (!date.getTime()) {\n                this._base_setDateDatepicker.apply(this, arguments);\n                date = $(target).datepicker('getDate');\n            }\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n        var tp_date;\n        if (date instanceof Date) {\n            tp_date = new Date(date.getTime());\n            tp_date.setMicroseconds(date.getMicroseconds());\n        } else {\n            tp_date = date;\n        }\n\n        // This is important if you are using the timezone option, javascript's Date\n        // object will only return the timezone offset for the current locale, so we\n        // adjust it accordingly.  If not using timezone option this won't matter..\n        // If a timezone is different in tp, keep the timezone as is\n        if (tp_inst && tp_date) {\n            // look out for DST if tz wasn't specified\n            if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {\n                tp_inst.timezone = tp_date.getTimezoneOffset() * -1;\n            }\n            date = $.timepicker.timezoneAdjust(date, $.timepicker.timezoneOffsetString(-date.getTimezoneOffset()), tp_inst.timezone);\n            tp_date = $.timepicker.timezoneAdjust(tp_date, $.timepicker.timezoneOffsetString(-tp_date.getTimezoneOffset()), tp_inst.timezone);\n        }\n\n        this._updateDatepicker(inst);\n        this._base_setDateDatepicker.apply(this, arguments);\n        this._setTimeDatepicker(target, tp_date, true);\n    };\n\n    /*\n    * override getDate() to allow getting time too within Date object\n    */\n    $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;\n    $.datepicker._getDateDatepicker = function (target, noDefault) {\n        var inst = this._getInst(target);\n        if (!inst) {\n            return;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n\n        if (tp_inst) {\n            // if it hasn't yet been defined, grab from field\n            if (inst.lastVal === undefined) {\n                this._setDateFromField(inst, noDefault);\n            }\n\n            var date = this._getDate(inst);\n\n            var currDT = null;\n\n            if (tp_inst.$altInput && tp_inst._defaults.altFieldTimeOnly) {\n                currDT = tp_inst.$input.val() + ' ' + tp_inst.$altInput.val();\n            }\n            else if (tp_inst.$input.get(0).tagName !== 'INPUT' && tp_inst.$altInput) {\n                /**\n                 * in case the datetimepicker has been applied to a non-input tag for inline UI,\n                 * and the user has not configured the plugin to display only time in altInput,\n                 * pick current date time from the altInput (and hope for the best, for now, until \"ER1\" is applied)\n                 *\n                 * @todo ER1. Since altInput can have a totally difference format, convert it to standard format by reading input format from \"altFormat\" and \"altTimeFormat\" option values\n                 */\n                currDT = tp_inst.$altInput.val();\n            }\n            else {\n                currDT = tp_inst.$input.val();\n            }\n\n            if (date && tp_inst._parseTime(currDT, !inst.settings.timeOnly)) {\n                date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);\n                date.setMicroseconds(tp_inst.microsec);\n\n                // This is important if you are using the timezone option, javascript's Date\n                // object will only return the timezone offset for the current locale, so we\n                // adjust it accordingly.  If not using timezone option this won't matter..\n                if (tp_inst.timezone != null) {\n                    // look out for DST if tz wasn't specified\n                    if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {\n                        tp_inst.timezone = date.getTimezoneOffset() * -1;\n                    }\n                    date = $.timepicker.timezoneAdjust(date, tp_inst.timezone, $.timepicker.timezoneOffsetString(-date.getTimezoneOffset()));\n                }\n            }\n            return date;\n        }\n        return this._base_getDateDatepicker(target, noDefault);\n    };\n\n    /*\n    * override parseDate() because UI 1.8.14 throws an error about \"Extra characters\"\n    * An option in datapicker to ignore extra format characters would be nicer.\n    */\n    $.datepicker._base_parseDate = $.datepicker.parseDate;\n    $.datepicker.parseDate = function (format, value, settings) {\n        var date;\n        try {\n            date = this._base_parseDate(format, value, settings);\n        } catch (err) {\n            // Hack!  The error message ends with a colon, a space, and\n            // the \"extra\" characters.  We rely on that instead of\n            // attempting to perfectly reproduce the parsing algorithm.\n            if (err.indexOf(\":\") >= 0) {\n                date = this._base_parseDate(format, value.substring(0, value.length - (err.length - err.indexOf(':') - 2)), settings);\n                $.timepicker.log(\"Error parsing the date string: \" + err + \"\\ndate string = \" + value + \"\\ndate format = \" + format);\n            } else {\n                throw err;\n            }\n        }\n        return date;\n    };\n\n    /*\n    * override formatDate to set date with time to the input\n    */\n    $.datepicker._base_formatDate = $.datepicker._formatDate;\n    $.datepicker._formatDate = function (inst, day, month, year) {\n        var tp_inst = this._get(inst, 'timepicker');\n        if (tp_inst) {\n            tp_inst._updateDateTime(inst);\n            return tp_inst.$input.val();\n        }\n        return this._base_formatDate(inst);\n    };\n\n    /*\n    * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate\n    */\n    $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;\n    $.datepicker._optionDatepicker = function (target, name, value) {\n        var inst = this._getInst(target),\n            name_clone;\n        if (!inst) {\n            return null;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n        if (tp_inst) {\n            var min = null,\n                max = null,\n                onselect = null,\n                overrides = tp_inst._defaults.evnts,\n                fns = {},\n                prop,\n                ret,\n                oldVal,\n                $target;\n            if (typeof name === 'string') { // if min/max was set with the string\n                if (name === 'minDate' || name === 'minDateTime') {\n                    min = value;\n                } else if (name === 'maxDate' || name === 'maxDateTime') {\n                    max = value;\n                } else if (name === 'onSelect') {\n                    onselect = value;\n                } else if (overrides.hasOwnProperty(name)) {\n                    if (typeof (value) === 'undefined') {\n                        return overrides[name];\n                    }\n                    fns[name] = value;\n                    name_clone = {}; //empty results in exiting function after overrides updated\n                }\n            } else if (typeof name === 'object') { //if min/max was set with the JSON\n                if (name.minDate) {\n                    min = name.minDate;\n                } else if (name.minDateTime) {\n                    min = name.minDateTime;\n                } else if (name.maxDate) {\n                    max = name.maxDate;\n                } else if (name.maxDateTime) {\n                    max = name.maxDateTime;\n                }\n                for (prop in overrides) {\n                    if (overrides.hasOwnProperty(prop) && name[prop]) {\n                        fns[prop] = name[prop];\n                    }\n                }\n            }\n            for (prop in fns) {\n                if (fns.hasOwnProperty(prop)) {\n                    overrides[prop] = fns[prop];\n                    if (!name_clone) { name_clone = $.extend({}, name); }\n                    delete name_clone[prop];\n                }\n            }\n            if (name_clone && isEmptyObject(name_clone)) { return; }\n            if (min) { //if min was set\n                if (min === 0) {\n                    min = new Date();\n                } else {\n                    min = new Date(min);\n                }\n                tp_inst._defaults.minDate = min;\n                tp_inst._defaults.minDateTime = min;\n            } else if (max) { //if max was set\n                if (max === 0) {\n                    max = new Date();\n                } else {\n                    max = new Date(max);\n                }\n                tp_inst._defaults.maxDate = max;\n                tp_inst._defaults.maxDateTime = max;\n            } else if (onselect) {\n                tp_inst._defaults.onSelect = onselect;\n            }\n\n            // Datepicker will override our date when we call _base_optionDatepicker when\n            // calling minDate/maxDate, so we will first grab the value, call\n            // _base_optionDatepicker, then set our value back.\n            if(min || max){\n                $target = $(target);\n                oldVal = $target.datetimepicker('getDate');\n                ret = this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);\n                $target.datetimepicker('setDate', oldVal);\n                return ret;\n            }\n        }\n        if (value === undefined) {\n            return this._base_optionDatepicker.call($.datepicker, target, name);\n        }\n        return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);\n    };\n\n    /*\n    * jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,\n    * it will return false for all objects\n    */\n    var isEmptyObject = function (obj) {\n        var prop;\n        for (prop in obj) {\n            if (obj.hasOwnProperty(prop)) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    /*\n    * jQuery extend now ignores nulls!\n    */\n    var extendRemove = function (target, props) {\n        $.extend(target, props);\n        for (var name in props) {\n            if (props[name] === null || props[name] === undefined) {\n                target[name] = props[name];\n            }\n        }\n        return target;\n    };\n\n    /*\n    * Determine by the time format which units are supported\n    * Returns an object of booleans for each unit\n    */\n    var detectSupport = function (timeFormat) {\n        var tf = timeFormat.replace(/'.*?'/g, '').toLowerCase(), // removes literals\n            isIn = function (f, t) { // does the format contain the token?\n                return f.indexOf(t) !== -1 ? true : false;\n            };\n        return {\n            hour: isIn(tf, 'h'),\n            minute: isIn(tf, 'm'),\n            second: isIn(tf, 's'),\n            millisec: isIn(tf, 'l'),\n            microsec: isIn(tf, 'c'),\n            timezone: isIn(tf, 'z'),\n            ampm: isIn(tf, 't') && isIn(timeFormat, 'h'),\n            iso8601: isIn(timeFormat, 'Z')\n        };\n    };\n\n    /*\n    * Converts 24 hour format into 12 hour\n    * Returns 12 hour without leading 0\n    */\n    var convert24to12 = function (hour) {\n        hour %= 12;\n\n        if (hour === 0) {\n            hour = 12;\n        }\n\n        return String(hour);\n    };\n\n    var computeEffectiveSetting = function (settings, property) {\n        return settings && settings[property] ? settings[property] : $.timepicker._defaults[property];\n    };\n\n    /*\n    * Splits datetime string into date and time substrings.\n    * Throws exception when date can't be parsed\n    * Returns {dateString: dateString, timeString: timeString}\n    */\n    var splitDateTime = function (dateTimeString, timeSettings) {\n        // The idea is to get the number separator occurrences in datetime and the time format requested (since time has\n        // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.\n        var separator = computeEffectiveSetting(timeSettings, 'separator'),\n            format = computeEffectiveSetting(timeSettings, 'timeFormat'),\n            timeParts = format.split(separator), // how many occurrences of separator may be in our format?\n            timePartsLen = timeParts.length,\n            allParts = dateTimeString.split(separator),\n            allPartsLen = allParts.length;\n\n        if (allPartsLen > 1) {\n            return {\n                dateString: allParts.splice(0, allPartsLen - timePartsLen).join(separator),\n                timeString: allParts.splice(0, timePartsLen).join(separator)\n            };\n        }\n\n        return {\n            dateString: dateTimeString,\n            timeString: ''\n        };\n    };\n\n    /*\n    * Internal function to parse datetime interval\n    * Returns: {date: Date, timeObj: Object}, where\n    *   date - parsed date without time (type Date)\n    *   timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional\n    */\n    var parseDateTimeInternal = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {\n        var date,\n            parts,\n            parsedTime;\n\n        parts = splitDateTime(dateTimeString, timeSettings);\n        date = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings);\n\n        if (parts.timeString === '') {\n            return {\n                date: date\n            };\n        }\n\n        parsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings);\n\n        if (!parsedTime) {\n            throw 'Wrong time format';\n        }\n\n        return {\n            date: date,\n            timeObj: parsedTime\n        };\n    };\n\n    /*\n    * Internal function to set timezone_select to the local timezone\n    */\n    var selectLocalTimezone = function (tp_inst, date) {\n        if (tp_inst && tp_inst.timezone_select) {\n            var now = date || new Date();\n            tp_inst.timezone_select.val(-now.getTimezoneOffset());\n        }\n    };\n\n    /*\n    * Create a Singleton Instance\n    */\n    $.timepicker = new Timepicker();\n\n    /**\n     * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)\n     * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned\n     * @param {boolean} iso8601 if true formats in accordance to iso8601 \"+12:45\"\n     * @return {string}\n     */\n    $.timepicker.timezoneOffsetString = function (tzMinutes, iso8601) {\n        if (isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720) {\n            return tzMinutes;\n        }\n\n        var off = tzMinutes,\n            minutes = off % 60,\n            hours = (off - minutes) / 60,\n            iso = iso8601 ? ':' : '',\n            tz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2);\n\n        if (tz === '+00:00') {\n            return 'Z';\n        }\n        return tz;\n    };\n\n    /**\n     * Get the number in minutes that represents a timezone string\n     * @param  {string} tzString formatted like \"+0500\", \"-1245\", \"Z\"\n     * @return {number} the offset minutes or the original string if it doesn't match expectations\n     */\n    $.timepicker.timezoneOffsetNumber = function (tzString) {\n        var normalized = tzString.toString().replace(':', ''); // excuse any iso8601, end up with \"+1245\"\n\n        if (normalized.toUpperCase() === 'Z') { // if iso8601 with Z, its 0 minute offset\n            return 0;\n        }\n\n        if (!/^(\\-|\\+)\\d{4}$/.test(normalized)) { // possibly a user defined tz, so just give it back\n            return parseInt(tzString, 10);\n        }\n\n        return ((normalized.substr(0, 1) === '-' ? -1 : 1) * // plus or minus\n            ((parseInt(normalized.substr(1, 2), 10) * 60) + // hours (converted to minutes)\n                parseInt(normalized.substr(3, 2), 10))); // minutes\n    };\n\n    /**\n     * No way to set timezone in js Date, so we must adjust the minutes to compensate. (think setDate, getDate)\n     * @param  {Date} date\n     * @param  {string} fromTimezone formatted like \"+0500\", \"-1245\"\n     * @param  {string} toTimezone formatted like \"+0500\", \"-1245\"\n     * @return {Date}\n     */\n    $.timepicker.timezoneAdjust = function (date, fromTimezone, toTimezone) {\n        var fromTz = $.timepicker.timezoneOffsetNumber(fromTimezone);\n        var toTz = $.timepicker.timezoneOffsetNumber(toTimezone);\n        if (!isNaN(toTz)) {\n            date.setMinutes(date.getMinutes() + (-fromTz) - (-toTz));\n        }\n        return date;\n    };\n\n    /**\n     * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to\n     * enforce date range limits.\n     * n.b. The input value must be correctly formatted (reformatting is not supported)\n     * @param  {Element} startTime\n     * @param  {Element} endTime\n     * @param  {Object} options Options for the timepicker() call\n     * @return {jQuery}\n     */\n    $.timepicker.timeRange = function (startTime, endTime, options) {\n        return $.timepicker.handleRange('timepicker', startTime, endTime, options);\n    };\n\n    /**\n     * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to\n     * enforce date range limits.\n     * @param  {Element} startTime\n     * @param  {Element} endTime\n     * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,\n     *   a boolean value that can be used to reformat the input values to the `dateFormat`.\n     * @param  {string} method Can be used to specify the type of picker to be added\n     * @return {jQuery}\n     */\n    $.timepicker.datetimeRange = function (startTime, endTime, options) {\n        $.timepicker.handleRange('datetimepicker', startTime, endTime, options);\n    };\n\n    /**\n     * Calls `datepicker` on the `startTime` and `endTime` elements, and configures them to\n     * enforce date range limits.\n     * @param  {Element} startTime\n     * @param  {Element} endTime\n     * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,\n     *   a boolean value that can be used to reformat the input values to the `dateFormat`.\n     * @return {jQuery}\n     */\n    $.timepicker.dateRange = function (startTime, endTime, options) {\n        $.timepicker.handleRange('datepicker', startTime, endTime, options);\n    };\n\n    /**\n     * Calls `method` on the `startTime` and `endTime` elements, and configures them to\n     * enforce date range limits.\n     * @param  {string} method Can be used to specify the type of picker to be added\n     * @param  {Element} startTime\n     * @param  {Element} endTime\n     * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,\n     *   a boolean value that can be used to reformat the input values to the `dateFormat`.\n     * @return {jQuery}\n     */\n    $.timepicker.handleRange = function (method, startTime, endTime, options) {\n        options = $.extend({}, {\n            minInterval: 0, // min allowed interval in milliseconds\n            maxInterval: 0, // max allowed interval in milliseconds\n            start: {},      // options for start picker\n            end: {}         // options for end picker\n        }, options);\n\n        // for the mean time this fixes an issue with calling getDate with timepicker()\n        var timeOnly = false;\n        if(method === 'timepicker'){\n            timeOnly = true;\n            method = 'datetimepicker';\n        }\n\n        function checkDates(changed, other) {\n            var startdt = startTime[method]('getDate'),\n                enddt = endTime[method]('getDate'),\n                changeddt = changed[method]('getDate');\n\n            if (startdt !== null) {\n                var minDate = new Date(startdt.getTime()),\n                    maxDate = new Date(startdt.getTime());\n\n                minDate.setMilliseconds(minDate.getMilliseconds() + options.minInterval);\n                maxDate.setMilliseconds(maxDate.getMilliseconds() + options.maxInterval);\n\n                if (options.minInterval > 0 && minDate > enddt) { // minInterval check\n                    endTime[method]('setDate', minDate);\n                }\n                else if (options.maxInterval > 0 && maxDate < enddt) { // max interval check\n                    endTime[method]('setDate', maxDate);\n                }\n                else if (startdt > enddt) {\n                    other[method]('setDate', changeddt);\n                }\n            }\n        }\n\n        function selected(changed, other, option) {\n            if (!changed.val()) {\n                return;\n            }\n            var date = changed[method].call(changed, 'getDate');\n            if (date !== null && options.minInterval > 0) {\n                if (option === 'minDate') {\n                    date.setMilliseconds(date.getMilliseconds() + options.minInterval);\n                }\n                if (option === 'maxDate') {\n                    date.setMilliseconds(date.getMilliseconds() - options.minInterval);\n                }\n            }\n\n            if (date.getTime) {\n                other[method].call(other, 'option', option, date);\n            }\n        }\n\n        $.fn[method].call(startTime, $.extend({\n            timeOnly: timeOnly,\n            onClose: function (dateText, inst) {\n                checkDates($(this), endTime);\n            },\n            onSelect: function (selectedDateTime) {\n                selected($(this), endTime, 'minDate');\n            }\n        }, options, options.start));\n        $.fn[method].call(endTime, $.extend({\n            timeOnly: timeOnly,\n            onClose: function (dateText, inst) {\n                checkDates($(this), startTime);\n            },\n            onSelect: function (selectedDateTime) {\n                selected($(this), startTime, 'maxDate');\n            }\n        }, options, options.end));\n\n        checkDates(startTime, endTime);\n\n        selected(startTime, endTime, 'minDate');\n        selected(endTime, startTime, 'maxDate');\n\n        return $([startTime.get(0), endTime.get(0)]);\n    };\n\n    /**\n     * Log error or data to the console during error or debugging\n     * @param  {Object} err pass any type object to log to the console during error or debugging\n     * @return {void}\n     */\n    $.timepicker.log = function () {\n        // Older IE (9, maybe 10) throw error on accessing `window.console.log.apply`, so check first.\n        if (window.console && window.console.log && window.console.log.apply) {\n            window.console.log.apply(window.console, Array.prototype.slice.call(arguments));\n        }\n    };\n\n    /*\n     * Add util object to allow access to private methods for testability.\n     */\n    $.timepicker._util = {\n        _extendRemove: extendRemove,\n        _isEmptyObject: isEmptyObject,\n        _convert24to12: convert24to12,\n        _detectSupport: detectSupport,\n        _selectLocalTimezone: selectLocalTimezone,\n        _computeEffectiveSetting: computeEffectiveSetting,\n        _splitDateTime: splitDateTime,\n        _parseDateTimeInternal: parseDateTimeInternal\n    };\n\n    /*\n    * Microsecond support\n    */\n    if (!Date.prototype.getMicroseconds) {\n        Date.prototype.microseconds = 0;\n        Date.prototype.getMicroseconds = function () { return this.microseconds; };\n        Date.prototype.setMicroseconds = function (m) {\n            this.setMilliseconds(this.getMilliseconds() + Math.floor(m / 1000));\n            this.microseconds = m % 1000;\n            return this;\n        };\n    }\n\n    /*\n    * Keep up with the version\n    */\n    $.timepicker.version = \"1.6.3\";\n\n}));\n","jquery/jquery-ui-timepicker-addon.js":"/*! jQuery Timepicker Addon - v1.6.3 - 2016-04-20\n* http://trentrichardson.com/examples/timepicker\n* Copyright (c) 2016 Trent Richardson; Licensed MIT */\n(function (factory) {\n    if (typeof define === 'function' && define.amd) {\n        define(['jquery', 'jquery/ui'], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($) {\n\n    /*\n    * Lets not redefine timepicker, Prevent \"Uncaught RangeError: Maximum call stack size exceeded\"\n    */\n    $.ui.timepicker = $.ui.timepicker || {};\n    if ($.ui.timepicker.version) {\n        return;\n    }\n\n    /*\n    * Extend jQueryUI, get it started with our version number\n    */\n    $.extend($.ui, {\n        timepicker: {\n            version: \"1.6.3\"\n        }\n    });\n\n    /*\n    * Timepicker manager.\n    * Use the singleton instance of this class, $.timepicker, to interact with the time picker.\n    * Settings for (groups of) time pickers are maintained in an instance object,\n    * allowing multiple different settings on the same page.\n    */\n    var Timepicker = function () {\n        this.regional = []; // Available regional settings, indexed by language code\n        this.regional[''] = { // Default regional settings\n            currentText: 'Now',\n            closeText: 'Done',\n            amNames: ['AM', 'A'],\n            pmNames: ['PM', 'P'],\n            timeFormat: 'HH:mm',\n            timeSuffix: '',\n            timeOnlyTitle: 'Choose Time',\n            timeText: 'Time',\n            hourText: 'Hour',\n            minuteText: 'Minute',\n            secondText: 'Second',\n            millisecText: 'Millisecond',\n            microsecText: 'Microsecond',\n            timezoneText: 'Time Zone',\n            isRTL: false\n        };\n        this._defaults = { // Global defaults for all the datetime picker instances\n            showButtonPanel: true,\n            timeOnly: false,\n            timeOnlyShowDate: false,\n            showHour: null,\n            showMinute: null,\n            showSecond: null,\n            showMillisec: null,\n            showMicrosec: null,\n            showTimezone: null,\n            showTime: true,\n            stepHour: 1,\n            stepMinute: 1,\n            stepSecond: 1,\n            stepMillisec: 1,\n            stepMicrosec: 1,\n            hour: 0,\n            minute: 0,\n            second: 0,\n            millisec: 0,\n            microsec: 0,\n            timezone: null,\n            hourMin: 0,\n            minuteMin: 0,\n            secondMin: 0,\n            millisecMin: 0,\n            microsecMin: 0,\n            hourMax: 23,\n            minuteMax: 59,\n            secondMax: 59,\n            millisecMax: 999,\n            microsecMax: 999,\n            minDateTime: null,\n            maxDateTime: null,\n            maxTime: null,\n            minTime: null,\n            onSelect: null,\n            hourGrid: 0,\n            minuteGrid: 0,\n            secondGrid: 0,\n            millisecGrid: 0,\n            microsecGrid: 0,\n            alwaysSetTime: true,\n            separator: ' ',\n            altFieldTimeOnly: true,\n            altTimeFormat: null,\n            altSeparator: null,\n            altTimeSuffix: null,\n            altRedirectFocus: true,\n            pickerTimeFormat: null,\n            pickerTimeSuffix: null,\n            showTimepicker: true,\n            timezoneList: null,\n            addSliderAccess: false,\n            sliderAccessArgs: null,\n            controlType: 'slider',\n            oneLine: false,\n            defaultValue: null,\n            parse: 'strict',\n            afterInject: null\n        };\n        $.extend(this._defaults, this.regional['']);\n    };\n\n    $.extend(Timepicker.prototype, {\n        $input: null,\n        $altInput: null,\n        $timeObj: null,\n        inst: null,\n        hour_slider: null,\n        minute_slider: null,\n        second_slider: null,\n        millisec_slider: null,\n        microsec_slider: null,\n        timezone_select: null,\n        maxTime: null,\n        minTime: null,\n        hour: 0,\n        minute: 0,\n        second: 0,\n        millisec: 0,\n        microsec: 0,\n        timezone: null,\n        hourMinOriginal: null,\n        minuteMinOriginal: null,\n        secondMinOriginal: null,\n        millisecMinOriginal: null,\n        microsecMinOriginal: null,\n        hourMaxOriginal: null,\n        minuteMaxOriginal: null,\n        secondMaxOriginal: null,\n        millisecMaxOriginal: null,\n        microsecMaxOriginal: null,\n        ampm: '',\n        formattedDate: '',\n        formattedTime: '',\n        formattedDateTime: '',\n        timezoneList: null,\n        units: ['hour', 'minute', 'second', 'millisec', 'microsec'],\n        support: {},\n        control: null,\n\n        /*\n        * Override the default settings for all instances of the time picker.\n        * @param  {Object} settings  object - the new settings to use as defaults (anonymous object)\n        * @return {Object} the manager object\n        */\n        setDefaults: function (settings) {\n            extendRemove(this._defaults, settings || {});\n            return this;\n        },\n\n        /*\n        * Create a new Timepicker instance\n        */\n        _newInst: function ($input, opts) {\n            var tp_inst = new Timepicker(),\n                inlineSettings = {},\n                fns = {},\n                overrides, i;\n\n            for (var attrName in this._defaults) {\n                if (this._defaults.hasOwnProperty(attrName)) {\n                    var attrValue = $input.attr('time:' + attrName);\n                    if (attrValue) {\n                        try {\n                            inlineSettings[attrName] = eval(attrValue);\n                        } catch (err) {\n                            inlineSettings[attrName] = attrValue;\n                        }\n                    }\n                }\n            }\n\n            overrides = {\n                beforeShow: function (input, dp_inst) {\n                    if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {\n                        return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);\n                    }\n                },\n                onChangeMonthYear: function (year, month, dp_inst) {\n                    // Update the time as well : this prevents the time from disappearing from the $input field.\n                    // tp_inst._updateDateTime(dp_inst);\n                    if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {\n                        tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);\n                    }\n                },\n                onClose: function (dateText, dp_inst) {\n                    if (tp_inst.timeDefined === true && $input.val() !== '') {\n                        tp_inst._updateDateTime(dp_inst);\n                    }\n                    if ($.isFunction(tp_inst._defaults.evnts.onClose)) {\n                        tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);\n                    }\n                }\n            };\n            for (i in overrides) {\n                if (overrides.hasOwnProperty(i)) {\n                    fns[i] = opts[i] || this._defaults[i] || null;\n                }\n            }\n\n            tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, opts, overrides, {\n                evnts: fns,\n                timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');\n            });\n            tp_inst.amNames = $.map(tp_inst._defaults.amNames, function (val) {\n                return val.toUpperCase();\n            });\n            tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function (val) {\n                return val.toUpperCase();\n            });\n\n            // detect which units are supported\n            tp_inst.support = detectSupport(\n                tp_inst._defaults.timeFormat +\n                (tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') +\n                (tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : ''));\n\n            // controlType is string - key to our this._controls\n            if (typeof(tp_inst._defaults.controlType) === 'string') {\n                if (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') {\n                    tp_inst._defaults.controlType = 'select';\n                }\n                tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];\n            }\n            // controlType is an object and must implement create, options, value methods\n            else {\n                tp_inst.control = tp_inst._defaults.controlType;\n            }\n\n            // prep the timezone options\n            var timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60,\n                0, 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            if (tp_inst._defaults.timezoneList !== null) {\n                timezoneList = tp_inst._defaults.timezoneList;\n            }\n            var tzl = timezoneList.length, tzi = 0, tzv = null;\n            if (tzl > 0 && typeof timezoneList[0] !== 'object') {\n                for (; tzi < tzl; tzi++) {\n                    tzv = timezoneList[tzi];\n                    timezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) };\n                }\n            }\n            tp_inst._defaults.timezoneList = timezoneList;\n\n            // set the default units\n            tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) :\n                ((new Date()).getTimezoneOffset() * -1);\n            tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin :\n                tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour;\n            tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin :\n                tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute;\n            tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin :\n                tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second;\n            tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin :\n                tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec;\n            tp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin :\n                tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec;\n            tp_inst.ampm = '';\n            tp_inst.$input = $input;\n\n            if (tp_inst._defaults.altField) {\n                tp_inst.$altInput = $(tp_inst._defaults.altField);\n                if (tp_inst._defaults.altRedirectFocus === true) {\n                    tp_inst.$altInput.css({\n                        cursor: 'pointer'\n                    }).focus(function () {\n                        $input.trigger(\"focus\");\n                    });\n                }\n            }\n\n            if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {\n                tp_inst._defaults.minDate = new Date();\n            }\n            if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {\n                tp_inst._defaults.maxDate = new Date();\n            }\n\n            // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..\n            if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {\n                tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());\n            }\n            if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {\n                tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());\n            }\n            if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {\n                tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());\n            }\n            if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {\n                tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());\n            }\n            tp_inst.$input.bind('focus', function () {\n                tp_inst._onFocus();\n            });\n\n            return tp_inst;\n        },\n\n        /*\n        * add our sliders to the calendar\n        */\n        _addTimePicker: function (dp_inst) {\n            var currDT = $.trim((this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val());\n\n            this.timeDefined = this._parseTime(currDT);\n            this._limitMinMaxDateTime(dp_inst, false);\n            this._injectTimePicker();\n            this._afterInject();\n        },\n\n        /*\n        * parse the time string from input value or _setTime\n        */\n        _parseTime: function (timeString, withDate) {\n            if (!this.inst) {\n                this.inst = $.datepicker._getInst(this.$input[0]);\n            }\n\n            if (withDate || !this._defaults.timeOnly) {\n                var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');\n                try {\n                    var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);\n                    if (!parseRes.timeObj) {\n                        return false;\n                    }\n                    $.extend(this, parseRes.timeObj);\n                } catch (err) {\n                    $.timepicker.log(\"Error parsing the date/time string: \" + err +\n                        \"\\ndate/time string = \" + timeString +\n                        \"\\ntimeFormat = \" + this._defaults.timeFormat +\n                        \"\\ndateFormat = \" + dp_dateFormat);\n                    return false;\n                }\n                return true;\n            } else {\n                var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);\n                if (!timeObj) {\n                    return false;\n                }\n                $.extend(this, timeObj);\n                return true;\n            }\n        },\n\n        /*\n        * Handle callback option after injecting timepicker\n        */\n        _afterInject: function() {\n            var o = this.inst.settings;\n            if ($.isFunction(o.afterInject)) {\n                o.afterInject.call(this);\n            }\n        },\n\n        /*\n        * generate and inject html for timepicker into ui datepicker\n        */\n        _injectTimePicker: function () {\n            var $dp = this.inst.dpDiv,\n                o = this.inst.settings,\n                tp_inst = this,\n                litem = '',\n                uitem = '',\n                show = null,\n                max = {},\n                gridSize = {},\n                size = null,\n                i = 0,\n                l = 0;\n\n            // Prevent displaying twice\n            if ($dp.find(\"div.ui-timepicker-div\").length === 0 && o.showTimepicker) {\n                var noDisplay = ' ui_tpicker_unit_hide',\n                    html = '<div class=\"ui-timepicker-div' + (o.isRTL ? ' ui-timepicker-rtl' : '') + (o.oneLine && o.controlType === 'select' ? ' ui-timepicker-oneLine' : '') + '\"><dl>' + '<dt class=\"ui_tpicker_time_label' + ((o.showTime) ? '' : noDisplay) + '\">' + o.timeText + '</dt>' +\n                        '<dd class=\"ui_tpicker_time '+ ((o.showTime) ? '' : noDisplay) + '\"><input class=\"ui_tpicker_time_input\" ' + (o.timeInput ? '' : 'disabled') + '/></dd>';\n\n                // Create the markup\n                for (i = 0, l = this.units.length; i < l; i++) {\n                    litem = this.units[i];\n                    uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);\n                    show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];\n\n                    // Added by Peter Medeiros:\n                    // - Figure out what the hour/minute/second max should be based on the step values.\n                    // - Example: if stepMinute is 15, then minMax is 45.\n                    max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10);\n                    gridSize[litem] = 0;\n\n                    html += '<dt class=\"ui_tpicker_' + litem + '_label' + (show ? '' : noDisplay) + '\">' + o[litem + 'Text'] + '</dt>' +\n                        '<dd class=\"ui_tpicker_' + litem + (show ? '' : noDisplay) + '\"><div class=\"ui_tpicker_' + litem + '_slider' + (show ? '' : noDisplay) + '\"></div>';\n\n                    if (show && o[litem + 'Grid'] > 0) {\n                        html += '<div style=\"padding-left: 1px\"><table class=\"ui-tpicker-grid-label\"><tr>';\n\n                        if (litem === 'hour') {\n                            for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) {\n                                gridSize[litem]++;\n                                var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o);\n                                html += '<td data-for=\"' + litem + '\">' + tmph + '</td>';\n                            }\n                        }\n                        else {\n                            for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) {\n                                gridSize[litem]++;\n                                html += '<td data-for=\"' + litem + '\">' + ((m < 10) ? '0' : '') + m + '</td>';\n                            }\n                        }\n\n                        html += '</tr></table></div>';\n                    }\n                    html += '</dd>';\n                }\n\n                // Timezone\n                var showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone;\n                html += '<dt class=\"ui_tpicker_timezone_label' + (showTz ? '' : noDisplay) + '\">' + o.timezoneText + '</dt>';\n                html += '<dd class=\"ui_tpicker_timezone' + (showTz ? '' : noDisplay) + '\"></dd>';\n\n                // Create the elements from string\n                html += '</dl></div>';\n                var $tp = $(html);\n\n                // if we only want time picker...\n                if (o.timeOnly === true) {\n                    $tp.prepend('<div class=\"ui-widget-header ui-helper-clearfix ui-corner-all\">' + '<div class=\"ui-datepicker-title\">' + o.timeOnlyTitle + '</div>' + '</div>');\n                    $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();\n                }\n\n                // add sliders, adjust grids, add events\n                for (i = 0, l = tp_inst.units.length; i < l; i++) {\n                    litem = tp_inst.units[i];\n                    uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);\n                    show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];\n\n                    // add the slider\n                    tp_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                    // adjust the grid and add click event\n                    if (show && o[litem + 'Grid'] > 0) {\n                        size = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']);\n                        $tp.find('.ui_tpicker_' + litem + ' table').css({\n                            width: size + \"%\",\n                            marginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + \"%\"),\n                            marginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + \"%\") : '0',\n                            borderCollapse: 'collapse'\n                        }).find(\"td\").click(function (e) {\n                            var $t = $(this),\n                                h = $t.html(),\n                                n = parseInt(h.replace(/[^0-9]/g), 10),\n                                ap = h.replace(/[^apm]/ig),\n                                f = $t.data('for'); // loses scope, so we use data-for\n\n                            if (f === 'hour') {\n                                if (ap.indexOf('p') !== -1 && n < 12) {\n                                    n += 12;\n                                }\n                                else {\n                                    if (ap.indexOf('a') !== -1 && n === 12) {\n                                        n = 0;\n                                    }\n                                }\n                            }\n\n                            tp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n);\n\n                            tp_inst._onTimeChange();\n                            tp_inst._onSelectHandler();\n                        }).css({\n                            cursor: 'pointer',\n                            width: (100 / gridSize[litem]) + '%',\n                            textAlign: 'center',\n                            overflow: 'hidden'\n                        });\n                    } // end if grid > 0\n                } // end for loop\n\n                // Add timezone options\n                this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find(\"select\");\n                $.fn.append.apply(this.timezone_select,\n                    $.map(o.timezoneList, function (val, idx) {\n                        return $(\"<option />\").val(typeof val === \"object\" ? val.value : val).text(typeof val === \"object\" ? val.label : val);\n                    }));\n                if (typeof(this.timezone) !== \"undefined\" && this.timezone !== null && this.timezone !== \"\") {\n                    var local_timezone = (new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12)).getTimezoneOffset() * -1;\n                    if (local_timezone === this.timezone) {\n                        selectLocalTimezone(tp_inst);\n                    } else {\n                        this.timezone_select.val(this.timezone);\n                    }\n                } else {\n                    if (typeof(this.hour) !== \"undefined\" && this.hour !== null && this.hour !== \"\") {\n                        this.timezone_select.val(o.timezone);\n                    } else {\n                        selectLocalTimezone(tp_inst);\n                    }\n                }\n                this.timezone_select.change(function () {\n                    tp_inst._onTimeChange();\n                    tp_inst._onSelectHandler();\n                    tp_inst._afterInject();\n                });\n                // End timezone options\n\n                // inject timepicker into datepicker\n                var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');\n                if ($buttonPanel.length) {\n                    $buttonPanel.before($tp);\n                } else {\n                    $dp.append($tp);\n                }\n\n                this.$timeObj = $tp.find('.ui_tpicker_time_input');\n                this.$timeObj.change(function () {\n                    var timeFormat = tp_inst.inst.settings.timeFormat;\n                    var parsedTime = $.datepicker.parseTime(timeFormat, this.value);\n                    var update = new Date();\n                    if (parsedTime) {\n                        update.setHours(parsedTime.hour);\n                        update.setMinutes(parsedTime.minute);\n                        update.setSeconds(parsedTime.second);\n                        $.datepicker._setTime(tp_inst.inst, update);\n                    } else {\n                        this.value = tp_inst.formattedTime;\n                        this.blur();\n                    }\n                });\n\n                if (this.inst !== null) {\n                    var timeDefined = this.timeDefined;\n                    this._onTimeChange();\n                    this.timeDefined = timeDefined;\n                }\n\n                // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/\n                if (this._defaults.addSliderAccess) {\n                    var sliderAccessArgs = this._defaults.sliderAccessArgs,\n                        rtl = this._defaults.isRTL;\n                    sliderAccessArgs.isRTL = rtl;\n\n                    setTimeout(function () { // fix for inline mode\n                        if ($tp.find('.ui-slider-access').length === 0) {\n                            $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);\n\n                            // fix any grids since sliders are shorter\n                            var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);\n                            if (sliderAccessWidth) {\n                                $tp.find('table:visible').each(function () {\n                                    var $g = $(this),\n                                        oldWidth = $g.outerWidth(),\n                                        oldMarginLeft = $g.css(rtl ? 'marginRight' : 'marginLeft').toString().replace('%', ''),\n                                        newWidth = oldWidth - sliderAccessWidth,\n                                        newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',\n                                        css = { width: newWidth, marginRight: 0, marginLeft: 0 };\n                                    css[rtl ? 'marginRight' : 'marginLeft'] = newMarginLeft;\n                                    $g.css(css);\n                                });\n                            }\n                        }\n                    }, 10);\n                }\n                // end slideAccess integration\n\n                tp_inst._limitMinMaxDateTime(this.inst, true);\n            }\n        },\n\n        /*\n        * This function tries to limit the ability to go outside the\n        * min/max date range\n        */\n        _limitMinMaxDateTime: function (dp_inst, adjustSliders) {\n            var o = this._defaults,\n                dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);\n\n            if (!this._defaults.showTimepicker) {\n                return;\n            } // No time so nothing to check here\n\n            if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {\n                var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),\n                    minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);\n\n                if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null || this.microsecMinOriginal === null) {\n                    this.hourMinOriginal = o.hourMin;\n                    this.minuteMinOriginal = o.minuteMin;\n                    this.secondMinOriginal = o.secondMin;\n                    this.millisecMinOriginal = o.millisecMin;\n                    this.microsecMinOriginal = o.microsecMin;\n                }\n\n                if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() === dp_date.getTime()) {\n                    this._defaults.hourMin = minDateTime.getHours();\n                    if (this.hour <= this._defaults.hourMin) {\n                        this.hour = this._defaults.hourMin;\n                        this._defaults.minuteMin = minDateTime.getMinutes();\n                        if (this.minute <= this._defaults.minuteMin) {\n                            this.minute = this._defaults.minuteMin;\n                            this._defaults.secondMin = minDateTime.getSeconds();\n                            if (this.second <= this._defaults.secondMin) {\n                                this.second = this._defaults.secondMin;\n                                this._defaults.millisecMin = minDateTime.getMilliseconds();\n                                if (this.millisec <= this._defaults.millisecMin) {\n                                    this.millisec = this._defaults.millisecMin;\n                                    this._defaults.microsecMin = minDateTime.getMicroseconds();\n                                } else {\n                                    if (this.microsec < this._defaults.microsecMin) {\n                                        this.microsec = this._defaults.microsecMin;\n                                    }\n                                    this._defaults.microsecMin = this.microsecMinOriginal;\n                                }\n                            } else {\n                                this._defaults.millisecMin = this.millisecMinOriginal;\n                                this._defaults.microsecMin = this.microsecMinOriginal;\n                            }\n                        } else {\n                            this._defaults.secondMin = this.secondMinOriginal;\n                            this._defaults.millisecMin = this.millisecMinOriginal;\n                            this._defaults.microsecMin = this.microsecMinOriginal;\n                        }\n                    } else {\n                        this._defaults.minuteMin = this.minuteMinOriginal;\n                        this._defaults.secondMin = this.secondMinOriginal;\n                        this._defaults.millisecMin = this.millisecMinOriginal;\n                        this._defaults.microsecMin = this.microsecMinOriginal;\n                    }\n                } else {\n                    this._defaults.hourMin = this.hourMinOriginal;\n                    this._defaults.minuteMin = this.minuteMinOriginal;\n                    this._defaults.secondMin = this.secondMinOriginal;\n                    this._defaults.millisecMin = this.millisecMinOriginal;\n                    this._defaults.microsecMin = this.microsecMinOriginal;\n                }\n            }\n\n            if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {\n                var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),\n                    maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);\n\n                if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null || this.millisecMaxOriginal === null) {\n                    this.hourMaxOriginal = o.hourMax;\n                    this.minuteMaxOriginal = o.minuteMax;\n                    this.secondMaxOriginal = o.secondMax;\n                    this.millisecMaxOriginal = o.millisecMax;\n                    this.microsecMaxOriginal = o.microsecMax;\n                }\n\n                if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() === dp_date.getTime()) {\n                    this._defaults.hourMax = maxDateTime.getHours();\n                    if (this.hour >= this._defaults.hourMax) {\n                        this.hour = this._defaults.hourMax;\n                        this._defaults.minuteMax = maxDateTime.getMinutes();\n                        if (this.minute >= this._defaults.minuteMax) {\n                            this.minute = this._defaults.minuteMax;\n                            this._defaults.secondMax = maxDateTime.getSeconds();\n                            if (this.second >= this._defaults.secondMax) {\n                                this.second = this._defaults.secondMax;\n                                this._defaults.millisecMax = maxDateTime.getMilliseconds();\n                                if (this.millisec >= this._defaults.millisecMax) {\n                                    this.millisec = this._defaults.millisecMax;\n                                    this._defaults.microsecMax = maxDateTime.getMicroseconds();\n                                } else {\n                                    if (this.microsec > this._defaults.microsecMax) {\n                                        this.microsec = this._defaults.microsecMax;\n                                    }\n                                    this._defaults.microsecMax = this.microsecMaxOriginal;\n                                }\n                            } else {\n                                this._defaults.millisecMax = this.millisecMaxOriginal;\n                                this._defaults.microsecMax = this.microsecMaxOriginal;\n                            }\n                        } else {\n                            this._defaults.secondMax = this.secondMaxOriginal;\n                            this._defaults.millisecMax = this.millisecMaxOriginal;\n                            this._defaults.microsecMax = this.microsecMaxOriginal;\n                        }\n                    } else {\n                        this._defaults.minuteMax = this.minuteMaxOriginal;\n                        this._defaults.secondMax = this.secondMaxOriginal;\n                        this._defaults.millisecMax = this.millisecMaxOriginal;\n                        this._defaults.microsecMax = this.microsecMaxOriginal;\n                    }\n                } else {\n                    this._defaults.hourMax = this.hourMaxOriginal;\n                    this._defaults.minuteMax = this.minuteMaxOriginal;\n                    this._defaults.secondMax = this.secondMaxOriginal;\n                    this._defaults.millisecMax = this.millisecMaxOriginal;\n                    this._defaults.microsecMax = this.microsecMaxOriginal;\n                }\n            }\n\n            if (dp_inst.settings.minTime!==null) {\n                var tempMinTime=new Date(\"01/01/1970 \" + dp_inst.settings.minTime);\n                if (this.hour<tempMinTime.getHours()) {\n                    this.hour=this._defaults.hourMin=tempMinTime.getHours();\n                    this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();\n                } else if (this.hour===tempMinTime.getHours() && this.minute<tempMinTime.getMinutes()) {\n                    this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();\n                } else {\n                    if (this._defaults.hourMin<tempMinTime.getHours()) {\n                        this._defaults.hourMin=tempMinTime.getHours();\n                        this._defaults.minuteMin=tempMinTime.getMinutes();\n                    } else if (this._defaults.hourMin===tempMinTime.getHours()===this.hour && this._defaults.minuteMin<tempMinTime.getMinutes()) {\n                        this._defaults.minuteMin=tempMinTime.getMinutes();\n                    } else {\n                        this._defaults.minuteMin=0;\n                    }\n                }\n            }\n\n            if (dp_inst.settings.maxTime!==null) {\n                var tempMaxTime=new Date(\"01/01/1970 \" + dp_inst.settings.maxTime);\n                if (this.hour>tempMaxTime.getHours()) {\n                    this.hour=this._defaults.hourMax=tempMaxTime.getHours();\n                    this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();\n                } else if (this.hour===tempMaxTime.getHours() && this.minute>tempMaxTime.getMinutes()) {\n                    this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();\n                } else {\n                    if (this._defaults.hourMax>tempMaxTime.getHours()) {\n                        this._defaults.hourMax=tempMaxTime.getHours();\n                        this._defaults.minuteMax=tempMaxTime.getMinutes();\n                    } else if (this._defaults.hourMax===tempMaxTime.getHours()===this.hour && this._defaults.minuteMax>tempMaxTime.getMinutes()) {\n                        this._defaults.minuteMax=tempMaxTime.getMinutes();\n                    } else {\n                        this._defaults.minuteMax=59;\n                    }\n                }\n            }\n\n            if (adjustSliders !== undefined && adjustSliders === true) {\n                var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),\n                    minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),\n                    secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),\n                    millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10),\n                    microsecMax = parseInt((this._defaults.microsecMax - ((this._defaults.microsecMax - this._defaults.microsecMin) % this._defaults.stepMicrosec)), 10);\n\n                if (this.hour_slider) {\n                    this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax, step: this._defaults.stepHour });\n                    this.control.value(this, this.hour_slider, 'hour', this.hour - (this.hour % this._defaults.stepHour));\n                }\n                if (this.minute_slider) {\n                    this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax, step: this._defaults.stepMinute });\n                    this.control.value(this, this.minute_slider, 'minute', this.minute - (this.minute % this._defaults.stepMinute));\n                }\n                if (this.second_slider) {\n                    this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax, step: this._defaults.stepSecond });\n                    this.control.value(this, this.second_slider, 'second', this.second - (this.second % this._defaults.stepSecond));\n                }\n                if (this.millisec_slider) {\n                    this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax, step: this._defaults.stepMillisec });\n                    this.control.value(this, this.millisec_slider, 'millisec', this.millisec - (this.millisec % this._defaults.stepMillisec));\n                }\n                if (this.microsec_slider) {\n                    this.control.options(this, this.microsec_slider, 'microsec', { min: this._defaults.microsecMin, max: microsecMax, step: this._defaults.stepMicrosec });\n                    this.control.value(this, this.microsec_slider, 'microsec', this.microsec - (this.microsec % this._defaults.stepMicrosec));\n                }\n            }\n\n        },\n\n        /*\n        * when a slider moves, set the internal time...\n        * on time change is also called when the time is updated in the text field\n        */\n        _onTimeChange: function () {\n            if (!this._defaults.showTimepicker) {\n                return;\n            }\n            var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,\n                minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,\n                second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,\n                millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,\n                microsec = (this.microsec_slider) ? this.control.value(this, this.microsec_slider, 'microsec') : false,\n                timezone = (this.timezone_select) ? this.timezone_select.val() : false,\n                o = this._defaults,\n                pickerTimeFormat = o.pickerTimeFormat || o.timeFormat,\n                pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;\n\n            if (typeof(hour) === 'object') {\n                hour = false;\n            }\n            if (typeof(minute) === 'object') {\n                minute = false;\n            }\n            if (typeof(second) === 'object') {\n                second = false;\n            }\n            if (typeof(millisec) === 'object') {\n                millisec = false;\n            }\n            if (typeof(microsec) === 'object') {\n                microsec = false;\n            }\n            if (typeof(timezone) === 'object') {\n                timezone = false;\n            }\n\n            if (hour !== false) {\n                hour = parseInt(hour, 10);\n            }\n            if (minute !== false) {\n                minute = parseInt(minute, 10);\n            }\n            if (second !== false) {\n                second = parseInt(second, 10);\n            }\n            if (millisec !== false) {\n                millisec = parseInt(millisec, 10);\n            }\n            if (microsec !== false) {\n                microsec = parseInt(microsec, 10);\n            }\n            if (timezone !== false) {\n                timezone = timezone.toString();\n            }\n\n            var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];\n\n            // If the update was done in the input field, the input field should not be updated.\n            // If the update was done using the sliders, update the input field.\n            var hasChanged = (\n                hour !== parseInt(this.hour,10) || // sliders should all be numeric\n                minute !== parseInt(this.minute,10) ||\n                second !== parseInt(this.second,10) ||\n                millisec !== parseInt(this.millisec,10) ||\n                microsec !== parseInt(this.microsec,10) ||\n                (this.ampm.length > 0 && (hour < 12) !== ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) ||\n                (this.timezone !== null && timezone !== this.timezone.toString()) // could be numeric or \"EST\" format, so use toString()\n            );\n\n            if (hasChanged) {\n\n                if (hour !== false) {\n                    this.hour = hour;\n                }\n                if (minute !== false) {\n                    this.minute = minute;\n                }\n                if (second !== false) {\n                    this.second = second;\n                }\n                if (millisec !== false) {\n                    this.millisec = millisec;\n                }\n                if (microsec !== false) {\n                    this.microsec = microsec;\n                }\n                if (timezone !== false) {\n                    this.timezone = timezone;\n                }\n\n                if (!this.inst) {\n                    this.inst = $.datepicker._getInst(this.$input[0]);\n                }\n\n                this._limitMinMaxDateTime(this.inst, true);\n            }\n            if (this.support.ampm) {\n                this.ampm = ampm;\n            }\n\n            // Updates the time within the timepicker\n            this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);\n            if (this.$timeObj) {\n                if (pickerTimeFormat === o.timeFormat) {\n                    this.$timeObj.val(this.formattedTime + pickerTimeSuffix);\n                }\n                else {\n                    this.$timeObj.val($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);\n                }\n                if (this.$timeObj[0].setSelectionRange) {\n                    var sPos = this.$timeObj[0].selectionStart;\n                    var ePos = this.$timeObj[0].selectionEnd;\n                    this.$timeObj[0].setSelectionRange(sPos, ePos);\n                }\n            }\n\n            this.timeDefined = true;\n            if (hasChanged) {\n                this._updateDateTime();\n                //this.$input.focus(); // may automatically open the picker on setDate\n            }\n        },\n\n        /*\n        * call custom onSelect.\n        * bind to sliders slidestop, and grid click.\n        */\n        _onSelectHandler: function () {\n            var onSelect = this._defaults.onSelect || this.inst.settings.onSelect;\n            var inputEl = this.$input ? this.$input[0] : null;\n            if (onSelect && inputEl) {\n                onSelect.apply(inputEl, [this.formattedDateTime, this]);\n            }\n        },\n\n        /*\n        * update our input with the new date time..\n        */\n        _updateDateTime: function (dp_inst) {\n            dp_inst = this.inst || dp_inst;\n            var dtTmp = (dp_inst.currentYear > 0?\n                new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay) :\n                new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),\n                dt = $.datepicker._daylightSavingAdjust(dtTmp),\n                //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),\n                //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay)),\n                dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),\n                formatCfg = $.datepicker._getFormatConfig(dp_inst),\n                timeAvailable = dt !== null && this.timeDefined;\n            this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);\n            var formattedDateTime = this.formattedDate;\n\n            // if a slider was changed but datepicker doesn't have a value yet, set it\n            if (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            /*\n            * remove following lines to force every changes in date picker to change the input value\n            * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker.\n            * If the user manually empty the value in the input field, the date picker will never change selected value.\n            */\n            //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {\n            //\treturn;\n            //}\n\n            if (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === false) {\n                formattedDateTime = this.formattedTime;\n            } else if ((this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) || (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === true)) {\n                formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;\n            }\n\n            this.formattedDateTime = formattedDateTime;\n\n            if (!this._defaults.showTimepicker) {\n                this.$input.val(this.formattedDate);\n            } else if (this.$altInput && this._defaults.timeOnly === false && this._defaults.altFieldTimeOnly === true) {\n                this.$altInput.val(this.formattedTime);\n                this.$input.val(this.formattedDate);\n            } else if (this.$altInput) {\n                this.$input.val(formattedDateTime);\n                var altFormattedDateTime = '',\n                    altSeparator = this._defaults.altSeparator !== null ? this._defaults.altSeparator : this._defaults.separator,\n                    altTimeSuffix = this._defaults.altTimeSuffix !== null ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;\n\n                if (!this._defaults.timeOnly) {\n                    if (this._defaults.altFormat) {\n                        altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);\n                    }\n                    else {\n                        altFormattedDateTime = this.formattedDate;\n                    }\n\n                    if (altFormattedDateTime) {\n                        altFormattedDateTime += altSeparator;\n                    }\n                }\n\n                if (this._defaults.altTimeFormat !== null) {\n                    altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;\n                }\n                else {\n                    altFormattedDateTime += this.formattedTime + altTimeSuffix;\n                }\n                this.$altInput.val(altFormattedDateTime);\n            } else {\n                this.$input.val(formattedDateTime);\n            }\n\n            this.$input.trigger(\"change\");\n        },\n\n        _onFocus: function () {\n            if (!this.$input.val() && this._defaults.defaultValue) {\n                this.$input.val(this._defaults.defaultValue);\n                var inst = $.datepicker._getInst(this.$input.get(0)),\n                    tp_inst = $.datepicker._get(inst, 'timepicker');\n                if (tp_inst) {\n                    if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {\n                        try {\n                            $.datepicker._updateDatepicker(inst);\n                        } catch (err) {\n                            $.timepicker.log(err);\n                        }\n                    }\n                }\n            }\n        },\n\n        /*\n        * Small abstraction to control types\n        * We can add more, just be sure to follow the pattern: create, options, value\n        */\n        _controls: {\n            // slider methods\n            slider: {\n                create: function (tp_inst, obj, unit, val, min, max, step) {\n                    var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60\n                    return obj.prop('slide', null).slider({\n                        orientation: \"horizontal\",\n                        value: rtl ? val * -1 : val,\n                        min: rtl ? max * -1 : min,\n                        max: rtl ? min * -1 : max,\n                        step: step,\n                        slide: function (event, ui) {\n                            tp_inst.control.value(tp_inst, $(this), unit, rtl ? ui.value * -1 : ui.value);\n                            tp_inst._onTimeChange();\n                        },\n                        stop: function (event, ui) {\n                            tp_inst._onSelectHandler();\n                        }\n                    });\n                },\n                options: function (tp_inst, obj, unit, opts, val) {\n                    if (tp_inst._defaults.isRTL) {\n                        if (typeof(opts) === 'string') {\n                            if (opts === 'min' || opts === 'max') {\n                                if (val !== undefined) {\n                                    return obj.slider(opts, val * -1);\n                                }\n                                return Math.abs(obj.slider(opts));\n                            }\n                            return obj.slider(opts);\n                        }\n                        var min = opts.min,\n                            max = opts.max;\n                        opts.min = opts.max = null;\n                        if (min !== undefined) {\n                            opts.max = min * -1;\n                        }\n                        if (max !== undefined) {\n                            opts.min = max * -1;\n                        }\n                        return obj.slider(opts);\n                    }\n                    if (typeof(opts) === 'string' && val !== undefined) {\n                        return obj.slider(opts, val);\n                    }\n                    return obj.slider(opts);\n                },\n                value: function (tp_inst, obj, unit, val) {\n                    if (tp_inst._defaults.isRTL) {\n                        if (val !== undefined) {\n                            return obj.slider('value', val * -1);\n                        }\n                        return Math.abs(obj.slider('value'));\n                    }\n                    if (val !== undefined) {\n                        return obj.slider('value', val);\n                    }\n                    return obj.slider('value');\n                }\n            },\n            // select methods\n            select: {\n                create: function (tp_inst, obj, unit, val, min, max, step) {\n                    var sel = '<select class=\"ui-timepicker-select ui-state-default ui-corner-all\" data-unit=\"' + unit + '\" data-min=\"' + min + '\" data-max=\"' + max + '\" data-step=\"' + step + '\">',\n                        format = tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat;\n\n                    for (var i = min; i <= max; i += step) {\n                        sel += '<option value=\"' + i + '\"' + (i === val ? ' selected' : '') + '>';\n                        if (unit === 'hour') {\n                            sel += $.datepicker.formatTime($.trim(format.replace(/[^ht ]/ig, '')), {hour: i}, tp_inst._defaults);\n                        }\n                        else if (unit === 'millisec' || unit === 'microsec' || i >= 10) { sel += i; }\n                        else {sel += '0' + i.toString(); }\n                        sel += '</option>';\n                    }\n                    sel += '</select>';\n\n                    obj.children('select').remove();\n\n                    $(sel).appendTo(obj).change(function (e) {\n                        tp_inst._onTimeChange();\n                        tp_inst._onSelectHandler();\n                        tp_inst._afterInject();\n                    });\n\n                    return obj;\n                },\n                options: function (tp_inst, obj, unit, opts, val) {\n                    var o = {},\n                        $t = obj.children('select');\n                    if (typeof(opts) === 'string') {\n                        if (val === undefined) {\n                            return $t.data(opts);\n                        }\n                        o[opts] = val;\n                    }\n                    else { o = opts; }\n                    return tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min>=0 ? o.min : $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step'));\n                },\n                value: function (tp_inst, obj, unit, val) {\n                    var $t = obj.children('select');\n                    if (val !== undefined) {\n                        return $t.val(val);\n                    }\n                    return $t.val();\n                }\n            }\n        } // end _controls\n\n    });\n\n    $.fn.extend({\n        /*\n        * shorthand just to use timepicker.\n        */\n        timepicker: function (o) {\n            o = o || {};\n            var tmp_args = Array.prototype.slice.call(arguments);\n\n            if (typeof o === 'object') {\n                tmp_args[0] = $.extend(o, {\n                    timeOnly: true\n                });\n            }\n\n            return $(this).each(function () {\n                $.fn.datetimepicker.apply($(this), tmp_args);\n            });\n        },\n\n        /*\n        * extend timepicker to datepicker\n        */\n        datetimepicker: function (o) {\n            o = o || {};\n            var tmp_args = arguments;\n\n            if (typeof(o) === 'string') {\n                if (o === 'getDate'  || (o === 'option' && tmp_args.length === 2 && typeof (tmp_args[1]) === 'string')) {\n                    return $.fn.datepicker.apply($(this[0]), tmp_args);\n                } else {\n                    return this.each(function () {\n                        var $t = $(this);\n                        $t.datepicker.apply($t, tmp_args);\n                    });\n                }\n            } else {\n                return this.each(function () {\n                    var $t = $(this);\n                    $t.datepicker($.timepicker._newInst($t, o)._defaults);\n                });\n            }\n        }\n    });\n\n    /*\n    * Public Utility to parse date and time\n    */\n    $.datepicker.parseDateTime = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {\n        var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);\n        if (parseRes.timeObj) {\n            var t = parseRes.timeObj;\n            parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);\n            parseRes.date.setMicroseconds(t.microsec);\n        }\n\n        return parseRes.date;\n    };\n\n    /*\n    * Public utility to parse time\n    */\n    $.datepicker.parseTime = function (timeFormat, timeString, options) {\n        var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}),\n            iso8601 = (timeFormat.replace(/\\'.*?\\'/g, '').indexOf('Z') !== -1);\n\n        // Strict parse requires the timeString to match the timeFormat exactly\n        var strictParse = function (f, s, o) {\n\n            // pattern for standard and localized AM/PM markers\n            var getPatternAmpm = function (amNames, pmNames) {\n                var markers = [];\n                if (amNames) {\n                    $.merge(markers, amNames);\n                }\n                if (pmNames) {\n                    $.merge(markers, pmNames);\n                }\n                markers = $.map(markers, function (val) {\n                    return val.replace(/[.*+?|()\\[\\]{}\\\\]/g, '\\\\$&');\n                });\n                return '(' + markers.join('|') + ')?';\n            };\n\n            // figure out position of time elements.. cause js cant do named captures\n            var getFormatPositions = function (timeFormat) {\n                var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),\n                    orders = {\n                        h: -1,\n                        m: -1,\n                        s: -1,\n                        l: -1,\n                        c: -1,\n                        t: -1,\n                        z: -1\n                    };\n\n                if (finds) {\n                    for (var i = 0; i < finds.length; i++) {\n                        if (orders[finds[i].toString().charAt(0)] === -1) {\n                            orders[finds[i].toString().charAt(0)] = i + 1;\n                        }\n                    }\n                }\n                return orders;\n            };\n\n            var regstr = '^' + f.toString()\n                    .replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {\n                        var ml = match.length;\n                        switch (match.charAt(0).toLowerCase()) {\n                            case 'h':\n                                return ml === 1 ? '(\\\\d?\\\\d)' : '(\\\\d{' + ml + '})';\n                            case 'm':\n                                return ml === 1 ? '(\\\\d?\\\\d)' : '(\\\\d{' + ml + '})';\n                            case 's':\n                                return ml === 1 ? '(\\\\d?\\\\d)' : '(\\\\d{' + ml + '})';\n                            case 'l':\n                                return '(\\\\d?\\\\d?\\\\d)';\n                            case 'c':\n                                return '(\\\\d?\\\\d?\\\\d)';\n                            case 'z':\n                                return '(z|[-+]\\\\d\\\\d:?\\\\d\\\\d|\\\\S+)?';\n                            case 't':\n                                return getPatternAmpm(o.amNames, o.pmNames);\n                            default:    // literal escaped in quotes\n                                return '(' + match.replace(/\\'/g, \"\").replace(/(\\.|\\$|\\^|\\\\|\\/|\\(|\\)|\\[|\\]|\\?|\\+|\\*)/g, function (m) { return \"\\\\\" + m; }) + ')?';\n                        }\n                    })\n                    .replace(/\\s/g, '\\\\s?') +\n                o.timeSuffix + '$',\n                order = getFormatPositions(f),\n                ampm = '',\n                treg;\n\n            treg = s.match(new RegExp(regstr, 'i'));\n\n            var resTime = {\n                hour: 0,\n                minute: 0,\n                second: 0,\n                millisec: 0,\n                microsec: 0\n            };\n\n            if (treg) {\n                if (order.t !== -1) {\n                    if (treg[order.t] === undefined || treg[order.t].length === 0) {\n                        ampm = '';\n                        resTime.ampm = '';\n                    } else {\n                        ampm = $.inArray(treg[order.t].toUpperCase(), $.map(o.amNames, function (x,i) { return x.toUpperCase(); })) !== -1 ? 'AM' : 'PM';\n                        resTime.ampm = o[ampm === 'AM' ? 'amNames' : 'pmNames'][0];\n                    }\n                }\n\n                if (order.h !== -1) {\n                    if (ampm === 'AM' && treg[order.h] === '12') {\n                        resTime.hour = 0; // 12am = 0 hour\n                    } else {\n                        if (ampm === 'PM' && treg[order.h] !== '12') {\n                            resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 12\n                        } else {\n                            resTime.hour = Number(treg[order.h]);\n                        }\n                    }\n                }\n\n                if (order.m !== -1) {\n                    resTime.minute = Number(treg[order.m]);\n                }\n                if (order.s !== -1) {\n                    resTime.second = Number(treg[order.s]);\n                }\n                if (order.l !== -1) {\n                    resTime.millisec = Number(treg[order.l]);\n                }\n                if (order.c !== -1) {\n                    resTime.microsec = Number(treg[order.c]);\n                }\n                if (order.z !== -1 && treg[order.z] !== undefined) {\n                    resTime.timezone = $.timepicker.timezoneOffsetNumber(treg[order.z]);\n                }\n\n\n                return resTime;\n            }\n            return false;\n        };// end strictParse\n\n        // First try JS Date, if that fails, use strictParse\n        var looseParse = function (f, s, o) {\n            try {\n                var d = new Date('2012-01-01 ' + s);\n                if (isNaN(d.getTime())) {\n                    d = new Date('2012-01-01T' + s);\n                    if (isNaN(d.getTime())) {\n                        d = new Date('01/01/2012 ' + s);\n                        if (isNaN(d.getTime())) {\n                            throw \"Unable to parse time with native Date: \" + s;\n                        }\n                    }\n                }\n\n                return {\n                    hour: d.getHours(),\n                    minute: d.getMinutes(),\n                    second: d.getSeconds(),\n                    millisec: d.getMilliseconds(),\n                    microsec: d.getMicroseconds(),\n                    timezone: d.getTimezoneOffset() * -1\n                };\n            }\n            catch (err) {\n                try {\n                    return strictParse(f, s, o);\n                }\n                catch (err2) {\n                    $.timepicker.log(\"Unable to parse \\ntimeString: \" + s + \"\\ntimeFormat: \" + f);\n                }\n            }\n            return false;\n        }; // end looseParse\n\n        if (typeof o.parse === \"function\") {\n            return o.parse(timeFormat, timeString, o);\n        }\n        if (o.parse === 'loose') {\n            return looseParse(timeFormat, timeString, o);\n        }\n        return strictParse(timeFormat, timeString, o);\n    };\n\n    /**\n     * Public utility to format the time\n     * @param {string} format format of the time\n     * @param {Object} time Object not a Date for timezones\n     * @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm\n     * @returns {string} the formatted time\n     */\n    $.datepicker.formatTime = function (format, time, options) {\n        options = options || {};\n        options = $.extend({}, $.timepicker._defaults, options);\n        time = $.extend({\n            hour: 0,\n            minute: 0,\n            second: 0,\n            millisec: 0,\n            microsec: 0,\n            timezone: null\n        }, time);\n\n        var tmptime = format,\n            ampmName = options.amNames[0],\n            hour = parseInt(time.hour, 10);\n\n        if (hour > 11) {\n            ampmName = options.pmNames[0];\n        }\n\n        tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {\n            switch (match) {\n                case 'HH':\n                    return ('0' + hour).slice(-2);\n                case 'H':\n                    return hour;\n                case 'hh':\n                    return ('0' + convert24to12(hour)).slice(-2);\n                case 'h':\n                    return convert24to12(hour);\n                case 'mm':\n                    return ('0' + time.minute).slice(-2);\n                case 'm':\n                    return time.minute;\n                case 'ss':\n                    return ('0' + time.second).slice(-2);\n                case 's':\n                    return time.second;\n                case 'l':\n                    return ('00' + time.millisec).slice(-3);\n                case 'c':\n                    return ('00' + time.microsec).slice(-3);\n                case 'z':\n                    return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, false);\n                case 'Z':\n                    return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, true);\n                case 'T':\n                    return ampmName.charAt(0).toUpperCase();\n                case 'TT':\n                    return ampmName.toUpperCase();\n                case 't':\n                    return ampmName.charAt(0).toLowerCase();\n                case 'tt':\n                    return ampmName.toLowerCase();\n                default:\n                    return match.replace(/'/g, \"\");\n            }\n        });\n\n        return tmptime;\n    };\n\n    /*\n    * the bad hack :/ override datepicker so it doesn't close on select\n    // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378\n    */\n    $.datepicker._base_selectDate = $.datepicker._selectDate;\n    $.datepicker._selectDate = function (id, dateStr) {\n        var inst = this._getInst($(id)[0]),\n            tp_inst = this._get(inst, 'timepicker'),\n            was_inline;\n\n        if (tp_inst && inst.settings.showTimepicker) {\n            tp_inst._limitMinMaxDateTime(inst, true);\n            was_inline = inst.inline;\n            inst.inline = inst.stay_open = true;\n            //This way the onSelect handler called from calendarpicker get the full dateTime\n            this._base_selectDate(id, dateStr);\n            inst.inline = was_inline;\n            inst.stay_open = false;\n            this._notifyChange(inst);\n            this._updateDatepicker(inst);\n        } else {\n            this._base_selectDate(id, dateStr);\n        }\n    };\n\n    /*\n    * second bad hack :/ override datepicker so it triggers an event when changing the input field\n    * and does not redraw the datepicker on every selectDate event\n    */\n    $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;\n    $.datepicker._updateDatepicker = function (inst) {\n\n        // don't popup the datepicker if there is another instance already opened\n        var input = inst.input[0];\n        if ($.datepicker._curInst && $.datepicker._curInst !== inst && $.datepicker._datepickerShowing && $.datepicker._lastInput !== input) {\n            return;\n        }\n\n        if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {\n\n            this._base_updateDatepicker(inst);\n\n            // Reload the time control when changing something in the input text field.\n            var tp_inst = this._get(inst, 'timepicker');\n            if (tp_inst) {\n                tp_inst._addTimePicker(inst);\n            }\n        }\n    };\n\n    /*\n    * third bad hack :/ override datepicker so it allows spaces and colon in the input field\n    */\n    $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;\n    $.datepicker._doKeyPress = function (event) {\n        var inst = $.datepicker._getInst(event.target),\n            tp_inst = $.datepicker._get(inst, 'timepicker');\n\n        if (tp_inst) {\n            if ($.datepicker._get(inst, 'constrainInput')) {\n                var ampm = tp_inst.support.ampm,\n                    tz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone,\n                    dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),\n                    datetimeChars = tp_inst._defaults.timeFormat.toString()\n                            .replace(/[hms]/g, '')\n                            .replace(/TT/g, ampm ? 'APM' : '')\n                            .replace(/Tt/g, ampm ? 'AaPpMm' : '')\n                            .replace(/tT/g, ampm ? 'AaPpMm' : '')\n                            .replace(/T/g, ampm ? 'AP' : '')\n                            .replace(/tt/g, ampm ? 'apm' : '')\n                            .replace(/t/g, ampm ? 'ap' : '') +\n                        \" \" + tp_inst._defaults.separator +\n                        tp_inst._defaults.timeSuffix +\n                        (tz ? tp_inst._defaults.timezoneList.join('') : '') +\n                        (tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) +\n                        dateChars,\n                    chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);\n                return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);\n            }\n        }\n\n        return $.datepicker._base_doKeyPress(event);\n    };\n\n    /*\n    * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField\n    * Update any alternate field to synchronise with the main field.\n    */\n    $.datepicker._base_updateAlternate = $.datepicker._updateAlternate;\n    $.datepicker._updateAlternate = function (inst) {\n        var tp_inst = this._get(inst, 'timepicker');\n        if (tp_inst) {\n            var altField = tp_inst._defaults.altField;\n            if (altField) { // update alternate field too\n                var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,\n                    date = this._getDate(inst),\n                    formatCfg = $.datepicker._getFormatConfig(inst),\n                    altFormattedDateTime = '',\n                    altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator,\n                    altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,\n                    altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;\n\n                altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;\n                if (!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null) {\n                    if (tp_inst._defaults.altFormat) {\n                        altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;\n                    }\n                    else {\n                        altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;\n                    }\n                }\n                $(altField).val( inst.input.val() ? altFormattedDateTime : \"\");\n            }\n        }\n        else {\n            $.datepicker._base_updateAlternate(inst);\n        }\n    };\n\n    /*\n    * Override key up event to sync manual input changes.\n    */\n    $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;\n    $.datepicker._doKeyUp = function (event) {\n        var inst = $.datepicker._getInst(event.target),\n            tp_inst = $.datepicker._get(inst, 'timepicker');\n\n        if (tp_inst) {\n            if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {\n                try {\n                    $.datepicker._updateDatepicker(inst);\n                } catch (err) {\n                    $.timepicker.log(err);\n                }\n            }\n        }\n\n        return $.datepicker._base_doKeyUp(event);\n    };\n\n    /*\n    * override \"Today\" button to also grab the time and set it to input field.\n    */\n    $.datepicker._base_gotoToday = $.datepicker._gotoToday;\n    $.datepicker._gotoToday = function (id) {\n        var inst = this._getInst($(id)[0]);\n        this._base_gotoToday(id);\n        var tp_inst = this._get(inst, 'timepicker');\n        if (!tp_inst) {\n            return;\n        }\n\n        var tzoffset = $.timepicker.timezoneOffsetNumber(tp_inst.timezone);\n        var now = new Date();\n        now.setMinutes(now.getMinutes() + now.getTimezoneOffset() + parseInt(tzoffset, 10));\n        this._setTime(inst, now);\n        this._setDate(inst, now);\n        tp_inst._onSelectHandler();\n    };\n\n    /*\n    * Disable & enable the Time in the datetimepicker\n    */\n    $.datepicker._disableTimepickerDatepicker = function (target) {\n        var inst = this._getInst(target);\n        if (!inst) {\n            return;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n        $(target).datepicker('getDate'); // Init selected[Year|Month|Day]\n        if (tp_inst) {\n            inst.settings.showTimepicker = false;\n            tp_inst._defaults.showTimepicker = false;\n            tp_inst._updateDateTime(inst);\n        }\n    };\n\n    $.datepicker._enableTimepickerDatepicker = function (target) {\n        var inst = this._getInst(target);\n        if (!inst) {\n            return;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n        $(target).datepicker('getDate'); // Init selected[Year|Month|Day]\n        if (tp_inst) {\n            inst.settings.showTimepicker = true;\n            tp_inst._defaults.showTimepicker = true;\n            tp_inst._addTimePicker(inst); // Could be disabled on page load\n            tp_inst._updateDateTime(inst);\n        }\n    };\n\n    /*\n    * Create our own set time function\n    */\n    $.datepicker._setTime = function (inst, date) {\n        var tp_inst = this._get(inst, 'timepicker');\n        if (tp_inst) {\n            var defaults = tp_inst._defaults;\n\n            // calling _setTime with no date sets time to defaults\n            tp_inst.hour = date ? date.getHours() : defaults.hour;\n            tp_inst.minute = date ? date.getMinutes() : defaults.minute;\n            tp_inst.second = date ? date.getSeconds() : defaults.second;\n            tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;\n            tp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec;\n\n            //check if within min/max times..\n            tp_inst._limitMinMaxDateTime(inst, true);\n\n            tp_inst._onTimeChange();\n            tp_inst._updateDateTime(inst);\n        }\n    };\n\n    /*\n    * Create new public method to set only time, callable as $().datepicker('setTime', date)\n    */\n    $.datepicker._setTimeDatepicker = function (target, date, withDate) {\n        var inst = this._getInst(target);\n        if (!inst) {\n            return;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n\n        if (tp_inst) {\n            this._setDateFromField(inst);\n            var tp_date;\n            if (date) {\n                if (typeof date === \"string\") {\n                    tp_inst._parseTime(date, withDate);\n                    tp_date = new Date();\n                    tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);\n                    tp_date.setMicroseconds(tp_inst.microsec);\n                } else {\n                    tp_date = new Date(date.getTime());\n                    tp_date.setMicroseconds(date.getMicroseconds());\n                }\n                if (tp_date.toString() === 'Invalid Date') {\n                    tp_date = undefined;\n                }\n                this._setTime(inst, tp_date);\n            }\n        }\n\n    };\n\n    /*\n    * override setDate() to allow setting time too within Date object\n    */\n    $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;\n    $.datepicker._setDateDatepicker = function (target, _date) {\n        var inst = this._getInst(target);\n        var date = _date;\n        if (!inst) {\n            return;\n        }\n\n        if (typeof(_date) === 'string') {\n            date = new Date(_date);\n            if (!date.getTime()) {\n                this._base_setDateDatepicker.apply(this, arguments);\n                date = $(target).datepicker('getDate');\n            }\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n        var tp_date;\n        if (date instanceof Date) {\n            tp_date = new Date(date.getTime());\n            tp_date.setMicroseconds(date.getMicroseconds());\n        } else {\n            tp_date = date;\n        }\n\n        // This is important if you are using the timezone option, javascript's Date\n        // object will only return the timezone offset for the current locale, so we\n        // adjust it accordingly.  If not using timezone option this won't matter..\n        // If a timezone is different in tp, keep the timezone as is\n        if (tp_inst && tp_date) {\n            // look out for DST if tz wasn't specified\n            if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {\n                tp_inst.timezone = tp_date.getTimezoneOffset() * -1;\n            }\n            date = $.timepicker.timezoneAdjust(date, $.timepicker.timezoneOffsetString(-date.getTimezoneOffset()), tp_inst.timezone);\n            tp_date = $.timepicker.timezoneAdjust(tp_date, $.timepicker.timezoneOffsetString(-tp_date.getTimezoneOffset()), tp_inst.timezone);\n        }\n\n        this._updateDatepicker(inst);\n        this._base_setDateDatepicker.apply(this, arguments);\n        this._setTimeDatepicker(target, tp_date, true);\n    };\n\n    /*\n    * override getDate() to allow getting time too within Date object\n    */\n    $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;\n    $.datepicker._getDateDatepicker = function (target, noDefault) {\n        var inst = this._getInst(target);\n        if (!inst) {\n            return;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n\n        if (tp_inst) {\n            // if it hasn't yet been defined, grab from field\n            if (inst.lastVal === undefined) {\n                this._setDateFromField(inst, noDefault);\n            }\n\n            var date = this._getDate(inst);\n\n            var currDT = null;\n\n            if (tp_inst.$altInput && tp_inst._defaults.altFieldTimeOnly) {\n                currDT = tp_inst.$input.val() + ' ' + tp_inst.$altInput.val();\n            }\n            else if (tp_inst.$input.get(0).tagName !== 'INPUT' && tp_inst.$altInput) {\n                /**\n                 * in case the datetimepicker has been applied to a non-input tag for inline UI,\n                 * and the user has not configured the plugin to display only time in altInput,\n                 * pick current date time from the altInput (and hope for the best, for now, until \"ER1\" is applied)\n                 *\n                 * @todo ER1. Since altInput can have a totally difference format, convert it to standard format by reading input format from \"altFormat\" and \"altTimeFormat\" option values\n                 */\n                currDT = tp_inst.$altInput.val();\n            }\n            else {\n                currDT = tp_inst.$input.val();\n            }\n\n            if (date && tp_inst._parseTime(currDT, !inst.settings.timeOnly)) {\n                date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);\n                date.setMicroseconds(tp_inst.microsec);\n\n                // This is important if you are using the timezone option, javascript's Date\n                // object will only return the timezone offset for the current locale, so we\n                // adjust it accordingly.  If not using timezone option this won't matter..\n                if (tp_inst.timezone != null) {\n                    // look out for DST if tz wasn't specified\n                    if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {\n                        tp_inst.timezone = date.getTimezoneOffset() * -1;\n                    }\n                    date = $.timepicker.timezoneAdjust(date, tp_inst.timezone, $.timepicker.timezoneOffsetString(-date.getTimezoneOffset()));\n                }\n            }\n            return date;\n        }\n        return this._base_getDateDatepicker(target, noDefault);\n    };\n\n    /*\n    * override parseDate() because UI 1.8.14 throws an error about \"Extra characters\"\n    * An option in datapicker to ignore extra format characters would be nicer.\n    */\n    $.datepicker._base_parseDate = $.datepicker.parseDate;\n    $.datepicker.parseDate = function (format, value, settings) {\n        var date;\n        try {\n            date = this._base_parseDate(format, value, settings);\n        } catch (err) {\n            // Hack!  The error message ends with a colon, a space, and\n            // the \"extra\" characters.  We rely on that instead of\n            // attempting to perfectly reproduce the parsing algorithm.\n            if (err.indexOf(\":\") >= 0) {\n                date = this._base_parseDate(format, value.substring(0, value.length - (err.length - err.indexOf(':') - 2)), settings);\n                $.timepicker.log(\"Error parsing the date string: \" + err + \"\\ndate string = \" + value + \"\\ndate format = \" + format);\n            } else {\n                throw err;\n            }\n        }\n        return date;\n    };\n\n    /*\n    * override formatDate to set date with time to the input\n    */\n    $.datepicker._base_formatDate = $.datepicker._formatDate;\n    $.datepicker._formatDate = function (inst, day, month, year) {\n        var tp_inst = this._get(inst, 'timepicker');\n        if (tp_inst) {\n            tp_inst._updateDateTime(inst);\n            return tp_inst.$input.val();\n        }\n        return this._base_formatDate(inst);\n    };\n\n    /*\n    * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate\n    */\n    $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;\n    $.datepicker._optionDatepicker = function (target, name, value) {\n        var inst = this._getInst(target),\n            name_clone;\n        if (!inst) {\n            return null;\n        }\n\n        var tp_inst = this._get(inst, 'timepicker');\n        if (tp_inst) {\n            var min = null,\n                max = null,\n                onselect = null,\n                overrides = tp_inst._defaults.evnts,\n                fns = {},\n                prop,\n                ret,\n                oldVal,\n                $target;\n            if (typeof name === 'string') { // if min/max was set with the string\n                if (name === 'minDate' || name === 'minDateTime') {\n                    min = value;\n                } else if (name === 'maxDate' || name === 'maxDateTime') {\n                    max = value;\n                } else if (name === 'onSelect') {\n                    onselect = value;\n                } else if (overrides.hasOwnProperty(name)) {\n                    if (typeof (value) === 'undefined') {\n                        return overrides[name];\n                    }\n                    fns[name] = value;\n                    name_clone = {}; //empty results in exiting function after overrides updated\n                }\n            } else if (typeof name === 'object') { //if min/max was set with the JSON\n                if (name.minDate) {\n                    min = name.minDate;\n                } else if (name.minDateTime) {\n                    min = name.minDateTime;\n                } else if (name.maxDate) {\n                    max = name.maxDate;\n                } else if (name.maxDateTime) {\n                    max = name.maxDateTime;\n                }\n                for (prop in overrides) {\n                    if (overrides.hasOwnProperty(prop) && name[prop]) {\n                        fns[prop] = name[prop];\n                    }\n                }\n            }\n            for (prop in fns) {\n                if (fns.hasOwnProperty(prop)) {\n                    overrides[prop] = fns[prop];\n                    if (!name_clone) { name_clone = $.extend({}, name); }\n                    delete name_clone[prop];\n                }\n            }\n            if (name_clone && isEmptyObject(name_clone)) { return; }\n            if (min) { //if min was set\n                if (min === 0) {\n                    min = new Date();\n                } else {\n                    min = new Date(min);\n                }\n                tp_inst._defaults.minDate = min;\n                tp_inst._defaults.minDateTime = min;\n            } else if (max) { //if max was set\n                if (max === 0) {\n                    max = new Date();\n                } else {\n                    max = new Date(max);\n                }\n                tp_inst._defaults.maxDate = max;\n                tp_inst._defaults.maxDateTime = max;\n            } else if (onselect) {\n                tp_inst._defaults.onSelect = onselect;\n            }\n\n            // Datepicker will override our date when we call _base_optionDatepicker when\n            // calling minDate/maxDate, so we will first grab the value, call\n            // _base_optionDatepicker, then set our value back.\n            if(min || max){\n                $target = $(target);\n                oldVal = $target.datetimepicker('getDate');\n                ret = this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);\n                $target.datetimepicker('setDate', oldVal);\n                return ret;\n            }\n        }\n        if (value === undefined) {\n            return this._base_optionDatepicker.call($.datepicker, target, name);\n        }\n        return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);\n    };\n\n    /*\n    * jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,\n    * it will return false for all objects\n    */\n    var isEmptyObject = function (obj) {\n        var prop;\n        for (prop in obj) {\n            if (obj.hasOwnProperty(prop)) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    /*\n    * jQuery extend now ignores nulls!\n    */\n    var extendRemove = function (target, props) {\n        $.extend(target, props);\n        for (var name in props) {\n            if (props[name] === null || props[name] === undefined) {\n                target[name] = props[name];\n            }\n        }\n        return target;\n    };\n\n    /*\n    * Determine by the time format which units are supported\n    * Returns an object of booleans for each unit\n    */\n    var detectSupport = function (timeFormat) {\n        var tf = timeFormat.replace(/'.*?'/g, '').toLowerCase(), // removes literals\n            isIn = function (f, t) { // does the format contain the token?\n                return f.indexOf(t) !== -1 ? true : false;\n            };\n        return {\n            hour: isIn(tf, 'h'),\n            minute: isIn(tf, 'm'),\n            second: isIn(tf, 's'),\n            millisec: isIn(tf, 'l'),\n            microsec: isIn(tf, 'c'),\n            timezone: isIn(tf, 'z'),\n            ampm: isIn(tf, 't') && isIn(timeFormat, 'h'),\n            iso8601: isIn(timeFormat, 'Z')\n        };\n    };\n\n    /*\n    * Converts 24 hour format into 12 hour\n    * Returns 12 hour without leading 0\n    */\n    var convert24to12 = function (hour) {\n        hour %= 12;\n\n        if (hour === 0) {\n            hour = 12;\n        }\n\n        return String(hour);\n    };\n\n    var computeEffectiveSetting = function (settings, property) {\n        return settings && settings[property] ? settings[property] : $.timepicker._defaults[property];\n    };\n\n    /*\n    * Splits datetime string into date and time substrings.\n    * Throws exception when date can't be parsed\n    * Returns {dateString: dateString, timeString: timeString}\n    */\n    var splitDateTime = function (dateTimeString, timeSettings) {\n        // The idea is to get the number separator occurrences in datetime and the time format requested (since time has\n        // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.\n        var separator = computeEffectiveSetting(timeSettings, 'separator'),\n            format = computeEffectiveSetting(timeSettings, 'timeFormat'),\n            timeParts = format.split(separator), // how many occurrences of separator may be in our format?\n            timePartsLen = timeParts.length,\n            allParts = dateTimeString.split(separator),\n            allPartsLen = allParts.length;\n\n        if (allPartsLen > 1) {\n            return {\n                dateString: allParts.splice(0, allPartsLen - timePartsLen).join(separator),\n                timeString: allParts.splice(0, timePartsLen).join(separator)\n            };\n        }\n\n        return {\n            dateString: dateTimeString,\n            timeString: ''\n        };\n    };\n\n    /*\n    * Internal function to parse datetime interval\n    * Returns: {date: Date, timeObj: Object}, where\n    *   date - parsed date without time (type Date)\n    *   timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional\n    */\n    var parseDateTimeInternal = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {\n        var date,\n            parts,\n            parsedTime;\n\n        parts = splitDateTime(dateTimeString, timeSettings);\n        date = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings);\n\n        if (parts.timeString === '') {\n            return {\n                date: date\n            };\n        }\n\n        parsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings);\n\n        if (!parsedTime) {\n            throw 'Wrong time format';\n        }\n\n        return {\n            date: date,\n            timeObj: parsedTime\n        };\n    };\n\n    /*\n    * Internal function to set timezone_select to the local timezone\n    */\n    var selectLocalTimezone = function (tp_inst, date) {\n        if (tp_inst && tp_inst.timezone_select) {\n            var now = date || new Date();\n            tp_inst.timezone_select.val(-now.getTimezoneOffset());\n        }\n    };\n\n    /*\n    * Create a Singleton Instance\n    */\n    $.timepicker = new Timepicker();\n\n    /**\n     * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)\n     * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned\n     * @param {boolean} iso8601 if true formats in accordance to iso8601 \"+12:45\"\n     * @return {string}\n     */\n    $.timepicker.timezoneOffsetString = function (tzMinutes, iso8601) {\n        if (isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720) {\n            return tzMinutes;\n        }\n\n        var off = tzMinutes,\n            minutes = off % 60,\n            hours = (off - minutes) / 60,\n            iso = iso8601 ? ':' : '',\n            tz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2);\n\n        if (tz === '+00:00') {\n            return 'Z';\n        }\n        return tz;\n    };\n\n    /**\n     * Get the number in minutes that represents a timezone string\n     * @param  {string} tzString formatted like \"+0500\", \"-1245\", \"Z\"\n     * @return {number} the offset minutes or the original string if it doesn't match expectations\n     */\n    $.timepicker.timezoneOffsetNumber = function (tzString) {\n        var normalized = tzString.toString().replace(':', ''); // excuse any iso8601, end up with \"+1245\"\n\n        if (normalized.toUpperCase() === 'Z') { // if iso8601 with Z, its 0 minute offset\n            return 0;\n        }\n\n        if (!/^(\\-|\\+)\\d{4}$/.test(normalized)) { // possibly a user defined tz, so just give it back\n            return parseInt(tzString, 10);\n        }\n\n        return ((normalized.substr(0, 1) === '-' ? -1 : 1) * // plus or minus\n            ((parseInt(normalized.substr(1, 2), 10) * 60) + // hours (converted to minutes)\n                parseInt(normalized.substr(3, 2), 10))); // minutes\n    };\n\n    /**\n     * No way to set timezone in js Date, so we must adjust the minutes to compensate. (think setDate, getDate)\n     * @param  {Date} date\n     * @param  {string} fromTimezone formatted like \"+0500\", \"-1245\"\n     * @param  {string} toTimezone formatted like \"+0500\", \"-1245\"\n     * @return {Date}\n     */\n    $.timepicker.timezoneAdjust = function (date, fromTimezone, toTimezone) {\n        var fromTz = $.timepicker.timezoneOffsetNumber(fromTimezone);\n        var toTz = $.timepicker.timezoneOffsetNumber(toTimezone);\n        if (!isNaN(toTz)) {\n            date.setMinutes(date.getMinutes() + (-fromTz) - (-toTz));\n        }\n        return date;\n    };\n\n    /**\n     * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to\n     * enforce date range limits.\n     * n.b. The input value must be correctly formatted (reformatting is not supported)\n     * @param  {Element} startTime\n     * @param  {Element} endTime\n     * @param  {Object} options Options for the timepicker() call\n     * @return {jQuery}\n     */\n    $.timepicker.timeRange = function (startTime, endTime, options) {\n        return $.timepicker.handleRange('timepicker', startTime, endTime, options);\n    };\n\n    /**\n     * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to\n     * enforce date range limits.\n     * @param  {Element} startTime\n     * @param  {Element} endTime\n     * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,\n     *   a boolean value that can be used to reformat the input values to the `dateFormat`.\n     * @param  {string} method Can be used to specify the type of picker to be added\n     * @return {jQuery}\n     */\n    $.timepicker.datetimeRange = function (startTime, endTime, options) {\n        $.timepicker.handleRange('datetimepicker', startTime, endTime, options);\n    };\n\n    /**\n     * Calls `datepicker` on the `startTime` and `endTime` elements, and configures them to\n     * enforce date range limits.\n     * @param  {Element} startTime\n     * @param  {Element} endTime\n     * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,\n     *   a boolean value that can be used to reformat the input values to the `dateFormat`.\n     * @return {jQuery}\n     */\n    $.timepicker.dateRange = function (startTime, endTime, options) {\n        $.timepicker.handleRange('datepicker', startTime, endTime, options);\n    };\n\n    /**\n     * Calls `method` on the `startTime` and `endTime` elements, and configures them to\n     * enforce date range limits.\n     * @param  {string} method Can be used to specify the type of picker to be added\n     * @param  {Element} startTime\n     * @param  {Element} endTime\n     * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,\n     *   a boolean value that can be used to reformat the input values to the `dateFormat`.\n     * @return {jQuery}\n     */\n    $.timepicker.handleRange = function (method, startTime, endTime, options) {\n        options = $.extend({}, {\n            minInterval: 0, // min allowed interval in milliseconds\n            maxInterval: 0, // max allowed interval in milliseconds\n            start: {},      // options for start picker\n            end: {}         // options for end picker\n        }, options);\n\n        // for the mean time this fixes an issue with calling getDate with timepicker()\n        var timeOnly = false;\n        if(method === 'timepicker'){\n            timeOnly = true;\n            method = 'datetimepicker';\n        }\n\n        function checkDates(changed, other) {\n            var startdt = startTime[method]('getDate'),\n                enddt = endTime[method]('getDate'),\n                changeddt = changed[method]('getDate');\n\n            if (startdt !== null) {\n                var minDate = new Date(startdt.getTime()),\n                    maxDate = new Date(startdt.getTime());\n\n                minDate.setMilliseconds(minDate.getMilliseconds() + options.minInterval);\n                maxDate.setMilliseconds(maxDate.getMilliseconds() + options.maxInterval);\n\n                if (options.minInterval > 0 && minDate > enddt) { // minInterval check\n                    endTime[method]('setDate', minDate);\n                }\n                else if (options.maxInterval > 0 && maxDate < enddt) { // max interval check\n                    endTime[method]('setDate', maxDate);\n                }\n                else if (startdt > enddt) {\n                    other[method]('setDate', changeddt);\n                }\n            }\n        }\n\n        function selected(changed, other, option) {\n            if (!changed.val()) {\n                return;\n            }\n            var date = changed[method].call(changed, 'getDate');\n            if (date !== null && options.minInterval > 0) {\n                if (option === 'minDate') {\n                    date.setMilliseconds(date.getMilliseconds() + options.minInterval);\n                }\n                if (option === 'maxDate') {\n                    date.setMilliseconds(date.getMilliseconds() - options.minInterval);\n                }\n            }\n\n            if (date.getTime) {\n                other[method].call(other, 'option', option, date);\n            }\n        }\n\n        $.fn[method].call(startTime, $.extend({\n            timeOnly: timeOnly,\n            onClose: function (dateText, inst) {\n                checkDates($(this), endTime);\n            },\n            onSelect: function (selectedDateTime) {\n                selected($(this), endTime, 'minDate');\n            }\n        }, options, options.start));\n        $.fn[method].call(endTime, $.extend({\n            timeOnly: timeOnly,\n            onClose: function (dateText, inst) {\n                checkDates($(this), startTime);\n            },\n            onSelect: function (selectedDateTime) {\n                selected($(this), startTime, 'maxDate');\n            }\n        }, options, options.end));\n\n        checkDates(startTime, endTime);\n\n        selected(startTime, endTime, 'minDate');\n        selected(endTime, startTime, 'maxDate');\n\n        return $([startTime.get(0), endTime.get(0)]);\n    };\n\n    /**\n     * Log error or data to the console during error or debugging\n     * @param  {Object} err pass any type object to log to the console during error or debugging\n     * @return {void}\n     */\n    $.timepicker.log = function () {\n        // Older IE (9, maybe 10) throw error on accessing `window.console.log.apply`, so check first.\n        if (window.console && window.console.log && window.console.log.apply) {\n            window.console.log.apply(window.console, Array.prototype.slice.call(arguments));\n        }\n    };\n\n    /*\n     * Add util object to allow access to private methods for testability.\n     */\n    $.timepicker._util = {\n        _extendRemove: extendRemove,\n        _isEmptyObject: isEmptyObject,\n        _convert24to12: convert24to12,\n        _detectSupport: detectSupport,\n        _selectLocalTimezone: selectLocalTimezone,\n        _computeEffectiveSetting: computeEffectiveSetting,\n        _splitDateTime: splitDateTime,\n        _parseDateTimeInternal: parseDateTimeInternal\n    };\n\n    /*\n    * Microsecond support\n    */\n    if (!Date.prototype.getMicroseconds) {\n        Date.prototype.microseconds = 0;\n        Date.prototype.getMicroseconds = function () { return this.microseconds; };\n        Date.prototype.setMicroseconds = function (m) {\n            this.setMilliseconds(this.getMilliseconds() + Math.floor(m / 1000));\n            this.microseconds = m % 1000;\n            return this;\n        };\n    }\n\n    /*\n    * Keep up with the version\n    */\n    $.timepicker.version = \"1.6.3\";\n\n}));\n","jquery/jquery.validate.js":"/*!\n * jQuery Validation Plugin v1.19.5\n *\n * https://jqueryvalidation.org/\n *\n * Copyright (c) 2022 J\u00f6rn Zaefferer\n * Released under the MIT license\n */\n(function( factory ) {\n    if ( typeof define === \"function\" && define.amd ) {\n        define( [\"jquery\", \"jquery/jquery.metadata\"], factory );\n    } else if (typeof module === \"object\" && module.exports) {\n        module.exports = factory( require( \"jquery\" ) );\n    } else {\n        factory( jQuery );\n    }\n}(function( $ ) {\n\n    $.extend( $.fn, {\n\n        // https://jqueryvalidation.org/validate/\n        validate: function( options ) {\n\n            // If nothing is selected, return nothing; can't chain anyway\n            if ( !this.length ) {\n                if ( options && options.debug && window.console ) {\n                    console.warn( \"Nothing selected, can't validate, returning nothing.\" );\n                }\n                return;\n            }\n\n            // Check if a validator for this form was already created\n            var validator = $.data( this[ 0 ], \"validator\" );\n            if ( validator ) {\n                return validator;\n            }\n\n            // Add novalidate tag if HTML5.\n            this.attr( \"novalidate\", \"novalidate\" );\n\n            validator = new $.validator( options, this[ 0 ] );\n            $.data( this[ 0 ], \"validator\", validator );\n\n            if ( validator.settings.onsubmit ) {\n\n                this.on( \"click.validate\", \":submit\", function( event ) {\n\n                    // Track the used submit button to properly handle scripted\n                    // submits later.\n                    validator.submitButton = event.currentTarget;\n\n                    // Allow suppressing validation by adding a cancel class to the submit button\n                    if ( $( this ).hasClass( \"cancel\" ) ) {\n                        validator.cancelSubmit = true;\n                    }\n\n                    // Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button\n                    if ( $( this ).attr( \"formnovalidate\" ) !== undefined ) {\n                        validator.cancelSubmit = true;\n                    }\n                } );\n\n                // Validate the form on submit\n                this.on( \"submit.validate\", function( event ) {\n                    if ( validator.settings.debug ) {\n\n                        // Prevent form submit to be able to see console output\n                        event.preventDefault();\n                    }\n\n                    function handle() {\n                        var hidden, result;\n\n                        // Insert a hidden input as a replacement for the missing submit button\n                        // The hidden input is inserted in two cases:\n                        //   - A user defined a `submitHandler`\n                        //   - There was a pending request due to `remote` method and `stopRequest()`\n                        //     was called to submit the form in case it's valid\n                        if ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) {\n                            hidden = $( \"<input type='hidden'/>\" )\n                                .attr( \"name\", validator.submitButton.name )\n                                .val( $( validator.submitButton ).val() )\n                                .appendTo( validator.currentForm );\n                        }\n\n                        if ( validator.settings.submitHandler && !validator.settings.debug ) {\n                            result = validator.settings.submitHandler.call( validator, validator.currentForm, event );\n                            if ( hidden ) {\n\n                                // And clean up afterwards; thanks to no-block-scope, hidden can be referenced\n                                hidden.remove();\n                            }\n                            if ( result !== undefined ) {\n                                return result;\n                            }\n                            return false;\n                        }\n                        return true;\n                    }\n\n                    // Prevent submit for invalid forms or custom submit handlers\n                    if ( validator.cancelSubmit ) {\n                        validator.cancelSubmit = false;\n                        return handle();\n                    }\n                    if ( validator.form() ) {\n                        if ( validator.pendingRequest ) {\n                            validator.formSubmitted = true;\n                            return false;\n                        }\n                        return handle();\n                    } else {\n                        validator.focusInvalid();\n                        return false;\n                    }\n                } );\n            }\n\n            return validator;\n        },\n\n        // https://jqueryvalidation.org/valid/\n        valid: function() {\n            var valid, validator, errorList;\n\n            if ( $( this[ 0 ] ).is( \"form\" ) ) {\n                valid = this.validate().form();\n            } else {\n                errorList = [];\n                valid = true;\n                validator = $( this[ 0 ].form ).validate();\n                this.each( function() {\n                    valid = validator.element( this ) && valid;\n                    if ( !valid ) {\n                        errorList = errorList.concat( validator.errorList );\n                    }\n                } );\n                validator.errorList = errorList;\n            }\n            return valid;\n        },\n\n        // https://jqueryvalidation.org/rules/\n        rules: function( command, argument ) {\n            var element = this[ 0 ],\n                isContentEditable = typeof this.attr( \"contenteditable\" ) !== \"undefined\" && this.attr( \"contenteditable\" ) !== \"false\",\n                settings, staticRules, existingRules, data, param, filtered;\n\n            // If nothing is selected, return empty object; can't chain anyway\n            if ( element == null ) {\n                return;\n            }\n\n            if ( !element.form && isContentEditable ) {\n                element.form = this.closest( \"form\" )[ 0 ];\n                element.name = this.attr( \"name\" );\n            }\n\n            if ( element.form == null ) {\n                return;\n            }\n\n            if ( command ) {\n                settings = $.data( element.form, \"validator\" ).settings;\n                staticRules = settings.rules;\n                existingRules = $.validator.staticRules( element );\n                switch ( command ) {\n                    case \"add\":\n                        $.extend( existingRules, $.validator.normalizeRule( argument ) );\n\n                        // Remove messages from rules, but allow them to be set separately\n                        delete existingRules.messages;\n                        staticRules[ element.name ] = existingRules;\n                        if ( argument.messages ) {\n                            settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );\n                        }\n                        break;\n                    case \"remove\":\n                        if ( !argument ) {\n                            delete staticRules[ element.name ];\n                            return existingRules;\n                        }\n                        filtered = {};\n                        $.each( argument.split( /\\s/ ), function( index, method ) {\n                            filtered[ method ] = existingRules[ method ];\n                            delete existingRules[ method ];\n                        } );\n                        return filtered;\n                }\n            }\n\n            data = $.validator.normalizeRules(\n                $.extend(\n                    {},\n                    $.validator.metadataRules(element),\n                    $.validator.classRules( element ),\n                    $.validator.attributeRules( element ),\n                    $.validator.dataRules( element ),\n                    $.validator.staticRules( element )\n                ), element );\n\n            // Make sure required is at front\n            if ( data.required ) {\n                param = data.required;\n                delete data.required;\n                data = $.extend( { required: param }, data );\n            }\n\n            // Make sure remote is at back\n            if ( data.remote ) {\n                param = data.remote;\n                delete data.remote;\n                data = $.extend( data, { remote: param } );\n            }\n\n            return data;\n        }\n    } );\n\n// JQuery trim is deprecated, provide a trim method based on String.prototype.trim\n    var trim = function( str ) {\n\n        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim#Polyfill\n        return str.replace( /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g, \"\" );\n    };\n\n// Custom selectors\n    $.extend( $.expr.pseudos || $.expr[ \":\" ], {\t\t// '|| $.expr[ \":\" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support\n\n        // https://jqueryvalidation.org/blank-selector/\n        blank: function( a ) {\n            return !trim( \"\" + $( a ).val() );\n        },\n\n        // https://jqueryvalidation.org/filled-selector/\n        filled: function( a ) {\n            var val = $( a ).val();\n            return val !== null && !!trim( \"\" + val );\n        },\n\n        // https://jqueryvalidation.org/unchecked-selector/\n        unchecked: function( a ) {\n            return !$( a ).prop( \"checked\" );\n        }\n    } );\n\n// Constructor for validator\n    $.validator = function( options, form ) {\n        this.settings = $.extend( true, {}, $.validator.defaults, options );\n        this.currentForm = form;\n        this.init();\n    };\n\n// https://jqueryvalidation.org/jQuery.validator.format/\n    $.validator.format = function( source, params ) {\n        if ( arguments.length === 1 ) {\n            return function() {\n                var args = $.makeArray( arguments );\n                args.unshift( source );\n                return $.validator.format.apply( this, args );\n            };\n        }\n        if ( params === undefined ) {\n            return source;\n        }\n        if ( arguments.length > 2 && params.constructor !== Array  ) {\n            params = $.makeArray( arguments ).slice( 1 );\n        }\n        if ( params.constructor !== Array ) {\n            params = [ params ];\n        }\n        $.each( params, function( i, n ) {\n            source = source.replace( new RegExp( \"\\\\{\" + i + \"\\\\}\", \"g\" ), function() {\n                return n;\n            } );\n        } );\n        return source;\n    };\n\n    $.extend( $.validator, {\n\n        defaults: {\n            messages: {},\n            groups: {},\n            rules: {},\n            errorClass: \"error\",\n            pendingClass: \"pending\",\n            validClass: \"valid\",\n            errorElement: \"label\",\n            focusCleanup: false,\n            focusInvalid: true,\n            errorContainer: $( [] ),\n            errorLabelContainer: $( [] ),\n            onsubmit: true,\n            ignore: \":hidden\",\n            ignoreTitle: false,\n            onfocusin: function( element ) {\n                this.lastActive = element;\n\n                // Hide error label and remove error class on focus if enabled\n                if ( this.settings.focusCleanup ) {\n                    if ( this.settings.unhighlight ) {\n                        this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );\n                    }\n                    this.hideThese( this.errorsFor( element ) );\n                }\n            },\n            onfocusout: function( element ) {\n                if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {\n                    this.element( element );\n                }\n            },\n            onkeyup: function( element, event ) {\n\n                // Avoid revalidate the field when pressing one of the following keys\n                // Shift       => 16\n                // Ctrl        => 17\n                // Alt         => 18\n                // Caps lock   => 20\n                // End         => 35\n                // Home        => 36\n                // Left arrow  => 37\n                // Up arrow    => 38\n                // Right arrow => 39\n                // Down arrow  => 40\n                // Insert      => 45\n                // Num lock    => 144\n                // AltGr key   => 225\n                var excludedKeys = [\n                    16, 17, 18, 20, 35, 36, 37,\n                    38, 39, 40, 45, 144, 225\n                ];\n\n                if ( event.which === 9 && this.elementValue( element ) === \"\" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {\n                    return;\n                } else if ( element.name in this.submitted || element.name in this.invalid ) {\n                    this.element( element );\n                }\n            },\n            onclick: function( element ) {\n\n                // Click on selects, radiobuttons and checkboxes\n                if ( element.name in this.submitted ) {\n                    this.element( element );\n\n                    // Or option elements, check parent select in that case\n                } else if ( element.parentNode.name in this.submitted ) {\n                    this.element( element.parentNode );\n                }\n            },\n            highlight: function( element, errorClass, validClass ) {\n                if ( element.type === \"radio\" ) {\n                    this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );\n                } else {\n                    $( element ).addClass( errorClass ).removeClass( validClass );\n                }\n            },\n            unhighlight: function( element, errorClass, validClass ) {\n                if ( element.type === \"radio\" ) {\n                    this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );\n                } else {\n                    $( element ).removeClass( errorClass ).addClass( validClass );\n                }\n            }\n        },\n\n        // https://jqueryvalidation.org/jQuery.validator.setDefaults/\n        setDefaults: function( settings ) {\n            $.extend( $.validator.defaults, settings );\n        },\n\n        messages: {\n            required: \"This field is required.\",\n            remote: \"Please fix this field.\",\n            email: \"Please enter a valid email address.\",\n            url: \"Please enter a valid URL.\",\n            date: \"Please enter a valid date.\",\n            dateISO: \"Please enter a valid date (ISO).\",\n            number: \"Please enter a valid number.\",\n            digits: \"Please enter only digits.\",\n            equalTo: \"Please enter the same value again.\",\n            maxlength: $.validator.format( \"Please enter no more than {0} characters.\" ),\n            minlength: $.validator.format( \"Please enter at least {0} characters.\" ),\n            rangelength: $.validator.format( \"Please enter a value between {0} and {1} characters long.\" ),\n            range: $.validator.format( \"Please enter a value between {0} and {1}.\" ),\n            max: $.validator.format( \"Please enter a value less than or equal to {0}.\" ),\n            min: $.validator.format( \"Please enter a value greater than or equal to {0}.\" ),\n            step: $.validator.format( \"Please enter a multiple of {0}.\" )\n        },\n\n        autoCreateRanges: false,\n\n        prototype: {\n\n            init: function() {\n                this.labelContainer = $( this.settings.errorLabelContainer );\n                this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );\n                this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );\n                this.submitted = {};\n                this.valueCache = {};\n                this.pendingRequest = 0;\n                this.pending = {};\n                this.invalid = {};\n                this.reset();\n\n                var currentForm = this.currentForm,\n                    groups = ( this.groups = {} ),\n                    rules;\n                $.each( this.settings.groups, function( key, value ) {\n                    if ( typeof value === \"string\" ) {\n                        value = value.split( /\\s/ );\n                    }\n                    $.each( value, function( index, name ) {\n                        groups[ name ] = key;\n                    } );\n                } );\n                rules = this.settings.rules;\n                $.each( rules, function( key, value ) {\n                    rules[ key ] = $.validator.normalizeRule( value );\n                } );\n\n                function delegate( event ) {\n                    var isContentEditable = typeof $( this ).attr( \"contenteditable\" ) !== \"undefined\" && $( this ).attr( \"contenteditable\" ) !== \"false\";\n\n                    // Set form expando on contenteditable\n                    if ( !this.form && isContentEditable ) {\n                        this.form = $( this ).closest( \"form\" )[ 0 ];\n                        this.name = $( this ).attr( \"name\" );\n                    }\n\n                    // Ignore the element if it belongs to another form. This will happen mainly\n                    // when setting the `form` attribute of an input to the id of another form.\n                    if ( currentForm !== this.form ) {\n                        return;\n                    }\n\n                    var validator = $.data( this.form, \"validator\" ),\n                        eventType = \"on\" + event.type.replace( /^validate/, \"\" ),\n                        settings = validator.settings;\n                    if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {\n                        settings[ eventType ].call( validator, this, event );\n                    }\n                }\n\n                $( this.currentForm )\n                    .on( \"focusin.validate focusout.validate keyup.validate\",\n                        \":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], \" +\n                        \"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], \" +\n                        \"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], \" +\n                        \"[type='radio'], [type='checkbox'], [contenteditable], [type='button']\", delegate )\n\n                    // Support: Chrome, oldIE\n                    // \"select\" is provided as event.target when clicking a option\n                    .on( \"click.validate\", \"select, option, [type='radio'], [type='checkbox']\", delegate );\n\n                if ( this.settings.invalidHandler ) {\n                    $( this.currentForm ).on( \"invalid-form.validate\", this.settings.invalidHandler );\n                }\n            },\n\n            // https://jqueryvalidation.org/Validator.form/\n            form: function() {\n                this.checkForm();\n                $.extend( this.submitted, this.errorMap );\n                this.invalid = $.extend( {}, this.errorMap );\n                if ( !this.valid() ) {\n                    $( this.currentForm ).triggerHandler( \"invalid-form\", [ this ] );\n                }\n                this.showErrors();\n                return this.valid();\n            },\n\n            checkForm: function() {\n                this.prepareForm();\n                for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {\n                    this.check( elements[ i ] );\n                }\n                return this.valid();\n            },\n\n            // https://jqueryvalidation.org/Validator.element/\n            element: function( element ) {\n                var cleanElement = this.clean( element ),\n                    checkElement = this.validationTargetFor( cleanElement ),\n                    v = this,\n                    result = true,\n                    rs, group;\n\n                if ( checkElement === undefined ) {\n                    delete this.invalid[ cleanElement.name ];\n                } else {\n                    this.prepareElement( checkElement );\n                    this.currentElements = $( checkElement );\n\n                    // If this element is grouped, then validate all group elements already\n                    // containing a value\n                    group = this.groups[ checkElement.name ];\n                    if ( group ) {\n                        $.each( this.groups, function( name, testgroup ) {\n                            if ( testgroup === group && name !== checkElement.name ) {\n                                cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) );\n                                if ( cleanElement && cleanElement.name in v.invalid ) {\n                                    v.currentElements.push( cleanElement );\n                                    result = v.check( cleanElement ) && result;\n                                }\n                            }\n                        } );\n                    }\n\n                    rs = this.check( checkElement ) !== false;\n                    result = result && rs;\n                    if ( rs ) {\n                        this.invalid[ checkElement.name ] = false;\n                    } else {\n                        this.invalid[ checkElement.name ] = true;\n                    }\n\n                    if ( !this.numberOfInvalids() ) {\n\n                        // Hide error containers on last error\n                        this.toHide = this.toHide.add( this.containers );\n                    }\n                    this.showErrors();\n\n                    // Add aria-invalid status for screen readers\n                    $( element ).attr( \"aria-invalid\", !rs );\n                }\n\n                return result;\n            },\n\n            // https://jqueryvalidation.org/Validator.showErrors/\n            showErrors: function( errors ) {\n                if ( errors ) {\n                    var validator = this;\n\n                    // Add items to error list and map\n                    $.extend( this.errorMap, errors );\n                    this.errorList = $.map( this.errorMap, function( message, name ) {\n                        return {\n                            message: message,\n                            element: validator.findByName( name )[ 0 ]\n                        };\n                    } );\n\n                    // Remove items from success list\n                    this.successList = $.grep( this.successList, function( element ) {\n                        return !( element.name in errors );\n                    } );\n                }\n                if ( this.settings.showErrors ) {\n                    this.settings.showErrors.call( this, this.errorMap, this.errorList );\n                } else {\n                    this.defaultShowErrors();\n                }\n            },\n\n            // https://jqueryvalidation.org/Validator.resetForm/\n            resetForm: function() {\n                if ( $.fn.resetForm ) {\n                    $( this.currentForm ).resetForm();\n                }\n                this.invalid = {};\n                this.submitted = {};\n                this.prepareForm();\n                this.hideErrors();\n                var elements = this.elements()\n                    .removeData( \"previousValue\" )\n                    .removeAttr( \"aria-invalid\" );\n\n                this.resetElements( elements );\n            },\n\n            resetElements: function( elements ) {\n                var i;\n\n                if ( this.settings.unhighlight ) {\n                    for ( i = 0; elements[ i ]; i++ ) {\n                        this.settings.unhighlight.call( this, elements[ i ],\n                            this.settings.errorClass, \"\" );\n                        this.findByName( elements[ i ].name ).removeClass( this.settings.validClass );\n                    }\n                } else {\n                    elements\n                        .removeClass( this.settings.errorClass )\n                        .removeClass( this.settings.validClass );\n                }\n            },\n\n            numberOfInvalids: function() {\n                return this.objectLength( this.invalid );\n            },\n\n            objectLength: function( obj ) {\n                /* jshint unused: false */\n                var count = 0,\n                    i;\n                for ( i in obj ) {\n\n                    // This check allows counting elements with empty error\n                    // message as invalid elements\n                    if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) {\n                        count++;\n                    }\n                }\n                return count;\n            },\n\n            hideErrors: function() {\n                this.hideThese( this.toHide );\n            },\n\n            hideThese: function( errors ) {\n                errors.not( this.containers ).text( \"\" );\n                this.addWrapper( errors ).hide();\n            },\n\n            valid: function() {\n                return this.size() === 0;\n            },\n\n            size: function() {\n                return this.errorList.length;\n            },\n\n            focusInvalid: function() {\n                if ( this.settings.focusInvalid ) {\n                    try {\n                        $( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] )\n                            .filter( \":visible\" )\n                            .trigger( \"focus\" )\n\n                            // Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find\n                            .trigger( \"focusin\" );\n                    } catch ( e ) {\n\n                        // Ignore IE throwing errors when focusing hidden elements\n                    }\n                }\n            },\n\n            findLastActive: function() {\n                var lastActive = this.lastActive;\n                return lastActive && $.grep( this.errorList, function( n ) {\n                    return n.element.name === lastActive.name;\n                } ).length === 1 && lastActive;\n            },\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, [contenteditable]\" )\n                    .not( \":submit, :reset, :image, :disabled\" )\n                    .not( this.settings.ignore )\n                    .filter( function() {\n                        var name = this.name || $( this ).attr( \"name\" ); // For contenteditable\n                        var isContentEditable = typeof $( this ).attr( \"contenteditable\" ) !== \"undefined\" && $( this ).attr( \"contenteditable\" ) !== \"false\";\n\n                        if ( !name && validator.settings.debug && window.console ) {\n                            console.error( \"%o has no name assigned\", this );\n                        }\n\n                        // Set form expando on contenteditable\n                        if ( isContentEditable ) {\n                            this.form = $( this ).closest( \"form\" )[ 0 ];\n                            this.name = name;\n                        }\n\n                        // Ignore elements that belong to other/nested forms\n                        if ( this.form !== validator.currentForm ) {\n                            return false;\n                        }\n\n                        // Select only the first element for each name, and only those with rules specified\n                        if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {\n                            return false;\n                        }\n\n                        rulesCache[ name ] = true;\n                        return true;\n                    } );\n            },\n\n            clean: function( selector ) {\n                return $( selector )[ 0 ];\n            },\n\n            errors: function() {\n                var errorClass = this.settings.errorClass.split( \" \" ).join( \".\" );\n                return $( this.settings.errorElement + \".\" + errorClass, this.errorContext );\n            },\n\n            resetInternals: function() {\n                this.successList = [];\n                this.errorList = [];\n                this.errorMap = {};\n                this.toShow = $( [] );\n                this.toHide = $( [] );\n            },\n\n            reset: function() {\n                this.resetInternals();\n                this.currentElements = $( [] );\n            },\n\n            prepareForm: function() {\n                this.reset();\n                this.toHide = this.errors().add( this.containers );\n            },\n\n            prepareElement: function( element ) {\n                this.reset();\n                this.toHide = this.errorsFor( element );\n            },\n\n            elementValue: function( element ) {\n                var $element = $( element ),\n                    type = element.type,\n                    isContentEditable = typeof $element.attr( \"contenteditable\" ) !== \"undefined\" && $element.attr( \"contenteditable\" ) !== \"false\",\n                    val, idx;\n\n                if ( type === \"radio\" || type === \"checkbox\" ) {\n                    return this.findByName( element.name ).filter( \":checked\" ).val();\n                } else if ( type === \"number\" && typeof element.validity !== \"undefined\" ) {\n                    return element.validity.badInput ? \"NaN\" : $element.val();\n                }\n\n                if ( isContentEditable ) {\n                    val = $element.text();\n                } else {\n                    val = $element.val();\n                }\n\n                if ( type === \"file\" ) {\n\n                    // Modern browser (chrome & safari)\n                    if ( val.substr( 0, 12 ) === \"C:\\\\fakepath\\\\\" ) {\n                        return val.substr( 12 );\n                    }\n\n                    // Legacy browsers\n                    // Unix-based path\n                    idx = val.lastIndexOf( \"/\" );\n                    if ( idx >= 0 ) {\n                        return val.substr( idx + 1 );\n                    }\n\n                    // Windows-based path\n                    idx = val.lastIndexOf( \"\\\\\" );\n                    if ( idx >= 0 ) {\n                        return val.substr( idx + 1 );\n                    }\n\n                    // Just the file name\n                    return val;\n                }\n\n                if ( typeof val === \"string\" ) {\n                    return val.replace( /\\r/g, \"\" );\n                }\n                return val;\n            },\n\n            check: function( element ) {\n                element = this.validationTargetFor( this.clean( element ) );\n\n                var rules = $( element ).rules(),\n                    rulesCount = $.map( rules, function( n, i ) {\n                        return i;\n                    } ).length,\n                    dependencyMismatch = false,\n                    val = this.elementValue( element ),\n                    result, method, rule, normalizer;\n\n                // Prioritize the local normalizer defined for this element over the global one\n                // if the former exists, otherwise user the global one in case it exists.\n                if ( typeof rules.normalizer === \"function\" ) {\n                    normalizer = rules.normalizer;\n                } else if (\ttypeof this.settings.normalizer === \"function\" ) {\n                    normalizer = this.settings.normalizer;\n                }\n\n                // If normalizer is defined, then call it to the changed value instead\n                // of using the real one.\n                // Note that `this` in the normalizer is `element`.\n                if ( normalizer ) {\n                    val = normalizer.call( element, val );\n\n                    // Delete the normalizer from rules to avoid treating it as a pre-defined method.\n                    delete rules.normalizer;\n                }\n\n                for ( method in rules ) {\n                    rule = { method: method, parameters: rules[ method ] };\n                    try {\n                        result = $.validator.methods[ method ].call( this, val, element, rule.parameters );\n\n                        // If a method indicates that the field is optional and therefore valid,\n                        // don't mark it as valid when there are no other rules\n                        if ( result === \"dependency-mismatch\" && rulesCount === 1 ) {\n                            dependencyMismatch = true;\n                            continue;\n                        }\n                        dependencyMismatch = false;\n\n                        if ( result === \"pending\" ) {\n                            this.toHide = this.toHide.not( this.errorsFor( element ) );\n                            return;\n                        }\n\n                        if ( !result ) {\n                            this.formatAndAdd( element, rule );\n                            return false;\n                        }\n                    } catch ( e ) {\n                        if ( this.settings.debug && window.console ) {\n                            console.log( \"Exception occurred when checking element \" + element.id + \", check the '\" + rule.method + \"' method.\", e );\n                        }\n                        if ( e instanceof TypeError ) {\n                            e.message += \".  Exception occurred when checking element \" + element.id + \", check the '\" + rule.method + \"' method.\";\n                        }\n\n                        throw e;\n                    }\n                }\n                if ( dependencyMismatch ) {\n                    return;\n                }\n                if ( this.objectLength( rules ) ) {\n                    this.successList.push( element );\n                }\n                return true;\n            },\n\n            // Return the custom message for the given element and validation method\n            // specified in the element's HTML5 data attribute\n            // return the generic message if present and no method specific message is present\n            customDataMessage: function( element, method ) {\n                return $( element ).data( \"msg\" + method.charAt( 0 ).toUpperCase() +\n                    method.substring( 1 ).toLowerCase() ) || $( element ).data( \"msg\" );\n            },\n\n            // Return the custom message for the given element name and validation method\n            customMessage: function( name, method ) {\n                var m = this.settings.messages[ name ];\n                return m && ( m.constructor === String ? m : m[ method ] );\n            },\n\n            // Return the first defined argument, allowing empty strings\n            findDefined: function() {\n                for ( var i = 0; i < arguments.length; i++ ) {\n                    if ( arguments[ i ] !== undefined ) {\n                        return arguments[ i ];\n                    }\n                }\n                return undefined;\n            },\n\n            // The second parameter 'rule' used to be a string, and extended to an object literal\n            // of the following form:\n            // rule = {\n            //     method: \"method name\",\n            //     parameters: \"the given method parameters\"\n            // }\n            //\n            // The old behavior still supported, kept to maintain backward compatibility with\n            // old code, and will be removed in the next major release.\n            defaultMessage: function( element, rule ) {\n                if ( typeof rule === \"string\" ) {\n                    rule = { method: rule };\n                }\n\n                var message = this.findDefined(\n                        this.customMessage( element.name, rule.method ),\n                        this.customDataMessage( element, rule.method ),\n\n                        // 'title' is never undefined, so handle empty string as undefined\n                        !this.settings.ignoreTitle && element.title || undefined,\n                        $.validator.messages[ rule.method ],\n                        \"<strong>Warning: No message defined for \" + element.name + \"</strong>\"\n                    ),\n                    theregex = /\\$?\\{(\\d+)\\}/g;\n                if ( typeof message === \"function\" ) {\n                    message = message.call( this, rule.parameters, element );\n                } else if ( theregex.test( message ) ) {\n                    message = $.validator.format( message.replace( theregex, \"{$1}\" ), rule.parameters );\n                }\n\n                return message;\n            },\n\n            formatAndAdd: function( element, rule ) {\n                var message = this.defaultMessage( element, rule );\n\n                this.errorList.push( {\n                    message: message,\n                    element: element,\n                    method: rule.method\n                } );\n\n                this.errorMap[ element.name ] = message;\n                this.submitted[ element.name ] = message;\n            },\n\n            addWrapper: function( toToggle ) {\n                if ( this.settings.wrapper ) {\n                    toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );\n                }\n                return toToggle;\n            },\n\n            defaultShowErrors: function() {\n                var i, elements, error;\n                for ( i = 0; this.errorList[ i ]; i++ ) {\n                    error = this.errorList[ i ];\n                    if ( this.settings.highlight ) {\n                        this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );\n                    }\n                    this.showLabel( error.element, error.message );\n                }\n                if ( this.errorList.length ) {\n                    this.toShow = this.toShow.add( this.containers );\n                }\n                if ( this.settings.success ) {\n                    for ( i = 0; this.successList[ i ]; i++ ) {\n                        this.showLabel( this.successList[ i ] );\n                    }\n                }\n                if ( this.settings.unhighlight ) {\n                    for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {\n                        this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );\n                    }\n                }\n                this.toHide = this.toHide.not( this.toShow );\n                this.hideErrors();\n                this.addWrapper( this.toShow ).show();\n            },\n\n            validElements: function() {\n                return this.currentElements.not( this.invalidElements() );\n            },\n\n            invalidElements: function() {\n                return $( this.errorList ).map( function() {\n                    return this.element;\n                } );\n            },\n\n            showLabel: function( element, message ) {\n                var place, group, errorID, v,\n                    error = this.errorsFor( element ),\n                    elementID = this.idOrName( element ),\n                    describedBy = $( element ).attr( \"aria-describedby\" );\n\n                if ( error.length ) {\n\n                    // Refresh error/success class\n                    error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );\n\n                    // Replace message on existing label\n                    error.html( message );\n                } else {\n\n                    // Create error element\n                    error = $( \"<\" + this.settings.errorElement + \">\" )\n                        .attr( \"id\", elementID + \"-error\" )\n                        .addClass( this.settings.errorClass )\n                        .html( message || \"\" );\n\n                    // Maintain reference to the element to be placed into the DOM\n                    place = error;\n                    if ( this.settings.wrapper ) {\n\n                        // Make sure the element is visible, even in IE\n                        // actually showing the wrapped element is handled elsewhere\n                        place = error.hide().show().wrap( \"<\" + this.settings.wrapper + \"/>\" ).parent();\n                    }\n                    if ( this.labelContainer.length ) {\n                        this.labelContainer.append( place );\n                    } else if ( this.settings.errorPlacement ) {\n                        this.settings.errorPlacement.call( this, place, $( element ) );\n                    } else {\n                        place.insertAfter( element );\n                    }\n\n                    // Link error back to the element\n                    if ( error.is( \"label\" ) ) {\n\n                        // If the error is a label, then associate using 'for'\n                        error.attr( \"for\", elementID );\n\n                        // If the element is not a child of an associated label, then it's necessary\n                        // to explicitly apply aria-describedby\n                    } else if ( error.parents( \"label[for='\" + this.escapeCssMeta( elementID ) + \"']\" ).length === 0 ) {\n                        errorID = error.attr( \"id\" );\n\n                        // Respect existing non-error aria-describedby\n                        if ( !describedBy ) {\n                            describedBy = errorID;\n                        } else if ( !describedBy.match( new RegExp( \"\\\\b\" + this.escapeCssMeta( errorID ) + \"\\\\b\" ) ) ) {\n\n                            // Add to end of list if not already present\n                            describedBy += \" \" + errorID;\n                        }\n                        $( element ).attr( \"aria-describedby\", describedBy );\n\n                        // If this element is grouped, then assign to all elements in the same group\n                        group = this.groups[ element.name ];\n                        if ( group ) {\n                            v = this;\n                            $.each( v.groups, function( name, testgroup ) {\n                                if ( testgroup === group ) {\n                                    $( \"[name='\" + v.escapeCssMeta( name ) + \"']\", v.currentForm )\n                                        .attr( \"aria-describedby\", error.attr( \"id\" ) );\n                                }\n                            } );\n                        }\n                    }\n                }\n                if ( !message && this.settings.success ) {\n                    error.text( \"\" );\n                    if ( typeof this.settings.success === \"string\" ) {\n                        error.addClass( this.settings.success );\n                    } else {\n                        this.settings.success( error, element );\n                    }\n                }\n                this.toShow = this.toShow.add( error );\n            },\n\n            errorsFor: function( element ) {\n                var name = this.escapeCssMeta( this.idOrName( element ) ),\n                    describer = $( element ).attr( \"aria-describedby\" ),\n                    selector = \"label[for='\" + name + \"'], label[for='\" + name + \"'] *\";\n\n                // 'aria-describedby' should directly reference the error element\n                if ( describer ) {\n                    selector = selector + \", #\" + this.escapeCssMeta( describer )\n                        .replace( /\\s+/g, \", #\" ) + \":visible\";\n                }\n\n                return this\n                    .errors()\n                    .filter( selector );\n            },\n\n            // See https://api.jquery.com/category/selectors/, for CSS\n            // meta-characters that should be escaped in order to be used with JQuery\n            // as a literal part of a name/id or any selector.\n            escapeCssMeta: function( string ) {\n                if ( string === undefined ) {\n                    return \"\";\n                }\n\n                return string.replace( /([\\\\!\"#$%&'()*+,./:;<=>?@\\[\\]^`{|}~])/g, \"\\\\$1\" );\n            },\n\n            idOrName: function( element ) {\n                return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );\n            },\n\n            validationTargetFor: function( element ) {\n\n                // If radio/checkbox, validate first element in group instead\n                if ( this.checkable( element ) ) {\n                    element = this.findByName( element.name );\n                }\n\n                // Always apply ignore filter\n                return $( element ).not( this.settings.ignore )[ 0 ];\n            },\n\n            checkable: function( element ) {\n                return ( /radio|checkbox/i ).test( element.type );\n            },\n\n            findByName: function( name ) {\n                return $( this.currentForm ).find( \"[name='\" + this.escapeCssMeta( name ) + \"']\" );\n            },\n\n            getLength: function( value, element ) {\n                switch ( element.nodeName.toLowerCase() ) {\n                    case \"select\":\n                        return $( \"option:selected\", element ).length;\n                    case \"input\":\n                        if ( this.checkable( element ) ) {\n                            return this.findByName( element.name ).filter( \":checked\" ).length;\n                        }\n                }\n                return value.length;\n            },\n\n            depend: function( param, element ) {\n                return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true;\n            },\n\n            dependTypes: {\n                \"boolean\": function( param ) {\n                    return param;\n                },\n                \"string\": function( param, element ) {\n                    return !!$( param, element.form ).length;\n                },\n                \"function\": function( param, element ) {\n                    return param( element );\n                }\n            },\n\n            optional: function( element ) {\n                var val = this.elementValue( element );\n                return !$.validator.methods.required.call( this, val, element ) && \"dependency-mismatch\";\n            },\n\n            startRequest: function( element ) {\n                if ( !this.pending[ element.name ] ) {\n                    this.pendingRequest++;\n                    $( element ).addClass( this.settings.pendingClass );\n                    this.pending[ element.name ] = true;\n                }\n            },\n\n            stopRequest: function( element, valid ) {\n                this.pendingRequest--;\n\n                // Sometimes synchronization fails, make sure pendingRequest is never < 0\n                if ( this.pendingRequest < 0 ) {\n                    this.pendingRequest = 0;\n                }\n                delete this.pending[ element.name ];\n                $( element ).removeClass( this.settings.pendingClass );\n                if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() && this.pendingRequest === 0 ) {\n                    $( this.currentForm ).trigger( \"submit\" );\n\n                    // Remove the hidden input that was used as a replacement for the\n                    // missing submit button. The hidden input is added by `handle()`\n                    // to ensure that the value of the used submit button is passed on\n                    // for scripted submits triggered by this method\n                    if ( this.submitButton ) {\n                        $( \"input:hidden[name='\" + this.submitButton.name + \"']\", this.currentForm ).remove();\n                    }\n\n                    this.formSubmitted = false;\n                } else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) {\n                    $( this.currentForm ).triggerHandler( \"invalid-form\", [ this ] );\n                    this.formSubmitted = false;\n                }\n            },\n\n            previousValue: function( element, method ) {\n                method = typeof method === \"string\" && method || \"remote\";\n\n                return $.data( element, \"previousValue\" ) || $.data( element, \"previousValue\", {\n                    old: null,\n                    valid: true,\n                    message: this.defaultMessage( element, { method: method } )\n                } );\n            },\n\n            // Cleans up all forms and elements, removes validator-specific events\n            destroy: function() {\n                this.resetForm();\n\n                $( this.currentForm )\n                    .off( \".validate\" )\n                    .removeData( \"validator\" )\n                    .find( \".validate-equalTo-blur\" )\n                    .off( \".validate-equalTo\" )\n                    .removeClass( \"validate-equalTo-blur\" )\n                    .find( \".validate-lessThan-blur\" )\n                    .off( \".validate-lessThan\" )\n                    .removeClass( \"validate-lessThan-blur\" )\n                    .find( \".validate-lessThanEqual-blur\" )\n                    .off( \".validate-lessThanEqual\" )\n                    .removeClass( \"validate-lessThanEqual-blur\" )\n                    .find( \".validate-greaterThanEqual-blur\" )\n                    .off( \".validate-greaterThanEqual\" )\n                    .removeClass( \"validate-greaterThanEqual-blur\" )\n                    .find( \".validate-greaterThan-blur\" )\n                    .off( \".validate-greaterThan\" )\n                    .removeClass( \"validate-greaterThan-blur\" );\n            }\n\n        },\n\n        classRuleSettings: {\n            required: { required: true },\n            email: { email: true },\n            url: { url: true },\n            date: { date: true },\n            dateISO: { dateISO: true },\n            number: { number: true },\n            digits: { digits: true },\n            creditcard: { creditcard: true }\n        },\n\n        addClassRules: function( className, rules ) {\n            if ( className.constructor === String ) {\n                this.classRuleSettings[ className ] = rules;\n            } else {\n                $.extend( this.classRuleSettings, className );\n            }\n        },\n\n        classRules: function( element ) {\n            var rules = {},\n                classes = $( element ).attr( \"class\" );\n\n            if ( classes ) {\n                $.each( classes.split( \" \" ), function() {\n                    if ( this in $.validator.classRuleSettings ) {\n                        $.extend( rules, $.validator.classRuleSettings[ this ] );\n                    }\n                } );\n            }\n            return rules;\n        },\n\n        normalizeAttributeRule: function( rules, type, method, value ) {\n\n            // Convert the value to a number for number inputs, and for text for backwards compability\n            // allows type=\"date\" and others to be compared as strings\n            if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {\n                value = Number( value );\n\n                // Support Opera Mini, which returns NaN for undefined minlength\n                if ( isNaN( value ) ) {\n                    value = undefined;\n                }\n            }\n\n            if ( value || value === 0 ) {\n                rules[ method ] = value;\n            } else if ( type === method && type !== \"range\" ) {\n\n                // Exception: the jquery validate 'range' method\n                // does not test for the html5 'range' type\n                rules[ type === \"date\" ? \"dateISO\" : method ] = true;\n            }\n        },\n\n        attributeRules: function( element ) {\n            var rules = {},\n                $element = $( element ),\n                type = element.getAttribute( \"type\" ),\n                method, value;\n\n            for ( method in $.validator.methods ) {\n\n                // Support for <input required> in both html5 and older browsers\n                if ( method === \"required\" ) {\n                    value = element.getAttribute( method );\n\n                    // Some browsers return an empty string for the required attribute\n                    // and non-HTML5 browsers might have required=\"\" markup\n                    if ( value === \"\" ) {\n                        value = true;\n                    }\n\n                    // Force non-HTML5 browsers to return bool\n                    value = !!value;\n                } else {\n                    value = $element.attr( method );\n                }\n\n                this.normalizeAttributeRule( rules, type, method, value );\n            }\n\n            // 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs\n            if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {\n                delete rules.maxlength;\n            }\n\n            return rules;\n        },\n\n        metadataRules: function (element) {\n            if (!$.metadata) {\n                return {};\n            }\n\n            var meta = $.data(element.form, 'validator').settings.meta;\n            return meta ?\n                $(element).metadata()[meta] :\n                $(element).metadata();\n        },\n\n        dataRules: function( element ) {\n            var rules = {},\n                $element = $( element ),\n                type = element.getAttribute( \"type\" ),\n                method, value;\n\n            for ( method in $.validator.methods ) {\n                value = $element.data( \"rule\" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );\n\n                // Cast empty attributes like `data-rule-required` to `true`\n                if ( value === \"\" ) {\n                    value = true;\n                }\n\n                this.normalizeAttributeRule( rules, type, method, value );\n            }\n            return rules;\n        },\n\n        staticRules: function( element ) {\n            var rules = {},\n                validator = $.data( element.form, \"validator\" );\n\n            if ( validator.settings.rules ) {\n                rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};\n            }\n            return rules;\n        },\n\n        normalizeRules: function( rules, element ) {\n\n            // Handle dependency check\n            $.each( rules, function( prop, val ) {\n\n                // Ignore rule when param is explicitly false, eg. required:false\n                if ( val === false ) {\n                    delete rules[ prop ];\n                    return;\n                }\n                if ( val.param || val.depends ) {\n                    var keepRule = true;\n                    switch ( typeof val.depends ) {\n                        case \"string\":\n                            keepRule = !!$( val.depends, element.form ).length;\n                            break;\n                        case \"function\":\n                            keepRule = val.depends.call( element, element );\n                            break;\n                    }\n                    if ( keepRule ) {\n                        rules[ prop ] = val.param !== undefined ? val.param : true;\n                    } else {\n                        $.data( element.form, \"validator\" ).resetElements( $( element ) );\n                        delete rules[ prop ];\n                    }\n                }\n            } );\n\n            // Evaluate parameters\n            $.each( rules, function( rule, parameter ) {\n                rules[ rule ] = typeof parameter === \"function\" && rule !== \"normalizer\" ? parameter( element ) : parameter;\n            } );\n\n            // Clean number parameters\n            $.each( [ \"minlength\", \"maxlength\" ], function() {\n                if ( rules[ this ] ) {\n                    rules[ this ] = Number( rules[ this ] );\n                }\n            } );\n            $.each( [ \"rangelength\", \"range\" ], function() {\n                var parts;\n                if ( rules[ this ] ) {\n                    if ( Array.isArray( rules[ this ] ) ) {\n                        rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ];\n                    } else if ( typeof rules[ this ] === \"string\" ) {\n                        parts = rules[ this ].replace( /[\\[\\]]/g, \"\" ).split( /[\\s,]+/ );\n                        rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ];\n                    }\n                }\n            } );\n\n            if ( $.validator.autoCreateRanges ) {\n\n                // Auto-create ranges\n                if ( rules.min != null && rules.max != null ) {\n                    rules.range = [ rules.min, rules.max ];\n                    delete rules.min;\n                    delete rules.max;\n                }\n                if ( rules.minlength != null && rules.maxlength != null ) {\n                    rules.rangelength = [ rules.minlength, rules.maxlength ];\n                    delete rules.minlength;\n                    delete rules.maxlength;\n                }\n            }\n\n            return rules;\n        },\n\n        // Converts a simple string to a {string: true} rule, e.g., \"required\" to {required:true}\n        normalizeRule: function( data ) {\n            if ( typeof data === \"string\" ) {\n                var transformed = {};\n                $.each( data.split( /\\s/ ), function() {\n                    transformed[ this ] = true;\n                } );\n                data = transformed;\n            }\n            return data;\n        },\n\n        // https://jqueryvalidation.org/jQuery.validator.addMethod/\n        addMethod: function( name, method, message ) {\n            $.validator.methods[ name ] = method;\n            $.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];\n            if ( method.length < 3 ) {\n                $.validator.addClassRules( name, $.validator.normalizeRule( name ) );\n            }\n        },\n\n        // https://jqueryvalidation.org/jQuery.validator.methods/\n        methods: {\n\n            // https://jqueryvalidation.org/required-method/\n            required: function( value, element, param ) {\n\n                // Check if dependency is met\n                if ( !this.depend( param, element ) ) {\n                    return \"dependency-mismatch\";\n                }\n                if ( element.nodeName.toLowerCase() === \"select\" ) {\n\n                    // Could be an array for select-multiple or a string, both are fine this way\n                    var val = $( element ).val();\n                    return val && val.length > 0;\n                }\n                if ( this.checkable( element ) ) {\n                    return this.getLength( value, element ) > 0;\n                }\n                return value !== undefined && value !== null && value.length > 0;\n            },\n\n            // https://jqueryvalidation.org/email-method/\n            email: function( value, element ) {\n\n                // From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address\n                // Retrieved 2014-01-14\n                // If you have a problem with this implementation, report a bug against the above spec\n                // Or use custom methods to implement your own email validation\n                return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );\n            },\n\n            // https://jqueryvalidation.org/url-method/\n            url: function( value, element ) {\n\n                // Copyright (c) 2010-2013 Diego Perini, MIT licensed\n                // https://gist.github.com/dperini/729294\n                // see also https://mathiasbynens.be/demo/url-regex\n                // modified to allow protocol-relative URLs\n                return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\\/\\/)(?:(?:[^\\]\\[?\\/<~#`!@$^&*()+=}|:\";',>{ ]|%[0-9A-Fa-f]{2})+(?::(?:[^\\]\\[?\\/<~#`!@$^&*()+=}|:\";',>{ ]|%[0-9A-Fa-f]{2})*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z0-9\\u00a1-\\uffff][a-z0-9\\u00a1-\\uffff_-]{0,62})?[a-z0-9\\u00a1-\\uffff]\\.)+(?:[a-z\\u00a1-\\uffff]{2,}\\.?))(?::\\d{2,5})?(?:[/?#]\\S*)?$/i.test( value );\n            },\n\n            // https://jqueryvalidation.org/date-method/\n            date: ( function() {\n                var called = false;\n\n                return function( value, element ) {\n                    if ( !called ) {\n                        called = true;\n                        if ( this.settings.debug && window.console ) {\n                            console.warn(\n                                \"The `date` method is deprecated and will be removed in version '2.0.0'.\\n\" +\n                                \"Please don't use it, since it relies on the Date constructor, which\\n\" +\n                                \"behaves very differently across browsers and locales. Use `dateISO`\\n\" +\n                                \"instead or one of the locale specific methods in `localizations/`\\n\" +\n                                \"and `additional-methods.js`.\"\n                            );\n                        }\n                    }\n\n                    return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );\n                };\n            }() ),\n\n            // https://jqueryvalidation.org/dateISO-method/\n            dateISO: function( value, element ) {\n                return this.optional( element ) || /^\\d{4}[\\/\\-](0?[1-9]|1[012])[\\/\\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );\n            },\n\n            // https://jqueryvalidation.org/number-method/\n            number: function( value, element ) {\n                return this.optional( element ) || /^(?:-?\\d+|-?\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$/.test( value );\n            },\n\n            // https://jqueryvalidation.org/digits-method/\n            digits: function( value, element ) {\n                return this.optional( element ) || /^\\d+$/.test( value );\n            },\n\n            // https://jqueryvalidation.org/minlength-method/\n            minlength: function( value, element, param ) {\n                var length = Array.isArray( value ) ? value.length : this.getLength( value, element );\n                return this.optional( element ) || length >= param;\n            },\n\n            // https://jqueryvalidation.org/maxlength-method/\n            maxlength: function( value, element, param ) {\n                var length = Array.isArray( value ) ? value.length : this.getLength( value, element );\n                return this.optional( element ) || length <= param;\n            },\n\n            // https://jqueryvalidation.org/rangelength-method/\n            rangelength: function( value, element, param ) {\n                var length = Array.isArray( value ) ? value.length : this.getLength( value, element );\n                return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );\n            },\n\n            // https://jqueryvalidation.org/min-method/\n            min: function( value, element, param ) {\n                return this.optional( element ) || value >= param;\n            },\n\n            // https://jqueryvalidation.org/max-method/\n            max: function( value, element, param ) {\n                return this.optional( element ) || value <= param;\n            },\n\n            // https://jqueryvalidation.org/range-method/\n            range: function( value, element, param ) {\n                return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );\n            },\n\n            // https://jqueryvalidation.org/step-method/\n            step: function( value, element, param ) {\n                var type = $( element ).attr( \"type\" ),\n                    errorMessage = \"Step attribute on input type \" + type + \" is not supported.\",\n                    supportedTypes = [ \"text\", \"number\", \"range\" ],\n                    re = new RegExp( \"\\\\b\" + type + \"\\\\b\" ),\n                    notSupported = type && !re.test( supportedTypes.join() ),\n                    decimalPlaces = function( num ) {\n                        var match = ( \"\" + num ).match( /(?:\\.(\\d+))?$/ );\n                        if ( !match ) {\n                            return 0;\n                        }\n\n                        // Number of digits right of decimal point.\n                        return match[ 1 ] ? match[ 1 ].length : 0;\n                    },\n                    toInt = function( num ) {\n                        return Math.round( num * Math.pow( 10, decimals ) );\n                    },\n                    valid = true,\n                    decimals;\n\n                // Works only for text, number and range input types\n                // TODO find a way to support input types date, datetime, datetime-local, month, time and week\n                if ( notSupported ) {\n                    throw new Error( errorMessage );\n                }\n\n                decimals = decimalPlaces( param );\n\n                // Value can't have too many decimals\n                if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) {\n                    valid = false;\n                }\n\n                return this.optional( element ) || valid;\n            },\n\n            // https://jqueryvalidation.org/equalTo-method/\n            equalTo: function( value, element, param ) {\n\n                // Bind to the blur event of the target in order to revalidate whenever the target field is updated\n                var target = $( param );\n                if ( this.settings.onfocusout && target.not( \".validate-equalTo-blur\" ).length ) {\n                    target.addClass( \"validate-equalTo-blur\" ).on( \"blur.validate-equalTo\", function() {\n                        $( element ).valid();\n                    } );\n                }\n                return value === target.val();\n            },\n\n            // https://jqueryvalidation.org/remote-method/\n            remote: function( value, element, param, method ) {\n                if ( this.optional( element ) ) {\n                    return \"dependency-mismatch\";\n                }\n\n                method = typeof method === \"string\" && method || \"remote\";\n\n                var previous = this.previousValue( element, method ),\n                    validator, data, optionDataString;\n\n                if ( !this.settings.messages[ element.name ] ) {\n                    this.settings.messages[ element.name ] = {};\n                }\n                previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ];\n                this.settings.messages[ element.name ][ method ] = previous.message;\n\n                param = typeof param === \"string\" && { url: param } || param;\n                optionDataString = $.param( $.extend( { data: value }, param.data ) );\n                if ( previous.old === optionDataString ) {\n                    return previous.valid;\n                }\n\n                previous.old = optionDataString;\n                validator = this;\n                this.startRequest( element );\n                data = {};\n                data[ element.name ] = value;\n                $.ajax( $.extend( true, {\n                    mode: \"abort\",\n                    port: \"validate\" + element.name,\n                    dataType: \"json\",\n                    data: data,\n                    context: validator.currentForm,\n                    success: function( response ) {\n                        var valid = response === true || response === \"true\",\n                            errors, message, submitted;\n\n                        validator.settings.messages[ element.name ][ method ] = previous.originalMessage;\n                        if ( valid ) {\n                            submitted = validator.formSubmitted;\n                            validator.resetInternals();\n                            validator.toHide = validator.errorsFor( element );\n                            validator.formSubmitted = submitted;\n                            validator.successList.push( element );\n                            validator.invalid[ element.name ] = false;\n                            validator.showErrors();\n                        } else {\n                            errors = {};\n                            message = response || validator.defaultMessage( element, { method: method, parameters: value } );\n                            errors[ element.name ] = previous.message = message;\n                            validator.invalid[ element.name ] = true;\n                            validator.showErrors( errors );\n                        }\n                        previous.valid = valid;\n                        validator.stopRequest( element, valid );\n                    }\n                }, param ) );\n                return \"pending\";\n            }\n        }\n\n    } );\n\n// Ajax mode: abort\n// usage: $.ajax({ mode: \"abort\"[, port: \"uniqueport\"]});\n// if mode:\"abort\" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()\n\n    var pendingRequests = {},\n        ajax;\n\n// Use a prefilter if available (1.5+)\n    if ( $.ajaxPrefilter ) {\n        $.ajaxPrefilter( function( settings, _, xhr ) {\n            var port = settings.port;\n            if ( settings.mode === \"abort\" ) {\n                if ( pendingRequests[ port ] ) {\n                    pendingRequests[ port ].abort();\n                }\n                pendingRequests[ port ] = xhr;\n            }\n        } );\n    } else {\n\n        // Proxy ajax\n        ajax = $.ajax;\n        $.ajax = function( settings ) {\n            var mode = ( \"mode\" in settings ? settings : $.ajaxSettings ).mode,\n                port = ( \"port\" in settings ? settings : $.ajaxSettings ).port;\n            if ( mode === \"abort\" ) {\n                if ( pendingRequests[ port ] ) {\n                    pendingRequests[ port ].abort();\n                }\n                pendingRequests[ port ] = ajax.apply( this, arguments );\n                return pendingRequests[ port ];\n            }\n            return ajax.apply( this, arguments );\n        };\n    }\n    return $;\n}));\n","jquery/z-index.js":"/*!\n * zIndex plugin from jQuery UI Core - v1.10.4\n * http://jqueryui.com\n *\n * Copyright 2014 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/category/ui-core/\n */\ndefine([\n    'jquery'\n], function ($, undefined) {\n\n// plugins\n    $.fn.extend({\n        zIndex: function (zIndex) {\n            if (zIndex !== undefined) {\n                return this.css(\"zIndex\", zIndex);\n            }\n\n            if (this.length) {\n                var elem = $(this[0]), position, value;\n                while (elem.length && elem[0] !== document) {\n                    // Ignore z-index if position is set to a value where z-index is ignored by the browser\n                    // This makes behavior of this function consistent across browsers\n                    // WebKit always returns auto if the element is positioned\n                    position = elem.css(\"position\");\n                    if (position === \"absolute\" || position === \"relative\" || position === \"fixed\") {\n                        // IE returns 0 when zIndex is not specified\n                        // other browsers return a string\n                        // we ignore the case of nested elements with an explicit value of 0\n                        // <div style=\"z-index: -10;\"><div style=\"z-index: 0;\"></div></div>\n                        value = parseInt(elem.css(\"zIndex\"), 10);\n                        if (!isNaN(value) && value !== 0) {\n                            return value;\n                        }\n                    }\n                    elem = elem.parent();\n                }\n            }\n\n            return 0;\n        }\n    });\n});\n","jquery/jquery.tabs.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    \"jquery\",\n    \"jquery/bootstrap/tab\",\n    \"jquery/bootstrap/collapse\",\n], function () {\n\n});\n","jquery/jquery.metadata.js":"/*\n * Metadata - jQuery plugin for parsing metadata from elements\n *\n * Copyright (c) 2006 John Resig, Yehuda Katz, J\u00ef\u00bf\u00bd\u00c3\u00b6rn Zaefferer, Paul McLanahan\n *\n * Dual licensed under the MIT and GPL licenses:\n *   http://www.opensource.org/licenses/mit-license.php\n *   http://www.gnu.org/licenses/gpl.html\n *\n * Revision: $Id: jquery.metadata.js 3640 2007-10-11 18:34:38Z pmclanahan $\n *\n */\n\n/**\n * Sets the type of metadata to use. Metadata is encoded in JSON, and each property\n * in the JSON will become a property of the element itself.\n *\n * There are four supported types of metadata storage:\n *\n *   attr:  Inside an attribute. The name parameter indicates *which* attribute.\n *\n *   class: Inside the class attribute, wrapped in curly braces: { }\n *\n *   elem:  Inside a child element (e.g. a script tag). The\n *          name parameter indicates *which* element.\n *   html5: Values are stored in data-* attributes.\n *\n * The metadata for an element is loaded the first time the element is accessed via jQuery.\n *\n * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements\n * matched by expr, then redefine the metadata type and run another $(expr) for other elements.\n *\n * @name $.metadata.setType\n *\n * @example <p id=\"one\" class=\"some_class {item_id: 1, item_label: 'Label'}\">This is a p</p>\n * @before $.metadata.setType(\"class\")\n * @after $(\"#one\").metadata().item_id == 1; $(\"#one\").metadata().item_label == \"Label\"\n * @desc Reads metadata from the class attribute\n *\n * @example <p id=\"one\" class=\"some_class\" data=\"{item_id: 1, item_label: 'Label'}\">This is a p</p>\n * @before $.metadata.setType(\"attr\", \"data\")\n * @after $(\"#one\").metadata().item_id == 1; $(\"#one\").metadata().item_label == \"Label\"\n * @desc Reads metadata from a \"data\" attribute\n *\n * @example <p id=\"one\" class=\"some_class\"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>\n * @before $.metadata.setType(\"elem\", \"script\")\n * @after $(\"#one\").metadata().item_id == 1; $(\"#one\").metadata().item_label == \"Label\"\n * @desc Reads metadata from a nested script element\n *\n * @example <p id=\"one\" class=\"some_class\" data-item_id=\"1\" data-item_label=\"Label\">This is a p</p>\n * @before $.metadata.setType(\"html5\")\n * @after $(\"#one\").metadata().item_id == 1; $(\"#one\").metadata().item_label == \"Label\"\n * @desc Reads metadata from a series of data-* attributes\n *\n * @param String type The encoding type\n * @param String name The name of the attribute to be used to get metadata (optional)\n * @cat Plugins/Metadata\n * @descr Sets the type of encoding to be used when loading metadata for the first time\n * @type undefined\n * @see metadata()\n */\n(function (factory) {\n    if (typeof define === 'function' && define.amd) {\n        define([\"jquery\"], factory);\n    } else {\n        factory(jQuery);\n    }\n}(function ($) {\n\n\n    $.extend({\n        metadata : {\n            defaults : {\n                type: 'class',\n                name: 'metadata',\n                cre: /({.*})/,\n                single: 'metadata',\n                meta:'validate'\n            },\n            setType: function( type, name ){\n                this.defaults.type = type;\n                this.defaults.name = name;\n            },\n            get: function( elem, opts ){\n                var settings = $.extend({},this.defaults,opts);\n                // check for empty string in single property\n                if (!settings.single.length) {\n                    settings.single = 'metadata';\n                }\n                if (!settings.meta.length) {\n                    settings.meta = 'validate';\n                }\n\n                var data = $.data(elem, settings.single);\n                // returned cached data if it already exists\n                if ( data ) return data;\n\n                data = \"{}\";\n\n                var getData = function(data) {\n                    if(typeof data != \"string\") return data;\n\n                    if( data.indexOf('{') < 0 ) {\n                        data = eval(\"(\" + data + \")\");\n                    }\n                }\n\n                var getObject = function(data) {\n                    if(typeof data != \"string\") return data;\n\n                    data = eval(\"(\" + data + \")\");\n                    return data;\n                }\n\n                if ( settings.type == \"html5\" ) {\n                    var object = {};\n                    $( elem.attributes ).each(function() {\n                        var name = this.nodeName;\n                        if (name.indexOf('data-' + settings.meta) === 0) {\n                            name = name.replace(/^data-/, '');\n                        }\n                        else {\n                            return true;\n                        }\n                        object[name] = getObject(this.value);\n                    });\n                } else {\n                    if ( settings.type == \"class\" ) {\n                        var m = settings.cre.exec( elem.className );\n                        if ( m )\n                            data = m[1];\n                    } else if ( settings.type == \"elem\" ) {\n                        if( !elem.getElementsByTagName ) return;\n                        var e = elem.getElementsByTagName(settings.name);\n                        if ( e.length )\n                            data = $.trim(e[0].innerHTML);\n                    } else if ( elem.getAttribute != undefined ) {\n                        var attr = elem.getAttribute( settings.name );\n                        if ( attr )\n                            data = attr;\n                    }\n                    object = getObject(data.indexOf(\"{\") < 0 ? \"{\" + data + \"}\" : data);\n                }\n\n                $.data( elem, settings.single, object );\n                return object;\n            }\n        }\n    });\n\n    /**\n     * Returns the metadata object for the first member of the jQuery object.\n     *\n     * @name metadata\n     * @descr Returns element's metadata object\n     * @param Object opts An object contianing settings to override the defaults\n     * @type jQuery\n     * @cat Plugins/Metadata\n     */\n    $.fn.metadata = function( opts ){\n        return $.metadata.get( this[0], opts );\n    };\n\n}));","jquery/jquery.cookie.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'js-cookie/cookie-wrapper'\n], function () {\n\n});\n"}
}});

Spamworldpro Mini