/* Minification failed. Returning unminified contents.
(7068,292-293): run-time error JS1006: Expected ')': ]
(7068,300): run-time error JS1004: Expected ';'
(7068,300-301): run-time error JS1195: Expected expression: )
(7068,301-302): run-time error JS1195: Expected expression: .
(7068,358-359): run-time error JS1006: Expected ')': ]
(7068,367): run-time error JS1004: Expected ';'
(7068,367-368): run-time error JS1195: Expected expression: )
(7068,358-359): run-time error JS1013: Syntax error in regular expression: ]
(7068,292-293): run-time error JS1013: Syntax error in regular expression: ]
 */
namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.FormBuilderFormModel = Backbone.Model.extend(
{
    initialize: function (model, settings)
    {
        this.settings = settings || {};
        settings.fieldModelFunc = settings.fieldModel ? getFunctionByName(this.settings.fieldModel) : awardsCommon.FieldModel;

        var fields = this.get("fields");

        _.each(this.get("pages"), function (page, index)
        {
            var pageFields = _(fields).filter(function (f)
            {
                return _(page.fieldIds).contains(f.id);
            });

            page.readOnly = _(pageFields).all(function (f)
            {
                return f.data.readOnly;
            });

            page.index = index;
        });

        this.attributes.fields = new awardsCommon.FieldCollection(this.get("fields"), settings);
    },
    toJSON: function (options)
    {
        var data = Backbone.Model.prototype.toJSON.call(this, options);
        delete data.readOnly;

        return data;
    },

    getPageId: function (fieldId)
    {
        var page = _(this.get("pages")).find(function (item) { return _.include(item.fieldIds, fieldId); });
        return page ? page.id : null;
    },
    getFieldById: function (fieldId)
    {
        return this.get("fields").find(function (field) { return field.id == fieldId; });
    }
});;(function ($)
{
    $.extend($.fn,
    {
        formBuilderForm: function (model, settings)
        {
            if (this.length == 0)
                return null;

            var formBuilderFormEl = this.is(".formBuilder.form") ? this : this.find(".formBuilder.form");
            if (formBuilderFormEl.length == 0)
                return null;

            var fbForm = formBuilderFormEl.data("formBuilderForm");
            if (fbForm)
                return fbForm;

            fbForm = new awardsCommon.widgets.formBuilderForm.FormBuilderFormView(
            {
                el: formBuilderFormEl,
                model: new awardsCommon.widgets.formBuilderForm.FormBuilderFormModel(model, settings),
                settings: settings
            });
            this.data("formBuilderForm", fbForm);

            fbForm.render();
            return fbForm;
        }
    });
} (jQuery));
;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.FormBuilderFormView = Backbone.View.extend(
{
    events:
    {
        "click a.breadCrumbLink:not(.selected, .notAccessible)": "onBreadCrumbLinkClicked",
        "change .fieldSection input:radio, .fieldSection input:checkbox, select": "onDependentFieldsParentElementClicked",
        "click .resetRadioListSelectedValues a": "onResetRadioListSelectedValues",
        "focusout section.url input": "onUrlFocusOut",
        "change .address select[name$='.CountryCode']": "onAddressCountryChanged"
    },

    initialize: function ()
    {
        var form = this.$el.closest("form");
        this.$form = form;

        var self = this;

        form.on("error", this.onFormError);

        var disabledUntilFormSavedClass = "disabledUntilFormSaved";
        form.on("submit", function ()
        {
            var buttonsToDisableOnFormSubmit = self.$("button.disableOnSubmit").not(":disabled");
            buttonsToDisableOnFormSubmit.prop("disabled", true);
            buttonsToDisableOnFormSubmit.addClass(disabledUntilFormSavedClass);
        });
        form.on("save error cancel", function ()
        {
            var buttonsDisabledOnFormSubmit = self.$("button.disableOnSubmit." + disabledUntilFormSavedClass);
            buttonsDisabledOnFormSubmit.prop("disabled", false);
        });
        
        // compile templates
        $.templates("textTmpl", this.$("#textTmpl").html());
        $.templates("emailTmpl", this.$("#emailTmpl").html());
        $.templates("dropDownListTmpl", this.$("#dropDownListTmpl").html());
        $.templates("dropDownItemTmpl", this.$("#dropDownItemTmpl").html());
        $.templates("radioListTmpl", this.$("#radioListTmpl").html());
        $.templates("radioItemTmpl", this.$("#radioItemTmpl").html());
        $.templates("checkBoxListTmpl", this.$("#checkBoxListTmpl").html());
        $.templates("checkBoxItemTmpl", this.$("#checkBoxItemTmpl").html());
        $.templates("multilineTextTmpl", this.$("#multilineTextTmpl").html());
        $.templates("numberTmpl", this.$("#numberTmpl").html());
        $.templates("dateTmpl", this.$("#dateTmpl").html());
        $.templates("confirmationTmpl", this.$("#confirmationTmpl").html());
        $.templates("separatorTmpl", this.$("#separatorTmpl").html());
        $.templates("fileUploadTmpl", this.$("#fileUploadTmpl").html());
        $.templates("labelTmpl", this.$("#labelTmpl").html());
        $.templates("detailsTmpl", this.$("#detailsTmpl").html());
        $.templates("deleteBtnTmpl", this.$("#deleteBtnTmpl").html());
        $.templates("fieldInfoTmpl", this.$("#fieldInfoTmpl").html());
        $.templates("sectionAttributesTmpl", this.$("#sectionAttributesTmpl").html());
        $.templates("inputAttributesTmpl", this.$("#inputAttributesTmpl").html());
        $.templates("rightTmpl", this.$("#rightTmpl").html());
        $.templates("breadCrumbTmpl", this.$("#breadCrumbTmpl").html());
        $.templates("urlTmpl", this.$("#urlTmpl").html());
        $.templates("addressTmpl", this.$("#addressTmpl").html());
        $.templates("addressStateTmpl", this.$("#addressStateTmpl").html());
        $.templates("textFieldLengthCounterTmpl", this.$("#textFieldLengthCounterTmpl").html());
        $.templates("imisNumberFieldTmpl", this.$("#imisNumberFieldTmpl").html());
        $.templates("tableFieldTmpl", this.$("#tableFieldTmpl").html());
        $.templates("digitalSignatureFieldTmpl", this.$("#digitalSignatureFieldTmpl").html());
        $.templates("phoneNumberFieldTmpl", this.$("#phoneNumberFieldTmpl").html());

        // some fields can have subordinate sections (confirmation section for email field, scores in Awards), 
        // this query includes such sections into result set
        $.fn.extend(
        {
            includeSubordinateSections: function ()
            {
                return this.nextUntil("section[id]", "section:not(.control):not(.static)").addBack();
            }
        });

        _(this.settings.customSections).each(function (item)
        {
            var found = $(item.jsTemplate);
            if (found.length > 0)
                $.templates(item.jsTemplate, found.html());
        });

        _(this.settings.overriddenTemplates).each(function (value, key)
        {
            var found = $(value);
            if (found.length > 0)
                $.templates(key, found.html());
        });

        // clone and save compiled templates in a local instance
        this.templates = _.clone($.templates);

        this.fieldModels = {};
        this.fieldViews = {};
        this.fieldSections = new Map();
        this.fieldAliasesIds = {};

        this.model.get("fields").walkTree(function (field)
        {
            self.fieldAliasesIds[field.get("alias")] = field.id;
        });
    },
    render: function ()
    {
        this.clear();
        this.renderControlSections("top");
        this.renderFields();
        this.renderControlSections("bottom");
        this.renderStaticSections();

        if (!this.settings.showAllPages)
            this.goToFirstPage();
    },

    onHiddenOrHiddenByParentChanged: function (field)
    {
        if (field.isVisible())
            this.showField(field);
        else
            this.hideField(field);

        var selectedValues = this.getSelectedValuesForField(field);
        _(this.getDependentFieldsFor(field)).each(function (depField)
        {
            var depFieldSelectedListValueId = depField.get("visibilityCondition").selectedListValueId;
            depField.set({ hiddenByParent: !field.isVisible() || !_(selectedValues).contains(depFieldSelectedListValueId) });
        });
    },

    onAddressCountryChanged: function (event)
    {
        this.updateAddressStateInput(event.target, this.fieldModels[$(event.target).closest("section").attr("data-fieldPath")].get("prefix"));
    },
    onWysiwygWithLimitedMaxLengthTextChanged: function (event)
    {
        this.updateTextLengthCounterForWysiwygField($(event.editor.element.$));
    },
    onResetRadioListSelectedValues: function (event, options)
    {
        options = _.extend({ suppressHidingFieldsConfirmation: false, suppressChangeEvent: false }, options);

        var $target = $(event.target).parents(".resetRadioListSelectedValues");
        var section = $target.closest("section");
        var sectionId = section.attr("id");

        if (!sectionId)
            return;

        var field = this.fieldModels[section.attr("data-fieldPath")];
        var dependentFields = this.getDependentFieldsFor(field, false);

        var confirmCallback = function ()
        {
            $target.toggle(false);

            var selectedRadioButton = $target.siblings().find("input[type=radio]:checked");
            selectedRadioButton.prop("checked", false);
            if (!options.suppressChangeEvent)
                selectedRadioButton.change();

            field.set({ previousSelectedValueIds: [] });
            _(dependentFields).each(function (depField)
            {
                depField.set({ hiddenByParent: true });
            });
        };

        if (options.suppressHidingFieldsConfirmation)
            confirmCallback();
        else
            this.askToHideFields(dependentFields, confirmCallback);
    },

    renderFields: function ()
    {
        if (!this.model.readOnly)
        {
            this.ensureFormValidatorAttached();
            this.initializeValidationMethods();
        }

        if (!this.settings.hideBreadCrumb)
            this.renderBreadCrumb();

        var self = this;
        var appendAfter = null;
        var fieldSections = this.$("section[data-pageid]:not(.control)");
        if (fieldSections.length > 0)
            appendAfter = fieldSections.last();
        else if (this.$("section.control.topControl").length > 0)
            appendAfter = this.$("section.control.topControl:last");
        else if (this.$("section.control.bottomControl").length > 0)
            appendAfter = function (el) { self.$("section.control.bottomControl:first").before(el); };

        var fields = this.prepareFieldViewModel(this.model.get("fields"), this.model.get("fieldValues"), { prefix: this.settings.fieldPrefix });
        this.renderContainerFields(fields, appendAfter);

        fieldSections.remove();
    },
    renderContainerFields: function (fields, appendAfterSection)
    {
        this.renderFieldsImpl(_(fields).filter(function (f) { return !f.get("visibilityCondition") }), fields, appendAfterSection);
    },
    renderFieldsImpl: function (fieldsToRender, allFields, appendAfterSection)
    {
        var renderFieldsInner = function (fields, parentField)
        {
            if (parentField && (parentField.isDropDownList() || parentField.isRadioList()))
                fields = _(fields).filter(function (f) { return !f.get("hiddenByParent") }); // for dropdown and radio render only not hidden by parent dependents

            // for checkbox render all dependents if any of them are not hidden by parent to preserve section order
            if (parentField && _(fields).all(function (f) { return f.get("hiddenByParent") }))
                return;

            _(fields).each(function (field)
            {
                appendAfterSection = this.renderField(field, appendAfterSection);
                if (field.canHaveDependentFields())
                {
                    renderFieldsInner.call(this, _(allFields).filter(function (f)
                    {
                        var visibilityCondition = f.get("visibilityCondition");
                        return visibilityCondition && visibilityCondition.fieldId == field.id && f.get("rowId") == field.get("rowId");
                    }), field);
                }
            }, this);
        }

        renderFieldsInner.call(this, fieldsToRender);
    },
    renderBreadCrumb: function ()
    {
        var breadCrumbContainer = this.$(".formBuilderFormBreadCrumb");
        breadCrumbContainer.empty().hide();

        var pages = this.getPagesWithVisibleFields();
        if (pages.length > 1)
            breadCrumbContainer.html($.render("breadCrumbTmpl", { pages: pages }, { templates: this.templates })).show();

        this.selectBreadCrumb(this.currentPageIndex);
    },
    askToHideFields: function (fields, confirmCallback, cancelCallback)
    {
        var fieldsWithDependentFields = [];
        var fieldsWithValues = [];
        var self = this;

        _(fields).each(function (field)
        {
            fieldsWithDependentFields.add(field);
            fieldsWithDependentFields = fieldsWithDependentFields.concat(self.getDependentFieldsFor(field, true));
        });

        _(fieldsWithDependentFields).chain().filter(function (field) { return field.isVisible(); }).each(function (field)
        {
            var section = self.getSection(field);

            var fieldElements = section.find("input, select, textarea").not(":hidden")
                .add(section.find("textarea.textEditor, input.mediaIdInput"))
                .not(".ignoreOnSubmit, :parents(.ignoreOnSubmit:not(.inEditMode), .hiddenPage)").not(":disabled");

            if (fieldElements.hasValue() || field.isTable() && (section.data("view").hasValue() || section.data("view").hasUnsavedChanges()))
                fieldsWithValues.add(field);
        });

        if (fieldsWithValues.length > 0)
        {
            var options = { callback: confirmCallback };
            if (_.isFunction(cancelCallback))
                _.extend(options, { cancelCallback: cancelCallback });

            Confirmation.request("Warning: Changing this field will clear fields that data has been provided for. Do you wish to proceed?", options);
        }
        else
            confirmCallback();
    },
    clear: function (keepControlSections)
    {
        keepControlSections ? this.$("section:not(.control)").remove() : this.$("fieldset").empty();
        this.$(".formBuilderFormBreadCrumb").empty().hide();
        this.sections = null;
    },
    showField: function (field)
    {
        var fieldSection = this.getSection(field).includeSubordinateSections();
        $(fieldSection).show().removeClass("hiddenField");

        if (!field.readOnly && !fieldSection.hasClass("inEditMode"))
            $(fieldSection).ignoreOnSubmit(false);

        field.trigger("shown");
    },
    hideField: function (field)
    {
        this.getSection(field).includeSubordinateSections()
            .hide().ignoreOnSubmit(true)
            .addClass("hiddenField");
    },
    renderField: function (field, appendAfter)
    {
        if (field.rendered)
            return this.getLastCustomOrSelfSectionForField(field);

        var pageId = field.get("pageId") || this.model.getPageId(field.id);
        var data = _.extend(field.attributes,
        {
            settings: this.settings,
            pageId: pageId,
            fieldPath: field.getPath()
        });

        var tmpl, onCustomFieldAdded;

        var customSection = _(this.settings.customSections).find(function (s) { return s.fieldType == field.get("typeName"); });
        if (customSection != null)
        {
            tmpl = customSection.jsTemplate;
            onCustomFieldAdded = customSection.onAdded;
        }
        else if (field.isText())
            tmpl = "textTmpl";
        else if (field.isEmail())
            tmpl = "emailTmpl";
        else if (field.isMultilineText())
            tmpl = "multilineTextTmpl";
        else if (field.isDropDownList())
            tmpl = "dropDownListTmpl";
        else if (field.isRadioList())
            tmpl = "radioListTmpl";
        else if (field.isCheckBoxList())
            tmpl = "checkBoxListTmpl";
        else if (field.isNumber())
            tmpl = "numberTmpl";
        else if (field.isDate())
            tmpl = "dateTmpl";
        else if (field.isSeparator())
            tmpl = "separatorTmpl";
        else if (field.isFileUpload())
            tmpl = "fileUploadTmpl";
        else if (field.isUrl())
            tmpl = "urlTmpl";
        else if (field.isAddress())
            tmpl = "addressTmpl";
        else if (field.isImisNumber())
            tmpl = "imisNumberFieldTmpl";
        else if (field.isTable())
            tmpl = "tableFieldTmpl";
        else if (field.isDigitalSignature())
            tmpl = "digitalSignatureFieldTmpl";
        else if (field.isPhoneNumber())
            tmpl = "phoneNumberFieldTmpl";

        if (field.isDropDownList() && field.get("preFillType") != "None")
            data.preFillValues = awardsCommon.widgets.formBuilderForm.geoNamesProvider[field.get("preFillType").firstLetterToLowerCase()];
        else if (field.isAddress())
        {
            var country = (_.findWhere(awardsCommon.widgets.formBuilderForm.geoNamesProvider.countriesWithStates, { code: field.get("countryCode") }) || {});

            data.countries = awardsCommon.widgets.formBuilderForm.geoNamesProvider.countriesWithStates;
            data.states = country.states;
            data.stateGroups = country.stateGroups;
            data.doesntHaveStates = country.doesntHaveStates;
        }

        this.extendFieldData(data, field);

        // Filter out <text> tags added after parseHtml function call.
        var fieldSection = $($.parseHTML($.render(tmpl, data, { templates: this.templates }).trim())).filter(":not(text)");
        var fieldView;

        // Short-term fix to prevent iframes rendered in field details to change url of root window. See #4945.
        fieldSection.find("iframe:not([sandbox])").attr("sandbox", "allow-same-origin allow-scripts allow-forms allow-popups");

        if (this.settings.isPreviewMode || field.readOnly)
            fieldSection.addClass("ignoreOnSubmit");

        if (appendAfter && appendAfter.length)
            _.isFunction(appendAfter) ? appendAfter.call(this, fieldSection) : appendAfter.after(fieldSection);
        else
            this.appendSection(fieldSection);

        this.fieldSections.set(field, fieldSection);
        field.rendered = true;

        field.on("change:hidden", this.onHiddenOrHiddenByParentChanged, this);

        if (field.isDependentField())
        {
            field.on("change:hiddenByParent", this.onHiddenOrHiddenByParentChanged, this);
            if (!field.isVisible())
                this.hideField(field);
        }

        if (field.isNumber())
        {
            var numberFormat = field.get("format");
            var inputEl = fieldSection.find("input[name$='.Value']");
            var value = inputEl.val();

            if (this.settings.isPreviewMode || !field.get("readOnly"))
                fieldSection.find("input[name$='.Value']").numeric();

            if (numberFormat && value != "")
                inputEl.val(format(numberFormat, value));

            fieldView = new awardsCommon.widgets.formBuilderForm.NumberFieldView({ el: fieldSection, model: field, formBuilderForm: this });
        }

        if (field.isDate())
        {
            this.renderDatepicker(field, { readOnly: field.readOnly });
            fieldView = new awardsCommon.widgets.formBuilderForm.DateFieldView({ el: fieldSection, model: field, formBuilderForm: this });
        }

        if (field.isMultilineText() && field.get("isWysiwyg") && !field.readOnly)
            this.renderWysiwygFor(field);

        var self = this;
        var textInput;

        if (field.isText())
        {
            fieldView = new awardsCommon.widgets.formBuilderForm.TextFieldView({ el: fieldSection, model: field, formBuilderForm: this });
            textInput = fieldView.getComponent();
        }
        else if (field.isMultilineText() && !field.get("isWysiwyg"))
            textInput = fieldSection.find("textarea");

        if (!this.settings.isFormBuilderMode && !field.readOnly && (field.get("maxLength") || field.get("minLength")))
        {
            if (field.isMultilineText() && field.get("isWysiwyg"))
            {
                // http://docs.ckeditor.com/#!/api/CKEDITOR.event
                var editor = fieldSection.find(".textEditor").textEditor();
                editor.on("key", this.onWysiwygWithLimitedMaxLengthTextChanged, this, null, 100);
                editor.on("change", this.onWysiwygWithLimitedMaxLengthTextChanged, this, null, 100);
                editor.on("dataReady", this.onWysiwygWithLimitedMaxLengthTextChanged, this, null, 100);
                editor.on("afterPaste", this.onWysiwygWithLimitedMaxLengthTextChanged, this, null, 100);
            }
            else if (textInput)
            {
                $(textInput).on("keyup", function (event)
                {
                    self.updateTextLengthCounterForWysiwygField($(event.target));
                }).keyup();
            }
        }

        if (field.isMultilineText())
            fieldView = new awardsCommon.widgets.formBuilderForm.MultilineTextFieldView({ el: fieldSection, model: field, formBuilderForm: this });

        if (field.isCheckBoxList())
            fieldView = new awardsCommon.widgets.formBuilderForm.CheckboxListFieldView({ el: fieldSection, model: field, formBuilderForm: this });

        if (field.isRadioList())
            fieldView = new awardsCommon.widgets.formBuilderForm.RadioListFieldView({ el: fieldSection, model: field, formBuilderForm: this });

        if (field.isDropDownList())
            fieldView = new awardsCommon.widgets.formBuilderForm.DropDownListFieldView({ el: fieldSection, model: field, formBuilderForm: this });

        if (field.isEmail())
            fieldView = new awardsCommon.widgets.formBuilderForm.EmailFieldView({ el: fieldSection, model: field, formBuilderForm: this });

        if (field.isUrl())
            fieldView = new awardsCommon.widgets.formBuilderForm.UrlFieldView({ el: fieldSection, model: field, formBuilderForm: this });

        if (field.isImisNumber())
            fieldView = new awardsCommon.widgets.formBuilderForm.SingleInputFieldView({ el: fieldSection, model: field, formBuilderForm: this });

        if (field.isAddress())
            fieldView = new awardsCommon.widgets.formBuilderForm.AddressFieldView({ el: fieldSection, model: field, formBuilderForm: this });

        if (field.isUrl())
            this.renderUrlFor(field);

        if (field.isFileUpload())
        {
            var uploader = fieldSection.fileUploader(_.extend(
            {
                params: { owner: this.model.get("name"), isPrivate: true },
                disabled: field.readOnly,
                dontShowDeleteButton: field.readOnly,
                enableCloudflareStreamsStartEndTimeEditing: !field.readOnly,
                enableCloudflareStreamCaptionsEditing: !field.readOnly,
                enforceCloudflareStreamsPlaybackWithinStartEndTime: this.settings.enforceCloudflareStreamsPlaybackWithinStartEndTime,
                required: !this.model.get("readOnly") && field.get("required"),
                allowedFileExtensions: field.get("allowedFileExtensions"),
                showCaption: field.get("showCaption"),
                showDocumentPreview: field.get("showDocumentPreview"),
                showAudioPreview: field.get("showAudioPreview"),
                showImagePreview: field.get("showImagePreview"),
                showVideoPreview: field.get("showVideoPreview"),
                maxFileSize: field.get("maxFileSize"),
                ownerId: this.model.get("ownerId")
            }, this.settings.mediaInfo));

            if (field.get("mediaId"))
                uploader.renderPreviewWithMediaId(field.get("mediaId")); // must be invoked here to set mediaId to DOM input

            fieldView = new awardsCommon.widgets.formBuilderForm.FileUploadFieldView({ el: fieldSection, model: field, formBuilderForm: this });
        }

        if (field.isTable())
        {
            var view = new awardsCommon.widgets.formBuilderForm.TableFieldView(
            {
                el: this.el,
                field: field,
                scope: field.get("prefix") + ".FieldValues[" + field.id + "]",
                formBuilderForm: this,
                redirectToMediaUrl: this.settings.redirectToMediaUrl,
                redirectToMediaPreviewUrl: this.settings.redirectToMediaPreviewUrl,
                mediaFileNameUrl: this.settings.mediaFileNameUrl,
                noFileUploadedUrl: this.settings.tableFieldSettings.noFileUploadedUrl,
                deleteMultipleMediaUrl: this.settings.mediaInfo.deleteMultipleUrl,
            });

            fieldSection.data("view", view);
            fieldView = view;
        }

        if (field.isDigitalSignature())
        {
            var $digitalSignatureTextInput = fieldSection.find("input[type='text'].digitalSignature");
            var $digitalSignatureContainer = fieldSection.find("div.digitalSignatureContainer");

            // default width is incorrect when a field is hidden on initial render which leads to incorrect canvas width
            if (field.get("hidden"))
                $digitalSignatureContainer.width((fieldSection.closest("fieldset").width() * 0.95).toFixed());

            $digitalSignatureContainer.signature({ syncFormat: "SVG", syncField: $digitalSignatureTextInput });
            $digitalSignatureContainer.signature().bind("signaturechange", function ()
            {
                $digitalSignatureTextInput.val($digitalSignatureContainer.signature("isEmpty") ? "" : $digitalSignatureContainer.signature("toSVG"));
            });

            var digitalSignatureValue = $digitalSignatureTextInput.val();
            if (digitalSignatureValue)
                $digitalSignatureContainer.signature("draw", digitalSignatureValue);

            fieldSection.find("a.clearDigitalSignature").click(function ()
            {
                $digitalSignatureContainer.signature("enable");
                $digitalSignatureContainer.signature("clear");
            });

            if (field.readOnly || !$digitalSignatureContainer.signature("isEmpty"))
                $digitalSignatureContainer.signature("disable");
        }

        if (field.isPhoneNumber())
        {
            fieldView = new awardsCommon.widgets.formBuilderForm.PhoneNumberFieldView(
            {
                el: fieldSection,
                initialCountryCode: this.settings.phoneNumberFieldInitialCountryCode,
                field: field
            });
        }

        if (fieldView)
        {
            fieldView.render();
            this.fieldViews[field.getPath()] = fieldView;
        }

        if (!field.readOnly)
            this.addValidationRules(field);

        if (onCustomFieldAdded)
        {
            fieldView = callFunction(onCustomFieldAdded, data, fieldSection, this);
            this.fieldViews[field.getPath()] = fieldView;
        }

        if (this.settings.onFieldAdded)
            callFunction(this.settings.onFieldAdded, data, fieldSection, this, fieldView);

        field.trigger("rendered", fieldSection);

        return this.getLastCustomOrSelfSectionForField(field);
    },
    getSection: function (field)
    {
        var fieldSection = this.fieldSections.get(field);
        if (!fieldSection && field.rendered)
            throw "Section doesn't exist for field with alias '" + field.get("alias") + "'.";

        return fieldSection;
    },
    buildFieldSectionId: function (fieldPath)
    {
        return "section_" + $.escapeSelector(fieldPath);
    },
    renderControlSections: function (position)
    {
        if (!this.settings.controlSections)
            return;

        var self = this;
        _.each(_(this.settings.controlSections).filter(function (s) { return s.position.toLowerCase() == position; }), function (item)
        {
            var controlSection = $(item.htmlTemplate).children();
            if (controlSection.is("section"))
                controlSection.addClass("control " + position + "Control");

            self.appendSection(controlSection);
            self.$(".fields fieldset").appendScripts($(item.htmlTemplate));
            $(item.htmlTemplate).remove();
        });
    },
    renderStaticSections: function ()
    {
        if (!this.settings.staticSections)
            return;

        var self = this;
        _.each(this.settings.staticSections, function (item)
        {
            var section = $($(item.htmlTemplate).html());
            if (section.is("section"))
                section.addClass("static");

            var found;
            if (item.position.toLowerCase() == "top")
            {
                section.addClass("topStatic");

                found = self.$("fieldset section[data-fieldId]:first");
                found.before(section);
            }
            else
            {
                section.addClass("bottomStatic");

                found = self.$("fieldset section:not(.control):last");
                found.after(section);
            }
        });

        this.assignPageIdToStaticSections();
    },
    assignPageIdToStaticSections: function ()
    {
        if (!this.settings.staticSections)
            return;

        var visiblePages = this.getPagesWithVisibleFields();
        if (!visiblePages.length)
            return;

        var firstPageId = _(visiblePages).first().id;
        var lastPageId = _(visiblePages).last().id;

        _(this.$("section.static")).each(function (staticSection)
        {
            var $section = $(staticSection);
            $section.attr("data-pageId", $section.hasClass("topStatic") ? firstPageId : lastPageId);
        });
    },
    renderDatepicker: function (field, settings)
    {
        var rangeValueToFillWithTodayDate = field.get("rangeValueToFillWithTodayDate");
        var dateNow = (new Date()).toString(appConfig.dateFormat);
        this.getSection(field).dateTimePicker(
        {
            readOnly: settings.readOnly,
            minValue: rangeValueToFillWithTodayDate && rangeValueToFillWithTodayDate.contains("minValue") ?
                dateNow :
                field.get("minValueUtc") ? field.get("minValueUtc").formatDate("{d}") : null,
            maxValue: rangeValueToFillWithTodayDate && rangeValueToFillWithTodayDate.contains("maxValue") ?
                dateNow :
                field.get("maxValueUtc") ? field.get("maxValueUtc").formatDate("{d}") : null
        });

        if (field.get("valueUtc"))
            this.getSection(field).dateTimePicker().setValue(field.get("valueUtc"));
    },
    renderWysiwygFor: function (field)
    {
        var fieldEl = this.getSection(field).find("textarea[name$='.Value']");

        var options = {
            readOnly: field.readOnly,
            mode: "Restricted",
            allowUseLinks: this.settings.allowUseLinksInWysiwyg,
            allowViewSource: this.settings.allowSourceViewForWysiwyg
        };

        if (field.isComplexField())
            options.height = 600;

        var allowedHtmlTags = field.get("allowedHtmlTags");
        if (allowedHtmlTags)
            options = _.extend(options, { allowedHtmlTags: allowedHtmlTags });

        var editor = fieldEl.textEditor(options);

        // for #2943 - log next paste validation error
        if (!appConfig.isDevEnvironment)
        {
            editor.on("afterPaste", function ()
            {
                if (!editor.getHostElement().valid())
                {
                    var sectionEl = $(fieldEl.closest("section"));
                    var currentLength = sectionEl.find(".lengthCounter .currentLength").html().asInt();
                    var maxLength = field.get("maxLength");

                    if (field.get("textLengthCountMode") != "Words" || maxLength >= currentLength)
                        return;

                    window.KeenClient.recordEvent("WYSIWYG.WordCounterValidationError",
                    {
                        maxWordCount: maxLength,
                        wordCount: currentLength,
                        text: fieldEl.val()
                    });
                }
            });
        }
    },

    appendSection: function (section)
    {
        this.$(".fields fieldset").append(section);
    },
    updateTextLengthCounterForWysiwygField: function (textFieldEl)
    {
        var sectionEl = $(textFieldEl.closest("section"));
        var field = this.model.get("fields").deepSearch(sectionEl.attr("data-fieldId"));

        var value = textFieldEl.val();
        if (field.get("isWysiwyg"))
            value = value.withoutHtml();

        var length;
        if (field.get("textLengthCountMode") == "Words")
        {
            var words = value.match(appConfig.regexLib.words) || [];
            length = words.length;
        }
        else
            length = value.length;

        sectionEl.find(".lengthCounter .currentLength").html(length);
    },
    updateAddressStateInput: function (countrySelector, stateInputPrefix)
    {
        var $countrySelector = $(countrySelector);
        var selectedCountryCode = $countrySelector.val();
        var country = _.findWhere(awardsCommon.widgets.formBuilderForm.geoNamesProvider.countriesWithStates, { code: selectedCountryCode }) || {};

        var section = $countrySelector.closest("section");
        var html = $.render("addressStateTmpl",
        {
            id: section.attr("data-fieldId"),
            states: country.states,
            stateGroups: country.stateGroups,
            doesntHaveStates: country.doesntHaveStates,
            prefix: stateInputPrefix
        }, { templates: this.templates });

        var stateSpan = section.find("span.state");
        stateSpan.next().remove();
        stateSpan.after(html);
        stateSpan.toggle(!country.doesntHaveStates);

        if (country.doesntHaveStates)
            return null;
        else
            return stateSpan.next();
    },
    extendFieldData: function (data, field)
    {
    },
    renderComplexFields: function ()
    {
    },
    prepareFieldViewModel: function (fields, fieldValues, customData)
    {
        var values = _(fieldValues).groupBy("fieldId");

        var fieldViewModels = fields.map(function (f) // merge fields with values and extends with readOnly property from data
        {
            var newField = f.clone();
            _.extend(newField.attributes, { $valueType: f.get("fieldValueTypeName") }, customData);

            // Synchronize hidden property of original fields with field view models.
            // It's shortterm fix for #3720. The longterm solution is to have single source of field models.
            // TODO: removed after proper implementation (#3724).
            newField.on("change:hidden", function (model, hidden)
            {
                f.set({ hidden: hidden });
            });

            var value = values[f.id];
            if (!value || !value.length)
                return newField;

            //delete value.fieldId;
            _.extend(newField.attributes, _.omit(value[0], "$type"), { readOnly: f.readOnly });
            return newField;
        });

        _(fieldViewModels).chain().filter(function (field) { return field.canHaveDependentFields() }).each(function (parentField)
        {
            _(fieldViewModels).chain()
                .filter(function (f) { return f.has("visibilityCondition") && f.get("visibilityCondition").fieldId == parentField.id })
                .each(function (depField)
                {
                    var customSectionAttributes = _.clone(depField.get("customSectionAttributes") || {});
                    customSectionAttributes.parentFieldPath = parentField.getPath();

                    var visibilityConditionSelectedListValueId = depField.get("visibilityCondition").selectedListValueId;
                    var hiddenByParent = parentField.isCheckBoxList() ? !_(parentField.get("selectedValueIds")).contains(visibilityConditionSelectedListValueId) : visibilityConditionSelectedListValueId != parentField.get("selectedValueId")

                    depField.set(
                    {
                        hiddenByParent: hiddenByParent,
                        customSectionAttributes: customSectionAttributes
                    });
                });
        });

        _(fieldViewModels).each(function (f)
        {
            this.fieldModels[f.getPath()] = f;
        }, this);

        return fieldViewModels;
    },
    getLastCustomOrSelfSectionForField: function (field)
    {
        return this.getSection(field).nextUntil(".static, .control, .fieldSection").addBack().last();
    },
    deleteFieldModel: function (model)
    {
        var fieldPath = model.getPath();
        delete this.fieldModels[fieldPath];
        delete this.fieldViews[fieldPath];

        var section = this.getSection(model);
        if (section && section.length)
        {
            this.fieldSections.delete(model);
            
            var textarea = section.find("textarea.textEditor");
            if (textarea.length)
                textarea.textEditor().destroy();

            section.remove();
        }

        this.trigger("fieldModelDeleted", model);
    },
    disableListItems: function ()
    {
        var self = this;

        // Not disabling table fields here, because every time table is opened, render() is called for each nested field and list values are disabled properly.
        var rootFieldIds = _(this.model.get("fields").models).pluck("id");

        _(this.fieldModels).chain().filter(function (f) { return f.isList() && f.isVisible() && _(rootFieldIds).contains(f.id) }).each(function (listField)
        {
            var fieldView = self.fieldViews[listField.getPath()];
            var selectedValues = self.getSelectedValuesForField(listField);

            if (listField.isCheckBoxList())
                fieldView.model.set({ selectedValueIds: selectedValues });
            else if (listField.isDropDownList() || listField.isRadioList())
                fieldView.model.set({ selectedValueId: selectedValues[0] });

            fieldView.disableListValues();
        });
    }
});;$.extend(awardsCommon.widgets.formBuilderForm.FormBuilderFormView.prototype,
{
    currentPageIndex: 0,
    changePageById: function (pageId)
    {
        var pages = this.getAllPages();
        if (pages.length == 0)
            return;

        var pageIndex = _(pages).findIndex(function (page)
        {
            return page.id == pageId;
        });

        this.changePage(pageIndex);
    },
    changePage: function (pageIndex)
    {
        if (!this.validateTableFieldRowsWithUnsavedChanges())
        {
            this.focusFirstUnsavedTableRow();
            return;
        }

        var pages = this.getAllPages();
        if (pages.length == 0)
            return;

        if (!pages[pageIndex])
            return;

        this.currentPageIndex = pageIndex;
        this.hidePages();
        this.showPage(pages[pageIndex].id);

        this.selectBreadCrumb(this.currentPageIndex);
        this.trigger("pageChanged", this.currentPageIndex, this.$el);
    },
    refreshPage: function ()
    {
        this.changePage(this.currentPageIndex);
    },
    goToFirstPage: function ()
    {
        var firstVisiblePage = _.first(this.getPagesWithVisibleFields());
        if (firstVisiblePage)
            this.changePage(firstVisiblePage.index);
    },
    goToNextPage: function ()
    {
        var nextPage = this.getPageByCurrentPageIndexOffset(1);
        if (nextPage)
            this.changePage(nextPage.index);
    },
    goToPreviousPage: function ()
    {
        var prevPage = this.getPageByCurrentPageIndexOffset(-1);
        if (prevPage)
            this.changePage(prevPage.index);
    },
    goToFirstEditablePage: function ()
    {
        var allPages = this.getAllPages();
        var visiblePages = this.getPagesWithVisibleFields();
        var firstEditablePage = _(visiblePages).find(function (p) { return !p.readOnly });

        this.changePage(_(allPages).indexOf(firstEditablePage));
    },
    isCurrentPageReadOnly: function ()
    {
        var pages = this.getAllPages();
        var currentPage = pages[this.currentPageIndex];

        return currentPage.readOnly;
    },
    isFirstPage: function ()
    {
        var firstPage = _.first(this.getPagesWithVisibleFields());
        return this.getAllPages().length == 0 || firstPage.index === this.currentPageIndex;
    },
    isLastPage: function ()
    {
        var lastPage = _.last(this.getPagesWithVisibleFields());
        return this.getAllPages().length == 0 || lastPage.index === this.currentPageIndex;
    },
    showPage: function (pageId)
    {
        this.$("section[data-pageId='" + pageId + "']").removeClass("hiddenPage");
    },
    hidePages: function ()
    {
        this.$("section[data-pageId]").includeSubordinateSections().addClass("hiddenPage");
    },

    onBreadCrumbLinkClicked: function (event)
    {
        event.preventDefault();
        event.stopImmediatePropagation();

        var pageIndex = parseInt($(event.target).attr("data-pageIndex"));
        this.changePage(pageIndex);
    },
    selectBreadCrumb: function (pageIndex)
    {
        this.$(".formBuilderFormBreadCrumb a").removeClass("selected");
        this.$(".formBuilderFormBreadCrumb").find("a[data-pageIndex=" + pageIndex + "]").addClass("selected").removeClass("notAccessible");
    },
    getAllPages: function ()
    {
        return this.model.get("pages");
    },
    getPagesWithVisibleFields: function ()
    {
        var pages = this.getAllPages();
        var fields = this.model.get("fields");

        return _.filter(pages, function (page)
        {
            return page.fieldIds.length > 0 && fields.any(function (field)
            {
                return _.contains(page.fieldIds, field.id) && !field.get("hidden") && !field.isComplexFieldAggregate();
            });
        });
    },
    getPageByCurrentPageIndexOffset: function (offset)
    {
        var pages = this.getPagesWithVisibleFields();
        var page = _(pages).findWhere({ index: this.currentPageIndex });
        var pageIndex = _.indexOf(pages, page);

        return pages[pageIndex + offset];
    },
    getPageIndexByFieldId: function (fieldId)
    {
        var pageId = this.model.getPageId(fieldId);
        return _(this.getAllPages()).findIndex(function (page)
        {
            return page.id == pageId;
        });
    }
});;$.extend(awardsCommon.widgets.formBuilderForm.FormBuilderFormView.prototype,
{
    validate: function (pageIndexToValidate)
    {
        var pages = this.model.get("pages");
        if (pages.length == 0)
        {
            var valid = this.validateSections(this.$("section[data-pageId]"));
            if (!valid)
            {
                this.focusFirstInvalidEl();
                this._showWarningIfOnlyHiddenTableNestedFieldsAreInvalid();
            }

            var areTableFieldRowsValid = this.validateTableFieldRowsWithUnsavedChanges();
            if (!areTableFieldRowsValid)
                this.focusFirstUnsavedTableRow();

            return valid && areTableFieldRowsValid;
        }
        else
        {
            var self = this;

            function validatePageSections(pageIndex)
            {
                if (!self.validateSections(self.$("section[data-pageId='" + pages[pageIndex].id + "']"), { includeHidden: true }))
                {
                    self.changePage(pageIndex);
                    self.focusFirstInvalidEl();
                    self._showWarningIfOnlyHiddenTableNestedFieldsAreInvalid();

                    return false;
                }

                if (!self.validateTableFieldRowsWithUnsavedChanges())
                {
                    self.focusFirstUnsavedTableRow();
                    return false;
                }

                return true;
            }

            if (!_.isUndefined(pageIndexToValidate))
            {
                var page = pages[pageIndexToValidate];
                if (!page)
                    throw "Page with index " + pageIndexToValidate + " doesn't exist. ";

                for (var i = 0; i <= pageIndexToValidate; i++)
                {
                    if (!validatePageSections(i))
                        return false;
                }
            }
            else
            {
                for (var i = 0; i < pages.length; i++)
                {
                    if (!validatePageSections(i))
                        return false;
                }
            }
        }

        return true;
    },
    validateSections: function (sections, options)
    {
        return this.$el.closest("form").validate().checkElements(sections, options || {});
    },
    validateTableFieldRowsWithUnsavedChanges: function ()
    {
        var hasUnsavedChanges = this.hasTableFieldRowsWithUnsavedChanges();

        if (hasUnsavedChanges)
        {
            _(this.$("section.table:not(.hidden,.hiddenPage)")).each(function (section)
            {
                $(section).data("view").highlightRowControlsIfItHasUnsavedChanges();
            });
        }

        return !hasUnsavedChanges;
    },
    hasTableFieldRowsWithUnsavedChanges: function ()
    {
        return _(this.$("section.table:not(.hidden,.hiddenPage)")).any(function (section)
        {
            return $(section).data("view").hasUnsavedChanges();
        });
    },
    focusFirstUnsavedTableRow: function ()
    {
        var elementToFocus = $(_(this.$("section.table:not(.hidden,.hiddenPage)")).chain().filter(function (table) { return !_.isUndefined($(table).data("view").currentRowEdit); }).first().value()).data("view").currentRowEdit.subformFieldSections;
        this._scrollToElement(elementToFocus);
    },
    focusFirstInvalidEl: function (changePageIfNecessary)
    {
        var validator = this.$el.closest("form").validate();
        var firstInvalidEl = $(validator.errorList[0].element);

        if (changePageIfNecessary)
            this.changePageById(firstInvalidEl.closest("section").data("pageid"));

        var elementToFocus = firstInvalidEl.is(":visible") ? firstInvalidEl : firstInvalidEl.closest("div.view");
        this._scrollToElement(elementToFocus);

        if (elementToFocus == firstInvalidEl)
            firstInvalidEl.focus();
    },

    onFormError: function (event, resultInfo)
    {
        if (!resultInfo || !resultInfo.formElementErrors || !resultInfo.formElementErrors[0])
            return;

        var fieldId = resultInfo.formElementErrors[0].elementName;
        var formBuilderForm = $(this).formBuilderForm();
        var pages = formBuilderForm.model.get("pages");
        var page = _(pages).find(function (item) { return _(item.fields).contains(fieldId); });
        var pageIndex = _.indexOf(pages, page);

        if (pageIndex < 0)
            return;

        formBuilderForm.changePage(pageIndex);
    },
    initializeValidationMethods: function ()
    {
        var self = this;
        $.validator.addMethod("phoneNumber", function (param, element)
        {
            if (this.optional(element))
                return true;

            var fieldPath = $(element).closest("section").attr("data-fieldPath");
            var fieldView = self.fieldViews[fieldPath];

            return fieldView.isValid();
        }, "Phone number is incomplete");
    },
    addValidationRules: function (field)
    {
        if (field.get("readOnly"))
            return;

        var fieldValueEl = this.getValidatingElement(field);
        var validator = this.$el.closest("form").validate();

        if (field.isTable() && !fieldValueEl[0].name && fieldValueEl.attr("name"))
            fieldValueEl[0].name = fieldValueEl.attr("name"); // name property is created only on "input" elements

        this.syncRequiredValidationRules(field);

        if (field.isNumber())
        {
            fieldValueEl.rules("add", { number: true });
            this.addValidationContainer(fieldValueEl);

            var minValue = field.get("minValue");
            var maxValue = field.get("maxValue");
            var maxPrecision = field.get("maxPrecision");
            var numberFormat = field.get("format");

            if (minValue)
                fieldValueEl.rules("add", { min: minValue });
            if (maxValue)
                fieldValueEl.rules("add", { max: maxValue });

            if (maxPrecision !== null || numberFormat)
            {
                fieldValueEl.blur(function ()
                {
                    var value = fieldValueEl.val();
                    if (value === "")
                        return;

                    if (maxPrecision === null)
                    {
                        fieldValueEl.val(format(numberFormat, value));
                        return;
                    }

                    var numberWithPrecision = value.asFloat(maxPrecision);
                    fieldValueEl.val(numberFormat ? format(numberFormat, numberWithPrecision) : numberWithPrecision);
                });
            }
        }

        if (field.isEmail())
            fieldValueEl.addExtendedEmailValidationRule();

        if (field.isText() || field.isMultilineText())
        {
            var minLength = field.get("minLength");
            var maxLength = field.get("maxLength");

            fieldValueEl.addTextLengthValidationRules(minLength, maxLength, field.get("textLengthCountMode"));

            if (minLength || maxLength)
                this.addValidationContainer(fieldValueEl);

            if (field.isText() && this.fieldViews[field.get("fieldPath")].addValidationRules(fieldValueEl, validator))
                this.addValidationContainer(fieldValueEl);
        }

        if (field.isUrl())
        {
            fieldValueEl.addUrlValidationRule();
            this.addValidationContainer(fieldValueEl);
        }

        if (field.isTable())
        {
            validator.addCustomElementToValidate(fieldValueEl, function (table)
            {
                return $(table).closest("section").data("view").tableRowData;
            });

            if (field.get("required"))
            {
                var minRowCount = field.get("minRowCount");
                fieldValueEl.rules("add", { minRowCount: minRowCount, messages: { minRowCount: $.validator.format("Please add at least {0} rows.") } });
            }

            // always handle "change" event due to validation rules can be changed dynamically
            // table can't fire "focusout" event
            fieldValueEl.on("change",
                function ()
                {
                    if (validator.settings.onfocusout)
                        validator.element(fieldValueEl);
                });

            this.addValidationContainer(fieldValueEl);
        }

        if (field.isDigitalSignature())
        {
            fieldValueEl.siblings(".digitalSignatureContainer").bind("signaturechange", function ()
            {
                if (validator.settings.onfocusout)
                    validator.element(fieldValueEl);
            });

            validator.addCustomValueFunction(fieldValueEl, function (input)
            {
                return $(input).siblings(".digitalSignatureContainer").signature("isEmpty") ? "" : "not_empty";
            });
        }

        if (field.isPhoneNumber())
        {
            fieldValueEl.rules("add",
            {
                phoneNumber: true
            });

            this.fieldViews[field.get("fieldPath")].addValidationContainer();
        }

    },
    syncRequiredValidationRules: function (field)
    {
        if (!field.rendered)
            throw "Field '" + field.get("name") + "' is not rendered yet.";

        var self = this;
        var fieldValueEl = this.getValidatingElement(field);
        var isRequired = field.get("required");

        function enableRequiredValidationRuleWithValidationContainer(fieldValueEl, enable, validationRequired)
        {
            fieldValueEl.enableRequiredValidationRule(enable);

            if (enable)
                self.addValidationContainer(fieldValueEl);

            if (enable && validationRequired)
            {
                fieldValueEl.on("change", function ()
                {
                    var $this = $(this);
                    $this.closest("form").validate().element($.escapeSelector("#" + $this.attr("id")));
                });
            }
        }

        if (field.isEmail() && field.get("confirmationRequired") && !this.settings.turnOffEmailConfirmations)
        {
            var confirmationEl = this.$($.escapeSelector("#" + fieldValueEl.attr("id") + "_confirm"));
            confirmationEl.rules("add", { equalTo: $.escapeSelector("#" + fieldValueEl.attr("id")) });
            confirmationEl.ignoreOnSubmit().addClass("forceValidation");
            enableRequiredValidationRuleWithValidationContainer(confirmationEl, isRequired);
        }
        else if (field.isCheckBoxList())
        {
            fieldValueEl.enableAtLeastOneCheckedValidationRule(isRequired);

            if (isRequired)
            {
                var minSelectedValueCount = field.get("minSelectedValueCount");
                var maxSelectedValueCount = field.get("maxSelectedValueCount");

                if (minSelectedValueCount)
                {
                    fieldValueEl.each(function ()
                    {
                        var minSelectedValueCountMessage = sprintf(minSelectedValueCount == 1 
                            ? "At least one checked item is required."
                            : "At least %s checked items are required.", minSelectedValueCount );

                        $(this).rules("add", { minSelectedValueCount: { elements: fieldValueEl, minSelectedValueCount: minSelectedValueCount }, messages: { minSelectedValueCount: minSelectedValueCountMessage } });
                    });
                }

                if (maxSelectedValueCount)
                {
                    fieldValueEl.each(function ()
                    {
                        var maxSelectedValueCountMessage = sprintf(maxSelectedValueCount == 1 
                            ? "A maximum one checked item is permitted."
                            : "A maximum of %s checked items are permitted.", maxSelectedValueCount );

                        $(this).rules("add", { maxSelectedValueCount: { elements: fieldValueEl, maxSelectedValueCount: maxSelectedValueCount }, messages: { maxSelectedValueCount: maxSelectedValueCountMessage } });
                    });
                }

                var lastCheckboxListItem = fieldValueEl.last();
                lastCheckboxListItem.parent().addErrorContainerIfNotExists(lastCheckboxListItem.attr("name"));

                fieldValueEl.on("change", function () { $(this).closest("form").validate().element($.escapeSelector("#" + lastCheckboxListItem.attr("id"))); });
            }
        }
        else if (field.isFileUpload())
        {
            var section = this.getSection(field);
            var fileInput = section.find(":file");

            var fileUploader = section.fileUploader();
            fileUploader.setRequiredOption(isRequired);

            if (field.get("showCaption"))
            {
                var caption = section.find("input[name$='Caption']");
                if (caption.length)
                {
                    if (isRequired)
                        enableRequiredValidationRuleWithValidationContainer(caption, isRequired);
                    else
                    {
                        if (fileInput.length)
                        {
                            fileInput.rules("add",
                            {
                                required: function ()
                                {
                                    return caption.is(":filled");
                                },
                            });
                        }

                        caption.enableRequiredValidationRule(false);
                    }
                }
            }
            else
            {
                this.addValidationContainer(fieldValueEl);
                enableRequiredValidationRuleWithValidationContainer(fileInput, isRequired);
                isRequired ? fileInput.addClass("required") : fileInput.removeClass("required");
            }
        }
        else if (field.isAddress())
        {
            this.getSection(field).find("select[name$='CountryCode'], select[name$='State'], input[name$='State'], " +
                "input[name$='City'], input[name$='Street'], input[name$='Zip']").each(function ()
            {
                enableRequiredValidationRuleWithValidationContainer($(this), isRequired);
            });
        }
        else if (field.isPhoneNumber())
        {
            fieldValueEl.enableRequiredValidationRule(isRequired);
        }
        else if (field.isRadioList())
        {
            fieldValueEl.enableRequiredValidationRule(isRequired);

            var lastRadioListItem = fieldValueEl.last();
            lastRadioListItem.parent().addErrorContainerIfNotExists(lastRadioListItem.attr("name"));
        }
        else if (field.isMultilineText() && !field.readOnly && field.get("isWysiwyg") && isRequired)
        {
            enableRequiredValidationRuleWithValidationContainer(fieldValueEl, isRequired);

            var editor = fieldValueEl.textEditor();
            editor.on("key", this._validateTextEditor, this, null);
            editor.on("change", this._validateTextEditor, this, null);
            editor.on("afterPaste", this._validateTextEditor, this, null);
        }
        else
        {
            fieldValueEl.each(function ()
            {
                enableRequiredValidationRuleWithValidationContainer($(this), isRequired);
            });
        }

        this.trigger("syncRequiredValidationRules", field);

        if (field.get("name"))
        {
            var label = this.getSection(field).find("label.name");
            label.find("span.required").remove();

            if (field.get("required"))
                label.append("<span class='required'/>");
        }
    },
    addValidationContainer: function (fieldElement)
    {
        fieldElement.addErrorContainerIfNotExists();
    },
    ensureFormValidatorAttached: function ()
    {
        var form = this.$el.closest("form");
        if (!form.isValidatorAttached())
            $.validator.unobtrusive.parse(form);
    },
    getValidatingElement: function (field)
    {
        if (field.isTable())
        {
            var element = this.getSection(field).find(".view table[id^='Table-']")[0];

            if (!element.form)
                element.form = $(element).closest("form")[0];

            return $(element);
        }

        if (field.isPhoneNumber())
            return field.get("readOnly") ? $() : this.fieldViews[field.get("fieldPath")].$phoneNumberInput;

        return this.getSection(field).find(".view[name*='Value'], .view *[name*='Value']");
    },

    _validateTextEditor: function (event)
    {
        var $textEditorEl = $(event.editor.element.$);
        $textEditorEl.closest("form").validate().element($.escapeSelector("#" + $textEditorEl.attr("id")));
    },
    _scrollToElement: function (elementToFocus)
    {
        $("html, body").scrollTop(elementToFocus.offset().top - ($(window).height() - elementToFocus.outerHeight(true)) / 2); // scroll element to the center of the page
    },
    _showWarningIfOnlyHiddenTableNestedFieldsAreInvalid: function ()
    {
        if (this.hasTableFieldRowsWithUnsavedChanges())
            return;

        if (_(this.$el.closest("form").validate().errorList).all(function (error) { return $(error.element).closest("section").hasClass("tableNestedField"); }))
            Alert.error("One or more table row fields are not valid.");
    }
});;$.extend(awardsCommon.widgets.formBuilderForm.FormBuilderFormView.prototype,
{
    onVisibilityConditionChanged: function (field)
    {
        if (field.isVisible())
            this.renderDependentField(field);
        else
            this.hideField(field);

        var fields = this.model.get("fields");
        if (!fields.hasDependentFieldsFor(field))
            return;

        var conditionMatch = field.get("visibilityConditionMatch");
        var fieldValue = field.get("selectedValueId");

        _(fields.getDependentFieldsFor(field)).each(function (depField)
        {
            var isDepFieldSelected = fieldValue == depField.get("visibilityCondition").selectedListValueId;
            depField.set({ visibilityConditionMatch: conditionMatch && isDepFieldSelected });
        });
    },
    onDependentFieldsParentElementClicked: function (event, options)
    {
        this.dependentFieldsParentElementClickedHandler($(event.target), options);
    },

    dependentFieldsParentElementClickedHandler: function ($target, options)
    {
        options = _.extend({ suppressHidingFieldsConfirmation: false }, options);

        // prevent radio or dropdown value selecting if user doesn't confirm
        var section = $target.closest("section");
        var sectionId = section.attr("id");

        if (!sectionId)
            return;

        var field = this.fieldModels[section.attr("data-fieldPath")];

        var selectedListValueIds = this.getSelectedValuesForField(field);

        var dependentFields = this.getDependentFieldsFor(field, false);

        // Render dependents on demand. Render all dependents because their state is not determined yet.
        // When we set their state (by setting "hiddenByParent" attribute) field model event handlers expect that it's already rendered.
        this.renderFieldsImpl(dependentFields, dependentFields, this.getLastCustomOrSelfSectionForField(field));

        var fieldsToHide = _(dependentFields).filter(function (depField)
        {
            return depField.isVisible() && !_(selectedListValueIds).contains(depField.get("visibilityCondition").selectedListValueId);
        });

        var confirmCallback = function ()
        {
            field.set({ previousSelectedValueIds: selectedListValueIds });
            _(dependentFields).each(function (depField)
            {
                var isVisible = _(selectedListValueIds).contains(depField.get("visibilityCondition").selectedListValueId);
                depField.set({ hiddenByParent: !isVisible });
            });

            if (field.isRadioList())
            {
                section.find(".listItem").each(function ()
                {
                    var $this = $(this);
                    $this.find(".resetRadioListSelectedValues").toggle($this.attr("data-listvalueId") == $target.val());
                });
            }
        };

        if (options.suppressHidingFieldsConfirmation)
            confirmCallback();
        else
        {
            this.askToHideFields(fieldsToHide, confirmCallback, function ()
            {
                var previousSelectedValueIds = field.get("previousSelectedValueIds") || field.get("selectedValueIds") || [field.get("selectedValueId")];
                if (field.isDropDownList())
                    $target.closest("select").val(previousSelectedValueIds[0]);
                else if (field.isCheckBoxList() || field.isRadioList())
                {
                    $target.attr("checked", false);
                    _(previousSelectedValueIds).each(function (id)
                    {
                        section.find("input[value='" + id + "']").attr("checked", true).change();
                    });
                }
                else
                    throw "Unexpected field with type '" + field.get("typeName") + "'.";
            });
        }
    },
    renderDependentField: function (field)
    {
        var fields = field.collection.allFields || field.collection;
        var parentField = fields.get(field.get("visibilityCondition").fieldId);
        var parentSection = this.getSection(parentField);

        var parentSectionId = parentSection.attr("id");
        if (!parentSectionId)
            return;

        var parentFieldId = _.last(parentSectionId.split("_"));
        var selectedListValueId = field.get("visibilityCondition").selectedListValueId;
        var currentPath = parentSection.attr("data-path");
        var path = currentPath ? (currentPath + "_") : "";

        // insert after last rendered section (including dependent field's own dependent fields)
        var insertAfter = this.$("section[data-path^='" + path + parentFieldId + "_" + selectedListValueId + "']").includeSubordinateSections().last();
        if (!insertAfter.length)
        {
            var nextParentSection = parentSection.next();
            if (nextParentSection.length && nextParentSection.hasClass("scoring"))
                insertAfter = nextParentSection;
            else
                insertAfter = parentSection;
        }

        var pageId = parentSection.attr("data-pageId");

        field.set({ path: path + parentFieldId + "_" + selectedListValueId + "_" + field.id });
        field.set({ pageId: pageId });

        this.renderField(field, insertAfter);
    },
    getDependentFieldsFor: function (field, deep)
    {
        var fields = _(this.fieldModels).values();
        var result = _(fields).filter(function (f)
        {
            var visibilityCondition = f.get("visibilityCondition");
            return visibilityCondition && visibilityCondition.fieldId == field.id && f.get("rowId") == field.get("rowId") && f.get("inEditMode") == field.get("inEditMode");
        });

        if (deep)
        {
            result = _(result).chain().map(function (f)
            {
                if (f.canHaveDependentFields())
                    return this.getDependentFieldsFor(f, deep);

                return f;
            }, this).flatten().value();
        }

        return result;
    },
    getSelectedValuesForField: function (field)
    {
        return this.getSection(field).find(":checked").map(function () { return $(this).val(); }).get();
    }
});;$.extend(awardsCommon.widgets.formBuilderForm.FormBuilderFormView.prototype,
{
    onUrlFocusOut: function (event)
    {
        var fieldPath = $(event.target).parents("section.url").attr("data-fieldPath");
        var field = this.fieldModels[fieldPath];

        this.renderUrlFor(field, $(event.target).val());
    },
    renderUrlFor: function (field, url)
    {
        if (url == undefined)
            url = field.attributes.value;

        var $videoContainer = $(this.getSection(field).find("div.videoContainer"));
        var $linkContainer = $(this.getSection(field).find("div.linkContainer"));
        $videoContainer.html("");
        $linkContainer.html("");

        if (!url)
            return;

        var youtubeMatch = url.match(appConfig.regexLib.youtubeVideoLink);
        if (youtubeMatch)
        {
            var youtubeEmbed = "//www.youtube.com/embed/" + youtubeMatch[1];
            $videoContainer.html("<iframe src=\"" + youtubeEmbed + "\">" + "</iframe>");
            return;
        }

        var vimeoMatch = url.match(appConfig.regexLib.vimeoLink);
        if (vimeoMatch)
        {
            var vimeoEmbed = "//player.vimeo.com/video/" + vimeoMatch[1];
            $videoContainer.html("<iframe src=\"" + vimeoEmbed + "\">" + "</iframe>");
            return;
        }

        var vrideoMatch = url.match(appConfig.regexLib.vrideoLink);
        if (vrideoMatch)
        {
            var vrideoEmbed = "//www.vrideo.com/embed/" + vrideoMatch[1];
            $videoContainer.html("<iframe src=\"" + vrideoEmbed + "\" scrolling='no' frameborder='0' allowfullscreen='1'>" + "</iframe>");
            return;
        }

        if (url.match(appConfig.regexLib.url))
        {
            if (url.search(appConfig.regexLib.urlProtocol) != 0)
                url = "http://" + url;

            $linkContainer.html("<a target=\"_blank\" href=\"" + url + "\">Open Link in New Window</a>");
        }
    }

});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.GroupsSettingsView = Backbone.View.extend(
{
    initialize: function (options)
    {
        _.extend(this, options);

        this.formBuilderForm = this.$el.formBuilderForm();
    },

    changeGroupSettings: function (itemIds)
    {
        this._applyFieldsDefaultSettings();
        this.applyGroupSettings(itemIds);

        this.formBuilderForm.assignPageIdToStaticSections();
        this.formBuilderForm.refreshPage();
    },
    applyGroupSettings: function (itemIds)
    {
        this.affectedFields = [];

        var self = this;
        var mergedGroupSettings = {};

        if (_(itemIds).any())
        {
            _(itemIds).each(function (itemId)
            {
                self._mergeGroupSettings(mergedGroupSettings, self.affectedFields, itemId);
            });
        }
        else
        // if itemId (categoryId or sessionTypeId) is undefined group settings will be merged with default settings
            this._mergeGroupSettings(mergedGroupSettings, this.affectedFields);

        _(this.affectedFields).each(function (field)
        {
            field.set({ hidden: mergedGroupSettings[field.id] == "Hidden" });
            field.set({ required: mergedGroupSettings[field.id] == "Required" });

            if (field.rendered && !field.get("readOnly"))
                self.formBuilderForm.syncRequiredValidationRules(field);
        });

        this.formBuilderForm.renderBreadCrumb();
    },
    getGroupSettings: function (itemId)
    {
        itemId = parseInt(itemId);
        return _(this.model.groupsSettings).find(function (item)
        {
            return itemId ? _(item.groupItemIds).contains(itemId) : item.isDefaultGroup;
        });
    },
    handleTargetItemStateChange: function (itemIds, cancelCallback)
    {
        var self = this;
        var fieldsToHide = this._getFieldsToHide(itemIds);

        this.formBuilderForm.askToHideFields(fieldsToHide, function ()
        {
            self.changeGroupSettings(itemIds);
            self.trigger("targetItemChanged");
        }, cancelCallback);

        this.clearErrors();
    },
    clearErrors: function ()
    {
        var $form = this.$el.closest("form");
        var elementsToClearErrors = $form.find(".input-validation-error:not([aria-required])");
        var messageContainersToClearErrors = _(elementsToClearErrors).map(function (element)
        {
            return $form.find("[data-valmsg-for=\"" + $(element).attr("name") +"\"]");
        });

        $form.clearErrorsForElements(elementsToClearErrors);
        $form.clearErrorsForElements(messageContainersToClearErrors);
    },

    _applyFieldsDefaultSettings: function ()
    {
        if (!this.affectedFields.length)
            return;

        var self = this;
        _(this.affectedFields).each(function (field)
        {
            var setting = _(self.model.fieldsDefaultSettings).findWhere({ fieldId: field.id });
            if (!setting)
                return;

            field.set({ hidden: setting.hidden });
            field.set({ required: setting.required }, { silent: true });

            if (field.rendered)
                self.formBuilderForm.syncRequiredValidationRules(field);
        });
    },
    _mergeGroupSettings: function (mergedGroupSettings, affectedFields, itemId)
    {
        var self = this;
        _(this._getGroupSettingsWithMissingFieldsDefaultSettings(itemId)).each(function (settings)
        {
            var field = self._getFieldById(settings.fieldId);
            if (!field)
                return;

            // set the default value for mergedGroupSettings
            if (!_(affectedFields).contains(field))
            {
                affectedFields.push(field);
                mergedGroupSettings[settings.fieldId] = settings.fieldMode;
            }
            // Change mergedGroupSettings in the case: 
            // If at least one field settings not hidden then the merged group settings for current field can't be hidden.
            // If field settings are required then common group settings for current field is required.
            else if (settings.fieldMode != "Hidden" && mergedGroupSettings[settings.fieldId] == "Hidden" ||
                settings.fieldMode == "Required" && mergedGroupSettings[settings.fieldId] != "Required")
                mergedGroupSettings[settings.fieldId] = settings.fieldMode;
        });
    },
    _getGroupSettingsWithMissingFieldsDefaultSettings: function (itemId)
    {
        var groupSettings = this.getGroupSettings(itemId);
        if (!groupSettings)
            return null;

        var fieldsSettings = _(this.model.fieldsDefaultSettings).chain()
            .filter(function (fieldSettings)
            {
                var fieldIds = _(groupSettings.fieldsSettings).pluck("fieldId");
                return (!_(fieldIds).contains(fieldSettings.fieldId));
            })
            .map(function (fieldSettings)
            {
                var fieldMode;

                if (fieldSettings.hidden)
                    fieldMode = "Hidden";
                else if (fieldSettings.required)
                    fieldMode = "Required";
                else
                    fieldMode = "Not required";

                return { fieldId: fieldSettings.fieldId, fieldMode: fieldMode };
            }).value();

        return groupSettings.fieldsSettings = groupSettings.fieldsSettings.concat(fieldsSettings);
    },
    _getFieldsToHide: function (itemIds)
    {
        var fieldsToHide = [];
        var visibleFieldIds = [];

        var self = this;
        _(itemIds).each(function (itemId)
        {
            var groupSettings = self.getGroupSettings(itemId);
            if (!groupSettings)
                return fieldsToHide;

            _(groupSettings.fieldsSettings).each(function (setting)
            {
                var field = self._getFieldById(setting.fieldId);
                if (!field)
                    return;

                var fieldNeedToShow = _(visibleFieldIds).contains(field.get("id"));
                var existsInListToHide = _(fieldsToHide).contains(field);
                if (setting.fieldMode == "Hidden" && !field.get("hidden") && !fieldNeedToShow && !existsInListToHide)
                    fieldsToHide.add(field);
                else
                {
                    if (_(fieldsToHide).contains(field))
                        fieldsToHide.remove(field);

                    visibleFieldIds.add(field.get("id"));
                }
            });
        });

        return fieldsToHide;
    },
    _getFieldById: function (fieldId)
    {
        return this.formBuilderForm.fieldModels[fieldId];
    },
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.StatefulFieldBaseView = Backbone.View.extend(
{
    initialize: function (options)
    {
        _.extend(this, options);
    },
    
    setValue: function (value)
    {
        var validationResult = this.validateValue(value);
        if (validationResult.error)
            throw validationResult.error;

        this.setValueWithoutValidation(value);
    },
    setValueWithoutValidation: function (value)
    {
        throw "Not Implemented";
    },
    getValueSchema: function ()
    {
        throw "Not Implemented";
    },
    validateValue: function (value)
    {
        return this.getValueSchema().required().validate(value, { abortEarly: false, convert: false });
    }
});
;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.SingleInputFieldView = awardsCommon.widgets.formBuilderForm.StatefulFieldBaseView.extend(
{
    getComponent: function ()
    {
        return this.$(".view input[type='text']");
    },
    getValue: function ()
    {
        return this.getComponent().val();
    },
    setValueWithoutValidation: function (value)
    {
        this.getComponent().val(value).change().focusout().blur();
    },
    getValueSchema: function ()
    {
        return Joi.string().allow("", null);
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.ListFieldBaseView = awardsCommon.widgets.formBuilderForm.StatefulFieldBaseView.extend(
{
    getValueSchema: function ()
    {
        var listValues = this.model.get("listValues");
        var allowedListValueIds = listValues.map(function (v) { return v.id; });
        var allowedListValueValues = listValues.map(function (v) { return v.value; });

        return Joi.string().valid(allowedListValueIds.concat(allowedListValueValues));
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.AddressFieldView = awardsCommon.widgets.formBuilderForm.StatefulFieldBaseView.extend(
{
    getComponent: function ()
    {
        var view = this.$(".view");
        return {
            getStreet: function () { return view.find("input[name$='.Street']"); },
            getLine2: function () { return view.find("input[name$='.Line2']"); },
            getLine3: function () { return view.find("input[name$='.Line3']"); },
            getCity: function () { return view.find("input[name$='.City']"); },
            getCountryCode: function () { return view.find("select[name$='.CountryCode']"); },
            getState: function () { return view.find("[name$='.State']"); },
            getZip: function () { return view.find("input[name$='.Zip']"); }
        };
    },
    getValue: function ()
    {
        var component = this.getComponent();
        return {
            street: component.getStreet().val(),
            line2: component.getLine2().val(),
            line3: component.getLine3().val(),
            city: component.getCity().val(),
            countryCode: component.getCountryCode().val(),
            state: component.getState().val(),
            zip: component.getZip().val()
        };
    },
    setValueWithoutValidation: function (value)
    {
        var component = this.getComponent();

        if (value === null)
        {
            _(component).chain().keys().sort().each(function (k)
            {
                component[k]().val(null).change();
            });
        }
        else
        {
            // sort by key to ensure state is set after country code
            _(value).chain().keys().sort().each(function (k)
            {
                var getInput = component["get" + k.firstLetterToUpperCase()];
                if (getInput)
                    getInput().val(value[k]).change();
            });
        }
    },
    getValueSchema: function ()
    {
        var allowEmptyStringSchema = Joi.string().allow("");
        return Joi.object(
        {
            street: allowEmptyStringSchema,
            line2: allowEmptyStringSchema,
            line3: allowEmptyStringSchema,
            city: allowEmptyStringSchema,
            countryCode: allowEmptyStringSchema,
            state: allowEmptyStringSchema,
            zip: allowEmptyStringSchema
        }).allow(null);
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.CheckboxListFieldView = awardsCommon.widgets.formBuilderForm.ListFieldBaseView.extend(
{
    render: function ()
    {
        this.disableListValues();
    },

    getComponent: function ()
    {
        return this.$(".view input:checkbox");
    },
    getValue: function ()
    {
        return this.getComponent().filter(":checked").map(function ()
        {
            return $(this).val();
        }).get();
    },
    setValueWithoutValidation: function (value)
    {
        var self = this;
        var listValues = this.model.get("listValues");

        this.getComponent().each(function ()
        {
            var $this = $(this);
            var listValue = _(listValues).findWhere({ id: $this.val() });

            var shouldBeChecked = listValue && (_(value).contains(listValue.id) || _(value).contains(listValue.value));
            if (shouldBeChecked && !this.checked || this.checked && !shouldBeChecked)
            {
                // jQuery fires native click event for checkboxes so custom data can't be passed
                // see https://github.com/jquery/jquery/blob/7869f83ddd5a3156a358284cbef6837b5e7a2a62/src/event.js#L480
                // and https://github.com/jquery/jquery/issues/4139
                // It's fixed only in 3.4 version https://github.com/jquery/jquery/commit/669f720edc4f557dfef986db747c09ebfaa16ef5
                // Let's manually invoke handler.
                $this.prop("checked", shouldBeChecked);
                self.formBuilderForm.dependentFieldsParentElementClickedHandler($this, { suppressHidingFieldsConfirmation: true });
            }
        });
    },
    getValueSchema: function ()
    {
        var listValueSchema = this.constructor.__super__.getValueSchema.call(this);
        return Joi.array().items(listValueSchema);
    },
    disableListValues : function ()
    {
        var self = this;
        var selectedValueIds = this.model.get("selectedValueIds");

        _(this.model.get("listValues")).chain().filter(function (v) { return v.isDisabled && (!selectedValueIds || !_(selectedValueIds).contains(v.id)) }).map(function(v) { return v.id; }).each(function (valueId)
        {
            self.getComponent().filter("input[value='" + valueId + "']").prop('disabled', true);
        });
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.DateFieldView = awardsCommon.widgets.formBuilderForm.StatefulFieldBaseView.extend(
{
    getComponent: function ()
    {
        return this.formBuilderForm.getSection(this.model).dateTimePicker();
    },
    getValue: function ()
    {
        return Date.parseExact(this.getComponent().getValue(), this.getDateFormat());
    },
    setValueWithoutValidation: function (value)
    {
        var dateTimePicker = this.getComponent();
        if (value === null)
            dateTimePicker.clearValue();
        else
            dateTimePicker.setValue(value.toString(this.getDateFormat()));
    },
    getValueSchema: function ()
    {
        return Joi.date().allow(null);
    },
    getDateFormat: function ()
    {
        return appConfig.dateFormat;
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.DropDownListFieldView = awardsCommon.widgets.formBuilderForm.ListFieldBaseView.extend(
{
    render: function ()
    {
        this.disableListValues();
    },

    getComponent: function ()
    {
        return this.$(".view select[name$='.SelectedValueId']");
    },
    getValue: function ()
    {
        return this.getComponent().val();
    },
    setValueWithoutValidation: function (value)
    {
        var listValue = _(this.model.get("listValues")).findWhere({ value: value });
        this.getComponent().val(listValue ? listValue.id : value).trigger("change", { suppressHidingFieldsConfirmation: true });
    },
    getValueSchema: function ()
    {
        var listValueSchema = this.constructor.__super__.getValueSchema.call(this);
        return listValueSchema.allow(null);
    },
    disableListValues : function ()
    {
        var self = this;
        var selectedValueId = this.model.get("selectedValueId");

        _(this.model.get("listValues")).chain().filter(function (v) { return v.isDisabled && selectedValueId != v.id }).map(function(v) { return v.id; }).each(function (valueId)
        {
            self.getComponent().find("option[value='" + valueId + "']").prop('disabled', true);
        });
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.FileUploadFieldView = awardsCommon.widgets.formBuilderForm.StatefulFieldBaseView.extend(
{
    initialize: function (options)
    {
        this.constructor.__super__.initialize.call(this, options);

        this.fileUploader = this.$el.fileUploader();
        this.isCaptionShown = this.model.get("showCaption");
    },

    getComponent: function ()
    {
        throw "Not Supported";
    },
    getValue: function ()
    {
        var mediaIdStr = this.fileUploader.mediaIdInput.val();
        var value = {
            mediaId: mediaIdStr ? Number(mediaIdStr) : undefined
        };

        if (this.isCaptionShown)
            value.caption = this.getCaptionInput().val();

        return value;
    },
    setValueWithoutValidation: function (value)
    {
        var fileUploader = this.fileUploader;
        if (value.mediaId && fileUploader.fileUploaded && value.mediaId != this.getValue().mediaId)
            throw "Cannot change uploaded file.";

        if (value.mediaId && !fileUploader.fileUploaded)
        {
            fileUploader.hideUploadPanel();

            var self = this;
            return fileUploader.setMediaId(value.mediaId)
                .then(function () { self.getCaptionInput().val(value.caption); });
        }
        else
            this.getCaptionInput().val(value.caption);

        return Promise.resolve();
    },
    getValueSchema: function ()
    {
        return Joi.object({ mediaId: Joi.number().integer().min(1), caption: Joi.string().allow("") });
    },
    getCaptionInput: function ()
    {
        return this.$("input[name$='.Caption']");
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.MultilineTextFieldView = awardsCommon.widgets.formBuilderForm.StatefulFieldBaseView.extend(
{
    getComponent: function ()
    {
        return this.$(".view textarea");
    },
    getValue: function ()
    {
        var component = this.getComponent();
        return this.isWysiwyg() ? component.textEditor().getData() : component.val();
    },
    setValueWithoutValidation: function (value)
    {
        var component = this.getComponent();
        this.isWysiwyg() ? component.textEditor().setData(value) : component.val(value);
    },
    getValueSchema: function ()
    {
        return Joi.string().allow("", null);
    },
    isWysiwyg: function ()
    {
        return this.model.get("isWysiwyg");
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.NumberFieldView = awardsCommon.widgets.formBuilderForm.SingleInputFieldView.extend(
{
    getValue: function ()
    {
        var value = this.constructor.__super__.getValue.call(this);
        return value ? Number(value) : undefined;
    },
    getValueSchema: function ()
    {
        var model = this.model;
        var schema = Joi.number().allow(null);

        var minValue = model.get("minValue");
        if (!_.isNullOrUndefined(minValue))
            schema = schema.min(minValue);

        var maxValue = model.get("maxValue");
        if (!_.isNullOrUndefined(maxValue))
            schema = schema.max(maxValue);

        var maxPrecision = model.get("maxPrecision");
        if (!_.isNullOrUndefined(maxPrecision))
            schema = schema.precision(maxPrecision);

        return schema;
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.RadioListFieldView = awardsCommon.widgets.formBuilderForm.ListFieldBaseView.extend(
{
    render: function ()
    {
        this.disableListValues();
    },

    getComponent: function ()
    {
        return this.$(".view input:radio");
    },
    getValue: function ()
    {
        return this.getComponent().filter(":checked").val();
    },
    setValueWithoutValidation: function (value)
    {
        if (value == this.getValue())
            return;

        var listValue = _(this.model.get("listValues")).findWhere({ value: value });
        var listValueId = listValue ? listValue.id : value;

        this.getComponent().filter("[value='" + listValueId + "']").prop("checked", true).trigger("change", { suppressHidingFieldsConfirmation: true });
    },
    disableListValues : function ()
    {
        var self = this;
        var selectedValueId = this.model.get("selectedValueId");

        _(this.model.get("listValues")).chain().filter(function (v) { return v.isDisabled && selectedValueId != v.id }).map(function(v) { return v.id; }).each(function (valueId)
        {
            self.getComponent().filter("input[value='" + valueId + "']").prop('disabled', true);
        });
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.TableFieldView = Backbone.View.extend(
{
    initialize: function (options)
    {
        _.extend(this, options);

        $.templates("tableFieldEditControlsSectionTmpl", this.$("#tableFieldEditControlsSectionTmpl").html());
        
        this.events = this.events || {};

        var tableFieldSectionSelector = "section[data-fieldId='" + this.field.id + "']";
        this.tableEl = this.$(tableFieldSectionSelector + " table");

        var tableFieldSectionClickEventSelector = "click " + tableFieldSectionSelector;
        this.events[tableFieldSectionClickEventSelector + " button.add"] = this.onAddRowClicked;
        this.events[tableFieldSectionClickEventSelector + " a.edit"] = this.onEditRowClicked;
        this.events[tableFieldSectionClickEventSelector + " a.remove"] = this.onRemoveRowClicked;
        this.delegateEvents();

        this.field.on("change:hidden change:hiddenByParent", this.onHiddenOrHiddenByParentChanged, this);

        this.arrayIndexSequence = 0;

        this.tableRowData = new Backbone.Collection(_(this.field.get("rows")).chain().map(this.buildTableRow, this).sortBy("id").value());

        this.tableRowData.on("add change:fieldValues", this.updateRowContent, this);
        this.tableRowData.on("add remove change:fieldValues", function () { this.tableEl.trigger("change"); }, this);
        this.tableRowData.on("add remove", this.toggleAddRowButton, this);

        this.formBuilderForm.on("pageChanged", function (newPageIndex)
        {
            if (this.formBuilderForm.getPageIndexByFieldId(this.field.id) != newPageIndex)
                this.cancelCurrentRowEditIfExists();
        }, this);

        this.nestedFields = options.field.get("fields");
        this.maxRowCount = options.field.get("maxRowCount");

        this.rowValueSchema = Joi.object(
        {
            alias: Joi.string().required().valid(this.nestedFields.map(function (f) { return f.get("alias"); })),
            value: Joi.any().required()
        });

        this.rowValuesSchema = Joi.array().items(this.rowValueSchema).required();
    },
    render: function ()
    {
        var fieldsToRender = this.tableRowData.chain().map(function (r)
        {
            return this.mergeFieldsWithRowFieldValues(r, false);
        }, this).flatten().value();

        this.tableFieldSection = this.formBuilderForm.getSection(this.field);
        this.formBuilderForm.renderContainerFields(fieldsToRender, this.tableFieldSection);

        var self = this;
        this.dataTable = this.tableFieldSection.find("#Table-" + this.field.id).DataTable(
        {
            data: this.tableRowData,
            columnDefs:
            [
                { orderable: false, targets: "_all" }
            ],
            columns:
            [
                { data: "sortOrder", visible: false },
                { width: "10%", template: "<div class='reorderCell'></div>", visible: !this.field.readOnly },
                { title: htmlEncode(this.field.get("rowNamePlural")) || "Items", width: "70%", template: "{{:content}}" },
                {
                    title: "Action",
                    width: "20%",
                    template: "<a class='edit' data-rowId='{{:id}}' href='javascript:void(0)'>Edit</a>" +
                        "<span> | </span><a class='remove' data-rowId='{{:id}}' href='javascript:void(0)' style='color:red'>Remove</a>",
                    visible: !this.field.readOnly
                }
            ],
            searching: false,
            paging: false,
            info: false,
            order: [[0, "asc"]],
            rowReorder:
            {
                snapX: true,
                update: false,
                selector: "td:has(div.reorderCell)",
                enable: !this.field.readOnly
            },
            language:
            {
                emptyTable: sprintf("No %(rowNamePlural)s have been added. Click on Add %(rowName)s below.",
                {
                    rowName: htmlEncode(this.field.get("rowName")) || "Item",
                    rowNamePlural: htmlEncode(this.field.get("rowNamePlural")) || "Items"
                })
            }
        })
        .on("row-reorder", function (e, diff)
        {
            // Row Reorder extension prevents detecting changes by LeavingViewProtector,
            // because it stops propogation of click event, which is tracked by LeavingViewProtector.
            if (_(diff).any())
                self.formBuilderForm.trigger("changed");

            var rowToSort = {};
            var sortOrders = _(self.tableRowData.pluck("sortOrder")).sortBy(); // map rowOrder [0...rowCount-1] to model.sortOrder, which can start from both 0 or 1

            _(diff).chain().each(function (r)
            {
                rowToSort[r.oldPosition] = self.tableRowData.findWhere({ sortOrder: sortOrders[r.oldPosition] });
            }, self).sortBy("oldPosition").each(function (r)
            {
                this.updateRowSortOrder(rowToSort[r.oldPosition], r.newPosition);
            }, self);
        });

        this.toggleAddRowButton();
        if (!this.field.get("fields").length)
        {
            this.tableFieldSection.find("button.add")
                .prop("disabled", true)
                .attr("title", "Table field form doesn't contain any field.");
        }

        return this;
    },

    onAddRowClicked: function (e)
    {
        this.cancelCurrentRowEditIfExists();
        this._disableRowReorder();

        var newRow = this.buildTableRow(
        {
            id: uuid.v4(),
            fieldValues: [],
        });

        var fieldModels = this.mergeFieldsWithRowFieldValues(newRow, true);

        this.currentRowEdit = new this.subformModificationView(
        {
            tableFieldSection: this.tableFieldSection,
            tableFieldId: this.field.id,
            fieldModels: fieldModels,
            isAdd: true
        })
        .render()
        .on("saved", function ()
        {
            // Set sort order on save because new rows can be added while sub-form is still opened (by frontend API),
            // so sort order can't be reserved in advance.
            var sortOrder = this._getNextSortOrder();
            _(fieldModels).each(function (m)
            {
                m.set({ sortOrder: sortOrder });
            });

            this._replaceOldModelsWithNewOne(fieldModels);
            newRow.set({ fieldValues: this._extractRowFieldValues(newRow.id), sortOrder: sortOrder });
            this.tableRowData.add(newRow);

            this.getRowFieldSections(newRow.id).find("input[name$='.SortOrder'][type='hidden']").val(sortOrder);
            this.trigger("rowAdded");
            this._enableRowReorder();
        }, this)
        .on("dispose", function ()
        {
            this.currentRowEdit = null;
            this.toggleAddRowButton();
            this._enableRowReorder();
        }, this)
        .on("canceled", function ()
        {
            this._onAddOrEditCanceled(fieldModels);
            this._enableRowReorder();
        }, this);

        this.formBuilderForm.renderContainerFields(fieldModels, this.tableFieldSection);
        this.toggleAddRowButton();
        this.scrollToTopOfSubformModificationForm();

        this._triggerRowOpenedEvent(newRow.id);
    },
    onEditRowClicked: function (e)
    {
        e.preventDefault();

        this.cancelCurrentRowEditIfExists();
        this._disableRowReorder();

        var rowId = $(e.target).attr("data-rowId");
        var row = this.tableRowData.get(rowId);

        var originalRowFieldSections = this.getRowFieldSections(rowId);
        var fieldModels = this.mergeFieldsWithRowFieldValues(row, true);

        this.currentRowEdit = new this.subformModificationView(
        {
            rowId: rowId,
            tableFieldId: this.field.id,
            tableFieldSection: this.tableFieldSection,
            fieldModels: fieldModels
        })
        .on("saved", function ()
        {
            this._replaceOldModelsWithNewOne(fieldModels);
            row.set({ fieldValues: this._extractRowFieldValues(rowId) });
            this.trigger("rowUpdated");
            this._enableRowReorder();
        }, this)
        .on("dispose", function ()
        {
            this.currentRowEdit = null;
            this.toggleAddRowButton();
            this._enableRowReorder();
        }, this)
        .on("canceled", function ()
        {
            this._onAddOrEditCanceled(fieldModels);
            this._enableRowReorder();
        }, this)
        .render();

        // detach original field sections before rendering duplicate sections to avoid input name conflicts (e.g. in radio inputs)
        originalRowFieldSections.detach();
        this.formBuilderForm.renderContainerFields(fieldModels, this.tableFieldSection);
        this.tableFieldSection.after(originalRowFieldSections);

        this.toggleAddRowButton();
        this.scrollToTopOfSubformModificationForm();

        this._triggerRowOpenedEvent(rowId);
    },
    onRemoveRowClicked: function (e)
    {
        e.preventDefault();

        var self = this;
        if (self.hasUnsavedChanges())
        {
            self.highlightRowControlsIfItHasUnsavedChanges();
            return;
        }

        Confirmation.requestDelete(
        {
            callback: function ()
            {
                var rowId = $(e.target).attr("data-rowId");
                self.removeRowAsync(rowId).catch(function () {});
            }
        });
    },

    onHiddenOrHiddenByParentChanged: function ()
    {
        var visible = this.field.isVisible();

        if (!visible)
            this.cancelCurrentRowEditIfExists();

        this.getContainerFieldSections().filter(":not(.hiddenField)").ignoreOnSubmit(!visible);
    },

    buildTableRow: function(row)
    {
        return new Backbone.Model(_.extend({}, row,
        {
            id: row.id,
            content: this.resolveRowContent(row.fieldValues),
        }));
    },
    getContainerFieldSectionSelector: function (path)
    {
        var tableFieldSectionId = this.formBuilderForm.buildFieldSectionId(this.field.getPath());
        return "[id^='" + tableFieldSectionId + $.escapeSelector(path || "") + "']:not(#" + tableFieldSectionId + ")";
    },
    getContainerFieldSections: function ()
    {
        return this.$(this.getContainerFieldSectionSelector());
    },
    getRowFieldSections: function (rowId)
    {
        return this.$(this.getContainerFieldSectionSelector("[" + rowId + "]"));
    },
    getVisibleRowFieldSections: function (rowId)
    {
        return this.getRowFieldSections(rowId).filter("[data-containerFieldPath='" + $.escapeSelector(this.field.getPath()) + "']");
    },
    getSubformFields: function ()
    {
        return this.field.get("fields");
    },
    mergeFieldsWithRowFieldValues: function (row, inEditMode, disableAutocomplete)
    {
        var sortOrder = row.get("sortOrder");
        return this.formBuilderForm.prepareFieldViewModel(this.getSubformFields(), row.get("fieldValues"),
        {
            parentFieldPath: this.field.getPath(),
            prefix: this.scope + ".Rows[" + row.id + "]",
            sortOrder: sortOrder,
            pageId: this.field.get("pageId"),
            rowId: row.id,
            inEditMode: inEditMode,
            disableAutocomplete: disableAutocomplete,
            customSectionAttributes:
            {
                containerFieldPath: this.field.getPath()
            }
        });
    },
    updateRowSortOrder: function (row, newSortOrder)
    {
        _(this.getVisibleRowFieldSections(row.id).toArray()).each(function (section)
        {
            $(section).find("input[name$='.SortOrder']").val(newSortOrder);
        }, this);

        row.set({ sortOrder: newSortOrder }, { reDraw: false });
    },
    updateRowContent: function (row)
    {
        row.set({ content: this.resolveRowContent(row.get("fieldValues")) });
    },
    resolveRowContent: function (fieldValues)
    {
        var rowTemplate = this.field.get("rowTemplate");
        if (fieldValues.length == 0 || !rowTemplate)
            return "";

        var self = this;
        var nestedFields = this.field.get("fields");
        _(rowTemplate.matchAllRegex(appConfig.regexLib.tableFieldRowTemplateFieldValuePlaceholder)).each(function (match)
        {
            var placeholder = match[0],
                field = nestedFields.get(match[1]),
                source = match[3]; // source without dot

            if (field)
                rowTemplate = rowTemplate.replace(placeholder, self.resolveFieldValueForPlaceholder(field, source, fieldValues));
        });

        return rowTemplate;
    },
    resolveFieldValueForPlaceholder: function (field, source, fieldValues)
    {
        var fields = this.field.get("fields");
        var fieldValue = _(fieldValues).findWhere({ fieldId: field.id });

        var isFieldHidden = function (fieldToCheck)
        {
            var visibilityCondition = fieldToCheck.get("visibilityCondition");
            if (!visibilityCondition)
                return false;

            var parentField = fields.get(visibilityCondition.fieldId);
            if (isFieldHidden(parentField))
                return true;

            var parentFieldValue = _(fieldValues).findWhere({ fieldId: parentField.id });

            if (parentField.isDropDownList() || parentField.isRadioList())
                return parentFieldValue.selectedValueId != visibilityCondition.selectedListValueId;

            return !_(parentFieldValue.selectedValueIds).contains(visibilityCondition.selectedListValueId);
        };

        var value = "";

        // case when field is removed from form template but it's id is still used in row template or field is hidden
        if (!fieldValue || isFieldHidden(field)) 
            return value;

        if (source)
        {
            var sourceProperty = source.firstLetterToLowerCase();
            var sourceValue = fieldValue[sourceProperty];
            var isMediaUrlSource = sourceProperty === "mediaUrl";
            var isMediaPreviewUrlSource = sourceProperty === "mediaPreviewUrl";
            var isMediaFileNameSource = sourceProperty === "mediaFileName";

            if (!_.isNull(sourceValue) && !_.isUndefined(sourceValue))
                value = sourceValue;
            else if (isMediaUrlSource || isMediaPreviewUrlSource || isMediaFileNameSource)
            {
                var mediaId = fieldValue["mediaId"];
                if (mediaId)
                {
                    value = (isMediaUrlSource ? this.redirectToMediaUrl
                        : isMediaPreviewUrlSource ? this.redirectToMediaPreviewUrl : this.mediaFileNameUrl).replace("{{:mediaId}}", mediaId);
                }
                else
                    value = this.noFileUploadedUrl;
            }
            else if (sourceProperty == "countryName")
            {
                var countryCode = fieldValue["countryCode"];
                if (countryCode)
                    value = _(awardsCommon.widgets.formBuilderForm.geoNamesProvider.countriesWithStates).findWhere({ code: countryCode }).name;
            }
        }
        else
        {
            if (field.isList())
            {
                var listValues = field.get("listValues");

                if (field.isCheckBoxList())
                {
                    var selectedValueIds = fieldValue.selectedValueIds;
                    if (selectedValueIds)
                    {
                        value = _(listValues).chain().filter(function (listValue)
                        {
                            return _(selectedValueIds).contains(listValue.id);
                        }).map(function (listValue)
                        {
                            return listValue.value;
                        }).value().join(", ");
                    }
                }
                else
                {
                    if (field.isDropDownList())
                        listValues = awardsCommon.widgets.formBuilderForm.geoNamesProvider[field.get("preFillType").firstLetterToLowerCase()] || listValues;

                    var selectedValueId = fieldValue.selectedValueId;
                    if (selectedValueId)
                        value = _(listValues).findWhere({ id: selectedValueId }).value;
                }
            }
            else if (field.isDate() && !_.isNull(fieldValue.valueUtc))
                value = fieldValue.valueUtc.formatDate("{d}");
            else if (!_.isNull(fieldValue.value))
                value = field.isPhoneNumber() ? fieldValue.value.formatPhoneNumber() : fieldValue.value;
        }

        return value;
    },
    cancelCurrentRowEditIfExists: function ()
    {
        if (this.currentRowEdit)
            this.currentRowEdit.cancel();
    },
    hasValue: function ()
    {
        return this.tableRowData.length > 0;
    },
    hasUnsavedChanges: function ()
    {
        return !_.isNull(this.currentRowEdit) && !_.isUndefined(this.currentRowEdit);
    },
    highlightRowControlsIfItHasUnsavedChanges: function ()
    {
        if (!this.hasUnsavedChanges())
            return;

        var elementsToFocus = this.currentRowEdit.subformFieldSections;
        var controlSection  = elementsToFocus.next();
        var validationErrorClass = "input-validation-error";

        controlSection.find("button.cancel").addClass(validationErrorClass);
        controlSection.find("button.save").addClass(validationErrorClass);
    },
    toggleAddRowButton: function ()
    {
        var canAddRows = this.tableRowData.length < this.field.get("maxRowCount") && !this.currentRowEdit;
        var hasRows = this.tableRowData.length > 0;
        this.tableFieldSection.find("button.add.first").toggle(!hasRows && canAddRows);
        this.tableFieldSection.find("button.add.another").toggle(hasRows && canAddRows);
    },
    scrollToTopOfSubformModificationForm: function ()
    {
        $("html, body").animate(
        {
            scrollTop: this.tableFieldSection.nextAll("section:visible").first().offset().top - appConfig.verticalScrollOffset
        }, 500);
    },
    addEmptyRow: function ()
    {
        var newRow = this.buildTableRow(
        {
            id: uuid.v4(),
            fieldValues: [], 
            sortOrder: this._getNextSortOrder(),
        });

        var fieldModels = this.mergeFieldsWithRowFieldValues(newRow, false, true);
        this.formBuilderForm.renderContainerFields(fieldModels, this.tableFieldSection);
        this.getRowFieldSections(newRow.id).hide();
        this.tableRowData.add(newRow);

        return newRow.get("sortOrder");
    },
    updateRowFieldValues: function (rowSortOrder)
    {
        var row = this.tableRowData.find(function (r) { return r.get("sortOrder") == rowSortOrder });
        if (row)
            row.set({ fieldValues: this._extractRowFieldValues(row.id) });
    },
    resolveRowIdBySortOrder: function (sortOrder)
    {
        var row = this.tableRowData.find(function (r) { return r.get("sortOrder") == sortOrder; });
        return row ? row.id : undefined;
    },
    removeRowAsync: function (rowId)
    {
        var self = this;
        return new Promise(function (resolve, reject)
        {
            var mediaIds = _(self.tableRowData.get(rowId).get("fieldValues")).chain()
                .filter(function (fv) { return fv["mediaId"]; }).map(function (fv) { return fv["mediaId"]; }).value();

            if (!mediaIds.length)
            {
                self._removeRow(rowId);
                resolve();
            }
            else
            {
                Backbone.post(self.deleteMultipleMediaUrl,
                {
                    mediaIds: mediaIds,
                },
                {
                    success: function ()
                    {
                        self._removeRow(rowId);
                        resolve();
                    },
                    error: function (response)
                    {
                        reject(response.responseJSON.description);
                    }
                });
            }
        });
    },
    getComponent: function ()
    {
        return this;
    },
    getRowCount: function ()
    {
        return this.tableRowData.length;
    },
    addRow: function (rowValues)
    {
        if (this.getRowCount() == this.maxRowCount)
            throw "Table already reached maximum allowed row count.";

        Joi.assert(rowValues, this.rowValuesSchema);

        var sortOrder = this.addEmptyRow();
        var rowId = this.resolveRowIdBySortOrder(sortOrder);

        var self = this;
        _(rowValues).each(function (v)
        {
            self.setValueInRow(rowId, v);
        });

        this.updateRowFieldValues(sortOrder);

        return sortOrder;
    },
    setValueInRow: function (rowId, value)
    {
        Joi.assert(value, this.rowValueSchema);

        var form = this.formBuilderForm;
        
        var fieldId = form.fieldAliasesIds[value.alias];
        if (!fieldId)
            throw "Failed to find row field by alias '" + value.alias + "'.";

        var fieldPath = _(form.fieldModels).chain().keys().find(function (k)
        {
            return k.endsWith("[" + rowId + "]_" + fieldId);
        }).value();

        if (!fieldPath)
            throw "Row with id '" + rowId + "' doesn't exist.";

        var field = form.fieldModels[fieldPath];
        var fieldView = form.fieldViews[fieldPath];

        fieldView.setValue(value.value);
    },
    clear: function ()
    {
        var self = this;

        this.tableRowData
            .chain()
            .map(function (row) { return row.id; })
            .each(function (rowId) { self._removeRow(rowId); });
    },

    _getNextSortOrder: function ()
    {
        return this.tableRowData.length
            ? this.tableRowData.chain().map(function (row) { return row.get("sortOrder"); }).max().value() + 1
            : 0;
    },
    _extractRowFieldValues: function (rowId)
    {
        var subformFields = this.getSubformFields();
        return this._extractFieldValueFromObject($("<form>").append(this.getRowFieldSections(rowId).clone()).toObject(), function (obj)
        {
            return obj.constructor.modelType == "awardsCommon.FieldModel" &&
                subformFields.any(function (f)
                {
                    return f.id == obj.fieldId;
                });
        });
    },
    _extractFieldValueFromObject: function (theObject, predicate)
    {
        if (!theObject)
            return theObject;

        var result = [];
        if (theObject instanceof Array)
        {
            for (var i = 0; i < theObject.length; i++)
            {
                var value = this._extractFieldValueFromObject(theObject[i], predicate);

                if (value.length)
                    result = result.concat(value);
            }
        }
        else
        {
            if (predicate(theObject))
                return [theObject];

            var propNames = _(theObject).chain().keys().filter(function (p) { return !_.isFunction(theObject[p]) }).value();

            for (var i = 0; i < propNames.length; i++)
            {
                result = this._extractFieldValueFromObject(theObject[propNames[i]], predicate);

                if (result)
                    break;
            }
        }

        return result;
    },
    _replaceOldModelsWithNewOne: function (fieldModels)
    {
        var self = this;
        _(fieldModels).each(function (m)
        {
            var inEditModeFieldPath = m.getPath();
            var newView = self.formBuilderForm.fieldViews[inEditModeFieldPath];

            // delete model and view with "inEditMode" path
            delete self.formBuilderForm.fieldModels[inEditModeFieldPath];
            delete self.formBuilderForm.fieldViews[inEditModeFieldPath];

            // when disable edit mode and replace old model
            m.set({ inEditMode: false });

            var newPath = m.getPath();

            var oldModel = self.formBuilderForm.fieldModels[newPath];
            if (oldModel)
                self.formBuilderForm.deleteFieldModel(oldModel);

            m.set({ fieldPath: newPath });
            self.formBuilderForm.fieldModels[newPath] = m;
            self.formBuilderForm.fieldViews[newPath] = newView;
        });
    },
    _onAddOrEditCanceled: function (fieldModels)
    {
        var self = this;
        _(fieldModels).each(function (m)
        {
            self.formBuilderForm.deleteFieldModel(m);
        });
    },
    _disableRowReorder: function ()
    {
        this.dataTable.rowReorder.disable();
    },
    _enableRowReorder: function ()
    {
        this.dataTable.rowReorder.enable();
    },
    _removeRow: function (rowId)
    {
        var sortOrder = this.tableRowData.get(rowId).get("sortOrder");

        if (this.currentRowEdit && this.currentRowEdit.rowId === rowId)
            this.cancelCurrentRowEditIfExists();

        this.tableRowData.remove(rowId);

        var rowFieldSections = this.getRowFieldSections(rowId);
        _(rowFieldSections).each(function (section)
        {
            var textarea = $(section).find("textarea.textEditor");
            if (textarea.length &&
                CKEDITOR.instances[textarea.attr("id")]) // textEditor can be destroyed already after row edit finish
                textarea.textEditor().destroy();
        });

        rowFieldSections.remove();

        this.tableRowData.chain().filter(function (row) { return row.get("sortOrder") > sortOrder; }).each(function (row)
        {
            this.updateRowSortOrder(row, row.get("sortOrder") - 1);
        }, this);
    },
    _triggerRowOpenedEvent: function (rowId)
    {
        this.trigger("rowOpened", { rowId: rowId });
    },
});;$.extend(awardsCommon.widgets.formBuilderForm.TableFieldView.prototype,
{
    subformModificationView: Backbone.View.extend(
    {
        initialize: function (options)
        {
            _.extend(this, options);
        },
        render: function ()
        {
            this.subformFieldSections = $();

            _(this.fieldModels).each(function (f)
            {
                f.on("rendered", this.onFieldRendered, this);
            }, this);

            this.controlsSection = $.parseHTML($.render("tableFieldEditControlsSectionTmpl", { isAdd: this.isAdd }).trim());

            var $controlsSection = $(this.controlsSection);
            $controlsSection.attr("data-containerfieldpath", this.options.tableFieldId);
            $controlsSection.find("button.save").on("click", this.onSaveClicked.bind(this));
            $controlsSection.find("button.cancel").on("click", this.onCancelClicked.bind(this));

            this.tableFieldSection.after(this.controlsSection);

            return this;
        },

        onSaveClicked: function ()
        {
            this.save();
        },
        onCancelClicked: function ()
        {
            this.cancel();
        },
        onAddressCountryChanged: function (event)
        {
            var fieldPath = $(event.target).closest("section").attr("data-fieldPath");
            var fieldModel = _(this.fieldModels).find(function (model)
            {
                return model.get("fieldPath") == fieldPath;
            });

            var stateInput = awardsCommon.widgets.formBuilderForm.FormBuilderFormView.prototype.updateAddressStateInput(event.target, fieldModel.get("prefix"));

            if (stateInput != null)
                stateInput.attr("name", stateInput.attr("name") + "_inEditMode");
        },
        onFieldRendered: function ($fieldSection)
        {
            $fieldSection.ignoreOnSubmit().addClass("forceValidation");

            // make input names unique for editable fields to overcome conflict with original inputs (conflicts cause issues with validation - only first element with the name
            // will be selected by $.validator.elements for validation; also it cause issues with radio groups - only one item can be selected in radio group with the name)
            var validator = this.getValidator($fieldSection);
            var fieldInputElements = $fieldSection.find("input, select, textarea").filter(function () { return $(this).parents("span.details").length == 0; });
            fieldInputElements.each(function ()
            {
                var $this = $(this);
                var name = $this.attr("name");
                var nameWithPostfix = name + "_inEditMode";
                $this.attr("name", nameWithPostfix);

                var valmsgForDataAttributeName = "data-valmsg-for";
                var errorContainer = $("[" + valmsgForDataAttributeName + "='" + $.escapeSelector(name) + "']");
                errorContainer.attr(valmsgForDataAttributeName, nameWithPostfix);

                var validationRules = validator.settings.rules[name];
                var validationMessages = validator.settings.messages[name];
                if (validationRules)
                {
                    delete validator.settings.rules[name];
                    delete validator.settings.messages[name];

                    validator.settings.rules[nameWithPostfix] = validationRules;
                    validator.settings.messages[nameWithPostfix] = validationMessages;
                }
            });

            $fieldSection.find("select[name$='.CountryCode_inEditMode']").on("change", this.onAddressCountryChanged.bind(this));

            this.subformFieldSections = this.subformFieldSections.add($fieldSection);
        },

        save: function ()
        {
            var validator = this.getValidator();
            if (!validator.checkElements(this.subformFieldSections))
            {
                validator.enableValidationOnFocusOutOrKeyUpEvents();
                return;
            }
            
            this.finishEdit();
            this.subformFieldSections.removeClass("forceValidation inEditMode").filter(":not(.hiddenField)").ignoreOnSubmit(false);

            this.subformFieldSections.each(function ()
            {
                var removeInEditModeInAttribute = function ($elem, attrName)
                {
                    $elem.attr(attrName, $elem.attr(attrName).replace("_inEditMode", ""));
                };

                var $this = $(this);
                $this.find("[name$='_inEditMode']").each(function ()
                {
                    removeInEditModeInAttribute($(this), "name");
                });

                removeInEditModeInAttribute($this, "id");

                var fieldPathAttrName = "data-fieldPath";
                if (!_.isUndefined($this.attr(fieldPathAttrName)))
                    removeInEditModeInAttribute($this, fieldPathAttrName);
            });

            this.trigger("saved");
        },
        cancel: function ()
        {
            this.finishEdit();
            this.trigger("canceled");
        },
        finishEdit: function ()
        {
            var validator = this.getValidator();
            this.subformFieldSections.find("[name$='_inEditMode']").each(function ()
            {
                delete validator.settings.rules[$(this).attr("name")];
            });

            _(this.fieldModels).each(function (f)
            {
                f.off("rendered", this.onFieldRendered, this);
            }, this);

            $(this.controlsSection).remove();
            this.trigger("dispose");
        },
        getValidator: function ($fieldSection)
        {
            var anyFormElement = $fieldSection || this.subformFieldSections;
            return anyFormElement.closest("form").validate();
        }
    })
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.TextFieldView = awardsCommon.widgets.formBuilderForm.SingleInputFieldView.extend(
{
    render: function ()
    {
        var textInput = this.getComponent();
        var field = this.model;

        if (field.get("allowAutocompleteFromExternalSource") && !field.get("disableAutocomplete"))
        {
            var self = this;
            var sourceUrl = field.get("externalAutocompleteSourceUrl");
            textInput.devbridgeAutocomplete(
            {
                serviceUrl: sourceUrl,
                preventBadQueries: false,
                transformResult: function (response)
                {
                    return {
                        suggestions: _(JSON.parse(response)).map(function (suggestion)
                        {
                            var isSuggestionString = _.isString(suggestion);

                            return {
                                value: isSuggestionString ? suggestion : suggestion.label,
                                data: isSuggestionString ? suggestion : suggestion.value
                            };
                        })
                    };
                },
                formatResult: function(suggestion)
                {
                    return htmlEncode(suggestion.value);
                },
                onSelect: function (suggestion)
                {
                    if (field.get("allowUseAutocompleteSuggestionsToSetFieldValuesFromExternalSource") && suggestion.data)
                    {
                        var fieldValuesUrl = field.get("externalSourceUrlToSetFieldValuesByAutocompleteSuggestion");
                        Backbone.get(fieldValuesUrl,
                        {
                            data: { value: suggestion.data },
                            success: function (response)
                            {
                                self._setFieldValuesFromExternalSource(response.result);
                            }
                        });
                    }
                }
            });
        }
    },

    addValidationRules: function (fieldValueEl, validator)
    {
        var anyValidationRuleAdded = false;
        var field = this.model;

        var externalValidationUrl = field.get("externalValidationUrl");
        if (externalValidationUrl)
        {
            fieldValueEl.on("blur", function ()
            {
                if (validator.settings.onfocusout)
                    validator.element(fieldValueEl);
            });

            fieldValueEl.rules("add", { validOnExternalSource: externalValidationUrl, messages: { validOnExternalSource: "" } });
            anyValidationRuleAdded = true;
        }

        if (field.get("allowAutocompleteFromExternalSource") && field.get("areOnlyExternalSourceValuesAllowed"))
        {
            var devbridgeAutocomplete = fieldValueEl.devbridgeAutocomplete();
            var existingOptionsHandler = devbridgeAutocomplete.options.onSelect;

            devbridgeAutocomplete.setOptions(
            {
                triggerSelectOnValidInput: false,
                onSelect: function (suggestion)
                {
                    if (validator.settings.onfocusout)
                        validator.element(fieldValueEl);

                    if (_.isFunction(existingOptionsHandler))
                        existingOptionsHandler(suggestion);
                }
            });

            fieldValueEl.rules("add", { selectedFromExternalSource: field.get("externalAutocompleteSourceUrl"), messages: { selectedFromExternalSource: "Please, select one of suggested values." } });
            anyValidationRuleAdded = true;
        }

        return anyValidationRuleAdded;
    },

    _setFieldValuesFromExternalSource: function (externalSourceResponse)
    {
        var self = this;
        var tableAliases = [];
        var parentFieldPath = this.model.get("parentFieldPath");

        _(externalSourceResponse)
            .chain()
            .filter(function (entry) { return !_.isNull(entry.tableAlias); })
            .each(function (entry)
            {
                if (!_(tableAliases).contains(entry.tableAlias) && parentFieldPath !== self.formBuilderForm.fieldAliasesIds[entry.tableAlias])
                    tableAliases.push(entry.tableAlias);
            });

        _(tableAliases).each(function (tableAlias)
        {
            var tableFieldView = self._getFieldView(tableAlias);

            if (tableFieldView)
                tableFieldView.clear();
        });

        _(externalSourceResponse).each(function (entry)
        {
            if (entry.tableAlias)
                self._applyDataToTableFieldRow(entry.tableAlias, entry.fields);
            else
                self._applyDataToFields(entry.fields);
        });
    },
    _applyDataToFields: function (fieldValues)
    {
        this._parseDateFieldValues(fieldValues, this.formBuilderForm.model.get("fields"), this.formBuilderForm.fieldAliasesIds);

        var self = this;
        _(fieldValues).each(function (fieldValue)
        {
            try
            {
                var fieldView = self._getFieldView(fieldValue.alias);
                if (!fieldView)
                    throw "Failed to find field with alias '" + fieldValue.alias + "'";

                fieldView.setValue(fieldValue.value);
            }
            catch (error)
            {
                console.error(error);
            }
        });
    },
    _applyDataToTableFieldRow: function (tableFieldAlias, fieldValues)
    {
        var form = this.formBuilderForm;
        var tableField = form.fieldModels[form.fieldAliasesIds[tableFieldAlias]];
        this._parseDateFieldValues(fieldValues, tableField.get("fields"), form.fieldAliasesIds);

        var tableFieldView = this._getFieldView(tableFieldAlias);
        tableFieldView.addRow(fieldValues);
        tableFieldView.cancelCurrentRowEditIfExists();
    },
    _parseDateFieldValues: function (fieldValues, fields, fieldAliasesIds)
    {
        _(fieldValues).each(function (externalFieldValue)
        {
            var field = fields.get(fieldAliasesIds[externalFieldValue.alias]);
            if (field && field.isDate())
                externalFieldValue.value = new Date(externalFieldValue.value);
        });
    },
    _getFieldView: function (alias)
    {
        return this.formBuilderForm.fieldViews[this.formBuilderForm.fieldAliasesIds[alias]];
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.EmailFieldView = awardsCommon.widgets.formBuilderForm.SingleInputFieldView.extend(
{
    validateValue: function (value)
    {
        var result = this.constructor.__super__.validateValue.call(this, value);
        if (result.error)
            return result;

        if (!value)
            return {};

        if (!isEmail(value))
            return { value: value, error: new Error("'value' must be an email") };

        return {};
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.UrlFieldView = awardsCommon.widgets.formBuilderForm.SingleInputFieldView.extend(
{
    validateValue: function (value)
    {
        var result = this.constructor.__super__.validateValue.call(this, value);
        if (result.error)
            return result;

        if (!value)
            return {};

        if (!value.match(appConfig.regexLib.url))
            return { value: value, error: new Error("'value' must be a uri") };

        return {};
    }
});;namespace("awardsCommon.widgets.formBuilderForm");
awardsCommon.widgets.formBuilderForm.PhoneNumberFieldView = awardsCommon.widgets.formBuilderForm.SingleInputFieldView.extend(
{
    events: 
    {
        "input .phoneNumberInput": "onPhoneNumberInputChange",
        "change .phoneNumberInput": "onPhoneNumberInputChange",
    },

    initialize: function (options)
    {
        _.extend(this, options);
        this.lastCorrectNumberType = intlTelInputUtils.numberType.MOBILE;
    },
    render: function ()
    {
        var field = this.field;
        var value = field.get("value");

        if (field.readOnly)
        {
            if (value)
                this.$(".formValue").text(value.formatPhoneNumber());

            return this;
        }

        var initialCountry = "us";
        if (this.initialCountryCode)
        {
            var initialCountryCode = this.initialCountryCode.toLowerCase();
            if (_(intlTelInputGlobals.getCountryData()).any(function (c) { return c.iso2 == initialCountryCode; }))
                initialCountry = initialCountryCode;
        }

        var $phoneNumberInput = this.$phoneNumberInput = this.$(".phoneNumberInput").intlTelInput(
        {
            dropdownContainer: document.body,
            initialCountry:  initialCountry,
            preferredCountries: ["au", "ca", "fr", "it", "es", "gb", "us"]
        });

        if (value)
            $phoneNumberInput.intlTelInput("setNumber", value);

        var self = this;
        $phoneNumberInput.on("countrychange", function ()
        {
            self._syncHiddenInput();
            var currentNumber = $phoneNumberInput.inputmask("unmaskedvalue");
            self._setInputMask();

            // After "countrychange" event "intl-tel-input" lib sets focus on input.
            // "focusin" event is also handled by "inputmask" lib. Inside callback it uses "setTimeout(func, 0)" trick for some reason,
            // which restores mask for previous country. Didn't find any correct fix except this workaround.
            setTimeout(function ()
            {
                $phoneNumberInput.inputmask("setvalue", currentNumber);
            }, 0);
        });

        self._setInputMask();

        return this;
    },

    onPhoneNumberInputChange: function ()
    {
        this._syncHiddenInput();
        this._setInputMask();
    },

    isValid: function ()
    {
        if (this.$phoneNumberInput.inputmask("isComplete"))
            return true;

        var customCountriesPhoneNumberDigitCounts =
        {
            "it": 9,
            "de": 9,
            "at": 10,
            "nz": 8,
            "in": 10,
            "hr": 9,
            "id": 10,
        };

        var customPhoneNumberDigitCount = customCountriesPhoneNumberDigitCounts[this.getSelectedCountryCode()];
        if (!_.isUndefined(customPhoneNumberDigitCount))
            return this.$phoneNumberInput.val().match(/\d/g).length >= customPhoneNumberDigitCount;

        return false;
    },
    addValidationContainer: function ()
    {
        this.$(".phoneNumberInputContainer").addErrorContainerIfNotExists(this.$phoneNumberInput.attr("name"));
    },
    getComponent: function ()
    {
        return this.$phoneNumberInput;
    },
    getSelectedCountryCode: function ()
    {
        return this.$phoneNumberInput.intlTelInput("getSelectedCountryData").iso2;
    },
    setCountryCode: function (countryCode)
    {
        if (_.isNullOrUndefined(countryCode))
            throw new Error("Country code is not provided.");

        this.$phoneNumberInput.intlTelInput("setCountry", countryCode);
    },
    
    _setInputMask: function ()
    {
        var countryCode = this.getSelectedCountryCode();
        var numberType = intlTelInputUtils.getNumberType(this._getNumber(), countryCode);

        if (numberType != intlTelInputUtils.numberType.FIXED_LINE && numberType != intlTelInputUtils.numberType.MOBILE)
            numberType = this.lastCorrectNumberType;
        else
            this.lastCorrectNumberType = numberType;

        var customMasks =
        {
            "de": "99999 999999",
            "nz": "99999 9999",
            "id": "999-9999-9999",
        };

        var mask = customMasks[countryCode];
        if (_.isUndefined(mask))
            mask = intlTelInputUtils.getExampleNumber(countryCode, true, numberType).replace(/\d/g, "9");

        this.$phoneNumberInput.inputmask({ mask: mask });
    },
    _syncHiddenInput: function ()
    {
        this.$("[data-value]").val(this._getNumber());
    },
    _getNumber: function ()
    {
        return this.$phoneNumberInput.intlTelInput("getNumber");
    }
});;/*! http://keith-wood.name/signature.html
	Signature plugin for jQuery UI v1.2.0.
	Requires excanvas.js in IE.
	Written by Keith Wood (wood.keith{at}optusnet.com.au) April 2012.
	Available under the MIT (http://keith-wood.name/licence.html) license. 
	Please attribute the author if you use it. */

/* globals G_vmlCanvasManager */

(function($) { // Hide scope, no $ conflict
	'use strict';

	/** Signature capture and display.
		<p>Depends on <code>jquery.ui.widget</code>, <code>jquery.ui.mouse</code>.</p>
		<p>Expects HTML like:</p>
		<pre>&lt;div>&lt;/div></pre>
		@namespace Signature
		@augments $.Widget
		@example $(selector).signature()
$(selector).signature({color: 'blue', guideline: true}) */
	var signatureOverrides = {

		/** Be notified when a signature changes.
			@callback SignatureChange
			@global
			@this Signature
			@example change: function() {
  console.log('Signature changed');
} */

		/** Global defaults for signature.
			@memberof Signature
			@property {number} [distance=0] The minimum distance to start a drag.
			@property {string} [background='#fff'] The background colour.
			@property {string} [color='#000'] The colour of the signature.
			@property {number} [thickness=2] The thickness of the lines.
			@property {boolean} [guideline=false] <code>true</code> to add a guideline.
			@property {string} [guidelineColor='#a0a0a0'] The guideline colour.
			@property {number} [guidelineOffset=50] The guideline offset (pixels) from the bottom.
			@property {number} [guidelineIndex=10] The guideline indent (pixels) from the edges.
			@property {string} [notAvailable='Your browser doesn\'t support signing']
								The error message to show when no canvas is available.
			@property {string|Element|jQuery} [syncField=null] The selector, DOM element, or jQuery object
								for a field to automatically synchronise with a text version of the signature.
			@property {string} [syncFormat='JSON'] The output representation: 'JSON', 'SVG', 'PNG', 'JPEG'.
			@property {boolean} [svgStyles=false] <code>true</code> to use the <code>style</code> attribute in SVG.
			@property {SignatureChange} [change=null] A callback triggered when the signature changes.
			@example $.extend($.kbw.signature.options, {guideline: true}) */
		options: {
			distance: 0,
			background: '#fff',
			color: '#000',
			thickness: 2,
			guideline: false,
			guidelineColor: '#a0a0a0',
			guidelineOffset: 50,
			guidelineIndent: 10,
			notAvailable: 'Your browser doesn\'t support signing',
			syncField: null,
			syncFormat: 'JSON',
			svgStyles: false,
			change: null
		},

		/** Initialise a new signature area.
			@memberof Signature
			@private */
		_create: function() {
			this.element.addClass(this.widgetFullName || this.widgetBaseClass);
			try {
				this.canvas = $('<canvas width="' + this.element.width() + '" height="' +
					this.element.height() + '">' + this.options.notAvailable + '</canvas>')[0];
				this.element.append(this.canvas);
			}
			catch (e) {
				$(this.canvas).remove();
				this.resize = true;
				this.canvas = document.createElement('canvas');
				this.canvas.setAttribute('width', this.element.width());
				this.canvas.setAttribute('height', this.element.height());
				this.canvas.innerHTML = this.options.notAvailable;
				this.element.append(this.canvas);
				/* jshint -W106 */
				if (G_vmlCanvasManager) { // Requires excanvas.js
					G_vmlCanvasManager.initElement(this.canvas);
				}
				/* jshint +W106 */
			}
			this.ctx = this.canvas.getContext('2d');
			this._refresh(true);
			this._mouseInit();
		},

		/** Refresh the appearance of the signature area.
			@memberof Signature
			@private
			@param {boolean} init <code>true</code> if initialising. */
		_refresh: function(init) {
			if (this.resize) {
				var parent = $(this.canvas);
				$('div', this.canvas).css({width: parent.width(), height: parent.height()});
			}
			this.ctx.fillStyle = this.options.background;
			this.ctx.strokeStyle = this.options.color;
			this.ctx.lineWidth = this.options.thickness;
			this.ctx.lineCap = 'round';
			this.ctx.lineJoin = 'round';
			this.clear(init);
		},

		/** Clear the signature area.
			@memberof Signature
			@param {boolean} init <code>true</code> if initialising - internal use only.
			@example $(selector).signature('clear') */
		clear: function(init) {
			if (this.options.disabled) {
				return;
			}
			this.ctx.fillRect(0, 0, this.element.width(), this.element.height());
			if (this.options.guideline) {
				this.ctx.save();
				this.ctx.strokeStyle = this.options.guidelineColor;
				this.ctx.lineWidth = 1;
				this.ctx.beginPath();
				this.ctx.moveTo(this.options.guidelineIndent,
					this.element.height() - this.options.guidelineOffset);
				this.ctx.lineTo(this.element.width() - this.options.guidelineIndent,
					this.element.height() - this.options.guidelineOffset);
				this.ctx.stroke();
				this.ctx.restore();
			}
			this.lines = [];
			if (!init) {
				this._changed();
			}
		},

		/** Synchronise changes and trigger a change event.
			@memberof Signature
			@private
			@param {Event} event The triggering event. */
		_changed: function(event) {
			if (this.options.syncField) {
				var output = '';
				switch (this.options.syncFormat) {
					case 'PNG':
						output = this.toDataURL();
						break;
					case 'JPEG':
						output = this.toDataURL('image/jpeg');
						break;
					case 'SVG':
						output = this.toSVG();
						break;
					default:
						output = this.toJSON();
				}
				$(this.options.syncField).val(output);
			}
			this._trigger('change', event, {});
		},

		/** Refresh the signature when options change.
			@memberof Signature
			@private
			@param {object} options The new option values. */
		_setOptions: function(/* options */) {
			if (this._superApply) {
				this._superApply(arguments); // Base widget handling
			}
			else {
				$.Widget.prototype._setOptions.apply(this, arguments); // Base widget handling
			}
			var count = 0;
			var onlyDisable = true;
			for (var name in arguments[0]) {
				if (arguments[0].hasOwnProperty(name)) {
					count++;
					onlyDisable = onlyDisable && name === 'disabled';
				}
			}
			if (count > 1 || !onlyDisable) {
				this._refresh();
			}
		},

		/** Determine if dragging can start.
			@memberof Signature
			@private
			@param {Event} event The triggering mouse event.
			@return {boolean} <code>true</code> if allowed, <code>false</code> if not */
		_mouseCapture: function(/* event */) {
			return !this.options.disabled;
		},

		/** Start a new line.
			@memberof Signature
			@private
			@param {Event} event The triggering mouse event. */
		_mouseStart: function(event) {
			this.offset = this.element.offset();
			this.offset.left -= document.documentElement.scrollLeft || document.body.scrollLeft;
			this.offset.top -= document.documentElement.scrollTop || document.body.scrollTop;
			this.lastPoint = [this._round(event.clientX - this.offset.left),
				this._round(event.clientY - this.offset.top)];
			this.curLine = [this.lastPoint];
			this.lines.push(this.curLine);
		},

		/** Track the mouse.
			@memberof Signature
			@private
			@param {Event} event The triggering mouse event. */
		_mouseDrag: function(event) {
			var point = [this._round(event.clientX - this.offset.left),
				this._round(event.clientY - this.offset.top)];
			this.curLine.push(point);
			this.ctx.beginPath();
			this.ctx.moveTo(this.lastPoint[0], this.lastPoint[1]);
			this.ctx.lineTo(point[0], point[1]);
			this.ctx.stroke();
			this.lastPoint = point;
		},

		/** End a line.
			@memberof Signature
			@private
			@param {Event} event The triggering mouse event. */
		_mouseStop: function(event) {
			if (this.curLine.length === 1) {
				event.clientY += this.options.thickness;
				this._mouseDrag(event);
			}
			this.lastPoint = null;
			this.curLine = null;
			this._changed(event);
		},

		/** Round to two decimal points.
			@memberof Signature
			@private
			@param {number} value The value to round.
			@return {number} The rounded value. */
		_round: function(value) {
			return Math.round(value * 100) / 100;
		},

		/** Convert the captured lines to JSON text.
			@memberof Signature
			@return {string} The JSON text version of the lines.
			@example var json = $(selector).signature('toJSON') */
		toJSON: function() {
			return '{"lines":[' + $.map(this.lines, function(line) {
				return '[' + $.map(line, function(point) {
						return '[' + point + ']';
					}) + ']';
			}) + ']}';
		},

		/** Convert the captured lines to SVG text.
			@memberof Signature
			@return {string} The SVG text version of the lines.
			@example var svg = $(selector).signature('toSVG') */
		toSVG: function() {
			var attrs1 = (this.options.svgStyles ? 'style="fill: ' + this.options.background + ';"' :
				'fill="' + this.options.background + '"');
			var attrs2 = (this.options.svgStyles ?
				'style="fill: none; stroke: ' + this.options.color + '; stroke-width: ' + this.options.thickness + ';"' :
				'fill="none" stroke="' + this.options.color + '" stroke-width="' + this.options.thickness + '"');
			return '<?xml version="1.0"?>\n<!DOCTYPE svg PUBLIC ' +
				'"-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' +
				'<svg xmlns="http://www.w3.org/2000/svg" width="' + this.canvas.width + 'px" height="' + this.canvas.height + 'px">\n' +
				'	<g ' + attrs1 + '>\n' +
				'		<rect preserveAspectRatio="xMidYMid meet" viewBox = "0 0 ' + this.canvas.width + ' ' + this.canvas.height + '" x="0" y="0" width="' + this.canvas.width + '" height="' + this.canvas.height + '"/>\n' +
				'		<g ' + attrs2 +	'>\n'+
				$.map(this.lines, function(line) {
					return '			<polyline points="' +
						$.map(line, function(point) { return point + ''; }).join(' ') + '"/>\n';
				}).join('') +
				'		</g>\n	</g>\n</svg>\n';
		},
		
		/** Convert the captured lines to an image encoded in a <code>data:</code> URL.
			@memberof Signature
			@param {string} [type='image/png'] The MIME type of the image.
			@param {number} [quality=0.92] The image quality, between 0 and 1.
			@return {string} The signature as a data: URL image.
			@example var data = $(selector).signature('toDataURL', 'image/jpeg') */
		toDataURL: function(type, quality) {
			return this.canvas.toDataURL(type, quality);
		},

		/** Draw a signature from its JSON or SVG description or <code>data:</code> URL.
			<p>Note that drawing a <code>data:</code> URL does not reconstruct the internal representation!</p>
			@memberof Signature
			@param {object|string} sig An object with attribute <code>lines</code> being an array of arrays of points
							or the text version of the JSON or SVG or a <code>data:</code> URL containing an image.
			@example $(selector).signature('draw', sigAsJSON) */
		draw: function(sig) {
			if (this.options.disabled) {
				return;
			}
			this.clear(true);
			if (typeof sig === 'string' && sig.indexOf('data:') === 0) { // Data URL
				this._drawDataURL(sig);
			} else if (typeof sig === 'string' && sig.indexOf('<svg') > -1) { // SVG
				this._drawSVG(sig);
			} else {
				this._drawJSON(sig);
			}
			this._changed();
		},

		/** Draw a signature from its JSON description.
			@memberof Signature
			@private
			@param {object|string} sig An object with attribute <code>lines</code> being an array of arrays of points
							or the text version of the JSON. */
		_drawJSON: function(sig) {
			if (typeof sig === 'string') {
				sig = $.parseJSON(sig);
			}
			this.lines = sig.lines || [];
			var ctx = this.ctx;
			$.each(this.lines, function() {
				ctx.beginPath();
				$.each(this, function(i) {
					ctx[i === 0 ? 'moveTo' : 'lineTo'](this[0], this[1]);
				});
				ctx.stroke();
			});
		},

		/** Draw a signature from its SVG description.
			@memberof Signature
			@private
			@param {string} sig The text version of the SVG. */
		_drawSVG: function(sig) {
			var lines = this.lines = [];
			$(sig).find('polyline').each(function() {
				var line = [];
				$.each($(this).attr('points').split(' '), function(i, point) {
					var xy = point.split(',');
					line.push([parseFloat(xy[0]), parseFloat(xy[1])]);
				});
				lines.push(line);
			});
			var ctx = this.ctx;
			$.each(this.lines, function() {
				ctx.beginPath();
				$.each(this, function(i) {
					ctx[i === 0 ? 'moveTo' : 'lineTo'](this[0], this[1]);
				});
				ctx.stroke();
			});
		},

		/** Draw a signature from its <code>data:</code> URL.
			<p>Note that this does not reconstruct the internal representation!</p>
			@memberof Signature
			@private
			@param {string} sig The <code>data:</code> URL containing an image. */
		_drawDataURL: function(sig) {
			var image = new Image();
			var context = this.ctx;
			image.onload = function() {
				context.drawImage(this, 0, 0);
			};
			image.src = sig;
		},

		/** Determine whether or not any drawing has occurred.
			@memberof Signature
			@return {boolean} <code>true</code> if not signed, <code>false</code> if signed.
			@example if ($(selector).signature('isEmpty')) ... */
		isEmpty: function() {
			return this.lines.length === 0;
		},

		/** Remove the signature functionality.
			@memberof Signature
			@private */
		_destroy: function() {
			this.element.removeClass(this.widgetFullName || this.widgetBaseClass);
			$(this.canvas).remove();
			this.canvas = this.ctx = this.lines = null;
			this._mouseDestroy();
		}
	};

	if (!$.Widget.prototype._destroy) {
		$.extend(signatureOverrides, {
			/* Remove the signature functionality. */
			destroy: function() {
				this._destroy();
				$.Widget.prototype.destroy.call(this); // Base widget handling
			}
		});
	}

	if ($.Widget.prototype._getCreateOptions === $.noop) {
		$.extend(signatureOverrides, {
			/* Restore the metadata functionality. */
			_getCreateOptions: function() {
				return $.metadata && $.metadata.get(this.element[0])[this.widgetName];
			}
		});
	}

	$.widget('kbw.signature', $.ui.mouse, signatureOverrides);

	// Make some things more accessible
	$.kbw.signature.options = $.kbw.signature.prototype.options;

})(jQuery);
;/*!
 * jQuery UI Touch Punch 0.2.3
 *
 * Copyright 2011–2014, Dave Furfero
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * Depends:
 *  jquery.ui.widget.js
 *  jquery.ui.mouse.js
 */
!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);;/**
*  Ajax Autocomplete for jQuery, version 1.4.10
*  (c) 2017 Tomas Kirda
*
*  Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
*  For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
*/

/*jslint  browser: true, white: true, single: true, this: true, multivar: true */
/*global define, window, document, jQuery, exports, require */

// Expose plugin as an AMD module if AMD loader is present:
(function (factory) {
    "use strict";
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof exports === 'object' && typeof require === 'function') {
        // Browserify
        factory(require('jquery'));
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($) {
    'use strict';

    var
        utils = (function () {
            return {
                escapeRegExChars: function (value) {
                    return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
                },
                createNode: function (containerClass) {
                    var div = document.createElement('div');
                    div.className = containerClass;
                    div.style.position = 'absolute';
                    div.style.display = 'none';
                    return div;
                }
            };
        }()),

        keys = {
            ESC: 27,
            TAB: 9,
            RETURN: 13,
            LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40
        },

        noop = $.noop;

    function Autocomplete(el, options) {
        var that = this;

        // Shared variables:
        that.element = el;
        that.el = $(el);
        that.suggestions = [];
        that.badQueries = [];
        that.selectedIndex = -1;
        that.currentValue = that.element.value;
        that.timeoutId = null;
        that.cachedResponse = {};
        that.onChangeTimeout = null;
        that.onChange = null;
        that.isLocal = false;
        that.suggestionsContainer = null;
        that.noSuggestionsContainer = null;
        that.options = $.extend(true, {}, Autocomplete.defaults, options);
        that.classes = {
            selected: 'autocomplete-selected',
            suggestion: 'autocomplete-suggestion'
        };
        that.hint = null;
        that.hintValue = '';
        that.selection = null;

        // Initialize and set options:
        that.initialize();
        that.setOptions(options);
    }

    Autocomplete.utils = utils;

    $.Autocomplete = Autocomplete;

    Autocomplete.defaults = {
            ajaxSettings: {},
            autoSelectFirst: false,
            appendTo: 'body',
            serviceUrl: null,
            lookup: null,
            onSelect: null,
            width: 'auto',
            minChars: 1,
            maxHeight: 300,
            deferRequestBy: 0,
            params: {},
            formatResult: _formatResult,
            formatGroup: _formatGroup,
            delimiter: null,
            zIndex: 9999,
            type: 'GET',
            noCache: false,
            onSearchStart: noop,
            onSearchComplete: noop,
            onSearchError: noop,
            preserveInput: false,
            containerClass: 'autocomplete-suggestions',
            tabDisabled: false,
            dataType: 'text',
            currentRequest: null,
            triggerSelectOnValidInput: true,
            preventBadQueries: true,
            lookupFilter: _lookupFilter,
            paramName: 'query',
            transformResult: _transformResult,
            showNoSuggestionNotice: false,
            noSuggestionNotice: 'No results',
            orientation: 'bottom',
            forceFixPosition: false
    };

    function _lookupFilter(suggestion, originalQuery, queryLowerCase) {
        return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1;
    };

    function _transformResult(response) {
        return typeof response === 'string' ? $.parseJSON(response) : response;
    };

    function _formatResult(suggestion, currentValue) {
        // Do not replace anything if the current value is empty
        if (!currentValue) {
            return suggestion.value;
        }

        var pattern = '(' + utils.escapeRegExChars(currentValue) + ')';

        return suggestion.value
            .replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>')
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/&lt;(\/?strong)&gt;/g, '<$1>');
    };

    function _formatGroup(suggestion, category) {
        return '<div class="autocomplete-group">' + category + '</div>';
    };

    Autocomplete.prototype = {

        initialize: function () {
            var that = this,
                suggestionSelector = '.' + that.classes.suggestion,
                selected = that.classes.selected,
                options = that.options,
                container;

            that.element.setAttribute('autocomplete', 'off');

            // html() deals with many types: htmlString or Element or Array or jQuery
            that.noSuggestionsContainer = $('<div class="autocomplete-no-suggestion"></div>')
                                          .html(this.options.noSuggestionNotice).get(0);

            that.suggestionsContainer = Autocomplete.utils.createNode(options.containerClass);

            container = $(that.suggestionsContainer);

            container.appendTo(options.appendTo || 'body');

            // Only set width if it was provided:
            if (options.width !== 'auto') {
                container.css('width', options.width);
            }

            // Listen for mouse over event on suggestions list:
            container.on('mouseover.autocomplete', suggestionSelector, function () {
                that.activate($(this).data('index'));
            });

            // Deselect active element when mouse leaves suggestions container:
            container.on('mouseout.autocomplete', function () {
                that.selectedIndex = -1;
                container.children('.' + selected).removeClass(selected);
            });

            // Listen for click event on suggestions list:
            container.on('click.autocomplete', suggestionSelector, function () {
                that.select($(this).data('index'));
            });

            container.on('click.autocomplete', function () {
                clearTimeout(that.blurTimeoutId);
            })

            that.fixPositionCapture = function () {
                if (that.visible) {
                    that.fixPosition();
                }
            };

            $(window).on('resize.autocomplete', that.fixPositionCapture);

            that.el.on('keydown.autocomplete', function (e) { that.onKeyPress(e); });
            that.el.on('keyup.autocomplete', function (e) { that.onKeyUp(e); });
            that.el.on('blur.autocomplete', function () { that.onBlur(); });
            that.el.on('focus.autocomplete', function () { that.onFocus(); });
            that.el.on('change.autocomplete', function (e) { that.onKeyUp(e); });
            that.el.on('input.autocomplete', function (e) { that.onKeyUp(e); });
        },

        onFocus: function () {
            var that = this;

            that.fixPosition();

            if (that.el.val().length >= that.options.minChars) {
                that.onValueChange();
            }
        },

        onBlur: function () {
            var that = this,
                options = that.options,
                value = that.el.val(),
                query = that.getQuery(value);

            // If user clicked on a suggestion, hide() will
            // be canceled, otherwise close suggestions
            that.blurTimeoutId = setTimeout(function () {
                that.hide();

                if (that.selection && that.currentValue !== query) {
                    (options.onInvalidateSelection || $.noop).call(that.element);
                }
            }, 200);
        },

        abortAjax: function () {
            var that = this;
            if (that.currentRequest) {
                that.currentRequest.abort();
                that.currentRequest = null;
            }
        },

        setOptions: function (suppliedOptions) {
            var that = this,
                options = $.extend({}, that.options, suppliedOptions);

            that.isLocal = Array.isArray(options.lookup);

            if (that.isLocal) {
                options.lookup = that.verifySuggestionsFormat(options.lookup);
            }

            options.orientation = that.validateOrientation(options.orientation, 'bottom');

            // Adjust height, width and z-index:
            $(that.suggestionsContainer).css({
                'max-height': options.maxHeight + 'px',
                'width': options.width + 'px',
                'z-index': options.zIndex
            });

            this.options = options;            
        },


        clearCache: function () {
            this.cachedResponse = {};
            this.badQueries = [];
        },

        clear: function () {
            this.clearCache();
            this.currentValue = '';
            this.suggestions = [];
        },

        disable: function () {
            var that = this;
            that.disabled = true;
            clearTimeout(that.onChangeTimeout);
            that.abortAjax();
        },

        enable: function () {
            this.disabled = false;
        },

        fixPosition: function () {
            // Use only when container has already its content

            var that = this,
                $container = $(that.suggestionsContainer),
                containerParent = $container.parent().get(0);
            // Fix position automatically when appended to body.
            // In other cases force parameter must be given.
            if (containerParent !== document.body && !that.options.forceFixPosition) {
                return;
            }

            // Choose orientation
            var orientation = that.options.orientation,
                containerHeight = $container.outerHeight(),
                height = that.el.outerHeight(),
                offset = that.el.offset(),
                styles = { 'top': offset.top, 'left': offset.left };

            if (orientation === 'auto') {
                var viewPortHeight = $(window).height(),
                    scrollTop = $(window).scrollTop(),
                    topOverflow = -scrollTop + offset.top - containerHeight,
                    bottomOverflow = scrollTop + viewPortHeight - (offset.top + height + containerHeight);

                orientation = (Math.max(topOverflow, bottomOverflow) === topOverflow) ? 'top' : 'bottom';
            }

            if (orientation === 'top') {
                styles.top += -containerHeight;
            } else {
                styles.top += height;
            }

            // If container is not positioned to body,
            // correct its position using offset parent offset
            if(containerParent !== document.body) {
                var opacity = $container.css('opacity'),
                    parentOffsetDiff;

                    if (!that.visible){
                        $container.css('opacity', 0).show();
                    }

                parentOffsetDiff = $container.offsetParent().offset();
                styles.top -= parentOffsetDiff.top;
                styles.top += containerParent.scrollTop;
                styles.left -= parentOffsetDiff.left;

                if (!that.visible){
                    $container.css('opacity', opacity).hide();
                }
            }

            if (that.options.width === 'auto') {
                styles.width = that.el.outerWidth() + 'px';
            }

            $container.css(styles);
        },

        isCursorAtEnd: function () {
            var that = this,
                valLength = that.el.val().length,
                selectionStart = that.element.selectionStart,
                range;

            if (typeof selectionStart === 'number') {
                return selectionStart === valLength;
            }
            if (document.selection) {
                range = document.selection.createRange();
                range.moveStart('character', -valLength);
                return valLength === range.text.length;
            }
            return true;
        },

        onKeyPress: function (e) {
            var that = this;

            // If suggestions are hidden and user presses arrow down, display suggestions:
            if (!that.disabled && !that.visible && e.which === keys.DOWN && that.currentValue) {
                that.suggest();
                return;
            }

            if (that.disabled || !that.visible) {
                return;
            }

            switch (e.which) {
                case keys.ESC:
                    that.el.val(that.currentValue);
                    that.hide();
                    break;
                case keys.RIGHT:
                    if (that.hint && that.options.onHint && that.isCursorAtEnd()) {
                        that.selectHint();
                        break;
                    }
                    return;
                case keys.TAB:
                    if (that.hint && that.options.onHint) {
                        that.selectHint();
                        return;
                    }
                    if (that.selectedIndex === -1) {
                        that.hide();
                        return;
                    }
                    that.select(that.selectedIndex);
                    if (that.options.tabDisabled === false) {
                        return;
                    }
                    break;
                case keys.RETURN:
                    if (that.selectedIndex === -1) {
                        that.hide();
                        return;
                    }
                    that.select(that.selectedIndex);
                    break;
                case keys.UP:
                    that.moveUp();
                    break;
                case keys.DOWN:
                    that.moveDown();
                    break;
                default:
                    return;
            }

            // Cancel event if function did not return:
            e.stopImmediatePropagation();
            e.preventDefault();
        },

        onKeyUp: function (e) {
            var that = this;

            if (that.disabled) {
                return;
            }

            switch (e.which) {
                case keys.UP:
                case keys.DOWN:
                    return;
            }

            clearTimeout(that.onChangeTimeout);

            if (that.currentValue !== that.el.val()) {
                that.findBestHint();
                if (that.options.deferRequestBy > 0) {
                    // Defer lookup in case when value changes very quickly:
                    that.onChangeTimeout = setTimeout(function () {
                        that.onValueChange();
                    }, that.options.deferRequestBy);
                } else {
                    that.onValueChange();
                }
            }
        },

        onValueChange: function () {
            if (this.ignoreValueChange) {
                this.ignoreValueChange = false;
                return;
            }

            var that = this,
                options = that.options,
                value = that.el.val(),
                query = that.getQuery(value);

            if (that.selection && that.currentValue !== query) {
                that.selection = null;
                (options.onInvalidateSelection || $.noop).call(that.element);
            }

            clearTimeout(that.onChangeTimeout);
            that.currentValue = value;
            that.selectedIndex = -1;

            // Check existing suggestion for the match before proceeding:
            if (options.triggerSelectOnValidInput && that.isExactMatch(query)) {
                that.select(0);
                return;
            }

            if (query.length < options.minChars) {
                that.hide();
            } else {
                that.getSuggestions(query);
            }
        },

        isExactMatch: function (query) {
            var suggestions = this.suggestions;

            return (suggestions.length === 1 && suggestions[0].value.toLowerCase() === query.toLowerCase());
        },

        getQuery: function (value) {
            var delimiter = this.options.delimiter,
                parts;

            if (!delimiter) {
                return value;
            }
            parts = value.split(delimiter);
            return $.trim(parts[parts.length - 1]);
        },

        getSuggestionsLocal: function (query) {
            var that = this,
                options = that.options,
                queryLowerCase = query.toLowerCase(),
                filter = options.lookupFilter,
                limit = parseInt(options.lookupLimit, 10),
                data;

            data = {
                suggestions: $.grep(options.lookup, function (suggestion) {
                    return filter(suggestion, query, queryLowerCase);
                })
            };

            if (limit && data.suggestions.length > limit) {
                data.suggestions = data.suggestions.slice(0, limit);
            }

            return data;
        },

        getSuggestions: function (q) {
            var response,
                that = this,
                options = that.options,
                serviceUrl = options.serviceUrl,
                params,
                cacheKey,
                ajaxSettings;

            options.params[options.paramName] = q;

            if (options.onSearchStart.call(that.element, options.params) === false) {
                return;
            }

            params = options.ignoreParams ? null : options.params;

            if ($.isFunction(options.lookup)){
                options.lookup(q, function (data) {
                    that.suggestions = data.suggestions;
                    that.suggest();
                    options.onSearchComplete.call(that.element, q, data.suggestions);
                });
                return;
            }

            if (that.isLocal) {
                response = that.getSuggestionsLocal(q);
            } else {
                if ($.isFunction(serviceUrl)) {
                    serviceUrl = serviceUrl.call(that.element, q);
                }
                cacheKey = serviceUrl + '?' + $.param(params || {});
                response = that.cachedResponse[cacheKey];
            }

            if (response && Array.isArray(response.suggestions)) {
                that.suggestions = response.suggestions;
                that.suggest();
                options.onSearchComplete.call(that.element, q, response.suggestions);
            } else if (!that.isBadQuery(q)) {
                that.abortAjax();

                ajaxSettings = {
                    url: serviceUrl,
                    data: params,
                    type: options.type,
                    dataType: options.dataType
                };

                $.extend(ajaxSettings, options.ajaxSettings);

                that.currentRequest = $.ajax(ajaxSettings).done(function (data) {
                    var result;
                    that.currentRequest = null;
                    result = options.transformResult(data, q);
                    that.processResponse(result, q, cacheKey);
                    options.onSearchComplete.call(that.element, q, result.suggestions);
                }).fail(function (jqXHR, textStatus, errorThrown) {
                    options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown);
                });
            } else {
                options.onSearchComplete.call(that.element, q, []);
            }
        },

        isBadQuery: function (q) {
            if (!this.options.preventBadQueries){
                return false;
            }

            var badQueries = this.badQueries,
                i = badQueries.length;

            while (i--) {
                if (q.indexOf(badQueries[i]) === 0) {
                    return true;
                }
            }

            return false;
        },

        hide: function () {
            var that = this,
                container = $(that.suggestionsContainer);

            if ($.isFunction(that.options.onHide) && that.visible) {
                that.options.onHide.call(that.element, container);
            }

            that.visible = false;
            that.selectedIndex = -1;
            clearTimeout(that.onChangeTimeout);
            $(that.suggestionsContainer).hide();
            that.signalHint(null);
        },

        suggest: function () {
            if (!this.suggestions.length) {
                if (this.options.showNoSuggestionNotice) {
                    this.noSuggestions();
                } else {
                    this.hide();
                }
                return;
            }

            var that = this,
                options = that.options,
                groupBy = options.groupBy,
                formatResult = options.formatResult,
                value = that.getQuery(that.currentValue),
                className = that.classes.suggestion,
                classSelected = that.classes.selected,
                container = $(that.suggestionsContainer),
                noSuggestionsContainer = $(that.noSuggestionsContainer),
                beforeRender = options.beforeRender,
                html = '',
                category,
                formatGroup = function (suggestion, index) {
                        var currentCategory = suggestion.data[groupBy];

                        if (category === currentCategory){
                            return '';
                        }

                        category = currentCategory;

                        return options.formatGroup(suggestion, category);
                    };

            if (options.triggerSelectOnValidInput && that.isExactMatch(value)) {
                that.select(0);
                return;
            }

            // Build suggestions inner HTML:
            $.each(that.suggestions, function (i, suggestion) {
                if (groupBy){
                    html += formatGroup(suggestion, value, i);
                }

                html += '<div class="' + className + '" data-index="' + i + '">' + formatResult(suggestion, value, i) + '</div>';
            });

            this.adjustContainerWidth();

            noSuggestionsContainer.detach();
            container.html(html);

            if ($.isFunction(beforeRender)) {
                beforeRender.call(that.element, container, that.suggestions);
            }

            that.fixPosition();
            container.show();

            // Select first value by default:
            if (options.autoSelectFirst) {
                that.selectedIndex = 0;
                container.scrollTop(0);
                container.children('.' + className).first().addClass(classSelected);
            }

            that.visible = true;
            that.findBestHint();
        },

        noSuggestions: function() {
             var that = this,
                 beforeRender = that.options.beforeRender,
                 container = $(that.suggestionsContainer),
                 noSuggestionsContainer = $(that.noSuggestionsContainer);

            this.adjustContainerWidth();

            // Some explicit steps. Be careful here as it easy to get
            // noSuggestionsContainer removed from DOM if not detached properly.
            noSuggestionsContainer.detach();

            // clean suggestions if any
            container.empty();
            container.append(noSuggestionsContainer);

            if ($.isFunction(beforeRender)) {
                beforeRender.call(that.element, container, that.suggestions);
            }

            that.fixPosition();

            container.show();
            that.visible = true;
        },

        adjustContainerWidth: function() {
            var that = this,
                options = that.options,
                width,
                container = $(that.suggestionsContainer);

            // If width is auto, adjust width before displaying suggestions,
            // because if instance was created before input had width, it will be zero.
            // Also it adjusts if input width has changed.
            if (options.width === 'auto') {
                width = that.el.outerWidth();
                container.css('width', width > 0 ? width : 300);
            } else if(options.width === 'flex') {
                // Trust the source! Unset the width property so it will be the max length
                // the containing elements.
                container.css('width', '');
            }
        },

        findBestHint: function () {
            var that = this,
                value = that.el.val().toLowerCase(),
                bestMatch = null;

            if (!value) {
                return;
            }

            $.each(that.suggestions, function (i, suggestion) {
                var foundMatch = suggestion.value.toLowerCase().indexOf(value) === 0;
                if (foundMatch) {
                    bestMatch = suggestion;
                }
                return !foundMatch;
            });

            that.signalHint(bestMatch);
        },

        signalHint: function (suggestion) {
            var hintValue = '',
                that = this;
            if (suggestion) {
                hintValue = that.currentValue + suggestion.value.substr(that.currentValue.length);
            }
            if (that.hintValue !== hintValue) {
                that.hintValue = hintValue;
                that.hint = suggestion;
                (this.options.onHint || $.noop)(hintValue);
            }
        },

        verifySuggestionsFormat: function (suggestions) {
            // If suggestions is string array, convert them to supported format:
            if (suggestions.length && typeof suggestions[0] === 'string') {
                return $.map(suggestions, function (value) {
                    return { value: value, data: null };
                });
            }

            return suggestions;
        },

        validateOrientation: function(orientation, fallback) {
            orientation = $.trim(orientation || '').toLowerCase();

            if($.inArray(orientation, ['auto', 'bottom', 'top']) === -1){
                orientation = fallback;
            }

            return orientation;
        },

        processResponse: function (result, originalQuery, cacheKey) {
            var that = this,
                options = that.options;

            result.suggestions = that.verifySuggestionsFormat(result.suggestions);

            // Cache results if cache is not disabled:
            if (!options.noCache) {
                that.cachedResponse[cacheKey] = result;
                if (options.preventBadQueries && !result.suggestions.length) {
                    that.badQueries.push(originalQuery);
                }
            }

            // Return if originalQuery is not matching current query:
            if (originalQuery !== that.getQuery(that.currentValue)) {
                return;
            }

            that.suggestions = result.suggestions;
            that.suggest();
        },

        activate: function (index) {
            var that = this,
                activeItem,
                selected = that.classes.selected,
                container = $(that.suggestionsContainer),
                children = container.find('.' + that.classes.suggestion);

            container.find('.' + selected).removeClass(selected);

            that.selectedIndex = index;

            if (that.selectedIndex !== -1 && children.length > that.selectedIndex) {
                activeItem = children.get(that.selectedIndex);
                $(activeItem).addClass(selected);
                return activeItem;
            }

            return null;
        },

        selectHint: function () {
            var that = this,
                i = $.inArray(that.hint, that.suggestions);

            that.select(i);
        },

        select: function (i) {
            var that = this;
            that.hide();
            that.onSelect(i);
        },

        moveUp: function () {
            var that = this;

            if (that.selectedIndex === -1) {
                return;
            }

            if (that.selectedIndex === 0) {
                $(that.suggestionsContainer).children('.' + that.classes.suggestion).first().removeClass(that.classes.selected);
                that.selectedIndex = -1;
                that.ignoreValueChange = false;
                that.el.val(that.currentValue);
                that.findBestHint();
                return;
            }

            that.adjustScroll(that.selectedIndex - 1);
        },

        moveDown: function () {
            var that = this;

            if (that.selectedIndex === (that.suggestions.length - 1)) {
                return;
            }

            that.adjustScroll(that.selectedIndex + 1);
        },

        adjustScroll: function (index) {
            var that = this,
                activeItem = that.activate(index);

            if (!activeItem) {
                return;
            }

            var offsetTop,
                upperBound,
                lowerBound,
                heightDelta = $(activeItem).outerHeight();

            offsetTop = activeItem.offsetTop;
            upperBound = $(that.suggestionsContainer).scrollTop();
            lowerBound = upperBound + that.options.maxHeight - heightDelta;

            if (offsetTop < upperBound) {
                $(that.suggestionsContainer).scrollTop(offsetTop);
            } else if (offsetTop > lowerBound) {
                $(that.suggestionsContainer).scrollTop(offsetTop - that.options.maxHeight + heightDelta);
            }

            if (!that.options.preserveInput) {
                // During onBlur event, browser will trigger "change" event,
                // because value has changed, to avoid side effect ignore,
                // that event, so that correct suggestion can be selected
                // when clicking on suggestion with a mouse
                that.ignoreValueChange = true;
                that.el.val(that.getValue(that.suggestions[index].value));
            }

            that.signalHint(null);
        },

        onSelect: function (index) {
            var that = this,
                onSelectCallback = that.options.onSelect,
                suggestion = that.suggestions[index];

            that.currentValue = that.getValue(suggestion.value);

            if (that.currentValue !== that.el.val() && !that.options.preserveInput) {
                that.el.val(that.currentValue);
            }

            that.signalHint(null);
            that.suggestions = [];
            that.selection = suggestion;

            if ($.isFunction(onSelectCallback)) {
                onSelectCallback.call(that.element, suggestion);
            }
        },

        getValue: function (value) {
            var that = this,
                delimiter = that.options.delimiter,
                currentValue,
                parts;

            if (!delimiter) {
                return value;
            }

            currentValue = that.currentValue;
            parts = currentValue.split(delimiter);

            if (parts.length === 1) {
                return value;
            }

            return currentValue.substr(0, currentValue.length - parts[parts.length - 1].length) + value;
        },

        dispose: function () {
            var that = this;
            that.el.off('.autocomplete').removeData('autocomplete');
            $(window).off('resize.autocomplete', that.fixPositionCapture);
            $(that.suggestionsContainer).remove();
        }
    };

    // Create chainable jQuery plugin:
    $.fn.devbridgeAutocomplete = function (options, args) {
        var dataKey = 'autocomplete';
        // If function invoked without argument return
        // instance of the first matched element:
        if (!arguments.length) {
            return this.first().data(dataKey);
        }

        return this.each(function () {
            var inputElement = $(this),
                instance = inputElement.data(dataKey);

            if (typeof options === 'string') {
                if (instance && typeof instance[options] === 'function') {
                    instance[options](args);
                }
            } else {
                // If instance already exists, destroy it:
                if (instance && instance.dispose) {
                    instance.dispose();
                }
                instance = new Autocomplete(this, options);
                inputElement.data(dataKey, instance);
            }
        });
    };

    // Don't overwrite if it already exists
    if (!$.fn.autocomplete) {
        $.fn.autocomplete = $.fn.devbridgeAutocomplete;
    }
}));
;/*
 * International Telephone Input v16.0.11
 * https://github.com/jackocnr/intl-tel-input.git
 * Licensed under the MIT license
 */

// wrap in UMD
(function(factory) {
    if (typeof module === "object" && module.exports) {
        module.exports = factory(require("jquery"), window, document);
    } else if (typeof define === "function" && define.amd) {
        define([ "jquery" ], function($) {
            factory($, window, document);
        });
    } else factory(jQuery, window, document);
})(function($, window, document, undefined) {
    "use strict";
    // Array of country objects for the flag dropdown.
    // Here is the criteria for the plugin to support a given country/territory
    // - It has an iso2 code: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
    // - It has it's own country calling code (it is not a sub-region of another country): https://en.wikipedia.org/wiki/List_of_country_calling_codes
    // - It has a flag in the region-flags project: https://github.com/behdad/region-flags/tree/gh-pages/png
    // - It is supported by libphonenumber (it must be listed on this page): https://github.com/googlei18n/libphonenumber/blob/master/resources/ShortNumberMetadata.xml
    // Each country array has the following information:
    // [
    //    Country name,
    //    iso2 code,
    //    International dial code,
    //    Order (if >1 country with same dial code),
    //    Area codes
    // ]
    var allCountries = [ [ "Afghanistan (‫افغانستان‬‎)", "af", "93" ], [ "Albania (Shqipëri)", "al", "355" ], [ "Algeria (‫الجزائر‬‎)", "dz", "213" ], [ "American Samoa", "as", "1", 5, [ "684" ] ], [ "Andorra", "ad", "376" ], [ "Angola", "ao", "244" ], [ "Anguilla", "ai", "1", 6, [ "264" ] ], [ "Antigua and Barbuda", "ag", "1", 7, [ "268" ] ], [ "Argentina", "ar", "54" ], [ "Armenia (Հայաստան)", "am", "374" ], [ "Aruba", "aw", "297" ], [ "Australia", "au", "61", 0 ], [ "Austria (Österreich)", "at", "43" ], [ "Azerbaijan (Azərbaycan)", "az", "994" ], [ "Bahamas", "bs", "1", 8, [ "242" ] ], [ "Bahrain (‫البحرين‬‎)", "bh", "973" ], [ "Bangladesh (বাংলাদেশ)", "bd", "880" ], [ "Barbados", "bb", "1", 9, [ "246" ] ], [ "Belarus (Беларусь)", "by", "375" ], [ "Belgium (België)", "be", "32" ], [ "Belize", "bz", "501" ], [ "Benin (Bénin)", "bj", "229" ], [ "Bermuda", "bm", "1", 10, [ "441" ] ], [ "Bhutan (འབྲུག)", "bt", "975" ], [ "Bolivia", "bo", "591" ], [ "Bosnia and Herzegovina (Босна и Херцеговина)", "ba", "387" ], [ "Botswana", "bw", "267" ], [ "Brazil (Brasil)", "br", "55" ], [ "British Indian Ocean Territory", "io", "246" ], [ "British Virgin Islands", "vg", "1", 11, [ "284" ] ], [ "Brunei", "bn", "673" ], [ "Bulgaria (България)", "bg", "359" ], [ "Burkina Faso", "bf", "226" ], [ "Burundi (Uburundi)", "bi", "257" ], [ "Cambodia (កម្ពុជា)", "kh", "855" ], [ "Cameroon (Cameroun)", "cm", "237" ], [ "Canada", "ca", "1", 1, [ "204", "226", "236", "249", "250", "289", "306", "343", "365", "387", "403", "416", "418", "431", "437", "438", "450", "506", "514", "519", "548", "579", "581", "587", "604", "613", "639", "647", "672", "705", "709", "742", "778", "780", "782", "807", "819", "825", "867", "873", "902", "905" ] ], [ "Cape Verde (Kabu Verdi)", "cv", "238" ], [ "Caribbean Netherlands", "bq", "599", 1, [ "3", "4", "7" ] ], [ "Cayman Islands", "ky", "1", 12, [ "345" ] ], [ "Central African Republic (République centrafricaine)", "cf", "236" ], [ "Chad (Tchad)", "td", "235" ], [ "Chile", "cl", "56" ], [ "China (中国)", "cn", "86" ], [ "Christmas Island", "cx", "61", 2 ], [ "Cocos (Keeling) Islands", "cc", "61", 1 ], [ "Colombia", "co", "57" ], [ "Comoros (‫جزر القمر‬‎)", "km", "269" ], [ "Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)", "cd", "243" ], [ "Congo (Republic) (Congo-Brazzaville)", "cg", "242" ], [ "Cook Islands", "ck", "682" ], [ "Costa Rica", "cr", "506" ], [ "Côte d’Ivoire", "ci", "225" ], [ "Croatia (Hrvatska)", "hr", "385" ], [ "Cuba", "cu", "53" ], [ "Curaçao", "cw", "599", 0 ], [ "Cyprus (Κύπρος)", "cy", "357" ], [ "Czech Republic (Česká republika)", "cz", "420" ], [ "Denmark (Danmark)", "dk", "45" ], [ "Djibouti", "dj", "253" ], [ "Dominica", "dm", "1", 13, [ "767" ] ], [ "Dominican Republic (República Dominicana)", "do", "1", 2, [ "809", "829", "849" ] ], [ "Ecuador", "ec", "593" ], [ "Egypt (‫مصر‬‎)", "eg", "20" ], [ "El Salvador", "sv", "503" ], [ "Equatorial Guinea (Guinea Ecuatorial)", "gq", "240" ], [ "Eritrea", "er", "291" ], [ "Estonia (Eesti)", "ee", "372" ], [ "Ethiopia", "et", "251" ], [ "Falkland Islands (Islas Malvinas)", "fk", "500" ], [ "Faroe Islands (Føroyar)", "fo", "298" ], [ "Fiji", "fj", "679" ], [ "Finland (Suomi)", "fi", "358", 0 ], [ "France", "fr", "33" ], [ "French Guiana (Guyane française)", "gf", "594" ], [ "French Polynesia (Polynésie française)", "pf", "689" ], [ "Gabon", "ga", "241" ], [ "Gambia", "gm", "220" ], [ "Georgia (საქართველო)", "ge", "995" ], [ "Germany (Deutschland)", "de", "49" ], [ "Ghana (Gaana)", "gh", "233" ], [ "Gibraltar", "gi", "350" ], [ "Greece (Ελλάδα)", "gr", "30" ], [ "Greenland (Kalaallit Nunaat)", "gl", "299" ], [ "Grenada", "gd", "1", 14, [ "473" ] ], [ "Guadeloupe", "gp", "590", 0 ], [ "Guam", "gu", "1", 15, [ "671" ] ], [ "Guatemala", "gt", "502" ], [ "Guernsey", "gg", "44", 1, [ "1481", "7781", "7839", "7911" ] ], [ "Guinea (Guinée)", "gn", "224" ], [ "Guinea-Bissau (Guiné Bissau)", "gw", "245" ], [ "Guyana", "gy", "592" ], [ "Haiti", "ht", "509" ], [ "Honduras", "hn", "504" ], [ "Hong Kong (香港)", "hk", "852" ], [ "Hungary (Magyarország)", "hu", "36" ], [ "Iceland (Ísland)", "is", "354" ], [ "India (भारत)", "in", "91" ], [ "Indonesia", "id", "62" ], [ "Iran (‫ایران‬‎)", "ir", "98" ], [ "Iraq (‫العراق‬‎)", "iq", "964" ], [ "Ireland", "ie", "353" ], [ "Isle of Man", "im", "44", 2, [ "1624", "74576", "7524", "7924", "7624" ] ], [ "Israel (‫ישראל‬‎)", "il", "972" ], [ "Italy (Italia)", "it", "39", 0 ], [ "Jamaica", "jm", "1", 4, [ "876", "658" ] ], [ "Japan (日本)", "jp", "81" ], [ "Jersey", "je", "44", 3, [ "1534", "7509", "7700", "7797", "7829", "7937" ] ], [ "Jordan (‫الأردن‬‎)", "jo", "962" ], [ "Kazakhstan (Казахстан)", "kz", "7", 1, [ "33", "7" ] ], [ "Kenya", "ke", "254" ], [ "Kiribati", "ki", "686" ], [ "Kosovo", "xk", "383" ], [ "Kuwait (‫الكويت‬‎)", "kw", "965" ], [ "Kyrgyzstan (Кыргызстан)", "kg", "996" ], [ "Laos (ລາວ)", "la", "856" ], [ "Latvia (Latvija)", "lv", "371" ], [ "Lebanon (‫لبنان‬‎)", "lb", "961" ], [ "Lesotho", "ls", "266" ], [ "Liberia", "lr", "231" ], [ "Libya (‫ليبيا‬‎)", "ly", "218" ], [ "Liechtenstein", "li", "423" ], [ "Lithuania (Lietuva)", "lt", "370" ], [ "Luxembourg", "lu", "352" ], [ "Macau (澳門)", "mo", "853" ], [ "Macedonia (FYROM) (Македонија)", "mk", "389" ], [ "Madagascar (Madagasikara)", "mg", "261" ], [ "Malawi", "mw", "265" ], [ "Malaysia", "my", "60" ], [ "Maldives", "mv", "960" ], [ "Mali", "ml", "223" ], [ "Malta", "mt", "356" ], [ "Marshall Islands", "mh", "692" ], [ "Martinique", "mq", "596" ], [ "Mauritania (‫موريتانيا‬‎)", "mr", "222" ], [ "Mauritius (Moris)", "mu", "230" ], [ "Mayotte", "yt", "262", 1, [ "269", "639" ] ], [ "Mexico (México)", "mx", "52" ], [ "Micronesia", "fm", "691" ], [ "Moldova (Republica Moldova)", "md", "373" ], [ "Monaco", "mc", "377" ], [ "Mongolia (Монгол)", "mn", "976" ], [ "Montenegro (Crna Gora)", "me", "382" ], [ "Montserrat", "ms", "1", 16, [ "664" ] ], [ "Morocco (‫المغرب‬‎)", "ma", "212", 0 ], [ "Mozambique (Moçambique)", "mz", "258" ], [ "Myanmar (Burma) (မြန်မာ)", "mm", "95" ], [ "Namibia (Namibië)", "na", "264" ], [ "Nauru", "nr", "674" ], [ "Nepal (नेपाल)", "np", "977" ], [ "Netherlands (Nederland)", "nl", "31" ], [ "New Caledonia (Nouvelle-Calédonie)", "nc", "687" ], [ "New Zealand", "nz", "64" ], [ "Nicaragua", "ni", "505" ], [ "Niger (Nijar)", "ne", "227" ], [ "Nigeria", "ng", "234" ], [ "Niue", "nu", "683" ], [ "Norfolk Island", "nf", "672" ], [ "North Korea (조선 민주주의 인민 공화국)", "kp", "850" ], [ "Northern Mariana Islands", "mp", "1", 17, [ "670" ] ], [ "Norway (Norge)", "no", "47", 0 ], [ "Oman (‫عُمان‬‎)", "om", "968" ], [ "Pakistan (‫پاکستان‬‎)", "pk", "92" ], [ "Palau", "pw", "680" ], [ "Palestine (‫فلسطين‬‎)", "ps", "970" ], [ "Panama (Panamá)", "pa", "507" ], [ "Papua New Guinea", "pg", "675" ], [ "Paraguay", "py", "595" ], [ "Peru (Perú)", "pe", "51" ], [ "Philippines", "ph", "63" ], [ "Poland (Polska)", "pl", "48" ], [ "Portugal", "pt", "351" ], [ "Puerto Rico", "pr", "1", 3, [ "787", "939" ] ], [ "Qatar (‫قطر‬‎)", "qa", "974" ], [ "Réunion (La Réunion)", "re", "262", 0 ], [ "Romania (România)", "ro", "40" ], [ "Russia (Россия)", "ru", "7", 0 ], [ "Rwanda", "rw", "250" ], [ "Saint Barthélemy", "bl", "590", 1 ], [ "Saint Helena", "sh", "290" ], [ "Saint Kitts and Nevis", "kn", "1", 18, [ "869" ] ], [ "Saint Lucia", "lc", "1", 19, [ "758" ] ], [ "Saint Martin (Saint-Martin (partie française))", "mf", "590", 2 ], [ "Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)", "pm", "508" ], [ "Saint Vincent and the Grenadines", "vc", "1", 20, [ "784" ] ], [ "Samoa", "ws", "685" ], [ "San Marino", "sm", "378" ], [ "São Tomé and Príncipe (São Tomé e Príncipe)", "st", "239" ], [ "Saudi Arabia (‫المملكة العربية السعودية‬‎)", "sa", "966" ], [ "Senegal (Sénégal)", "sn", "221" ], [ "Serbia (Србија)", "rs", "381" ], [ "Seychelles", "sc", "248" ], [ "Sierra Leone", "sl", "232" ], [ "Singapore", "sg", "65" ], [ "Sint Maarten", "sx", "1", 21, [ "721" ] ], [ "Slovakia (Slovensko)", "sk", "421" ], [ "Slovenia (Slovenija)", "si", "386" ], [ "Solomon Islands", "sb", "677" ], [ "Somalia (Soomaaliya)", "so", "252" ], [ "South Africa", "za", "27" ], [ "South Korea (대한민국)", "kr", "82" ], [ "South Sudan (‫جنوب السودان‬‎)", "ss", "211" ], [ "Spain (España)", "es", "34" ], [ "Sri Lanka (ශ්‍රී ලංකාව)", "lk", "94" ], [ "Sudan (‫السودان‬‎)", "sd", "249" ], [ "Suriname", "sr", "597" ], [ "Svalbard and Jan Mayen", "sj", "47", 1, [ "79" ] ], [ "Swaziland", "sz", "268" ], [ "Sweden (Sverige)", "se", "46" ], [ "Switzerland (Schweiz)", "ch", "41" ], [ "Syria (‫سوريا‬‎)", "sy", "963" ], [ "Taiwan (台灣)", "tw", "886" ], [ "Tajikistan", "tj", "992" ], [ "Tanzania", "tz", "255" ], [ "Thailand (ไทย)", "th", "66" ], [ "Timor-Leste", "tl", "670" ], [ "Togo", "tg", "228" ], [ "Tokelau", "tk", "690" ], [ "Tonga", "to", "676" ], [ "Trinidad and Tobago", "tt", "1", 22, [ "868" ] ], [ "Tunisia (‫تونس‬‎)", "tn", "216" ], [ "Turkey (Türkiye)", "tr", "90" ], [ "Turkmenistan", "tm", "993" ], [ "Turks and Caicos Islands", "tc", "1", 23, [ "649" ] ], [ "Tuvalu", "tv", "688" ], [ "U.S. Virgin Islands", "vi", "1", 24, [ "340" ] ], [ "Uganda", "ug", "256" ], [ "Ukraine (Україна)", "ua", "380" ], [ "United Arab Emirates (‫الإمارات العربية المتحدة‬‎)", "ae", "971" ], [ "United Kingdom", "gb", "44", 0 ], [ "United States", "us", "1", 0 ], [ "Uruguay", "uy", "598" ], [ "Uzbekistan (Oʻzbekiston)", "uz", "998" ], [ "Vanuatu", "vu", "678" ], [ "Vatican City (Città del Vaticano)", "va", "39", 1, [ "06698" ] ], [ "Venezuela", "ve", "58" ], [ "Vietnam (Việt Nam)", "vn", "84" ], [ "Wallis and Futuna (Wallis-et-Futuna)", "wf", "681" ], [ "Western Sahara (‫الصحراء الغربية‬‎)", "eh", "212", 1, [ "5288", "5289" ] ], [ "Yemen (‫اليمن‬‎)", "ye", "967" ], [ "Zambia", "zm", "260" ], [ "Zimbabwe", "zw", "263" ], [ "Åland Islands", "ax", "358", 1, [ "18" ] ] ];
    // loop over all of the countries above, restructuring the data to be objects with named keys
    for (var i = 0; i < allCountries.length; i++) {
        var c = allCountries[i];
        allCountries[i] = {
            name: c[0],
            iso2: c[1],
            dialCode: c[2],
            priority: c[3] || 0,
            areaCodes: c[4] || null
        };
    }
    "use strict";
    function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError("Cannot call a class as a function");
        }
    }
    function _defineProperties(target, props) {
        for (var i = 0; i < props.length; i++) {
            var descriptor = props[i];
            descriptor.enumerable = descriptor.enumerable || false;
            descriptor.configurable = true;
            if ("value" in descriptor) descriptor.writable = true;
            Object.defineProperty(target, descriptor.key, descriptor);
        }
    }
    function _createClass(Constructor, protoProps, staticProps) {
        if (protoProps) _defineProperties(Constructor.prototype, protoProps);
        if (staticProps) _defineProperties(Constructor, staticProps);
        return Constructor;
    }
    window.intlTelInputGlobals = {
        getInstance: function getInstance(input) {
            var id = input.getAttribute("data-intl-tel-input-id");
            return window.intlTelInputGlobals.instances[id];
        },
        instances: {}
    };
    // these vars persist through all instances of the plugin
    var id = 0;
    var defaults = {
        // whether or not to allow the dropdown
        allowDropdown: true,
        // if there is just a dial code in the input: remove it on blur
        autoHideDialCode: true,
        // add a placeholder in the input with an example number for the selected country
        autoPlaceholder: "polite",
        // modify the parentClass
        customContainer: "",
        // modify the auto placeholder
        customPlaceholder: null,
        // append menu to specified element
        dropdownContainer: null,
        // don't display these countries
        excludeCountries: [],
        // format the input value during initialisation and on setNumber
        formatOnDisplay: true,
        // geoIp lookup function
        geoIpLookup: null,
        // inject a hidden input with this name, and on submit, populate it with the result of getNumber
        hiddenInput: "",
        // initial country
        initialCountry: "",
        // localized country names e.g. { 'de': 'Deutschland' }
        localizedCountries: null,
        // don't insert international dial codes
        nationalMode: true,
        // display only these countries
        onlyCountries: [],
        // number type to use for placeholders
        placeholderNumberType: "MOBILE",
        // the countries at the top of the list. defaults to united states and united kingdom
        preferredCountries: [ "us", "gb" ],
        // display the country dial code next to the selected flag so it's not part of the typed number
        separateDialCode: false,
        // specify the path to the libphonenumber script to enable validation/formatting
        utilsScript: ""
    };
    // https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes#Non-geographic_area_codes
    var regionlessNanpNumbers = [ "800", "822", "833", "844", "855", "866", "877", "880", "881", "882", "883", "884", "885", "886", "887", "888", "889" ];
    // keep track of if the window.load event has fired as impossible to check after the fact
    window.addEventListener("load", function() {
        // UPDATE: use a public static field so we can fudge it in the tests
        window.intlTelInputGlobals.windowLoaded = true;
    });
    // utility function to iterate over an object. can't use Object.entries or native forEach because
    // of IE11
    var forEachProp = function forEachProp(obj, callback) {
        var keys = Object.keys(obj);
        for (var i = 0; i < keys.length; i++) {
            callback(keys[i], obj[keys[i]]);
        }
    };
    // run a method on each instance of the plugin
    var forEachInstance = function forEachInstance(method) {
        forEachProp(window.intlTelInputGlobals.instances, function(key) {
            window.intlTelInputGlobals.instances[key][method]();
        });
    };
    // this is our plugin class that we will create an instance of
    // eslint-disable-next-line no-unused-vars
    var Iti = /*#__PURE__*/
    function() {
        function Iti(input, options) {
            var _this = this;
            _classCallCheck(this, Iti);
            this.id = id++;
            this.telInput = input;
            this.activeItem = null;
            this.highlightedItem = null;
            // process specified options / defaults
            // alternative to Object.assign, which isn't supported by IE11
            var customOptions = options || {};
            this.options = {};
            forEachProp(defaults, function(key, value) {
                _this.options[key] = customOptions.hasOwnProperty(key) ? customOptions[key] : value;
            });
            this.hadInitialPlaceholder = Boolean(input.getAttribute("placeholder"));
        }
        _createClass(Iti, [ {
            key: "_init",
            value: function _init() {
                var _this2 = this;
                // if in nationalMode, disable options relating to dial codes
                if (this.options.nationalMode) this.options.autoHideDialCode = false;
                // if separateDialCode then doesn't make sense to A) insert dial code into input
                // (autoHideDialCode), and B) display national numbers (because we're displaying the country
                // dial code next to them)
                if (this.options.separateDialCode) {
                    this.options.autoHideDialCode = this.options.nationalMode = false;
                }
                // we cannot just test screen size as some smartphones/website meta tags will report desktop
                // resolutions
                // Note: for some reason jasmine breaks if you put this in the main Plugin function with the
                // rest of these declarations
                // Note: to target Android Mobiles (and not Tablets), we must find 'Android' and 'Mobile'
                this.isMobile = /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
                if (this.isMobile) {
                    // trigger the mobile dropdown css
                    document.body.classList.add("iti-mobile");
                    // on mobile, we want a full screen dropdown, so we must append it to the body
                    if (!this.options.dropdownContainer) this.options.dropdownContainer = document.body;
                }
                // these promises get resolved when their individual requests complete
                // this way the dev can do something like iti.promise.then(...) to know when all requests are
                // complete
                if (typeof Promise !== "undefined") {
                    var autoCountryPromise = new Promise(function(resolve, reject) {
                        _this2.resolveAutoCountryPromise = resolve;
                        _this2.rejectAutoCountryPromise = reject;
                    });
                    var utilsScriptPromise = new Promise(function(resolve, reject) {
                        _this2.resolveUtilsScriptPromise = resolve;
                        _this2.rejectUtilsScriptPromise = reject;
                    });
                    this.promise = Promise.all([ autoCountryPromise, utilsScriptPromise ]);
                } else {
                    // prevent errors when Promise doesn't exist
                    this.resolveAutoCountryPromise = this.rejectAutoCountryPromise = function() {};
                    this.resolveUtilsScriptPromise = this.rejectUtilsScriptPromise = function() {};
                }
                // in various situations there could be no country selected initially, but we need to be able
                // to assume this variable exists
                this.selectedCountryData = {};
                // process all the data: onlyCountries, excludeCountries, preferredCountries etc
                this._processCountryData();
                // generate the markup
                this._generateMarkup();
                // set the initial state of the input value and the selected flag
                this._setInitialState();
                // start all of the event listeners: autoHideDialCode, input keydown, selectedFlag click
                this._initListeners();
                // utils script, and auto country
                this._initRequests();
            }
        }, {
            key: "_processCountryData",
            value: function _processCountryData() {
                // process onlyCountries or excludeCountries array if present
                this._processAllCountries();
                // process the countryCodes map
                this._processCountryCodes();
                // process the preferredCountries
                this._processPreferredCountries();
                // translate countries according to localizedCountries option
                if (this.options.localizedCountries) this._translateCountriesByLocale();
                // sort countries by name
                if (this.options.onlyCountries.length || this.options.localizedCountries) {
                    this.countries.sort(this._countryNameSort);
                }
            }
        }, {
            key: "_addCountryCode",
            value: function _addCountryCode(iso2, dialCode, priority) {
                if (dialCode.length > this.dialCodeMaxLen) {
                    this.dialCodeMaxLen = dialCode.length;
                }
                if (!this.countryCodes.hasOwnProperty(dialCode)) {
                    this.countryCodes[dialCode] = [];
                }
                // bail if we already have this country for this dialCode
                for (var i = 0; i < this.countryCodes[dialCode].length; i++) {
                    if (this.countryCodes[dialCode][i] === iso2) return;
                }
                // check for undefined as 0 is falsy
                var index = priority !== undefined ? priority : this.countryCodes[dialCode].length;
                this.countryCodes[dialCode][index] = iso2;
            }
        }, {
            key: "_processAllCountries",
            value: function _processAllCountries() {
                if (this.options.onlyCountries.length) {
                    var lowerCaseOnlyCountries = this.options.onlyCountries.map(function(country) {
                        return country.toLowerCase();
                    });
                    this.countries = allCountries.filter(function(country) {
                        return lowerCaseOnlyCountries.indexOf(country.iso2) > -1;
                    });
                } else if (this.options.excludeCountries.length) {
                    var lowerCaseExcludeCountries = this.options.excludeCountries.map(function(country) {
                        return country.toLowerCase();
                    });
                    this.countries = allCountries.filter(function(country) {
                        return lowerCaseExcludeCountries.indexOf(country.iso2) === -1;
                    });
                } else {
                    this.countries = allCountries;
                }
            }
        }, {
            key: "_translateCountriesByLocale",
            value: function _translateCountriesByLocale() {
                for (var i = 0; i < this.countries.length; i++) {
                    var iso = this.countries[i].iso2.toLowerCase();
                    if (this.options.localizedCountries.hasOwnProperty(iso)) {
                        this.countries[i].name = this.options.localizedCountries[iso];
                    }
                }
            }
        }, {
            key: "_countryNameSort",
            value: function _countryNameSort(a, b) {
                return a.name.localeCompare(b.name);
            }
        }, {
            key: "_processCountryCodes",
            value: function _processCountryCodes() {
                this.dialCodeMaxLen = 0;
                this.countryCodes = {};
                // first: add dial codes
                for (var i = 0; i < this.countries.length; i++) {
                    var c = this.countries[i];
                    this._addCountryCode(c.iso2, c.dialCode, c.priority);
                }
                // next: add area codes
                // this is a second loop over countries, to make sure we have all of the "root" countries
                // already in the map, so that we can access them, as each time we add an area code substring
                // to the map, we also need to include the "root" country's code, as that also matches
                for (var _i = 0; _i < this.countries.length; _i++) {
                    var _c = this.countries[_i];
                    // area codes
                    if (_c.areaCodes) {
                        var rootCountryCode = this.countryCodes[_c.dialCode][0];
                        // for each area code
                        for (var j = 0; j < _c.areaCodes.length; j++) {
                            var areaCode = _c.areaCodes[j];
                            // for each digit in the area code to add all partial matches as well
                            for (var k = 1; k < areaCode.length; k++) {
                                var partialDialCode = _c.dialCode + areaCode.substr(0, k);
                                // start with the root country, as that also matches this dial code
                                this._addCountryCode(rootCountryCode, partialDialCode);
                                this._addCountryCode(_c.iso2, partialDialCode);
                            }
                            // add the full area code
                            this._addCountryCode(_c.iso2, _c.dialCode + areaCode);
                        }
                    }
                }
            }
        }, {
            key: "_processPreferredCountries",
            value: function _processPreferredCountries() {
                this.preferredCountries = [];
                for (var i = 0; i < this.options.preferredCountries.length; i++) {
                    var countryCode = this.options.preferredCountries[i].toLowerCase();
                    var countryData = this._getCountryData(countryCode, false, true);
                    if (countryData) this.preferredCountries.push(countryData);
                }
            }
        }, {
            key: "_createEl",
            value: function _createEl(name, attrs, container) {
                var el = document.createElement(name);
                if (attrs) forEachProp(attrs, function(key, value) {
                    return el.setAttribute(key, value);
                });
                if (container) container.appendChild(el);
                return el;
            }
        }, {
            key: "_generateMarkup",
            value: function _generateMarkup() {
                // prevent autocomplete as there's no safe, cross-browser event we can react to, so it can
                // easily put the plugin in an inconsistent state e.g. the wrong flag selected for the
                // autocompleted number, which on submit could mean wrong number is saved (esp in nationalMode)
                this.telInput.setAttribute("autocomplete", "off");
                // containers (mostly for positioning)
                var parentClass = "iti";
                if (this.options.allowDropdown) parentClass += " iti--allow-dropdown";
                if (this.options.separateDialCode) parentClass += " iti--separate-dial-code";
                if (this.options.customContainer) {
                    parentClass += " ";
                    parentClass += this.options.customContainer;
                }
                var wrapper = this._createEl("div", {
                    "class": parentClass
                });
                this.telInput.parentNode.insertBefore(wrapper, this.telInput);
                this.flagsContainer = this._createEl("div", {
                    "class": "iti__flag-container"
                }, wrapper);
                wrapper.appendChild(this.telInput);
                // selected flag (displayed to left of input)
                this.selectedFlag = this._createEl("div", {
                    "class": "iti__selected-flag",
                    role: "combobox",
                    "aria-owns": "country-listbox"
                }, this.flagsContainer);
                this.selectedFlagInner = this._createEl("div", {
                    "class": "iti__flag"
                }, this.selectedFlag);
                if (this.options.separateDialCode) {
                    this.selectedDialCode = this._createEl("div", {
                        "class": "iti__selected-dial-code"
                    }, this.selectedFlag);
                }
                if (this.options.allowDropdown) {
                    // make element focusable and tab navigable
                    this.selectedFlag.setAttribute("tabindex", "0");
                    this.dropdownArrow = this._createEl("div", {
                        "class": "iti__arrow"
                    }, this.selectedFlag);
                    // country dropdown: preferred countries, then divider, then all countries
                    this.countryList = this._createEl("ul", {
                        "class": "iti__country-list iti__hide",
                        id: "country-listbox",
                        "aria-expanded": "false",
                        role: "listbox"
                    });
                    if (this.preferredCountries.length) {
                        this._appendListItems(this.preferredCountries, "iti__preferred");
                        this._createEl("li", {
                            "class": "iti__divider",
                            role: "separator",
                            "aria-disabled": "true"
                        }, this.countryList);
                    }
                    this._appendListItems(this.countries, "iti__standard");
                    // create dropdownContainer markup
                    if (this.options.dropdownContainer) {
                        this.dropdown = this._createEl("div", {
                            "class": "iti iti--container"
                        });
                        this.dropdown.appendChild(this.countryList);
                    } else {
                        this.flagsContainer.appendChild(this.countryList);
                    }
                }
                if (this.options.hiddenInput) {
                    var hiddenInputName = this.options.hiddenInput;
                    var name = this.telInput.getAttribute("name");
                    if (name) {
                        var i = name.lastIndexOf("[");
                        // if input name contains square brackets, then give the hidden input the same name,
                        // replacing the contents of the last set of brackets with the given hiddenInput name
                        if (i !== -1) hiddenInputName = "".concat(name.substr(0, i), "[").concat(hiddenInputName, "]");
                    }
                    this.hiddenInput = this._createEl("input", {
                        type: "hidden",
                        name: hiddenInputName
                    });
                    wrapper.appendChild(this.hiddenInput);
                }
            }
        }, {
            key: "_appendListItems",
            value: function _appendListItems(countries, className) {
                // we create so many DOM elements, it is faster to build a temp string
                // and then add everything to the DOM in one go at the end
                var tmp = "";
                // for each country
                for (var i = 0; i < countries.length; i++) {
                    var c = countries[i];
                    // open the list item
                    tmp += "<li class='iti__country ".concat(className, "' tabIndex='-1' id='iti-item-").concat(c.iso2, "' role='option' data-dial-code='").concat(c.dialCode, "' data-country-code='").concat(c.iso2, "'>");
                    // add the flag
                    tmp += "<div class='iti__flag-box'><div class='iti__flag iti__".concat(c.iso2, "'></div></div>");
                    // and the country name and dial code
                    tmp += "<span class='iti__country-name'>".concat(c.name, "</span>");
                    tmp += "<span class='iti__dial-code'>+".concat(c.dialCode, "</span>");
                    // close the list item
                    tmp += "</li>";
                }
                this.countryList.insertAdjacentHTML("beforeend", tmp);
            }
        }, {
            key: "_setInitialState",
            value: function _setInitialState() {
                var val = this.telInput.value;
                var dialCode = this._getDialCode(val);
                var isRegionlessNanp = this._isRegionlessNanp(val);
                var _this$options = this.options, initialCountry = _this$options.initialCountry, nationalMode = _this$options.nationalMode, autoHideDialCode = _this$options.autoHideDialCode, separateDialCode = _this$options.separateDialCode;
                // if we already have a dial code, and it's not a regionlessNanp, we can go ahead and set the
                // flag, else fall back to the default country
                if (dialCode && !isRegionlessNanp) {
                    this._updateFlagFromNumber(val);
                } else if (initialCountry !== "auto") {
                    // see if we should select a flag
                    if (initialCountry) {
                        this._setFlag(initialCountry.toLowerCase());
                    } else {
                        if (dialCode && isRegionlessNanp) {
                            // has intl dial code, is regionless nanp, and no initialCountry, so default to US
                            this._setFlag("us");
                        } else {
                            // no dial code and no initialCountry, so default to first in list
                            this.defaultCountry = this.preferredCountries.length ? this.preferredCountries[0].iso2 : this.countries[0].iso2;
                            if (!val) {
                                this._setFlag(this.defaultCountry);
                            }
                        }
                    }
                    // if empty and no nationalMode and no autoHideDialCode then insert the default dial code
                    if (!val && !nationalMode && !autoHideDialCode && !separateDialCode) {
                        this.telInput.value = "+".concat(this.selectedCountryData.dialCode);
                    }
                }
                // NOTE: if initialCountry is set to auto, that will be handled separately
                // format - note this wont be run after _updateDialCode as that's only called if no val
                if (val) this._updateValFromNumber(val);
            }
        }, {
            key: "_initListeners",
            value: function _initListeners() {
                this._initKeyListeners();
                if (this.options.autoHideDialCode) this._initBlurListeners();
                if (this.options.allowDropdown) this._initDropdownListeners();
                if (this.hiddenInput) this._initHiddenInputListener();
            }
        }, {
            key: "_initHiddenInputListener",
            value: function _initHiddenInputListener() {
                var _this3 = this;
                this._handleHiddenInputSubmit = function() {
                    _this3.hiddenInput.value = _this3.getNumber();
                };
                if (this.telInput.form) this.telInput.form.addEventListener("submit", this._handleHiddenInputSubmit);
            }
        }, {
            key: "_getClosestLabel",
            value: function _getClosestLabel() {
                var el = this.telInput;
                while (el && el.tagName !== "LABEL") {
                    el = el.parentNode;
                }
                return el;
            }
        }, {
            key: "_initDropdownListeners",
            value: function _initDropdownListeners() {
                var _this4 = this;
                // hack for input nested inside label (which is valid markup): clicking the selected-flag to
                // open the dropdown would then automatically trigger a 2nd click on the input which would
                // close it again
                this._handleLabelClick = function(e) {
                    // if the dropdown is closed, then focus the input, else ignore the click
                    if (_this4.countryList.classList.contains("iti__hide")) _this4.telInput.focus(); else e.preventDefault();
                };
                var label = this._getClosestLabel();
                if (label) label.addEventListener("click", this._handleLabelClick);
                // toggle country dropdown on click
                this._handleClickSelectedFlag = function() {
                    // only intercept this event if we're opening the dropdown
                    // else let it bubble up to the top ("click-off-to-close" listener)
                    // we cannot just stopPropagation as it may be needed to close another instance
                    if (_this4.countryList.classList.contains("iti__hide") && !_this4.telInput.disabled && !_this4.telInput.readOnly) {
                        _this4._showDropdown();
                    }
                };
                this.selectedFlag.addEventListener("click", this._handleClickSelectedFlag);
                // open dropdown list if currently focused
                this._handleFlagsContainerKeydown = function(e) {
                    var isDropdownHidden = _this4.countryList.classList.contains("iti__hide");
                    if (isDropdownHidden && [ "ArrowUp", "Up", "ArrowDown", "Down", " ", "Enter" ].indexOf(e.key) !== -1) {
                        // prevent form from being submitted if "ENTER" was pressed
                        e.preventDefault();
                        // prevent event from being handled again by document
                        e.stopPropagation();
                        _this4._showDropdown();
                    }
                    // allow navigation from dropdown to input on TAB
                    if (e.key === "Tab") _this4._closeDropdown();
                };
                this.flagsContainer.addEventListener("keydown", this._handleFlagsContainerKeydown);
            }
        }, {
            key: "_initRequests",
            value: function _initRequests() {
                var _this5 = this;
                // if the user has specified the path to the utils script, fetch it on window.load, else resolve
                if (this.options.utilsScript && !window.intlTelInputUtils) {
                    // if the plugin is being initialised after the window.load event has already been fired
                    if (window.intlTelInputGlobals.windowLoaded) {
                        window.intlTelInputGlobals.loadUtils(this.options.utilsScript);
                    } else {
                        // wait until the load event so we don't block any other requests e.g. the flags image
                        window.addEventListener("load", function() {
                            window.intlTelInputGlobals.loadUtils(_this5.options.utilsScript);
                        });
                    }
                } else this.resolveUtilsScriptPromise();
                if (this.options.initialCountry === "auto") this._loadAutoCountry(); else this.resolveAutoCountryPromise();
            }
        }, {
            key: "_loadAutoCountry",
            value: function _loadAutoCountry() {
                // 3 options:
                // 1) already loaded (we're done)
                // 2) not already started loading (start)
                // 3) already started loading (do nothing - just wait for loading callback to fire)
                if (window.intlTelInputGlobals.autoCountry) {
                    this.handleAutoCountry();
                } else if (!window.intlTelInputGlobals.startedLoadingAutoCountry) {
                    // don't do this twice!
                    window.intlTelInputGlobals.startedLoadingAutoCountry = true;
                    if (typeof this.options.geoIpLookup === "function") {
                        this.options.geoIpLookup(function(countryCode) {
                            window.intlTelInputGlobals.autoCountry = countryCode.toLowerCase();
                            // tell all instances the auto country is ready
                            // TODO: this should just be the current instances
                            // UPDATE: use setTimeout in case their geoIpLookup function calls this callback straight
                            // away (e.g. if they have already done the geo ip lookup somewhere else). Using
                            // setTimeout means that the current thread of execution will finish before executing
                            // this, which allows the plugin to finish initialising.
                            setTimeout(function() {
                                return forEachInstance("handleAutoCountry");
                            });
                        }, function() {
                            return forEachInstance("rejectAutoCountryPromise");
                        });
                    }
                }
            }
        }, {
            key: "_initKeyListeners",
            value: function _initKeyListeners() {
                var _this6 = this;
                // update flag on keyup
                this._handleKeyupEvent = function() {
                    if (_this6._updateFlagFromNumber(_this6.telInput.value)) {
                        _this6._triggerCountryChange();
                    }
                };
                this.telInput.addEventListener("keyup", this._handleKeyupEvent);
                // update flag on cut/paste events (now supported in all major browsers)
                this._handleClipboardEvent = function() {
                    // hack because "paste" event is fired before input is updated
                    setTimeout(_this6._handleKeyupEvent);
                };
                this.telInput.addEventListener("cut", this._handleClipboardEvent);
                this.telInput.addEventListener("paste", this._handleClipboardEvent);
            }
        }, {
            key: "_cap",
            value: function _cap(number) {
                var max = this.telInput.getAttribute("maxlength");
                return max && number.length > max ? number.substr(0, max) : number;
            }
        }, {
            key: "_initBlurListeners",
            value: function _initBlurListeners() {
                var _this7 = this;
                // on blur or form submit: if just a dial code then remove it
                this._handleSubmitOrBlurEvent = function() {
                    _this7._removeEmptyDialCode();
                };
                if (this.telInput.form) this.telInput.form.addEventListener("submit", this._handleSubmitOrBlurEvent);
                this.telInput.addEventListener("blur", this._handleSubmitOrBlurEvent);
            }
        }, {
            key: "_removeEmptyDialCode",
            value: function _removeEmptyDialCode() {
                if (this.telInput.value.charAt(0) === "+") {
                    var numeric = this._getNumeric(this.telInput.value);
                    // if just a plus, or if just a dial code
                    if (!numeric || this.selectedCountryData.dialCode === numeric) {
                        this.telInput.value = "";
                    }
                }
            }
        }, {
            key: "_getNumeric",
            value: function _getNumeric(s) {
                return s.replace(/\D/g, "");
            }
        }, {
            key: "_trigger",
            value: function _trigger(name) {
                // have to use old school document.createEvent as IE11 doesn't support `new Event()` syntax
                var e = document.createEvent("Event");
                e.initEvent(name, true, true);
                // can bubble, and is cancellable
                this.telInput.dispatchEvent(e);
            }
        }, {
            key: "_showDropdown",
            value: function _showDropdown() {
                this.countryList.classList.remove("iti__hide");
                this.countryList.setAttribute("aria-expanded", "true");
                this._setDropdownPosition();
                // update highlighting and scroll to active list item
                if (this.activeItem) {
                    this._highlightListItem(this.activeItem, false);
                    this._scrollTo(this.activeItem, true);
                }
                // bind all the dropdown-related listeners: mouseover, click, click-off, keydown
                this._bindDropdownListeners();
                // update the arrow
                this.dropdownArrow.classList.add("iti__arrow--up");
                this._trigger("open:countrydropdown");
            }
        }, {
            key: "_toggleClass",
            value: function _toggleClass(el, className, shouldHaveClass) {
                if (shouldHaveClass && !el.classList.contains(className)) el.classList.add(className); else if (!shouldHaveClass && el.classList.contains(className)) el.classList.remove(className);
            }
        }, {
            key: "_setDropdownPosition",
            value: function _setDropdownPosition() {
                var _this8 = this;
                if (this.options.dropdownContainer) {
                    this.options.dropdownContainer.appendChild(this.dropdown);
                }
                if (!this.isMobile) {
                    var pos = this.telInput.getBoundingClientRect();
                    // windowTop from https://stackoverflow.com/a/14384091/217866
                    var windowTop = window.pageYOffset || document.documentElement.scrollTop;
                    var inputTop = pos.top + windowTop;
                    var dropdownHeight = this.countryList.offsetHeight;
                    // dropdownFitsBelow = (dropdownBottom < windowBottom)
                    var dropdownFitsBelow = inputTop + this.telInput.offsetHeight + dropdownHeight < windowTop + window.innerHeight;
                    var dropdownFitsAbove = inputTop - dropdownHeight > windowTop;
                    // by default, the dropdown will be below the input. If we want to position it above the
                    // input, we add the dropup class.
                    this._toggleClass(this.countryList, "iti__country-list--dropup", !dropdownFitsBelow && dropdownFitsAbove);
                    // if dropdownContainer is enabled, calculate postion
                    if (this.options.dropdownContainer) {
                        // by default the dropdown will be directly over the input because it's not in the flow.
                        // If we want to position it below, we need to add some extra top value.
                        var extraTop = !dropdownFitsBelow && dropdownFitsAbove ? 0 : this.telInput.offsetHeight;
                        // calculate placement
                        this.dropdown.style.top = "".concat(inputTop + extraTop, "px");
                        this.dropdown.style.left = "".concat(pos.left + document.body.scrollLeft, "px");
                        // close menu on window scroll
                        this._handleWindowScroll = function() {
                            return _this8._closeDropdown();
                        };
                        window.addEventListener("scroll", this._handleWindowScroll);
                    }
                }
            }
        }, {
            key: "_getClosestListItem",
            value: function _getClosestListItem(target) {
                var el = target;
                while (el && el !== this.countryList && !el.classList.contains("iti__country")) {
                    el = el.parentNode;
                }
                // if we reached the countryList element, then return null
                return el === this.countryList ? null : el;
            }
        }, {
            key: "_bindDropdownListeners",
            value: function _bindDropdownListeners() {
                var _this9 = this;
                // when mouse over a list item, just highlight that one
                // we add the class "highlight", so if they hit "enter" we know which one to select
                this._handleMouseoverCountryList = function(e) {
                    // handle event delegation, as we're listening for this event on the countryList
                    var listItem = _this9._getClosestListItem(e.target);
                    if (listItem) _this9._highlightListItem(listItem, false);
                };
                this.countryList.addEventListener("mouseover", this._handleMouseoverCountryList);
                // listen for country selection
                this._handleClickCountryList = function(e) {
                    var listItem = _this9._getClosestListItem(e.target);
                    if (listItem) _this9._selectListItem(listItem);
                };
                this.countryList.addEventListener("click", this._handleClickCountryList);
                // click off to close
                // (except when this initial opening click is bubbling up)
                // we cannot just stopPropagation as it may be needed to close another instance
                var isOpening = true;
                this._handleClickOffToClose = function() {
                    if (!isOpening) _this9._closeDropdown();
                    isOpening = false;
                };
                document.documentElement.addEventListener("click", this._handleClickOffToClose);
                // listen for up/down scrolling, enter to select, or letters to jump to country name.
                // use keydown as keypress doesn't fire for non-char keys and we want to catch if they
                // just hit down and hold it to scroll down (no keyup event).
                // listen on the document because that's where key events are triggered if no input has focus
                var query = "";
                var queryTimer = null;
                this._handleKeydownOnDropdown = function(e) {
                    // prevent down key from scrolling the whole page,
                    // and enter key from submitting a form etc
                    e.preventDefault();
                    // up and down to navigate
                    if (e.key === "ArrowUp" || e.key === "Up" || e.key === "ArrowDown" || e.key === "Down") _this9._handleUpDownKey(e.key); else if (e.key === "Enter") _this9._handleEnterKey(); else if (e.key === "Escape") _this9._closeDropdown(); else if (/^[a-zA-ZÀ-ÿа-яА-Я ]$/.test(e.key)) {
                        // jump to countries that start with the query string
                        if (queryTimer) clearTimeout(queryTimer);
                        query += e.key.toLowerCase();
                        _this9._searchForCountry(query);
                        // if the timer hits 1 second, reset the query
                        queryTimer = setTimeout(function() {
                            query = "";
                        }, 1e3);
                    }
                };
                document.addEventListener("keydown", this._handleKeydownOnDropdown);
            }
        }, {
            key: "_handleUpDownKey",
            value: function _handleUpDownKey(key) {
                var next = key === "ArrowUp" || key === "Up" ? this.highlightedItem.previousElementSibling : this.highlightedItem.nextElementSibling;
                if (next) {
                    // skip the divider
                    if (next.classList.contains("iti__divider")) {
                        next = key === "ArrowUp" || key === "Up" ? next.previousElementSibling : next.nextElementSibling;
                    }
                    this._highlightListItem(next, true);
                }
            }
        }, {
            key: "_handleEnterKey",
            value: function _handleEnterKey() {
                if (this.highlightedItem) this._selectListItem(this.highlightedItem);
            }
        }, {
            key: "_searchForCountry",
            value: function _searchForCountry(query) {
                for (var i = 0; i < this.countries.length; i++) {
                    if (this._startsWith(this.countries[i].name, query)) {
                        var listItem = this.countryList.querySelector("#iti-item-".concat(this.countries[i].iso2));
                        // update highlighting and scroll
                        this._highlightListItem(listItem, false);
                        this._scrollTo(listItem, true);
                        break;
                    }
                }
            }
        }, {
            key: "_startsWith",
            value: function _startsWith(a, b) {
                return a.substr(0, b.length).toLowerCase() === b;
            }
        }, {
            key: "_updateValFromNumber",
            value: function _updateValFromNumber(originalNumber) {
                var number = originalNumber;
                if (this.options.formatOnDisplay && window.intlTelInputUtils && this.selectedCountryData) {
                    var useNational = !this.options.separateDialCode && (this.options.nationalMode || number.charAt(0) !== "+");
                    var _intlTelInputUtils$nu = intlTelInputUtils.numberFormat, NATIONAL = _intlTelInputUtils$nu.NATIONAL, INTERNATIONAL = _intlTelInputUtils$nu.INTERNATIONAL;
                    var format = useNational ? NATIONAL : INTERNATIONAL;
                    number = intlTelInputUtils.formatNumber(number, this.selectedCountryData.iso2, format);
                }
                number = this._beforeSetNumber(number);
                this.telInput.value = number;
            }
        }, {
            key: "_updateFlagFromNumber",
            value: function _updateFlagFromNumber(originalNumber) {
                // if we're in nationalMode and we already have US/Canada selected, make sure the number starts
                // with a +1 so _getDialCode will be able to extract the area code
                // update: if we dont yet have selectedCountryData, but we're here (trying to update the flag
                // from the number), that means we're initialising the plugin with a number that already has a
                // dial code, so fine to ignore this bit
                var number = originalNumber;
                var selectedDialCode = this.selectedCountryData.dialCode;
                var isNanp = selectedDialCode === "1";
                if (number && this.options.nationalMode && isNanp && number.charAt(0) !== "+") {
                    if (number.charAt(0) !== "1") number = "1".concat(number);
                    number = "+".concat(number);
                }
                // update flag if user types area code for another country
                if (this.options.separateDialCode && selectedDialCode && number.charAt(0) !== "+") {
                    number = "+".concat(selectedDialCode).concat(number);
                }
                // try and extract valid dial code from input
                var dialCode = this._getDialCode(number);
                var numeric = this._getNumeric(number);
                var countryCode = null;
                if (dialCode) {
                    var countryCodes = this.countryCodes[this._getNumeric(dialCode)];
                    // check if the right country is already selected. this should be false if the number is
                    // longer than the matched dial code because in this case we need to make sure that if
                    // there are multiple country matches, that the first one is selected (note: we could
                    // just check that here, but it requires the same loop that we already have later)
                    var alreadySelected = countryCodes.indexOf(this.selectedCountryData.iso2) !== -1 && numeric.length <= dialCode.length - 1;
                    var isRegionlessNanpNumber = selectedDialCode === "1" && this._isRegionlessNanp(numeric);
                    // only update the flag if:
                    // A) NOT (we currently have a NANP flag selected, and the number is a regionlessNanp)
                    // AND
                    // B) the right country is not already selected
                    if (!isRegionlessNanpNumber && !alreadySelected) {
                        // if using onlyCountries option, countryCodes[0] may be empty, so we must find the first
                        // non-empty index
                        for (var j = 0; j < countryCodes.length; j++) {
                            if (countryCodes[j]) {
                                countryCode = countryCodes[j];
                                break;
                            }
                        }
                    }
                } else if (number.charAt(0) === "+" && numeric.length) {
                    // invalid dial code, so empty
                    // Note: use getNumeric here because the number has not been formatted yet, so could contain
                    // bad chars
                    countryCode = "";
                } else if (!number || number === "+") {
                    // empty, or just a plus, so default
                    countryCode = this.defaultCountry;
                }
                if (countryCode !== null) {
                    return this._setFlag(countryCode);
                }
                return false;
            }
        }, {
            key: "_isRegionlessNanp",
            value: function _isRegionlessNanp(number) {
                var numeric = this._getNumeric(number);
                if (numeric.charAt(0) === "1") {
                    var areaCode = numeric.substr(1, 3);
                    return regionlessNanpNumbers.indexOf(areaCode) !== -1;
                }
                return false;
            }
        }, {
            key: "_highlightListItem",
            value: function _highlightListItem(listItem, shouldFocus) {
                var prevItem = this.highlightedItem;
                if (prevItem) prevItem.classList.remove("iti__highlight");
                this.highlightedItem = listItem;
                this.highlightedItem.classList.add("iti__highlight");
                if (shouldFocus) this.highlightedItem.focus();
            }
        }, {
            key: "_getCountryData",
            value: function _getCountryData(countryCode, ignoreOnlyCountriesOption, allowFail) {
                var countryList = ignoreOnlyCountriesOption ? allCountries : this.countries;
                for (var i = 0; i < countryList.length; i++) {
                    if (countryList[i].iso2 === countryCode) {
                        return countryList[i];
                    }
                }
                if (allowFail) {
                    return null;
                }
                throw new Error("No country data for '".concat(countryCode, "'"));
            }
        }, {
            key: "_setFlag",
            value: function _setFlag(countryCode) {
                var prevCountry = this.selectedCountryData.iso2 ? this.selectedCountryData : {};
                // do this first as it will throw an error and stop if countryCode is invalid
                this.selectedCountryData = countryCode ? this._getCountryData(countryCode, false, false) : {};
                // update the defaultCountry - we only need the iso2 from now on, so just store that
                if (this.selectedCountryData.iso2) {
                    this.defaultCountry = this.selectedCountryData.iso2;
                }
                this.selectedFlagInner.setAttribute("class", "iti__flag iti__".concat(countryCode));
                // update the selected country's title attribute
                var title = countryCode ? "".concat(this.selectedCountryData.name, ": +").concat(this.selectedCountryData.dialCode) : "Unknown";
                this.selectedFlag.setAttribute("title", title);
                if (this.options.separateDialCode) {
                    var dialCode = this.selectedCountryData.dialCode ? "+".concat(this.selectedCountryData.dialCode) : "";
                    this.selectedDialCode.innerHTML = dialCode;
                    // offsetWidth is zero if input is in a hidden container during initialisation
                    var selectedFlagWidth = this.selectedFlag.offsetWidth || this._getHiddenSelectedFlagWidth();
                    // add 6px of padding after the grey selected-dial-code box, as this is what we use in the css
                    this.telInput.style.paddingLeft = "".concat(selectedFlagWidth + 6, "px");
                }
                // and the input's placeholder
                this._updatePlaceholder();
                // update the active list item
                if (this.options.allowDropdown) {
                    var prevItem = this.activeItem;
                    if (prevItem) {
                        prevItem.classList.remove("iti__active");
                        prevItem.setAttribute("aria-selected", "false");
                    }
                    if (countryCode) {
                        var nextItem = this.countryList.querySelector("#iti-item-".concat(countryCode));
                        nextItem.setAttribute("aria-selected", "true");
                        nextItem.classList.add("iti__active");
                        this.activeItem = nextItem;
                        this.countryList.setAttribute("aria-activedescendant", nextItem.getAttribute("id"));
                    }
                }
                // return if the flag has changed or not
                return prevCountry.iso2 !== countryCode;
            }
        }, {
            key: "_getHiddenSelectedFlagWidth",
            value: function _getHiddenSelectedFlagWidth() {
                // to get the right styling to apply, all we need is a shallow clone of the container,
                // and then to inject a deep clone of the selectedFlag element
                var containerClone = this.telInput.parentNode.cloneNode();
                containerClone.style.visibility = "hidden";
                document.body.appendChild(containerClone);
                var selectedFlagClone = this.selectedFlag.cloneNode(true);
                containerClone.appendChild(selectedFlagClone);
                var width = selectedFlagClone.offsetWidth;
                containerClone.parentNode.removeChild(containerClone);
                return width;
            }
        }, {
            key: "_updatePlaceholder",
            value: function _updatePlaceholder() {
                var shouldSetPlaceholder = this.options.autoPlaceholder === "aggressive" || !this.hadInitialPlaceholder && this.options.autoPlaceholder === "polite";
                if (window.intlTelInputUtils && shouldSetPlaceholder) {
                    var numberType = intlTelInputUtils.numberType[this.options.placeholderNumberType];
                    var placeholder = this.selectedCountryData.iso2 ? intlTelInputUtils.getExampleNumber(this.selectedCountryData.iso2, this.options.nationalMode, numberType) : "";
                    placeholder = this._beforeSetNumber(placeholder);
                    if (typeof this.options.customPlaceholder === "function") {
                        placeholder = this.options.customPlaceholder(placeholder, this.selectedCountryData);
                    }
                    this.telInput.setAttribute("placeholder", placeholder);
                }
            }
        }, {
            key: "_selectListItem",
            value: function _selectListItem(listItem) {
                // update selected flag and active list item
                var flagChanged = this._setFlag(listItem.getAttribute("data-country-code"));
                this._closeDropdown();
                this._updateDialCode(listItem.getAttribute("data-dial-code"), true);
                // focus the input
                this.telInput.focus();
                // put cursor at end - this fix is required for FF and IE11 (with nationalMode=false i.e. auto
                // inserting dial code), who try to put the cursor at the beginning the first time
                var len = this.telInput.value.length;
                this.telInput.setSelectionRange(len, len);
                if (flagChanged) {
                    this._triggerCountryChange();
                }
            }
        }, {
            key: "_closeDropdown",
            value: function _closeDropdown() {
                this.countryList.classList.add("iti__hide");
                this.countryList.setAttribute("aria-expanded", "false");
                // update the arrow
                this.dropdownArrow.classList.remove("iti__arrow--up");
                // unbind key events
                document.removeEventListener("keydown", this._handleKeydownOnDropdown);
                document.documentElement.removeEventListener("click", this._handleClickOffToClose);
                this.countryList.removeEventListener("mouseover", this._handleMouseoverCountryList);
                this.countryList.removeEventListener("click", this._handleClickCountryList);
                // remove menu from container
                if (this.options.dropdownContainer) {
                    if (!this.isMobile) window.removeEventListener("scroll", this._handleWindowScroll);
                    if (this.dropdown.parentNode) this.dropdown.parentNode.removeChild(this.dropdown);
                }
                this._trigger("close:countrydropdown");
            }
        }, {
            key: "_scrollTo",
            value: function _scrollTo(element, middle) {
                var container = this.countryList;
                // windowTop from https://stackoverflow.com/a/14384091/217866
                var windowTop = window.pageYOffset || document.documentElement.scrollTop;
                var containerHeight = container.offsetHeight;
                var containerTop = container.getBoundingClientRect().top + windowTop;
                var containerBottom = containerTop + containerHeight;
                var elementHeight = element.offsetHeight;
                var elementTop = element.getBoundingClientRect().top + windowTop;
                var elementBottom = elementTop + elementHeight;
                var newScrollTop = elementTop - containerTop + container.scrollTop;
                var middleOffset = containerHeight / 2 - elementHeight / 2;
                if (elementTop < containerTop) {
                    // scroll up
                    if (middle) newScrollTop -= middleOffset;
                    container.scrollTop = newScrollTop;
                } else if (elementBottom > containerBottom) {
                    // scroll down
                    if (middle) newScrollTop += middleOffset;
                    var heightDifference = containerHeight - elementHeight;
                    container.scrollTop = newScrollTop - heightDifference;
                }
            }
        }, {
            key: "_updateDialCode",
            value: function _updateDialCode(newDialCodeBare, hasSelectedListItem) {
                var inputVal = this.telInput.value;
                // save having to pass this every time
                var newDialCode = "+".concat(newDialCodeBare);
                var newNumber;
                if (inputVal.charAt(0) === "+") {
                    // there's a plus so we're dealing with a replacement (doesn't matter if nationalMode or not)
                    var prevDialCode = this._getDialCode(inputVal);
                    if (prevDialCode) {
                        // current number contains a valid dial code, so replace it
                        newNumber = inputVal.replace(prevDialCode, newDialCode);
                    } else {
                        // current number contains an invalid dial code, so ditch it
                        // (no way to determine where the invalid dial code ends and the rest of the number begins)
                        newNumber = newDialCode;
                    }
                } else if (this.options.nationalMode || this.options.separateDialCode) {
                    // don't do anything
                    return;
                } else {
                    // nationalMode is disabled
                    if (inputVal) {
                        // there is an existing value with no dial code: prefix the new dial code
                        newNumber = newDialCode + inputVal;
                    } else if (hasSelectedListItem || !this.options.autoHideDialCode) {
                        // no existing value and either they've just selected a list item, or autoHideDialCode is
                        // disabled: insert new dial code
                        newNumber = newDialCode;
                    } else {
                        return;
                    }
                }
                this.telInput.value = newNumber;
            }
        }, {
            key: "_getDialCode",
            value: function _getDialCode(number) {
                var dialCode = "";
                // only interested in international numbers (starting with a plus)
                if (number.charAt(0) === "+") {
                    var numericChars = "";
                    // iterate over chars
                    for (var i = 0; i < number.length; i++) {
                        var c = number.charAt(i);
                        // if char is number (https://stackoverflow.com/a/8935649/217866)
                        if (!isNaN(parseInt(c, 10))) {
                            numericChars += c;
                            // if current numericChars make a valid dial code
                            if (this.countryCodes[numericChars]) {
                                // store the actual raw string (useful for matching later)
                                dialCode = number.substr(0, i + 1);
                            }
                            if (numericChars.length === this.dialCodeMaxLen) {
                                break;
                            }
                        }
                    }
                }
                return dialCode;
            }
        }, {
            key: "_getFullNumber",
            value: function _getFullNumber() {
                var val = this.telInput.value.trim();
                var dialCode = this.selectedCountryData.dialCode;
                var prefix;
                var numericVal = this._getNumeric(val);
                if (this.options.separateDialCode && val.charAt(0) !== "+" && dialCode && numericVal) {
                    // when using separateDialCode, it is visible so is effectively part of the typed number
                    prefix = "+".concat(dialCode);
                } else {
                    prefix = "";
                }
                return prefix + val;
            }
        }, {
            key: "_beforeSetNumber",
            value: function _beforeSetNumber(originalNumber) {
                var number = originalNumber;
                if (this.options.separateDialCode) {
                    var dialCode = this._getDialCode(number);
                    // if there is a valid dial code
                    if (dialCode) {
                        // in case _getDialCode returned an area code as well
                        dialCode = "+".concat(this.selectedCountryData.dialCode);
                        // a lot of numbers will have a space separating the dial code and the main number, and
                        // some NANP numbers will have a hyphen e.g. +1 684-733-1234 - in both cases we want to get
                        // rid of it
                        // NOTE: don't just trim all non-numerics as may want to preserve an open parenthesis etc
                        var start = number[dialCode.length] === " " || number[dialCode.length] === "-" ? dialCode.length + 1 : dialCode.length;
                        number = number.substr(start);
                    }
                }
                return this._cap(number);
            }
        }, {
            key: "_triggerCountryChange",
            value: function _triggerCountryChange() {
                this._trigger("countrychange");
            }
        }, {
            key: "handleAutoCountry",
            value: function handleAutoCountry() {
                if (this.options.initialCountry === "auto") {
                    // we must set this even if there is an initial val in the input: in case the initial val is
                    // invalid and they delete it - they should see their auto country
                    this.defaultCountry = window.intlTelInputGlobals.autoCountry;
                    // if there's no initial value in the input, then update the flag
                    if (!this.telInput.value) {
                        this.setCountry(this.defaultCountry);
                    }
                    this.resolveAutoCountryPromise();
                }
            }
        }, {
            key: "handleUtils",
            value: function handleUtils() {
                // if the request was successful
                if (window.intlTelInputUtils) {
                    // if there's an initial value in the input, then format it
                    if (this.telInput.value) {
                        this._updateValFromNumber(this.telInput.value);
                    }
                    this._updatePlaceholder();
                }
                this.resolveUtilsScriptPromise();
            }
        }, {
            key: "destroy",
            value: function destroy() {
                var form = this.telInput.form;
                if (this.options.allowDropdown) {
                    // make sure the dropdown is closed (and unbind listeners)
                    this._closeDropdown();
                    this.selectedFlag.removeEventListener("click", this._handleClickSelectedFlag);
                    this.flagsContainer.removeEventListener("keydown", this._handleFlagsContainerKeydown);
                    // label click hack
                    var label = this._getClosestLabel();
                    if (label) label.removeEventListener("click", this._handleLabelClick);
                }
                // unbind hiddenInput listeners
                if (this.hiddenInput && form) form.removeEventListener("submit", this._handleHiddenInputSubmit);
                // unbind autoHideDialCode listeners
                if (this.options.autoHideDialCode) {
                    if (form) form.removeEventListener("submit", this._handleSubmitOrBlurEvent);
                    this.telInput.removeEventListener("blur", this._handleSubmitOrBlurEvent);
                }
                // unbind key events, and cut/paste events
                this.telInput.removeEventListener("keyup", this._handleKeyupEvent);
                this.telInput.removeEventListener("cut", this._handleClipboardEvent);
                this.telInput.removeEventListener("paste", this._handleClipboardEvent);
                // remove attribute of id instance: data-intl-tel-input-id
                this.telInput.removeAttribute("data-intl-tel-input-id");
                // remove markup (but leave the original input)
                var wrapper = this.telInput.parentNode;
                wrapper.parentNode.insertBefore(this.telInput, wrapper);
                wrapper.parentNode.removeChild(wrapper);
                delete window.intlTelInputGlobals.instances[this.id];
            }
        }, {
            key: "getExtension",
            value: function getExtension() {
                if (window.intlTelInputUtils) {
                    return intlTelInputUtils.getExtension(this._getFullNumber(), this.selectedCountryData.iso2);
                }
                return "";
            }
        }, {
            key: "getNumber",
            value: function getNumber(format) {
                if (window.intlTelInputUtils) {
                    var iso2 = this.selectedCountryData.iso2;
                    return intlTelInputUtils.formatNumber(this._getFullNumber(), iso2, format);
                }
                return "";
            }
        }, {
            key: "getNumberType",
            value: function getNumberType() {
                if (window.intlTelInputUtils) {
                    return intlTelInputUtils.getNumberType(this._getFullNumber(), this.selectedCountryData.iso2);
                }
                return -99;
            }
        }, {
            key: "getSelectedCountryData",
            value: function getSelectedCountryData() {
                return this.selectedCountryData;
            }
        }, {
            key: "getValidationError",
            value: function getValidationError() {
                if (window.intlTelInputUtils) {
                    var iso2 = this.selectedCountryData.iso2;
                    return intlTelInputUtils.getValidationError(this._getFullNumber(), iso2);
                }
                return -99;
            }
        }, {
            key: "isValidNumber",
            value: function isValidNumber() {
                var val = this._getFullNumber().trim();
                var countryCode = this.options.nationalMode ? this.selectedCountryData.iso2 : "";
                return window.intlTelInputUtils ? intlTelInputUtils.isValidNumber(val, countryCode) : null;
            }
        }, {
            key: "setCountry",
            value: function setCountry(originalCountryCode) {
                var countryCode = originalCountryCode.toLowerCase();
                // check if already selected
                if (!this.selectedFlagInner.classList.contains("iti__".concat(countryCode))) {
                    this._setFlag(countryCode);
                    this._updateDialCode(this.selectedCountryData.dialCode, false);
                    this._triggerCountryChange();
                }
            }
        }, {
            key: "setNumber",
            value: function setNumber(number) {
                // we must update the flag first, which updates this.selectedCountryData, which is used for
                // formatting the number before displaying it
                var flagChanged = this._updateFlagFromNumber(number);
                this._updateValFromNumber(number);
                if (flagChanged) {
                    this._triggerCountryChange();
                }
            }
        }, {
            key: "setPlaceholderNumberType",
            value: function setPlaceholderNumberType(type) {
                this.options.placeholderNumberType = type;
                this._updatePlaceholder();
            }
        } ]);
        return Iti;
    }();
    /********************
 *  STATIC METHODS
 ********************/
    // get the country data object
    window.intlTelInputGlobals.getCountryData = function() {
        return allCountries;
    };
    // inject a <script> element to load utils.js
    var injectScript = function injectScript(path, handleSuccess, handleFailure) {
        // inject a new script element into the page
        var script = document.createElement("script");
        script.onload = function() {
            forEachInstance("handleUtils");
            if (handleSuccess) handleSuccess();
        };
        script.onerror = function() {
            forEachInstance("rejectUtilsScriptPromise");
            if (handleFailure) handleFailure();
        };
        script.className = "iti-load-utils";
        script.async = true;
        script.src = path;
        document.body.appendChild(script);
    };
    // load the utils script
    window.intlTelInputGlobals.loadUtils = function(path) {
        // 2 options:
        // 1) not already started loading (start)
        // 2) already started loading (do nothing - just wait for the onload callback to fire, which will
        // trigger handleUtils on all instances, invoking their resolveUtilsScriptPromise functions)
        if (!window.intlTelInputUtils && !window.intlTelInputGlobals.startedLoadingUtilsScript) {
            // only do this once
            window.intlTelInputGlobals.startedLoadingUtilsScript = true;
            // if we have promises, then return a promise
            if (typeof Promise !== "undefined") {
                return new Promise(function(resolve, reject) {
                    return injectScript(path, resolve, reject);
                });
            }
            injectScript(path);
        }
        return null;
    };
    // default options
    window.intlTelInputGlobals.defaults = defaults;
    // version
    window.intlTelInputGlobals.version = "16.0.11";
    var pluginName = "intlTelInput";
    // A really lightweight plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[pluginName] = function(options) {
        var args = arguments;
        // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
        if (options === undefined || typeof options === "object") {
            return this.each(function() {
                if (!$.data(this, "plugin_" + pluginName)) {
                    var iti = new Iti(this, options);
                    iti._init();
                    window.intlTelInputGlobals.instances[iti.id] = iti;
                    $.data(this, "plugin_" + pluginName, iti);
                }
            });
        } else if (typeof options === "string" && options[0] !== "_") {
            // If the first parameter is a string and it doesn't start with an underscore treat this as a call to a public method.
            // Cache the method call to make it possible to return a value
            var returns;
            this.each(function() {
                var instance = $.data(this, "plugin_" + pluginName);
                // Tests that there's already a plugin-instance and checks that the requested public method exists
                if (instance instanceof Iti && typeof instance[options] === "function") {
                    // Call the method of our plugin instance, and pass it the supplied arguments.
                    returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
                }
                // Allow instances to be destroyed via the 'destroy' method
                if (options === "destroy") $.data(this, "plugin_" + pluginName, null);
            });
            // If the earlier cached method gives a value back return the value, otherwise return this to preserve chainability.
            return returns !== undefined ? returns : this;
        }
    };
});;/*!
 * dist/jquery.inputmask
 * https://github.com/RobinHerbots/Inputmask
 * Copyright (c) 2010 - 2020 Robin Herbots
 * Licensed under the MIT license
 * Version: 5.0.3
 */
!function webpackUniversalModuleDefinition(root, factory) {
    if ("object" == typeof exports && "object" == typeof module) module.exports = factory(require("jquery")); else if ("function" == typeof define && define.amd) define([ "jquery" ], factory); else {
        var a = "object" == typeof exports ? factory(require("jquery")) : factory(root.jQuery);
        for (var i in a) ("object" == typeof exports ? exports : root)[i] = a[i];
    }
}(window, function(__WEBPACK_EXTERNAL_MODULE__3__) {
    return modules = [ function(module) {
        module.exports = JSON.parse('{"BACKSPACE":8,"BACKSPACE_SAFARI":127,"DELETE":46,"DOWN":40,"END":35,"ENTER":13,"ESCAPE":27,"HOME":36,"INSERT":45,"LEFT":37,"PAGE_DOWN":34,"PAGE_UP":33,"RIGHT":39,"SPACE":32,"TAB":9,"UP":38,"X":88,"CONTROL":17}');
    }, function(module, exports, __webpack_require__) {
        "use strict";
        function _typeof(obj) {
            return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                return typeof obj;
            } : function _typeof(obj) {
                return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
            }, _typeof(obj);
        }
        var $ = __webpack_require__(2), window = __webpack_require__(4), document = window.document, generateMaskSet = __webpack_require__(5).generateMaskSet, analyseMask = __webpack_require__(5).analyseMask, maskScope = __webpack_require__(8);
        function Inputmask(alias, options, internal) {
            if (!(this instanceof Inputmask)) return new Inputmask(alias, options, internal);
            this.el = void 0, this.events = {}, this.maskset = void 0, this.refreshValue = !1, 
            !0 !== internal && ($.isPlainObject(alias) ? options = alias : (options = options || {}, 
            alias && (options.alias = alias)), this.opts = $.extend(!0, {}, this.defaults, options), 
            this.noMasksCache = options && void 0 !== options.definitions, this.userOptions = options || {}, 
            resolveAlias(this.opts.alias, options, this.opts), this.isRTL = this.opts.numericInput);
        }
        function resolveAlias(aliasStr, options, opts) {
            var aliasDefinition = Inputmask.prototype.aliases[aliasStr];
            return aliasDefinition ? (aliasDefinition.alias && resolveAlias(aliasDefinition.alias, void 0, opts), 
            $.extend(!0, opts, aliasDefinition), $.extend(!0, opts, options), !0) : (null === opts.mask && (opts.mask = aliasStr), 
            !1);
        }
        function importAttributeOptions(npt, opts, userOptions, dataAttribute) {
            function importOption(option, optionData) {
                optionData = void 0 !== optionData ? optionData : npt.getAttribute(dataAttribute + "-" + option), 
                null !== optionData && ("string" == typeof optionData && (0 === option.indexOf("on") ? optionData = window[optionData] : "false" === optionData ? optionData = !1 : "true" === optionData && (optionData = !0)), 
                userOptions[option] = optionData);
            }
            if (!0 === opts.importDataAttributes) {
                var attrOptions = npt.getAttribute(dataAttribute), option, dataoptions, optionData, p;
                if (attrOptions && "" !== attrOptions && (attrOptions = attrOptions.replace(/'/g, '"'), 
                dataoptions = JSON.parse("{" + attrOptions + "}")), dataoptions) for (p in optionData = void 0, 
                dataoptions) if ("alias" === p.toLowerCase()) {
                    optionData = dataoptions[p];
                    break;
                }
                for (option in importOption("alias", optionData), userOptions.alias && resolveAlias(userOptions.alias, userOptions, opts), 
                opts) {
                    if (dataoptions) for (p in optionData = void 0, dataoptions) if (p.toLowerCase() === option.toLowerCase()) {
                        optionData = dataoptions[p];
                        break;
                    }
                    importOption(option, optionData);
                }
            }
            return $.extend(!0, opts, userOptions), "rtl" !== npt.dir && !opts.rightAlign || (npt.style.textAlign = "right"), 
            "rtl" !== npt.dir && !opts.numericInput || (npt.dir = "ltr", npt.removeAttribute("dir"), 
            opts.isRTL = !0), Object.keys(userOptions).length;
        }
        Inputmask.prototype = {
            dataAttribute: "data-inputmask",
            defaults: {
                _maxTestPos: 500,
                placeholder: "_",
                optionalmarker: [ "[", "]" ],
                quantifiermarker: [ "{", "}" ],
                groupmarker: [ "(", ")" ],
                alternatormarker: "|",
                escapeChar: "\\",
                mask: null,
                regex: null,
                oncomplete: $.noop,
                onincomplete: $.noop,
                oncleared: $.noop,
                repeat: 0,
                greedy: !1,
                autoUnmask: !1,
                removeMaskOnSubmit: !1,
                clearMaskOnLostFocus: !0,
                insertMode: !0,
                insertModeVisual: !0,
                clearIncomplete: !1,
                alias: null,
                onKeyDown: $.noop,
                onBeforeMask: null,
                onBeforePaste: function onBeforePaste(pastedValue, opts) {
                    return $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(this, pastedValue, opts) : pastedValue;
                },
                onBeforeWrite: null,
                onUnMask: null,
                showMaskOnFocus: !0,
                showMaskOnHover: !0,
                onKeyValidation: $.noop,
                skipOptionalPartCharacter: " ",
                numericInput: !1,
                rightAlign: !1,
                undoOnEscape: !0,
                radixPoint: "",
                _radixDance: !1,
                groupSeparator: "",
                keepStatic: null,
                positionCaretOnTab: !0,
                tabThrough: !1,
                supportsInputType: [ "text", "tel", "url", "password", "search" ],
                ignorables: [ 8, 9, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 0, 229 ],
                isComplete: null,
                preValidation: null,
                postValidation: null,
                staticDefinitionSymbol: void 0,
                jitMasking: !1,
                nullable: !0,
                inputEventOnly: !1,
                noValuePatching: !1,
                positionCaretOnClick: "lvp",
                casing: null,
                inputmode: "text",
                importDataAttributes: !0,
                shiftPositions: !0
            },
            definitions: {
                9: {
                    validator: "[0-9\uff11-\uff19]",
                    definitionSymbol: "*"
                },
                a: {
                    validator: "[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
                    definitionSymbol: "*"
                },
                "*": {
                    validator: "[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]"
                }
            },
            aliases: {},
            masksCache: {},
            mask: function mask(elems) {
                var that = this;
                return "string" == typeof elems && (elems = document.getElementById(elems) || document.querySelectorAll(elems)), 
                elems = elems.nodeName ? [ elems ] : elems, $.each(elems, function(ndx, el) {
                    var scopedOpts = $.extend(!0, {}, that.opts);
                    if (importAttributeOptions(el, scopedOpts, $.extend(!0, {}, that.userOptions), that.dataAttribute)) {
                        var maskset = generateMaskSet(scopedOpts, that.noMasksCache);
                        void 0 !== maskset && (void 0 !== el.inputmask && (el.inputmask.opts.autoUnmask = !0, 
                        el.inputmask.remove()), el.inputmask = new Inputmask(void 0, void 0, !0), el.inputmask.opts = scopedOpts, 
                        el.inputmask.noMasksCache = that.noMasksCache, el.inputmask.userOptions = $.extend(!0, {}, that.userOptions), 
                        el.inputmask.isRTL = scopedOpts.isRTL || scopedOpts.numericInput, el.inputmask.el = el, 
                        el.inputmask.maskset = maskset, $.data(el, "_inputmask_opts", scopedOpts), maskScope.call(el.inputmask, {
                            action: "mask"
                        }));
                    }
                }), elems && elems[0] && elems[0].inputmask || this;
            },
            option: function option(options, noremask) {
                return "string" == typeof options ? this.opts[options] : "object" === _typeof(options) ? ($.extend(this.userOptions, options), 
                this.el && !0 !== noremask && this.mask(this.el), this) : void 0;
            },
            unmaskedvalue: function unmaskedvalue(value) {
                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                maskScope.call(this, {
                    action: "unmaskedvalue",
                    value: value
                });
            },
            remove: function remove() {
                return maskScope.call(this, {
                    action: "remove"
                });
            },
            getemptymask: function getemptymask() {
                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                maskScope.call(this, {
                    action: "getemptymask"
                });
            },
            hasMaskedValue: function hasMaskedValue() {
                return !this.opts.autoUnmask;
            },
            isComplete: function isComplete() {
                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                maskScope.call(this, {
                    action: "isComplete"
                });
            },
            getmetadata: function getmetadata() {
                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                maskScope.call(this, {
                    action: "getmetadata"
                });
            },
            isValid: function isValid(value) {
                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                maskScope.call(this, {
                    action: "isValid",
                    value: value
                });
            },
            format: function format(value, metadata) {
                return this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache), 
                maskScope.call(this, {
                    action: "format",
                    value: value,
                    metadata: metadata
                });
            },
            setValue: function setValue(value) {
                this.el && $(this.el).trigger("setvalue", [ value ]);
            },
            analyseMask: analyseMask
        }, Inputmask.extendDefaults = function(options) {
            $.extend(!0, Inputmask.prototype.defaults, options);
        }, Inputmask.extendDefinitions = function(definition) {
            $.extend(!0, Inputmask.prototype.definitions, definition);
        }, Inputmask.extendAliases = function(alias) {
            $.extend(!0, Inputmask.prototype.aliases, alias);
        }, Inputmask.format = function(value, options, metadata) {
            return Inputmask(options).format(value, metadata);
        }, Inputmask.unmask = function(value, options) {
            return Inputmask(options).unmaskedvalue(value);
        }, Inputmask.isValid = function(value, options) {
            return Inputmask(options).isValid(value);
        }, Inputmask.remove = function(elems) {
            "string" == typeof elems && (elems = document.getElementById(elems) || document.querySelectorAll(elems)), 
            elems = elems.nodeName ? [ elems ] : elems, $.each(elems, function(ndx, el) {
                el.inputmask && el.inputmask.remove();
            });
        }, Inputmask.setValue = function(elems, value) {
            "string" == typeof elems && (elems = document.getElementById(elems) || document.querySelectorAll(elems)), 
            elems = elems.nodeName ? [ elems ] : elems, $.each(elems, function(ndx, el) {
                el.inputmask ? el.inputmask.setValue(value) : $(el).trigger("setvalue", [ value ]);
            });
        };
        var escapeRegexRegex = new RegExp("(\\" + [ "/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\", "$", "^" ].join("|\\") + ")", "gim");
        Inputmask.escapeRegex = function(str) {
            return str.replace(escapeRegexRegex, "\\$1");
        }, Inputmask.dependencyLib = $, window.Inputmask = Inputmask, module.exports = Inputmask;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var jquery = __webpack_require__(3);
        if (void 0 === jquery) throw "jQuery not loaded!";
        module.exports = jquery;
    }, function(module, exports) {
        module.exports = __WEBPACK_EXTERNAL_MODULE__3__;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __WEBPACK_AMD_DEFINE_RESULT__;
        function _typeof(obj) {
            return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                return typeof obj;
            } : function _typeof(obj) {
                return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
            }, _typeof(obj);
        }
        __WEBPACK_AMD_DEFINE_RESULT__ = function() {
            return "undefined" != typeof window ? window : new (eval("require('jsdom').JSDOM"))("").window;
        }.call(exports, __webpack_require__, exports, module), void 0 === __WEBPACK_AMD_DEFINE_RESULT__ || (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var $ = __webpack_require__(2);
        function generateMaskSet(opts, nocache) {
            var ms;
            function generateMask(mask, metadata, opts) {
                var regexMask = !1, masksetDefinition, maskdefKey;
                if (null !== mask && "" !== mask || (regexMask = null !== opts.regex, mask = regexMask ? (mask = opts.regex, 
                mask.replace(/^(\^)(.*)(\$)$/, "$2")) : (regexMask = !0, ".*")), 1 === mask.length && !1 === opts.greedy && 0 !== opts.repeat && (opts.placeholder = ""), 
                0 < opts.repeat || "*" === opts.repeat || "+" === opts.repeat) {
                    var repeatStart = "*" === opts.repeat ? 0 : "+" === opts.repeat ? 1 : opts.repeat;
                    mask = opts.groupmarker[0] + mask + opts.groupmarker[1] + opts.quantifiermarker[0] + repeatStart + "," + opts.repeat + opts.quantifiermarker[1];
                }
                return maskdefKey = regexMask ? "regex_" + opts.regex : opts.numericInput ? mask.split("").reverse().join("") : mask, 
                !1 !== opts.keepStatic && (maskdefKey = "ks_" + maskdefKey), void 0 === Inputmask.prototype.masksCache[maskdefKey] || !0 === nocache ? (masksetDefinition = {
                    mask: mask,
                    maskToken: Inputmask.prototype.analyseMask(mask, regexMask, opts),
                    validPositions: {},
                    _buffer: void 0,
                    buffer: void 0,
                    tests: {},
                    excludes: {},
                    metadata: metadata,
                    maskLength: void 0,
                    jitOffset: {}
                }, !0 !== nocache && (Inputmask.prototype.masksCache[maskdefKey] = masksetDefinition, 
                masksetDefinition = $.extend(!0, {}, Inputmask.prototype.masksCache[maskdefKey]))) : masksetDefinition = $.extend(!0, {}, Inputmask.prototype.masksCache[maskdefKey]), 
                masksetDefinition;
            }
            if ($.isFunction(opts.mask) && (opts.mask = opts.mask(opts)), $.isArray(opts.mask)) {
                if (1 < opts.mask.length) {
                    null === opts.keepStatic && (opts.keepStatic = !0);
                    var altMask = opts.groupmarker[0];
                    return $.each(opts.isRTL ? opts.mask.reverse() : opts.mask, function(ndx, msk) {
                        1 < altMask.length && (altMask += opts.groupmarker[1] + opts.alternatormarker + opts.groupmarker[0]), 
                        void 0 === msk.mask || $.isFunction(msk.mask) ? altMask += msk : altMask += msk.mask;
                    }), altMask += opts.groupmarker[1], generateMask(altMask, opts.mask, opts);
                }
                opts.mask = opts.mask.pop();
            }
            return null === opts.keepStatic && (opts.keepStatic = !1), ms = opts.mask && void 0 !== opts.mask.mask && !$.isFunction(opts.mask.mask) ? generateMask(opts.mask.mask, opts.mask, opts) : generateMask(opts.mask, opts.mask, opts), 
            ms;
        }
        function analyseMask(mask, regexMask, opts) {
            var tokenizer = /(?:[?*+]|\{[0-9+*]+(?:,[0-9+*]*)?(?:\|[0-9+*]*)?\})|[^.?*+^${[]()|\\]+|./g, regexTokenizer = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, escaped = !1, currentToken = new MaskToken(), match, m, openenings = [], maskTokens = [], openingToken, currentOpeningToken, alternator, lastMatch, closeRegexGroup = !1;
            function MaskToken(isGroup, isOptional, isQuantifier, isAlternator) {
                this.matches = [], this.openGroup = isGroup || !1, this.alternatorGroup = !1, this.isGroup = isGroup || !1, 
                this.isOptional = isOptional || !1, this.isQuantifier = isQuantifier || !1, this.isAlternator = isAlternator || !1, 
                this.quantifier = {
                    min: 1,
                    max: 1
                };
            }
            function insertTestDefinition(mtoken, element, position) {
                position = void 0 !== position ? position : mtoken.matches.length;
                var prevMatch = mtoken.matches[position - 1];
                if (regexMask) 0 === element.indexOf("[") || escaped && /\\d|\\s|\\w]/i.test(element) || "." === element ? mtoken.matches.splice(position++, 0, {
                    fn: new RegExp(element, opts.casing ? "i" : ""),
                    static: !1,
                    optionality: !1,
                    newBlockMarker: void 0 === prevMatch ? "master" : prevMatch.def !== element,
                    casing: null,
                    def: element,
                    placeholder: void 0,
                    nativeDef: element
                }) : (escaped && (element = element[element.length - 1]), $.each(element.split(""), function(ndx, lmnt) {
                    prevMatch = mtoken.matches[position - 1], mtoken.matches.splice(position++, 0, {
                        fn: /[a-z]/i.test(opts.staticDefinitionSymbol || lmnt) ? new RegExp("[" + (opts.staticDefinitionSymbol || lmnt) + "]", opts.casing ? "i" : "") : null,
                        static: !0,
                        optionality: !1,
                        newBlockMarker: void 0 === prevMatch ? "master" : prevMatch.def !== lmnt && !0 !== prevMatch.static,
                        casing: null,
                        def: opts.staticDefinitionSymbol || lmnt,
                        placeholder: void 0 !== opts.staticDefinitionSymbol ? lmnt : void 0,
                        nativeDef: (escaped ? "'" : "") + lmnt
                    });
                })), escaped = !1; else {
                    var maskdef = (opts.definitions ? opts.definitions[element] : void 0) || Inputmask.prototype.definitions[element];
                    maskdef && !escaped ? mtoken.matches.splice(position++, 0, {
                        fn: maskdef.validator ? "string" == typeof maskdef.validator ? new RegExp(maskdef.validator, opts.casing ? "i" : "") : new function() {
                            this.test = maskdef.validator;
                        }() : new RegExp("."),
                        static: maskdef.static || !1,
                        optionality: !1,
                        newBlockMarker: void 0 === prevMatch ? "master" : prevMatch.def !== (maskdef.definitionSymbol || element),
                        casing: maskdef.casing,
                        def: maskdef.definitionSymbol || element,
                        placeholder: maskdef.placeholder,
                        nativeDef: element,
                        generated: maskdef.generated
                    }) : (mtoken.matches.splice(position++, 0, {
                        fn: /[a-z]/i.test(opts.staticDefinitionSymbol || element) ? new RegExp("[" + (opts.staticDefinitionSymbol || element) + "]", opts.casing ? "i" : "") : null,
                        static: !0,
                        optionality: !1,
                        newBlockMarker: void 0 === prevMatch ? "master" : prevMatch.def !== element && !0 !== prevMatch.static,
                        casing: null,
                        def: opts.staticDefinitionSymbol || element,
                        placeholder: void 0 !== opts.staticDefinitionSymbol ? element : void 0,
                        nativeDef: (escaped ? "'" : "") + element
                    }), escaped = !1);
                }
            }
            function verifyGroupMarker(maskToken) {
                maskToken && maskToken.matches && $.each(maskToken.matches, function(ndx, token) {
                    var nextToken = maskToken.matches[ndx + 1];
                    (void 0 === nextToken || void 0 === nextToken.matches || !1 === nextToken.isQuantifier) && token && token.isGroup && (token.isGroup = !1, 
                    regexMask || (insertTestDefinition(token, opts.groupmarker[0], 0), !0 !== token.openGroup && insertTestDefinition(token, opts.groupmarker[1]))), 
                    verifyGroupMarker(token);
                });
            }
            function defaultCase() {
                if (0 < openenings.length) {
                    if (currentOpeningToken = openenings[openenings.length - 1], insertTestDefinition(currentOpeningToken, m), 
                    currentOpeningToken.isAlternator) {
                        alternator = openenings.pop();
                        for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup && (alternator.matches[mndx].isGroup = !1);
                        0 < openenings.length ? (currentOpeningToken = openenings[openenings.length - 1], 
                        currentOpeningToken.matches.push(alternator)) : currentToken.matches.push(alternator);
                    }
                } else insertTestDefinition(currentToken, m);
            }
            function reverseTokens(maskToken) {
                function reverseStatic(st) {
                    return st === opts.optionalmarker[0] ? st = opts.optionalmarker[1] : st === opts.optionalmarker[1] ? st = opts.optionalmarker[0] : st === opts.groupmarker[0] ? st = opts.groupmarker[1] : st === opts.groupmarker[1] && (st = opts.groupmarker[0]), 
                    st;
                }
                for (var match in maskToken.matches = maskToken.matches.reverse(), maskToken.matches) if (Object.prototype.hasOwnProperty.call(maskToken.matches, match)) {
                    var intMatch = parseInt(match);
                    if (maskToken.matches[match].isQuantifier && maskToken.matches[intMatch + 1] && maskToken.matches[intMatch + 1].isGroup) {
                        var qt = maskToken.matches[match];
                        maskToken.matches.splice(match, 1), maskToken.matches.splice(intMatch + 1, 0, qt);
                    }
                    void 0 !== maskToken.matches[match].matches ? maskToken.matches[match] = reverseTokens(maskToken.matches[match]) : maskToken.matches[match] = reverseStatic(maskToken.matches[match]);
                }
                return maskToken;
            }
            function groupify(matches) {
                var groupToken = new MaskToken(!0);
                return groupToken.openGroup = !1, groupToken.matches = matches, groupToken;
            }
            function closeGroup() {
                if (openingToken = openenings.pop(), openingToken.openGroup = !1, void 0 !== openingToken) if (0 < openenings.length) {
                    if (currentOpeningToken = openenings[openenings.length - 1], currentOpeningToken.matches.push(openingToken), 
                    currentOpeningToken.isAlternator) {
                        alternator = openenings.pop();
                        for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup = !1, 
                        alternator.matches[mndx].alternatorGroup = !1;
                        0 < openenings.length ? (currentOpeningToken = openenings[openenings.length - 1], 
                        currentOpeningToken.matches.push(alternator)) : currentToken.matches.push(alternator);
                    }
                } else currentToken.matches.push(openingToken); else defaultCase();
            }
            function groupQuantifier(matches) {
                var lastMatch = matches.pop();
                return lastMatch.isQuantifier && (lastMatch = groupify([ matches.pop(), lastMatch ])), 
                lastMatch;
            }
            for (regexMask && (opts.optionalmarker[0] = void 0, opts.optionalmarker[1] = void 0); match = regexMask ? regexTokenizer.exec(mask) : tokenizer.exec(mask); ) {
                if (m = match[0], regexMask) switch (m.charAt(0)) {
                  case "?":
                    m = "{0,1}";
                    break;

                  case "+":
                  case "*":
                    m = "{" + m + "}";
                    break;

                  case "|":
                    if (0 === openenings.length) {
                        var altRegexGroup = groupify(currentToken.matches);
                        altRegexGroup.openGroup = !0, openenings.push(altRegexGroup), currentToken.matches = [], 
                        closeRegexGroup = !0;
                    }
                    break;
                }
                if (escaped) defaultCase(); else switch (m.charAt(0)) {
                  case "(?=":
                    break;

                  case "(?!":
                    break;

                  case "(?<=":
                    break;

                  case "(?<!":
                    break;

                  case opts.escapeChar:
                    escaped = !0, regexMask && defaultCase();
                    break;

                  case opts.optionalmarker[1]:
                  case opts.groupmarker[1]:
                    closeGroup();
                    break;

                  case opts.optionalmarker[0]:
                    openenings.push(new MaskToken(!1, !0));
                    break;

                  case opts.groupmarker[0]:
                    openenings.push(new MaskToken(!0));
                    break;

                  case opts.quantifiermarker[0]:
                    var quantifier = new MaskToken(!1, !1, !0);
                    m = m.replace(/[{}]/g, "");
                    var mqj = m.split("|"), mq = mqj[0].split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = 1 === mq.length ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
                    "*" !== mq0 && "+" !== mq0 || (mq0 = "*" === mq1 ? 0 : 1), quantifier.quantifier = {
                        min: mq0,
                        max: mq1,
                        jit: mqj[1]
                    };
                    var matches = 0 < openenings.length ? openenings[openenings.length - 1].matches : currentToken.matches;
                    if (match = matches.pop(), match.isAlternator) {
                        matches.push(match), matches = match.matches;
                        var groupToken = new MaskToken(!0), tmpMatch = matches.pop();
                        matches.push(groupToken), matches = groupToken.matches, match = tmpMatch;
                    }
                    match.isGroup || (match = groupify([ match ])), matches.push(match), matches.push(quantifier);
                    break;

                  case opts.alternatormarker:
                    if (0 < openenings.length) {
                        currentOpeningToken = openenings[openenings.length - 1];
                        var subToken = currentOpeningToken.matches[currentOpeningToken.matches.length - 1];
                        lastMatch = currentOpeningToken.openGroup && (void 0 === subToken.matches || !1 === subToken.isGroup && !1 === subToken.isAlternator) ? openenings.pop() : groupQuantifier(currentOpeningToken.matches);
                    } else lastMatch = groupQuantifier(currentToken.matches);
                    if (lastMatch.isAlternator) openenings.push(lastMatch); else if (lastMatch.alternatorGroup ? (alternator = openenings.pop(), 
                    lastMatch.alternatorGroup = !1) : alternator = new MaskToken(!1, !1, !1, !0), alternator.matches.push(lastMatch), 
                    openenings.push(alternator), lastMatch.openGroup) {
                        lastMatch.openGroup = !1;
                        var alternatorGroup = new MaskToken(!0);
                        alternatorGroup.alternatorGroup = !0, openenings.push(alternatorGroup);
                    }
                    break;

                  default:
                    defaultCase();
                }
            }
            for (closeRegexGroup && closeGroup(); 0 < openenings.length; ) openingToken = openenings.pop(), 
            currentToken.matches.push(openingToken);
            return 0 < currentToken.matches.length && (verifyGroupMarker(currentToken), maskTokens.push(currentToken)), 
            (opts.numericInput || opts.isRTL) && reverseTokens(maskTokens[0]), maskTokens;
        }
        module.exports = {
            generateMaskSet: generateMaskSet,
            analyseMask: analyseMask
        };
    }, function(module, exports, __webpack_require__) {
        "use strict";
        __webpack_require__(7), __webpack_require__(9), __webpack_require__(10), __webpack_require__(11), 
        module.exports = __webpack_require__(1);
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var Inputmask = __webpack_require__(1);
        Inputmask.extendDefinitions({
            A: {
                validator: "[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
                casing: "upper"
            },
            "&": {
                validator: "[0-9A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
                casing: "upper"
            },
            "#": {
                validator: "[0-9A-Fa-f]",
                casing: "upper"
            }
        });
        var ipValidatorRegex = new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]");
        function ipValidator(chrs, maskset, pos, strict, opts) {
            return chrs = -1 < pos - 1 && "." !== maskset.buffer[pos - 1] ? (chrs = maskset.buffer[pos - 1] + chrs, 
            -1 < pos - 2 && "." !== maskset.buffer[pos - 2] ? maskset.buffer[pos - 2] + chrs : "0" + chrs) : "00" + chrs, 
            ipValidatorRegex.test(chrs);
        }
        Inputmask.extendAliases({
            cssunit: {
                regex: "[+-]?[0-9]+\\.?([0-9]+)?(px|em|rem|ex|%|in|cm|mm|pt|pc)"
            },
            url: {
                regex: "(https?|ftp)//.*",
                autoUnmask: !1
            },
            ip: {
                mask: "i[i[i]].j[j[j]].k[k[k]].l[l[l]]",
                definitions: {
                    i: {
                        validator: ipValidator
                    },
                    j: {
                        validator: ipValidator
                    },
                    k: {
                        validator: ipValidator
                    },
                    l: {
                        validator: ipValidator
                    }
                },
                onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                    return maskedValue;
                },
                inputmode: "numeric"
            },
            email: {
                mask: "*{1,64}[.*{1,64}][.*{1,64}][.*{1,63}]@-{1,63}.-{1,63}[.-{1,63}][.-{1,63}]",
                greedy: !1,
                casing: "lower",
                onBeforePaste: function onBeforePaste(pastedValue, opts) {
                    return pastedValue = pastedValue.toLowerCase(), pastedValue.replace("mailto:", "");
                },
                definitions: {
                    "*": {
                        validator: "[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5!#$%&'*+/=?^_`{|}~-]"
                    },
                    "-": {
                        validator: "[0-9A-Za-z-]"
                    }
                },
                onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                    return maskedValue;
                },
                inputmode: "email"
            },
            mac: {
                mask: "##:##:##:##:##:##"
            },
            vin: {
                mask: "V{13}9{4}",
                definitions: {
                    V: {
                        validator: "[A-HJ-NPR-Za-hj-npr-z\\d]",
                        casing: "upper"
                    }
                },
                clearIncomplete: !0,
                autoUnmask: !0
            },
            ssn: {
                mask: "999-99-9999",
                postValidation: function postValidation(buffer, pos, c, currentResult, opts, maskset, strict) {
                    return /^(?!219-09-9999|078-05-1120)(?!666|000|9.{2}).{3}-(?!00).{2}-(?!0{4}).{4}$/.test(buffer.join(""));
                }
            }
        }), module.exports = Inputmask;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        function _typeof(obj) {
            return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                return typeof obj;
            } : function _typeof(obj) {
                return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
            }, _typeof(obj);
        }
        var $ = __webpack_require__(2), window = __webpack_require__(4), document = window.document, ua = window.navigator && window.navigator.userAgent || "", ie = 0 < ua.indexOf("MSIE ") || 0 < ua.indexOf("Trident/"), mobile = "ontouchstart" in window, iemobile = /iemobile/i.test(ua), iphone = /iphone/i.test(ua) && !iemobile, keyCode = __webpack_require__(0);
        module.exports = function maskScope(actionObj, maskset, opts) {
            maskset = maskset || this.maskset, opts = opts || this.opts;
            var inputmask = this, el = this.el, isRTL = this.isRTL || (this.isRTL = opts.numericInput), undoValue, $el, skipKeyPressEvent = !1, skipInputEvent = !1, validationEvent = !1, ignorable = !1, maxLength, mouseEnter = !1, originalPlaceholder = void 0;
            function getMaskTemplate(baseOnInput, minimalPos, includeMode, noJit, clearOptionalTail) {
                var greedy = opts.greedy;
                clearOptionalTail && (opts.greedy = !1), minimalPos = minimalPos || 0;
                var maskTemplate = [], ndxIntlzr, pos = 0, test, testPos, jitRenderStatic;
                do {
                    if (!0 === baseOnInput && maskset.validPositions[pos]) testPos = clearOptionalTail && !0 === maskset.validPositions[pos].match.optionality && void 0 === maskset.validPositions[pos + 1] && (!0 === maskset.validPositions[pos].generatedInput || maskset.validPositions[pos].input == opts.skipOptionalPartCharacter && 0 < pos) ? determineTestTemplate(pos, getTests(pos, ndxIntlzr, pos - 1)) : maskset.validPositions[pos], 
                    test = testPos.match, ndxIntlzr = testPos.locator.slice(), maskTemplate.push(!0 === includeMode ? testPos.input : !1 === includeMode ? test.nativeDef : getPlaceholder(pos, test)); else {
                        testPos = getTestTemplate(pos, ndxIntlzr, pos - 1), test = testPos.match, ndxIntlzr = testPos.locator.slice();
                        var jitMasking = !0 !== noJit && (!1 !== opts.jitMasking ? opts.jitMasking : test.jit);
                        jitRenderStatic = jitRenderStatic && test.static && test.def !== opts.groupSeparator && null === test.fn || maskset.validPositions[pos - 1] && test.static && test.def !== opts.groupSeparator && null === test.fn, 
                        jitRenderStatic || !1 === jitMasking || void 0 === jitMasking || "number" == typeof jitMasking && isFinite(jitMasking) && pos < jitMasking ? maskTemplate.push(!1 === includeMode ? test.nativeDef : getPlaceholder(pos, test)) : jitRenderStatic = !1;
                    }
                    pos++;
                } while ((void 0 === maxLength || pos < maxLength) && (!0 !== test.static || "" !== test.def) || pos < minimalPos);
                return "" === maskTemplate[maskTemplate.length - 1] && maskTemplate.pop(), !1 === includeMode && void 0 !== maskset.maskLength || (maskset.maskLength = pos - 1), 
                opts.greedy = greedy, maskTemplate;
            }
            function resetMaskSet(soft) {
                maskset.buffer = void 0, !0 !== soft && (maskset.validPositions = {}, maskset.p = 0);
            }
            function getLastValidPosition(closestTo, strict, validPositions) {
                var before = -1, after = -1, valids = validPositions || maskset.validPositions;
                for (var posNdx in void 0 === closestTo && (closestTo = -1), valids) {
                    var psNdx = parseInt(posNdx);
                    valids[psNdx] && (strict || !0 !== valids[psNdx].generatedInput) && (psNdx <= closestTo && (before = psNdx), 
                    closestTo <= psNdx && (after = psNdx));
                }
                return -1 === before || before == closestTo ? after : -1 == after ? before : closestTo - before < after - closestTo ? before : after;
            }
            function getDecisionTaker(tst) {
                var decisionTaker = tst.locator[tst.alternation];
                return "string" == typeof decisionTaker && 0 < decisionTaker.length && (decisionTaker = decisionTaker.split(",")[0]), 
                void 0 !== decisionTaker ? decisionTaker.toString() : "";
            }
            function getLocator(tst, align) {
                var locator = (null != tst.alternation ? tst.mloc[getDecisionTaker(tst)] : tst.locator).join("");
                if ("" !== locator) for (;locator.length < align; ) locator += "0";
                return locator;
            }
            function determineTestTemplate(pos, tests) {
                pos = 0 < pos ? pos - 1 : 0;
                for (var altTest = getTest(pos), targetLocator = getLocator(altTest), tstLocator, closest, bestMatch, ndx = 0; ndx < tests.length; ndx++) {
                    var tst = tests[ndx];
                    tstLocator = getLocator(tst, targetLocator.length);
                    var distance = Math.abs(tstLocator - targetLocator);
                    (void 0 === closest || "" !== tstLocator && distance < closest || bestMatch && !opts.greedy && bestMatch.match.optionality && "master" === bestMatch.match.newBlockMarker && (!tst.match.optionality || !tst.match.newBlockMarker) || bestMatch && bestMatch.match.optionalQuantifier && !tst.match.optionalQuantifier) && (closest = distance, 
                    bestMatch = tst);
                }
                return bestMatch;
            }
            function getTestTemplate(pos, ndxIntlzr, tstPs) {
                return maskset.validPositions[pos] || determineTestTemplate(pos, getTests(pos, ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr, tstPs));
            }
            function getTest(pos, tests) {
                return maskset.validPositions[pos] ? maskset.validPositions[pos] : (tests || getTests(pos))[0];
            }
            function positionCanMatchDefinition(pos, testDefinition, opts) {
                for (var valid = !1, tests = getTests(pos), tndx = 0; tndx < tests.length; tndx++) {
                    if (tests[tndx].match && (!(tests[tndx].match.nativeDef !== testDefinition.match[opts.shiftPositions ? "def" : "nativeDef"] || opts.shiftPositions && testDefinition.match.static) || tests[tndx].match.nativeDef === testDefinition.match.nativeDef)) {
                        valid = !0;
                        break;
                    }
                    if (tests[tndx].match && tests[tndx].match.def === testDefinition.match.nativeDef) {
                        valid = void 0;
                        break;
                    }
                }
                return !1 === valid && void 0 !== maskset.jitOffset[pos] && (valid = positionCanMatchDefinition(pos + maskset.jitOffset[pos], testDefinition, opts)), 
                valid;
            }
            function getTests(pos, ndxIntlzr, tstPs) {
                var maskTokens = maskset.maskToken, testPos = ndxIntlzr ? tstPs : 0, ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [ 0 ], matches = [], insertStop = !1, latestMatch, cacheDependency = ndxIntlzr ? ndxIntlzr.join("") : "";
                function resolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) {
                    function handleMatch(match, loopNdx, quantifierRecurse) {
                        function isFirstMatch(latestMatch, tokenGroup) {
                            var firstMatch = 0 === $.inArray(latestMatch, tokenGroup.matches);
                            return firstMatch || $.each(tokenGroup.matches, function(ndx, match) {
                                if (!0 === match.isQuantifier ? firstMatch = isFirstMatch(latestMatch, tokenGroup.matches[ndx - 1]) : Object.prototype.hasOwnProperty.call(match, "matches") && (firstMatch = isFirstMatch(latestMatch, match)), 
                                firstMatch) return !1;
                            }), firstMatch;
                        }
                        function resolveNdxInitializer(pos, alternateNdx, targetAlternation) {
                            var bestMatch, indexPos;
                            if ((maskset.tests[pos] || maskset.validPositions[pos]) && $.each(maskset.tests[pos] || [ maskset.validPositions[pos] ], function(ndx, lmnt) {
                                if (lmnt.mloc[alternateNdx]) return bestMatch = lmnt, !1;
                                var alternation = void 0 !== targetAlternation ? targetAlternation : lmnt.alternation, ndxPos = void 0 !== lmnt.locator[alternation] ? lmnt.locator[alternation].toString().indexOf(alternateNdx) : -1;
                                (void 0 === indexPos || ndxPos < indexPos) && -1 !== ndxPos && (bestMatch = lmnt, 
                                indexPos = ndxPos);
                            }), bestMatch) {
                                var bestMatchAltIndex = bestMatch.locator[bestMatch.alternation], locator = bestMatch.mloc[alternateNdx] || bestMatch.mloc[bestMatchAltIndex] || bestMatch.locator;
                                return locator.slice((void 0 !== targetAlternation ? targetAlternation : bestMatch.alternation) + 1);
                            }
                            return void 0 !== targetAlternation ? resolveNdxInitializer(pos, alternateNdx) : void 0;
                        }
                        function isSubsetOf(source, target) {
                            function expand(pattern) {
                                for (var expanded = [], start = -1, end, i = 0, l = pattern.length; i < l; i++) if ("-" === pattern.charAt(i)) for (end = pattern.charCodeAt(i + 1); ++start < end; ) expanded.push(String.fromCharCode(start)); else start = pattern.charCodeAt(i), 
                                expanded.push(pattern.charAt(i));
                                return expanded.join("");
                            }
                            return source.match.def === target.match.nativeDef || !(!(opts.regex || source.match.fn instanceof RegExp && target.match.fn instanceof RegExp) || !0 === source.match.static || !0 === target.match.static) && -1 !== expand(target.match.fn.toString().replace(/[[\]/]/g, "")).indexOf(expand(source.match.fn.toString().replace(/[[\]/]/g, "")));
                        }
                        function staticCanMatchDefinition(source, target) {
                            return !0 === source.match.static && !0 !== target.match.static && target.match.fn.test(source.match.def, maskset, pos, !1, opts, !1);
                        }
                        function setMergeLocators(targetMatch, altMatch) {
                            var alternationNdx = targetMatch.alternation, shouldMerge = void 0 === altMatch || alternationNdx === altMatch.alternation && -1 === targetMatch.locator[alternationNdx].toString().indexOf(altMatch.locator[alternationNdx]);
                            if (!shouldMerge && alternationNdx > altMatch.alternation) for (var i = altMatch.alternation; i < alternationNdx; i++) if (targetMatch.locator[i] !== altMatch.locator[i]) {
                                alternationNdx = i, shouldMerge = !0;
                                break;
                            }
                            if (shouldMerge) {
                                targetMatch.mloc = targetMatch.mloc || {};
                                var locNdx = targetMatch.locator[alternationNdx];
                                if (void 0 !== locNdx) {
                                    if ("string" == typeof locNdx && (locNdx = locNdx.split(",")[0]), void 0 === targetMatch.mloc[locNdx] && (targetMatch.mloc[locNdx] = targetMatch.locator.slice()), 
                                    void 0 !== altMatch) {
                                        for (var ndx in altMatch.mloc) "string" == typeof ndx && (ndx = ndx.split(",")[0]), 
                                        void 0 === targetMatch.mloc[ndx] && (targetMatch.mloc[ndx] = altMatch.mloc[ndx]);
                                        targetMatch.locator[alternationNdx] = Object.keys(targetMatch.mloc).join(",");
                                    }
                                    return !0;
                                }
                                targetMatch.alternation = void 0;
                            }
                            return !1;
                        }
                        function isSameLevel(targetMatch, altMatch) {
                            if (targetMatch.locator.length !== altMatch.locator.length) return !1;
                            for (var locNdx = targetMatch.alternation + 1; locNdx < targetMatch.locator.length; locNdx++) if (targetMatch.locator[locNdx] !== altMatch.locator[locNdx]) return !1;
                            return !0;
                        }
                        if (testPos > opts._maxTestPos && void 0 !== quantifierRecurse) throw "Inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. " + maskset.mask;
                        if (testPos === pos && void 0 === match.matches) return matches.push({
                            match: match,
                            locator: loopNdx.reverse(),
                            cd: cacheDependency,
                            mloc: {}
                        }), !0;
                        if (void 0 !== match.matches) {
                            if (match.isGroup && quantifierRecurse !== match) {
                                if (match = handleMatch(maskToken.matches[$.inArray(match, maskToken.matches) + 1], loopNdx, quantifierRecurse), 
                                match) return !0;
                            } else if (match.isOptional) {
                                var optionalToken = match, mtchsNdx = matches.length;
                                if (match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse), 
                                match) {
                                    if ($.each(matches, function(ndx, mtch) {
                                        mtchsNdx <= ndx && (mtch.match.optionality = !0);
                                    }), latestMatch = matches[matches.length - 1].match, void 0 !== quantifierRecurse || !isFirstMatch(latestMatch, optionalToken)) return !0;
                                    insertStop = !0, testPos = pos;
                                }
                            } else if (match.isAlternator) {
                                var alternateToken = match, malternateMatches = [], maltMatches, currentMatches = matches.slice(), loopNdxCnt = loopNdx.length, altIndex = 0 < ndxInitializer.length ? ndxInitializer.shift() : -1;
                                if (-1 === altIndex || "string" == typeof altIndex) {
                                    var currentPos = testPos, ndxInitializerClone = ndxInitializer.slice(), altIndexArr = [], amndx;
                                    if ("string" == typeof altIndex) altIndexArr = altIndex.split(","); else for (amndx = 0; amndx < alternateToken.matches.length; amndx++) altIndexArr.push(amndx.toString());
                                    if (void 0 !== maskset.excludes[pos]) {
                                        for (var altIndexArrClone = altIndexArr.slice(), i = 0, exl = maskset.excludes[pos].length; i < exl; i++) {
                                            var excludeSet = maskset.excludes[pos][i].toString().split(":");
                                            loopNdx.length == excludeSet[1] && altIndexArr.splice(altIndexArr.indexOf(excludeSet[0]), 1);
                                        }
                                        0 === altIndexArr.length && (delete maskset.excludes[pos], altIndexArr = altIndexArrClone);
                                    }
                                    (!0 === opts.keepStatic || isFinite(parseInt(opts.keepStatic)) && currentPos >= opts.keepStatic) && (altIndexArr = altIndexArr.slice(0, 1));
                                    for (var unMatchedAlternation = !1, ndx = 0; ndx < altIndexArr.length; ndx++) {
                                        amndx = parseInt(altIndexArr[ndx]), matches = [], ndxInitializer = "string" == typeof altIndex && resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice(), 
                                        alternateToken.matches[amndx] && handleMatch(alternateToken.matches[amndx], [ amndx ].concat(loopNdx), quantifierRecurse) ? match = !0 : 0 === ndx && (unMatchedAlternation = !0), 
                                        maltMatches = matches.slice(), testPos = currentPos, matches = [];
                                        for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
                                            var altMatch = maltMatches[ndx1], dropMatch = !1;
                                            altMatch.match.jit = altMatch.match.jit || unMatchedAlternation, altMatch.alternation = altMatch.alternation || loopNdxCnt, 
                                            setMergeLocators(altMatch);
                                            for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
                                                var altMatch2 = malternateMatches[ndx2];
                                                if ("string" != typeof altIndex || void 0 !== altMatch.alternation && -1 !== $.inArray(altMatch.locator[altMatch.alternation].toString(), altIndexArr)) {
                                                    if (altMatch.match.nativeDef === altMatch2.match.nativeDef) {
                                                        dropMatch = !0, setMergeLocators(altMatch2, altMatch);
                                                        break;
                                                    }
                                                    if (isSubsetOf(altMatch, altMatch2)) {
                                                        setMergeLocators(altMatch, altMatch2) && (dropMatch = !0, malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch));
                                                        break;
                                                    }
                                                    if (isSubsetOf(altMatch2, altMatch)) {
                                                        setMergeLocators(altMatch2, altMatch);
                                                        break;
                                                    }
                                                    if (staticCanMatchDefinition(altMatch, altMatch2)) {
                                                        isSameLevel(altMatch, altMatch2) || void 0 !== el.inputmask.userOptions.keepStatic ? setMergeLocators(altMatch, altMatch2) && (dropMatch = !0, 
                                                        malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch)) : opts.keepStatic = !0;
                                                        break;
                                                    }
                                                }
                                            }
                                            dropMatch || malternateMatches.push(altMatch);
                                        }
                                    }
                                    matches = currentMatches.concat(malternateMatches), testPos = pos, insertStop = 0 < matches.length, 
                                    match = 0 < malternateMatches.length, ndxInitializer = ndxInitializerClone.slice();
                                } else match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [ altIndex ].concat(loopNdx), quantifierRecurse);
                                if (match) return !0;
                            } else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[$.inArray(match, maskToken.matches) - 1]) for (var qt = match, qndx = 0 < ndxInitializer.length ? ndxInitializer.shift() : 0; qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max) && testPos <= pos; qndx++) {
                                var tokenGroup = maskToken.matches[$.inArray(qt, maskToken.matches) - 1];
                                if (match = handleMatch(tokenGroup, [ qndx ].concat(loopNdx), tokenGroup), match) {
                                    if (latestMatch = matches[matches.length - 1].match, latestMatch.optionalQuantifier = qndx >= qt.quantifier.min, 
                                    latestMatch.jit = (qndx || 1) * tokenGroup.matches.indexOf(latestMatch) >= qt.quantifier.jit, 
                                    latestMatch.optionalQuantifier && isFirstMatch(latestMatch, tokenGroup)) {
                                        insertStop = !0, testPos = pos;
                                        break;
                                    }
                                    return latestMatch.jit && (maskset.jitOffset[pos] = tokenGroup.matches.length - tokenGroup.matches.indexOf(latestMatch)), 
                                    !0;
                                }
                            } else if (match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse), 
                            match) return !0;
                        } else testPos++;
                    }
                    for (var tndx = 0 < ndxInitializer.length ? ndxInitializer.shift() : 0; tndx < maskToken.matches.length; tndx++) if (!0 !== maskToken.matches[tndx].isQuantifier) {
                        var match = handleMatch(maskToken.matches[tndx], [ tndx ].concat(loopNdx), quantifierRecurse);
                        if (match && testPos === pos) return match;
                        if (pos < testPos) break;
                    }
                }
                function mergeLocators(pos, tests) {
                    var locator = [];
                    return $.isArray(tests) || (tests = [ tests ]), 0 < tests.length && (void 0 === tests[0].alternation || !0 === opts.keepStatic ? (locator = determineTestTemplate(pos, tests.slice()).locator.slice(), 
                    0 === locator.length && (locator = tests[0].locator.slice())) : $.each(tests, function(ndx, tst) {
                        if ("" !== tst.def) if (0 === locator.length) locator = tst.locator.slice(); else for (var i = 0; i < locator.length; i++) tst.locator[i] && -1 === locator[i].toString().indexOf(tst.locator[i]) && (locator[i] += "," + tst.locator[i]);
                    })), locator;
                }
                if (-1 < pos && (void 0 === maxLength || pos < maxLength)) {
                    if (void 0 === ndxIntlzr) {
                        for (var previousPos = pos - 1, test; void 0 === (test = maskset.validPositions[previousPos] || maskset.tests[previousPos]) && -1 < previousPos; ) previousPos--;
                        void 0 !== test && -1 < previousPos && (ndxInitializer = mergeLocators(previousPos, test), 
                        cacheDependency = ndxInitializer.join(""), testPos = previousPos);
                    }
                    if (maskset.tests[pos] && maskset.tests[pos][0].cd === cacheDependency) return maskset.tests[pos];
                    for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length; mtndx++) {
                        var match = resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [ mtndx ]);
                        if (match && testPos === pos || pos < testPos) break;
                    }
                }
                return 0 !== matches.length && !insertStop || matches.push({
                    match: {
                        fn: null,
                        static: !0,
                        optionality: !1,
                        casing: null,
                        def: "",
                        placeholder: ""
                    },
                    locator: [],
                    mloc: {},
                    cd: cacheDependency
                }), void 0 !== ndxIntlzr && maskset.tests[pos] ? $.extend(!0, [], matches) : (maskset.tests[pos] = $.extend(!0, [], matches), 
                maskset.tests[pos]);
            }
            function getBufferTemplate() {
                return void 0 === maskset._buffer && (maskset._buffer = getMaskTemplate(!1, 1), 
                void 0 === maskset.buffer && (maskset.buffer = maskset._buffer.slice())), maskset._buffer;
            }
            function getBuffer(noCache) {
                return void 0 !== maskset.buffer && !0 !== noCache || (maskset.buffer = getMaskTemplate(!0, getLastValidPosition(), !0), 
                void 0 === maskset._buffer && (maskset._buffer = maskset.buffer.slice())), maskset.buffer;
            }
            function refreshFromBuffer(start, end, buffer) {
                var i, p, skipOptionalPartCharacter = opts.skipOptionalPartCharacter, bffr = isRTL ? buffer.slice().reverse() : buffer;
                if (opts.skipOptionalPartCharacter = "", !0 === start) resetMaskSet(), maskset.tests = {}, 
                start = 0, end = buffer.length, p = determineNewCaretPosition({
                    begin: 0,
                    end: 0
                }, !1).begin; else {
                    for (i = start; i < end; i++) delete maskset.validPositions[i];
                    p = start;
                }
                var keypress = new $.Event("keypress");
                for (i = start; i < end; i++) {
                    keypress.which = bffr[i].toString().charCodeAt(0), ignorable = !1;
                    var valResult = EventHandlers.keypressEvent.call(el, keypress, !0, !1, !1, p);
                    !1 !== valResult && (p = valResult.forwardPosition);
                }
                opts.skipOptionalPartCharacter = skipOptionalPartCharacter;
            }
            function casing(elem, test, pos) {
                switch (opts.casing || test.casing) {
                  case "upper":
                    elem = elem.toUpperCase();
                    break;

                  case "lower":
                    elem = elem.toLowerCase();
                    break;

                  case "title":
                    var posBefore = maskset.validPositions[pos - 1];
                    elem = 0 === pos || posBefore && posBefore.input === String.fromCharCode(keyCode.SPACE) ? elem.toUpperCase() : elem.toLowerCase();
                    break;

                  default:
                    if ($.isFunction(opts.casing)) {
                        var args = Array.prototype.slice.call(arguments);
                        args.push(maskset.validPositions), elem = opts.casing.apply(this, args);
                    }
                }
                return elem;
            }
            function checkAlternationMatch(altArr1, altArr2, na) {
                for (var altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1), isMatch = !1, naArr = void 0 !== na ? na.split(",") : [], naNdx, i = 0; i < naArr.length; i++) -1 !== (naNdx = altArr1.indexOf(naArr[i])) && altArr1.splice(naNdx, 1);
                for (var alndx = 0; alndx < altArr1.length; alndx++) if (-1 !== $.inArray(altArr1[alndx], altArrC)) {
                    isMatch = !0;
                    break;
                }
                return isMatch;
            }
            function alternate(maskPos, c, strict, fromIsValid, rAltPos, selection) {
                var validPsClone = $.extend(!0, {}, maskset.validPositions), tstClone = $.extend(!0, {}, maskset.tests), lastAlt, alternation, isValidRslt = !1, returnRslt = !1, altPos, prevAltPos, i, validPos, decisionPos, lAltPos = void 0 !== rAltPos ? rAltPos : getLastValidPosition(), nextPos, input, begin, end;
                if (selection && (begin = selection.begin, end = selection.end, selection.begin > selection.end && (begin = selection.end, 
                end = selection.begin)), -1 === lAltPos && void 0 === rAltPos) lastAlt = 0, prevAltPos = getTest(lastAlt), 
                alternation = prevAltPos.alternation; else for (;0 <= lAltPos; lAltPos--) if (altPos = maskset.validPositions[lAltPos], 
                altPos && void 0 !== altPos.alternation) {
                    if (prevAltPos && prevAltPos.locator[altPos.alternation] !== altPos.locator[altPos.alternation]) break;
                    lastAlt = lAltPos, alternation = maskset.validPositions[lastAlt].alternation, prevAltPos = altPos;
                }
                if (void 0 !== alternation) {
                    decisionPos = parseInt(lastAlt), maskset.excludes[decisionPos] = maskset.excludes[decisionPos] || [], 
                    !0 !== maskPos && maskset.excludes[decisionPos].push(getDecisionTaker(prevAltPos) + ":" + prevAltPos.alternation);
                    var validInputs = [], resultPos = -1;
                    for (i = decisionPos; i < getLastValidPosition(void 0, !0) + 1; i++) -1 === resultPos && maskPos <= i && void 0 !== c && (validInputs.push(c), 
                    resultPos = validInputs.length - 1), validPos = maskset.validPositions[i], validPos && !0 !== validPos.generatedInput && (void 0 === selection || i < begin || end <= i) && validInputs.push(validPos.input), 
                    delete maskset.validPositions[i];
                    for (-1 === resultPos && void 0 !== c && (validInputs.push(c), resultPos = validInputs.length - 1); void 0 !== maskset.excludes[decisionPos] && maskset.excludes[decisionPos].length < 10; ) {
                        for (maskset.tests = {}, resetMaskSet(!0), isValidRslt = !0, i = 0; i < validInputs.length && (nextPos = isValidRslt.caret || getLastValidPosition(void 0, !0) + 1, 
                        input = validInputs[i], isValidRslt = isValid(nextPos, input, !1, fromIsValid, !0)); i++) i === resultPos && (returnRslt = isValidRslt), 
                        1 == maskPos && isValidRslt && (returnRslt = {
                            caretPos: i
                        });
                        if (isValidRslt) break;
                        if (resetMaskSet(), prevAltPos = getTest(decisionPos), maskset.validPositions = $.extend(!0, {}, validPsClone), 
                        maskset.tests = $.extend(!0, {}, tstClone), !maskset.excludes[decisionPos]) {
                            returnRslt = alternate(maskPos, c, strict, fromIsValid, decisionPos - 1, selection);
                            break;
                        }
                        var decisionTaker = getDecisionTaker(prevAltPos);
                        if (-1 !== maskset.excludes[decisionPos].indexOf(decisionTaker + ":" + prevAltPos.alternation)) {
                            returnRslt = alternate(maskPos, c, strict, fromIsValid, decisionPos - 1, selection);
                            break;
                        }
                        for (maskset.excludes[decisionPos].push(decisionTaker + ":" + prevAltPos.alternation), 
                        i = decisionPos; i < getLastValidPosition(void 0, !0) + 1; i++) delete maskset.validPositions[i];
                    }
                }
                return returnRslt && !1 === opts.keepStatic || delete maskset.excludes[decisionPos], 
                returnRslt;
            }
            function isValid(pos, c, strict, fromIsValid, fromAlternate, validateOnly) {
                function isSelection(posObj) {
                    return isRTL ? 1 < posObj.begin - posObj.end || posObj.begin - posObj.end == 1 : 1 < posObj.end - posObj.begin || posObj.end - posObj.begin == 1;
                }
                strict = !0 === strict;
                var maskPos = pos;
                function processCommandObject(commandObj) {
                    if (void 0 !== commandObj) {
                        if (void 0 !== commandObj.remove && ($.isArray(commandObj.remove) || (commandObj.remove = [ commandObj.remove ]), 
                        $.each(commandObj.remove.sort(function(a, b) {
                            return b.pos - a.pos;
                        }), function(ndx, lmnt) {
                            revalidateMask({
                                begin: lmnt,
                                end: lmnt + 1
                            });
                        }), commandObj.remove = void 0), void 0 !== commandObj.insert && ($.isArray(commandObj.insert) || (commandObj.insert = [ commandObj.insert ]), 
                        $.each(commandObj.insert.sort(function(a, b) {
                            return a.pos - b.pos;
                        }), function(ndx, lmnt) {
                            "" !== lmnt.c && isValid(lmnt.pos, lmnt.c, void 0 === lmnt.strict || lmnt.strict, void 0 !== lmnt.fromIsValid ? lmnt.fromIsValid : fromIsValid);
                        }), commandObj.insert = void 0), commandObj.refreshFromBuffer && commandObj.buffer) {
                            var refresh = commandObj.refreshFromBuffer;
                            refreshFromBuffer(!0 === refresh ? refresh : refresh.start, refresh.end, commandObj.buffer), 
                            commandObj.refreshFromBuffer = void 0;
                        }
                        void 0 !== commandObj.rewritePosition && (maskPos = commandObj.rewritePosition, 
                        commandObj = !0);
                    }
                    return commandObj;
                }
                function _isValid(position, c, strict) {
                    var rslt = !1;
                    return $.each(getTests(position), function(ndx, tst) {
                        var test = tst.match;
                        if (getBuffer(!0), rslt = null != test.fn ? test.fn.test(c, maskset, position, strict, opts, isSelection(pos)) : (c === test.def || c === opts.skipOptionalPartCharacter) && "" !== test.def && {
                            c: getPlaceholder(position, test, !0) || test.def,
                            pos: position
                        }, !1 !== rslt) {
                            var elem = void 0 !== rslt.c ? rslt.c : c, validatedPos = position;
                            return elem = elem === opts.skipOptionalPartCharacter && !0 === test.static ? getPlaceholder(position, test, !0) || test.def : elem, 
                            rslt = processCommandObject(rslt), !0 !== rslt && void 0 !== rslt.pos && rslt.pos !== position && (validatedPos = rslt.pos), 
                            !0 !== rslt && void 0 === rslt.pos && void 0 === rslt.c ? !1 : (!1 === revalidateMask(pos, $.extend({}, tst, {
                                input: casing(elem, test, validatedPos)
                            }), fromIsValid, validatedPos) && (rslt = !1), !1);
                        }
                    }), rslt;
                }
                void 0 !== pos.begin && (maskPos = isRTL ? pos.end : pos.begin);
                var result = !0, positionsClone = $.extend(!0, {}, maskset.validPositions);
                if (!1 === opts.keepStatic && void 0 !== maskset.excludes[maskPos] && !0 !== fromAlternate && !0 !== fromIsValid) for (var i = maskPos; i < (isRTL ? pos.begin : pos.end); i++) void 0 !== maskset.excludes[i] && (maskset.excludes[i] = void 0, 
                delete maskset.tests[i]);
                if ($.isFunction(opts.preValidation) && !0 !== fromIsValid && !0 !== validateOnly && (result = opts.preValidation.call(el, getBuffer(), maskPos, c, isSelection(pos), opts, maskset, pos, strict || fromAlternate), 
                result = processCommandObject(result)), !0 === result) {
                    if (void 0 === maxLength || maskPos < maxLength) {
                        if (result = _isValid(maskPos, c, strict), (!strict || !0 === fromIsValid) && !1 === result && !0 !== validateOnly) {
                            var currentPosValid = maskset.validPositions[maskPos];
                            if (!currentPosValid || !0 !== currentPosValid.match.static || currentPosValid.match.def !== c && c !== opts.skipOptionalPartCharacter) {
                                if (opts.insertMode || void 0 === maskset.validPositions[seekNext(maskPos)] || pos.end > maskPos) {
                                    var skip = !1;
                                    if (maskset.jitOffset[maskPos] && void 0 === maskset.validPositions[seekNext(maskPos)] && (result = isValid(maskPos + maskset.jitOffset[maskPos], c, !0), 
                                    !1 !== result && (!0 !== fromAlternate && (result.caret = maskPos), skip = !0)), 
                                    pos.end > maskPos && (maskset.validPositions[maskPos] = void 0), !skip && !isMask(maskPos, opts.keepStatic)) for (var nPos = maskPos + 1, snPos = seekNext(maskPos); nPos <= snPos; nPos++) if (result = _isValid(nPos, c, strict), 
                                    !1 !== result) {
                                        result = trackbackPositions(maskPos, void 0 !== result.pos ? result.pos : nPos) || result, 
                                        maskPos = nPos;
                                        break;
                                    }
                                }
                            } else result = {
                                caret: seekNext(maskPos)
                            };
                        }
                    } else result = !1;
                    !1 !== result || !opts.keepStatic || !isComplete(getBuffer()) && 0 !== maskPos || strict || !0 === fromAlternate ? isSelection(pos) && maskset.tests[maskPos] && 1 < maskset.tests[maskPos].length && opts.keepStatic && !strict && !0 !== fromAlternate && (result = alternate(!0)) : result = alternate(maskPos, c, strict, fromIsValid, void 0, pos), 
                    !0 === result && (result = {
                        pos: maskPos
                    });
                }
                if ($.isFunction(opts.postValidation) && !0 !== fromIsValid && !0 !== validateOnly) {
                    var postResult = opts.postValidation.call(el, getBuffer(!0), void 0 !== pos.begin ? isRTL ? pos.end : pos.begin : pos, c, result, opts, maskset, strict);
                    void 0 !== postResult && (result = !0 === postResult ? result : postResult);
                }
                result && void 0 === result.pos && (result.pos = maskPos), !1 === result || !0 === validateOnly ? (resetMaskSet(!0), 
                maskset.validPositions = $.extend(!0, {}, positionsClone)) : trackbackPositions(void 0, maskPos, !0);
                var endResult = processCommandObject(result);
                return endResult;
            }
            function trackbackPositions(originalPos, newPos, fillOnly) {
                if (void 0 === originalPos) for (originalPos = newPos - 1; 0 < originalPos && !maskset.validPositions[originalPos]; originalPos--) ;
                for (var ps = originalPos; ps < newPos; ps++) if (void 0 === maskset.validPositions[ps] && !isMask(ps, !0)) {
                    var vp = 0 == ps ? getTest(ps) : maskset.validPositions[ps - 1];
                    if (vp) {
                        var tests = getTests(ps).slice();
                        "" === tests[tests.length - 1].match.def && tests.pop();
                        var bestMatch = determineTestTemplate(ps, tests), np;
                        if (bestMatch && (!0 !== bestMatch.match.jit || "master" === bestMatch.match.newBlockMarker && (np = maskset.validPositions[ps + 1]) && !0 === np.match.optionalQuantifier) && (bestMatch = $.extend({}, bestMatch, {
                            input: getPlaceholder(ps, bestMatch.match, !0) || bestMatch.match.def
                        }), bestMatch.generatedInput = !0, revalidateMask(ps, bestMatch, !0), !0 !== fillOnly)) {
                            var cvpInput = maskset.validPositions[newPos].input;
                            return maskset.validPositions[newPos] = void 0, isValid(newPos, cvpInput, !0, !0);
                        }
                    }
                }
            }
            function revalidateMask(pos, validTest, fromIsValid, validatedPos) {
                function IsEnclosedStatic(pos, valids, selection) {
                    var posMatch = valids[pos];
                    if (void 0 === posMatch || !0 !== posMatch.match.static || !0 === posMatch.match.optionality || void 0 !== valids[0] && void 0 !== valids[0].alternation) return !1;
                    var prevMatch = selection.begin <= pos - 1 ? valids[pos - 1] && !0 === valids[pos - 1].match.static && valids[pos - 1] : valids[pos - 1], nextMatch = selection.end > pos + 1 ? valids[pos + 1] && !0 === valids[pos + 1].match.static && valids[pos + 1] : valids[pos + 1];
                    return prevMatch && nextMatch;
                }
                var offset = 0, begin = void 0 !== pos.begin ? pos.begin : pos, end = void 0 !== pos.end ? pos.end : pos;
                if (pos.begin > pos.end && (begin = pos.end, end = pos.begin), validatedPos = void 0 !== validatedPos ? validatedPos : begin, 
                begin !== end || opts.insertMode && void 0 !== maskset.validPositions[validatedPos] && void 0 === fromIsValid || void 0 === validTest) {
                    var positionsClone = $.extend(!0, {}, maskset.validPositions), lvp = getLastValidPosition(void 0, !0), i;
                    for (maskset.p = begin, i = lvp; begin <= i; i--) delete maskset.validPositions[i], 
                    void 0 === validTest && delete maskset.tests[i + 1];
                    var valid = !0, j = validatedPos, posMatch = j, t, canMatch;
                    for (validTest && (maskset.validPositions[validatedPos] = $.extend(!0, {}, validTest), 
                    posMatch++, j++), i = validTest ? end : end - 1; i <= lvp; i++) {
                        if (void 0 !== (t = positionsClone[i]) && !0 !== t.generatedInput && (end <= i || begin <= i && IsEnclosedStatic(i, positionsClone, {
                            begin: begin,
                            end: end
                        }))) {
                            for (;"" !== getTest(posMatch).match.def; ) {
                                if (!1 !== (canMatch = positionCanMatchDefinition(posMatch, t, opts)) || "+" === t.match.def) {
                                    "+" === t.match.def && getBuffer(!0);
                                    var result = isValid(posMatch, t.input, "+" !== t.match.def, "+" !== t.match.def);
                                    if (valid = !1 !== result, j = (result.pos || posMatch) + 1, !valid && canMatch) break;
                                } else valid = !1;
                                if (valid) {
                                    void 0 === validTest && t.match.static && i === pos.begin && offset++;
                                    break;
                                }
                                if (!valid && posMatch > maskset.maskLength) break;
                                posMatch++;
                            }
                            "" == getTest(posMatch).match.def && (valid = !1), posMatch = j;
                        }
                        if (!valid) break;
                    }
                    if (!valid) return maskset.validPositions = $.extend(!0, {}, positionsClone), resetMaskSet(!0), 
                    !1;
                } else validTest && getTest(validatedPos).match.cd === validTest.match.cd && (maskset.validPositions[validatedPos] = $.extend(!0, {}, validTest));
                return resetMaskSet(!0), offset;
            }
            function isMask(pos, strict, fuzzy) {
                var test = getTestTemplate(pos).match;
                if ("" === test.def && (test = getTest(pos).match), !0 !== test.static) return test.fn;
                if (!0 === fuzzy && void 0 !== maskset.validPositions[pos] && !0 !== maskset.validPositions[pos].generatedInput) return !0;
                if (!0 !== strict && -1 < pos) {
                    if (fuzzy) {
                        var tests = getTests(pos);
                        return tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0);
                    }
                    var testTemplate = determineTestTemplate(pos, getTests(pos)), testPlaceHolder = getPlaceholder(pos, testTemplate.match);
                    return testTemplate.match.def !== testPlaceHolder;
                }
                return !1;
            }
            function seekNext(pos, newBlock, fuzzy) {
                void 0 === fuzzy && (fuzzy = !0);
                for (var position = pos + 1; "" !== getTest(position).match.def && (!0 === newBlock && (!0 !== getTest(position).match.newBlockMarker || !isMask(position, void 0, !0)) || !0 !== newBlock && !isMask(position, void 0, fuzzy)); ) position++;
                return position;
            }
            function seekPrevious(pos, newBlock) {
                var position = pos, tests;
                if (position <= 0) return 0;
                for (;0 < --position && (!0 === newBlock && !0 !== getTest(position).match.newBlockMarker || !0 !== newBlock && !isMask(position, void 0, !0) && (tests = getTests(position), 
                tests.length < 2 || 2 === tests.length && "" === tests[1].match.def)); ) ;
                return position;
            }
            function writeBuffer(input, buffer, caretPos, event, triggerEvents) {
                if (event && $.isFunction(opts.onBeforeWrite)) {
                    var result = opts.onBeforeWrite.call(inputmask, event, buffer, caretPos, opts);
                    if (result) {
                        if (result.refreshFromBuffer) {
                            var refresh = result.refreshFromBuffer;
                            refreshFromBuffer(!0 === refresh ? refresh : refresh.start, refresh.end, result.buffer || buffer), 
                            buffer = getBuffer(!0);
                        }
                        void 0 !== caretPos && (caretPos = void 0 !== result.caret ? result.caret : caretPos);
                    }
                }
                if (void 0 !== input && (input.inputmask._valueSet(buffer.join("")), void 0 === caretPos || void 0 !== event && "blur" === event.type || caret(input, caretPos, void 0, void 0, void 0 !== event && "keydown" === event.type && (event.keyCode === keyCode.DELETE || event.keyCode === keyCode.BACKSPACE)), 
                !0 === triggerEvents)) {
                    var $input = $(input), nptVal = input.inputmask._valueGet();
                    skipInputEvent = !0, $input.trigger("input"), setTimeout(function() {
                        nptVal === getBufferTemplate().join("") ? $input.trigger("cleared") : !0 === isComplete(buffer) && $input.trigger("complete");
                    }, 0);
                }
            }
            function getPlaceholder(pos, test, returnPL) {
                if (test = test || getTest(pos).match, void 0 !== test.placeholder || !0 === returnPL) return $.isFunction(test.placeholder) ? test.placeholder(opts) : test.placeholder;
                if (!0 !== test.static) return opts.placeholder.charAt(pos % opts.placeholder.length);
                if (-1 < pos && void 0 === maskset.validPositions[pos]) {
                    var tests = getTests(pos), staticAlternations = [], prevTest;
                    if (tests.length > 1 + ("" === tests[tests.length - 1].match.def ? 1 : 0)) for (var i = 0; i < tests.length; i++) if ("" !== tests[i].match.def && !0 !== tests[i].match.optionality && !0 !== tests[i].match.optionalQuantifier && (!0 === tests[i].match.static || void 0 === prevTest || !1 !== tests[i].match.fn.test(prevTest.match.def, maskset, pos, !0, opts)) && (staticAlternations.push(tests[i]), 
                    !0 === tests[i].match.static && (prevTest = tests[i]), 1 < staticAlternations.length && /[0-9a-bA-Z]/.test(staticAlternations[0].match.def))) return opts.placeholder.charAt(pos % opts.placeholder.length);
                }
                return test.def;
            }
            function HandleNativePlaceholder(npt, value) {
                if (ie) {
                    if (npt.inputmask._valueGet() !== value && (npt.placeholder !== value || "" === npt.placeholder)) {
                        var buffer = getBuffer().slice(), nptValue = npt.inputmask._valueGet();
                        if (nptValue !== value) {
                            var lvp = getLastValidPosition();
                            -1 === lvp && nptValue === getBufferTemplate().join("") ? buffer = [] : -1 !== lvp && clearOptionalTail(buffer), 
                            writeBuffer(npt, buffer);
                        }
                    }
                } else npt.placeholder !== value && (npt.placeholder = value, "" === npt.placeholder && npt.removeAttribute("placeholder"));
            }
            function determineNewCaretPosition(selectedCaret, tabbed) {
                function doRadixFocus(clickPos) {
                    if ("" !== opts.radixPoint && 0 !== opts.digits) {
                        var vps = maskset.validPositions;
                        if (void 0 === vps[clickPos] || vps[clickPos].input === getPlaceholder(clickPos)) {
                            if (clickPos < seekNext(-1)) return !0;
                            var radixPos = $.inArray(opts.radixPoint, getBuffer());
                            if (-1 !== radixPos) {
                                for (var vp in vps) if (vps[vp] && radixPos < vp && vps[vp].input !== getPlaceholder(vp)) return !1;
                                return !0;
                            }
                        }
                    }
                    return !1;
                }
                if (tabbed && (isRTL ? selectedCaret.end = selectedCaret.begin : selectedCaret.begin = selectedCaret.end), 
                selectedCaret.begin === selectedCaret.end) {
                    switch (opts.positionCaretOnClick) {
                      case "none":
                        break;

                      case "select":
                        selectedCaret = {
                            begin: 0,
                            end: getBuffer().length
                        };
                        break;

                      case "ignore":
                        selectedCaret.end = selectedCaret.begin = seekNext(getLastValidPosition());
                        break;

                      case "radixFocus":
                        if (doRadixFocus(selectedCaret.begin)) {
                            var radixPos = getBuffer().join("").indexOf(opts.radixPoint);
                            selectedCaret.end = selectedCaret.begin = opts.numericInput ? seekNext(radixPos) : radixPos;
                            break;
                        }

                      default:
                        var clickPosition = selectedCaret.begin, lvclickPosition = getLastValidPosition(clickPosition, !0), lastPosition = seekNext(-1 !== lvclickPosition || isMask(0) ? lvclickPosition : 0);
                        if (clickPosition < lastPosition) selectedCaret.end = selectedCaret.begin = isMask(clickPosition, !0) || isMask(clickPosition - 1, !0) ? clickPosition : seekNext(clickPosition); else {
                            var lvp = maskset.validPositions[lvclickPosition], tt = getTestTemplate(lastPosition, lvp ? lvp.match.locator : void 0, lvp), placeholder = getPlaceholder(lastPosition, tt.match);
                            if ("" !== placeholder && getBuffer()[lastPosition] !== placeholder && !0 !== tt.match.optionalQuantifier && !0 !== tt.match.newBlockMarker || !isMask(lastPosition, opts.keepStatic) && tt.match.def === placeholder) {
                                var newPos = seekNext(lastPosition);
                                (newPos <= clickPosition || clickPosition === lastPosition) && (lastPosition = newPos);
                            }
                            selectedCaret.end = selectedCaret.begin = lastPosition;
                        }
                    }
                    return selectedCaret;
                }
            }
            var EventRuler = {
                on: function on(input, eventName, eventHandler) {
                    var ev = function ev(e) {
                        e.originalEvent && (e = e.originalEvent || e, arguments[0] = e);
                        var that = this, args;
                        if (void 0 === that.inputmask && "FORM" !== this.nodeName) {
                            var imOpts = $.data(that, "_inputmask_opts");
                            imOpts ? new Inputmask(imOpts).mask(that) : EventRuler.off(that);
                        } else {
                            if ("setvalue" === e.type || "FORM" === this.nodeName || !(that.disabled || that.readOnly && !("keydown" === e.type && e.ctrlKey && 67 === e.keyCode || !1 === opts.tabThrough && e.keyCode === keyCode.TAB))) {
                                switch (e.type) {
                                  case "input":
                                    if (!0 === skipInputEvent || e.inputType && "insertCompositionText" === e.inputType) return skipInputEvent = !1, 
                                    e.preventDefault();
                                    break;

                                  case "keydown":
                                    skipKeyPressEvent = !1, skipInputEvent = !1;
                                    break;

                                  case "keypress":
                                    if (!0 === skipKeyPressEvent) return e.preventDefault();
                                    skipKeyPressEvent = !0;
                                    break;

                                  case "click":
                                  case "focus":
                                    return validationEvent ? (validationEvent = !1, input.blur(), HandleNativePlaceholder(input, (isRTL ? getBufferTemplate().slice().reverse() : getBufferTemplate()).join("")), 
                                    setTimeout(function() {
                                        input.focus();
                                    }, 3e3)) : (args = arguments, setTimeout(function() {
                                        input.inputmask && eventHandler.apply(that, args);
                                    }, 0)), !1;
                                }
                                var returnVal = eventHandler.apply(that, arguments);
                                return !1 === returnVal && (e.preventDefault(), e.stopPropagation()), returnVal;
                            }
                            e.preventDefault();
                        }
                    };
                    input.inputmask.events[eventName] = input.inputmask.events[eventName] || [], input.inputmask.events[eventName].push(ev), 
                    -1 !== $.inArray(eventName, [ "submit", "reset" ]) ? null !== input.form && $(input.form).on(eventName, ev) : $(input).on(eventName, ev);
                },
                off: function off(input, event) {
                    var events;
                    input.inputmask && input.inputmask.events && (event ? (events = [], events[event] = input.inputmask.events[event]) : events = input.inputmask.events, 
                    $.each(events, function(eventName, evArr) {
                        for (;0 < evArr.length; ) {
                            var ev = evArr.pop();
                            -1 !== $.inArray(eventName, [ "submit", "reset" ]) ? null !== input.form && $(input.form).off(eventName, ev) : $(input).off(eventName, ev);
                        }
                        delete input.inputmask.events[eventName];
                    }));
                }
            }, EventHandlers = {
                keydownEvent: function keydownEvent(e) {
                    var input = this, $input = $(input), k = e.keyCode, pos = caret(input), kdResult = opts.onKeyDown.call(this, e, getBuffer(), pos, opts);
                    if (void 0 !== kdResult) return kdResult;
                    if (k === keyCode.BACKSPACE || k === keyCode.DELETE || iphone && k === keyCode.BACKSPACE_SAFARI || e.ctrlKey && k === keyCode.X && !("oncut" in input)) e.preventDefault(), 
                    handleRemove(input, k, pos), writeBuffer(input, getBuffer(!0), maskset.p, e, input.inputmask._valueGet() !== getBuffer().join("")); else if (k === keyCode.END || k === keyCode.PAGE_DOWN) {
                        e.preventDefault();
                        var caretPos = seekNext(getLastValidPosition());
                        caret(input, e.shiftKey ? pos.begin : caretPos, caretPos, !0);
                    } else k === keyCode.HOME && !e.shiftKey || k === keyCode.PAGE_UP ? (e.preventDefault(), 
                    caret(input, 0, e.shiftKey ? pos.begin : 0, !0)) : (opts.undoOnEscape && k === keyCode.ESCAPE || 90 === k && e.ctrlKey) && !0 !== e.altKey ? (checkVal(input, !0, !1, undoValue.split("")), 
                    $input.trigger("click")) : !0 === opts.tabThrough && k === keyCode.TAB ? (!0 === e.shiftKey ? (!0 === getTest(pos.begin).match.static && (pos.begin = seekNext(pos.begin)), 
                    pos.end = seekPrevious(pos.begin, !0), pos.begin = seekPrevious(pos.end, !0)) : (pos.begin = seekNext(pos.begin, !0), 
                    pos.end = seekNext(pos.begin, !0), pos.end < maskset.maskLength && pos.end--), pos.begin < maskset.maskLength && (e.preventDefault(), 
                    caret(input, pos.begin, pos.end))) : e.shiftKey || opts.insertModeVisual && !1 === opts.insertMode && (k === keyCode.RIGHT ? setTimeout(function() {
                        var caretPos = caret(input);
                        caret(input, caretPos.begin);
                    }, 0) : k === keyCode.LEFT && setTimeout(function() {
                        var caretPos_begin = translatePosition(input.inputmask.caretPos.begin), caretPos_end = translatePosition(input.inputmask.caretPos.end);
                        caret(input, isRTL ? caretPos_begin + (caretPos_begin === maskset.maskLength ? 0 : 1) : caretPos_begin - (0 === caretPos_begin ? 0 : 1));
                    }, 0));
                    ignorable = -1 !== $.inArray(k, opts.ignorables);
                },
                keypressEvent: function keypressEvent(e, checkval, writeOut, strict, ndx) {
                    var input = this, $input = $(input), k = e.which || e.charCode || e.keyCode;
                    if (!(!0 === checkval || e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable)) return k === keyCode.ENTER && undoValue !== getBuffer().join("") && (undoValue = getBuffer().join(""), 
                    setTimeout(function() {
                        $input.trigger("change");
                    }, 0)), skipInputEvent = !0, !0;
                    if (k) {
                        44 !== k && 46 !== k || 3 !== e.location || "" === opts.radixPoint || (k = opts.radixPoint.charCodeAt(0));
                        var pos = checkval ? {
                            begin: ndx,
                            end: ndx
                        } : caret(input), forwardPosition, c = String.fromCharCode(k);
                        maskset.writeOutBuffer = !0;
                        var valResult = isValid(pos, c, strict);
                        if (!1 !== valResult && (resetMaskSet(!0), forwardPosition = void 0 !== valResult.caret ? valResult.caret : seekNext(valResult.pos.begin ? valResult.pos.begin : valResult.pos), 
                        maskset.p = forwardPosition), forwardPosition = opts.numericInput && void 0 === valResult.caret ? seekPrevious(forwardPosition) : forwardPosition, 
                        !1 !== writeOut && (setTimeout(function() {
                            opts.onKeyValidation.call(input, k, valResult);
                        }, 0), maskset.writeOutBuffer && !1 !== valResult)) {
                            var buffer = getBuffer();
                            writeBuffer(input, buffer, forwardPosition, e, !0 !== checkval);
                        }
                        if (e.preventDefault(), checkval) return !1 !== valResult && (valResult.forwardPosition = forwardPosition), 
                        valResult;
                    }
                },
                pasteEvent: function pasteEvent(e) {
                    var input = this, inputValue = this.inputmask._valueGet(!0), caretPos = caret(this), tempValue;
                    isRTL && (tempValue = caretPos.end, caretPos.end = caretPos.begin, caretPos.begin = tempValue);
                    var valueBeforeCaret = inputValue.substr(0, caretPos.begin), valueAfterCaret = inputValue.substr(caretPos.end, inputValue.length);
                    if (valueBeforeCaret == (isRTL ? getBufferTemplate().slice().reverse() : getBufferTemplate()).slice(0, caretPos.begin).join("") && (valueBeforeCaret = ""), 
                    valueAfterCaret == (isRTL ? getBufferTemplate().slice().reverse() : getBufferTemplate()).slice(caretPos.end).join("") && (valueAfterCaret = ""), 
                    window.clipboardData && window.clipboardData.getData) inputValue = valueBeforeCaret + window.clipboardData.getData("Text") + valueAfterCaret; else {
                        if (!e.clipboardData || !e.clipboardData.getData) return !0;
                        inputValue = valueBeforeCaret + e.clipboardData.getData("text/plain") + valueAfterCaret;
                    }
                    var pasteValue = inputValue;
                    if ($.isFunction(opts.onBeforePaste)) {
                        if (pasteValue = opts.onBeforePaste.call(inputmask, inputValue, opts), !1 === pasteValue) return e.preventDefault();
                        pasteValue = pasteValue || inputValue;
                    }
                    return checkVal(this, !1, !1, pasteValue.toString().split("")), writeBuffer(this, getBuffer(), seekNext(getLastValidPosition()), e, undoValue !== getBuffer().join("")), 
                    e.preventDefault();
                },
                inputFallBackEvent: function inputFallBackEvent(e) {
                    function ieMobileHandler(input, inputValue, caretPos) {
                        if (iemobile) {
                            var inputChar = inputValue.replace(getBuffer().join(""), "");
                            if (1 === inputChar.length) {
                                var iv = inputValue.split("");
                                iv.splice(caretPos.begin, 0, inputChar), inputValue = iv.join("");
                            }
                        }
                        return inputValue;
                    }
                    function analyseChanges(inputValue, buffer, caretPos) {
                        for (var frontPart = inputValue.substr(0, caretPos.begin).split(""), backPart = inputValue.substr(caretPos.begin).split(""), frontBufferPart = buffer.substr(0, caretPos.begin).split(""), backBufferPart = buffer.substr(caretPos.begin).split(""), fpl = frontPart.length >= frontBufferPart.length ? frontPart.length : frontBufferPart.length, bpl = backPart.length >= backBufferPart.length ? backPart.length : backBufferPart.length, bl, i, action = "", data = [], marker = "~", placeholder; frontPart.length < fpl; ) frontPart.push("~");
                        for (;frontBufferPart.length < fpl; ) frontBufferPart.push("~");
                        for (;backPart.length < bpl; ) backPart.unshift("~");
                        for (;backBufferPart.length < bpl; ) backBufferPart.unshift("~");
                        var newBuffer = frontPart.concat(backPart), oldBuffer = frontBufferPart.concat(backBufferPart);
                        for (i = 0, bl = newBuffer.length; i < bl; i++) switch (placeholder = getPlaceholder(translatePosition(i)), 
                        action) {
                          case "insertText":
                            oldBuffer[i - 1] === newBuffer[i] && caretPos.begin == newBuffer.length - 1 && data.push(newBuffer[i]), 
                            i = bl;
                            break;

                          case "insertReplacementText":
                            "~" === newBuffer[i] ? caretPos.end++ : i = bl;
                            break;

                          case "deleteContentBackward":
                            "~" === newBuffer[i] ? caretPos.end++ : i = bl;
                            break;

                          default:
                            newBuffer[i] !== oldBuffer[i] && ("~" !== newBuffer[i + 1] && newBuffer[i + 1] !== placeholder && void 0 !== newBuffer[i + 1] || (oldBuffer[i] !== placeholder || "~" !== oldBuffer[i + 1]) && "~" !== oldBuffer[i] ? "~" === oldBuffer[i + 1] && oldBuffer[i] === newBuffer[i + 1] ? (action = "insertText", 
                            data.push(newBuffer[i]), caretPos.begin--, caretPos.end--) : newBuffer[i] !== placeholder && "~" !== newBuffer[i] && ("~" === newBuffer[i + 1] || oldBuffer[i] !== newBuffer[i] && oldBuffer[i + 1] === newBuffer[i + 1]) ? (action = "insertReplacementText", 
                            data.push(newBuffer[i]), caretPos.begin--) : "~" === newBuffer[i] ? (action = "deleteContentBackward", 
                            !isMask(translatePosition(i), !0) && oldBuffer[i] !== opts.radixPoint || caretPos.end++) : i = bl : (action = "insertText", 
                            data.push(newBuffer[i]), caretPos.begin--, caretPos.end--));
                            break;
                        }
                        return {
                            action: action,
                            data: data,
                            caret: caretPos
                        };
                    }
                    var input = this, inputValue = input.inputmask._valueGet(!0), buffer = (isRTL ? getBuffer().slice().reverse() : getBuffer()).join(""), caretPos = caret(input, void 0, void 0, !0);
                    if (buffer !== inputValue) {
                        inputValue = ieMobileHandler(input, inputValue, caretPos);
                        var changes = analyseChanges(inputValue, buffer, caretPos);
                        switch ((input.inputmask.shadowRoot || document).activeElement !== input && input.focus(), 
                        writeBuffer(input, getBuffer()), caret(input, caretPos.begin, caretPos.end, !0), 
                        changes.action) {
                          case "insertText":
                          case "insertReplacementText":
                            $.each(changes.data, function(ndx, entry) {
                                var keypress = new $.Event("keypress");
                                keypress.which = entry.charCodeAt(0), ignorable = !1, EventHandlers.keypressEvent.call(input, keypress);
                            }), setTimeout(function() {
                                $el.trigger("keyup");
                            }, 0);
                            break;

                          case "deleteContentBackward":
                            var keydown = new $.Event("keydown");
                            keydown.keyCode = keyCode.BACKSPACE, EventHandlers.keydownEvent.call(input, keydown);
                            break;

                          default:
                            applyInputValue(input, inputValue);
                            break;
                        }
                        e.preventDefault();
                    }
                },
                compositionendEvent: function compositionendEvent(e) {
                    $el.trigger("input");
                },
                setValueEvent: function setValueEvent(e, argument_1, argument_2) {
                    var input = this, value = e && e.detail ? e.detail[0] : argument_1;
                    void 0 === value && (value = this.inputmask._valueGet(!0)), applyInputValue(this, value), 
                    (e.detail && void 0 !== e.detail[1] || void 0 !== argument_2) && caret(this, e.detail ? e.detail[1] : argument_2);
                },
                focusEvent: function focusEvent(e) {
                    var input = this, nptValue = this.inputmask._valueGet();
                    opts.showMaskOnFocus && nptValue !== getBuffer().join("") && writeBuffer(this, getBuffer(), seekNext(getLastValidPosition())), 
                    !0 !== opts.positionCaretOnTab || !1 !== mouseEnter || isComplete(getBuffer()) && -1 !== getLastValidPosition() || EventHandlers.clickEvent.apply(this, [ e, !0 ]), 
                    undoValue = getBuffer().join("");
                },
                invalidEvent: function invalidEvent(e) {
                    validationEvent = !0;
                },
                mouseleaveEvent: function mouseleaveEvent() {
                    var input = this;
                    mouseEnter = !1, opts.clearMaskOnLostFocus && (this.inputmask.shadowRoot || document).activeElement !== this && HandleNativePlaceholder(this, originalPlaceholder);
                },
                clickEvent: function clickEvent(e, tabbed) {
                    var input = this;
                    if ((this.inputmask.shadowRoot || document).activeElement === this) {
                        var newCaretPosition = determineNewCaretPosition(caret(this), tabbed);
                        void 0 !== newCaretPosition && caret(this, newCaretPosition);
                    }
                },
                cutEvent: function cutEvent(e) {
                    var input = this, pos = caret(this), clipboardData = window.clipboardData || e.clipboardData, clipData = isRTL ? getBuffer().slice(pos.end, pos.begin) : getBuffer().slice(pos.begin, pos.end);
                    clipboardData.setData("text", isRTL ? clipData.reverse().join("") : clipData.join("")), 
                    document.execCommand && document.execCommand("copy"), handleRemove(this, keyCode.DELETE, pos), 
                    writeBuffer(this, getBuffer(), maskset.p, e, undoValue !== getBuffer().join(""));
                },
                blurEvent: function blurEvent(e) {
                    var $input = $(this), input = this;
                    if (this.inputmask) {
                        HandleNativePlaceholder(this, originalPlaceholder);
                        var nptValue = this.inputmask._valueGet(), buffer = getBuffer().slice();
                        "" !== nptValue && (opts.clearMaskOnLostFocus && (-1 === getLastValidPosition() && nptValue === getBufferTemplate().join("") ? buffer = [] : clearOptionalTail(buffer)), 
                        !1 === isComplete(buffer) && (setTimeout(function() {
                            $input.trigger("incomplete");
                        }, 0), opts.clearIncomplete && (resetMaskSet(), buffer = opts.clearMaskOnLostFocus ? [] : getBufferTemplate().slice())), 
                        writeBuffer(this, buffer, void 0, e)), undoValue !== getBuffer().join("") && (undoValue = getBuffer().join(""), 
                        $input.trigger("change"));
                    }
                },
                mouseenterEvent: function mouseenterEvent() {
                    var input = this;
                    mouseEnter = !0, (this.inputmask.shadowRoot || document).activeElement !== this && (null == originalPlaceholder && this.placeholder !== originalPlaceholder && (originalPlaceholder = this.placeholder), 
                    opts.showMaskOnHover && HandleNativePlaceholder(this, (isRTL ? getBufferTemplate().slice().reverse() : getBufferTemplate()).join("")));
                },
                submitEvent: function submitEvent() {
                    undoValue !== getBuffer().join("") && $el.trigger("change"), opts.clearMaskOnLostFocus && -1 === getLastValidPosition() && el.inputmask._valueGet && el.inputmask._valueGet() === getBufferTemplate().join("") && el.inputmask._valueSet(""), 
                    opts.clearIncomplete && !1 === isComplete(getBuffer()) && el.inputmask._valueSet(""), 
                    opts.removeMaskOnSubmit && (el.inputmask._valueSet(el.inputmask.unmaskedvalue(), !0), 
                    setTimeout(function() {
                        writeBuffer(el, getBuffer());
                    }, 0));
                },
                resetEvent: function resetEvent() {
                    el.inputmask.refreshValue = !0, setTimeout(function() {
                        applyInputValue(el, el.inputmask._valueGet(!0));
                    }, 0);
                }
            }, valueBuffer;
            function checkVal(input, writeOut, strict, nptvl, initiatingEvent) {
                var inputmask = this || input.inputmask, inputValue = nptvl.slice(), charCodes = "", initialNdx = -1, result = void 0;
                function isTemplateMatch(ndx, charCodes) {
                    for (var targetTemplate = getMaskTemplate(!0, 0).slice(ndx, seekNext(ndx)).join("").replace(/'/g, ""), charCodeNdx = targetTemplate.indexOf(charCodes); 0 < charCodeNdx && " " === targetTemplate[charCodeNdx - 1]; ) charCodeNdx--;
                    var match = 0 === charCodeNdx && !isMask(ndx) && (getTest(ndx).match.nativeDef === charCodes.charAt(0) || !0 === getTest(ndx).match.static && getTest(ndx).match.nativeDef === "'" + charCodes.charAt(0) || " " === getTest(ndx).match.nativeDef && (getTest(ndx + 1).match.nativeDef === charCodes.charAt(0) || !0 === getTest(ndx + 1).match.static && getTest(ndx + 1).match.nativeDef === "'" + charCodes.charAt(0)));
                    if (!match && 0 < charCodeNdx && !isMask(ndx, !1, !0)) {
                        var nextPos = seekNext(ndx);
                        inputmask.caretPos.begin < nextPos && (inputmask.caretPos = {
                            begin: nextPos
                        });
                    }
                    return match;
                }
                resetMaskSet(), maskset.tests = {}, initialNdx = opts.radixPoint ? determineNewCaretPosition({
                    begin: 0,
                    end: 0
                }).begin : 0, maskset.p = initialNdx, inputmask.caretPos = {
                    begin: initialNdx
                };
                var staticMatches = [], prevCaretPos = inputmask.caretPos;
                if ($.each(inputValue, function(ndx, charCode) {
                    if (void 0 !== charCode) if (void 0 === maskset.validPositions[ndx] && inputValue[ndx] === getPlaceholder(ndx) && isMask(ndx, !0) && !1 === isValid(ndx, inputValue[ndx], !0, void 0, void 0, !0)) maskset.p++; else {
                        var keypress = new $.Event("_checkval");
                        keypress.which = charCode.toString().charCodeAt(0), charCodes += charCode;
                        var lvp = getLastValidPosition(void 0, !0);
                        isTemplateMatch(initialNdx, charCodes) ? result = EventHandlers.keypressEvent.call(input, keypress, !0, !1, strict, lvp + 1) : (result = EventHandlers.keypressEvent.call(input, keypress, !0, !1, strict, inputmask.caretPos.begin), 
                        result && (initialNdx = inputmask.caretPos.begin + 1, charCodes = "")), result ? (void 0 !== result.pos && maskset.validPositions[result.pos] && !0 === maskset.validPositions[result.pos].match.static && void 0 === maskset.validPositions[result.pos].alternation && (staticMatches.push(result.pos), 
                        isRTL || (result.forwardPosition = result.pos + 1)), writeBuffer(void 0, getBuffer(), result.forwardPosition, keypress, !1), 
                        inputmask.caretPos = {
                            begin: result.forwardPosition,
                            end: result.forwardPosition
                        }, prevCaretPos = inputmask.caretPos) : inputmask.caretPos = prevCaretPos;
                    }
                }), 0 < staticMatches.length) {
                    var sndx, validPos, nextValid = seekNext(-1, void 0, !1);
                    if (!isComplete(getBuffer()) && staticMatches.length <= nextValid || isComplete(getBuffer()) && 0 < staticMatches.length && staticMatches.length !== nextValid && 0 === staticMatches[0]) for (var nextSndx = nextValid; void 0 !== (sndx = staticMatches.shift()); ) {
                        var keypress = new $.Event("_checkval");
                        if (validPos = maskset.validPositions[sndx], validPos.generatedInput = !0, keypress.which = validPos.input.charCodeAt(0), 
                        result = EventHandlers.keypressEvent.call(input, keypress, !0, !1, strict, nextSndx), 
                        result && void 0 !== result.pos && result.pos !== sndx && maskset.validPositions[result.pos] && !0 === maskset.validPositions[result.pos].match.static) staticMatches.push(result.pos); else if (!result) break;
                        nextSndx++;
                    } else for (;sndx = staticMatches.pop(); ) validPos = maskset.validPositions[sndx], 
                    validPos && (validPos.generatedInput = !0);
                }
                if (writeOut) for (var vndx in writeBuffer(input, getBuffer(), result ? result.forwardPosition : void 0, initiatingEvent || new $.Event("checkval"), initiatingEvent && "input" === initiatingEvent.type), 
                maskset.validPositions) !0 !== maskset.validPositions[vndx].match.generated && delete maskset.validPositions[vndx].generatedInput;
            }
            function unmaskedvalue(input) {
                if (input) {
                    if (void 0 === input.inputmask) return input.value;
                    input.inputmask && input.inputmask.refreshValue && applyInputValue(input, input.inputmask._valueGet(!0));
                }
                var umValue = [], vps = maskset.validPositions;
                for (var pndx in vps) vps[pndx] && vps[pndx].match && (1 != vps[pndx].match.static || !0 !== vps[pndx].generatedInput) && umValue.push(vps[pndx].input);
                var unmaskedValue = 0 === umValue.length ? "" : (isRTL ? umValue.reverse() : umValue).join("");
                if ($.isFunction(opts.onUnMask)) {
                    var bufferValue = (isRTL ? getBuffer().slice().reverse() : getBuffer()).join("");
                    unmaskedValue = opts.onUnMask.call(inputmask, bufferValue, unmaskedValue, opts);
                }
                return unmaskedValue;
            }
            function translatePosition(pos) {
                return !isRTL || "number" != typeof pos || opts.greedy && "" === opts.placeholder || !el || (pos = el.inputmask._valueGet().length - pos), 
                pos;
            }
            function caret(input, begin, end, notranslate, isDelete) {
                var range;
                if (void 0 === begin) return "selectionStart" in input && "selectionEnd" in input ? (begin = input.selectionStart, 
                end = input.selectionEnd) : window.getSelection ? (range = window.getSelection().getRangeAt(0), 
                range.commonAncestorContainer.parentNode !== input && range.commonAncestorContainer !== input || (begin = range.startOffset, 
                end = range.endOffset)) : document.selection && document.selection.createRange && (range = document.selection.createRange(), 
                begin = 0 - range.duplicate().moveStart("character", -input.inputmask._valueGet().length), 
                end = begin + range.text.length), {
                    begin: notranslate ? begin : translatePosition(begin),
                    end: notranslate ? end : translatePosition(end)
                };
                if ($.isArray(begin) && (end = isRTL ? begin[0] : begin[1], begin = isRTL ? begin[1] : begin[0]), 
                void 0 !== begin.begin && (end = isRTL ? begin.begin : begin.end, begin = isRTL ? begin.end : begin.begin), 
                "number" == typeof begin) {
                    begin = notranslate ? begin : translatePosition(begin), end = notranslate ? end : translatePosition(end), 
                    end = "number" == typeof end ? end : begin;
                    var scrollCalc = parseInt(((input.ownerDocument.defaultView || window).getComputedStyle ? (input.ownerDocument.defaultView || window).getComputedStyle(input, null) : input.currentStyle).fontSize) * end;
                    if (input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0, input.inputmask.caretPos = {
                        begin: begin,
                        end: end
                    }, opts.insertModeVisual && !1 === opts.insertMode && begin === end && (isDelete || end++), 
                    input === (input.inputmask.shadowRoot || document).activeElement) if ("setSelectionRange" in input) input.setSelectionRange(begin, end); else if (window.getSelection) {
                        if (range = document.createRange(), void 0 === input.firstChild || null === input.firstChild) {
                            var textNode = document.createTextNode("");
                            input.appendChild(textNode);
                        }
                        range.setStart(input.firstChild, begin < input.inputmask._valueGet().length ? begin : input.inputmask._valueGet().length), 
                        range.setEnd(input.firstChild, end < input.inputmask._valueGet().length ? end : input.inputmask._valueGet().length), 
                        range.collapse(!0);
                        var sel = window.getSelection();
                        sel.removeAllRanges(), sel.addRange(range);
                    } else input.createTextRange && (range = input.createTextRange(), range.collapse(!0), 
                    range.moveEnd("character", end), range.moveStart("character", begin), range.select());
                }
            }
            function determineLastRequiredPosition(returnDefinition) {
                var buffer = getMaskTemplate(!0, getLastValidPosition(), !0, !0), bl = buffer.length, pos, lvp = getLastValidPosition(), positions = {}, lvTest = maskset.validPositions[lvp], ndxIntlzr = void 0 !== lvTest ? lvTest.locator.slice() : void 0, testPos;
                for (pos = lvp + 1; pos < buffer.length; pos++) testPos = getTestTemplate(pos, ndxIntlzr, pos - 1), 
                ndxIntlzr = testPos.locator.slice(), positions[pos] = $.extend(!0, {}, testPos);
                var lvTestAlt = lvTest && void 0 !== lvTest.alternation ? lvTest.locator[lvTest.alternation] : void 0;
                for (pos = bl - 1; lvp < pos && (testPos = positions[pos], (testPos.match.optionality || testPos.match.optionalQuantifier && testPos.match.newBlockMarker || lvTestAlt && (lvTestAlt !== positions[pos].locator[lvTest.alternation] && 1 != testPos.match.static || !0 === testPos.match.static && testPos.locator[lvTest.alternation] && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAlt.toString().split(",")) && "" !== getTests(pos)[0].def)) && buffer[pos] === getPlaceholder(pos, testPos.match)); pos--) bl--;
                return returnDefinition ? {
                    l: bl,
                    def: positions[bl] ? positions[bl].match : void 0
                } : bl;
            }
            function clearOptionalTail(buffer) {
                buffer.length = 0;
                for (var template = getMaskTemplate(!0, 0, !0, void 0, !0), lmnt; void 0 !== (lmnt = template.shift()); ) buffer.push(lmnt);
                return buffer;
            }
            function isComplete(buffer) {
                if ($.isFunction(opts.isComplete)) return opts.isComplete(buffer, opts);
                if ("*" !== opts.repeat) {
                    var complete = !1, lrp = determineLastRequiredPosition(!0), aml = seekPrevious(lrp.l);
                    if (void 0 === lrp.def || lrp.def.newBlockMarker || lrp.def.optionality || lrp.def.optionalQuantifier) {
                        complete = !0;
                        for (var i = 0; i <= aml; i++) {
                            var test = getTestTemplate(i).match;
                            if (!0 !== test.static && void 0 === maskset.validPositions[i] && !0 !== test.optionality && !0 !== test.optionalQuantifier || !0 === test.static && buffer[i] !== getPlaceholder(i, test)) {
                                complete = !1;
                                break;
                            }
                        }
                    }
                    return complete;
                }
            }
            function handleRemove(input, k, pos, strict, fromIsValid) {
                if ((opts.numericInput || isRTL) && (k === keyCode.BACKSPACE ? k = keyCode.DELETE : k === keyCode.DELETE && (k = keyCode.BACKSPACE), 
                isRTL)) {
                    var pend = pos.end;
                    pos.end = pos.begin, pos.begin = pend;
                }
                var lvp = getLastValidPosition(void 0, !0), offset;
                if (pos.end >= getBuffer().length && lvp >= pos.end && (pos.end = lvp + 1), k === keyCode.BACKSPACE ? pos.end - pos.begin < 1 && (pos.begin = seekPrevious(pos.begin)) : k === keyCode.DELETE && pos.begin === pos.end && (pos.end = isMask(pos.end, !0, !0) ? pos.end + 1 : seekNext(pos.end) + 1), 
                !1 !== (offset = revalidateMask(pos))) {
                    if (!0 !== strict && !1 !== opts.keepStatic || null !== opts.regex && -1 !== getTest(pos.begin).match.def.indexOf("|")) {
                        var result = alternate(!0);
                        if (result) {
                            var newPos = void 0 !== result.caret ? result.caret : result.pos ? seekNext(result.pos.begin ? result.pos.begin : result.pos) : getLastValidPosition(-1, !0);
                            (k !== keyCode.DELETE || pos.begin > newPos) && pos.begin;
                        }
                    }
                    !0 !== strict && (maskset.p = k === keyCode.DELETE ? pos.begin + offset : pos.begin);
                }
            }
            function applyInputValue(input, value) {
                input.inputmask.refreshValue = !1, $.isFunction(opts.onBeforeMask) && (value = opts.onBeforeMask.call(inputmask, value, opts) || value), 
                value = value.toString().split(""), checkVal(input, !0, !1, value), undoValue = getBuffer().join(""), 
                (opts.clearMaskOnLostFocus || opts.clearIncomplete) && input.inputmask._valueGet() === getBufferTemplate().join("") && -1 === getLastValidPosition() && input.inputmask._valueSet("");
            }
            function mask(elem) {
                function isElementTypeSupported(input, opts) {
                    function patchValueProperty(npt) {
                        var valueGet, valueSet;
                        function patchValhook(type) {
                            if ($.valHooks && (void 0 === $.valHooks[type] || !0 !== $.valHooks[type].inputmaskpatch)) {
                                var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function(elem) {
                                    return elem.value;
                                }, valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function(elem, value) {
                                    return elem.value = value, elem;
                                };
                                $.valHooks[type] = {
                                    get: function get(elem) {
                                        if (elem.inputmask) {
                                            if (elem.inputmask.opts.autoUnmask) return elem.inputmask.unmaskedvalue();
                                            var result = valhookGet(elem);
                                            return -1 !== getLastValidPosition(void 0, void 0, elem.inputmask.maskset.validPositions) || !0 !== opts.nullable ? result : "";
                                        }
                                        return valhookGet(elem);
                                    },
                                    set: function set(elem, value) {
                                        var result = valhookSet(elem, value);
                                        return elem.inputmask && applyInputValue(elem, value), result;
                                    },
                                    inputmaskpatch: !0
                                };
                            }
                        }
                        function getter() {
                            return this.inputmask ? this.inputmask.opts.autoUnmask ? this.inputmask.unmaskedvalue() : -1 !== getLastValidPosition() || !0 !== opts.nullable ? (this.inputmask.shadowRoot || document.activeElement) === this && opts.clearMaskOnLostFocus ? (isRTL ? clearOptionalTail(getBuffer().slice()).reverse() : clearOptionalTail(getBuffer().slice())).join("") : valueGet.call(this) : "" : valueGet.call(this);
                        }
                        function setter(value) {
                            valueSet.call(this, value), this.inputmask && applyInputValue(this, value);
                        }
                        function installNativeValueSetFallback(npt) {
                            EventRuler.on(npt, "mouseenter", function() {
                                var input = this, value = this.inputmask._valueGet(!0);
                                value !== (isRTL ? getBuffer().reverse() : getBuffer()).join("") && applyInputValue(this, value);
                            });
                        }
                        if (!npt.inputmask.__valueGet) {
                            if (!0 !== opts.noValuePatching) {
                                if (Object.getOwnPropertyDescriptor) {
                                    "function" != typeof Object.getPrototypeOf && (Object.getPrototypeOf = "object" === _typeof("test".__proto__) ? function(object) {
                                        return object.__proto__;
                                    } : function(object) {
                                        return object.constructor.prototype;
                                    });
                                    var valueProperty = Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(npt), "value") : void 0;
                                    valueProperty && valueProperty.get && valueProperty.set ? (valueGet = valueProperty.get, 
                                    valueSet = valueProperty.set, Object.defineProperty(npt, "value", {
                                        get: getter,
                                        set: setter,
                                        configurable: !0
                                    })) : "input" !== npt.tagName.toLowerCase() && (valueGet = function valueGet() {
                                        return this.textContent;
                                    }, valueSet = function valueSet(value) {
                                        this.textContent = value;
                                    }, Object.defineProperty(npt, "value", {
                                        get: getter,
                                        set: setter,
                                        configurable: !0
                                    }));
                                } else document.__lookupGetter__ && npt.__lookupGetter__("value") && (valueGet = npt.__lookupGetter__("value"), 
                                valueSet = npt.__lookupSetter__("value"), npt.__defineGetter__("value", getter), 
                                npt.__defineSetter__("value", setter));
                                npt.inputmask.__valueGet = valueGet, npt.inputmask.__valueSet = valueSet;
                            }
                            npt.inputmask._valueGet = function(overruleRTL) {
                                return isRTL && !0 !== overruleRTL ? valueGet.call(this.el).split("").reverse().join("") : valueGet.call(this.el);
                            }, npt.inputmask._valueSet = function(value, overruleRTL) {
                                valueSet.call(this.el, null == value ? "" : !0 !== overruleRTL && isRTL ? value.split("").reverse().join("") : value);
                            }, void 0 === valueGet && (valueGet = function valueGet() {
                                return this.value;
                            }, valueSet = function valueSet(value) {
                                this.value = value;
                            }, patchValhook(npt.type), installNativeValueSetFallback(npt));
                        }
                    }
                    "textarea" !== input.tagName.toLowerCase() && opts.ignorables.push(keyCode.ENTER);
                    var elementType = input.getAttribute("type"), isSupported = "input" === input.tagName.toLowerCase() && -1 !== $.inArray(elementType, opts.supportsInputType) || input.isContentEditable || "textarea" === input.tagName.toLowerCase();
                    if (!isSupported) if ("input" === input.tagName.toLowerCase()) {
                        var el = document.createElement("input");
                        el.setAttribute("type", elementType), isSupported = "text" === el.type, el = null;
                    } else isSupported = "partial";
                    return !1 !== isSupported ? patchValueProperty(input) : input.inputmask = void 0, 
                    isSupported;
                }
                EventRuler.off(elem);
                var isSupported = isElementTypeSupported(elem, opts);
                if (!1 !== isSupported) {
                    el = elem, $el = $(el), originalPlaceholder = el.placeholder, maxLength = void 0 !== el ? el.maxLength : void 0, 
                    -1 === maxLength && (maxLength = void 0), "inputMode" in el && null === el.getAttribute("inputmode") && (el.inputMode = opts.inputmode, 
                    el.setAttribute("inputmode", opts.inputmode)), !0 === isSupported && (opts.showMaskOnFocus = opts.showMaskOnFocus && -1 === [ "cc-number", "cc-exp" ].indexOf(el.autocomplete), 
                    iphone && (opts.insertModeVisual = !1), EventRuler.on(el, "submit", EventHandlers.submitEvent), 
                    EventRuler.on(el, "reset", EventHandlers.resetEvent), EventRuler.on(el, "blur", EventHandlers.blurEvent), 
                    EventRuler.on(el, "focus", EventHandlers.focusEvent), EventRuler.on(el, "invalid", EventHandlers.invalidEvent), 
                    EventRuler.on(el, "click", EventHandlers.clickEvent), EventRuler.on(el, "mouseleave", EventHandlers.mouseleaveEvent), 
                    EventRuler.on(el, "mouseenter", EventHandlers.mouseenterEvent), EventRuler.on(el, "paste", EventHandlers.pasteEvent), 
                    EventRuler.on(el, "cut", EventHandlers.cutEvent), EventRuler.on(el, "complete", opts.oncomplete), 
                    EventRuler.on(el, "incomplete", opts.onincomplete), EventRuler.on(el, "cleared", opts.oncleared), 
                    mobile || !0 === opts.inputEventOnly ? el.removeAttribute("maxLength") : (EventRuler.on(el, "keydown", EventHandlers.keydownEvent), 
                    EventRuler.on(el, "keypress", EventHandlers.keypressEvent)), EventRuler.on(el, "input", EventHandlers.inputFallBackEvent), 
                    EventRuler.on(el, "compositionend", EventHandlers.compositionendEvent)), EventRuler.on(el, "setvalue", EventHandlers.setValueEvent), 
                    undoValue = getBufferTemplate().join("");
                    var activeElement = (el.inputmask.shadowRoot || document).activeElement;
                    if ("" !== el.inputmask._valueGet(!0) || !1 === opts.clearMaskOnLostFocus || activeElement === el) {
                        applyInputValue(el, el.inputmask._valueGet(!0), opts);
                        var buffer = getBuffer().slice();
                        !1 === isComplete(buffer) && opts.clearIncomplete && resetMaskSet(), opts.clearMaskOnLostFocus && activeElement !== el && (-1 === getLastValidPosition() ? buffer = [] : clearOptionalTail(buffer)), 
                        (!1 === opts.clearMaskOnLostFocus || opts.showMaskOnFocus && activeElement === el || "" !== el.inputmask._valueGet(!0)) && writeBuffer(el, buffer), 
                        activeElement === el && caret(el, seekNext(getLastValidPosition()));
                    }
                }
            }
            if (void 0 !== actionObj) switch (actionObj.action) {
              case "isComplete":
                return el = actionObj.el, isComplete(getBuffer());

              case "unmaskedvalue":
                return void 0 !== el && void 0 === actionObj.value || (valueBuffer = actionObj.value, 
                valueBuffer = ($.isFunction(opts.onBeforeMask) && opts.onBeforeMask.call(inputmask, valueBuffer, opts) || valueBuffer).split(""), 
                checkVal.call(this, void 0, !1, !1, valueBuffer), $.isFunction(opts.onBeforeWrite) && opts.onBeforeWrite.call(inputmask, void 0, getBuffer(), 0, opts)), 
                unmaskedvalue(el);

              case "mask":
                mask(el);
                break;

              case "format":
                return valueBuffer = ($.isFunction(opts.onBeforeMask) && opts.onBeforeMask.call(inputmask, actionObj.value, opts) || actionObj.value).split(""), 
                checkVal.call(this, void 0, !0, !1, valueBuffer), actionObj.metadata ? {
                    value: isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""),
                    metadata: maskScope.call(this, {
                        action: "getmetadata"
                    }, maskset, opts)
                } : isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join("");

              case "isValid":
                actionObj.value ? (valueBuffer = ($.isFunction(opts.onBeforeMask) && opts.onBeforeMask.call(inputmask, actionObj.value, opts) || actionObj.value).split(""), 
                checkVal.call(this, void 0, !0, !1, valueBuffer)) : actionObj.value = isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join("");
                for (var buffer = getBuffer(), rl = determineLastRequiredPosition(), lmib = buffer.length - 1; rl < lmib && !isMask(lmib); lmib--) ;
                return buffer.splice(rl, lmib + 1 - rl), isComplete(buffer) && actionObj.value === (isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""));

              case "getemptymask":
                return getBufferTemplate().join("");

              case "remove":
                if (el && el.inputmask) {
                    $.data(el, "_inputmask_opts", null), $el = $(el);
                    var cv = opts.autoUnmask ? unmaskedvalue(el) : el.inputmask._valueGet(opts.autoUnmask), valueProperty;
                    cv !== getBufferTemplate().join("") ? el.inputmask._valueSet(cv, opts.autoUnmask) : el.inputmask._valueSet(""), 
                    EventRuler.off(el), Object.getOwnPropertyDescriptor && Object.getPrototypeOf ? (valueProperty = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value"), 
                    valueProperty && el.inputmask.__valueGet && Object.defineProperty(el, "value", {
                        get: el.inputmask.__valueGet,
                        set: el.inputmask.__valueSet,
                        configurable: !0
                    })) : document.__lookupGetter__ && el.__lookupGetter__("value") && el.inputmask.__valueGet && (el.__defineGetter__("value", el.inputmask.__valueGet), 
                    el.__defineSetter__("value", el.inputmask.__valueSet)), el.inputmask = void 0;
                }
                return el;

              case "getmetadata":
                if ($.isArray(maskset.metadata)) {
                    var maskTarget = getMaskTemplate(!0, 0, !1).join("");
                    return $.each(maskset.metadata, function(ndx, mtdt) {
                        if (mtdt.mask === maskTarget) return maskTarget = mtdt, !1;
                    }), maskTarget;
                }
                return maskset.metadata;
            }
        };
    }, function(module, exports, __webpack_require__) {
        "use strict";
        function _typeof(obj) {
            return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                return typeof obj;
            } : function _typeof(obj) {
                return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
            }, _typeof(obj);
        }
        var Inputmask = __webpack_require__(1), $ = Inputmask.dependencyLib, keyCode = __webpack_require__(0), formatCode = {
            d: [ "[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", Date.prototype.getDate ],
            dd: [ "0[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", function() {
                return pad(Date.prototype.getDate.call(this), 2);
            } ],
            ddd: [ "" ],
            dddd: [ "" ],
            m: [ "[1-9]|1[012]", Date.prototype.setMonth, "month", function() {
                return Date.prototype.getMonth.call(this) + 1;
            } ],
            mm: [ "0[1-9]|1[012]", Date.prototype.setMonth, "month", function() {
                return pad(Date.prototype.getMonth.call(this) + 1, 2);
            } ],
            mmm: [ "" ],
            mmmm: [ "" ],
            yy: [ "[0-9]{2}", Date.prototype.setFullYear, "year", function() {
                return pad(Date.prototype.getFullYear.call(this), 2);
            } ],
            yyyy: [ "[0-9]{4}", Date.prototype.setFullYear, "year", function() {
                return pad(Date.prototype.getFullYear.call(this), 4);
            } ],
            h: [ "[1-9]|1[0-2]", Date.prototype.setHours, "hours", Date.prototype.getHours ],
            hh: [ "0[1-9]|1[0-2]", Date.prototype.setHours, "hours", function() {
                return pad(Date.prototype.getHours.call(this), 2);
            } ],
            hx: [ function(x) {
                return "[0-9]{".concat(x, "}");
            }, Date.prototype.setHours, "hours", function(x) {
                return Date.prototype.getHours;
            } ],
            H: [ "1?[0-9]|2[0-3]", Date.prototype.setHours, "hours", Date.prototype.getHours ],
            HH: [ "0[0-9]|1[0-9]|2[0-3]", Date.prototype.setHours, "hours", function() {
                return pad(Date.prototype.getHours.call(this), 2);
            } ],
            Hx: [ function(x) {
                return "[0-9]{".concat(x, "}");
            }, Date.prototype.setHours, "hours", function(x) {
                return function() {
                    return pad(Date.prototype.getHours.call(this), x);
                };
            } ],
            M: [ "[1-5]?[0-9]", Date.prototype.setMinutes, "minutes", Date.prototype.getMinutes ],
            MM: [ "0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]", Date.prototype.setMinutes, "minutes", function() {
                return pad(Date.prototype.getMinutes.call(this), 2);
            } ],
            s: [ "[1-5]?[0-9]", Date.prototype.setSeconds, "seconds", Date.prototype.getSeconds ],
            ss: [ "0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]", Date.prototype.setSeconds, "seconds", function() {
                return pad(Date.prototype.getSeconds.call(this), 2);
            } ],
            l: [ "[0-9]{3}", Date.prototype.setMilliseconds, "milliseconds", function() {
                return pad(Date.prototype.getMilliseconds.call(this), 3);
            } ],
            L: [ "[0-9]{2}", Date.prototype.setMilliseconds, "milliseconds", function() {
                return pad(Date.prototype.getMilliseconds.call(this), 2);
            } ],
            t: [ "[ap]" ],
            tt: [ "[ap]m" ],
            T: [ "[AP]" ],
            TT: [ "[AP]M" ],
            Z: [ "" ],
            o: [ "" ],
            S: [ "" ]
        }, formatAlias = {
            isoDate: "yyyy-mm-dd",
            isoTime: "HH:MM:ss",
            isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
            isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
        };
        function formatcode(match) {
            var dynMatches = new RegExp("\\d+$").exec(match[0]);
            if (dynMatches && void 0 !== dynMatches[0]) {
                var fcode = formatCode[match[0][0] + "x"].slice("");
                return fcode[0] = fcode[0](dynMatches[0]), fcode[3] = fcode[3](dynMatches[0]), fcode;
            }
            if (formatCode[match[0]]) return formatCode[match[0]];
        }
        function getTokenizer(opts) {
            if (!opts.tokenizer) {
                var tokens = [], dyntokens = [];
                for (var ndx in formatCode) if (/\.*x$/.test(ndx)) {
                    var dynToken = ndx[0] + "\\d+";
                    -1 === dyntokens.indexOf(dynToken) && dyntokens.push(dynToken);
                } else -1 === tokens.indexOf(ndx[0]) && tokens.push(ndx[0]);
                opts.tokenizer = "(" + (0 < dyntokens.length ? dyntokens.join("|") + "|" : "") + tokens.join("+|") + ")+?|.", 
                opts.tokenizer = new RegExp(opts.tokenizer, "g");
            }
            return opts.tokenizer;
        }
        function isValidDate(dateParts, currentResult) {
            return (!isFinite(dateParts.rawday) || "29" == dateParts.day && !isFinite(dateParts.rawyear) || new Date(dateParts.date.getFullYear(), isFinite(dateParts.rawmonth) ? dateParts.month : dateParts.date.getMonth() + 1, 0).getDate() >= dateParts.day) && currentResult;
        }
        function isDateInRange(dateParts, opts) {
            var result = !0;
            if (opts.min) {
                if (dateParts.rawyear) {
                    var rawYear = dateParts.rawyear.replace(/[^0-9]/g, ""), minYear = opts.min.year.substr(0, rawYear.length);
                    result = minYear <= rawYear;
                }
                dateParts.year === dateParts.rawyear && opts.min.date.getTime() == opts.min.date.getTime() && (result = opts.min.date.getTime() <= dateParts.date.getTime());
            }
            return result && opts.max && opts.max.date.getTime() == opts.max.date.getTime() && (result = opts.max.date.getTime() >= dateParts.date.getTime()), 
            result;
        }
        function parse(format, dateObjValue, opts, raw) {
            var mask = "", match, fcode;
            for (getTokenizer(opts).lastIndex = 0; match = getTokenizer(opts).exec(format); ) if (void 0 === dateObjValue) if (fcode = formatcode(match)) mask += "(" + fcode[0] + ")"; else switch (match[0]) {
              case "[":
                mask += "(";
                break;

              case "]":
                mask += ")?";
                break;

              default:
                mask += Inputmask.escapeRegex(match[0]);
            } else if (fcode = formatcode(match)) if (!0 !== raw && fcode[3]) {
                var getFn = fcode[3];
                mask += getFn.call(dateObjValue.date);
            } else fcode[2] ? mask += dateObjValue["raw" + fcode[2]] : mask += match[0]; else mask += match[0];
            return mask;
        }
        function pad(val, len) {
            for (val = String(val), len = len || 2; val.length < len; ) val = "0" + val;
            return val;
        }
        function analyseMask(maskString, format, opts) {
            var dateObj = {
                date: new Date(1, 0, 1)
            }, targetProp, mask = maskString, match, dateOperation;
            function extendProperty(value) {
                var correctedValue = value.replace(/[^0-9]/g, "0");
                return correctedValue;
            }
            function setValue(dateObj, value, opts) {
                dateObj[targetProp] = extendProperty(value), dateObj["raw" + targetProp] = value, 
                void 0 !== dateOperation && dateOperation.call(dateObj.date, "month" == targetProp ? parseInt(dateObj[targetProp]) - 1 : dateObj[targetProp]);
            }
            if ("string" == typeof mask) {
                for (getTokenizer(opts).lastIndex = 0; match = getTokenizer(opts).exec(format); ) {
                    var value = mask.slice(0, match[0].length);
                    formatCode.hasOwnProperty(match[0]) && (targetProp = formatCode[match[0]][2], dateOperation = formatCode[match[0]][1], 
                    setValue(dateObj, value, opts)), mask = mask.slice(value.length);
                }
                return dateObj;
            }
            if (mask && "object" === _typeof(mask) && mask.hasOwnProperty("date")) return mask;
        }
        function importDate(dateObj, opts) {
            var match, date = "";
            for (getTokenizer(opts).lastIndex = 0; match = getTokenizer(opts).exec(opts.inputFormat); ) "d" === match[0].charAt(0) ? date += pad(dateObj.getDate(), match[0].length) : "m" === match[0].charAt(0) ? date += pad(dateObj.getMonth() + 1, match[0].length) : "yyyy" === match[0] ? date += dateObj.getFullYear().toString() : "y" === match[0].charAt(0) && (date += pad(dateObj.getYear(), match[0].length));
            return date;
        }
        function getTokenMatch(pos, opts) {
            var calcPos = 0, targetMatch, match, matchLength = 0;
            for (getTokenizer(opts).lastIndex = 0; match = getTokenizer(opts).exec(opts.inputFormat); ) {
                var dynMatches = new RegExp("\\d+$").exec(match[0]);
                if (matchLength = dynMatches ? parseInt(dynMatches[0]) : match[0].length, calcPos += matchLength, 
                pos <= calcPos) {
                    targetMatch = match, match = getTokenizer(opts).exec(opts.inputFormat);
                    break;
                }
            }
            return {
                targetMatchIndex: calcPos - matchLength,
                nextMatch: match,
                targetMatch: targetMatch
            };
        }
        Inputmask.extendAliases({
            datetime: {
                mask: function mask(opts) {
                    return opts.numericInput = !1, formatCode.S = opts.i18n.ordinalSuffix.join("|"), 
                    opts.inputFormat = formatAlias[opts.inputFormat] || opts.inputFormat, opts.displayFormat = formatAlias[opts.displayFormat] || opts.displayFormat || opts.inputFormat, 
                    opts.outputFormat = formatAlias[opts.outputFormat] || opts.outputFormat || opts.inputFormat, 
                    opts.placeholder = "" !== opts.placeholder ? opts.placeholder : opts.inputFormat.replace(/[[\]]/, ""), 
                    opts.regex = parse(opts.inputFormat, void 0, opts), opts.min = analyseMask(opts.min, opts.inputFormat, opts), 
                    opts.max = analyseMask(opts.max, opts.inputFormat, opts), null;
                },
                placeholder: "",
                inputFormat: "isoDateTime",
                displayFormat: void 0,
                outputFormat: void 0,
                min: null,
                max: null,
                skipOptionalPartCharacter: "",
                i18n: {
                    dayNames: [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ],
                    monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
                    ordinalSuffix: [ "st", "nd", "rd", "th" ]
                },
                preValidation: function preValidation(buffer, pos, c, isSelection, opts, maskset, caretPos, strict) {
                    if (strict) return !0;
                    if (isNaN(c) && buffer[pos] !== c) {
                        var tokenMatch = getTokenMatch(pos, opts);
                        if (tokenMatch.nextMatch && tokenMatch.nextMatch[0] === c && 1 < tokenMatch.targetMatch[0].length) {
                            var validator = formatCode[tokenMatch.targetMatch[0]][0];
                            if (new RegExp(validator).test("0" + buffer[pos - 1])) return buffer[pos] = buffer[pos - 1], 
                            buffer[pos - 1] = "0", {
                                fuzzy: !0,
                                buffer: buffer,
                                refreshFromBuffer: {
                                    start: pos - 1,
                                    end: pos + 1
                                },
                                pos: pos + 1
                            };
                        }
                    }
                    return !0;
                },
                postValidation: function postValidation(buffer, pos, c, currentResult, opts, maskset, strict) {
                    if (strict) return !0;
                    var tokenMatch, validator;
                    if (!1 === currentResult) return tokenMatch = getTokenMatch(pos + 1, opts), tokenMatch.targetMatch && tokenMatch.targetMatchIndex === pos && 1 < tokenMatch.targetMatch[0].length && void 0 !== formatCode[tokenMatch.targetMatch[0]] && (validator = formatCode[tokenMatch.targetMatch[0]][0], 
                    new RegExp(validator).test("0" + c)) ? {
                        insert: [ {
                            pos: pos,
                            c: "0"
                        }, {
                            pos: pos + 1,
                            c: c
                        } ],
                        pos: pos + 1
                    } : currentResult;
                    if (currentResult.fuzzy && (buffer = currentResult.buffer, pos = currentResult.pos), 
                    tokenMatch = getTokenMatch(pos, opts), tokenMatch.targetMatch && tokenMatch.targetMatch[0] && void 0 !== formatCode[tokenMatch.targetMatch[0]]) {
                        validator = formatCode[tokenMatch.targetMatch[0]][0];
                        var part = buffer.slice(tokenMatch.targetMatchIndex, tokenMatch.targetMatchIndex + tokenMatch.targetMatch[0].length);
                        !1 === new RegExp(validator).test(part.join("")) && 2 === tokenMatch.targetMatch[0].length && maskset.validPositions[tokenMatch.targetMatchIndex] && maskset.validPositions[tokenMatch.targetMatchIndex + 1] && (maskset.validPositions[tokenMatch.targetMatchIndex + 1].input = "0");
                    }
                    var result = currentResult, dateParts = analyseMask(buffer.join(""), opts.inputFormat, opts);
                    return result && dateParts.date.getTime() == dateParts.date.getTime() && (result = isValidDate(dateParts, result), 
                    result = result && isDateInRange(dateParts, opts)), pos && result && currentResult.pos !== pos ? {
                        buffer: parse(opts.inputFormat, dateParts, opts).split(""),
                        refreshFromBuffer: {
                            start: pos,
                            end: currentResult.pos
                        }
                    } : result;
                },
                onKeyDown: function onKeyDown(e, buffer, caretPos, opts) {
                    var input = this;
                    e.ctrlKey && e.keyCode === keyCode.RIGHT && (this.inputmask._valueSet(importDate(new Date(), opts)), 
                    $(this).trigger("setvalue"));
                },
                onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                    return unmaskedValue ? parse(opts.outputFormat, analyseMask(maskedValue, opts.inputFormat, opts), opts, !0) : unmaskedValue;
                },
                casing: function casing(elem, test, pos, validPositions) {
                    return 0 == test.nativeDef.indexOf("[ap]") ? elem.toLowerCase() : 0 == test.nativeDef.indexOf("[AP]") ? elem.toUpperCase() : elem;
                },
                onBeforeMask: function onBeforeMask(initialValue, opts) {
                    return "[object Date]" === Object.prototype.toString.call(initialValue) && (initialValue = importDate(initialValue, opts)), 
                    initialValue;
                },
                insertMode: !1,
                shiftPositions: !1,
                keepStatic: !1,
                inputmode: "numeric"
            }
        }), module.exports = Inputmask;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var Inputmask = __webpack_require__(1), $ = Inputmask.dependencyLib, keyCode = __webpack_require__(0);
        function autoEscape(txt, opts) {
            for (var escapedTxt = "", i = 0; i < txt.length; i++) Inputmask.prototype.definitions[txt.charAt(i)] || opts.definitions[txt.charAt(i)] || opts.optionalmarker[0] === txt.charAt(i) || opts.optionalmarker[1] === txt.charAt(i) || opts.quantifiermarker[0] === txt.charAt(i) || opts.quantifiermarker[1] === txt.charAt(i) || opts.groupmarker[0] === txt.charAt(i) || opts.groupmarker[1] === txt.charAt(i) || opts.alternatormarker === txt.charAt(i) ? escapedTxt += "\\" + txt.charAt(i) : escapedTxt += txt.charAt(i);
            return escapedTxt;
        }
        function alignDigits(buffer, digits, opts, force) {
            if (0 < buffer.length && 0 < digits && (!opts.digitsOptional || force)) {
                var radixPosition = $.inArray(opts.radixPoint, buffer);
                -1 === radixPosition && (buffer.push(opts.radixPoint), radixPosition = buffer.length - 1);
                for (var i = 1; i <= digits; i++) isFinite(buffer[radixPosition + i]) || (buffer[radixPosition + i] = "0");
            }
            return buffer;
        }
        function findValidator(symbol, maskset) {
            var posNdx = 0;
            if ("+" === symbol) {
                for (posNdx in maskset.validPositions) ;
                posNdx = parseInt(posNdx);
            }
            for (var tstNdx in maskset.tests) if (tstNdx = parseInt(tstNdx), posNdx <= tstNdx) for (var ndx = 0, ndxl = maskset.tests[tstNdx].length; ndx < ndxl; ndx++) if ((void 0 === maskset.validPositions[tstNdx] || "-" === symbol) && maskset.tests[tstNdx][ndx].match.def === symbol) return tstNdx + (void 0 !== maskset.validPositions[tstNdx] && "-" !== symbol ? 1 : 0);
            return posNdx;
        }
        function findValid(symbol, maskset) {
            var ret = -1;
            return $.each(maskset.validPositions, function(ndx, tst) {
                if (tst && tst.match.def === symbol) return ret = parseInt(ndx), !1;
            }), ret;
        }
        function parseMinMaxOptions(opts) {
            void 0 === opts.parseMinMaxOptions && (null !== opts.min && (opts.min = opts.min.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
            "," === opts.radixPoint && (opts.min = opts.min.replace(opts.radixPoint, ".")), 
            opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN, isNaN(opts.min) && (opts.min = Number.MIN_VALUE)), 
            null !== opts.max && (opts.max = opts.max.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
            "," === opts.radixPoint && (opts.max = opts.max.replace(opts.radixPoint, ".")), 
            opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN, isNaN(opts.max) && (opts.max = Number.MAX_VALUE)), 
            opts.parseMinMaxOptions = "done");
        }
        function genMask(opts) {
            opts.repeat = 0, opts.groupSeparator === opts.radixPoint && opts.digits && "0" !== opts.digits && ("." === opts.radixPoint ? opts.groupSeparator = "," : "," === opts.radixPoint ? opts.groupSeparator = "." : opts.groupSeparator = ""), 
            " " === opts.groupSeparator && (opts.skipOptionalPartCharacter = void 0), 1 < opts.placeholder.length && (opts.placeholder = opts.placeholder.charAt(0)), 
            "radixFocus" === opts.positionCaretOnClick && "" === opts.placeholder && (opts.positionCaretOnClick = "lvp");
            var decimalDef = "0", radixPointDef = opts.radixPoint;
            !0 === opts.numericInput && void 0 === opts.__financeInput ? (decimalDef = "1", 
            opts.positionCaretOnClick = "radixFocus" === opts.positionCaretOnClick ? "lvp" : opts.positionCaretOnClick, 
            opts.digitsOptional = !1, isNaN(opts.digits) && (opts.digits = 2), opts._radixDance = !1, 
            radixPointDef = "," === opts.radixPoint ? "?" : "!", "" !== opts.radixPoint && void 0 === opts.definitions[radixPointDef] && (opts.definitions[radixPointDef] = {}, 
            opts.definitions[radixPointDef].validator = "[" + opts.radixPoint + "]", opts.definitions[radixPointDef].placeholder = opts.radixPoint, 
            opts.definitions[radixPointDef].static = !0, opts.definitions[radixPointDef].generated = !0)) : (opts.__financeInput = !1, 
            opts.numericInput = !0);
            var mask = "[+]", altMask;
            if (mask += autoEscape(opts.prefix, opts), "" !== opts.groupSeparator ? (void 0 === opts.definitions[opts.groupSeparator] && (opts.definitions[opts.groupSeparator] = {}, 
            opts.definitions[opts.groupSeparator].validator = "[" + opts.groupSeparator + "]", 
            opts.definitions[opts.groupSeparator].placeholder = opts.groupSeparator, opts.definitions[opts.groupSeparator].static = !0, 
            opts.definitions[opts.groupSeparator].generated = !0), mask += opts._mask(opts)) : mask += "9{+}", 
            void 0 !== opts.digits && 0 !== opts.digits) {
                var dq = opts.digits.toString().split(",");
                isFinite(dq[0]) && dq[1] && isFinite(dq[1]) ? mask += radixPointDef + decimalDef + "{" + opts.digits + "}" : (isNaN(opts.digits) || 0 < parseInt(opts.digits)) && (opts.digitsOptional ? (altMask = mask + radixPointDef + decimalDef + "{0," + opts.digits + "}", 
                opts.keepStatic = !0) : mask += radixPointDef + decimalDef + "{" + opts.digits + "}");
            }
            return mask += autoEscape(opts.suffix, opts), mask += "[-]", altMask && (mask = [ altMask + autoEscape(opts.suffix, opts) + "[-]", mask ]), 
            opts.greedy = !1, parseMinMaxOptions(opts), mask;
        }
        function hanndleRadixDance(pos, c, radixPos, maskset, opts) {
            return opts._radixDance && opts.numericInput && c !== opts.negationSymbol.back && pos <= radixPos && (0 < radixPos || c == opts.radixPoint) && (void 0 === maskset.validPositions[pos - 1] || maskset.validPositions[pos - 1].input !== opts.negationSymbol.back) && (pos -= 1), 
            pos;
        }
        function decimalValidator(chrs, maskset, pos, strict, opts) {
            var radixPos = maskset.buffer ? maskset.buffer.indexOf(opts.radixPoint) : -1, result = -1 !== radixPos && new RegExp("[0-9\uff11-\uff19]").test(chrs);
            return opts._radixDance && result && null == maskset.validPositions[radixPos] ? {
                insert: {
                    pos: radixPos === pos ? radixPos + 1 : radixPos,
                    c: opts.radixPoint
                },
                pos: pos
            } : result;
        }
        function checkForLeadingZeroes(buffer, opts) {
            var numberMatches = new RegExp("(^" + ("" !== opts.negationSymbol.front ? Inputmask.escapeRegex(opts.negationSymbol.front) + "?" : "") + Inputmask.escapeRegex(opts.prefix) + ")(.*)(" + Inputmask.escapeRegex(opts.suffix) + ("" != opts.negationSymbol.back ? Inputmask.escapeRegex(opts.negationSymbol.back) + "?" : "") + "$)").exec(buffer.slice().reverse().join("")), number = numberMatches ? numberMatches[2] : "", leadingzeroes = !1;
            return number && (number = number.split(opts.radixPoint.charAt(0))[0], leadingzeroes = new RegExp("^[0" + opts.groupSeparator + "]*").exec(number)), 
            !(!leadingzeroes || !(1 < leadingzeroes[0].length || 0 < leadingzeroes[0].length && leadingzeroes[0].length < number.length)) && leadingzeroes;
        }
        Inputmask.extendAliases({
            numeric: {
                mask: genMask,
                _mask: function _mask(opts) {
                    return "(" + opts.groupSeparator + "999){+|1}";
                },
                digits: "*",
                digitsOptional: !0,
                enforceDigitsOnBlur: !1,
                radixPoint: ".",
                positionCaretOnClick: "radixFocus",
                _radixDance: !0,
                groupSeparator: "",
                allowMinus: !0,
                negationSymbol: {
                    front: "-",
                    back: ""
                },
                prefix: "",
                suffix: "",
                min: null,
                max: null,
                step: 1,
                unmaskAsNumber: !1,
                roundingFN: Math.round,
                inputmode: "numeric",
                shortcuts: {
                    k: "000",
                    m: "000000"
                },
                placeholder: "0",
                greedy: !1,
                rightAlign: !0,
                insertMode: !0,
                autoUnmask: !1,
                skipOptionalPartCharacter: "",
                definitions: {
                    0: {
                        validator: decimalValidator
                    },
                    1: {
                        validator: decimalValidator,
                        definitionSymbol: "9"
                    },
                    "+": {
                        validator: function validator(chrs, maskset, pos, strict, opts) {
                            return opts.allowMinus && ("-" === chrs || chrs === opts.negationSymbol.front);
                        }
                    },
                    "-": {
                        validator: function validator(chrs, maskset, pos, strict, opts) {
                            return opts.allowMinus && chrs === opts.negationSymbol.back;
                        }
                    }
                },
                preValidation: function preValidation(buffer, pos, c, isSelection, opts, maskset, caretPos, strict) {
                    if (!1 !== opts.__financeInput && c === opts.radixPoint) return !1;
                    var pattern;
                    if (pattern = opts.shortcuts && opts.shortcuts[c]) {
                        if (1 < pattern.length) for (var inserts = [], i = 0; i < pattern.length; i++) inserts.push({
                            pos: pos + i,
                            c: pattern[i],
                            strict: !1
                        });
                        return {
                            insert: inserts
                        };
                    }
                    var radixPos = $.inArray(opts.radixPoint, buffer), initPos = pos;
                    if (pos = hanndleRadixDance(pos, c, radixPos, maskset, opts), "-" === c || c === opts.negationSymbol.front) {
                        if (!0 !== opts.allowMinus) return !1;
                        var isNegative = !1, front = findValid("+", maskset), back = findValid("-", maskset);
                        return -1 !== front && (isNegative = [ front, back ]), !1 !== isNegative ? {
                            remove: isNegative,
                            caret: initPos
                        } : {
                            insert: [ {
                                pos: findValidator("+", maskset),
                                c: opts.negationSymbol.front,
                                fromIsValid: !0
                            }, {
                                pos: findValidator("-", maskset),
                                c: opts.negationSymbol.back,
                                fromIsValid: void 0
                            } ],
                            caret: initPos + opts.negationSymbol.back.length
                        };
                    }
                    if (strict) return !0;
                    if (-1 !== radixPos && !0 === opts._radixDance && !1 === isSelection && c === opts.radixPoint && void 0 !== opts.digits && (isNaN(opts.digits) || 0 < parseInt(opts.digits)) && radixPos !== pos) return {
                        caret: opts._radixDance && pos === radixPos - 1 ? radixPos + 1 : radixPos
                    };
                    if (!1 === opts.__financeInput) if (isSelection) {
                        if (opts.digitsOptional) return {
                            rewritePosition: caretPos.end
                        };
                        if (!opts.digitsOptional) {
                            if (caretPos.begin > radixPos && caretPos.end <= radixPos) return c === opts.radixPoint ? {
                                insert: {
                                    pos: radixPos + 1,
                                    c: "0",
                                    fromIsValid: !0
                                },
                                rewritePosition: radixPos
                            } : {
                                rewritePosition: radixPos + 1
                            };
                            if (caretPos.begin < radixPos) return {
                                rewritePosition: caretPos.begin - 1
                            };
                        }
                    } else if (!opts.showMaskOnHover && !opts.showMaskOnFocus && !opts.digitsOptional && 0 < opts.digits && "" === this.inputmask.__valueGet.call(this)) return {
                        rewritePosition: radixPos
                    };
                    return {
                        rewritePosition: pos
                    };
                },
                postValidation: function postValidation(buffer, pos, c, currentResult, opts, maskset, strict) {
                    if (!1 === currentResult) return currentResult;
                    if (strict) return !0;
                    if (null !== opts.min || null !== opts.max) {
                        var unmasked = opts.onUnMask(buffer.slice().reverse().join(""), void 0, $.extend({}, opts, {
                            unmaskAsNumber: !0
                        }));
                        if (null !== opts.min && unmasked < opts.min && (unmasked.toString().length >= opts.min.toString().length || unmasked < 0)) return !1;
                        if (null !== opts.max && unmasked > opts.max) return !1;
                    }
                    return currentResult;
                },
                onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
                    if ("" === unmaskedValue && !0 === opts.nullable) return unmaskedValue;
                    var processValue = maskedValue.replace(opts.prefix, "");
                    return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                    "" !== opts.placeholder.charAt(0) && (processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0")), 
                    opts.unmaskAsNumber ? ("" !== opts.radixPoint && -1 !== processValue.indexOf(opts.radixPoint) && (processValue = processValue.replace(Inputmask.escapeRegex.call(this, opts.radixPoint), ".")), 
                    processValue = processValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-"), 
                    processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""), 
                    Number(processValue)) : processValue;
                },
                isComplete: function isComplete(buffer, opts) {
                    var maskedValue = (opts.numericInput ? buffer.slice().reverse() : buffer).join("");
                    return maskedValue = maskedValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-"), 
                    maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""), 
                    maskedValue = maskedValue.replace(opts.prefix, ""), maskedValue = maskedValue.replace(opts.suffix, ""), 
                    maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator) + "([0-9]{3})", "g"), "$1"), 
                    "," === opts.radixPoint && (maskedValue = maskedValue.replace(Inputmask.escapeRegex(opts.radixPoint), ".")), 
                    isFinite(maskedValue);
                },
                onBeforeMask: function onBeforeMask(initialValue, opts) {
                    var radixPoint = opts.radixPoint || ",";
                    isFinite(opts.digits) && (opts.digits = parseInt(opts.digits)), "number" != typeof initialValue && "number" !== opts.inputType || "" === radixPoint || (initialValue = initialValue.toString().replace(".", radixPoint));
                    var valueParts = initialValue.split(radixPoint), integerPart = valueParts[0].replace(/[^\-0-9]/g, ""), decimalPart = 1 < valueParts.length ? valueParts[1].replace(/[^0-9]/g, "") : "", forceDigits = 1 < valueParts.length;
                    initialValue = integerPart + ("" !== decimalPart ? radixPoint + decimalPart : decimalPart);
                    var digits = 0;
                    if ("" !== radixPoint && (digits = opts.digitsOptional ? opts.digits < decimalPart.length ? opts.digits : decimalPart.length : opts.digits, 
                    "" !== decimalPart || !opts.digitsOptional)) {
                        var digitsFactor = Math.pow(10, digits || 1);
                        initialValue = initialValue.replace(Inputmask.escapeRegex(radixPoint), "."), isNaN(parseFloat(initialValue)) || (initialValue = (opts.roundingFN(parseFloat(initialValue) * digitsFactor) / digitsFactor).toFixed(digits)), 
                        initialValue = initialValue.toString().replace(".", radixPoint);
                    }
                    if (0 === opts.digits && -1 !== initialValue.indexOf(radixPoint) && (initialValue = initialValue.substring(0, initialValue.indexOf(radixPoint))), 
                    null !== opts.min || null !== opts.max) {
                        var numberValue = initialValue.toString().replace(radixPoint, ".");
                        null !== opts.min && numberValue < opts.min ? initialValue = opts.min.toString().replace(".", radixPoint) : null !== opts.max && numberValue > opts.max && (initialValue = opts.max.toString().replace(".", radixPoint));
                    }
                    return alignDigits(initialValue.toString().split(""), digits, opts, forceDigits).join("");
                },
                onBeforeWrite: function onBeforeWrite(e, buffer, caretPos, opts) {
                    function stripBuffer(buffer, stripRadix) {
                        if (!1 !== opts.__financeInput || stripRadix) {
                            var position = $.inArray(opts.radixPoint, buffer);
                            -1 !== position && buffer.splice(position, 1);
                        }
                        if ("" !== opts.groupSeparator) for (;-1 !== (position = buffer.indexOf(opts.groupSeparator)); ) buffer.splice(position, 1);
                        return buffer;
                    }
                    var result, leadingzeroes = checkForLeadingZeroes(buffer, opts);
                    if (leadingzeroes) {
                        var buf = buffer.slice().reverse(), caretNdx = buf.join("").indexOf(leadingzeroes[0]);
                        buf.splice(caretNdx, leadingzeroes[0].length);
                        var newCaretPos = buf.length - caretNdx;
                        stripBuffer(buf), result = {
                            refreshFromBuffer: !0,
                            buffer: buf.reverse(),
                            caret: caretPos < newCaretPos ? caretPos : newCaretPos
                        };
                    }
                    if (e) switch (e.type) {
                      case "blur":
                      case "checkval":
                        if (null !== opts.min) {
                            var unmasked = opts.onUnMask(buffer.slice().reverse().join(""), void 0, $.extend({}, opts, {
                                unmaskAsNumber: !0
                            }));
                            if (null !== opts.min && unmasked < opts.min) return {
                                refreshFromBuffer: !0,
                                buffer: alignDigits(opts.min.toString().replace(".", opts.radixPoint).split(""), opts.digits, opts).reverse()
                            };
                        }
                        if (buffer[buffer.length - 1] === opts.negationSymbol.front) {
                            var nmbrMtchs = new RegExp("(^" + ("" != opts.negationSymbol.front ? Inputmask.escapeRegex(opts.negationSymbol.front) + "?" : "") + Inputmask.escapeRegex(opts.prefix) + ")(.*)(" + Inputmask.escapeRegex(opts.suffix) + ("" != opts.negationSymbol.back ? Inputmask.escapeRegex(opts.negationSymbol.back) + "?" : "") + "$)").exec(stripBuffer(buffer.slice(), !0).reverse().join("")), number = nmbrMtchs ? nmbrMtchs[2] : "";
                            0 == number && (result = {
                                refreshFromBuffer: !0,
                                buffer: [ 0 ]
                            });
                        } else "" !== opts.radixPoint && buffer[0] === opts.radixPoint && (result && result.buffer ? result.buffer.shift() : (buffer.shift(), 
                        result = {
                            refreshFromBuffer: !0,
                            buffer: stripBuffer(buffer)
                        }));
                        if (opts.enforceDigitsOnBlur) {
                            result = result || {};
                            var bffr = result && result.buffer || buffer.slice().reverse();
                            result.refreshFromBuffer = !0, result.buffer = alignDigits(bffr, opts.digits, opts, !0).reverse();
                        }
                    }
                    return result;
                },
                onKeyDown: function onKeyDown(e, buffer, caretPos, opts) {
                    var $input = $(this), bffr;
                    if (e.ctrlKey) switch (e.keyCode) {
                      case keyCode.UP:
                        return this.inputmask.__valueSet.call(this, parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step)), 
                        $input.trigger("setvalue"), !1;

                      case keyCode.DOWN:
                        return this.inputmask.__valueSet.call(this, parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step)), 
                        $input.trigger("setvalue"), !1;
                    }
                    if (!e.shiftKey && (e.keyCode === keyCode.DELETE || e.keyCode === keyCode.BACKSPACE || e.keyCode === keyCode.BACKSPACE_SAFARI) && caretPos.begin !== buffer.length) {
                        if (buffer[e.keyCode === keyCode.DELETE ? caretPos.begin - 1 : caretPos.end] === opts.negationSymbol.front) return bffr = buffer.slice().reverse(), 
                        "" !== opts.negationSymbol.front && bffr.shift(), "" !== opts.negationSymbol.back && bffr.pop(), 
                        $input.trigger("setvalue", [ bffr.join(""), caretPos.begin ]), !1;
                        if (!0 === opts._radixDance) {
                            var radixPos = $.inArray(opts.radixPoint, buffer);
                            if (opts.digitsOptional) {
                                if (0 === radixPos) return bffr = buffer.slice().reverse(), bffr.pop(), $input.trigger("setvalue", [ bffr.join(""), caretPos.begin >= bffr.length ? bffr.length : caretPos.begin ]), 
                                !1;
                            } else if (-1 !== radixPos && (caretPos.begin < radixPos || caretPos.end < radixPos || e.keyCode === keyCode.DELETE && caretPos.begin === radixPos)) return caretPos.begin !== caretPos.end || e.keyCode !== keyCode.BACKSPACE && e.keyCode !== keyCode.BACKSPACE_SAFARI || caretPos.begin++, 
                            bffr = buffer.slice().reverse(), bffr.splice(bffr.length - caretPos.begin, caretPos.begin - caretPos.end + 1), 
                            bffr = alignDigits(bffr, opts.digits, opts).join(""), $input.trigger("setvalue", [ bffr, caretPos.begin >= bffr.length ? radixPos + 1 : caretPos.begin ]), 
                            !1;
                        }
                    }
                }
            },
            currency: {
                prefix: "",
                groupSeparator: ",",
                alias: "numeric",
                digits: 2,
                digitsOptional: !1
            },
            decimal: {
                alias: "numeric"
            },
            integer: {
                alias: "numeric",
                digits: 0
            },
            percentage: {
                alias: "numeric",
                min: 0,
                max: 100,
                suffix: " %",
                digits: 0,
                allowMinus: !1
            },
            indianns: {
                alias: "numeric",
                _mask: function _mask(opts) {
                    return "(" + opts.groupSeparator + "99){*|1}(" + opts.groupSeparator + "999){1|1}";
                },
                groupSeparator: ",",
                radixPoint: ".",
                placeholder: "0",
                digits: 2,
                digitsOptional: !1
            }
        }), module.exports = Inputmask;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var _inputmask = _interopRequireDefault(__webpack_require__(1));
        function _typeof(obj) {
            return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                return typeof obj;
            } : function _typeof(obj) {
                return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
            }, _typeof(obj);
        }
        function _classCallCheck(instance, Constructor) {
            if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
        }
        function _possibleConstructorReturn(self, call) {
            return !call || "object" !== _typeof(call) && "function" != typeof call ? _assertThisInitialized(self) : call;
        }
        function _assertThisInitialized(self) {
            if (void 0 === self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
            return self;
        }
        function _inherits(subClass, superClass) {
            if ("function" != typeof superClass && null !== superClass) throw new TypeError("Super expression must either be null or a function");
            subClass.prototype = Object.create(superClass && superClass.prototype, {
                constructor: {
                    value: subClass,
                    writable: !0,
                    configurable: !0
                }
            }), superClass && _setPrototypeOf(subClass, superClass);
        }
        function _wrapNativeSuper(Class) {
            var _cache = "function" == typeof Map ? new Map() : void 0;
            return _wrapNativeSuper = function _wrapNativeSuper(Class) {
                if (null === Class || !_isNativeFunction(Class)) return Class;
                if ("function" != typeof Class) throw new TypeError("Super expression must either be null or a function");
                if ("undefined" != typeof _cache) {
                    if (_cache.has(Class)) return _cache.get(Class);
                    _cache.set(Class, Wrapper);
                }
                function Wrapper() {
                    return _construct(Class, arguments, _getPrototypeOf(this).constructor);
                }
                return Wrapper.prototype = Object.create(Class.prototype, {
                    constructor: {
                        value: Wrapper,
                        enumerable: !1,
                        writable: !0,
                        configurable: !0
                    }
                }), _setPrototypeOf(Wrapper, Class);
            }, _wrapNativeSuper(Class);
        }
        function isNativeReflectConstruct() {
            if ("undefined" == typeof Reflect || !Reflect.construct) return !1;
            if (Reflect.construct.sham) return !1;
            if ("function" == typeof Proxy) return !0;
            try {
                return Date.prototype.toString.call(Reflect.construct(Date, [], function() {})), 
                !0;
            } catch (e) {
                return !1;
            }
        }
        function _construct(Parent, args, Class) {
            return _construct = isNativeReflectConstruct() ? Reflect.construct : function _construct(Parent, args, Class) {
                var a = [ null ];
                a.push.apply(a, args);
                var Constructor = Function.bind.apply(Parent, a), instance = new Constructor();
                return Class && _setPrototypeOf(instance, Class.prototype), instance;
            }, _construct.apply(null, arguments);
        }
        function _isNativeFunction(fn) {
            return -1 !== Function.toString.call(fn).indexOf("[native code]");
        }
        function _setPrototypeOf(o, p) {
            return _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
                return o.__proto__ = p, o;
            }, _setPrototypeOf(o, p);
        }
        function _getPrototypeOf(o) {
            return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
                return o.__proto__ || Object.getPrototypeOf(o);
            }, _getPrototypeOf(o);
        }
        function _interopRequireDefault(obj) {
            return obj && obj.__esModule ? obj : {
                default: obj
            };
        }
        if (document.head.createShadowRoot || document.head.attachShadow) {
            var InputmaskElement = function(_HTMLElement) {
                function InputmaskElement() {
                    var _this;
                    _classCallCheck(this, InputmaskElement), _this = _possibleConstructorReturn(this, _getPrototypeOf(InputmaskElement).call(this));
                    var attributeNames = _this.getAttributeNames(), shadow = _this.attachShadow({
                        mode: "closed"
                    }), input = document.createElement("input");
                    for (var attr in input.type = "text", shadow.appendChild(input), attributeNames) Object.prototype.hasOwnProperty.call(attributeNames, attr) && input.setAttribute("data-inputmask-" + attributeNames[attr], _this.getAttribute(attributeNames[attr]));
                    return new _inputmask.default().mask(input), input.inputmask.shadowRoot = shadow, 
                    _this;
                }
                return _inherits(InputmaskElement, _HTMLElement), InputmaskElement;
            }(_wrapNativeSuper(HTMLElement));
            customElements.define("input-mask", InputmaskElement);
        }
    }, function(module, exports, __webpack_require__) {
        "use strict";
        function _typeof(obj) {
            return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function _typeof(obj) {
                return typeof obj;
            } : function _typeof(obj) {
                return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
            }, _typeof(obj);
        }
        var $ = __webpack_require__(3), Inputmask = __webpack_require__(1);
        void 0 === $.fn.inputmask && ($.fn.inputmask = function(fn, options) {
            var nptmask, input = this[0];
            if (void 0 === options && (options = {}), "string" == typeof fn) switch (fn) {
              case "unmaskedvalue":
                return input && input.inputmask ? input.inputmask.unmaskedvalue() : $(input).val();

              case "remove":
                return this.each(function() {
                    this.inputmask && this.inputmask.remove();
                });

              case "getemptymask":
                return input && input.inputmask ? input.inputmask.getemptymask() : "";

              case "hasMaskedValue":
                return !(!input || !input.inputmask) && input.inputmask.hasMaskedValue();

              case "isComplete":
                return !input || !input.inputmask || input.inputmask.isComplete();

              case "getmetadata":
                return input && input.inputmask ? input.inputmask.getmetadata() : void 0;

              case "setvalue":
                Inputmask.setValue(input, options);
                break;

              case "option":
                if ("string" != typeof options) return this.each(function() {
                    if (void 0 !== this.inputmask) return this.inputmask.option(options);
                });
                if (input && void 0 !== input.inputmask) return input.inputmask.option(options);
                break;

              default:
                return options.alias = fn, nptmask = new Inputmask(options), this.each(function() {
                    nptmask.mask(this);
                });
            } else {
                if (Array.isArray(fn)) return options.alias = fn, nptmask = new Inputmask(options), 
                this.each(function() {
                    nptmask.mask(this);
                });
                if ("object" == _typeof(fn)) return nptmask = new Inputmask(fn), void 0 === fn.mask && void 0 === fn.alias ? this.each(function() {
                    if (void 0 !== this.inputmask) return this.inputmask.option(fn);
                    nptmask.mask(this);
                }) : this.each(function() {
                    nptmask.mask(this);
                });
                if (void 0 === fn) return this.each(function() {
                    nptmask = new Inputmask(options), nptmask.mask(this);
                });
            }
        });
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var im = __webpack_require__(6), jQuery = __webpack_require__(3);
        im.dependencyLib === jQuery && __webpack_require__(12), module.exports = im;
    } ], installedModules = {}, __webpack_require__.m = modules, __webpack_require__.c = installedModules, 
    __webpack_require__.d = function(exports, name, getter) {
        __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
            enumerable: !0,
            get: getter
        });
    }, __webpack_require__.r = function(exports) {
        "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(exports, Symbol.toStringTag, {
            value: "Module"
        }), Object.defineProperty(exports, "__esModule", {
            value: !0
        });
    }, __webpack_require__.t = function(value, mode) {
        if (1 & mode && (value = __webpack_require__(value)), 8 & mode) return value;
        if (4 & mode && "object" == typeof value && value && value.__esModule) return value;
        var ns = Object.create(null);
        if (__webpack_require__.r(ns), Object.defineProperty(ns, "default", {
            enumerable: !0,
            value: value
        }), 2 & mode && "string" != typeof value) for (var key in value) __webpack_require__.d(ns, key, function(key) {
            return value[key];
        }.bind(null, key));
        return ns;
    }, __webpack_require__.n = function(module) {
        var getter = module && module.__esModule ? function getDefault() {
            return module.default;
        } : function getModuleExports() {
            return module;
        };
        return __webpack_require__.d(getter, "a", getter), getter;
    }, __webpack_require__.o = function(object, property) {
        return Object.prototype.hasOwnProperty.call(object, property);
    }, __webpack_require__.p = "", __webpack_require__(__webpack_require__.s = 13);
    function __webpack_require__(moduleId) {
        if (installedModules[moduleId]) return installedModules[moduleId].exports;
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: !1,
            exports: {}
        };
        return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), 
        module.l = !0, module.exports;
    }
    var modules, installedModules;
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.FieldBase = oo.CustomBase(
{
    _init: function (options)
    {
        _.extend(this, options);
    },

    hide: function () 
    {
        this._getSection().addClass("hiddenByFrontendApi");
    },
    show: function () 
    {
        this._getSection().removeClass("hiddenByFrontendApi");
    },

    _getSection: function ()
    {
        this._throwIfFieldIsNotRendered();
        return this.formBuilderForm.getSection(this.model);
    },
    _getView: function ()
    {
        this._throwIfFieldIsNotRendered();
        return this.formBuilderForm.fieldViews[this.model.getPath()];
    },
    _$: function (selector)
    {
        return this._getSection().find(selector);
    },
    _throwMethodIsNotSupported: function (methodName)
    {
        throw methodName + " is not supported for this field type.";
    },
    _throwIfFieldIsNotRendered: function ()
    {
        if (!this.model.rendered)
        {
            var reason = this.model.get("hiddenByParent") && "hidden by parent field" || this.model.get("hidden") && "hidden by category group settings" || "is not ready for this operation";
            throw "Field '" + this.model.get("alias") + "' " + reason + ".";
        }
    }
});;
namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase = awardsCommon.widgets.formBuilderForm.frontendApi.FieldBase(
{
    _init: function (options)
    {
        this.changeHandlers = [];
    },

    getValue: function ()
    {
        return this.model.readOnly ? this._getReadOnlyValueInternal() : this._getValueInternal();
    },
    setValue: function (value)
    {
        if (this.model.readOnly)
            throw "Field with alias '" + this.alias + "' is read-only.";

        this._throwIfValueCantBeSet();

        var validationResult = this._validateValue(value);
        if (validationResult.error)
            throw validationResult.error;

        this.prevValue = value;

        this.isSettingValueInProgress = true;
        var result = this._setValueInternal(value);
        this.isSettingValueInProgress = false;

        return result;
    },
    onChange: function (handler)
    {
        if (!_.isFunction(handler))
            throw "Handler is not a function.";

        if (!this.isChangeListenerAttached)
        {
            var self = this;
            var attachChangeListenerOnFieldRenderFunc = function ()
            {
                var changeListener = self._changeListenerInternal.bind(self);
                self._attachChangeListener(changeListener);
                self.prevValue = self.getValue();
                self.internalChangeListenerFunc = changeListener;
            };

            if (this.model.rendered)
                attachChangeListenerOnFieldRenderFunc();
            else
            {
                this.model.once("rendered", attachChangeListenerOnFieldRenderFunc);
                this.attachChangeListenerOnFieldRenderFunc = attachChangeListenerOnFieldRenderFunc
            }

            this.isChangeListenerAttached = true;
        }

        // let's support only one handler for now until support of multiple handlers will be requested
        this.changeHandlers.length = 0;
        this.changeHandlers.push(handler);
    },
    offChange: function (handler)
    {
        if (!handler)
            this.changeHandlers.length = 0;
        else if (_.isFunction(handler))
            this.changeHandlers = _(this.changeHandlers).filter(function (h) { return h != handler; });
        else
            throw "Handler is not a function.";

        if (!this.changeHandlers.length && this.isChangeListenerAttached)
        {
            if (this.internalChangeListenerFunc)
                this._detachChangeListener(this.internalChangeListenerFunc);

            if (this.attachChangeListenerOnFieldRenderFunc)
                this.model.off("rendered", this.attachChangeListenerOnFieldRenderFunc);

            this.isChangeListenerAttached = false;
        }
    },

    _changeListenerInternal: function ()
    {
        // let's not invoke change handlers for now if value is setting via API
        if (this.isSettingValueInProgress)
            return;

        var newValue = this.getValue();
        var prevValue = this.prevValue;

        if (_.isEqual(prevValue, newValue))
            return;

        var results = _(this.changeHandlers).map(function (h)
        {
            return h(prevValue, newValue);
        });

        if (_(results).any(function (r) { return r && r.canceled; }))
        {
            this.setValue(prevValue);

            var messages = _(results).chain().filter(function (r) { return r && r.message; }).map(function (r) { return r.message; }).value();
            var showAlert = function (index)
            {
                if (index >= messages.length)
                    return;

                Confirmation.alert(messages[index])
                    .then(function () { showAlert(index + 1); });
            };

            showAlert(0);
        }
        else
            this.prevValue = newValue;
    },
    _validateValue: function (value)
    {
        return this._getView().validateValue(value);
    },

    _attachChangeListener: function (listener)
    {
        throw "Not implemented.";
    },
    _detachChangeListener: function (listener)
    {
        throw "Not implemented.";
    },
    _getValueInternal: function ()
    {
        return this._getView().getValue();
    },
    _getReadOnlyValueInternal: function ()
    {
        throw "Not implemented.";
    },
    _setValueInternal: function (value)
    {
        return this._getView().setValueWithoutValidation(value);
    },
    _getValueSchema: function ()
    {
        return this._getView().getValueSchema();
    },
    _getComponent: function ()
    {
        return this._getView().getComponent();
    },
    _throwIfValueCantBeSet: function (value)
    {
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.SingleInputField = awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase(
{
    _attachChangeListener: function (listener)
    {
        this._getComponent().on("blur", listener);
    },
    _detachChangeListener: function (listener)
    {
        this._getComponent().off("blur", listener);
    },
    _getReadOnlyValueInternal: function ()
    {
        return this.model.get("value");
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.AddressField = awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase(
{
    onChange: function ()
    {
        this._throwMethodIsNotSupported("Change");
    },
    offChange: function ()
    {
        this._throwMethodIsNotSupported("Change");
    },

    _getReadOnlyValueInternal: function ()
    {
        var model = this.model;
        return {
            street: model.get("street"),
            line2: model.get("line2"),
            line3: model.get("line3"),
            city: model.get("city"),
            countryCode: model.get("countryCode"),
            state: model.get("state"),
            zip: model.get("zip")
        };
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.MultilineTextField = awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase(
{
    _getReadOnlyValueInternal: function ()
    {
        return this.model.get("value");
    },
    _attachChangeListener: function (listener)
    {
        var component = this._getComponent();
        this._isWysiwyg() ? component.textEditor().on("blur", listener) : component.on("blur", listener);
    },
    _detachChangeListener: function (listener)
    {
        var component = this._getComponent();
        this._isWysiwyg() ? component.textEditor().removeListener("blur", listener) : component.off("blur", listener);
    },
   
    _isWysiwyg: function ()
    {
        return this._getView().isWysiwyg();
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.DropDownListField = awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase(
{
    _getReadOnlyValueInternal: function ()
    {
        return this.model.get("selectedValueId");
    },
    _attachChangeListener: function (listener)
    {
        this._getComponent().on("change", listener);
    },
    _detachChangeListener: function (listener)
    {
        this._getComponent().off("change", listener);
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.RadioListField = awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase(
{
    clearSelection: function ()
    {
        this._$(".resetRadioListSelectedValues:visible a").trigger("click", { suppressHidingFieldsConfirmation: true, suppressChangeEvent: true });
    },
    
    _getReadOnlyValueInternal: function ()
    {
        return this.model.get("selectedValueId");
    },
    _attachChangeListener: function (listener)
    {
        this._getComponent().on("change", listener);
    },
    _detachChangeListener: function (listener)
    {
        this._getComponent().off("change", listener);
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.CheckboxListField = awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase(
{
    _getReadOnlyValueInternal: function ()
    {
        return this.model.get("selectedValueIds");
    },
    _attachChangeListener: function (listener)
    {
        this._getComponent().on("change", listener);
    },
    _detachChangeListener: function (listener)
    {
        this._getComponent().off("change", listener);
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.DateField = awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase(
{
    _getReadOnlyValueInternal: function ()
    {
        return Date.parse(this.model.get("valueUtc"));
    },
    _attachChangeListener: function (listener)
    {
        this._getComponent().on("select", listener);
    },
    _detachChangeListener: function (listener)
    {
        this._getComponent().off("select", listener);
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.TableField = awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase(
{
    onChange: function ()
    {
        this._throwMethodIsNotSupported("Change");
    },
    onRowOpen: function (handler)
    {
        if (!_.isFunction(handler))
            throw new Error("Handler is not a function.");

        var self = this;

        this._getView().on("rowOpened", function (data)
        {
            handler(
            { 
                getField: function (alias)
                {
                    self._validateAlias(alias);

                    return self.fieldFactory.getOrCreate(alias, { id: data.rowId, isEditMode: true });
                }
            });
        });
    },
    offChange: function ()
    {
        this._throwMethodIsNotSupported("Change");
    },
    getValue: function ()
    {
        this._throwMethodIsNotSupported("getValue");
    },
    setValue: function (value)
    {
        this._throwMethodIsNotSupported("setValue");
    },
    hide: function () 
    {
        this._getComponent().cancelCurrentRowEditIfExists();
        this._super("hide");
    },
    addRow: function (rowValues)
    {
        return this._getView().addRow(rowValues);
    },
    removeRow: function (sortOrder)
    {
        this._validateSortOrder(sortOrder);

        var component = this._getComponent();

        return component.removeRowAsync(component.resolveRowIdBySortOrder(sortOrder));
    },
    getRowCount: function ()
    {
        return this._getView().getRowCount();
    },
    getValueInRow: function (sortOrder, alias)
    {
        this._validateSortOrder(sortOrder);
        this._validateAlias(alias);

        return this.fieldFactory.getOrCreate(alias, { id: this._getComponent().resolveRowIdBySortOrder(sortOrder) }).getValue();
    },

    _doesFieldExist: function (alias)
    {
        return this._getView().nestedFields.any(function (f) { return f.get("alias") == alias; });
    },
    _validateSortOrder: function (sortOrder)
    {
        if (!_.isNumber(sortOrder))
            throw new Error("Row index is not a number.");

        if (sortOrder >= this.getRowCount() || sortOrder < 0)
            throw new Error("Row with index " + sortOrder + " doesn't exist.");
    },
    _validateAlias: function (alias)
    {
        if (!_.isString(alias))
            throw new Error("Alias should be a string value.");

        if (!this._doesFieldExist(alias))
            throw new Error("Field with alias '" + alias + "' doesn't exist.");
    },
 
    // Made these methods private since they're not requested in initial spec.
    // But let's keep them here just in case that they'll be requested.
    _setValueInRow: function (sortOrder, value)
    {
        this._validateSortOrder(sortOrder);
        
        Joi.assert(value, this._getView().rowValueSchema.required());

        var component = this._getComponent();
        var rowId = component.resolveRowIdBySortOrder(sortOrder);
        component.setValueInRow(rowId, value);
        component.updateRowFieldValues(sortOrder);
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.FileUploadField = awardsCommon.widgets.formBuilderForm.frontendApi.StatefulFieldBase(
{
    _init: function ()
    {
        this.fileUploader = this._getSection().fileUploader();
        this.isCaptionShown = this.model.get("showCaption");
    },

    uploadFile: function (file)
    {
        if (this.getValue().mediaId)
            throw "File is already uploaded.";

        var self = this;
        return new Promise(function (resolve, reject)
        {
            self.fileUploader.uploadFile(file)
                .then(function () { resolve(self.getValue()); })
                .catch(reject);
        });
    },
    getUrl: function ()
    {
        return this.getValue().mediaId ? this._$(".link").attr("href") : undefined;
    },
    
    _getReadOnlyValueInternal: function ()
    {
        var model = this.model;
        var value = {
            mediaId: model.get("mediaId")
        };

        if (this.isCaptionShown)
            value.caption = model.get("caption");

        return value;
    },
    _attachChangeListener: function (listener)
    {
        $(this.fileUploader).on("uploadIsFinished deleted", listener);
    },
    _detachChangeListener: function (listener)
    {
        $(this.fileUploader).off("uploadIsFinished deleted", listener);
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.DigitalSignatureField = awardsCommon.widgets.formBuilderForm.frontendApi.FieldBase(
{
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.TextField = awardsCommon.widgets.formBuilderForm.frontendApi.SingleInputField(
{
    autocomplete: function (options)
    {
        Joi.object(
        {
            serviceUrl: Joi.string().required(),
            paramName: Joi.string(),
            transformResult: Joi.func(),
            onSelect: Joi.func()
        }).required().validate(options, { abortEarly: false, convert: false });

        this._getComponent().devbridgeAutocomplete(
        {
            serviceUrl: options.serviceUrl,
            paramName: options.paramName,
            transformResult: options.transformResult,
            onSelect: function (s) { options.onSelect(s); }
        });
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.SeparatorField = awardsCommon.widgets.formBuilderForm.frontendApi.FieldBase(
{
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.PhoneNumberField = awardsCommon.widgets.formBuilderForm.frontendApi.SingleInputField(
{
    getSelectedCountry: function ()
    {
        return this._getView().getSelectedCountryCode();
    },
    setCountry: function (countryCode)
    {
        this._getView().setCountryCode(countryCode);
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.ApiBase = oo.CustomBase(
{
    _init: function (formBuilderFormId)
    {
        this.formBuilderForm = $("#" + formBuilderFormId).formBuilderForm();
    },

    getField: function (alias)
    {
        return this._getFieldFactory().getOrCreate(alias);
    },

    _getFieldFactory: function ()
    {
        return this.fieldFactory || (this.fieldFactory = this._createFieldFactory());
    },
    _createFieldFactory: function ()
    {
        throw "Not implemented.";
    }
});;namespace("awardsCommon.widgets.formBuilderForm.frontendApi");
awardsCommon.widgets.formBuilderForm.frontendApi.FieldFactory = oo.createClass(
{
    _create: function (formBuilderForm)
    {
        this.formBuilderForm = formBuilderForm;
        this.cache = new Map();

        this.formBuilderForm.on("fieldModelDeleted", this._onFieldModelDeleted, this);
    },

    getOrCreate: function (alias, rowInfo)
    {
        var fbForm = this.formBuilderForm;

        var fieldId = fbForm.fieldAliasesIds[alias];
        if (!fieldId)
            return undefined;

        var fieldPath = fieldId;
        var rowId;

        if (!_.isNullOrUndefined(rowInfo))
        {
            rowId = rowInfo.id;

            fieldPath = _(fbForm.fieldModels).chain().keys().find(function (k)
            {
                var postfix = rowInfo.isEditMode ? "_inEditMode" : "";
                return k.endsWith("[" + rowId + "]_" + fieldId + postfix);
            }).value();

            if (!fieldPath)
                return undefined;
        }

        var field = fbForm.fieldModels[fieldPath];
        var result = this.cache.get(field);
        if (result)
            return result;

        var options = {
            formBuilderForm: fbForm,
            id: fieldId,
            alias: alias,
            rowId: rowId,
            model: field
        };

        result = this._createFieldApi(field, options);

        if (result)
        {
            this.cache.set(field, result);
            return result;
        }
        else
            throw new Error("Field of type '" + field.get("typeName") + "' is not supported.");
    },

    _createFieldApi: function (field, options)
    {
        if (field.isText())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.TextField(options);

        if (field.isEmail() || field.isUrl() || field.isImisNumber() || field.isNumber())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.SingleInputField(options);

        if (field.isPhoneNumber())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.PhoneNumberField(options);

        if (field.isAddress())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.AddressField(options);

        if (field.isMultilineText())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.MultilineTextField(options);

        if (field.isDropDownList())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.DropDownListField(options);

        if (field.isRadioList())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.RadioListField(options);

        if (field.isCheckBoxList())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.CheckboxListField(options);

        if (field.isDate())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.DateField(options);

        if (field.isDigitalSignature())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.DigitalSignatureField(options);

        if (field.isTable())
        {
            options.fieldFactory = this.iface;
            return new awardsCommon.widgets.formBuilderForm.frontendApi.TableField(options);
        }

        if (field.isFileUpload())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.FileUploadField(options);

        if (field.isSeparator())
            return new awardsCommon.widgets.formBuilderForm.frontendApi.SeparatorField(options);

        return undefined;
    },

    _onFieldModelDeleted: function (model)
    {
        this.cache.delete(model);
    }
});;