{ "version": 3, "sources": ["../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/adapters.js", "../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/logger.js", "../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/connection_monitor.js", "../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/internal.js", "../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/connection.js", "../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/subscription.js", "../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/subscription_guarantor.js", "../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/subscriptions.js", "../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/consumer.js", "../../../node_modules/@hotwired/turbo-rails/node_modules/@rails/actioncable/src/index.js", "../../../node_modules/clipboard/dist/clipboard.js", "../../../node_modules/tributejs/src/utils.js", "../../../node_modules/tributejs/src/TributeEvents.js", "../../../node_modules/tributejs/src/TributeMenuEvents.js", "../../../node_modules/tributejs/src/TributeRange.js", "../../../node_modules/tributejs/src/TributeSearch.js", "../../../node_modules/tributejs/src/Tribute.js", "webpack://inputmask/webpack/universalModuleDefinition", "webpack://inputmask/lib/polyfills/Object.getPrototypeOf.js", "webpack://inputmask/lib/polyfills/Array.includes.js", "webpack://inputmask/lib/polyfills/Object.entries.js", "webpack://inputmask/lib/polyfills/String.includes.js", "webpack://inputmask/lib/global/FormData.js", "webpack://inputmask/lib/extensions/inputmask.extensions.js", "webpack://inputmask/lib/inputmask.js", "webpack://inputmask/lib/defaults.js", "webpack://inputmask/lib/definitions.js", "webpack://inputmask/lib/dependencyLibs/inputmask.dependencyLib.js", "webpack://inputmask/lib/global/window.js", "webpack://inputmask/lib/dependencyLibs/data.js", "webpack://inputmask/lib/dependencyLibs/events.js", "webpack://inputmask/lib/dependencyLibs/extend.js", "webpack://inputmask/lib/eventruler.js", "webpack://inputmask/lib/inputHandling.js", "webpack://inputmask/lib/environment.js", "webpack://inputmask/lib/eventhandlers.js", "webpack://inputmask/lib/keycode.js", "webpack://inputmask/lib/positioning.js", "webpack://inputmask/lib/validation.js", "webpack://inputmask/lib/validation-tests.js", "webpack://inputmask/lib/mask.js", "webpack://inputmask/lib/mask-lexer.js", "webpack://inputmask/lib/escapeRegex.js", "webpack://inputmask/lib/masktoken.js", "webpack://inputmask/lib/extensions/inputmask.date.extensions.js", "webpack://inputmask/lib/extensions/inputmask.date.i18n.js", "webpack://inputmask/lib/extensions/inputmask.numeric.extensions.js", "webpack://inputmask/lib/inputmaskElement.js", "webpack://inputmask/webpack/bootstrap", "webpack://inputmask/bundle.js", "../../javascript/src/confirm.js", "../../javascript/src/direct_uploads.js", "../../javascript/src/lazysrc.js", "../../../node_modules/jstz/dist/jstz.js", "../../../node_modules/jstz/index.js", "../../../node_modules/@rails/activestorage/app/assets/javascripts/activestorage.js", "../../../node_modules/local-time/app/assets/javascripts/local-time.es2017-umd.js", "../../../node_modules/@hotwired/turbo/dist/turbo.es2017-esm.js", "../../../node_modules/@hotwired/turbo-rails/app/javascript/turbo/cable.js", "../../../node_modules/@hotwired/turbo-rails/app/javascript/turbo/snakeize.js", "../../../node_modules/@hotwired/turbo-rails/app/javascript/turbo/cable_stream_source_element.js", "../../../node_modules/@hotwired/turbo-rails/app/javascript/turbo/fetch_requests.js", "../../../node_modules/@hotwired/turbo-rails/app/javascript/turbo/index.js", "../../../node_modules/@hotwired/stimulus/dist/stimulus.js", "../../javascript/controllers/application.js", "../../javascript/controllers/accounts_controller.js", "../../../node_modules/@rails/actioncable/app/assets/javascripts/actioncable.esm.js", "../../javascript/channels/consumer.js", "../../javascript/controllers/acknowledgment_form_controller.js", "../../javascript/controllers/address_autocomplete_controller.js", "../../javascript/controllers/address_components_controller.js", "../../javascript/controllers/alloy_controller.js", "../../../node_modules/@alloyidentity/web-sdk/node_modules/decode-uri-component/index.js", "../../../node_modules/@alloyidentity/web-sdk/node_modules/filter-obj/index.js", "../../../node_modules/@alloyidentity/web-sdk/node_modules/split-on-first/index.js", "../../../node_modules/@alloyidentity/web-sdk/node_modules/query-string/base.js", "../../../node_modules/@alloyidentity/web-sdk/node_modules/uuid/dist/esm-browser/stringify.js", "../../../node_modules/@alloyidentity/web-sdk/node_modules/uuid/dist/esm-browser/rng.js", "../../../node_modules/@alloyidentity/web-sdk/node_modules/uuid/dist/esm-browser/native.js", "../../../node_modules/@alloyidentity/web-sdk/node_modules/uuid/dist/esm-browser/v4.js", "../../../node_modules/@alloyidentity/web-sdk/src/version.js", "../../javascript/controllers/area_choice_controller.js", "../../javascript/controllers/autogrow_controller.js", "../../javascript/controllers/bulk_controller.js", "../../javascript/controllers/bulk_upload_controller.js", "../../javascript/controllers/clipboard_controller.js", "../../../node_modules/@popperjs/core/lib/enums.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getNodeName.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getWindow.js", "../../../node_modules/@popperjs/core/lib/dom-utils/instanceOf.js", "../../../node_modules/@popperjs/core/lib/modifiers/applyStyles.js", "../../../node_modules/@popperjs/core/lib/utils/getBasePlacement.js", "../../../node_modules/@popperjs/core/lib/utils/math.js", "../../../node_modules/@popperjs/core/lib/utils/userAgent.js", "../../../node_modules/@popperjs/core/lib/dom-utils/isLayoutViewport.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getBoundingClientRect.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getLayoutRect.js", "../../../node_modules/@popperjs/core/lib/dom-utils/contains.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js", "../../../node_modules/@popperjs/core/lib/dom-utils/isTableElement.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getDocumentElement.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getParentNode.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getOffsetParent.js", "../../../node_modules/@popperjs/core/lib/utils/getMainAxisFromPlacement.js", "../../../node_modules/@popperjs/core/lib/utils/within.js", "../../../node_modules/@popperjs/core/lib/utils/getFreshSideObject.js", "../../../node_modules/@popperjs/core/lib/utils/mergePaddingObject.js", "../../../node_modules/@popperjs/core/lib/utils/expandToHashMap.js", "../../../node_modules/@popperjs/core/lib/modifiers/arrow.js", "../../../node_modules/@popperjs/core/lib/utils/getVariation.js", "../../../node_modules/@popperjs/core/lib/modifiers/computeStyles.js", "../../../node_modules/@popperjs/core/lib/modifiers/eventListeners.js", "../../../node_modules/@popperjs/core/lib/utils/getOppositePlacement.js", "../../../node_modules/@popperjs/core/lib/utils/getOppositeVariationPlacement.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getWindowScroll.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getWindowScrollBarX.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getViewportRect.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getDocumentRect.js", "../../../node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getScrollParent.js", "../../../node_modules/@popperjs/core/lib/dom-utils/listScrollParents.js", "../../../node_modules/@popperjs/core/lib/utils/rectToClientRect.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getClippingRect.js", "../../../node_modules/@popperjs/core/lib/utils/computeOffsets.js", "../../../node_modules/@popperjs/core/lib/utils/detectOverflow.js", "../../../node_modules/@popperjs/core/lib/utils/computeAutoPlacement.js", "../../../node_modules/@popperjs/core/lib/modifiers/flip.js", "../../../node_modules/@popperjs/core/lib/modifiers/hide.js", "../../../node_modules/@popperjs/core/lib/modifiers/offset.js", "../../../node_modules/@popperjs/core/lib/modifiers/popperOffsets.js", "../../../node_modules/@popperjs/core/lib/utils/getAltAxis.js", "../../../node_modules/@popperjs/core/lib/modifiers/preventOverflow.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getHTMLElementScroll.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getNodeScroll.js", "../../../node_modules/@popperjs/core/lib/dom-utils/getCompositeRect.js", "../../../node_modules/@popperjs/core/lib/utils/orderModifiers.js", "../../../node_modules/@popperjs/core/lib/utils/debounce.js", "../../../node_modules/@popperjs/core/lib/utils/format.js", "../../../node_modules/@popperjs/core/lib/utils/validateModifiers.js", "../../../node_modules/@popperjs/core/lib/utils/uniqueBy.js", "../../../node_modules/@popperjs/core/lib/utils/mergeByName.js", "../../../node_modules/@popperjs/core/lib/createPopper.js", "../../../node_modules/@popperjs/core/lib/popper.js", "../../../node_modules/tippy.js/src/constants.ts", "../../../node_modules/tippy.js/src/utils.ts", "../../../node_modules/tippy.js/src/dom-utils.ts", "../../../node_modules/tippy.js/src/bindGlobalEventListeners.ts", "../../../node_modules/tippy.js/src/browser.ts", "../../../node_modules/tippy.js/src/validation.ts", "../../../node_modules/tippy.js/src/props.ts", "../../../node_modules/tippy.js/src/template.ts", "../../../node_modules/tippy.js/src/createTippy.ts", "../../../node_modules/tippy.js/src/index.ts", "../../../node_modules/tippy.js/src/addons/createSingleton.ts", "../../../node_modules/tippy.js/src/addons/delegate.ts", "../../../node_modules/tippy.js/src/plugins/animateFill.ts", "../../../node_modules/tippy.js/src/plugins/followCursor.ts", "../../../node_modules/tippy.js/src/plugins/inlinePositioning.ts", "../../../node_modules/tippy.js/src/plugins/sticky.ts", "../../../node_modules/tippy.js/build/base.js", "../../javascript/controllers/collapsible_section_controller.js", "../../javascript/controllers/command_palette_controller.js", "../../../node_modules/@lit/reactive-element/src/css-tag.ts", "../../../node_modules/@lit/reactive-element/src/reactive-element.ts", "../../../node_modules/lit-html/src/lit-html.ts", "../../../node_modules/lit-element/src/lit-element.ts", "../../../node_modules/@lit/reactive-element/src/decorators/custom-element.ts", "../../../node_modules/@lit/reactive-element/src/decorators/property.ts", "../../../node_modules/@lit/reactive-element/src/decorators/state.ts", "../../../node_modules/@lit/reactive-element/src/decorators/query-assigned-elements.ts", "../../../node_modules/lit-html/src/directive.ts", "../../../node_modules/lit-html/src/directive-helpers.ts", "../../../node_modules/lit-html/src/directives/repeat.ts", "../../../node_modules/lit-html/src/directives/live.ts", "../../../node_modules/lit-html/src/async-directive.ts", "../../../node_modules/lit-html/src/directives/ref.ts", "../../../node_modules/lit-html/src/directives/class-map.ts", "../../../node_modules/hotkeys-js/dist/hotkeys.esm.js", "../../../node_modules/@gorails/ninja-keys/src/ninja-header.ts", "../../../node_modules/lit-html/src/directives/unsafe-html.ts", "../../../node_modules/@material/mwc-icon/node_modules/tslib/tslib.es6.js", "../../../node_modules/@material/mwc-icon/mwc-icon-host.css.ts", "../../../node_modules/@material/mwc-icon/mwc-icon.ts", "../../../node_modules/@gorails/ninja-keys/src/ninja-action.ts", "../../../node_modules/@gorails/ninja-keys/src/ninja-footer.ts", "../../../node_modules/@gorails/ninja-keys/src/base-styles.ts", "../../../node_modules/@gorails/ninja-keys/src/ninja-keys.ts", "../../javascript/controllers/deal_tabs_controller.js", "../../javascript/controllers/document_type_context_controller.js", "../../javascript/controllers/dropdown_controller.js", "../../javascript/controllers/eligibility_rule_form_controller.js", "../../../node_modules/tom-select/src/contrib/microevent.ts", "../../../node_modules/tom-select/src/contrib/microplugin.ts", "../../../node_modules/@orchidjs/unicode-variants/lib/regex.ts", "../../../node_modules/@orchidjs/unicode-variants/lib/strings.ts", "../../../node_modules/@orchidjs/unicode-variants/lib/index.ts", "../../../node_modules/@orchidjs/sifter/lib/utils.ts", "../../../node_modules/@orchidjs/sifter/lib/sifter.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/contrib/highlight.ts", "../../../node_modules/tom-select/src/constants.ts", "../../../node_modules/tom-select/src/defaults.ts", "../../../node_modules/tom-select/src/getSettings.ts", "../../../node_modules/tom-select/src/tom-select.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/plugins/change_listener/plugin.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/plugins/checkbox_options/plugin.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/plugins/clear_button/plugin.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/plugins/drag_drop/plugin.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/plugins/dropdown_header/plugin.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/plugins/caret_position/plugin.ts", "../../../node_modules/tom-select/src/constants.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/plugins/dropdown_input/plugin.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/plugins/input_autogrow/plugin.ts", "../../../node_modules/tom-select/src/plugins/no_backspace_delete/plugin.ts", "../../../node_modules/tom-select/src/plugins/no_active_items/plugin.ts", "../../../node_modules/tom-select/src/constants.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/plugins/optgroup_columns/plugin.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/plugins/remove_button/plugin.ts", "../../../node_modules/tom-select/src/plugins/restore_on_backspace/plugin.ts", "../../../node_modules/tom-select/src/utils.ts", "../../../node_modules/tom-select/src/vanilla.ts", "../../../node_modules/tom-select/src/plugins/virtual_scroll/plugin.ts", "../../../node_modules/tom-select/src/tom-select.complete.ts", "../../javascript/controllers/flyer_generation_controller.js", "../../javascript/controllers/form_field_editor_controller.js", "../../javascript/controllers/form_redirect_controller.js", "../../javascript/controllers/google_analytics_controller.js", "../../javascript/controllers/hubspot_controller.js", "../../javascript/controllers/income_question_controller.js", "../../javascript/controllers/load_recaptcha_v2_controller.js", "../../javascript/controllers/loading_controller.js", "../../javascript/controllers/mentions_controller.js", "../../../node_modules/trix/src/trix/config/attachments.js", "../../../node_modules/trix/src/trix/config/block_attributes.js", "../../../node_modules/trix/src/trix/config/browser.js", "../../../node_modules/trix/src/trix/config/dompurify.js", "../../../node_modules/trix/src/trix/config/lang.js", "../../../node_modules/trix/src/trix/config/file_size_formatting.js", "../../../node_modules/trix/src/trix/constants.js", "../../../node_modules/trix/src/trix/core/helpers/extend.js", "../../../node_modules/trix/src/trix/core/helpers/dom.js", "../../../node_modules/trix/src/trix/config/input.js", "../../../node_modules/trix/src/trix/config/key_names.js", "../../../node_modules/trix/src/trix/config/parser.js", "../../../node_modules/trix/src/trix/config/text_attributes.js", "../../../node_modules/trix/src/trix/config/toolbar.js", "../../../node_modules/trix/src/trix/config/undo.js", "../../../node_modules/trix/src/trix/config/css.js", "../../../node_modules/trix/src/trix/core/basic_object.js", "../../../node_modules/trix/src/trix/core/utilities/utf16_string.js", "../../../node_modules/trix/src/trix/core/object.js", "../../../node_modules/trix/src/trix/core/helpers/arrays.js", "../../../node_modules/trix/src/trix/core/helpers/bidi.js", "../../../node_modules/trix/src/trix/core/helpers/config.js", "../../../node_modules/trix/src/trix/core/helpers/custom_elements.js", "../../../node_modules/trix/src/trix/core/helpers/events.js", "../../../node_modules/trix/src/trix/core/helpers/functions.js", "../../../node_modules/trix/src/trix/core/helpers/objects.js", "../../../node_modules/trix/src/trix/core/helpers/ranges.js", "../../../node_modules/trix/src/trix/observers/selection_change_observer.js", "../../../node_modules/trix/src/trix/core/helpers/strings.js", "../../../node_modules/trix/src/trix/core/collections/hash.js", "../../../node_modules/trix/src/trix/core/collections/object_group.js", "../../../node_modules/trix/src/trix/core/collections/object_map.js", "../../../node_modules/trix/src/trix/core/collections/element_store.js", "../../../node_modules/trix/src/trix/core/utilities/operation.js", "../../../node_modules/trix/src/trix/views/object_view.js", "../../../node_modules/trix/node_modules/dompurify/dist/purify.es.mjs", "../../../node_modules/trix/src/trix/models/html_sanitizer.js", "../../../node_modules/trix/src/trix/views/attachment_view.js", "../../../node_modules/trix/src/trix/views/previewable_attachment_view.js", "../../../node_modules/trix/src/trix/views/piece_view.js", "../../../node_modules/trix/src/trix/views/text_view.js", "../../../node_modules/trix/src/trix/views/block_view.js", "../../../node_modules/trix/src/trix/views/document_view.js", "../../../node_modules/trix/src/trix/models/piece.js", "../../../node_modules/trix/src/trix/operations/image_preload_operation.js", "../../../node_modules/trix/src/trix/models/attachment.js", "../../../node_modules/trix/src/trix/models/attachment_piece.js", "../../../node_modules/trix/src/trix/models/string_piece.js", "../../../node_modules/trix/src/trix/models/splittable_list.js", "../../../node_modules/trix/src/trix/models/text.js", "../../../node_modules/trix/src/trix/models/block.js", "../../../node_modules/trix/src/trix/models/document.js", "../../../node_modules/trix/src/trix/models/html_parser.js", "../../../node_modules/trix/src/trix/core/serialization.js", "../../../node_modules/trix/src/trix/models/managed_attachment.js", "../../../node_modules/trix/src/trix/models/attachment_manager.js", "../../../node_modules/trix/src/trix/models/line_break_insertion.js", "../../../node_modules/trix/src/trix/models/composition.js", "../../../node_modules/trix/src/trix/models/undo_manager.js", "../../../node_modules/trix/src/trix/filters/filter.js", "../../../node_modules/trix/src/trix/filters/attachment_gallery_filter.js", "../../../node_modules/trix/src/trix/models/editor.js", "../../../node_modules/trix/src/trix/models/location_mapper.js", "../../../node_modules/trix/src/trix/models/point_mapper.js", "../../../node_modules/trix/src/trix/models/selection_manager.js", "../../../node_modules/trix/src/trix/controllers/attachment_editor_controller.js", "../../../node_modules/trix/src/trix/controllers/composition_controller.js", "../../../node_modules/trix/src/trix/controllers/controller.js", "../../../node_modules/trix/src/trix/observers/mutation_observer.js", "../../../node_modules/trix/src/trix/operations/file_verification_operation.js", "../../../node_modules/trix/src/trix/models/flaky_android_keyboard_detector.js", "../../../node_modules/trix/src/trix/controllers/input_controller.js", "../../../node_modules/trix/src/trix/controllers/level_0_input_controller.js", "../../../node_modules/trix/src/trix/controllers/level_2_input_controller.js", "../../../node_modules/trix/src/trix/controllers/toolbar_controller.js", "../../../node_modules/trix/src/trix/controllers/editor_controller.js", "../../../node_modules/trix/src/trix/elements/trix_toolbar_element.js", "../../../node_modules/trix/src/trix/elements/trix_editor_element.js", "../../../node_modules/trix/src/trix/trix.js", "../../javascript/controllers/money_mask_controller.js", "../../../node_modules/inputmask/dist/inputmask.mjs", "../../javascript/controllers/notifications_controller.js", "../../javascript/controllers/property_tools_controller.js", "../../javascript/controllers/quiz_controller.js", "../../javascript/controllers/redirect_controller.js", "../../javascript/controllers/repairs_intake_controller.js", "../../javascript/controllers/request_flow_controller.js", "../../javascript/controllers/schedule_c_controller.js", "../../javascript/controllers/select_controller.js", "../../javascript/controllers/show_section_controller.js", "../../javascript/controllers/state_controller.js", "../../../node_modules/@rails/request.js/src/fetch_response.js", "../../../node_modules/@rails/request.js/src/request_interceptor.js", "../../../node_modules/@rails/request.js/src/lib/utils.js", "../../../node_modules/@rails/request.js/src/fetch_request.js", "../../../node_modules/@rails/request.js/src/verbs.js", "../../javascript/controllers/theme_controller.js", "../../javascript/controllers/thumbtack_search_controller.js", "../../javascript/controllers/tooltip_controller.js", "../../javascript/controllers/truv_controller.js", "../../javascript/controllers/turbo_native/sign_out_controller.js", "rails:/tmp/build_37276744/app/javascript/controllers/**/*_controller.js", "../../../node_modules/tailwindcss-stimulus-components/dist/tailwindcss-stimulus-components.module.js", "../../../node_modules/stimulus/dist/stimulus.js", "../../../node_modules/flatpickr/dist/esm/types/options.js", "../../../node_modules/flatpickr/dist/esm/l10n/default.js", "../../../node_modules/flatpickr/dist/esm/utils/index.js", "../../../node_modules/flatpickr/dist/esm/utils/dom.js", "../../../node_modules/flatpickr/dist/esm/utils/formatting.js", "../../../node_modules/flatpickr/dist/esm/utils/dates.js", "../../../node_modules/flatpickr/dist/esm/utils/polyfills.js", "../../../node_modules/flatpickr/dist/esm/index.js", "../../../node_modules/stimulus-flatpickr/src/utils.js", "../../../node_modules/stimulus-flatpickr/src/config_options.js", "../../../node_modules/stimulus-flatpickr/src/events.js", "../../../node_modules/stimulus-flatpickr/src/elements.js", "../../../node_modules/stimulus-flatpickr/src/strftime_mapping.js", "../../../node_modules/stimulus-flatpickr/src/index.js", "../../javascript/controllers/index.js", "../../../node_modules/@rails/actiontext/app/assets/javascripts/actiontext.esm.js", "../../javascript/src/actiontext.js", "rails:/tmp/build_37276744/app/javascript/src/**/*", "../../javascript/src/lead_event.js", "../../../node_modules/js-cookie/dist/js.cookie.mjs", "../../javascript/src/timezone.js", "../../javascript/src/turbo_native/bridge.js", "../../javascript/src/turbo_streams.js", "../../javascript/application.js"], "sourcesContent": ["export default {\n logger: typeof console !== \"undefined\" ? console : undefined,\n WebSocket: typeof WebSocket !== \"undefined\" ? WebSocket : undefined,\n}\n", "import adapters from \"./adapters\"\n\n// The logger is disabled by default. You can enable it with:\n//\n// ActionCable.logger.enabled = true\n//\n// Example:\n//\n// import * as ActionCable from '@rails/actioncable'\n//\n// ActionCable.logger.enabled = true\n// ActionCable.logger.log('Connection Established.')\n//\n\nexport default {\n log(...messages) {\n if (this.enabled) {\n messages.push(Date.now())\n adapters.logger.log(\"[ActionCable]\", ...messages)\n }\n },\n}\n", "import logger from \"./logger\"\n\n// Responsible for ensuring the cable connection is in good health by validating the heartbeat pings sent from the server, and attempting\n// revival reconnections if things go astray. Internal class, not intended for direct user manipulation.\n\nconst now = () => new Date().getTime()\n\nconst secondsSince = time => (now() - time) / 1000\n\nclass ConnectionMonitor {\n constructor(connection) {\n this.visibilityDidChange = this.visibilityDidChange.bind(this)\n this.connection = connection\n this.reconnectAttempts = 0\n }\n\n start() {\n if (!this.isRunning()) {\n this.startedAt = now()\n delete this.stoppedAt\n this.startPolling()\n addEventListener(\"visibilitychange\", this.visibilityDidChange)\n logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`)\n }\n }\n\n stop() {\n if (this.isRunning()) {\n this.stoppedAt = now()\n this.stopPolling()\n removeEventListener(\"visibilitychange\", this.visibilityDidChange)\n logger.log(\"ConnectionMonitor stopped\")\n }\n }\n\n isRunning() {\n return this.startedAt && !this.stoppedAt\n }\n\n recordPing() {\n this.pingedAt = now()\n }\n\n recordConnect() {\n this.reconnectAttempts = 0\n this.recordPing()\n delete this.disconnectedAt\n logger.log(\"ConnectionMonitor recorded connect\")\n }\n\n recordDisconnect() {\n this.disconnectedAt = now()\n logger.log(\"ConnectionMonitor recorded disconnect\")\n }\n\n // Private\n\n startPolling() {\n this.stopPolling()\n this.poll()\n }\n\n stopPolling() {\n clearTimeout(this.pollTimeout)\n }\n\n poll() {\n this.pollTimeout = setTimeout(() => {\n this.reconnectIfStale()\n this.poll()\n }\n , this.getPollInterval())\n }\n\n getPollInterval() {\n const { staleThreshold, reconnectionBackoffRate } = this.constructor\n const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10))\n const jitterMax = this.reconnectAttempts === 0 ? 1.0 : reconnectionBackoffRate\n const jitter = jitterMax * Math.random()\n return staleThreshold * 1000 * backoff * (1 + jitter)\n }\n\n reconnectIfStale() {\n if (this.connectionIsStale()) {\n logger.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`)\n this.reconnectAttempts++\n if (this.disconnectedRecently()) {\n logger.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`)\n } else {\n logger.log(\"ConnectionMonitor reopening\")\n this.connection.reopen()\n }\n }\n }\n\n get refreshedAt() {\n return this.pingedAt ? this.pingedAt : this.startedAt\n }\n\n connectionIsStale() {\n return secondsSince(this.refreshedAt) > this.constructor.staleThreshold\n }\n\n disconnectedRecently() {\n return this.disconnectedAt && (secondsSince(this.disconnectedAt) < this.constructor.staleThreshold)\n }\n\n visibilityDidChange() {\n if (document.visibilityState === \"visible\") {\n setTimeout(() => {\n if (this.connectionIsStale() || !this.connection.isOpen()) {\n logger.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`)\n this.connection.reopen()\n }\n }\n , 200)\n }\n }\n\n}\n\nConnectionMonitor.staleThreshold = 6 // Server::Connections::BEAT_INTERVAL * 2 (missed two pings)\nConnectionMonitor.reconnectionBackoffRate = 0.15\n\nexport default ConnectionMonitor\n", "export default {\n \"message_types\": {\n \"welcome\": \"welcome\",\n \"disconnect\": \"disconnect\",\n \"ping\": \"ping\",\n \"confirmation\": \"confirm_subscription\",\n \"rejection\": \"reject_subscription\"\n },\n \"disconnect_reasons\": {\n \"unauthorized\": \"unauthorized\",\n \"invalid_request\": \"invalid_request\",\n \"server_restart\": \"server_restart\",\n \"remote\": \"remote\"\n },\n \"default_mount_path\": \"/cable\",\n \"protocols\": [\n \"actioncable-v1-json\",\n \"actioncable-unsupported\"\n ]\n}\n", "import adapters from \"./adapters\"\nimport ConnectionMonitor from \"./connection_monitor\"\nimport INTERNAL from \"./internal\"\nimport logger from \"./logger\"\n\n// Encapsulate the cable connection held by the consumer. This is an internal class not intended for direct user manipulation.\n\nconst {message_types, protocols} = INTERNAL\nconst supportedProtocols = protocols.slice(0, protocols.length - 1)\n\nconst indexOf = [].indexOf\n\nclass Connection {\n constructor(consumer) {\n this.open = this.open.bind(this)\n this.consumer = consumer\n this.subscriptions = this.consumer.subscriptions\n this.monitor = new ConnectionMonitor(this)\n this.disconnected = true\n }\n\n send(data) {\n if (this.isOpen()) {\n this.webSocket.send(JSON.stringify(data))\n return true\n } else {\n return false\n }\n }\n\n open() {\n if (this.isActive()) {\n logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`)\n return false\n } else {\n const socketProtocols = [...protocols, ...this.consumer.subprotocols || []]\n logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${socketProtocols}`)\n if (this.webSocket) { this.uninstallEventHandlers() }\n this.webSocket = new adapters.WebSocket(this.consumer.url, socketProtocols)\n this.installEventHandlers()\n this.monitor.start()\n return true\n }\n }\n\n close({allowReconnect} = {allowReconnect: true}) {\n if (!allowReconnect) { this.monitor.stop() }\n // Avoid closing websockets in a \"connecting\" state due to Safari 15.1+ bug. See: https://github.com/rails/rails/issues/43835#issuecomment-1002288478\n if (this.isOpen()) {\n return this.webSocket.close()\n }\n }\n\n reopen() {\n logger.log(`Reopening WebSocket, current state is ${this.getState()}`)\n if (this.isActive()) {\n try {\n return this.close()\n } catch (error) {\n logger.log(\"Failed to reopen WebSocket\", error)\n }\n finally {\n logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`)\n setTimeout(this.open, this.constructor.reopenDelay)\n }\n } else {\n return this.open()\n }\n }\n\n getProtocol() {\n if (this.webSocket) {\n return this.webSocket.protocol\n }\n }\n\n isOpen() {\n return this.isState(\"open\")\n }\n\n isActive() {\n return this.isState(\"open\", \"connecting\")\n }\n\n triedToReconnect() {\n return this.monitor.reconnectAttempts > 0\n }\n\n // Private\n\n isProtocolSupported() {\n return indexOf.call(supportedProtocols, this.getProtocol()) >= 0\n }\n\n isState(...states) {\n return indexOf.call(states, this.getState()) >= 0\n }\n\n getState() {\n if (this.webSocket) {\n for (let state in adapters.WebSocket) {\n if (adapters.WebSocket[state] === this.webSocket.readyState) {\n return state.toLowerCase()\n }\n }\n }\n return null\n }\n\n installEventHandlers() {\n for (let eventName in this.events) {\n const handler = this.events[eventName].bind(this)\n this.webSocket[`on${eventName}`] = handler\n }\n }\n\n uninstallEventHandlers() {\n for (let eventName in this.events) {\n this.webSocket[`on${eventName}`] = function() {}\n }\n }\n\n}\n\nConnection.reopenDelay = 500\n\nConnection.prototype.events = {\n message(event) {\n if (!this.isProtocolSupported()) { return }\n const {identifier, message, reason, reconnect, type} = JSON.parse(event.data)\n switch (type) {\n case message_types.welcome:\n if (this.triedToReconnect()) {\n this.reconnectAttempted = true\n }\n this.monitor.recordConnect()\n return this.subscriptions.reload()\n case message_types.disconnect:\n logger.log(`Disconnecting. Reason: ${reason}`)\n return this.close({allowReconnect: reconnect})\n case message_types.ping:\n return this.monitor.recordPing()\n case message_types.confirmation:\n this.subscriptions.confirmSubscription(identifier)\n if (this.reconnectAttempted) {\n this.reconnectAttempted = false\n return this.subscriptions.notify(identifier, \"connected\", {reconnected: true})\n } else {\n return this.subscriptions.notify(identifier, \"connected\", {reconnected: false})\n }\n case message_types.rejection:\n return this.subscriptions.reject(identifier)\n default:\n return this.subscriptions.notify(identifier, \"received\", message)\n }\n },\n\n open() {\n logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`)\n this.disconnected = false\n if (!this.isProtocolSupported()) {\n logger.log(\"Protocol is unsupported. Stopping monitor and disconnecting.\")\n return this.close({allowReconnect: false})\n }\n },\n\n close(event) {\n logger.log(\"WebSocket onclose event\")\n if (this.disconnected) { return }\n this.disconnected = true\n this.monitor.recordDisconnect()\n return this.subscriptions.notifyAll(\"disconnected\", {willAttemptReconnect: this.monitor.isRunning()})\n },\n\n error() {\n logger.log(\"WebSocket onerror event\")\n }\n}\n\nexport default Connection\n", "// A new subscription is created through the ActionCable.Subscriptions instance available on the consumer.\n// It provides a number of callbacks and a method for calling remote procedure calls on the corresponding\n// Channel instance on the server side.\n//\n// An example demonstrates the basic functionality:\n//\n// App.appearance = App.cable.subscriptions.create(\"AppearanceChannel\", {\n// connected() {\n// // Called once the subscription has been successfully completed\n// },\n//\n// disconnected({ willAttemptReconnect: boolean }) {\n// // Called when the client has disconnected with the server.\n// // The object will have an `willAttemptReconnect` property which\n// // says whether the client has the intention of attempting\n// // to reconnect.\n// },\n//\n// appear() {\n// this.perform('appear', {appearing_on: this.appearingOn()})\n// },\n//\n// away() {\n// this.perform('away')\n// },\n//\n// appearingOn() {\n// $('main').data('appearing-on')\n// }\n// })\n//\n// The methods #appear and #away forward their intent to the remote AppearanceChannel instance on the server\n// by calling the `perform` method with the first parameter being the action (which maps to AppearanceChannel#appear/away).\n// The second parameter is a hash that'll get JSON encoded and made available on the server in the data parameter.\n//\n// This is how the server component would look:\n//\n// class AppearanceChannel < ApplicationActionCable::Channel\n// def subscribed\n// current_user.appear\n// end\n//\n// def unsubscribed\n// current_user.disappear\n// end\n//\n// def appear(data)\n// current_user.appear on: data['appearing_on']\n// end\n//\n// def away\n// current_user.away\n// end\n// end\n//\n// The \"AppearanceChannel\" name is automatically mapped between the client-side subscription creation and the server-side Ruby class name.\n// The AppearanceChannel#appear/away public methods are exposed automatically to client-side invocation through the perform method.\n\nconst extend = function(object, properties) {\n if (properties != null) {\n for (let key in properties) {\n const value = properties[key]\n object[key] = value\n }\n }\n return object\n}\n\nexport default class Subscription {\n constructor(consumer, params = {}, mixin) {\n this.consumer = consumer\n this.identifier = JSON.stringify(params)\n extend(this, mixin)\n }\n\n // Perform a channel action with the optional data passed as an attribute\n perform(action, data = {}) {\n data.action = action\n return this.send(data)\n }\n\n send(data) {\n return this.consumer.send({command: \"message\", identifier: this.identifier, data: JSON.stringify(data)})\n }\n\n unsubscribe() {\n return this.consumer.subscriptions.remove(this)\n }\n}\n", "import logger from \"./logger\"\n\n// Responsible for ensuring channel subscribe command is confirmed, retrying until confirmation is received.\n// Internal class, not intended for direct user manipulation.\n\nclass SubscriptionGuarantor {\n constructor(subscriptions) {\n this.subscriptions = subscriptions\n this.pendingSubscriptions = []\n }\n\n guarantee(subscription) {\n if(this.pendingSubscriptions.indexOf(subscription) == -1){ \n logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`)\n this.pendingSubscriptions.push(subscription) \n }\n else {\n logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`)\n }\n this.startGuaranteeing()\n }\n\n forget(subscription) {\n logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`)\n this.pendingSubscriptions = (this.pendingSubscriptions.filter((s) => s !== subscription))\n }\n\n startGuaranteeing() {\n this.stopGuaranteeing()\n this.retrySubscribing()\n }\n \n stopGuaranteeing() {\n clearTimeout(this.retryTimeout)\n }\n\n retrySubscribing() {\n this.retryTimeout = setTimeout(() => {\n if (this.subscriptions && typeof(this.subscriptions.subscribe) === \"function\") {\n this.pendingSubscriptions.map((subscription) => {\n logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`)\n this.subscriptions.subscribe(subscription)\n })\n }\n }\n , 500)\n }\n}\n\nexport default SubscriptionGuarantor", "import Subscription from \"./subscription\"\nimport SubscriptionGuarantor from \"./subscription_guarantor\"\nimport logger from \"./logger\"\n\n// Collection class for creating (and internally managing) channel subscriptions.\n// The only method intended to be triggered by the user is ActionCable.Subscriptions#create,\n// and it should be called through the consumer like so:\n//\n// App = {}\n// App.cable = ActionCable.createConsumer(\"ws://example.com/accounts/1\")\n// App.appearance = App.cable.subscriptions.create(\"AppearanceChannel\")\n//\n// For more details on how you'd configure an actual channel subscription, see ActionCable.Subscription.\n\nexport default class Subscriptions {\n constructor(consumer) {\n this.consumer = consumer\n this.guarantor = new SubscriptionGuarantor(this)\n this.subscriptions = []\n }\n\n create(channelName, mixin) {\n const channel = channelName\n const params = typeof channel === \"object\" ? channel : {channel}\n const subscription = new Subscription(this.consumer, params, mixin)\n return this.add(subscription)\n }\n\n // Private\n\n add(subscription) {\n this.subscriptions.push(subscription)\n this.consumer.ensureActiveConnection()\n this.notify(subscription, \"initialized\")\n this.subscribe(subscription)\n return subscription\n }\n\n remove(subscription) {\n this.forget(subscription)\n if (!this.findAll(subscription.identifier).length) {\n this.sendCommand(subscription, \"unsubscribe\")\n }\n return subscription\n }\n\n reject(identifier) {\n return this.findAll(identifier).map((subscription) => {\n this.forget(subscription)\n this.notify(subscription, \"rejected\")\n return subscription\n })\n }\n\n forget(subscription) {\n this.guarantor.forget(subscription)\n this.subscriptions = (this.subscriptions.filter((s) => s !== subscription))\n return subscription\n }\n\n findAll(identifier) {\n return this.subscriptions.filter((s) => s.identifier === identifier)\n }\n\n reload() {\n return this.subscriptions.map((subscription) =>\n this.subscribe(subscription))\n }\n\n notifyAll(callbackName, ...args) {\n return this.subscriptions.map((subscription) =>\n this.notify(subscription, callbackName, ...args))\n }\n\n notify(subscription, callbackName, ...args) {\n let subscriptions\n if (typeof subscription === \"string\") {\n subscriptions = this.findAll(subscription)\n } else {\n subscriptions = [subscription]\n }\n\n return subscriptions.map((subscription) =>\n (typeof subscription[callbackName] === \"function\" ? subscription[callbackName](...args) : undefined))\n }\n\n subscribe(subscription) {\n if (this.sendCommand(subscription, \"subscribe\")) {\n this.guarantor.guarantee(subscription)\n }\n }\n\n confirmSubscription(identifier) {\n logger.log(`Subscription confirmed ${identifier}`)\n this.findAll(identifier).map((subscription) =>\n this.guarantor.forget(subscription))\n }\n\n sendCommand(subscription, command) {\n const {identifier} = subscription\n return this.consumer.send({command, identifier})\n }\n}\n", "import Connection from \"./connection\"\nimport Subscriptions from \"./subscriptions\"\n\n// The ActionCable.Consumer establishes the connection to a server-side Ruby Connection object. Once established,\n// the ActionCable.ConnectionMonitor will ensure that its properly maintained through heartbeats and checking for stale updates.\n// The Consumer instance is also the gateway to establishing subscriptions to desired channels through the #createSubscription\n// method.\n//\n// The following example shows how this can be set up:\n//\n// App = {}\n// App.cable = ActionCable.createConsumer(\"ws://example.com/accounts/1\")\n// App.appearance = App.cable.subscriptions.create(\"AppearanceChannel\")\n//\n// For more details on how you'd configure an actual channel subscription, see ActionCable.Subscription.\n//\n// When a consumer is created, it automatically connects with the server.\n//\n// To disconnect from the server, call\n//\n// App.cable.disconnect()\n//\n// and to restart the connection:\n//\n// App.cable.connect()\n//\n// Any channel subscriptions which existed prior to disconnecting will\n// automatically resubscribe.\n\nexport default class Consumer {\n constructor(url) {\n this._url = url\n this.subscriptions = new Subscriptions(this)\n this.connection = new Connection(this)\n this.subprotocols = []\n }\n\n get url() {\n return createWebSocketURL(this._url)\n }\n\n send(data) {\n return this.connection.send(data)\n }\n\n connect() {\n return this.connection.open()\n }\n\n disconnect() {\n return this.connection.close({allowReconnect: false})\n }\n\n ensureActiveConnection() {\n if (!this.connection.isActive()) {\n return this.connection.open()\n }\n }\n\n addSubProtocol(subprotocol) {\n this.subprotocols = [...this.subprotocols, subprotocol]\n }\n}\n\nexport function createWebSocketURL(url) {\n if (typeof url === \"function\") {\n url = url()\n }\n\n if (url && !/^wss?:/i.test(url)) {\n const a = document.createElement(\"a\")\n a.href = url\n // Fix populating Location properties in IE. Otherwise, protocol will be blank.\n a.href = a.href\n a.protocol = a.protocol.replace(\"http\", \"ws\")\n return a.href\n } else {\n return url\n }\n}\n", "import Connection from \"./connection\"\nimport ConnectionMonitor from \"./connection_monitor\"\nimport Consumer, { createWebSocketURL } from \"./consumer\"\nimport INTERNAL from \"./internal\"\nimport Subscription from \"./subscription\"\nimport Subscriptions from \"./subscriptions\"\nimport SubscriptionGuarantor from \"./subscription_guarantor\"\nimport adapters from \"./adapters\"\nimport logger from \"./logger\"\n\nexport {\n Connection,\n ConnectionMonitor,\n Consumer,\n INTERNAL,\n Subscription,\n Subscriptions,\n SubscriptionGuarantor,\n adapters,\n createWebSocketURL,\n logger,\n}\n\nexport function createConsumer(url = getConfig(\"url\") || INTERNAL.default_mount_path) {\n return new Consumer(url)\n}\n\nexport function getConfig(name) {\n const element = document.head.querySelector(`meta[name='action-cable-${name}']`)\n if (element) {\n return element.getAttribute(\"content\")\n }\n}\n", "/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT \u00A9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _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); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\n});", "if (!Array.prototype.find) {\n Array.prototype.find = function(predicate) {\n if (this === null) {\n throw new TypeError('Array.prototype.find called on null or undefined')\n }\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function')\n }\n var list = Object(this)\n var length = list.length >>> 0\n var thisArg = arguments[1]\n var value\n\n for (var i = 0; i < length; i++) {\n value = list[i]\n if (predicate.call(thisArg, value, i, list)) {\n return value\n }\n }\n return undefined\n }\n}\n\nif (window && typeof window.CustomEvent !== \"function\") {\n function CustomEvent(event, params) {\n params = params || {\n bubbles: false,\n cancelable: false,\n detail: undefined\n }\n var evt = document.createEvent('CustomEvent')\n evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)\n return evt\n }\n\n if (typeof window.Event !== 'undefined') {\n CustomEvent.prototype = window.Event.prototype\n }\n\n window.CustomEvent = CustomEvent\n}", "class TributeEvents {\n constructor(tribute) {\n this.tribute = tribute;\n this.tribute.events = this;\n }\n\n static keys() {\n return [\n {\n key: 9,\n value: \"TAB\"\n },\n {\n key: 8,\n value: \"DELETE\"\n },\n {\n key: 13,\n value: \"ENTER\"\n },\n {\n key: 27,\n value: \"ESCAPE\"\n },\n {\n key: 32,\n value: \"SPACE\"\n },\n {\n key: 38,\n value: \"UP\"\n },\n {\n key: 40,\n value: \"DOWN\"\n }\n ];\n }\n\n bind(element) {\n element.boundKeydown = this.keydown.bind(element, this);\n element.boundKeyup = this.keyup.bind(element, this);\n element.boundInput = this.input.bind(element, this);\n\n element.addEventListener(\"keydown\", element.boundKeydown, false);\n element.addEventListener(\"keyup\", element.boundKeyup, false);\n element.addEventListener(\"input\", element.boundInput, false);\n }\n\n unbind(element) {\n element.removeEventListener(\"keydown\", element.boundKeydown, false);\n element.removeEventListener(\"keyup\", element.boundKeyup, false);\n element.removeEventListener(\"input\", element.boundInput, false);\n\n delete element.boundKeydown;\n delete element.boundKeyup;\n delete element.boundInput;\n }\n\n keydown(instance, event) {\n if (instance.shouldDeactivate(event)) {\n instance.tribute.isActive = false;\n instance.tribute.hideMenu();\n }\n\n let element = this;\n instance.commandEvent = false;\n\n TributeEvents.keys().forEach(o => {\n if (o.key === event.keyCode) {\n instance.commandEvent = true;\n instance.callbacks()[o.value.toLowerCase()](event, element);\n }\n });\n }\n\n input(instance, event) {\n instance.inputEvent = true;\n instance.keyup.call(this, instance, event);\n }\n\n click(instance, event) {\n let tribute = instance.tribute;\n if (tribute.menu && tribute.menu.contains(event.target)) {\n let li = event.target;\n event.preventDefault();\n event.stopPropagation();\n while (li.nodeName.toLowerCase() !== \"li\") {\n li = li.parentNode;\n if (!li || li === tribute.menu) {\n throw new Error(\"cannot find the
  • container for the click\");\n }\n }\n tribute.selectItemAtIndex(li.getAttribute(\"data-index\"), event);\n tribute.hideMenu();\n\n // TODO: should fire with externalTrigger and target is outside of menu\n } else if (tribute.current.element && !tribute.current.externalTrigger) {\n tribute.current.externalTrigger = false;\n setTimeout(() => tribute.hideMenu());\n }\n }\n\n keyup(instance, event) {\n if (instance.inputEvent) {\n instance.inputEvent = false;\n }\n instance.updateSelection(this);\n\n if (event.keyCode === 27) return;\n\n if (!instance.tribute.allowSpaces && instance.tribute.hasTrailingSpace) {\n instance.tribute.hasTrailingSpace = false;\n instance.commandEvent = true;\n instance.callbacks()[\"space\"](event, this);\n return;\n }\n\n if (!instance.tribute.isActive) {\n if (instance.tribute.autocompleteMode) {\n instance.callbacks().triggerChar(event, this, \"\");\n } else {\n let keyCode = instance.getKeyCode(instance, this, event);\n\n if (isNaN(keyCode) || !keyCode) return;\n\n let trigger = instance.tribute.triggers().find(trigger => {\n return trigger.charCodeAt(0) === keyCode;\n });\n\n if (typeof trigger !== \"undefined\") {\n instance.callbacks().triggerChar(event, this, trigger);\n }\n }\n }\n\n if (\n instance.tribute.current.mentionText.length <\n instance.tribute.current.collection.menuShowMinLength\n ) {\n return;\n }\n\n if (\n ((instance.tribute.current.trigger ||\n instance.tribute.autocompleteMode) &&\n instance.commandEvent === false) ||\n (instance.tribute.isActive && event.keyCode === 8)\n ) {\n instance.tribute.showMenuFor(this, true);\n }\n }\n\n shouldDeactivate(event) {\n if (!this.tribute.isActive) return false;\n\n if (this.tribute.current.mentionText.length === 0) {\n let eventKeyPressed = false;\n TributeEvents.keys().forEach(o => {\n if (event.keyCode === o.key) eventKeyPressed = true;\n });\n\n return !eventKeyPressed;\n }\n\n return false;\n }\n\n getKeyCode(instance, el, event) {\n let char;\n let tribute = instance.tribute;\n let info = tribute.range.getTriggerInfo(\n false,\n tribute.hasTrailingSpace,\n true,\n tribute.allowSpaces,\n tribute.autocompleteMode\n );\n\n if (info) {\n return info.mentionTriggerChar.charCodeAt(0);\n } else {\n return false;\n }\n }\n\n updateSelection(el) {\n this.tribute.current.element = el;\n let info = this.tribute.range.getTriggerInfo(\n false,\n this.tribute.hasTrailingSpace,\n true,\n this.tribute.allowSpaces,\n this.tribute.autocompleteMode\n );\n\n if (info) {\n this.tribute.current.selectedPath = info.mentionSelectedPath;\n this.tribute.current.mentionText = info.mentionText;\n this.tribute.current.selectedOffset = info.mentionSelectedOffset;\n }\n }\n\n callbacks() {\n return {\n triggerChar: (e, el, trigger) => {\n let tribute = this.tribute;\n tribute.current.trigger = trigger;\n\n let collectionItem = tribute.collection.find(item => {\n return item.trigger === trigger;\n });\n\n tribute.current.collection = collectionItem;\n\n if (\n tribute.current.mentionText.length >=\n tribute.current.collection.menuShowMinLength &&\n tribute.inputEvent\n ) {\n tribute.showMenuFor(el, true);\n }\n },\n enter: (e, el) => {\n // choose selection\n if (this.tribute.isActive && this.tribute.current.filteredItems) {\n e.preventDefault();\n e.stopPropagation();\n setTimeout(() => {\n this.tribute.selectItemAtIndex(this.tribute.menuSelected, e);\n this.tribute.hideMenu();\n }, 0);\n }\n },\n escape: (e, el) => {\n if (this.tribute.isActive) {\n e.preventDefault();\n e.stopPropagation();\n this.tribute.isActive = false;\n this.tribute.hideMenu();\n }\n },\n tab: (e, el) => {\n // choose first match\n this.callbacks().enter(e, el);\n },\n space: (e, el) => {\n if (this.tribute.isActive) {\n if (this.tribute.spaceSelectsMatch) {\n this.callbacks().enter(e, el);\n } else if (!this.tribute.allowSpaces) {\n e.stopPropagation();\n setTimeout(() => {\n this.tribute.hideMenu();\n this.tribute.isActive = false;\n }, 0);\n }\n }\n },\n up: (e, el) => {\n // navigate up ul\n if (this.tribute.isActive && this.tribute.current.filteredItems) {\n e.preventDefault();\n e.stopPropagation();\n let count = this.tribute.current.filteredItems.length,\n selected = this.tribute.menuSelected;\n\n if (count > selected && selected > 0) {\n this.tribute.menuSelected--;\n this.setActiveLi();\n } else if (selected === 0) {\n this.tribute.menuSelected = count - 1;\n this.setActiveLi();\n this.tribute.menu.scrollTop = this.tribute.menu.scrollHeight;\n }\n }\n },\n down: (e, el) => {\n // navigate down ul\n if (this.tribute.isActive && this.tribute.current.filteredItems) {\n e.preventDefault();\n e.stopPropagation();\n let count = this.tribute.current.filteredItems.length - 1,\n selected = this.tribute.menuSelected;\n\n if (count > selected) {\n this.tribute.menuSelected++;\n this.setActiveLi();\n } else if (count === selected) {\n this.tribute.menuSelected = 0;\n this.setActiveLi();\n this.tribute.menu.scrollTop = 0;\n }\n }\n },\n delete: (e, el) => {\n if (\n this.tribute.isActive &&\n this.tribute.current.mentionText.length < 1\n ) {\n this.tribute.hideMenu();\n } else if (this.tribute.isActive) {\n this.tribute.showMenuFor(el);\n }\n }\n };\n }\n\n setActiveLi(index) {\n let lis = this.tribute.menu.querySelectorAll(\"li\"),\n length = lis.length >>> 0;\n\n if (index) this.tribute.menuSelected = parseInt(index);\n\n for (let i = 0; i < length; i++) {\n let li = lis[i];\n if (i === this.tribute.menuSelected) {\n li.classList.add(this.tribute.current.collection.selectClass);\n\n let liClientRect = li.getBoundingClientRect();\n let menuClientRect = this.tribute.menu.getBoundingClientRect();\n\n if (liClientRect.bottom > menuClientRect.bottom) {\n let scrollDistance = liClientRect.bottom - menuClientRect.bottom;\n this.tribute.menu.scrollTop += scrollDistance;\n } else if (liClientRect.top < menuClientRect.top) {\n let scrollDistance = menuClientRect.top - liClientRect.top;\n this.tribute.menu.scrollTop -= scrollDistance;\n }\n } else {\n li.classList.remove(this.tribute.current.collection.selectClass);\n }\n }\n }\n\n getFullHeight(elem, includeMargin) {\n let height = elem.getBoundingClientRect().height;\n\n if (includeMargin) {\n let style = elem.currentStyle || window.getComputedStyle(elem);\n return (\n height + parseFloat(style.marginTop) + parseFloat(style.marginBottom)\n );\n }\n\n return height;\n }\n}\n\nexport default TributeEvents;\n", "class TributeMenuEvents {\n constructor(tribute) {\n this.tribute = tribute;\n this.tribute.menuEvents = this;\n this.menu = this.tribute.menu;\n }\n\n bind(menu) {\n this.menuClickEvent = this.tribute.events.click.bind(null, this);\n this.menuContainerScrollEvent = this.debounce(\n () => {\n if (this.tribute.isActive) {\n this.tribute.showMenuFor(this.tribute.current.element, false);\n }\n },\n 300,\n false\n );\n this.windowResizeEvent = this.debounce(\n () => {\n if (this.tribute.isActive) {\n this.tribute.range.positionMenuAtCaret(true);\n }\n },\n 300,\n false\n );\n\n // fixes IE11 issues with mousedown\n this.tribute.range\n .getDocument()\n .addEventListener(\"MSPointerDown\", this.menuClickEvent, false);\n this.tribute.range\n .getDocument()\n .addEventListener(\"mousedown\", this.menuClickEvent, false);\n window.addEventListener(\"resize\", this.windowResizeEvent);\n\n if (this.menuContainer) {\n this.menuContainer.addEventListener(\n \"scroll\",\n this.menuContainerScrollEvent,\n false\n );\n } else {\n window.addEventListener(\"scroll\", this.menuContainerScrollEvent);\n }\n }\n\n unbind(menu) {\n this.tribute.range\n .getDocument()\n .removeEventListener(\"mousedown\", this.menuClickEvent, false);\n this.tribute.range\n .getDocument()\n .removeEventListener(\"MSPointerDown\", this.menuClickEvent, false);\n window.removeEventListener(\"resize\", this.windowResizeEvent);\n\n if (this.menuContainer) {\n this.menuContainer.removeEventListener(\n \"scroll\",\n this.menuContainerScrollEvent,\n false\n );\n } else {\n window.removeEventListener(\"scroll\", this.menuContainerScrollEvent);\n }\n }\n\n debounce(func, wait, immediate) {\n var timeout;\n return () => {\n var context = this,\n args = arguments;\n var later = () => {\n timeout = null;\n if (!immediate) func.apply(context, args);\n };\n var callNow = immediate && !timeout;\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n if (callNow) func.apply(context, args);\n };\n }\n}\n\nexport default TributeMenuEvents;\n", "// Thanks to https://github.com/jeff-collins/ment.io\nimport \"./utils\";\n\nclass TributeRange {\n constructor(tribute) {\n this.tribute = tribute\n this.tribute.range = this\n }\n\n getDocument() {\n let iframe\n if (this.tribute.current.collection) {\n iframe = this.tribute.current.collection.iframe\n }\n\n if (!iframe) {\n return document\n }\n\n return iframe.contentWindow.document\n }\n\n positionMenuAtCaret(scrollTo) {\n let context = this.tribute.current,\n coordinates\n\n let info = this.getTriggerInfo(false, this.tribute.hasTrailingSpace, true, this.tribute.allowSpaces, this.tribute.autocompleteMode)\n\n if (typeof info !== 'undefined') {\n\n if(!this.tribute.positionMenu){\n this.tribute.menu.style.cssText = `display: block;`\n return\n }\n\n if (!this.isContentEditable(context.element)) {\n coordinates = this.getTextAreaOrInputUnderlinePosition(this.tribute.current.element,\n info.mentionPosition)\n }\n else {\n coordinates = this.getContentEditableCaretPosition(info.mentionPosition)\n }\n\n this.tribute.menu.style.cssText = `top: ${coordinates.top}px;\n left: ${coordinates.left}px;\n right: ${coordinates.right}px;\n bottom: ${coordinates.bottom}px;\n position: absolute;\n display: block;`\n\n if (coordinates.left === 'auto') {\n this.tribute.menu.style.left = 'auto'\n }\n\n if (coordinates.top === 'auto') {\n this.tribute.menu.style.top = 'auto'\n }\n\n if (scrollTo) this.scrollIntoView()\n\n window.setTimeout(() => {\n let menuDimensions = {\n width: this.tribute.menu.offsetWidth,\n height: this.tribute.menu.offsetHeight\n }\n let menuIsOffScreen = this.isMenuOffScreen(coordinates, menuDimensions)\n\n let menuIsOffScreenHorizontally = window.innerWidth > menuDimensions.width && (menuIsOffScreen.left || menuIsOffScreen.right)\n let menuIsOffScreenVertically = window.innerHeight > menuDimensions.height && (menuIsOffScreen.top || menuIsOffScreen.bottom)\n if (menuIsOffScreenHorizontally || menuIsOffScreenVertically) {\n this.tribute.menu.style.cssText = 'display: none'\n this.positionMenuAtCaret(scrollTo)\n }\n }, 0)\n\n } else {\n this.tribute.menu.style.cssText = 'display: none'\n }\n }\n\n get menuContainerIsBody() {\n return this.tribute.menuContainer === document.body || !this.tribute.menuContainer;\n }\n\n\n selectElement(targetElement, path, offset) {\n let range\n let elem = targetElement\n\n if (path) {\n for (var i = 0; i < path.length; i++) {\n elem = elem.childNodes[path[i]]\n if (elem === undefined) {\n return\n }\n while (elem.length < offset) {\n offset -= elem.length\n elem = elem.nextSibling\n }\n if (elem.childNodes.length === 0 && !elem.length) {\n elem = elem.previousSibling\n }\n }\n }\n let sel = this.getWindowSelection()\n\n range = this.getDocument().createRange()\n range.setStart(elem, offset)\n range.setEnd(elem, offset)\n range.collapse(true)\n\n try {\n sel.removeAllRanges()\n } catch (error) {}\n\n sel.addRange(range)\n targetElement.focus()\n }\n\n replaceTriggerText(text, requireLeadingSpace, hasTrailingSpace, originalEvent, item) {\n let info = this.getTriggerInfo(true, hasTrailingSpace, requireLeadingSpace, this.tribute.allowSpaces, this.tribute.autocompleteMode)\n\n if (info !== undefined) {\n let context = this.tribute.current\n let replaceEvent = new CustomEvent('tribute-replaced', {\n detail: {\n item: item,\n instance: context,\n context: info,\n event: originalEvent,\n }\n })\n\n if (!this.isContentEditable(context.element)) {\n let myField = this.tribute.current.element\n let textSuffix = typeof this.tribute.replaceTextSuffix == 'string'\n ? this.tribute.replaceTextSuffix\n : ' '\n text += textSuffix\n let startPos = info.mentionPosition\n let endPos = info.mentionPosition + info.mentionText.length + textSuffix.length\n if (!this.tribute.autocompleteMode) {\n endPos += info.mentionTriggerChar.length - 1\n }\n myField.value = myField.value.substring(0, startPos) + text +\n myField.value.substring(endPos, myField.value.length)\n myField.selectionStart = startPos + text.length\n myField.selectionEnd = startPos + text.length\n } else {\n // add a space to the end of the pasted text\n let textSuffix = typeof this.tribute.replaceTextSuffix == 'string'\n ? this.tribute.replaceTextSuffix\n : '\\xA0'\n text += textSuffix\n let endPos = info.mentionPosition + info.mentionText.length\n if (!this.tribute.autocompleteMode) {\n endPos += info.mentionTriggerChar.length\n }\n this.pasteHtml(text, info.mentionPosition, endPos)\n }\n\n context.element.dispatchEvent(new CustomEvent('input', { bubbles: true }))\n context.element.dispatchEvent(replaceEvent)\n }\n }\n\n pasteHtml(html, startPos, endPos) {\n let range, sel\n sel = this.getWindowSelection()\n range = this.getDocument().createRange()\n range.setStart(sel.anchorNode, startPos)\n range.setEnd(sel.anchorNode, endPos)\n range.deleteContents()\n\n let el = this.getDocument().createElement('div')\n el.innerHTML = html\n let frag = this.getDocument().createDocumentFragment(),\n node, lastNode\n while ((node = el.firstChild)) {\n lastNode = frag.appendChild(node)\n }\n range.insertNode(frag)\n\n // Preserve the selection\n if (lastNode) {\n range = range.cloneRange()\n range.setStartAfter(lastNode)\n range.collapse(true)\n sel.removeAllRanges()\n sel.addRange(range)\n }\n }\n\n getWindowSelection() {\n if (this.tribute.collection.iframe) {\n return this.tribute.collection.iframe.contentWindow.getSelection()\n }\n\n return window.getSelection()\n }\n\n getNodePositionInParent(element) {\n if (element.parentNode === null) {\n return 0\n }\n\n for (var i = 0; i < element.parentNode.childNodes.length; i++) {\n let node = element.parentNode.childNodes[i]\n\n if (node === element) {\n return i\n }\n }\n }\n\n getContentEditableSelectedPath(ctx) {\n let sel = this.getWindowSelection()\n let selected = sel.anchorNode\n let path = []\n let offset\n\n if (selected != null) {\n let i\n let ce = selected.contentEditable\n while (selected !== null && ce !== 'true') {\n i = this.getNodePositionInParent(selected)\n path.push(i)\n selected = selected.parentNode\n if (selected !== null) {\n ce = selected.contentEditable\n }\n }\n path.reverse()\n\n // getRangeAt may not exist, need alternative\n offset = sel.getRangeAt(0).startOffset\n\n return {\n selected: selected,\n path: path,\n offset: offset\n }\n }\n }\n\n getTextPrecedingCurrentSelection() {\n let context = this.tribute.current,\n text = ''\n\n if (!this.isContentEditable(context.element)) {\n let textComponent = this.tribute.current.element;\n if (textComponent) {\n let startPos = textComponent.selectionStart\n if (textComponent.value && startPos >= 0) {\n text = textComponent.value.substring(0, startPos)\n }\n }\n\n } else {\n let selectedElem = this.getWindowSelection().anchorNode\n\n if (selectedElem != null) {\n let workingNodeContent = selectedElem.textContent\n let selectStartOffset = this.getWindowSelection().getRangeAt(0).startOffset\n\n if (workingNodeContent && selectStartOffset >= 0) {\n text = workingNodeContent.substring(0, selectStartOffset)\n }\n }\n }\n\n return text\n }\n\n getLastWordInText(text) {\n text = text.replace(/\\u00A0/g, ' '); // https://stackoverflow.com/questions/29850407/how-do-i-replace-unicode-character-u00a0-with-a-space-in-javascript\n let wordsArray = text.split(/\\s+/);\n let worldsCount = wordsArray.length - 1\n return wordsArray[worldsCount].trim()\n }\n\n getTriggerInfo(menuAlreadyActive, hasTrailingSpace, requireLeadingSpace, allowSpaces, isAutocomplete) {\n let ctx = this.tribute.current\n let selected, path, offset\n\n if (!this.isContentEditable(ctx.element)) {\n selected = this.tribute.current.element\n } else {\n let selectionInfo = this.getContentEditableSelectedPath(ctx)\n\n if (selectionInfo) {\n selected = selectionInfo.selected\n path = selectionInfo.path\n offset = selectionInfo.offset\n }\n }\n\n let effectiveRange = this.getTextPrecedingCurrentSelection()\n let lastWordOfEffectiveRange = this.getLastWordInText(effectiveRange)\n\n if (isAutocomplete) {\n return {\n mentionPosition: effectiveRange.length - lastWordOfEffectiveRange.length,\n mentionText: lastWordOfEffectiveRange,\n mentionSelectedElement: selected,\n mentionSelectedPath: path,\n mentionSelectedOffset: offset\n }\n }\n\n if (effectiveRange !== undefined && effectiveRange !== null) {\n let mostRecentTriggerCharPos = -1\n let triggerChar\n\n this.tribute.collection.forEach(config => {\n let c = config.trigger\n let idx = config.requireLeadingSpace ?\n this.lastIndexWithLeadingSpace(effectiveRange, c) :\n effectiveRange.lastIndexOf(c)\n\n if (idx > mostRecentTriggerCharPos) {\n mostRecentTriggerCharPos = idx\n triggerChar = c\n requireLeadingSpace = config.requireLeadingSpace\n }\n })\n\n if (mostRecentTriggerCharPos >= 0 &&\n (\n mostRecentTriggerCharPos === 0 ||\n !requireLeadingSpace ||\n /[\\xA0\\s]/g.test(\n effectiveRange.substring(\n mostRecentTriggerCharPos - 1,\n mostRecentTriggerCharPos)\n )\n )\n ) {\n let currentTriggerSnippet = effectiveRange.substring(mostRecentTriggerCharPos + triggerChar.length,\n effectiveRange.length)\n\n triggerChar = effectiveRange.substring(mostRecentTriggerCharPos, mostRecentTriggerCharPos + triggerChar.length)\n let firstSnippetChar = currentTriggerSnippet.substring(0, 1)\n let leadingSpace = currentTriggerSnippet.length > 0 &&\n (\n firstSnippetChar === ' ' ||\n firstSnippetChar === '\\xA0'\n )\n if (hasTrailingSpace) {\n currentTriggerSnippet = currentTriggerSnippet.trim()\n }\n\n let regex = allowSpaces ? /[^\\S ]/g : /[\\xA0\\s]/g;\n\n this.tribute.hasTrailingSpace = regex.test(currentTriggerSnippet);\n\n if (!leadingSpace && (menuAlreadyActive || !(regex.test(currentTriggerSnippet)))) {\n return {\n mentionPosition: mostRecentTriggerCharPos,\n mentionText: currentTriggerSnippet,\n mentionSelectedElement: selected,\n mentionSelectedPath: path,\n mentionSelectedOffset: offset,\n mentionTriggerChar: triggerChar\n }\n }\n }\n }\n }\n\n lastIndexWithLeadingSpace (str, trigger) {\n let reversedStr = str.split('').reverse().join('')\n let index = -1\n\n for (let cidx = 0, len = str.length; cidx < len; cidx++) {\n let firstChar = cidx === str.length - 1\n let leadingSpace = /\\s/.test(reversedStr[cidx + 1])\n\n let match = true\n for (let triggerIdx = trigger.length - 1; triggerIdx >= 0; triggerIdx--) {\n if (trigger[triggerIdx] !== reversedStr[cidx-triggerIdx]) {\n match = false\n break\n }\n }\n\n if (match && (firstChar || leadingSpace)) {\n index = str.length - 1 - cidx\n break\n }\n }\n\n return index\n }\n\n isContentEditable(element) {\n return element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA'\n }\n\n isMenuOffScreen(coordinates, menuDimensions) {\n let windowWidth = window.innerWidth\n let windowHeight = window.innerHeight\n let doc = document.documentElement\n let windowLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0)\n let windowTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)\n\n let menuTop = typeof coordinates.top === 'number' ? coordinates.top : windowTop + windowHeight - coordinates.bottom - menuDimensions.height\n let menuRight = typeof coordinates.right === 'number' ? coordinates.right : coordinates.left + menuDimensions.width\n let menuBottom = typeof coordinates.bottom === 'number' ? coordinates.bottom : coordinates.top + menuDimensions.height\n let menuLeft = typeof coordinates.left === 'number' ? coordinates.left : windowLeft + windowWidth - coordinates.right - menuDimensions.width\n\n return {\n top: menuTop < Math.floor(windowTop),\n right: menuRight > Math.ceil(windowLeft + windowWidth),\n bottom: menuBottom > Math.ceil(windowTop + windowHeight),\n left: menuLeft < Math.floor(windowLeft)\n }\n }\n\n getMenuDimensions() {\n // Width of the menu depends of its contents and position\n // We must check what its width would be without any obstruction\n // This way, we can achieve good positioning for flipping the menu\n let dimensions = {\n width: null,\n height: null\n }\n\n this.tribute.menu.style.cssText = `top: 0px;\n left: 0px;\n position: fixed;\n display: block;\n visibility; hidden;`\n dimensions.width = this.tribute.menu.offsetWidth\n dimensions.height = this.tribute.menu.offsetHeight\n\n this.tribute.menu.style.cssText = `display: none;`\n\n return dimensions\n }\n\n getTextAreaOrInputUnderlinePosition(element, position, flipped) {\n let properties = ['direction', 'boxSizing', 'width', 'height', 'overflowX',\n 'overflowY', 'borderTopWidth', 'borderRightWidth',\n 'borderBottomWidth', 'borderLeftWidth', 'paddingTop',\n 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'fontStyle', 'fontVariant', 'fontWeight', 'fontStretch',\n 'fontSize', 'fontSizeAdjust', 'lineHeight', 'fontFamily',\n 'textAlign', 'textTransform', 'textIndent',\n 'textDecoration', 'letterSpacing', 'wordSpacing'\n ]\n\n let isFirefox = (window.mozInnerScreenX !== null)\n\n let div = this.getDocument().createElement('div')\n div.id = 'input-textarea-caret-position-mirror-div'\n this.getDocument().body.appendChild(div)\n\n let style = div.style\n let computed = window.getComputedStyle ? getComputedStyle(element) : element.currentStyle\n\n style.whiteSpace = 'pre-wrap'\n if (element.nodeName !== 'INPUT') {\n style.wordWrap = 'break-word'\n }\n\n // position off-screen\n style.position = 'absolute'\n style.visibility = 'hidden'\n\n // transfer the element's properties to the div\n properties.forEach(prop => {\n style[prop] = computed[prop]\n })\n\n if (isFirefox) {\n style.width = `${(parseInt(computed.width) - 2)}px`\n if (element.scrollHeight > parseInt(computed.height))\n style.overflowY = 'scroll'\n } else {\n style.overflow = 'hidden'\n }\n\n div.textContent = element.value.substring(0, position)\n\n if (element.nodeName === 'INPUT') {\n div.textContent = div.textContent.replace(/\\s/g, ' ')\n }\n\n let span = this.getDocument().createElement('span')\n span.textContent = element.value.substring(position) || '.'\n div.appendChild(span)\n\n let rect = element.getBoundingClientRect()\n let doc = document.documentElement\n let windowLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0)\n let windowTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)\n\n let top = 0;\n let left = 0;\n if (this.menuContainerIsBody) {\n top = rect.top;\n left = rect.left;\n }\n\n let coordinates = {\n top: top + windowTop + span.offsetTop + parseInt(computed.borderTopWidth) + parseInt(computed.fontSize) - element.scrollTop,\n left: left + windowLeft + span.offsetLeft + parseInt(computed.borderLeftWidth)\n }\n\n let windowWidth = window.innerWidth\n let windowHeight = window.innerHeight\n\n let menuDimensions = this.getMenuDimensions()\n let menuIsOffScreen = this.isMenuOffScreen(coordinates, menuDimensions)\n\n if (menuIsOffScreen.right) {\n coordinates.right = windowWidth - coordinates.left\n coordinates.left = 'auto'\n }\n\n let parentHeight = this.tribute.menuContainer\n ? this.tribute.menuContainer.offsetHeight\n : this.getDocument().body.offsetHeight\n\n if (menuIsOffScreen.bottom) {\n let parentRect = this.tribute.menuContainer\n ? this.tribute.menuContainer.getBoundingClientRect()\n : this.getDocument().body.getBoundingClientRect()\n let scrollStillAvailable = parentHeight - (windowHeight - parentRect.top)\n\n coordinates.bottom = scrollStillAvailable + (windowHeight - rect.top - span.offsetTop)\n coordinates.top = 'auto'\n }\n\n menuIsOffScreen = this.isMenuOffScreen(coordinates, menuDimensions)\n if (menuIsOffScreen.left) {\n coordinates.left = windowWidth > menuDimensions.width\n ? windowLeft + windowWidth - menuDimensions.width\n : windowLeft\n delete coordinates.right\n }\n if (menuIsOffScreen.top) {\n coordinates.top = windowHeight > menuDimensions.height\n ? windowTop + windowHeight - menuDimensions.height\n : windowTop\n delete coordinates.bottom\n }\n\n this.getDocument().body.removeChild(div)\n return coordinates\n }\n\n getContentEditableCaretPosition(selectedNodePosition) {\n let range\n let sel = this.getWindowSelection()\n\n range = this.getDocument().createRange()\n range.setStart(sel.anchorNode, selectedNodePosition)\n range.setEnd(sel.anchorNode, selectedNodePosition)\n\n range.collapse(false)\n\n let rect = range.getBoundingClientRect()\n let doc = document.documentElement\n let windowLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0)\n let windowTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)\n\n let left = rect.left\n let top = rect.top\n\n let coordinates = {\n left: left + windowLeft,\n top: top + rect.height + windowTop\n }\n let windowWidth = window.innerWidth\n let windowHeight = window.innerHeight\n\n let menuDimensions = this.getMenuDimensions()\n let menuIsOffScreen = this.isMenuOffScreen(coordinates, menuDimensions)\n\n if (menuIsOffScreen.right) {\n coordinates.left = 'auto'\n coordinates.right = windowWidth - rect.left - windowLeft\n }\n\n let parentHeight = this.tribute.menuContainer\n ? this.tribute.menuContainer.offsetHeight\n : this.getDocument().body.offsetHeight\n\n if (menuIsOffScreen.bottom) {\n let parentRect = this.tribute.menuContainer\n ? this.tribute.menuContainer.getBoundingClientRect()\n : this.getDocument().body.getBoundingClientRect()\n let scrollStillAvailable = parentHeight - (windowHeight - parentRect.top)\n\n coordinates.top = 'auto'\n coordinates.bottom = scrollStillAvailable + (windowHeight - rect.top)\n }\n\n menuIsOffScreen = this.isMenuOffScreen(coordinates, menuDimensions)\n if (menuIsOffScreen.left) {\n coordinates.left = windowWidth > menuDimensions.width\n ? windowLeft + windowWidth - menuDimensions.width\n : windowLeft\n delete coordinates.right\n }\n if (menuIsOffScreen.top) {\n coordinates.top = windowHeight > menuDimensions.height\n ? windowTop + windowHeight - menuDimensions.height\n : windowTop\n delete coordinates.bottom\n }\n\n if (!this.menuContainerIsBody) {\n coordinates.left = coordinates.left ? coordinates.left - this.tribute.menuContainer.offsetLeft : coordinates.left\n coordinates.top = coordinates.top ? coordinates.top - this.tribute.menuContainer.offsetTop : coordinates.top\n }\n\n return coordinates\n }\n\n scrollIntoView(elem) {\n let reasonableBuffer = 20,\n clientRect\n let maxScrollDisplacement = 100\n let e = this.menu\n\n if (typeof e === 'undefined') return;\n\n while (clientRect === undefined || clientRect.height === 0) {\n clientRect = e.getBoundingClientRect()\n\n if (clientRect.height === 0) {\n e = e.childNodes[0]\n if (e === undefined || !e.getBoundingClientRect) {\n return\n }\n }\n }\n\n let elemTop = clientRect.top\n let elemBottom = elemTop + clientRect.height\n\n if (elemTop < 0) {\n window.scrollTo(0, window.pageYOffset + clientRect.top - reasonableBuffer)\n } else if (elemBottom > window.innerHeight) {\n let maxY = window.pageYOffset + clientRect.top - reasonableBuffer\n\n if (maxY - window.pageYOffset > maxScrollDisplacement) {\n maxY = window.pageYOffset + maxScrollDisplacement\n }\n\n let targetY = window.pageYOffset - (window.innerHeight - elemBottom)\n\n if (targetY > maxY) {\n targetY = maxY\n }\n\n window.scrollTo(0, targetY)\n }\n }\n}\n\n\nexport default TributeRange;\n", "// Thanks to https://github.com/mattyork/fuzzy\nclass TributeSearch {\n constructor(tribute) {\n this.tribute = tribute\n this.tribute.search = this\n }\n\n simpleFilter(pattern, array) {\n return array.filter(string => {\n return this.test(pattern, string)\n })\n }\n\n test(pattern, string) {\n return this.match(pattern, string) !== null\n }\n\n match(pattern, string, opts) {\n opts = opts || {}\n let patternIdx = 0,\n result = [],\n len = string.length,\n totalScore = 0,\n currScore = 0,\n pre = opts.pre || '',\n post = opts.post || '',\n compareString = opts.caseSensitive && string || string.toLowerCase(),\n ch, compareChar\n\n if (opts.skip) {\n return {rendered: string, score: 0}\n }\n\n pattern = opts.caseSensitive && pattern || pattern.toLowerCase()\n\n let patternCache = this.traverse(compareString, pattern, 0, 0, [])\n if (!patternCache) {\n return null\n }\n return {\n rendered: this.render(string, patternCache.cache, pre, post),\n score: patternCache.score\n }\n }\n\n traverse(string, pattern, stringIndex, patternIndex, patternCache) {\n // if the pattern search at end\n if (pattern.length === patternIndex) {\n\n // calculate score and copy the cache containing the indices where it's found\n return {\n score: this.calculateScore(patternCache),\n cache: patternCache.slice()\n }\n }\n\n // if string at end or remaining pattern > remaining string\n if (string.length === stringIndex || pattern.length - patternIndex > string.length - stringIndex) {\n return undefined\n }\n\n let c = pattern[patternIndex]\n let index = string.indexOf(c, stringIndex)\n let best, temp\n\n while (index > -1) {\n patternCache.push(index)\n temp = this.traverse(string, pattern, index + 1, patternIndex + 1, patternCache)\n patternCache.pop()\n\n // if downstream traversal failed, return best answer so far\n if (!temp) {\n return best\n }\n\n if (!best || best.score < temp.score) {\n best = temp\n }\n\n index = string.indexOf(c, index + 1)\n }\n\n return best\n }\n\n calculateScore(patternCache) {\n let score = 0\n let temp = 1\n\n patternCache.forEach((index, i) => {\n if (i > 0) {\n if (patternCache[i - 1] + 1 === index) {\n temp += temp + 1\n }\n else {\n temp = 1\n }\n }\n\n score += temp\n })\n\n return score\n }\n\n render(string, indices, pre, post) {\n var rendered = string.substring(0, indices[0])\n\n indices.forEach((index, i) => {\n rendered += pre + string[index] + post +\n string.substring(index + 1, (indices[i + 1]) ? indices[i + 1] : string.length)\n })\n\n return rendered\n }\n\n filter(pattern, arr, opts) {\n opts = opts || {}\n return arr\n .reduce((prev, element, idx, arr) => {\n let str = element\n\n if (opts.extract) {\n str = opts.extract(element)\n\n if (!str) { // take care of undefineds / nulls / etc.\n str = ''\n }\n }\n\n let rendered = this.match(pattern, str, opts)\n\n if (rendered != null) {\n prev[prev.length] = {\n string: rendered.rendered,\n score: rendered.score,\n index: idx,\n original: element\n }\n }\n\n return prev\n }, [])\n\n .sort((a, b) => {\n let compare = b.score - a.score\n if (compare) return compare\n return a.index - b.index\n })\n }\n}\n\nexport default TributeSearch;\n", "import \"./utils\";\nimport TributeEvents from \"./TributeEvents\";\nimport TributeMenuEvents from \"./TributeMenuEvents\";\nimport TributeRange from \"./TributeRange\";\nimport TributeSearch from \"./TributeSearch\";\n\nclass Tribute {\n constructor({\n values = null,\n iframe = null,\n selectClass = \"highlight\",\n containerClass = \"tribute-container\",\n itemClass = \"\",\n trigger = \"@\",\n autocompleteMode = false,\n selectTemplate = null,\n menuItemTemplate = null,\n lookup = \"key\",\n fillAttr = \"value\",\n collection = null,\n menuContainer = null,\n noMatchTemplate = null,\n requireLeadingSpace = true,\n allowSpaces = false,\n replaceTextSuffix = null,\n positionMenu = true,\n spaceSelectsMatch = false,\n searchOpts = {},\n menuItemLimit = null,\n menuShowMinLength = 0\n }) {\n this.autocompleteMode = autocompleteMode;\n this.menuSelected = 0;\n this.current = {};\n this.inputEvent = false;\n this.isActive = false;\n this.menuContainer = menuContainer;\n this.allowSpaces = allowSpaces;\n this.replaceTextSuffix = replaceTextSuffix;\n this.positionMenu = positionMenu;\n this.hasTrailingSpace = false;\n this.spaceSelectsMatch = spaceSelectsMatch;\n\n if (this.autocompleteMode) {\n trigger = \"\";\n allowSpaces = false;\n }\n\n if (values) {\n this.collection = [\n {\n // symbol that starts the lookup\n trigger: trigger,\n\n // is it wrapped in an iframe\n iframe: iframe,\n\n // class applied to selected item\n selectClass: selectClass,\n\n // class applied to the Container\n containerClass: containerClass,\n\n // class applied to each item\n itemClass: itemClass,\n\n // function called on select that retuns the content to insert\n selectTemplate: (\n selectTemplate || Tribute.defaultSelectTemplate\n ).bind(this),\n\n // function called that returns content for an item\n menuItemTemplate: (\n menuItemTemplate || Tribute.defaultMenuItemTemplate\n ).bind(this),\n\n // function called when menu is empty, disables hiding of menu.\n noMatchTemplate: (t => {\n if (typeof t === \"string\") {\n if (t.trim() === \"\") return null;\n return t;\n }\n if (typeof t === \"function\") {\n return t.bind(this);\n }\n\n return (\n noMatchTemplate ||\n function() {\n return \"
  • No Match Found!
  • \";\n }.bind(this)\n );\n })(noMatchTemplate),\n\n // column to search against in the object\n lookup: lookup,\n\n // column that contains the content to insert by default\n fillAttr: fillAttr,\n\n // array of objects or a function returning an array of objects\n values: values,\n\n requireLeadingSpace: requireLeadingSpace,\n\n searchOpts: searchOpts,\n\n menuItemLimit: menuItemLimit,\n\n menuShowMinLength: menuShowMinLength\n }\n ];\n } else if (collection) {\n if (this.autocompleteMode)\n console.warn(\n \"Tribute in autocomplete mode does not work for collections\"\n );\n this.collection = collection.map(item => {\n return {\n trigger: item.trigger || trigger,\n iframe: item.iframe || iframe,\n selectClass: item.selectClass || selectClass,\n containerClass: item.containerClass || containerClass,\n itemClass: item.itemClass || itemClass,\n selectTemplate: (\n item.selectTemplate || Tribute.defaultSelectTemplate\n ).bind(this),\n menuItemTemplate: (\n item.menuItemTemplate || Tribute.defaultMenuItemTemplate\n ).bind(this),\n // function called when menu is empty, disables hiding of menu.\n noMatchTemplate: (t => {\n if (typeof t === \"string\") {\n if (t.trim() === \"\") return null;\n return t;\n }\n if (typeof t === \"function\") {\n return t.bind(this);\n }\n\n return (\n noMatchTemplate ||\n function() {\n return \"
  • No Match Found!
  • \";\n }.bind(this)\n );\n })(noMatchTemplate),\n lookup: item.lookup || lookup,\n fillAttr: item.fillAttr || fillAttr,\n values: item.values,\n requireLeadingSpace: item.requireLeadingSpace,\n searchOpts: item.searchOpts || searchOpts,\n menuItemLimit: item.menuItemLimit || menuItemLimit,\n menuShowMinLength: item.menuShowMinLength || menuShowMinLength\n };\n });\n } else {\n throw new Error(\"[Tribute] No collection specified.\");\n }\n\n new TributeRange(this);\n new TributeEvents(this);\n new TributeMenuEvents(this);\n new TributeSearch(this);\n }\n\n get isActive() {\n return this._isActive;\n }\n\n set isActive(val) {\n if (this._isActive != val) {\n this._isActive = val;\n if (this.current.element) {\n let noMatchEvent = new CustomEvent(`tribute-active-${val}`);\n this.current.element.dispatchEvent(noMatchEvent);\n }\n }\n }\n\n static defaultSelectTemplate(item) {\n if (typeof item === \"undefined\")\n return `${this.current.collection.trigger}${this.current.mentionText}`;\n if (this.range.isContentEditable(this.current.element)) {\n return (\n '' +\n (this.current.collection.trigger +\n item.original[this.current.collection.fillAttr]) +\n \"\"\n );\n }\n\n return (\n this.current.collection.trigger +\n item.original[this.current.collection.fillAttr]\n );\n }\n\n static defaultMenuItemTemplate(matchItem) {\n return matchItem.string;\n }\n\n static inputTypes() {\n return [\"TEXTAREA\", \"INPUT\"];\n }\n\n triggers() {\n return this.collection.map(config => {\n return config.trigger;\n });\n }\n\n attach(el) {\n if (!el) {\n throw new Error(\"[Tribute] Must pass in a DOM node or NodeList.\");\n }\n\n // Check if it is a jQuery collection\n if (typeof jQuery !== \"undefined\" && el instanceof jQuery) {\n el = el.get();\n }\n\n // Is el an Array/Array-like object?\n if (\n el.constructor === NodeList ||\n el.constructor === HTMLCollection ||\n el.constructor === Array\n ) {\n let length = el.length;\n for (var i = 0; i < length; ++i) {\n this._attach(el[i]);\n }\n } else {\n this._attach(el);\n }\n }\n\n _attach(el) {\n if (el.hasAttribute(\"data-tribute\")) {\n console.warn(\"Tribute was already bound to \" + el.nodeName);\n }\n\n this.ensureEditable(el);\n this.events.bind(el);\n el.setAttribute(\"data-tribute\", true);\n }\n\n ensureEditable(element) {\n if (Tribute.inputTypes().indexOf(element.nodeName) === -1) {\n if (element.contentEditable) {\n element.contentEditable = true;\n } else {\n throw new Error(\"[Tribute] Cannot bind to \" + element.nodeName);\n }\n }\n }\n\n createMenu(containerClass) {\n let wrapper = this.range.getDocument().createElement(\"div\"),\n ul = this.range.getDocument().createElement(\"ul\");\n wrapper.className = containerClass;\n wrapper.appendChild(ul);\n\n if (this.menuContainer) {\n return this.menuContainer.appendChild(wrapper);\n }\n\n return this.range.getDocument().body.appendChild(wrapper);\n }\n\n showMenuFor(element, scrollTo) {\n // Only proceed if menu isn't already shown for the current element & mentionText\n if (\n this.isActive &&\n this.current.element === element &&\n this.current.mentionText === this.currentMentionTextSnapshot\n ) {\n return;\n }\n this.currentMentionTextSnapshot = this.current.mentionText;\n\n // create the menu if it doesn't exist.\n if (!this.menu) {\n this.menu = this.createMenu(this.current.collection.containerClass);\n element.tributeMenu = this.menu;\n this.menuEvents.bind(this.menu);\n }\n\n this.isActive = true;\n this.menuSelected = 0;\n\n if (!this.current.mentionText) {\n this.current.mentionText = \"\";\n }\n\n const processValues = values => {\n // Tribute may not be active any more by the time the value callback returns\n if (!this.isActive) {\n return;\n }\n\n let items = this.search.filter(this.current.mentionText, values, {\n pre: this.current.collection.searchOpts.pre || \"\",\n post: this.current.collection.searchOpts.post || \"\",\n skip: this.current.collection.searchOpts.skip,\n extract: el => {\n if (typeof this.current.collection.lookup === \"string\") {\n return el[this.current.collection.lookup];\n } else if (typeof this.current.collection.lookup === \"function\") {\n return this.current.collection.lookup(el, this.current.mentionText);\n } else {\n throw new Error(\n \"Invalid lookup attribute, lookup must be string or function.\"\n );\n }\n }\n });\n\n if (this.current.collection.menuItemLimit) {\n items = items.slice(0, this.current.collection.menuItemLimit);\n }\n\n this.current.filteredItems = items;\n\n let ul = this.menu.querySelector(\"ul\");\n\n this.range.positionMenuAtCaret(scrollTo);\n\n if (!items.length) {\n let noMatchEvent = new CustomEvent(\"tribute-no-match\", {\n detail: this.menu\n });\n this.current.element.dispatchEvent(noMatchEvent);\n if (\n (typeof this.current.collection.noMatchTemplate === \"function\" &&\n !this.current.collection.noMatchTemplate()) ||\n !this.current.collection.noMatchTemplate\n ) {\n this.hideMenu();\n } else {\n typeof this.current.collection.noMatchTemplate === \"function\"\n ? (ul.innerHTML = this.current.collection.noMatchTemplate())\n : (ul.innerHTML = this.current.collection.noMatchTemplate);\n }\n\n return;\n }\n\n ul.innerHTML = \"\";\n let fragment = this.range.getDocument().createDocumentFragment();\n\n items.forEach((item, index) => {\n let li = this.range.getDocument().createElement(\"li\");\n li.setAttribute(\"data-index\", index);\n li.className = this.current.collection.itemClass;\n li.addEventListener(\"mousemove\", e => {\n let [li, index] = this._findLiTarget(e.target);\n if (e.movementY !== 0) {\n this.events.setActiveLi(index);\n }\n });\n if (this.menuSelected === index) {\n li.classList.add(this.current.collection.selectClass);\n }\n li.innerHTML = this.current.collection.menuItemTemplate(item);\n fragment.appendChild(li);\n });\n ul.appendChild(fragment);\n };\n\n if (typeof this.current.collection.values === \"function\") {\n this.current.collection.values(this.current.mentionText, processValues);\n } else {\n processValues(this.current.collection.values);\n }\n }\n\n _findLiTarget(el) {\n if (!el) return [];\n const index = el.getAttribute(\"data-index\");\n return !index ? this._findLiTarget(el.parentNode) : [el, index];\n }\n\n showMenuForCollection(element, collectionIndex) {\n if (element !== document.activeElement) {\n this.placeCaretAtEnd(element);\n }\n\n this.current.collection = this.collection[collectionIndex || 0];\n this.current.externalTrigger = true;\n this.current.element = element;\n\n if (element.isContentEditable)\n this.insertTextAtCursor(this.current.collection.trigger);\n else this.insertAtCaret(element, this.current.collection.trigger);\n\n this.showMenuFor(element);\n }\n\n // TODO: make sure this works for inputs/textareas\n placeCaretAtEnd(el) {\n el.focus();\n if (\n typeof window.getSelection != \"undefined\" &&\n typeof document.createRange != \"undefined\"\n ) {\n var range = document.createRange();\n range.selectNodeContents(el);\n range.collapse(false);\n var sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n } else if (typeof document.body.createTextRange != \"undefined\") {\n var textRange = document.body.createTextRange();\n textRange.moveToElementText(el);\n textRange.collapse(false);\n textRange.select();\n }\n }\n\n // for contenteditable\n insertTextAtCursor(text) {\n var sel, range, html;\n sel = window.getSelection();\n range = sel.getRangeAt(0);\n range.deleteContents();\n var textNode = document.createTextNode(text);\n range.insertNode(textNode);\n range.selectNodeContents(textNode);\n range.collapse(false);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n // for regular inputs\n insertAtCaret(textarea, text) {\n var scrollPos = textarea.scrollTop;\n var caretPos = textarea.selectionStart;\n\n var front = textarea.value.substring(0, caretPos);\n var back = textarea.value.substring(\n textarea.selectionEnd,\n textarea.value.length\n );\n textarea.value = front + text + back;\n caretPos = caretPos + text.length;\n textarea.selectionStart = caretPos;\n textarea.selectionEnd = caretPos;\n textarea.focus();\n textarea.scrollTop = scrollPos;\n }\n\n hideMenu() {\n if (this.menu) {\n this.menu.style.cssText = \"display: none;\";\n this.isActive = false;\n this.menuSelected = 0;\n this.current = {};\n }\n }\n\n selectItemAtIndex(index, originalEvent) {\n index = parseInt(index);\n if (typeof index !== \"number\" || isNaN(index)) return;\n let item = this.current.filteredItems[index];\n let content = this.current.collection.selectTemplate(item);\n if (content !== null) this.replaceText(content, originalEvent, item);\n }\n\n replaceText(content, originalEvent, item) {\n this.range.replaceTriggerText(content, true, true, originalEvent, item);\n }\n\n _append(collection, newValues, replace) {\n if (typeof collection.values === \"function\") {\n throw new Error(\"Unable to append to values, as it is a function.\");\n } else if (!replace) {\n collection.values = collection.values.concat(newValues);\n } else {\n collection.values = newValues;\n }\n }\n\n append(collectionIndex, newValues, replace) {\n let index = parseInt(collectionIndex);\n if (typeof index !== \"number\")\n throw new Error(\"please provide an index for the collection to update.\");\n\n let collection = this.collection[index];\n\n this._append(collection, newValues, replace);\n }\n\n appendCurrent(newValues, replace) {\n if (this.isActive) {\n this._append(this.current.collection, newValues, replace);\n } else {\n throw new Error(\n \"No active state. Please use append instead and pass an index.\"\n );\n }\n }\n\n detach(el) {\n if (!el) {\n throw new Error(\"[Tribute] Must pass in a DOM node or NodeList.\");\n }\n\n // Check if it is a jQuery collection\n if (typeof jQuery !== \"undefined\" && el instanceof jQuery) {\n el = el.get();\n }\n\n // Is el an Array/Array-like object?\n if (\n el.constructor === NodeList ||\n el.constructor === HTMLCollection ||\n el.constructor === Array\n ) {\n let length = el.length;\n for (var i = 0; i < length; ++i) {\n this._detach(el[i]);\n }\n } else {\n this._detach(el);\n }\n }\n\n _detach(el) {\n this.events.unbind(el);\n if (el.tributeMenu) {\n this.menuEvents.unbind(el.tributeMenu);\n }\n\n setTimeout(() => {\n el.removeAttribute(\"data-tribute\");\n this.isActive = false;\n if (el.tributeMenu) {\n el.tributeMenu.remove();\n }\n });\n }\n}\n\nexport default Tribute;\n", "(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})(Object(typeof self !== 'undefined' ? self : this), function() {\nreturn ", "if (typeof Object.getPrototypeOf !== \"function\") {\r\n Object.getPrototypeOf =\r\n typeof \"test\".__proto__ === \"object\"\r\n ? function (object) {\r\n return object.__proto__;\r\n }\r\n : function (object) {\r\n return object.constructor.prototype;\r\n };\r\n}\r\n", "// https://tc39.github.io/ecma262/#sec-array.prototype.includes\r\nif (!Array.prototype.includes) {\r\n // eslint-disable-next-line no-extend-native\r\n Object.defineProperty(Array.prototype, \"includes\", {\r\n value: function (searchElement, fromIndex) {\r\n // 1. Let O be ? ToObject(this value).\r\n if (this == null) {\r\n throw new TypeError('\"this\" is null or not defined');\r\n }\r\n\r\n const o = Object(this),\r\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\r\n len = o.length >>> 0;\r\n\r\n // 3. If len is 0, return false.\r\n if (len === 0) {\r\n return false;\r\n }\r\n\r\n // 4. Let n be ? ToInteger(fromIndex).\r\n // (If fromIndex is undefined, this step produces the value 0.)\r\n let n = fromIndex | 0,\r\n // 5. If n ≥ 0, then\r\n // a. Let k be n.\r\n // 6. Else n < 0,\r\n // a. Let k be len + n.\r\n // b. If k < 0, let k be 0.\r\n k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\r\n\r\n // 7. Repeat, while k < len\r\n while (k < len) {\r\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\r\n // b. If SameValueZero(searchElement, elementK) is true, return true.\r\n // c. Increase k by 1.\r\n // NOTE: === provides the correct \"SameValueZero\" comparison needed here.\r\n if (o[k] === searchElement) {\r\n return true;\r\n }\r\n k++;\r\n }\r\n\r\n // 8. Return false\r\n return false;\r\n }\r\n });\r\n}\r\n", "const reduce = Function.bind.call(Function.call, Array.prototype.reduce),\r\n isEnumerable = Function.bind.call(\r\n Function.call,\r\n Object.prototype.propertyIsEnumerable\r\n ),\r\n concat = Function.bind.call(Function.call, Array.prototype.concat),\r\n keys = Object.keys;\r\n\r\nif (!Object.entries) {\r\n Object.entries = function entries(O) {\r\n return reduce(\r\n keys(O),\r\n (e, k) =>\r\n concat(\r\n e,\r\n typeof k === \"string\" && isEnumerable(O, k) ? [[k, O[k]]] : []\r\n ),\r\n []\r\n );\r\n };\r\n}\r\n", "if (!String.prototype.includes) {\r\n // eslint-disable-next-line no-extend-native\r\n String.prototype.includes = function (search, start) {\r\n if (typeof start !== \"number\") {\r\n start = 0;\r\n }\r\n\r\n if (start + search.length > this.length) {\r\n return false;\r\n } else {\r\n return this.indexOf(search, start) !== -1;\r\n }\r\n };\r\n}\r\n", "if (FormData.Inputmask === undefined) {\r\n class FormDataPatch extends FormData {\r\n constructor(form, submitter) {\r\n super(form, submitter);\r\n\r\n const entries = this.entries();\r\n let entry;\r\n while ((entry = entries.next()).done === false) {\r\n const fieldName = entry.value[0],\r\n originalValue = entry.value[1], // Get the original value from FormData\r\n element = form[fieldName];\r\n\r\n if (\r\n element &&\r\n element.inputmask !== undefined &&\r\n !(originalValue instanceof File)\r\n ) {\r\n // Apply masking only if it's not a File and the element has inputmask\r\n this.set(fieldName, element.value);\r\n }\r\n }\r\n\r\n return this;\r\n }\r\n }\r\n FormDataPatch.Inputmask = true;\r\n // eslint-disable-next-line no-global-assign\r\n FormData = FormDataPatch;\r\n}\r\n", "/*\r\n Input Mask plugin extensions\r\n http://github.com/RobinHerbots/inputmask\r\n Copyright (c) Robin Herbots\r\n Licensed under the MIT license\r\n */\r\nimport Inputmask from \"../inputmask\";\r\nimport { getLastValidPosition } from \"../positioning\";\r\nimport { getMaskTemplate } from \"../validation-tests\";\r\n// extra definitions\r\nInputmask.extendDefinitions({\r\n A: {\r\n validator: \"[A-Za-z\\u0410-\\u044F\\u0401\\u0451\\u00C0-\\u00FF\\u00B5]\",\r\n casing: \"upper\" // auto uppercasing\r\n },\r\n \"&\": {\r\n // alfanumeric uppercasing\r\n validator: \"[0-9A-Za-z\\u0410-\\u044F\\u0401\\u0451\\u00C0-\\u00FF\\u00B5]\",\r\n casing: \"upper\"\r\n },\r\n \"#\": {\r\n // hexadecimal\r\n validator: \"[0-9A-Fa-f]\",\r\n casing: \"upper\"\r\n }\r\n});\r\n\r\nconst ipValidatorRegex = /25[0-5]|2[0-4][0-9]|[01][0-9][0-9]/;\r\n\r\nfunction ipValidator(chrs, maskset, pos, strict, opts) {\r\n if (pos - 1 > -1 && maskset.buffer[pos - 1] !== \".\") {\r\n chrs = maskset.buffer[pos - 1] + chrs;\r\n if (pos - 2 > -1 && maskset.buffer[pos - 2] !== \".\") {\r\n chrs = maskset.buffer[pos - 2] + chrs;\r\n } else chrs = \"0\" + chrs;\r\n } else chrs = \"00\" + chrs;\r\n if (\r\n opts.greedy &&\r\n parseInt(chrs) > 255 &&\r\n ipValidatorRegex.test(\"00\" + chrs.charAt(2))\r\n ) {\r\n const buffer = [...maskset.buffer.slice(0, pos), \".\", chrs.charAt(2)];\r\n if (buffer.join(\"\").match(/\\./g).length < 4) {\r\n return {\r\n refreshFromBuffer: true,\r\n buffer,\r\n caret: pos + 2\r\n };\r\n }\r\n }\r\n return ipValidatorRegex.test(chrs);\r\n}\r\n\r\nInputmask.extendAliases({\r\n cssunit: {\r\n regex: \"[+-]?[0-9]+\\\\.?([0-9]+)?(px|em|rem|ex|%|in|cm|mm|pt|pc)\"\r\n },\r\n url: {\r\n // needs update => https://en.wikipedia.org/wiki/URL\r\n regex: \"(https?|ftp)://.*\",\r\n autoUnmask: false,\r\n keepStatic: false,\r\n tabThrough: true\r\n },\r\n ip: {\r\n // ip-address mask\r\n mask: \"i{1,3}.j{1,3}.k{1,3}.l{1,3}\",\r\n definitions: {\r\n i: {\r\n validator: ipValidator\r\n },\r\n j: {\r\n validator: ipValidator\r\n },\r\n k: {\r\n validator: ipValidator\r\n },\r\n l: {\r\n validator: ipValidator\r\n }\r\n },\r\n onUnMask: function (maskedValue, unmaskedValue, opts) {\r\n return maskedValue;\r\n },\r\n inputmode: \"decimal\",\r\n substitutes: { \",\": \".\" }\r\n },\r\n email: {\r\n // https://en.wikipedia.org/wiki/Domain_name#Domain_name_space\r\n // https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names\r\n // should be extended with the toplevel domains at the end\r\n mask: function ({ separator, quantifier }) {\r\n let emailMask =\r\n \"*{1,64}[.*{1,64}][.*{1,64}][.*{1,63}]@-{1,63}.-{1,63}[.-{1,63}][.-{1,63}]\",\r\n mask = emailMask;\r\n if (separator) {\r\n for (let i = 0; i < quantifier; i++) {\r\n mask += `[${separator}${emailMask}]`;\r\n }\r\n }\r\n return mask;\r\n },\r\n greedy: false,\r\n casing: \"lower\",\r\n separator: null,\r\n quantifier: 5,\r\n skipOptionalPartCharacter: \"\",\r\n onBeforePaste: function (pastedValue, opts) {\r\n pastedValue = pastedValue.toLowerCase();\r\n return pastedValue.replace(\"mailto:\", \"\");\r\n },\r\n definitions: {\r\n \"*\": {\r\n validator:\r\n \"[0-9\\uFF11-\\uFF19A-Za-z\\u0410-\\u044F\\u0401\\u0451\\u00C0-\\u00FF\\u00B5!#$%&'*+/=?^_`{|}~-]\"\r\n },\r\n \"-\": {\r\n validator: \"[0-9A-Za-z-]\"\r\n }\r\n },\r\n onUnMask: function (maskedValue, unmaskedValue, opts) {\r\n return maskedValue;\r\n },\r\n inputmode: \"email\"\r\n },\r\n mac: {\r\n mask: \"##:##:##:##:##:##\"\r\n }, // https://en.wikipedia.org/wiki/Vehicle_identification_number\r\n // see issue #1199\r\n vin: {\r\n mask: \"V{13}9{4}\",\r\n definitions: {\r\n V: {\r\n validator: \"[A-HJ-NPR-Za-hj-npr-z\\\\d]\",\r\n casing: \"upper\"\r\n }\r\n },\r\n clearIncomplete: true,\r\n autoUnmask: true\r\n }, // http://rion.io/2013/09/10/validating-social-security-numbers-through-regular-expressions-2/\r\n // https://en.wikipedia.org/wiki/Social_Security_number\r\n ssn: {\r\n mask: \"999-99-9999\",\r\n postValidation: function (\r\n buffer,\r\n pos,\r\n c,\r\n currentResult,\r\n opts,\r\n maskset,\r\n strict\r\n ) {\r\n const bffr = getMaskTemplate.call(\r\n this,\r\n true,\r\n getLastValidPosition.call(this),\r\n true,\r\n true\r\n );\r\n return /^(?!219-09-9999|078-05-1120)(?!666|000|9.{2}).{3}-(?!00).{2}-(?!0{4}).{4}$/.test(\r\n bffr.join(\"\")\r\n );\r\n }\r\n }\r\n});\r\n", "/*\r\n * Input Mask Core\r\n * http://github.com/RobinHerbots/jquery.inputmask\r\n * Copyright (c) Robin Herbots\r\n * Licensed under the MIT license\r\n */\r\n\r\nimport defaults from \"./defaults\";\r\nimport definitions from \"./definitions\";\r\nimport $ from \"./dependencyLibs/inputmask.dependencyLib\";\r\nimport { EventRuler } from \"./eventruler\";\r\nimport window from \"./global/window\";\r\nimport { checkVal, clearOptionalTail, unmaskedvalue } from \"./inputHandling\";\r\nimport { mask } from \"./mask\";\r\nimport { generateMaskSet, analyseMask } from \"./mask-lexer\";\r\nimport { getBuffer, getBufferTemplate } from \"./positioning\";\r\nimport { isComplete } from \"./validation\";\r\nimport { getMaskTemplate } from \"./validation-tests\";\r\n\r\nconst document = window.document,\r\n dataKey = \"_inputmask_opts\";\r\n\r\nfunction Inputmask(alias, options, internal) {\r\n // allow instanciating without new\r\n if (!(this instanceof Inputmask)) {\r\n return new Inputmask(alias, options, internal);\r\n }\r\n\r\n this.dependencyLib = $;\r\n this.el = undefined;\r\n this.events = {};\r\n this.maskset = undefined;\r\n\r\n if (internal !== true) {\r\n // init options\r\n if (Object.prototype.toString.call(alias) === \"[object Object]\") {\r\n options = alias;\r\n } else {\r\n options = options || {};\r\n if (alias) options.alias = alias;\r\n }\r\n this.opts = $.extend(true, {}, this.defaults, options);\r\n this.noMasksCache = options && options.definitions !== undefined;\r\n this.userOptions = options || {}; // user passed options\r\n resolveAlias(this.opts.alias, options, this.opts);\r\n }\r\n\r\n // maskscope properties\r\n this.refreshValue = false; // indicate a refresh from the inputvalue is needed (form.reset)\r\n this.undoValue = undefined;\r\n this.$el = undefined;\r\n this.skipInputEvent = false; // skip when triggered from within inputmask\r\n this.validationEvent = false;\r\n this.ignorable = false;\r\n // eslint-disable-next-line no-unused-expressions\r\n this.maxLength;\r\n this.mouseEnter = false;\r\n this.clicked = 0;\r\n this.originalPlaceholder = undefined; // needed for FF\r\n this.isComposing = false; // keydowncode == 229 compositionevent fallback\r\n this.lastInputEvent = null; // track last input event to prevent duplicates #2855\r\n this.hasAlternator = false;\r\n}\r\n\r\nInputmask.prototype = {\r\n dataAttribute: \"data-inputmask\", // data attribute prefix used for attribute binding\r\n // options default\r\n defaults,\r\n definitions,\r\n aliases: {}, // aliases definitions\r\n masksCache: {},\r\n i18n: {},\r\n get isRTL() {\r\n return this.opts.isRTL || this.opts.numericInput;\r\n },\r\n mask: function (elems) {\r\n const that = this;\r\n if (typeof elems === \"string\") {\r\n elems =\r\n document.getElementById(elems) || document.querySelectorAll(elems);\r\n }\r\n elems = elems.nodeName\r\n ? [elems]\r\n : Array.isArray(elems)\r\n ? elems\r\n : [].slice.call(elems); // [].slice as alternate for Array.from (Yandex browser)\r\n elems.forEach(function (el, ndx) {\r\n const scopedOpts = $.extend(true, {}, that.opts);\r\n if (\r\n importAttributeOptions(\r\n el,\r\n scopedOpts,\r\n $.extend(true, {}, that.userOptions),\r\n that.dataAttribute\r\n )\r\n ) {\r\n const maskset = generateMaskSet(scopedOpts, that.noMasksCache);\r\n if (maskset !== undefined) {\r\n if (el.inputmask !== undefined) {\r\n el.inputmask.opts.autoUnmask = true; // force autounmasking when remasking\r\n el.inputmask.remove();\r\n }\r\n // store inputmask instance on the input with element reference\r\n el.inputmask = new Inputmask(undefined, undefined, true);\r\n el.inputmask.opts = scopedOpts;\r\n el.inputmask.noMasksCache = that.noMasksCache;\r\n el.inputmask.userOptions = $.extend(true, {}, that.userOptions);\r\n // el.inputmask.isRTL = scopedOpts.isRTL || scopedOpts.numericInput;\r\n el.inputmask.el = el;\r\n el.inputmask.$el = $(el);\r\n el.inputmask.maskset = maskset;\r\n\r\n $.data(el, dataKey, that.userOptions);\r\n mask.call(el.inputmask);\r\n }\r\n }\r\n });\r\n return elems && elems[0] ? elems[0].inputmask || this : this;\r\n },\r\n option: function (options, noremask) {\r\n // set extra options || retrieve value of a current option\r\n if (typeof options === \"string\") {\r\n return this.opts[options];\r\n } else if (typeof options === \"object\") {\r\n $.extend(this.userOptions, options); // user passed options\r\n // remask\r\n if (this.el && noremask !== true) {\r\n this.mask(this.el);\r\n }\r\n return this;\r\n }\r\n },\r\n unmaskedvalue: function (value) {\r\n this.maskset =\r\n this.maskset || generateMaskSet(this.opts, this.noMasksCache);\r\n if (this.el === undefined || value !== undefined) {\r\n const valueBuffer = (\r\n typeof this.opts.onBeforeMask === \"function\"\r\n ? this.opts.onBeforeMask.call(this, value, this.opts) || value\r\n : value\r\n ).split(\"\");\r\n checkVal.call(this, undefined, false, false, valueBuffer);\r\n if (typeof this.opts.onBeforeWrite === \"function\")\r\n this.opts.onBeforeWrite.call(\r\n this,\r\n undefined,\r\n getBuffer.call(this),\r\n 0,\r\n this.opts\r\n );\r\n }\r\n return unmaskedvalue.call(this, this.el);\r\n },\r\n remove: function () {\r\n if (this.el) {\r\n $.data(this.el, dataKey, null); // invalidate\r\n // writeout the value\r\n const cv = this.opts.autoUnmask\r\n ? unmaskedvalue(this.el)\r\n : this._valueGet(this.opts.autoUnmask);\r\n if (cv !== getBufferTemplate.call(this).join(\"\"))\r\n this._valueSet(cv, this.opts.autoUnmask);\r\n else this._valueSet(\"\");\r\n // unbind all events\r\n EventRuler.off(this.el);\r\n\r\n // restore the value property\r\n let valueProperty;\r\n if (Object.getOwnPropertyDescriptor && Object.getPrototypeOf) {\r\n valueProperty = Object.getOwnPropertyDescriptor(\r\n Object.getPrototypeOf(this.el),\r\n \"value\"\r\n );\r\n if (valueProperty) {\r\n if (this.__valueGet) {\r\n Object.defineProperty(this.el, \"value\", {\r\n get: this.__valueGet,\r\n set: this.__valueSet,\r\n configurable: true\r\n });\r\n }\r\n }\r\n } else if (\r\n document.__lookupGetter__ &&\r\n this.el.__lookupGetter__(\"value\")\r\n ) {\r\n if (this.__valueGet) {\r\n this.el.__defineGetter__(\"value\", this.__valueGet);\r\n this.el.__defineSetter__(\"value\", this.__valueSet);\r\n }\r\n }\r\n // clear data\r\n this.el.inputmask = undefined;\r\n }\r\n return this.el;\r\n },\r\n getemptymask: function () {\r\n // return the default (empty) mask value, usefull for setting the default value in validation\r\n this.maskset =\r\n this.maskset || generateMaskSet(this.opts, this.noMasksCache);\r\n return (\r\n this.isRTL\r\n ? getBufferTemplate.call(this).reverse()\r\n : getBufferTemplate.call(this)\r\n ).join(\"\");\r\n },\r\n hasMaskedValue: function () {\r\n // check wheter the returned value is masked or not; currently only works reliable when using jquery.val fn to retrieve the value\r\n return !this.opts.autoUnmask;\r\n },\r\n isComplete: function () {\r\n this.maskset =\r\n this.maskset || generateMaskSet(this.opts, this.noMasksCache);\r\n return isComplete.call(this, getBuffer.call(this));\r\n },\r\n getmetadata: function () {\r\n // return mask metadata if exists\r\n this.maskset =\r\n this.maskset || generateMaskSet(this.opts, this.noMasksCache);\r\n if (Array.isArray(this.maskset.metadata)) {\r\n let maskTarget = getMaskTemplate.call(this, true, 0, false).join(\"\");\r\n this.maskset.metadata.forEach(function (mtdt) {\r\n if (mtdt.mask === maskTarget) {\r\n maskTarget = mtdt;\r\n return false;\r\n }\r\n\r\n return true;\r\n });\r\n return maskTarget;\r\n }\r\n return this.maskset.metadata;\r\n },\r\n isValid: function (value) {\r\n this.maskset =\r\n this.maskset || generateMaskSet(this.opts, this.noMasksCache);\r\n if (value) {\r\n const valueBuffer = (\r\n typeof this.opts.onBeforeMask === \"function\"\r\n ? this.opts.onBeforeMask.call(this, value, this.opts) || value\r\n : value\r\n ).split(\"\");\r\n checkVal.call(this, undefined, true, false, valueBuffer);\r\n }\r\n\r\n const buffer = clearOptionalTail.call(this, []),\r\n isC = isComplete.call(this, buffer),\r\n isc2 =\r\n value === (this.isRTL ? buffer.reverse().join(\"\") : buffer.join(\"\"));\r\n\r\n return isC && (value === undefined || isc2);\r\n },\r\n format: function (value, metadata) {\r\n this.maskset =\r\n this.maskset || generateMaskSet(this.opts, this.noMasksCache);\r\n const valueBuffer = (\r\n typeof this.opts.onBeforeMask === \"function\"\r\n ? this.opts.onBeforeMask.call(this, value, this.opts) || value\r\n : value\r\n ).split(\"\");\r\n checkVal.call(this, undefined, true, false, valueBuffer);\r\n const formattedValue = this.isRTL\r\n ? getBuffer.call(this).slice().reverse().join(\"\")\r\n : getBuffer.call(this).join(\"\");\r\n return metadata\r\n ? {\r\n value: formattedValue,\r\n metadata: this.getmetadata()\r\n }\r\n : formattedValue;\r\n },\r\n setValue: function (value) {\r\n if (this.el) {\r\n $(this.el).trigger(\"setvalue\", [value]);\r\n }\r\n },\r\n analyseMask\r\n};\r\n\r\nfunction resolveAlias(aliasStr, options, opts) {\r\n const aliasDefinition = Inputmask.prototype.aliases[aliasStr];\r\n if (aliasDefinition) {\r\n if (aliasDefinition.alias)\r\n resolveAlias(aliasDefinition.alias, undefined, opts); // alias is another alias\r\n $.extend(true, opts, aliasDefinition); // merge alias definition in the options\r\n $.extend(true, opts, options); // reapply extra given options\r\n return true;\r\n } // alias not found - try as mask\r\n else if (opts.mask === null) {\r\n opts.mask = aliasStr;\r\n }\r\n\r\n return false;\r\n}\r\n\r\nfunction importAttributeOptions(npt, opts, userOptions, dataAttribute) {\r\n function importOption(option, optionData) {\r\n const attrOption =\r\n dataAttribute === \"\" ? option : dataAttribute + \"-\" + option;\r\n optionData =\r\n optionData !== undefined ? optionData : npt.getAttribute(attrOption);\r\n if (optionData !== null) {\r\n if (typeof optionData === \"string\") {\r\n if (option.startsWith(\"on\")) {\r\n // get function definition\r\n optionData = window[optionData];\r\n } else if (optionData === \"false\") optionData = false;\r\n else if (optionData === \"true\") optionData = true;\r\n else if (option === \"mask\")\r\n optionData = optionData.replace(/\\\\\\\\/g, \"\\\\\");\r\n }\r\n userOptions[option] = optionData;\r\n }\r\n }\r\n\r\n if (opts.importDataAttributes === true) {\r\n let attrOptions = npt.getAttribute(dataAttribute),\r\n option,\r\n dataoptions,\r\n optionData,\r\n p;\r\n\r\n if (attrOptions && attrOptions !== \"\") {\r\n attrOptions = attrOptions.replace(/'/g, '\"');\r\n dataoptions = JSON.parse(\"{\" + attrOptions + \"}\");\r\n }\r\n\r\n // resolve aliases\r\n if (dataoptions) {\r\n // pickup alias from dataAttribute\r\n optionData = undefined;\r\n for (p in dataoptions) {\r\n if (p.toLowerCase() === \"alias\") {\r\n optionData = dataoptions[p];\r\n break;\r\n }\r\n }\r\n }\r\n importOption(\"alias\", optionData); // pickup alias from dataAttribute-alias\r\n if (userOptions.alias) {\r\n resolveAlias(userOptions.alias, userOptions, opts);\r\n }\r\n\r\n for (option in opts) {\r\n if (dataoptions) {\r\n optionData = undefined;\r\n for (p in dataoptions) {\r\n if (p.toLowerCase() === option.toLowerCase()) {\r\n optionData = dataoptions[p];\r\n break;\r\n }\r\n }\r\n }\r\n importOption(option, optionData);\r\n }\r\n }\r\n $.extend(true, opts, userOptions);\r\n\r\n // handle dir=rtl\r\n if (npt.dir === \"rtl\" || opts.rightAlign) {\r\n npt.style.textAlign = \"right\";\r\n }\r\n\r\n if (npt.dir === \"rtl\" || opts.numericInput) {\r\n npt.dir = \"ltr\";\r\n npt.removeAttribute(\"dir\");\r\n opts.isRTL = true;\r\n }\r\n\r\n return Object.keys(userOptions).length;\r\n}\r\n\r\n// apply defaults, definitions, aliases\r\nInputmask.extendDefaults = function (options) {\r\n $.extend(true, Inputmask.prototype.defaults, options);\r\n};\r\nInputmask.extendDefinitions = function (definition) {\r\n $.extend(true, Inputmask.prototype.definitions, definition);\r\n};\r\nInputmask.extendAliases = function (alias) {\r\n $.extend(true, Inputmask.prototype.aliases, alias);\r\n};\r\n// static fn on inputmask\r\nInputmask.format = function (value, options, metadata) {\r\n return Inputmask(options).format(value, metadata);\r\n};\r\nInputmask.unmask = function (value, options) {\r\n return Inputmask(options).unmaskedvalue(value);\r\n};\r\nInputmask.isValid = function (value, options) {\r\n return Inputmask(options).isValid(value);\r\n};\r\nInputmask.remove = function (elems) {\r\n if (typeof elems === \"string\") {\r\n elems = document.getElementById(elems) || document.querySelectorAll(elems);\r\n }\r\n elems = elems.nodeName ? [elems] : elems;\r\n for (let i = 0; i < elems.length; i++) {\r\n if (elems[i].inputmask) elems[i].inputmask.remove();\r\n }\r\n};\r\nInputmask.setValue = function (elems, value) {\r\n if (typeof elems === \"string\") {\r\n elems = document.getElementById(elems) || document.querySelectorAll(elems);\r\n }\r\n elems = elems.nodeName ? [elems] : elems;\r\n elems.forEach(function (el) {\r\n if (el.inputmask) el.inputmask.setValue(value);\r\n else $(el).trigger(\"setvalue\", [value]);\r\n });\r\n};\r\n\r\nInputmask.dependencyLib = $;\r\n\r\n// make inputmask available\r\nwindow.Inputmask = Inputmask;\r\nexport default Inputmask;\r\n", "export default {\r\n _maxTestPos: 500,\r\n placeholder: \"_\",\r\n optionalmarker: [\"[\", \"]\"],\r\n quantifiermarker: [\"{\", \"}\"],\r\n groupmarker: [\"(\", \")\"],\r\n alternatormarker: \"|\",\r\n escapeChar: \"\\\\\",\r\n mask: null, // needs tobe null instead of undefined as the extend method does not consider props with the undefined value\r\n regex: null, // regular expression as a mask\r\n oncomplete: () => {}, // executes when the mask is complete\r\n onincomplete: () => {}, // executes when the mask is incomplete and focus is lost\r\n oncleared: () => {}, // executes when the mask is cleared\r\n repeat: 0, // repetitions of the mask: * ~ forever, otherwise specify an integer\r\n greedy: false, // true: allocated buffer for the mask and repetitions - false: allocate only if needed\r\n autoUnmask: false, // automatically unmask when retrieving the value with $.fn.val or value if the browser supports __lookupGetter__ or getOwnPropertyDescriptor\r\n removeMaskOnSubmit: false, // remove the mask before submitting the form.\r\n clearMaskOnLostFocus: true,\r\n insertMode: true, // insert the input or overwrite the input\r\n insertModeVisual: true, // show selected caret when insertmode = false\r\n clearIncomplete: false, // clear the incomplete input on blur\r\n alias: null,\r\n onKeyDown: () => {}, // callback to implement autocomplete on certain keys for example. args => event, buffer, caretPos, opts\r\n onBeforeMask: null, // executes before masking the initial value to allow preprocessing of the initial value.\targs => initialValue, opts => return processedValue\r\n onBeforePaste: function (pastedValue, opts) {\r\n return typeof opts.onBeforeMask === \"function\"\r\n ? opts.onBeforeMask.call(this, pastedValue, opts)\r\n : pastedValue;\r\n }, // executes before masking the pasted value to allow preprocessing of the pasted value.\targs => pastedValue, opts => return processedValue\r\n onBeforeWrite: null, // executes before writing to the masked element. args => event, opts\r\n onUnMask: null, // executes after unmasking to allow postprocessing of the unmaskedvalue.\targs => maskedValue, unmaskedValue, opts\r\n outputMask: null, // mask to apply when unmasking\r\n showMaskOnFocus: true, // show the mask-placeholder when the input has focus\r\n showMaskOnHover: true, // show the mask-placeholder when hovering the empty input\r\n onKeyValidation: () => {}, // executes on every key-press with the result of isValid. Params: key, result, opts\r\n skipOptionalPartCharacter: \" \", // a character which can be used to skip an optional part of a mask\r\n numericInput: false, // numericInput input direction style (input shifts to the left while holding the caret position)\r\n rightAlign: false, // align to the right\r\n undoOnEscape: true, // pressing escape reverts the value to the value before focus\r\n // numeric basic properties\r\n radixPoint: \"\", // \".\", // | \",\"\r\n _radixDance: false, // dance around the radixPoint\r\n groupSeparator: \"\", // \",\", // | \".\"\r\n // numeric basic properties\r\n keepStatic: null, // try to keep the mask static while typing. Decisions to alter the mask will be posponed if possible\r\n positionCaretOnTab: true, // when enabled the caret position is set after the latest valid position on TAB\r\n tabThrough: false, // allows for tabbing through the different parts of the masked field\r\n supportsInputType: [\"text\", \"tel\", \"url\", \"password\", \"search\"], // list with the supported input types\r\n isComplete: null, // override for isComplete - args => buffer, opts - return true || false\r\n preValidation: null, // hook to preValidate the input. Usefull for validating regardless the definition.\targs => buffer, pos, char, isSelection, opts, maskset, caretPos, strict => return true/false/command object\r\n postValidation: null, // hook to postValidate the result from isValid.\tUsefull for validating the entry as a whole.\targs => buffer, pos, c, currentResult, opts, maskset, strict, fromCheckval, fromAlternate => return true/false/json\r\n staticDefinitionSymbol: undefined, // specify a definitionSymbol for static content, used to make matches for alternators\r\n jitMasking: false, // just in time masking ~ only mask while typing, can n (number), true or false\r\n nullable: true, // return nothing instead of the buffertemplate when the user hasn't entered anything.\r\n inputEventOnly: false, // dev option - testing inputfallback behavior\r\n noValuePatching: false, // disable value property patching\r\n positionCaretOnClick: \"lvp\", // none, lvp (based on the last valid position (default), radixFocus (position caret to radixpoint on initial click), select (select the whole input), ignore (ignore the click and continue the mask)\r\n casing: null, // mask-level casing. Options: null, \"upper\", \"lower\" or \"title\" or \"follow\" or callback args => elem, test, pos, validPositions return charValue\r\n inputmode: \"text\", // specify the inputmode\r\n importDataAttributes: true, // import data-inputmask attributes\r\n shiftPositions: true, // shift position of the mask entries on entry and deletion.\r\n usePrototypeDefinitions: true, // use the default defined definitions from the prototype\r\n validationEventTimeOut: 3000, // Time to show validation error on form submit\r\n substitutes: {} // define character substitutes\r\n};\r\n", "export default {\r\n 9: {\r\n validator: \"\\\\p{N}\",\r\n definitionSymbol: \"*\"\r\n },\r\n a: {\r\n validator: \"\\\\p{L}\",\r\n definitionSymbol: \"*\"\r\n },\r\n \"*\": {\r\n validator: \"[\\\\p{L}\\\\p{N}]\"\r\n }\r\n};\r\n", "/*\r\n Input Mask plugin dependencyLib\r\n http://github.com/RobinHerbots/jquery.inputmask\r\n Copyright (c) Robin Herbots\r\n Licensed under the MIT license\r\n */\r\n\r\nimport window from \"../global/window\";\r\n\r\nimport data from \"./data\";\r\nimport { on, off, trigger, Event } from \"./events\";\r\nimport extend from \"./extend\";\r\n\r\nconst document = window.document;\r\n\r\nfunction DependencyLib(elem) {\r\n if (elem instanceof DependencyLib) {\r\n return elem;\r\n }\r\n if (!(this instanceof DependencyLib)) {\r\n return new DependencyLib(elem);\r\n }\r\n if (elem !== undefined && elem !== null && elem !== window) {\r\n this[0] = elem.nodeName\r\n ? elem\r\n : elem[0] !== undefined && elem[0].nodeName\r\n ? elem[0]\r\n : document.querySelector(elem);\r\n if (this[0] !== undefined && this[0] !== null) {\r\n data(this[0], \"events\", data(this[0], \"events\") || {});\r\n }\r\n }\r\n}\r\n\r\nDependencyLib.prototype = {\r\n on,\r\n off,\r\n trigger\r\n};\r\n\r\n// static\r\nDependencyLib.extend = extend;\r\nDependencyLib.data = data;\r\nDependencyLib.Event = Event;\r\n\r\nexport default DependencyLib;\r\n", "const canUseDOM = !!(\r\n typeof window !== \"undefined\" &&\r\n window.document &&\r\n window.document.createElement\r\n);\r\n\r\nexport default canUseDOM ? window : {};\r\n", "export default function (owner, key, value) {\r\n if (value === undefined) {\r\n return owner.__data ? owner.__data[key] : null;\r\n } else {\r\n owner.__data = owner.__data || {};\r\n owner.__data[key] = value;\r\n }\r\n}\r\n", "import window from \"../global/window\";\r\n\r\nimport data from \"./data\";\r\nimport extend from \"./extend\";\r\nimport DependencyLib from \"./inputmask.dependencyLib\";\r\n\r\nexport { on, off, trigger, Evnt as Event };\r\n\r\nconst document = window.document;\r\n\r\nfunction isValidElement(elem) {\r\n return elem instanceof Element && data(elem, \"events\");\r\n}\r\n\r\nlet Evnt;\r\nif (typeof window.CustomEvent === \"function\") {\r\n Evnt = window.CustomEvent;\r\n} else if (window.Event && document && document.createEvent) {\r\n Evnt = function (event, params) {\r\n params = params || {\r\n bubbles: false,\r\n cancelable: false,\r\n composed: true,\r\n detail: undefined\r\n };\r\n const evt = document.createEvent(\"CustomEvent\");\r\n evt.initCustomEvent(\r\n event,\r\n params.bubbles,\r\n params.cancelable,\r\n params.detail\r\n );\r\n return evt;\r\n };\r\n Evnt.prototype = window.Event.prototype;\r\n} else if (typeof Event !== \"undefined\") {\r\n // nodejs\r\n Evnt = Event;\r\n}\r\n\r\nfunction on(events, handler) {\r\n if (!this[0] || !isValidElement(this[0])) {\r\n return this; // Early return if no valid element\r\n }\r\n\r\n const elem = this[0],\r\n eventRegistry = data(elem, \"events\"),\r\n addEvent = (ev, namespace) => {\r\n // register domevent\r\n if (elem.addEventListener) {\r\n // all browsers except IE before version 9\r\n elem.addEventListener(ev, handler, false);\r\n } else if (elem.attachEvent) {\r\n // IE before version 9\r\n elem.attachEvent(`on${ev}`, handler);\r\n }\r\n eventRegistry[ev] = eventRegistry[ev] || {};\r\n eventRegistry[ev][namespace] = eventRegistry[ev][namespace] || [];\r\n eventRegistry[ev][namespace].push(handler);\r\n };\r\n\r\n events.split(\" \").forEach((event) => {\r\n const [ev, namespace = \"global\"] = event.split(\".\");\r\n addEvent(ev, namespace);\r\n });\r\n\r\n return this;\r\n}\r\n\r\nfunction off(events, handler) {\r\n let eventRegistry, elem;\r\n\r\n function removeEvent(ev, namespace, handler) {\r\n if (ev in eventRegistry === true) {\r\n // unbind to dom events\r\n if (elem.removeEventListener) {\r\n // all browsers except IE before version 9\r\n elem.removeEventListener(ev, handler, false);\r\n } else if (elem.detachEvent) {\r\n // IE before version 9\r\n elem.detachEvent(`on${ev}`, handler);\r\n }\r\n // when the namespace is not defined (global namespace), we need to clean up all events in all namespaces\r\n if (namespace === \"global\") {\r\n for (const nmsp in eventRegistry[ev]) {\r\n eventRegistry[ev][nmsp].splice(\r\n eventRegistry[ev][nmsp].indexOf(handler),\r\n 1\r\n );\r\n }\r\n } else {\r\n eventRegistry[ev][namespace].splice(\r\n eventRegistry[ev][namespace].indexOf(handler),\r\n 1\r\n );\r\n }\r\n }\r\n }\r\n\r\n function resolveNamespace(ev, namespace) {\r\n const evts = [];\r\n let hndx, hndL;\r\n if (ev.length > 0) {\r\n const namespaces = namespace\r\n ? [namespace]\r\n : Object.keys(eventRegistry[ev]);\r\n for (let nsi = 0; nsi < namespaces.length; nsi++) {\r\n namespace = namespaces[nsi];\r\n if (handler === undefined) {\r\n for (\r\n hndx = 0, hndL = eventRegistry[ev][namespace]?.length || 0;\r\n hndx < hndL;\r\n hndx++\r\n ) {\r\n evts.push({\r\n ev,\r\n namespace,\r\n handler: eventRegistry[ev][namespace][hndx]\r\n });\r\n }\r\n } else {\r\n evts.push({\r\n ev,\r\n namespace,\r\n handler\r\n });\r\n }\r\n }\r\n } else if (namespace.length > 0) {\r\n for (const evNdx in eventRegistry) {\r\n if (eventRegistry[evNdx][namespace]) {\r\n if (handler === undefined) {\r\n for (\r\n hndx = 0, hndL = eventRegistry[evNdx][namespace].length;\r\n hndx < hndL;\r\n hndx++\r\n ) {\r\n evts.push({\r\n ev: evNdx,\r\n namespace,\r\n handler: eventRegistry[evNdx][namespace][hndx]\r\n });\r\n }\r\n } else {\r\n evts.push({\r\n ev: evNdx,\r\n namespace,\r\n handler\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return evts;\r\n }\r\n\r\n if (isValidElement(this[0])) {\r\n eventRegistry = data(this[0], \"events\");\r\n elem = this[0];\r\n // if no events defined, remove all events\r\n events = events || Object.keys(eventRegistry).join(\" \");\r\n\r\n if (events !== \"\") {\r\n events.split(\" \").forEach((event) => {\r\n const [ev, namespace] = event.split(\".\");\r\n resolveNamespace(ev, namespace).forEach(\r\n ({ ev: ev1, handler: handler1, namespace: namespace1 }) => {\r\n removeEvent(ev1, namespace1, handler1);\r\n }\r\n );\r\n });\r\n }\r\n }\r\n return this;\r\n}\r\n\r\nfunction trigger(events /* , args... */) {\r\n if (isValidElement(this[0])) {\r\n const eventRegistry = data(this[0], \"events\"),\r\n elem = this[0],\r\n _events = typeof events === \"string\" ? events.split(\" \") : [events.type];\r\n for (let endx = 0; endx < _events.length; endx++) {\r\n const nsEvent = _events[endx].split(\".\"),\r\n ev = nsEvent[0],\r\n namespace = nsEvent[1] || \"global\";\r\n if (document !== undefined) {\r\n // trigger domevent\r\n let evnt;\r\n const params = {\r\n bubbles: true,\r\n cancelable: true,\r\n composed: true,\r\n detail: arguments[1]\r\n };\r\n // The custom event that will be created\r\n if (document.createEvent) {\r\n try {\r\n switch (ev) {\r\n case \"input\":\r\n params.inputType = \"insertText\";\r\n evnt = new InputEvent(ev, params);\r\n break;\r\n default:\r\n evnt = new CustomEvent(ev, params);\r\n }\r\n } catch (e) {\r\n evnt = document.createEvent(\"CustomEvent\");\r\n evnt.initCustomEvent(\r\n ev,\r\n params.bubbles,\r\n params.cancelable,\r\n params.detail\r\n );\r\n }\r\n if (events.type) extend(evnt, events);\r\n elem.dispatchEvent(evnt);\r\n } else {\r\n evnt = document.createEventObject();\r\n evnt.eventType = ev;\r\n evnt.detail = arguments[1];\r\n if (events.type) extend(evnt, events);\r\n elem.fireEvent(\"on\" + evnt.eventType, evnt);\r\n }\r\n } else if (eventRegistry[ev] !== undefined) {\r\n arguments[0] = arguments[0].type\r\n ? arguments[0]\r\n : DependencyLib.Event(arguments[0]);\r\n arguments[0].detail = arguments.slice(1);\r\n\r\n const registry = eventRegistry[ev],\r\n handlers =\r\n namespace === \"global\"\r\n ? Object.values(registry).flat()\r\n : registry[namespace];\r\n handlers.forEach((handler) => handler.apply(elem, arguments));\r\n }\r\n }\r\n }\r\n return this;\r\n}\r\n", "export default function extend() {\r\n let options,\r\n name,\r\n src,\r\n copy,\r\n copyIsArray,\r\n clone,\r\n target = arguments[0] || {},\r\n i = 1,\r\n length = arguments.length,\r\n deep = false;\r\n\r\n // Handle a deep copy situation\r\n if (typeof target === \"boolean\") {\r\n deep = target;\r\n\r\n // Skip the boolean and the target\r\n target = arguments[i] || {};\r\n i++;\r\n }\r\n\r\n // Handle case when target is a string or something (possible in deep copy)\r\n if (typeof target !== \"object\" && typeof target !== \"function\") {\r\n target = {};\r\n }\r\n\r\n for (; i < length; i++) {\r\n // Only deal with non-null/undefined values\r\n if ((options = arguments[i]) != null) {\r\n // Extend the base object\r\n for (name in options) {\r\n src = target[name];\r\n copy = options[name];\r\n\r\n // Prevent never-ending loop\r\n if (target === copy) {\r\n continue;\r\n }\r\n\r\n // Recurse if we're merging plain objects or arrays\r\n if (\r\n deep &&\r\n copy &&\r\n (Object.prototype.toString.call(copy) === \"[object Object]\" ||\r\n (copyIsArray = Array.isArray(copy)))\r\n ) {\r\n if (copyIsArray) {\r\n copyIsArray = false;\r\n clone = src && Array.isArray(src) ? src : [];\r\n } else {\r\n clone =\r\n src && Object.prototype.toString.call(src) === \"[object Object]\"\r\n ? src\r\n : {};\r\n }\r\n\r\n // Never move original objects, clone them\r\n target[name] = extend(deep, clone, copy);\r\n\r\n // Don't bring in undefined values\r\n } else if (copy !== undefined) {\r\n target[name] = copy;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Return the modified object\r\n return target;\r\n}\r\n", "import { HandleNativePlaceholder } from \"./inputHandling\";\r\nimport Inputmask from \"./inputmask\";\r\nimport { keys } from \"./keycode.js\";\r\nimport { getBufferTemplate } from \"./positioning\";\r\n\r\nexport { EventRuler };\r\n\r\nconst EventRuler = {\r\n on: function (input, eventName, eventHandler) {\r\n const $ = input.inputmask.dependencyLib;\r\n\r\n let ev = function (e) {\r\n if (e.originalEvent) {\r\n e = e.originalEvent || e; // get original event from jquery event\r\n arguments[0] = e;\r\n }\r\n // console.log(e.type);\r\n const that = this,\r\n inputmask = that.inputmask,\r\n opts = inputmask ? inputmask.opts : undefined;\r\n let args;\r\n if (inputmask === undefined && this.nodeName !== \"FORM\") {\r\n // happens when cloning an object with jquery.clone\r\n const imOpts = $.data(that, \"_inputmask_opts\");\r\n $(that).off(); // unbind all events\r\n if (imOpts) {\r\n new Inputmask(imOpts).mask(that);\r\n }\r\n } else if (\r\n ![\"submit\", \"reset\", \"setvalue\"].includes(e.type) &&\r\n this.nodeName !== \"FORM\" &&\r\n (that.disabled ||\r\n (that.readOnly &&\r\n !(\r\n (e.type === \"keydown\" && e.ctrlKey && e.key === keys.c) ||\r\n (opts.tabThrough === false && e.key === keys.Tab)\r\n )))\r\n ) {\r\n e.preventDefault();\r\n } else {\r\n switch (e.type) {\r\n case \"input\":\r\n if (inputmask.skipInputEvent === true) {\r\n inputmask.skipInputEvent = false;\r\n return e.preventDefault();\r\n }\r\n\r\n // #2855\r\n // Prevent duplicate input processing between keyEvent and inputFallBackEvent\r\n // This fixes Chinese IME duplication issue on Safari where both events fire for the same input\r\n // if (\r\n // inputmask.lastInputEvent &&\r\n // Date.now() - inputmask.lastInputEvent.time < 10 &&\r\n // inputmask.lastInputEvent.data === e.data\r\n // ) {\r\n // return;\r\n // }\r\n // Mark input as processed to prevent duplicate handling by keyEvent\r\n // This fixes Chinese IME duplication issue on Safari #2855\r\n inputmask.lastInputEvent = {\r\n time: Date.now(),\r\n data: e.data\r\n };\r\n\r\n // if (mobile) { //this causes problem see #2220\r\n // \targs = arguments;\r\n // \tsetTimeout(function () { //needed for caret selection when entering a char on Android 8 - #1818\r\n // \t\teventHandler.apply(that, args);\r\n // \t\tcaret(that, that.inputmask.caretPos, undefined, true);\r\n // \t}, 0);\r\n // \treturn false;\r\n // }\r\n break;\r\n case \"keydown\":\r\n // Prevent duplicate input processing between keyEvent and inputFallBackEvent #2855\r\n // This fixes Chinese IME duplication issue on Safari where both events fire for the same input\r\n if (\r\n inputmask.lastInputEvent &&\r\n Date.now() - inputmask.lastInputEvent.time < 10 &&\r\n inputmask.lastInputEvent.data === e.key\r\n ) {\r\n return false;\r\n }\r\n break;\r\n case \"click\":\r\n case \"focus\":\r\n if (inputmask.validationEvent) {\r\n // #841\r\n inputmask.validationEvent = false;\r\n input.blur();\r\n HandleNativePlaceholder(\r\n input,\r\n (inputmask.isRTL\r\n ? getBufferTemplate.call(inputmask).slice().reverse()\r\n : getBufferTemplate.call(inputmask)\r\n ).join(\"\")\r\n );\r\n setTimeout(function () {\r\n input.focus();\r\n }, opts.validationEventTimeOut);\r\n return false;\r\n }\r\n args = arguments;\r\n setTimeout(function () {\r\n // needed for Chrome ~ initial selection clears after the clickevent\r\n if (!input.inputmask) {\r\n // `inputmask.remove()` was called before this callback\r\n return;\r\n }\r\n eventHandler.apply(that, args);\r\n }, 0);\r\n return; /* false */ // #2423\r\n }\r\n const returnVal = eventHandler.apply(that, arguments);\r\n if (returnVal === false) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }\r\n return returnVal;\r\n }\r\n };\r\n // add inputmask namespace to event\r\n eventName = `${eventName}.inputmask`;\r\n if ([\"submit.inputmask\", \"reset.inputmask\"].includes(eventName)) {\r\n ev = ev.bind(input); // bind creates a new eventhandler (wrap)\r\n if (input.form !== null) $(input.form).on(eventName, ev);\r\n } else {\r\n $(input).on(eventName, ev);\r\n }\r\n },\r\n off: function (input, event) {\r\n if (input.inputmask) {\r\n const $ = input.inputmask.dependencyLib;\r\n $(input).off(event || \".inputmask\");\r\n }\r\n }\r\n};\r\n", "import { ie } from \"./environment\";\r\nimport { EventHandlers } from \"./eventhandlers\";\r\nimport Inputmask from \"./inputmask.js\";\r\nimport { keys } from \"./keycode.js\";\r\nimport {\r\n caret,\r\n determineNewCaretPosition,\r\n getBuffer,\r\n getBufferTemplate,\r\n getLastValidPosition,\r\n isMask,\r\n resetMaskSet,\r\n seekNext\r\n} from \"./positioning\";\r\nimport { isComplete, refreshFromBuffer } from \"./validation\";\r\nimport { getMaskTemplate, getPlaceholder, getTest } from \"./validation-tests\";\r\n\r\nexport {\r\n applyInputValue,\r\n clearOptionalTail,\r\n checkVal,\r\n HandleNativePlaceholder,\r\n unmaskedvalue,\r\n writeBuffer\r\n};\r\n\r\nfunction applyInputValue(input, value, initialEvent, strict) {\r\n const inputmask = input ? input.inputmask : this,\r\n opts = inputmask.opts;\r\n\r\n input.inputmask.refreshValue = false;\r\n if (strict !== true && typeof opts.onBeforeMask === \"function\")\r\n value = opts.onBeforeMask.call(inputmask, value, opts) || value;\r\n value = (value || \"\").toString().split(\"\");\r\n checkVal(input, true, false, value, initialEvent);\r\n inputmask.undoValue = inputmask._valueGet(true);\r\n if (\r\n (opts.clearMaskOnLostFocus || opts.clearIncomplete) &&\r\n input.inputmask._valueGet() ===\r\n getBufferTemplate.call(inputmask).join(\"\") &&\r\n getLastValidPosition.call(inputmask) === -1\r\n ) {\r\n input.inputmask._valueSet(\"\");\r\n }\r\n}\r\n\r\n// todo put on prototype?\r\nfunction clearOptionalTail(buffer) {\r\n const inputmask = this;\r\n\r\n buffer.length = 0;\r\n let template = getMaskTemplate.call(\r\n inputmask,\r\n true,\r\n 0,\r\n true,\r\n undefined,\r\n true\r\n ),\r\n lmnt;\r\n while ((lmnt = template.shift()) !== undefined) buffer.push(lmnt);\r\n return buffer;\r\n}\r\n\r\nfunction checkVal(input, writeOut, strict, nptvl, initiatingEvent) {\r\n const inputmask = input ? input.inputmask : this,\r\n maskset = inputmask.maskset,\r\n opts = inputmask.opts,\r\n $ = inputmask.dependencyLib;\r\n\r\n let inputValue = nptvl.slice(),\r\n charCodes = \"\",\r\n initialNdx = -1,\r\n result,\r\n skipOptionalPartCharacter = opts.skipOptionalPartCharacter;\r\n opts.skipOptionalPartCharacter = \"\"; // see issue #2311\r\n\r\n function isTemplateMatch(ndx, charCodes) {\r\n let targetTemplate = getMaskTemplate\r\n .call(inputmask, true, 0)\r\n .slice(ndx, seekNext.call(inputmask, ndx, false, false))\r\n .join(\"\")\r\n .replace(/'/g, \"\"),\r\n charCodeNdx = targetTemplate.indexOf(charCodes);\r\n // strip spaces from targetTemplate\r\n while (charCodeNdx > 0 && targetTemplate[charCodeNdx - 1] === \" \")\r\n charCodeNdx--;\r\n\r\n const match =\r\n charCodeNdx === 0 &&\r\n !isMask.call(inputmask, ndx) &&\r\n (getTest.call(inputmask, ndx).match.nativeDef === charCodes.charAt(0) ||\r\n (getTest.call(inputmask, ndx).match.static === true &&\r\n getTest.call(inputmask, ndx).match.nativeDef ===\r\n \"'\" + charCodes.charAt(0)) ||\r\n (getTest.call(inputmask, ndx).match.nativeDef === \" \" &&\r\n (getTest.call(inputmask, ndx + 1).match.nativeDef ===\r\n charCodes.charAt(0) ||\r\n (getTest.call(inputmask, ndx + 1).match.static === true &&\r\n getTest.call(inputmask, ndx + 1).match.nativeDef ===\r\n \"'\" + charCodes.charAt(0)))));\r\n\r\n if (\r\n !match &&\r\n charCodeNdx > 0 &&\r\n !isMask.call(inputmask, ndx, false, true)\r\n ) {\r\n const nextPos = seekNext.call(inputmask, ndx);\r\n if (inputmask.caretPos.begin < nextPos) {\r\n inputmask.caretPos = { begin: nextPos };\r\n }\r\n }\r\n return match;\r\n }\r\n\r\n resetMaskSet.call(inputmask, false);\r\n inputmask.clicked = 0; // reset click counter to correctly determine the caretposition in checkval\r\n initialNdx = opts.radixPoint\r\n ? determineNewCaretPosition.call(\r\n inputmask,\r\n {\r\n begin: 0,\r\n end: 0\r\n },\r\n false,\r\n opts.__financeInput === false ? \"radixFocus\" : undefined\r\n ).begin\r\n : 0;\r\n maskset.p = initialNdx;\r\n inputmask.caretPos = { begin: initialNdx };\r\n\r\n let staticMatches = [],\r\n prevCaretPos = inputmask.caretPos;\r\n inputValue.forEach(function (charCode, ndx) {\r\n if (charCode !== undefined) {\r\n // inputfallback strips some elements out of the inputarray. $.each logically presents them as undefined\r\n /* if (maskset.validPositions[ndx] === undefined && inputValue[ndx] === getPlaceholder.call(inputmask, ndx) && isMask.call(inputmask, ndx, true) &&\r\n\t\t\t\tisValid.call(inputmask, ndx, inputValue[ndx], true, undefined, true, true) === false) {\r\n\t\t\t\tinputmask.caretPos.begin++;\r\n\t\t\t} else */\r\n // console.log(\"caret \" + inputmask.caretPos.begin);\r\n const keypress = new $.Event(\"_checkval\");\r\n keypress.key = charCode;\r\n charCodes += charCode;\r\n const lvp = getLastValidPosition.call(inputmask, undefined, true);\r\n if (!isTemplateMatch(initialNdx, charCodes)) {\r\n result = EventHandlers.keypressEvent.call(\r\n inputmask,\r\n keypress,\r\n true,\r\n false,\r\n strict,\r\n inputmask.caretPos.begin\r\n );\r\n\r\n if (result) {\r\n initialNdx = inputmask.caretPos.begin + 1;\r\n charCodes = \"\";\r\n }\r\n } else {\r\n result =\r\n getTest.call(inputmask, ndx).match.static === true\r\n ? EventHandlers.keypressEvent.call(\r\n inputmask,\r\n keypress,\r\n true,\r\n false,\r\n strict,\r\n lvp + 1\r\n )\r\n : false;\r\n }\r\n if (result) {\r\n if (\r\n result.pos !== undefined &&\r\n maskset.validPositions[result.pos] &&\r\n maskset.validPositions[result.pos].match.static === true &&\r\n maskset.validPositions[result.pos].alternation === undefined\r\n ) {\r\n staticMatches.push(result.pos);\r\n if (!inputmask.isRTL) {\r\n result.forwardPosition = result.pos + 1;\r\n }\r\n }\r\n writeBuffer.call(\r\n inputmask,\r\n undefined,\r\n getBuffer.call(inputmask),\r\n result.forwardPosition,\r\n keypress,\r\n false\r\n );\r\n inputmask.caretPos = {\r\n begin: result.forwardPosition,\r\n end: result.forwardPosition\r\n };\r\n prevCaretPos = inputmask.caretPos;\r\n } else {\r\n if (\r\n maskset.validPositions[ndx] === undefined &&\r\n inputValue[ndx] === getPlaceholder.call(inputmask, ndx) &&\r\n isMask.call(inputmask, ndx, true)\r\n ) {\r\n inputmask.caretPos.begin++;\r\n } else inputmask.caretPos = prevCaretPos; // restore the caret position from before the failed validation\r\n }\r\n }\r\n });\r\n if (staticMatches.length > 0) {\r\n let sndx,\r\n validPos,\r\n nextValid = seekNext.call(inputmask, -1, undefined, false);\r\n if (\r\n (!isComplete.call(inputmask, getBuffer.call(inputmask)) &&\r\n staticMatches.length <= nextValid) ||\r\n (isComplete.call(inputmask, getBuffer.call(inputmask)) &&\r\n staticMatches.length > 0 &&\r\n staticMatches.length !== nextValid &&\r\n staticMatches[0] === 0)\r\n ) {\r\n // should check if is sequence starting from 0\r\n let nextSndx = nextValid;\r\n while ((sndx = staticMatches.shift()) !== undefined) {\r\n if (sndx < nextSndx) {\r\n const keypress = new $.Event(\"_checkval\");\r\n validPos = maskset.validPositions[sndx];\r\n validPos.generatedInput = true;\r\n keypress.key = validPos.input;\r\n result = EventHandlers.keypressEvent.call(\r\n inputmask,\r\n keypress,\r\n true,\r\n false,\r\n strict,\r\n nextSndx\r\n );\r\n if (\r\n result &&\r\n result.pos !== undefined &&\r\n result.pos !== sndx &&\r\n maskset.validPositions[result.pos] &&\r\n maskset.validPositions[result.pos].match.static === true\r\n ) {\r\n staticMatches.push(result.pos);\r\n } else if (!result) break;\r\n nextSndx++;\r\n }\r\n }\r\n } else {\r\n // delete all free statics\r\n while ((sndx = staticMatches.pop())) {\r\n validPos = maskset.validPositions[sndx];\r\n if (validPos && maskset.validPositions[sndx + 1] === undefined) {\r\n delete maskset.validPositions[sndx];\r\n }\r\n }\r\n }\r\n }\r\n if (writeOut) {\r\n writeBuffer.call(\r\n inputmask,\r\n input,\r\n getBuffer.call(inputmask),\r\n result ? result.forwardPosition : inputmask.caretPos.begin,\r\n initiatingEvent || new $.Event(\"checkval\"),\r\n initiatingEvent &&\r\n ((initiatingEvent.type === \"input\" &&\r\n inputmask.undoValue !== getBuffer.call(inputmask).join(\"\")) ||\r\n initiatingEvent.type === \"paste\")\r\n );\r\n // for (var vndx in maskset.validPositions) {\r\n // \tif (maskset.validPositions[vndx].match.generated !== true) { //only remove non forced generated\r\n // \t\tdelete maskset.validPositions[vndx].generatedInput; //clear generated markings ~ consider initializing with a value as fully typed\r\n // \t}\r\n // }\r\n }\r\n opts.skipOptionalPartCharacter = skipOptionalPartCharacter;\r\n}\r\n\r\nfunction HandleNativePlaceholder(npt, value) {\r\n const inputmask = npt ? npt.inputmask : this;\r\n\r\n if (ie) {\r\n if (\r\n npt.inputmask._valueGet() !== value &&\r\n (npt.placeholder !== value || npt.placeholder === \"\")\r\n ) {\r\n let buffer = getBuffer.call(inputmask).slice(),\r\n nptValue = npt.inputmask._valueGet();\r\n if (nptValue !== value) {\r\n const lvp = getLastValidPosition.call(inputmask);\r\n if (\r\n lvp === -1 &&\r\n nptValue === getBufferTemplate.call(inputmask).join(\"\")\r\n ) {\r\n buffer = [];\r\n } else if (lvp !== -1) {\r\n // clearout optional tail of the mask\r\n clearOptionalTail.call(inputmask, buffer);\r\n }\r\n writeBuffer(npt, buffer);\r\n }\r\n }\r\n } else if (npt.placeholder !== value) {\r\n npt.placeholder = value;\r\n if (npt.placeholder === \"\") npt.removeAttribute(\"placeholder\");\r\n }\r\n}\r\n\r\nfunction unmaskedvalue(input) {\r\n const inputmask = input ? input.inputmask : this,\r\n opts = inputmask.opts,\r\n maskset = inputmask.maskset;\r\n\r\n if (input) {\r\n if (input.inputmask === undefined) {\r\n return input.value;\r\n }\r\n if (input.inputmask && input.inputmask.refreshValue) {\r\n // forced refresh from the value form.reset\r\n applyInputValue(input, input.inputmask._valueGet(true));\r\n }\r\n }\r\n const umValue = [],\r\n vps = maskset.validPositions;\r\n for (let pndx = 0, vpl = vps.length; pndx < vpl; pndx++) {\r\n if (\r\n vps[pndx] &&\r\n vps[pndx].match &&\r\n (vps[pndx].match.static != true ||\r\n (opts.keepStatic !== true &&\r\n Array.isArray(maskset.metadata) &&\r\n vps[pndx].generatedInput !== true))\r\n ) {\r\n // only include non generated input with multiple masks (check on metadata) and without keepStatic true\r\n umValue.push(vps[pndx].input);\r\n }\r\n }\r\n let unmaskedValue =\r\n umValue.length === 0\r\n ? \"\"\r\n : (inputmask.isRTL ? umValue.reverse() : umValue).join(\"\");\r\n if (typeof opts.onUnMask === \"function\") {\r\n const bufferValue = (\r\n inputmask.isRTL\r\n ? getBuffer.call(inputmask).slice().reverse()\r\n : getBuffer.call(inputmask)\r\n ).join(\"\");\r\n unmaskedValue = opts.onUnMask.call(\r\n inputmask,\r\n bufferValue,\r\n unmaskedValue,\r\n opts\r\n );\r\n }\r\n\r\n if (opts.outputMask && unmaskedValue.length > 0) {\r\n return Inputmask.format(unmaskedValue, {\r\n ...opts,\r\n mask: opts.outputMask,\r\n alias: null\r\n });\r\n }\r\n\r\n return unmaskedValue;\r\n}\r\n\r\nfunction writeBuffer(input, buffer, caretPos, event, triggerEvents) {\r\n const inputmask = input ? input.inputmask : this,\r\n opts = inputmask.opts,\r\n $ = inputmask.dependencyLib;\r\n\r\n if (event && typeof opts.onBeforeWrite === \"function\") {\r\n // buffer = buffer.slice(); //prevent uncontrolled manipulation of the internal buffer\r\n const result = opts.onBeforeWrite.call(\r\n inputmask,\r\n event,\r\n buffer,\r\n caretPos,\r\n opts\r\n );\r\n if (result) {\r\n if (result.refreshFromBuffer) {\r\n const refresh = result.refreshFromBuffer;\r\n refreshFromBuffer.call(\r\n inputmask,\r\n refresh === true ? refresh : refresh.start,\r\n refresh.end,\r\n result.buffer || buffer\r\n );\r\n buffer = getBuffer.call(inputmask, true);\r\n }\r\n if (caretPos !== undefined)\r\n caretPos = result.caret !== undefined ? result.caret : caretPos;\r\n }\r\n }\r\n if (input !== undefined) {\r\n input.inputmask._valueSet(buffer.join(\"\"));\r\n if (\r\n caretPos !== undefined &&\r\n (event === undefined || event.type !== \"blur\")\r\n ) {\r\n // console.log(caretPos);\r\n caret.call(\r\n inputmask,\r\n input,\r\n caretPos,\r\n undefined,\r\n undefined,\r\n event !== undefined &&\r\n event.type === \"keydown\" &&\r\n (event.key === keys.Delete || event.key === keys.Backspace)\r\n );\r\n }\r\n input.inputmask.writeBufferHook === undefined ||\r\n input.inputmask.writeBufferHook(caretPos);\r\n if (triggerEvents === true) {\r\n const $input = $(input),\r\n nptVal = input.inputmask._valueGet();\r\n input.inputmask.skipInputEvent = true;\r\n $input.trigger(\"input\");\r\n setTimeout(function () {\r\n // timeout needed for IE\r\n if (nptVal === getBufferTemplate.call(inputmask).join(\"\")) {\r\n $input.trigger(\"cleared\");\r\n } else if (isComplete.call(inputmask, buffer) === true) {\r\n $input.trigger(\"complete\");\r\n }\r\n }, 0);\r\n }\r\n }\r\n}\r\n", "import window from \"./global/window\";\r\n\r\nconst ua = (window.navigator && window.navigator.userAgent) || \"\",\r\n ie = ua.indexOf(\"MSIE \") > 0 || ua.indexOf(\"Trident/\") > 0,\r\n mobile = !!(\r\n navigator.userAgentData?.mobile ??\r\n (((matchMedia(\"(pointer:coarse)\").matches || navigator.maxTouchPoints) &&\r\n innerWidth <= 1024) ||\r\n /Mobi|Android|iPhone/i.test(ua))\r\n ),\r\n iphone = /iphone/i.test(ua);\r\n\r\nexport { ie, mobile, iphone };\r\n", "import { iphone, mobile } from \"./environment\";\r\nimport window from \"./global/window\";\r\nimport {\r\n applyInputValue,\r\n checkVal,\r\n clearOptionalTail,\r\n HandleNativePlaceholder,\r\n writeBuffer\r\n} from \"./inputHandling\";\r\nimport { keys } from \"./keycode.js\";\r\nimport {\r\n caret,\r\n determineNewCaretPosition,\r\n getBuffer,\r\n getBufferTemplate,\r\n getLastValidPosition,\r\n isMask,\r\n resetMaskSet,\r\n seekNext,\r\n seekPrevious,\r\n translatePosition\r\n} from \"./positioning\";\r\nimport { handleRemove, isComplete, isSelection, isValid } from \"./validation\";\r\nimport { getPlaceholder, getTest } from \"./validation-tests\";\r\n\r\nexport { EventHandlers };\r\n\r\nconst EventHandlers = {\r\n keyEvent: function (e, checkval, writeOut, strict, ndx) {\r\n const inputmask = this.inputmask,\r\n opts = inputmask.opts,\r\n $ = inputmask.dependencyLib,\r\n maskset = inputmask.maskset,\r\n input = this,\r\n $input = $(input),\r\n c = e.key,\r\n pos = caret.call(inputmask, input),\r\n kdResult = opts.onKeyDown.call(\r\n this,\r\n e,\r\n getBuffer.call(inputmask),\r\n pos,\r\n opts\r\n );\r\n if (kdResult !== undefined) return kdResult;\r\n\r\n // backspace, delete, and escape get special treatment\r\n if (\r\n c === keys.Backspace ||\r\n c === keys.Delete ||\r\n (iphone && c === keys.BACKSPACE_SAFARI) ||\r\n (e.ctrlKey && c === keys.x && !(\"oncut\" in input))\r\n ) {\r\n // backspace/delete\r\n e.preventDefault(); // stop default action but allow propagation\r\n handleRemove.call(inputmask, input, c, pos);\r\n writeBuffer(\r\n input,\r\n getBuffer.call(inputmask, true),\r\n maskset.p,\r\n e,\r\n input.inputmask._valueGet() !== getBuffer.call(inputmask).join(\"\")\r\n );\r\n } else if (c === keys.End || c === keys.PageDown) {\r\n // when END or PAGE_DOWN pressed set position at lastmatch\r\n e.preventDefault();\r\n const caretPos = seekNext.call(\r\n inputmask,\r\n getLastValidPosition.call(inputmask)\r\n );\r\n caret.call(\r\n inputmask,\r\n input,\r\n e.shiftKey ? pos.begin : caretPos,\r\n caretPos,\r\n true\r\n );\r\n } else if ((c === keys.Home && !e.shiftKey) || c === keys.PageUp) {\r\n // Home or page_up\r\n e.preventDefault();\r\n caret.call(inputmask, input, 0, e.shiftKey ? pos.begin : 0, true);\r\n } else if (\r\n ((opts.undoOnEscape && c === keys.Escape) ||\r\n // eslint-disable-next-line no-constant-binary-expression -- TODO: revisit, ctrl+z undo branch is disabled via `false &&`, see #762\r\n (false && c === keys.z && e.ctrlKey)) &&\r\n e.altKey !== true\r\n ) {\r\n // escape && undo && #762\r\n checkVal(input, true, false, inputmask.undoValue.split(\"\"));\r\n $input.trigger(\"click\");\r\n } else if (\r\n c === keys.Insert &&\r\n !(e.shiftKey || e.ctrlKey) &&\r\n inputmask.userOptions.insertMode === undefined\r\n ) {\r\n // insert\r\n if (!isSelection.call(inputmask, pos)) {\r\n opts.insertMode = !opts.insertMode;\r\n caret.call(inputmask, input, pos.begin, pos.begin);\r\n } else opts.insertMode = !opts.insertMode;\r\n } else if (opts.tabThrough === true && c === keys.Tab) {\r\n if (e.shiftKey === true) {\r\n pos.end = seekPrevious.call(inputmask, pos.end, true);\r\n if (getTest.call(inputmask, pos.end - 1).match.static === true) {\r\n pos.end--;\r\n }\r\n pos.begin = seekPrevious.call(inputmask, pos.end, true);\r\n if (pos.begin >= 0 && pos.end > 0) {\r\n e.preventDefault();\r\n caret.call(inputmask, input, pos.begin, pos.end);\r\n }\r\n } else {\r\n pos.begin = seekNext.call(inputmask, pos.begin, true);\r\n pos.end = seekNext.call(inputmask, pos.begin, true);\r\n if (pos.end < maskset.maskLength) pos.end--;\r\n if (pos.begin <= maskset.maskLength) {\r\n e.preventDefault();\r\n caret.call(inputmask, input, pos.begin, pos.end);\r\n }\r\n }\r\n } else if (!e.shiftKey) {\r\n if (opts.insertModeVisual && opts.insertMode === false) {\r\n if (c === keys.ArrowRight) {\r\n setTimeout(function () {\r\n const caretPos = caret.call(inputmask, input);\r\n caret.call(inputmask, input, caretPos.begin);\r\n }, 0);\r\n } else if (c === keys.ArrowLeft) {\r\n setTimeout(function () {\r\n const caretPos = {\r\n begin: translatePosition.call(\r\n inputmask,\r\n input.inputmask.caretPos.begin\r\n ),\r\n end: translatePosition.call(\r\n inputmask,\r\n input.inputmask.caretPos.end\r\n )\r\n };\r\n if (inputmask.isRTL) {\r\n caret.call(\r\n inputmask,\r\n input,\r\n caretPos.begin + (caretPos.begin === maskset.maskLength ? 0 : 1)\r\n );\r\n } else {\r\n caret.call(\r\n inputmask,\r\n input,\r\n caretPos.begin - (caretPos.begin === 0 ? 0 : 1)\r\n );\r\n }\r\n }, 0);\r\n }\r\n } else {\r\n inputmask.keyEventHook === undefined || inputmask.keyEventHook(e);\r\n }\r\n }\r\n\r\n inputmask.isComposing = c === keys.Process || c === keys.Unidentified;\r\n\r\n inputmask.ignorable = c === undefined || c.length > 1;\r\n return EventHandlers.keypressEvent.call(\r\n inputmask,\r\n e,\r\n checkval,\r\n writeOut,\r\n strict,\r\n ndx\r\n );\r\n },\r\n keypressEvent: function (e, checkval, writeOut, strict, ndx) {\r\n const inputmask = this.inputmask || this,\r\n opts = inputmask.opts,\r\n $ = inputmask.dependencyLib,\r\n maskset = inputmask.maskset,\r\n input = inputmask.el,\r\n $input = $(input);\r\n\r\n let c = e.key;\r\n\r\n if (\r\n checkval !== true &&\r\n !(e.ctrlKey && e.altKey && !inputmask.ignorable) &&\r\n (e.ctrlKey || e.metaKey || inputmask.ignorable)\r\n ) {\r\n if (c === keys.Enter) {\r\n if (inputmask.undoValue !== inputmask._valueGet(true)) {\r\n inputmask.undoValue = inputmask._valueGet(true);\r\n setTimeout(function () {\r\n $input.trigger(\"change\");\r\n }, 0);\r\n }\r\n }\r\n } else if (c) {\r\n // special treat the decimal separator\r\n // if ((k === 44 || k === 46) && e.location === 3 && opts.radixPoint !== \"\") k = opts.radixPoint.charCodeAt(0);\r\n let pos = checkval\r\n ? {\r\n begin: ndx,\r\n end: ndx\r\n }\r\n : caret.call(inputmask, input),\r\n forwardPosition;\r\n\r\n // allow for character substitution\r\n if (!checkval) c = opts.substitutes[c] || c;\r\n maskset.writeOutBuffer = true;\r\n const valResult = isValid.call(\r\n inputmask,\r\n pos,\r\n c,\r\n strict,\r\n undefined,\r\n undefined,\r\n undefined,\r\n checkval\r\n );\r\n if (valResult !== false) {\r\n resetMaskSet.call(inputmask, true);\r\n forwardPosition =\r\n valResult.caret !== undefined\r\n ? valResult.caret\r\n : seekNext.call(\r\n inputmask,\r\n valResult.pos.begin ? valResult.pos.begin : valResult.pos\r\n );\r\n maskset.p = forwardPosition; // needed for checkval\r\n }\r\n\r\n forwardPosition =\r\n opts.numericInput && valResult.caret === undefined\r\n ? seekPrevious.call(inputmask, forwardPosition)\r\n : forwardPosition;\r\n if (writeOut !== false) {\r\n setTimeout(function () {\r\n opts.onKeyValidation.call(input, c, valResult);\r\n }, 0);\r\n if (maskset.writeOutBuffer && valResult !== false) {\r\n const buffer = getBuffer.call(inputmask);\r\n writeBuffer(input, buffer, forwardPosition, e, checkval !== true);\r\n }\r\n }\r\n\r\n e.preventDefault();\r\n\r\n if (checkval) {\r\n if (valResult !== false) valResult.forwardPosition = forwardPosition;\r\n return valResult;\r\n }\r\n }\r\n },\r\n pasteEvent: async function (e) {\r\n function handlePaste(\r\n inputmask,\r\n input,\r\n inputValue,\r\n pastedValue,\r\n onBeforePaste\r\n ) {\r\n let caretPos = caret.call(inputmask, input, undefined, undefined, true),\r\n valueBeforeCaret = inputValue.substr(0, caretPos.begin),\r\n valueAfterCaret = inputValue.substr(caretPos.end, inputValue.length);\r\n\r\n if (\r\n valueBeforeCaret ==\r\n (inputmask.isRTL\r\n ? getBufferTemplate.call(inputmask).slice().reverse()\r\n : getBufferTemplate.call(inputmask)\r\n )\r\n .slice(0, caretPos.begin)\r\n .join(\"\")\r\n )\r\n valueBeforeCaret = \"\";\r\n if (\r\n valueAfterCaret ==\r\n (inputmask.isRTL\r\n ? getBufferTemplate.call(inputmask).slice().reverse()\r\n : getBufferTemplate.call(inputmask)\r\n )\r\n .slice(caretPos.end)\r\n .join(\"\")\r\n )\r\n valueAfterCaret = \"\";\r\n\r\n pastedValue = valueBeforeCaret + pastedValue + valueAfterCaret;\r\n if (inputmask.isRTL && opts.numericInput !== true) {\r\n pastedValue = pastedValue.split(\"\");\r\n for (const c of getBufferTemplate.call(inputmask)) {\r\n if (pastedValue[0] === c) pastedValue.shift();\r\n }\r\n pastedValue = pastedValue.reverse().join(\"\");\r\n }\r\n\r\n let pasteValue = pastedValue;\r\n if (typeof onBeforePaste === \"function\") {\r\n pasteValue = onBeforePaste.call(inputmask, pasteValue, opts);\r\n if (pasteValue === false) {\r\n return false;\r\n }\r\n if (!pasteValue) {\r\n pasteValue = inputValue;\r\n }\r\n }\r\n checkVal(input, true, false, pasteValue.toString().split(\"\"), e);\r\n }\r\n\r\n const input = this,\r\n inputmask = this.inputmask,\r\n opts = inputmask.opts;\r\n let inputValue = inputmask._valueGet(true),\r\n pastedValue;\r\n\r\n inputmask.skipInputEvent = true;\r\n if (e.clipboardData && e.clipboardData.getData) {\r\n pastedValue = e.clipboardData.getData(\"text/plain\");\r\n } else if (window.clipboardData && window.clipboardData.getData) {\r\n // IE\r\n pastedValue = window.clipboardData.getData(\"Text\");\r\n }\r\n handlePaste(inputmask, input, inputValue, pastedValue, opts.onBeforePaste);\r\n e.preventDefault();\r\n },\r\n inputFallBackEvent: function (e) {\r\n // fallback when keypress is not triggered\r\n const inputmask = this.inputmask,\r\n opts = inputmask.opts,\r\n $ = inputmask.dependencyLib;\r\n\r\n // console.log(e.inputType);\r\n\r\n function analyseChanges(inputValue, buffer, caretPos) {\r\n let frontPart = inputValue.substr(0, caretPos.begin).split(\"\"),\r\n backPart = inputValue.substr(caretPos.begin).split(\"\"),\r\n frontBufferPart = buffer.substr(0, caretPos.begin).split(\"\"),\r\n backBufferPart = buffer.substr(caretPos.begin).split(\"\"),\r\n fpl =\r\n frontPart.length >= frontBufferPart.length\r\n ? frontPart.length\r\n : frontBufferPart.length,\r\n bpl =\r\n backPart.length >= backBufferPart.length\r\n ? backPart.length\r\n : backBufferPart.length,\r\n bl,\r\n i,\r\n action = \"\",\r\n data = [],\r\n marker = \"~\",\r\n placeholder;\r\n\r\n // align buffers\r\n while (frontPart.length < fpl) frontPart.push(marker);\r\n while (frontBufferPart.length < fpl) frontBufferPart.push(marker);\r\n while (backPart.length < bpl) backPart.unshift(marker);\r\n while (backBufferPart.length < bpl) backBufferPart.unshift(marker);\r\n\r\n const newBuffer = frontPart.concat(backPart),\r\n oldBuffer = frontBufferPart.concat(backBufferPart);\r\n\r\n // console.log(\"N \" + newBuffer);\r\n // console.log(\"O \" + oldBuffer);\r\n\r\n for (i = 0, bl = newBuffer.length; i < bl; i++) {\r\n placeholder = getPlaceholder.call(\r\n inputmask,\r\n translatePosition.call(inputmask, i)\r\n );\r\n switch (action) {\r\n case \"insertText\":\r\n if (\r\n oldBuffer[i - 1] === newBuffer[i] &&\r\n caretPos.begin == newBuffer.length - 1\r\n ) {\r\n data.push(newBuffer[i]);\r\n }\r\n i = bl;\r\n break;\r\n case \"insertReplacementText\":\r\n if (newBuffer[i] === marker) {\r\n // extend selection\r\n caretPos.end++;\r\n } else {\r\n // breakout loop\r\n i = bl;\r\n }\r\n break;\r\n case \"deleteContentBackward\":\r\n if (newBuffer[i] === marker) {\r\n caretPos.end++;\r\n } else {\r\n // breakout loop\r\n i = bl;\r\n }\r\n break;\r\n default:\r\n if (newBuffer[i] !== oldBuffer[i]) {\r\n if (\r\n (newBuffer[i + 1] === marker ||\r\n newBuffer[i + 1] === placeholder ||\r\n newBuffer[i + 1] === undefined) &&\r\n ((oldBuffer[i] === placeholder &&\r\n oldBuffer[i + 1] === marker) ||\r\n oldBuffer[i] === marker)\r\n ) {\r\n // basic insert\r\n action = \"insertText\";\r\n data.push(newBuffer[i]);\r\n caretPos.begin--;\r\n caretPos.end--;\r\n } else if (\r\n oldBuffer[i + 1] === marker &&\r\n oldBuffer[i] === newBuffer[i + 1]\r\n ) {\r\n // insert between\r\n action = \"insertText\";\r\n data.push(newBuffer[i]);\r\n caretPos.begin--;\r\n caretPos.end--;\r\n } else if (\r\n newBuffer[i] !== placeholder &&\r\n newBuffer[i] !== marker &&\r\n (newBuffer[i + 1] === marker ||\r\n (oldBuffer[i] !== newBuffer[i] &&\r\n oldBuffer[i + 1] ===\r\n newBuffer[i + 1])) /* single char replacement */\r\n ) {\r\n // replace selection\r\n action = \"insertReplacementText\";\r\n data.push(newBuffer[i]);\r\n caretPos.begin--;\r\n } else if (newBuffer[i] === marker) {\r\n // delete~backspace\r\n action = \"deleteContentBackward\";\r\n if (\r\n isMask.call(\r\n inputmask,\r\n translatePosition.call(inputmask, i),\r\n true\r\n ) ||\r\n oldBuffer[i] === opts.radixPoint\r\n )\r\n caretPos.end++;\r\n } else {\r\n i = bl;\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n\r\n return {\r\n action,\r\n data,\r\n caret: caretPos\r\n };\r\n }\r\n\r\n let input = this,\r\n inputValue = input.inputmask._valueGet(true),\r\n buffer = (\r\n inputmask.isRTL\r\n ? getBuffer.call(inputmask).slice().reverse()\r\n : getBuffer.call(inputmask)\r\n ).join(\"\"),\r\n caretPos = caret.call(inputmask, input, undefined, undefined, true),\r\n changes;\r\n\r\n if (buffer !== inputValue) {\r\n changes = analyseChanges(inputValue, buffer, caretPos);\r\n if (input.getRootNode().activeElement !== input) {\r\n input.focus();\r\n }\r\n writeBuffer(input, getBuffer.call(inputmask));\r\n caret.call(inputmask, input, caretPos.begin, caretPos.end, true);\r\n\r\n // Japanese IME hack #2662\r\n if (\r\n !mobile &&\r\n inputmask.skipNextInsert &&\r\n e.inputType === \"insertText\" &&\r\n changes.action === \"insertText\" &&\r\n inputmask.isComposing\r\n ) {\r\n return false;\r\n }\r\n if (\r\n e.inputType === \"insertCompositionText\" &&\r\n changes.action === \"insertText\" &&\r\n inputmask.isComposing\r\n ) {\r\n inputmask.skipNextInsert = true;\r\n } else {\r\n inputmask.skipNextInsert = false;\r\n }\r\n\r\n switch (changes.action) {\r\n case \"insertText\":\r\n case \"insertReplacementText\":\r\n changes.data.forEach(function (entry, ndx) {\r\n const keypress = new $.Event(\"keypress\");\r\n keypress.key = entry;\r\n inputmask.ignorable = false; // make sure ignorable is ignored ;-)\r\n EventHandlers.keypressEvent.call(input, keypress);\r\n });\r\n setTimeout(function () {\r\n // #2195 trigger keyup to help some other plugins to track changes\r\n inputmask.$el.trigger(\"keyup\");\r\n }, 0);\r\n break;\r\n case \"deleteContentBackward\":\r\n var keydown = new $.Event(\"keydown\");\r\n keydown.key = keys.Backspace;\r\n EventHandlers.keyEvent.call(input, keydown);\r\n break;\r\n default:\r\n applyInputValue(input, inputValue, e);\r\n caret.call(inputmask, input, caretPos.begin, caretPos.end, true);\r\n break;\r\n }\r\n\r\n e.preventDefault();\r\n }\r\n },\r\n setValueEvent: function (e) {\r\n const inputmask = this.inputmask,\r\n $ = inputmask.dependencyLib;\r\n let input = this,\r\n value = e && e.detail ? e.detail[0] : arguments[1];\r\n\r\n if (value === undefined) {\r\n value = input.inputmask._valueGet(true);\r\n }\r\n\r\n applyInputValue(\r\n input,\r\n value,\r\n new $.Event(\"input\"),\r\n (e && e.detail ? e.detail[0] : arguments[1]) !== undefined\r\n );\r\n\r\n if ((e.detail && e.detail[1] !== undefined) || arguments[2] !== undefined) {\r\n caret.call(inputmask, input, e.detail ? e.detail[1] : arguments[2]);\r\n }\r\n },\r\n focusEvent: function (e) {\r\n const inputmask = this.inputmask,\r\n opts = inputmask.opts,\r\n input = this,\r\n nptValue = inputmask && inputmask._valueGet();\r\n\r\n if (opts.showMaskOnFocus) {\r\n if (nptValue !== getBuffer.call(inputmask).join(\"\")) {\r\n writeBuffer(\r\n input,\r\n getBuffer.call(inputmask),\r\n seekNext.call(inputmask, getLastValidPosition.call(inputmask))\r\n );\r\n } /* else if (mouseEnter === false) { //only executed on focus without mouseenter\r\n\t\t\t\t\tcaret(input, seekNext(getLastValidPosition()));\r\n\t\t\t\t} */\r\n }\r\n if (\r\n opts.positionCaretOnTab === true &&\r\n inputmask.mouseEnter === false &&\r\n (!isComplete.call(inputmask, getBuffer.call(inputmask)) ||\r\n getLastValidPosition.call(inputmask) === -1)\r\n ) {\r\n EventHandlers.clickEvent.apply(input, [e, true]);\r\n }\r\n inputmask.undoValue = inputmask && inputmask._valueGet(true);\r\n },\r\n invalidEvent: function (e) {\r\n this.inputmask.validationEvent = true;\r\n },\r\n mouseleaveEvent: function () {\r\n const inputmask = this.inputmask,\r\n opts = inputmask.opts,\r\n input = this;\r\n inputmask.mouseEnter = false;\r\n if (\r\n opts.clearMaskOnLostFocus &&\r\n input.getRootNode().activeElement !== input\r\n ) {\r\n HandleNativePlaceholder(input, inputmask.originalPlaceholder);\r\n }\r\n },\r\n clickEvent: function (e, tabbed) {\r\n const inputmask = this.inputmask;\r\n inputmask.clicked++;\r\n\r\n const input = this;\r\n if (input.getRootNode().activeElement === input) {\r\n const newCaretPosition = determineNewCaretPosition.call(\r\n inputmask,\r\n caret.call(inputmask, input),\r\n tabbed\r\n );\r\n if (newCaretPosition !== undefined) {\r\n caret.call(inputmask, input, newCaretPosition);\r\n }\r\n }\r\n },\r\n cutEvent: function (e) {\r\n const inputmask = this.inputmask,\r\n maskset = inputmask.maskset,\r\n input = this,\r\n pos = caret.call(inputmask, input),\r\n // correct clipboardData\r\n clipData = inputmask.isRTL\r\n ? getBuffer.call(inputmask).slice(pos.end, pos.begin)\r\n : getBuffer.call(inputmask).slice(pos.begin, pos.end),\r\n clipDataText = inputmask.isRTL\r\n ? clipData.reverse().join(\"\")\r\n : clipData.join(\"\");\r\n if (window.navigator && window.navigator.clipboard)\r\n window.navigator.clipboard.writeText(clipDataText);\r\n else if (window.clipboardData && window.clipboardData.getData) {\r\n // IE\r\n window.clipboardData.setData(\"Text\", clipDataText);\r\n }\r\n handleRemove.call(inputmask, input, keys.Delete, pos);\r\n writeBuffer(\r\n input,\r\n getBuffer.call(inputmask),\r\n maskset.p,\r\n e,\r\n inputmask.undoValue !== inputmask._valueGet(true)\r\n );\r\n },\r\n blurEvent: function (e) {\r\n const inputmask = this.inputmask,\r\n opts = inputmask.opts,\r\n $ = inputmask.dependencyLib;\r\n inputmask.clicked = 0;\r\n\r\n const $input = $(this),\r\n input = this;\r\n if (input.inputmask) {\r\n HandleNativePlaceholder(input, inputmask.originalPlaceholder);\r\n let nptValue = input.inputmask._valueGet(),\r\n buffer = getBuffer.call(inputmask).slice();\r\n\r\n if (nptValue !== \"\") {\r\n if (opts.clearMaskOnLostFocus) {\r\n if (\r\n getLastValidPosition.call(inputmask) === -1 &&\r\n nptValue === getBufferTemplate.call(inputmask).join(\"\")\r\n ) {\r\n buffer = [];\r\n } else {\r\n // clearout optional tail of the mask\r\n clearOptionalTail.call(inputmask, buffer);\r\n }\r\n }\r\n if (isComplete.call(inputmask, buffer) === false) {\r\n setTimeout(function () {\r\n $input.trigger(\"incomplete\");\r\n }, 0);\r\n if (opts.clearIncomplete) {\r\n resetMaskSet.call(inputmask, false);\r\n if (opts.clearMaskOnLostFocus) {\r\n buffer = [];\r\n } else {\r\n buffer = getBufferTemplate.call(inputmask).slice();\r\n }\r\n }\r\n }\r\n\r\n writeBuffer(input, buffer, undefined, e);\r\n }\r\n\r\n nptValue = inputmask._valueGet(true);\r\n if (inputmask.undoValue !== nptValue) {\r\n const bufferTemplateStr = (\r\n inputmask.isRTL\r\n ? getBufferTemplate.call(inputmask).slice().reverse()\r\n : getBufferTemplate.call(inputmask)\r\n ).join(\"\");\r\n\r\n if (\r\n nptValue !== \"\" ||\r\n inputmask.undoValue !== bufferTemplateStr ||\r\n (inputmask.undoValue === bufferTemplateStr &&\r\n inputmask.maskset.validPositions.length > 0)\r\n ) {\r\n inputmask.undoValue = nptValue;\r\n $input.trigger(\"change\");\r\n }\r\n }\r\n }\r\n },\r\n mouseenterEvent: function () {\r\n const inputmask = this.inputmask,\r\n { showMaskOnHover } = inputmask.opts,\r\n input = this;\r\n inputmask.mouseEnter = true;\r\n if (input.getRootNode().activeElement !== input) {\r\n const bufferTemplate = (\r\n inputmask.isRTL\r\n ? getBufferTemplate.call(inputmask).slice().reverse()\r\n : getBufferTemplate.call(inputmask)\r\n ).join(\"\");\r\n if (showMaskOnHover) {\r\n HandleNativePlaceholder(input, bufferTemplate);\r\n }\r\n }\r\n },\r\n submitEvent: function () {\r\n // trigger change on submit if any\r\n const inputmask = this.inputmask,\r\n opts = inputmask.opts;\r\n\r\n if (inputmask.undoValue !== inputmask._valueGet(true)) {\r\n inputmask.$el.trigger(\"change\");\r\n }\r\n if (\r\n /* opts.clearMaskOnLostFocus && */ getLastValidPosition.call(\r\n inputmask\r\n ) === -1 &&\r\n inputmask._valueGet &&\r\n inputmask._valueGet() === getBufferTemplate.call(inputmask).join(\"\")\r\n ) {\r\n inputmask._valueSet(\"\"); // clear masktemplete on submit and still has focus\r\n }\r\n if (\r\n opts.clearIncomplete &&\r\n isComplete.call(inputmask, getBuffer.call(inputmask)) === false\r\n ) {\r\n inputmask._valueSet(\"\");\r\n }\r\n if (opts.removeMaskOnSubmit) {\r\n inputmask._valueSet(inputmask.unmaskedvalue(), true);\r\n setTimeout(function () {\r\n writeBuffer(inputmask.el, getBuffer.call(inputmask));\r\n }, 0);\r\n }\r\n },\r\n resetEvent: function () {\r\n const inputmask = this.inputmask;\r\n\r\n inputmask.refreshValue = true; // indicate a forced refresh when there is a call to the value before leaving the triggering event fn\r\n setTimeout(function () {\r\n applyInputValue(inputmask.el, inputmask._valueGet(true));\r\n }, 0);\r\n }\r\n};\r\n", "export { keyCode, toKey, toKeyCode, keys };\r\n\r\nconst ignorables = {\r\n Alt: 18,\r\n AltGraph: 18,\r\n ArrowDown: 40,\r\n ArrowLeft: 37,\r\n ArrowRight: 39,\r\n ArrowUp: 38,\r\n Backspace: 8,\r\n CapsLock: 20,\r\n Control: 17,\r\n ContextMenu: 93,\r\n Dead: 221,\r\n Delete: 46,\r\n End: 35,\r\n Escape: 27,\r\n F1: 112,\r\n F2: 113,\r\n F3: 114,\r\n F4: 115,\r\n F5: 116,\r\n F6: 117,\r\n F7: 118,\r\n F8: 119,\r\n F9: 120,\r\n F10: 121,\r\n F11: 122,\r\n F12: 123,\r\n Home: 36,\r\n Insert: 45,\r\n NumLock: 144,\r\n PageDown: 34,\r\n PageUp: 33,\r\n Pause: 19,\r\n PrintScreen: 44,\r\n Process: 229,\r\n Shift: 16,\r\n ScrollLock: 145,\r\n Tab: 9,\r\n Unidentified: 229\r\n },\r\n keyCode = {\r\n c: 67,\r\n x: 88,\r\n z: 90,\r\n BACKSPACE_SAFARI: 127,\r\n Enter: 13,\r\n Meta_LEFT: 91,\r\n Meta_RIGHT: 92,\r\n Space: 32,\r\n ...ignorables\r\n },\r\n keyCodeRev = Object.entries(keyCode).reduce(\r\n (acc, [key, value]) =>\r\n // eslint-disable-next-line no-sequences\r\n ((acc[value] = acc[value] === undefined ? key : acc[value]), acc),\r\n {}\r\n ),\r\n keys = Object.entries(keyCode).reduce(\r\n // eslint-disable-next-line no-sequences\r\n (acc, [key, value]) => ((acc[key] = key === \"Space\" ? \" \" : key), acc),\r\n {}\r\n );\r\n\r\nfunction toKey(keyCode, shiftKey) {\r\n return (\r\n keyCodeRev[keyCode] ||\r\n (shiftKey\r\n ? String.fromCharCode(keyCode)\r\n : String.fromCharCode(keyCode).toLowerCase())\r\n );\r\n}\r\n\r\nfunction toKeyCode(key) {\r\n return keyCode[key];\r\n}\r\n", "import window from \"./global/window\";\r\nimport { checkAlternationMatch } from \"./validation\";\r\nimport {\r\n determineTestTemplate,\r\n getMaskTemplate,\r\n getPlaceholder,\r\n getTest,\r\n getTests,\r\n getTestTemplate\r\n} from \"./validation-tests\";\r\n\r\nexport {\r\n caret,\r\n determineLastRequiredPosition,\r\n determineNewCaretPosition,\r\n getBuffer,\r\n getBufferTemplate,\r\n getLastValidPosition,\r\n isMask,\r\n resetMaskSet,\r\n seekNext,\r\n seekPrevious,\r\n translatePosition\r\n};\r\n\r\n// tobe put on prototype?\r\nfunction caret(input, begin, end, notranslate, isDelete) {\r\n const inputmask = this,\r\n opts = this.opts;\r\n\r\n let range;\r\n if (begin !== undefined) {\r\n if (Array.isArray(begin)) {\r\n end = inputmask.isRTL ? begin[0] : begin[1];\r\n begin = inputmask.isRTL ? begin[1] : begin[0];\r\n }\r\n if (begin.begin !== undefined) {\r\n end = inputmask.isRTL ? begin.begin : begin.end;\r\n begin = inputmask.isRTL ? begin.end : begin.begin;\r\n }\r\n if (typeof begin === \"number\") {\r\n begin = notranslate ? begin : translatePosition.call(inputmask, begin);\r\n end = notranslate ? end : translatePosition.call(inputmask, end);\r\n end = typeof end === \"number\" ? end : begin;\r\n // if (!$(input).is(\":visible\")) {\r\n // \treturn;\r\n // }\r\n\r\n const scrollCalc =\r\n parseInt(\r\n ((input.ownerDocument.defaultView || window).getComputedStyle\r\n ? (input.ownerDocument.defaultView || window).getComputedStyle(\r\n input,\r\n null\r\n )\r\n : input.currentStyle\r\n ).fontSize\r\n ) * end;\r\n input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0;\r\n input.inputmask.caretPos = { begin, end }; // track caret internally\r\n if (opts.insertModeVisual && opts.insertMode === false && begin === end) {\r\n if (!isDelete) {\r\n end++; // set visualization for insert/overwrite mode\r\n }\r\n }\r\n if (input === input.getRootNode().activeElement) {\r\n if (\"setSelectionRange\" in input) {\r\n input.setSelectionRange(begin, end);\r\n } else if (window.getSelection) {\r\n range = document.createRange();\r\n if (input.firstChild === undefined || input.firstChild === null) {\r\n const textNode = document.createTextNode(\"\");\r\n input.appendChild(textNode);\r\n }\r\n range.setStart(\r\n input.firstChild,\r\n begin < input.inputmask._valueGet().length\r\n ? begin\r\n : input.inputmask._valueGet().length\r\n );\r\n range.setEnd(\r\n input.firstChild,\r\n end < input.inputmask._valueGet().length\r\n ? end\r\n : input.inputmask._valueGet().length\r\n );\r\n range.collapse(true);\r\n const sel = window.getSelection();\r\n sel.removeAllRanges();\r\n sel.addRange(range);\r\n // input.focus();\r\n } else if (input.createTextRange) {\r\n range = input.createTextRange();\r\n range.collapse(true);\r\n range.moveEnd(\"character\", end);\r\n range.moveStart(\"character\", begin);\r\n range.select();\r\n }\r\n\r\n input.inputmask.caretHook === undefined ||\r\n input.inputmask.caretHook.call(inputmask, { begin, end });\r\n }\r\n }\r\n } else {\r\n if (\"selectionStart\" in input && \"selectionEnd\" in input) {\r\n begin = input.selectionStart;\r\n end = input.selectionEnd;\r\n } else if (window.getSelection) {\r\n range = window.getSelection().getRangeAt(0);\r\n if (\r\n range.commonAncestorContainer.parentNode === input ||\r\n range.commonAncestorContainer === input\r\n ) {\r\n begin = range.startOffset;\r\n end = range.endOffset;\r\n }\r\n } else if (document.selection && document.selection.createRange) {\r\n range = document.selection.createRange();\r\n begin =\r\n 0 -\r\n range\r\n .duplicate()\r\n .moveStart(\"character\", -input.inputmask._valueGet().length);\r\n end = begin + range.text.length;\r\n }\r\n\r\n // if (opts.insertModeVisual && opts.insertMode === false && begin === (end - 1)) end--; //correct caret for insert/overwrite mode\r\n\r\n return {\r\n begin: notranslate ? begin : translatePosition.call(inputmask, begin),\r\n end: notranslate ? end : translatePosition.call(inputmask, end)\r\n };\r\n }\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction determineLastRequiredPosition(returnDefinition) {\r\n const inputmask = this,\r\n { maskset, dependencyLib: $ } = inputmask,\r\n lvp = getLastValidPosition.call(inputmask),\r\n positions = {},\r\n lvTest = maskset.validPositions[lvp],\r\n buffer = getMaskTemplate.call(\r\n inputmask,\r\n true,\r\n getLastValidPosition.call(inputmask),\r\n true,\r\n true\r\n );\r\n let bl = buffer.length,\r\n pos,\r\n ndxIntlzr = lvTest !== undefined ? lvTest.locator.slice() : undefined,\r\n testPos;\r\n for (pos = lvp + 1; pos < buffer.length; pos++) {\r\n testPos = getTestTemplate.call(inputmask, pos, ndxIntlzr, pos - 1);\r\n ndxIntlzr = testPos.locator.slice();\r\n positions[pos] = $.extend(true, {}, testPos);\r\n }\r\n\r\n const lvTestAlt =\r\n lvTest && lvTest.alternation !== undefined\r\n ? lvTest.locator[lvTest.alternation]\r\n : undefined;\r\n for (pos = bl - 1; pos > lvp; pos--) {\r\n testPos = positions[pos];\r\n if (\r\n (testPos.match.optionality ||\r\n (testPos.match.optionalQuantifier && testPos.match.newBlockMarker) ||\r\n (lvTestAlt &&\r\n ((lvTestAlt !== positions[pos].locator[lvTest.alternation] &&\r\n testPos.match.static !== true) ||\r\n (testPos.match.static === true &&\r\n testPos.locator[lvTest.alternation] &&\r\n checkAlternationMatch.call(\r\n inputmask,\r\n testPos.locator[lvTest.alternation].toString().split(\",\"),\r\n lvTestAlt.toString().split(\",\")\r\n ) &&\r\n getTests.call(inputmask, pos)[0].def !== \"\")))) &&\r\n buffer[pos] === getPlaceholder.call(inputmask, pos, testPos.match)\r\n ) {\r\n bl--;\r\n if (testPos.match.optionality) {\r\n // find the last position that is not optional ~ isoptional and newblockmarker == \"master\"\r\n let prevPos = pos;\r\n while (prevPos > 0) {\r\n const test = getTest.call(inputmask, prevPos);\r\n if (\r\n test.match.newBlockMarker === \"master\" ||\r\n test.match.newBlockMarker === true\r\n ) {\r\n break;\r\n }\r\n prevPos--;\r\n }\r\n if (maskset.validPositions[prevPos] !== undefined) {\r\n break;\r\n }\r\n }\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n // no extra required positions\r\n if (pos === lvp) {\r\n bl = pos;\r\n }\r\n\r\n return returnDefinition\r\n ? {\r\n l: bl,\r\n def: positions[bl] ? positions[bl].match : undefined\r\n }\r\n : bl;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction determineNewCaretPosition(\r\n selectedCaret,\r\n tabbed,\r\n positionCaretOnClick\r\n) {\r\n const inputmask = this,\r\n { maskset, opts } = inputmask;\r\n let clickPosition, lvclickPosition, lastPosition;\r\n\r\n function doRadixFocus(clickPos) {\r\n if (opts.radixPoint !== \"\" && opts.digits !== 0) {\r\n const vps = maskset.validPositions;\r\n if (vps[clickPos] === undefined || vps[clickPos].input === undefined) {\r\n if (clickPos < seekNext.call(inputmask, -1)) return true;\r\n const radixPos = getBuffer.call(inputmask).indexOf(opts.radixPoint);\r\n if (radixPos !== -1) {\r\n for (const vp in vps) {\r\n const pos = Number(vp);\r\n if (\r\n radixPos < pos &&\r\n vps[vp].input !== getPlaceholder.call(inputmask, pos)\r\n ) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n if (tabbed) {\r\n if (inputmask.isRTL) {\r\n selectedCaret.end = selectedCaret.begin;\r\n } else {\r\n selectedCaret.begin = selectedCaret.end;\r\n }\r\n }\r\n if (selectedCaret.begin === selectedCaret.end) {\r\n positionCaretOnClick = positionCaretOnClick || opts.positionCaretOnClick;\r\n switch (positionCaretOnClick) {\r\n case \"none\":\r\n break;\r\n case \"select\":\r\n selectedCaret = { begin: 0, end: getBuffer.call(inputmask).length };\r\n break;\r\n case \"ignore\":\r\n selectedCaret.end = selectedCaret.begin = seekNext.call(\r\n inputmask,\r\n getLastValidPosition.call(inputmask)\r\n );\r\n break;\r\n case \"radixFocus\":\r\n if (inputmask.clicked > 1 && maskset.validPositions.length === 0) break;\r\n if (doRadixFocus(selectedCaret.begin)) {\r\n const radixPos = getBuffer\r\n .call(inputmask)\r\n .join(\"\")\r\n .indexOf(opts.radixPoint);\r\n selectedCaret.end = selectedCaret.begin = opts.numericInput\r\n ? seekNext.call(inputmask, radixPos)\r\n : radixPos;\r\n break;\r\n } // fallback to lvp\r\n // eslint-disable-next-line no-fallthrough\r\n default: // lvp:\r\n clickPosition = selectedCaret.begin;\r\n lvclickPosition = getLastValidPosition.call(\r\n inputmask,\r\n clickPosition,\r\n true\r\n );\r\n lastPosition = seekNext.call(\r\n inputmask,\r\n lvclickPosition === -1 && !isMask.call(inputmask, 0)\r\n ? -1\r\n : lvclickPosition\r\n );\r\n\r\n if (clickPosition <= lastPosition) {\r\n selectedCaret.end = selectedCaret.begin = !isMask.call(\r\n inputmask,\r\n clickPosition,\r\n false,\r\n true\r\n )\r\n ? seekNext.call(inputmask, clickPosition)\r\n : clickPosition;\r\n } else {\r\n const lvp = maskset.validPositions[lvclickPosition],\r\n tt = getTestTemplate.call(\r\n inputmask,\r\n lastPosition,\r\n lvp ? lvp.match.locator : undefined,\r\n lvp\r\n ),\r\n placeholder = getPlaceholder.call(\r\n inputmask,\r\n lastPosition,\r\n tt.match\r\n );\r\n if (\r\n (placeholder !== \"\" &&\r\n getBuffer.call(inputmask)[lastPosition] !== placeholder &&\r\n tt.match.optionalQuantifier !== true &&\r\n tt.match.newBlockMarker !== true) ||\r\n (!isMask.call(inputmask, lastPosition, opts.keepStatic, true) &&\r\n tt.match.def === placeholder)\r\n ) {\r\n const newPos = seekNext.call(inputmask, lastPosition);\r\n if (clickPosition >= newPos || clickPosition === lastPosition) {\r\n lastPosition = newPos;\r\n }\r\n }\r\n selectedCaret.end = selectedCaret.begin = lastPosition;\r\n }\r\n }\r\n\r\n return selectedCaret;\r\n }\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction getBuffer(noCache) {\r\n const inputmask = this,\r\n { maskset } = inputmask;\r\n\r\n if (maskset.buffer === undefined || noCache === true) {\r\n maskset.buffer = getMaskTemplate.call(\r\n inputmask,\r\n true,\r\n getLastValidPosition.call(inputmask),\r\n true\r\n );\r\n if (maskset._buffer === undefined) maskset._buffer = maskset.buffer.slice();\r\n }\r\n return maskset.buffer;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction getBufferTemplate() {\r\n const inputmask = this,\r\n maskset = this.maskset;\r\n\r\n if (maskset._buffer === undefined) {\r\n // generate template\r\n maskset._buffer = getMaskTemplate.call(inputmask, false, 1);\r\n if (maskset.buffer === undefined) maskset.buffer = maskset._buffer.slice();\r\n }\r\n return maskset._buffer;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction getLastValidPosition(closestTo, strict, validPositions) {\r\n const maskset = this.maskset;\r\n\r\n let before = -1,\r\n after = -1;\r\n const valids = validPositions || maskset.validPositions; // for use in valhook ~ context switch\r\n if (closestTo === undefined) closestTo = -1;\r\n for (let psNdx = 0, vpl = valids.length; psNdx < vpl; psNdx++) {\r\n if (valids[psNdx] && (strict || valids[psNdx].generatedInput !== true)) {\r\n if (psNdx <= closestTo) before = psNdx;\r\n if (psNdx >= closestTo) after = psNdx;\r\n }\r\n }\r\n return before === -1 || before === closestTo\r\n ? after\r\n : after === -1\r\n ? before\r\n : closestTo - before < after - closestTo\r\n ? before\r\n : after;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction isMask(pos, strict, fuzzy) {\r\n const inputmask = this,\r\n maskset = this.maskset;\r\n\r\n let test = getTestTemplate.call(inputmask, pos).match;\r\n if (test.def === \"\") test = getTest.call(inputmask, pos).match;\r\n\r\n if (test.static !== true) {\r\n return test.fn;\r\n }\r\n if (\r\n fuzzy === true &&\r\n maskset.validPositions[pos] !== undefined &&\r\n maskset.validPositions[pos].generatedInput !== true\r\n ) {\r\n return true;\r\n }\r\n\r\n if (strict !== true && pos > -1) {\r\n if (fuzzy) {\r\n // check on the number of tests\r\n const tests = getTests.call(inputmask, pos);\r\n return (\r\n tests.length > 1 + (tests[tests.length - 1].match.def === \"\" ? 1 : 0)\r\n );\r\n }\r\n // else based on the template\r\n const testTemplate = determineTestTemplate.call(\r\n inputmask,\r\n pos,\r\n getTests.call(inputmask, pos)\r\n ),\r\n testPlaceHolder = getPlaceholder.call(inputmask, pos, testTemplate.match);\r\n return testTemplate.match.def !== testPlaceHolder;\r\n }\r\n return false;\r\n}\r\n\r\n// tobe put on prototype?\r\n// soft ~ undefined reset validpositions; soft = false also reset tests; soft = true only reset the maskset\r\nfunction resetMaskSet(soft) {\r\n const maskset = this.maskset;\r\n\r\n maskset.buffer = undefined;\r\n if (soft !== true) {\r\n maskset.validPositions = [];\r\n maskset.p = 0;\r\n }\r\n if (soft === false) {\r\n maskset.tests = {};\r\n maskset.jitOffset = {};\r\n }\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction seekNext(pos, newBlock, fuzzy) {\r\n const inputmask = this;\r\n\r\n if (fuzzy === undefined) fuzzy = true;\r\n let position = pos + 1;\r\n while (\r\n getTest.call(inputmask, position).match.def !== \"\" &&\r\n ((newBlock === true &&\r\n (getTest.call(inputmask, position).match.newBlockMarker !== true ||\r\n !isMask.call(inputmask, position, undefined, true))) ||\r\n (newBlock !== true &&\r\n !isMask.call(inputmask, position, undefined, fuzzy)))\r\n ) {\r\n position++;\r\n }\r\n return position;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction seekPrevious(pos, newBlock) {\r\n const inputmask = this;\r\n\r\n let position = pos - 1;\r\n if (pos <= 0) return 0;\r\n\r\n while (\r\n position > 0 &&\r\n ((newBlock === true &&\r\n (getTest.call(inputmask, position).match.newBlockMarker !== true ||\r\n !isMask.call(inputmask, position, undefined, true))) ||\r\n (newBlock !== true && !isMask.call(inputmask, position, undefined, true)))\r\n ) {\r\n position--;\r\n }\r\n return position;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction translatePosition(pos) {\r\n const inputmask = this,\r\n opts = this.opts,\r\n el = this.el;\r\n\r\n if (\r\n inputmask.isRTL &&\r\n typeof pos === \"number\" &&\r\n (!opts.greedy || opts.placeholder !== \"\") &&\r\n el\r\n ) {\r\n pos = inputmask._valueGet().length - pos;\r\n if (pos < 0) pos = 0;\r\n }\r\n return pos;\r\n}\r\n", "import { EventHandlers } from \"./eventhandlers\";\r\nimport { keyCode, keys } from \"./keycode.js\";\r\nimport {\r\n determineLastRequiredPosition,\r\n determineNewCaretPosition,\r\n getBuffer,\r\n getLastValidPosition,\r\n isMask,\r\n resetMaskSet,\r\n seekNext,\r\n seekPrevious\r\n} from \"./positioning\";\r\nimport {\r\n determineTestTemplate,\r\n getDecisionTaker,\r\n getPlaceholder,\r\n getTest,\r\n getTests,\r\n getTestTemplate,\r\n getMaskTemplate\r\n} from \"./validation-tests\";\r\n\r\nexport {\r\n alternate,\r\n checkAlternationMatch,\r\n isComplete,\r\n isSelection,\r\n isValid,\r\n refreshFromBuffer,\r\n revalidateMask,\r\n handleRemove,\r\n casing\r\n};\r\n\r\n// tobe put on prototype?\r\nfunction alternate(maskPos, c, strict, fromIsValid, rAltPos, selection) {\r\n // pos == true => generalize\r\n const inputmask = this,\r\n $ = this.dependencyLib,\r\n opts = this.opts,\r\n maskset = inputmask.maskset;\r\n\r\n if (!inputmask.hasAlternator) return false;\r\n\r\n const validPsClone = $.extend(true, [], maskset.validPositions),\r\n tstClone = $.extend(true, {}, maskset.tests);\r\n let lastAlt,\r\n alternation,\r\n isValidRslt = false,\r\n returnRslt = false,\r\n altPos,\r\n prevAltPos,\r\n i,\r\n validPos,\r\n decisionPos,\r\n lAltPos =\r\n rAltPos !== undefined ? rAltPos : getLastValidPosition.call(inputmask),\r\n nextPos,\r\n input,\r\n begin,\r\n end;\r\n\r\n if (selection) {\r\n begin = selection.begin;\r\n end = selection.end;\r\n if (selection.begin > selection.end) {\r\n begin = selection.end;\r\n end = selection.begin;\r\n }\r\n }\r\n\r\n if (lAltPos === -1 && rAltPos === undefined) {\r\n // do not recurse when already passed the beginning\r\n lastAlt = 0;\r\n prevAltPos = getTest.call(inputmask, lastAlt);\r\n alternation = prevAltPos.alternation;\r\n } else {\r\n // find last modified alternation\r\n for (; lAltPos >= 0; lAltPos--) {\r\n altPos =\r\n lAltPos === 0\r\n ? getTest.call(inputmask, 0)\r\n : maskset.validPositions[lAltPos];\r\n if (altPos && altPos.alternation !== undefined) {\r\n if (\r\n lAltPos <= (maskPos || 0) &&\r\n prevAltPos &&\r\n prevAltPos.locator[altPos.alternation] !==\r\n altPos.locator[altPos.alternation]\r\n ) {\r\n break;\r\n }\r\n lastAlt = lAltPos;\r\n alternation = altPos.alternation;\r\n prevAltPos = altPos;\r\n }\r\n }\r\n }\r\n\r\n if (alternation !== undefined) {\r\n decisionPos = parseInt(lastAlt);\r\n maskset.excludes[decisionPos] = maskset.excludes[decisionPos] || [];\r\n // generalize\r\n if (maskPos !== true) {\r\n maskset.excludes[decisionPos].push(\r\n getDecisionTaker(prevAltPos) + \":\" + prevAltPos.alternation\r\n );\r\n }\r\n\r\n const validInputs = [];\r\n let resultPos = -1;\r\n for (\r\n i = decisionPos;\r\n decisionPos < getLastValidPosition.call(inputmask, undefined, true) + 1;\r\n i++\r\n ) {\r\n if (resultPos === -1 && maskPos <= i && c !== undefined) {\r\n validInputs.push(c);\r\n resultPos = validInputs.length - 1;\r\n }\r\n validPos = maskset.validPositions[decisionPos];\r\n if (\r\n validPos &&\r\n validPos.generatedInput !== true &&\r\n (decisionPos !== 0 ||\r\n validPos.input !== opts.skipOptionalPartCharacter) &&\r\n (selection === undefined || i < begin || i >= end)\r\n ) {\r\n validInputs.push(validPos.input);\r\n }\r\n // delete maskset.validPositions[i++];\r\n maskset.validPositions.splice(decisionPos, 1);\r\n }\r\n if (resultPos === -1 && c !== undefined) {\r\n validInputs.push(c);\r\n resultPos = validInputs.length - 1;\r\n }\r\n\r\n while (\r\n maskset.excludes[decisionPos] !== undefined &&\r\n maskset.excludes[decisionPos].length < 10\r\n ) {\r\n // maskset.tests[decisionPos] = undefined; //clear decisionPos\r\n maskset.tests = {}; // clear all\r\n resetMaskSet.call(inputmask, true); // clear getbuffer\r\n isValidRslt = true;\r\n nextPos = decisionPos - 1;\r\n const targetTemplate = getMaskTemplate.call(inputmask, true, 0);\r\n\r\n for (i = 0; i < validInputs.length; i++) {\r\n input = validInputs[i];\r\n if (\r\n targetTemplate[nextPos + 1] === input &&\r\n opts.numericInput !== true\r\n ) {\r\n nextPos++;\r\n } else if (\r\n i === 0 ||\r\n returnRslt.caretPos !== undefined ||\r\n opts.insertMode === false\r\n ) {\r\n nextPos = seekNext.call(inputmask, nextPos);\r\n } else {\r\n nextPos = getLastValidPosition.call(inputmask, nextPos, true) + 1;\r\n }\r\n\r\n // nextPos = translatePosition.call(inputmask, nextPos);\r\n if (\r\n !(isValidRslt = isValid.call(\r\n inputmask,\r\n nextPos,\r\n input,\r\n false,\r\n fromIsValid,\r\n true\r\n ))\r\n ) {\r\n // if (isComplete.call(inputmask, getBuffer.call(inputmask))) {\r\n // isValidRslt = returnRslt; // keep previous result if any\r\n // }\r\n break;\r\n }\r\n if (i === resultPos) {\r\n returnRslt = isValidRslt;\r\n }\r\n if (maskPos === true && isValidRslt) {\r\n // return validposition on generalise\r\n returnRslt = { caretPos: i };\r\n }\r\n }\r\n\r\n if (!isValidRslt) {\r\n resetMaskSet.call(inputmask);\r\n prevAltPos = getTest.call(inputmask, decisionPos); // get the current decisionPos to exclude ~ needs to be before restoring the initial validation\r\n // reset & revert\r\n maskset.validPositions = $.extend(true, [], validPsClone);\r\n maskset.tests = $.extend(true, {}, tstClone); // refresh tests after possible alternating\r\n returnRslt = false;\r\n if (maskset.excludes[decisionPos]) {\r\n if (prevAltPos.alternation != undefined) {\r\n const decisionTaker = getDecisionTaker(prevAltPos);\r\n if (\r\n maskset.excludes[decisionPos].indexOf(\r\n decisionTaker + \":\" + prevAltPos.alternation\r\n ) !== -1\r\n ) {\r\n returnRslt = alternate.call(\r\n inputmask,\r\n maskPos,\r\n c,\r\n strict,\r\n fromIsValid,\r\n decisionPos - 1,\r\n selection\r\n );\r\n break;\r\n }\r\n maskset.excludes[decisionPos].push(\r\n decisionTaker + \":\" + prevAltPos.alternation\r\n );\r\n for (\r\n i = decisionPos;\r\n i < getLastValidPosition.call(inputmask, undefined, true) + 1;\r\n i++\r\n )\r\n maskset.validPositions.splice(decisionPos);\r\n } else delete maskset.excludes[decisionPos];\r\n } else {\r\n // latest alternation\r\n returnRslt = alternate.call(\r\n inputmask,\r\n maskPos,\r\n c,\r\n strict,\r\n fromIsValid,\r\n decisionPos - 1,\r\n selection\r\n );\r\n break;\r\n }\r\n } else {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // reset alternation excludes\r\n if (!returnRslt || opts.keepStatic !== false) {\r\n delete maskset.excludes[decisionPos];\r\n }\r\n if (!returnRslt) {\r\n maskset.validPositions = $.extend(true, [], validPsClone);\r\n maskset.tests = $.extend(true, {}, tstClone); // refresh tests after possible alternating\r\n }\r\n return returnRslt;\r\n}\r\n\r\nfunction casing(elem, test, pos) {\r\n const opts = this.opts,\r\n maskset = this.maskset;\r\n\r\n switch (opts.casing || test.casing) {\r\n case \"upper\":\r\n elem = elem.toLocaleUpperCase();\r\n break;\r\n case \"lower\":\r\n elem = elem.toLocaleLowerCase();\r\n break;\r\n case \"title\":\r\n var posBefore = maskset.validPositions[pos - 1];\r\n if (\r\n pos === 0 ||\r\n (posBefore && posBefore.input === String.fromCharCode(keyCode.Space))\r\n ) {\r\n elem = elem.toLocaleUpperCase();\r\n } else {\r\n elem = elem.toLocaleLowerCase();\r\n }\r\n break;\r\n case \"follow\":\r\n if (test.def && test.def !== test.def.toLocaleLowerCase()) {\r\n elem = elem.toLocaleUpperCase();\r\n } else if (test.def && test.def !== test.def.toLocaleUpperCase()) {\r\n elem = elem.toLocaleLowerCase();\r\n }\r\n break;\r\n default:\r\n if (typeof opts.casing === \"function\") {\r\n const args = Array.prototype.slice.call(arguments);\r\n args.push(maskset.validPositions);\r\n elem = opts.casing.apply(this, args);\r\n }\r\n }\r\n\r\n return elem;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction checkAlternationMatch(altArr1, altArr2, na) {\r\n const opts = this.opts;\r\n\r\n let altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1),\r\n isMatch = false,\r\n naArr = na !== undefined ? na.split(\",\") : [],\r\n naNdx;\r\n\r\n // remove no alternate indexes from alternation array\r\n for (let i = 0; i < naArr.length; i++) {\r\n if ((naNdx = altArr1.indexOf(naArr[i])) !== -1) {\r\n altArr1.splice(naNdx, 1);\r\n }\r\n }\r\n\r\n for (let alndx = 0; alndx < altArr1.length; alndx++) {\r\n if (altArrC.includes(altArr1[alndx])) {\r\n isMatch = true;\r\n break;\r\n }\r\n }\r\n return isMatch;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction handleRemove(input, c, pos, strict, fromIsValid) {\r\n const inputmask = this,\r\n maskset = this.maskset,\r\n opts = this.opts;\r\n\r\n if (opts.numericInput || inputmask.isRTL) {\r\n if (c === keys.Backspace) {\r\n c = keys.Delete;\r\n } else if (c === keys.Delete) {\r\n c = keys.Backspace;\r\n }\r\n\r\n if (inputmask.isRTL) {\r\n const pend = pos.end;\r\n pos.end = pos.begin;\r\n pos.begin = pend;\r\n }\r\n }\r\n\r\n const lvp = getLastValidPosition.call(inputmask, undefined, true);\r\n if (pos.end >= getBuffer.call(inputmask).length && lvp >= pos.end) {\r\n // handle numeric negate symbol offset, due to dynamic jit masking\r\n pos.end = lvp + 1;\r\n }\r\n\r\n if (c === keys.Backspace) {\r\n if (pos.end - pos.begin < 1) {\r\n pos.begin = seekPrevious.call(inputmask, pos.begin);\r\n }\r\n } else if (c === keys.Delete) {\r\n if (pos.begin === pos.end) {\r\n pos.end = isMask.call(inputmask, pos.end, true, true)\r\n ? pos.end + 1\r\n : seekNext.call(inputmask, pos.end) + 1;\r\n }\r\n }\r\n let offset;\r\n if ((offset = revalidateMask.call(inputmask, pos)) !== false) {\r\n if (\r\n (strict !== true && opts.keepStatic !== false) ||\r\n (opts.regex !== null &&\r\n getTest.call(inputmask, pos.begin).match.def.indexOf(\"|\") !== -1)\r\n ) {\r\n // TODO NEEDS BETTER CHECK WHEN TO ALTERNATE ~ opts regex isn\"t good enough\r\n alternate.call(inputmask, true);\r\n }\r\n\r\n if (strict !== true) {\r\n maskset.p = c === keys.Delete ? pos.begin + offset : pos.begin;\r\n maskset.p = determineNewCaretPosition.call(\r\n inputmask,\r\n {\r\n begin: maskset.p,\r\n end: maskset.p\r\n },\r\n false,\r\n opts.insertMode === false && c === keys.Backspace ? \"none\" : undefined\r\n ).begin;\r\n }\r\n }\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction isComplete(buffer) {\r\n // return true / false / undefined (repeat *)\r\n const inputmask = this,\r\n opts = this.opts,\r\n maskset = this.maskset;\r\n\r\n if (typeof opts.isComplete === \"function\")\r\n return opts.isComplete(buffer, opts);\r\n if (opts.repeat === \"*\") return undefined;\r\n let complete = false,\r\n lrp = determineLastRequiredPosition.call(inputmask, true),\r\n aml = lrp.l; // seekPrevious.call(inputmask, lrp.l);\r\n\r\n if (\r\n lrp.def === undefined ||\r\n lrp.def.newBlockMarker ||\r\n lrp.def.optionality ||\r\n lrp.def.optionalQuantifier\r\n ) {\r\n complete = true;\r\n for (let i = 0; i <= aml; i++) {\r\n const test = getTestTemplate.call(inputmask, i).match;\r\n if (\r\n (test.static !== true &&\r\n maskset.validPositions[i] === undefined &&\r\n (test.optionality === false ||\r\n test.optionality === undefined ||\r\n (test.optionality && test.newBlockMarker == false)) &&\r\n (test.optionalQuantifier === false ||\r\n test.optionalQuantifier === undefined)) ||\r\n (test.static === true &&\r\n test.def != \"\" &&\r\n buffer[i] !== getPlaceholder.call(inputmask, i, test))\r\n ) {\r\n complete = false;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return complete;\r\n}\r\n\r\nfunction isSelection(posObj) {\r\n const inputmask = this,\r\n opts = this.opts,\r\n insertModeOffset = opts.insertMode ? 0 : 1;\r\n return inputmask.isRTL\r\n ? posObj.begin - posObj.end > insertModeOffset\r\n : posObj.end - posObj.begin > insertModeOffset;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction isValid(\r\n pos,\r\n c,\r\n strict,\r\n fromIsValid,\r\n fromAlternate,\r\n validateOnly,\r\n fromCheckval\r\n) {\r\n // strict true ~ no correction or autofill\r\n const inputmask = this,\r\n $ = this.dependencyLib,\r\n opts = this.opts,\r\n maskset = inputmask.maskset;\r\n\r\n strict = strict === true; // always set a value to strict to prevent possible strange behavior in the extensions\r\n\r\n let maskPos = pos;\r\n if (pos.begin !== undefined) {\r\n // position was a position object - used to handle a delete by typing over a selection\r\n maskPos = inputmask.isRTL ? pos.end : pos.begin;\r\n }\r\n\r\n function processCommandObject(commandObj) {\r\n if (commandObj !== undefined) {\r\n if (commandObj.remove !== undefined) {\r\n // remove position(s)\r\n if (!Array.isArray(commandObj.remove))\r\n commandObj.remove = [commandObj.remove];\r\n commandObj.remove\r\n .sort(function (a, b) {\r\n return inputmask.isRTL ? a.pos - b.pos : b.pos - a.pos;\r\n })\r\n .forEach(function (lmnt) {\r\n revalidateMask.call(inputmask, { begin: lmnt, end: lmnt + 1 });\r\n });\r\n commandObj.remove = undefined;\r\n }\r\n if (commandObj.insert !== undefined) {\r\n // insert position(s)\r\n if (!Array.isArray(commandObj.insert))\r\n commandObj.insert = [commandObj.insert];\r\n commandObj.insert\r\n .sort(function (a, b) {\r\n return inputmask.isRTL ? b.pos - a.pos : a.pos - b.pos;\r\n })\r\n .forEach(function (lmnt) {\r\n if (lmnt.c !== \"\") {\r\n isValid.call(\r\n inputmask,\r\n lmnt.pos,\r\n lmnt.c,\r\n lmnt.strict !== undefined ? lmnt.strict : true,\r\n lmnt.fromIsValid !== undefined ? lmnt.fromIsValid : fromIsValid\r\n );\r\n }\r\n });\r\n commandObj.insert = undefined;\r\n }\r\n\r\n if (commandObj.refreshFromBuffer && commandObj.buffer) {\r\n const refresh = commandObj.refreshFromBuffer;\r\n refreshFromBuffer.call(\r\n inputmask,\r\n refresh === true ? refresh : refresh.start,\r\n refresh.end,\r\n commandObj.buffer\r\n );\r\n commandObj.refreshFromBuffer = undefined;\r\n }\r\n\r\n if (commandObj.rewritePosition !== undefined) {\r\n maskPos = commandObj.rewritePosition;\r\n // commandObj.rewritePosition = undefined;\r\n commandObj = true; // see prevalidation in isValid\r\n }\r\n }\r\n return commandObj;\r\n }\r\n\r\n function _isValid(position, c, strict) {\r\n let rslt = false;\r\n getTests.call(inputmask, position).every(function (tst, ndx) {\r\n const test = tst.match;\r\n // make sure the buffer is set and correct\r\n getBuffer.call(inputmask, true);\r\n if (\r\n test.jit &&\r\n maskset.validPositions[seekPrevious.call(inputmask, position)] ===\r\n undefined\r\n ) {\r\n // ignore if jit is not desirable\r\n rslt = false;\r\n } else {\r\n // return is false or a json object => { pos: ??, c: ??} or true\r\n rslt =\r\n test.fn != null\r\n ? test.fn.test(\r\n c,\r\n maskset,\r\n position,\r\n strict,\r\n opts,\r\n isSelection.call(inputmask, pos)\r\n )\r\n : (c === test.def || c === opts.skipOptionalPartCharacter) &&\r\n test.def !== \"\" // non mask\r\n ? {\r\n c:\r\n getPlaceholder.call(inputmask, position, test, true) ||\r\n test.def,\r\n pos: position\r\n }\r\n : false;\r\n }\r\n if (rslt !== false) {\r\n let elem = rslt.c !== undefined ? rslt.c : c,\r\n validatedPos = position;\r\n elem =\r\n elem === opts.skipOptionalPartCharacter && test.static === true\r\n ? getPlaceholder.call(inputmask, position, test, true) || test.def\r\n : elem;\r\n\r\n rslt = processCommandObject(rslt);\r\n\r\n if (rslt !== true && rslt.pos !== undefined && rslt.pos !== position) {\r\n // their is a position offset\r\n validatedPos = rslt.pos;\r\n }\r\n\r\n if (rslt !== true && rslt.pos === undefined && rslt.c === undefined) {\r\n return false; // breakout if nothing to insert\r\n }\r\n\r\n if (\r\n revalidateMask.call(\r\n inputmask,\r\n pos,\r\n $.extend({}, tst, {\r\n input: casing.call(inputmask, elem, test, validatedPos)\r\n }),\r\n fromIsValid,\r\n validatedPos\r\n ) === false\r\n ) {\r\n rslt = false;\r\n }\r\n return false; // break from loop\r\n }\r\n\r\n return true;\r\n });\r\n return rslt;\r\n }\r\n\r\n let result = true,\r\n positionsClone = $.extend(true, [], maskset.validPositions); // clone the currentPositions\r\n\r\n if (\r\n opts.keepStatic === false &&\r\n maskset.excludes[maskPos] !== undefined &&\r\n fromAlternate !== true &&\r\n fromIsValid !== true\r\n ) {\r\n for (let i = maskPos; i < (inputmask.isRTL ? pos.begin : pos.end); i++) {\r\n if (maskset.excludes[i] !== undefined) {\r\n maskset.excludes[i] = undefined;\r\n delete maskset.tests[i];\r\n }\r\n }\r\n }\r\n\r\n if (\r\n typeof opts.preValidation === \"function\" &&\r\n fromIsValid !== true &&\r\n validateOnly !== true\r\n ) {\r\n result = opts.preValidation.call(\r\n inputmask,\r\n getBuffer.call(inputmask),\r\n maskPos,\r\n c,\r\n isSelection.call(inputmask, pos),\r\n opts,\r\n maskset,\r\n pos,\r\n strict || fromAlternate\r\n );\r\n result = processCommandObject(result);\r\n }\r\n if (result === true) {\r\n // preValidation result\r\n result = _isValid(maskPos, c, strict);\r\n if (\r\n (!strict || fromIsValid === true) &&\r\n result === false &&\r\n validateOnly !== true\r\n ) {\r\n const currentPosValid = maskset.validPositions[maskPos];\r\n if (\r\n currentPosValid &&\r\n currentPosValid.match.static === true &&\r\n (currentPosValid.match.def === c ||\r\n c === opts.skipOptionalPartCharacter)\r\n ) {\r\n result = {\r\n caret: seekNext.call(inputmask, maskPos)\r\n };\r\n } else {\r\n if (\r\n opts.insertMode ||\r\n maskset.validPositions[seekNext.call(inputmask, maskPos)] ===\r\n undefined ||\r\n pos.end > maskPos\r\n ) {\r\n // does the input match on a further position?\r\n let skip = false;\r\n if (\r\n maskset.jitOffset[maskPos] &&\r\n maskset.validPositions[seekNext.call(inputmask, maskPos)] ===\r\n undefined\r\n ) {\r\n result = isValid.call(\r\n inputmask,\r\n maskPos + maskset.jitOffset[maskPos],\r\n c,\r\n true,\r\n true\r\n );\r\n if (result !== false) {\r\n if (fromAlternate !== true) result.caret = maskPos;\r\n skip = true;\r\n }\r\n }\r\n if (pos.end > maskPos) {\r\n maskset.validPositions[maskPos] = undefined;\r\n }\r\n if (\r\n !skip &&\r\n !isMask.call(inputmask, maskPos, opts.keepStatic && maskPos === 0)\r\n ) {\r\n for (\r\n let nPos = maskPos + 1,\r\n snPos = seekNext.call(inputmask, maskPos, false, maskPos !== 0);\r\n nPos <= snPos;\r\n nPos++\r\n ) {\r\n // if (!isMask(nPos, true)) {\r\n // \tcontinue;\r\n // }\r\n result = _isValid(nPos, c, strict);\r\n if (result !== false) {\r\n result =\r\n trackbackPositions.call(\r\n inputmask,\r\n maskPos,\r\n result.pos !== undefined ? result.pos : nPos\r\n ) || result;\r\n maskPos = nPos;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (inputmask.hasAlternator && fromAlternate !== true && !strict) {\r\n fromAlternate = true; // stop possible loop\r\n if (result === false) {\r\n // try alternating when the validation fails\r\n if (\r\n opts.keepStatic === true ||\r\n (isFinite(parseInt(opts.keepStatic)) && maskPos >= opts.keepStatic)\r\n ) {\r\n // console.log(\"alternate 0\");\r\n result = alternate.call(\r\n inputmask,\r\n maskPos,\r\n c,\r\n strict,\r\n fromIsValid,\r\n undefined,\r\n pos\r\n );\r\n }\r\n } else if (result === true) {\r\n // try alternating when the validation succeeds\r\n // selection clears an alternated keepstatic mask ~ #2189\r\n if (\r\n isSelection.call(inputmask, pos) &&\r\n maskset.tests[maskPos] &&\r\n maskset.tests[maskPos].length > 1 &&\r\n opts.keepStatic\r\n ) {\r\n // console.log(\"alternate 1\");\r\n result = alternate.call(inputmask, true) || result;\r\n }\r\n // alternate by adding extra input in between\r\n else if (\r\n opts.numericInput !== true &&\r\n maskset.tests[maskPos] &&\r\n maskset.tests[maskPos].length > 1 &&\r\n getLastValidPosition.call(inputmask, undefined, true) > maskPos\r\n ) {\r\n // console.log(\"alternate 2\");\r\n result = alternate.call(inputmask, true) || result;\r\n }\r\n }\r\n }\r\n\r\n if (result === true) {\r\n result = {\r\n pos: maskPos\r\n };\r\n }\r\n\r\n if (\r\n typeof opts.postValidation === \"function\" &&\r\n fromIsValid !== true &&\r\n validateOnly !== true\r\n ) {\r\n const postResult = opts.postValidation.call(\r\n inputmask,\r\n getBuffer.call(inputmask, true),\r\n pos.begin !== undefined ? (inputmask.isRTL ? pos.end : pos.begin) : pos,\r\n c,\r\n result,\r\n opts,\r\n maskset,\r\n strict,\r\n fromCheckval,\r\n fromAlternate\r\n );\r\n if (postResult !== undefined) {\r\n result = postResult === true ? result : postResult;\r\n }\r\n }\r\n }\r\n\r\n if (result && result.pos === undefined) {\r\n result.pos = maskPos;\r\n }\r\n\r\n if (result === false || validateOnly === true) {\r\n resetMaskSet.call(inputmask, true);\r\n maskset.validPositions = $.extend(true, [], positionsClone); // revert validation changes\r\n } else {\r\n trackbackPositions.call(inputmask, undefined, maskPos, true);\r\n }\r\n\r\n let endResult = processCommandObject(result);\r\n // console.log(\"returned result \" + JSON.stringify(endResult));\r\n if (inputmask.maxLength !== undefined) {\r\n const buffer = getBuffer.call(inputmask);\r\n if (buffer.length > inputmask.maxLength && !fromIsValid) {\r\n resetMaskSet.call(inputmask, true);\r\n maskset.validPositions = $.extend(true, [], positionsClone); // revert validation changes\r\n endResult = false;\r\n }\r\n }\r\n return endResult;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction positionCanMatchDefinition(pos, testDefinition, opts) {\r\n const inputmask = this,\r\n maskset = this.maskset;\r\n\r\n let valid = false,\r\n tests = getTests.call(inputmask, pos);\r\n for (let tndx = 0; tndx < tests.length; tndx++) {\r\n if (\r\n tests[tndx].match &&\r\n ((tests[tndx].match.nativeDef ===\r\n testDefinition.match[opts.shiftPositions ? \"def\" : \"nativeDef\"] &&\r\n (!opts.shiftPositions || !testDefinition.match.static)) ||\r\n tests[tndx].match.nativeDef === testDefinition.match.nativeDef ||\r\n (opts.regex &&\r\n !tests[tndx].match.static &&\r\n tests[tndx].match.fn.test(\r\n testDefinition.input,\r\n maskset,\r\n pos,\r\n false,\r\n opts\r\n )))\r\n ) {\r\n valid = true;\r\n break;\r\n } else if (\r\n tests[tndx].match &&\r\n tests[tndx].match.def === testDefinition.match.nativeDef\r\n ) {\r\n valid = undefined;\r\n break;\r\n }\r\n }\r\n if (valid === false) {\r\n if (maskset.jitOffset[pos] !== undefined) {\r\n valid = positionCanMatchDefinition.call(\r\n inputmask,\r\n pos + maskset.jitOffset[pos],\r\n testDefinition,\r\n opts\r\n );\r\n }\r\n }\r\n return valid;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction refreshFromBuffer(start, end, buffer) {\r\n const inputmask = this,\r\n maskset = this.maskset,\r\n opts = this.opts,\r\n $ = this.dependencyLib;\r\n // checkVal.call(inputmask, el, false, true, isRTL ? buffer.reverse() : buffer);\r\n let i,\r\n p,\r\n skipOptionalPartCharacter = opts.skipOptionalPartCharacter,\r\n bffr = inputmask.isRTL ? buffer.slice().reverse() : buffer;\r\n opts.skipOptionalPartCharacter = \"\";\r\n if (start === true) {\r\n resetMaskSet.call(inputmask, false);\r\n start = 0;\r\n end = buffer.length;\r\n p = determineNewCaretPosition.call(\r\n inputmask,\r\n { begin: 0, end: 0 },\r\n false\r\n ).begin;\r\n } else {\r\n for (i = start; i < end; i++) {\r\n delete maskset.validPositions[i];\r\n }\r\n p = start;\r\n }\r\n\r\n const keypress = new $.Event(\"keypress\");\r\n for (i = start; i < end; i++) {\r\n keypress.key = bffr[i].toString();\r\n inputmask.ignorable = false; // make sure ignorable is ignored ;-)\r\n const valResult = EventHandlers.keypressEvent.call(\r\n inputmask,\r\n keypress,\r\n true,\r\n false,\r\n false,\r\n p\r\n );\r\n if (valResult !== false && valResult !== undefined) {\r\n p = valResult.forwardPosition;\r\n }\r\n }\r\n\r\n opts.skipOptionalPartCharacter = skipOptionalPartCharacter;\r\n}\r\n\r\n// tobe put on prototype?\r\n// fill in best positions according the current input\r\nfunction trackbackPositions(originalPos, newPos, fillOnly) {\r\n const inputmask = this,\r\n maskset = this.maskset,\r\n $ = this.dependencyLib;\r\n\r\n // console.log(\"trackbackPositions \" + originalPos + \" \" + newPos);\r\n if (originalPos === undefined) {\r\n // find previous valid\r\n for (originalPos = newPos - 1; originalPos > 0; originalPos--) {\r\n if (maskset.validPositions[originalPos]) break;\r\n }\r\n }\r\n for (let ps = originalPos; ps < newPos; ps++) {\r\n if (\r\n maskset.validPositions[ps] === undefined &&\r\n !isMask.call(inputmask, ps, false)\r\n ) {\r\n const vp =\r\n ps == 0 ? getTest.call(inputmask, ps) : maskset.validPositions[ps - 1];\r\n if (vp) {\r\n const tests = getTests.call(inputmask, ps).slice();\r\n if (tests[tests.length - 1].match.def === \"\") tests.pop();\r\n var bestMatch = determineTestTemplate.call(inputmask, ps, tests),\r\n np;\r\n if (\r\n bestMatch &&\r\n (bestMatch.match.jit !== true ||\r\n (bestMatch.match.newBlockMarker === \"master\" &&\r\n (np = maskset.validPositions[ps + 1]) &&\r\n np.match.optionalQuantifier === true))\r\n ) {\r\n bestMatch = $.extend({}, bestMatch, {\r\n input:\r\n getPlaceholder.call(inputmask, ps, bestMatch.match, true) ||\r\n bestMatch.match.def\r\n });\r\n bestMatch.generatedInput = true;\r\n revalidateMask.call(inputmask, ps, bestMatch, true);\r\n\r\n if (fillOnly !== true) {\r\n // revalidate the new position to update the locator value\r\n const cvpInput = maskset.validPositions[newPos].input;\r\n maskset.validPositions[newPos] = undefined;\r\n return isValid.call(inputmask, newPos, cvpInput, true, true);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction revalidateMask(pos, validTest, fromIsValid, validatedPos) {\r\n // console.log(\"revalidateMask \" + fromIsValid);\r\n const inputmask = this,\r\n maskset = this.maskset,\r\n opts = this.opts,\r\n $ = this.dependencyLib;\r\n\r\n function IsEnclosedStatic(pos, valids, selection) {\r\n const posMatch = valids[pos];\r\n if (\r\n posMatch !== undefined &&\r\n posMatch.match.static === true &&\r\n posMatch.match.optionality !== true &&\r\n (valids[0] === undefined || valids[0].alternation === undefined)\r\n ) {\r\n const prevMatch =\r\n selection.begin <= pos - 1\r\n ? valids[pos - 1] &&\r\n valids[pos - 1].match.static === true &&\r\n valids[pos - 1]\r\n : valids[pos - 1],\r\n nextMatch =\r\n selection.end > pos + 1\r\n ? valids[pos + 1] &&\r\n valids[pos + 1].match.static === true &&\r\n valids[pos + 1]\r\n : valids[pos + 1];\r\n return prevMatch && nextMatch;\r\n }\r\n return false;\r\n }\r\n\r\n let offset = 0,\r\n begin = pos.begin !== undefined ? pos.begin : pos,\r\n end = pos.end !== undefined ? pos.end : pos,\r\n valid = true;\r\n if (pos.begin > pos.end) {\r\n begin = pos.end;\r\n end = pos.begin;\r\n }\r\n\r\n validatedPos = validatedPos !== undefined ? validatedPos : begin;\r\n if (\r\n fromIsValid === undefined &&\r\n (begin !== end ||\r\n (opts.insertMode && maskset.validPositions[validatedPos] !== undefined) ||\r\n validTest === undefined ||\r\n validTest.match.optionalQuantifier ||\r\n validTest.match.optionality)\r\n ) {\r\n // reposition & revalidate others\r\n let positionsClone = $.extend(true, [], maskset.validPositions),\r\n lvp = getLastValidPosition.call(inputmask, undefined, true),\r\n i;\r\n maskset.p = begin; // needed for alternated position after overtype selection\r\n\r\n const clearpos = isSelection.call(inputmask, pos) ? begin : validatedPos;\r\n for (i = lvp; i >= clearpos; i--) {\r\n maskset.validPositions.splice(i, 1);\r\n if (validTest === undefined) delete maskset.tests[i + 1];\r\n }\r\n\r\n let j = validatedPos,\r\n posMatch = j,\r\n t,\r\n canMatch,\r\n test;\r\n\r\n if (validTest) {\r\n maskset.validPositions[validatedPos] = $.extend(true, {}, validTest);\r\n posMatch++;\r\n j++;\r\n }\r\n\r\n if (positionsClone[end] == undefined && maskset.jitOffset[end]) {\r\n end += maskset.jitOffset[end] + (validTest ? 1 : 0);\r\n }\r\n for (i = validTest ? end : end - 1; i <= lvp; i++) {\r\n if (\r\n (t = positionsClone[i]) !== undefined &&\r\n (opts.shiftPositions !== true || t.generatedInput !== true) &&\r\n (i >= end ||\r\n (i >= begin &&\r\n IsEnclosedStatic(i, positionsClone, {\r\n begin,\r\n end\r\n })))\r\n ) {\r\n while (\r\n ((test = getTest.call(inputmask, posMatch)), test.match.def !== \"\")\r\n ) {\r\n // loop needed to match further positions\r\n if (\r\n (canMatch = positionCanMatchDefinition.call(\r\n inputmask,\r\n posMatch,\r\n t,\r\n opts\r\n )) !== false ||\r\n t.match.def === \"+\"\r\n ) {\r\n // validated match //we still need some hackery for the + validator (numeric alias)\r\n if (t.match.def === \"+\") getBuffer.call(inputmask, true);\r\n const result = isValid.call(\r\n inputmask,\r\n posMatch,\r\n t.input,\r\n t.match.def !== \"+\",\r\n /* t.match.def !== \"+\" */ true\r\n );\r\n valid = result !== false;\r\n j = (result.pos || posMatch) + 1;\r\n if (!valid && canMatch) break;\r\n } else {\r\n valid = false;\r\n }\r\n if (valid) {\r\n if (validTest === undefined && t.match.static && i === pos.begin)\r\n offset++;\r\n break;\r\n }\r\n if (\r\n (!valid && getBuffer.call(inputmask), posMatch > maskset.maskLength)\r\n ) {\r\n break;\r\n }\r\n posMatch++;\r\n }\r\n if (getTest.call(inputmask, posMatch).match.def == \"\") {\r\n valid = false;\r\n }\r\n // restore position\r\n posMatch = j;\r\n }\r\n if (!valid) break;\r\n }\r\n if (!valid) {\r\n maskset.validPositions = $.extend(true, [], positionsClone);\r\n resetMaskSet.call(inputmask, true);\r\n return false;\r\n }\r\n } else if (\r\n validTest &&\r\n getTest.call(inputmask, validatedPos).match.cd === validTest.match.cd\r\n ) {\r\n maskset.validPositions[validatedPos] = $.extend(true, {}, validTest);\r\n }\r\n\r\n resetMaskSet.call(inputmask, true);\r\n return offset;\r\n}\r\n", "import Inputmask from \"./inputmask\";\r\nimport { getLastValidPosition, seekNext } from \"./positioning\";\r\nimport { casing } from \"./validation\";\r\n\r\nexport {\r\n determineTestTemplate,\r\n getDecisionTaker,\r\n getMaskTemplate,\r\n getPlaceholder,\r\n getTest,\r\n getTests,\r\n getTestTemplate,\r\n isSubsetOf\r\n};\r\n\r\nfunction getLocator(tst, align) {\r\n // need to align the locators to be correct\r\n let locator = (\r\n tst.alternation != undefined\r\n ? tst.mloc[`${getDecisionTaker(tst)}:${tst.alternation}`] || tst.locator\r\n : tst.locator\r\n ).join(\"\");\r\n if (locator !== \"\") {\r\n locator = locator.split(\":\")[0]; // strip off alternation marker\r\n while (locator.length < align) locator += \"0\";\r\n }\r\n return locator;\r\n}\r\n\r\nfunction getDecisionTaker(tst) {\r\n let decisionTaker = tst.locator[tst.alternation];\r\n if (typeof decisionTaker === \"string\" && decisionTaker.length > 0) {\r\n // no decision taken ~ take smallest as decider\r\n decisionTaker = decisionTaker.split(\",\").sort((a, b) => a - b)[0];\r\n }\r\n return decisionTaker !== undefined ? decisionTaker.toString() : \"\";\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction getPlaceholder(pos, test, returnPL) {\r\n const inputmask = this,\r\n opts = this.opts,\r\n maskset = this.maskset;\r\n\r\n test = test || getTest.call(inputmask, pos).match;\r\n\r\n if (test.placeholder !== undefined || returnPL === true) {\r\n if (\r\n test.placeholder !== \"\" &&\r\n test.static === true &&\r\n test.generated !== true\r\n ) {\r\n // static and not dynamically generated ~ does not occur in regex mask ~ numeric alias def is not a valid entry\r\n const lvp = getLastValidPosition.call(inputmask, pos),\r\n nextPos = seekNext.call(inputmask, lvp);\r\n return (returnPL ? pos <= nextPos : pos < nextPos)\r\n ? casing.call(\r\n inputmask,\r\n opts.staticDefinitionSymbol && test.static\r\n ? test.nativeDef\r\n : test.def,\r\n test,\r\n pos\r\n )\r\n : typeof test.placeholder === \"function\"\r\n ? test.placeholder(opts)\r\n : test.placeholder;\r\n } else {\r\n return typeof test.placeholder === \"function\"\r\n ? test.placeholder(opts)\r\n : test.placeholder;\r\n }\r\n } else if (test.static === true) {\r\n if (pos > -1 && maskset.validPositions[pos] === undefined) {\r\n let tests = getTests.call(inputmask, pos),\r\n staticAlternations = [],\r\n prevTest;\r\n if (\r\n typeof opts.placeholder === \"string\" &&\r\n tests.length > 1 + (tests[tests.length - 1].match.def === \"\" ? 1 : 0)\r\n ) {\r\n for (let i = 0; i < tests.length; i++) {\r\n if (\r\n tests[i].match.def !== \"\" &&\r\n tests[i].match.optionality !== true &&\r\n tests[i].match.optionalQuantifier !== true &&\r\n (tests[i].match.static === true ||\r\n prevTest === undefined ||\r\n tests[i].match.fn.test(\r\n prevTest.match.def,\r\n maskset,\r\n pos,\r\n true,\r\n opts\r\n ) !== false)\r\n ) {\r\n staticAlternations.push(tests[i]);\r\n if (tests[i].match.static === true) prevTest = tests[i];\r\n if (staticAlternations.length > 1) {\r\n if (/[0-9a-zA-Z]/.test(staticAlternations[0].match.def)) {\r\n return opts.placeholder.charAt(pos % opts.placeholder.length);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return test.def;\r\n }\r\n\r\n return typeof opts.placeholder === \"object\"\r\n ? test.def\r\n : opts.placeholder.charAt(pos % opts.placeholder.length);\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction getMaskTemplate(\r\n baseOnInput,\r\n minimalPos,\r\n includeMode,\r\n noJit,\r\n clearOptionalTail\r\n) {\r\n // includeMode true => input, undefined => placeholder, false => mask\r\n\r\n const inputmask = this,\r\n opts = this.opts,\r\n maskset = this.maskset,\r\n greedy = opts.greedy,\r\n maskTemplate = [];\r\n if (clearOptionalTail && opts.greedy) {\r\n opts.greedy = false;\r\n inputmask.maskset.tests = {};\r\n }\r\n minimalPos = minimalPos || 0;\r\n let ndxIntlzr,\r\n pos = 0,\r\n test,\r\n testPos,\r\n jitRenderStatic;\r\n do {\r\n if (baseOnInput === true && maskset.validPositions[pos]) {\r\n testPos =\r\n clearOptionalTail &&\r\n maskset.validPositions[pos].match.optionality &&\r\n maskset.validPositions[pos + 1] === undefined &&\r\n (maskset.validPositions[pos].generatedInput === true ||\r\n (maskset.validPositions[pos].input ==\r\n opts.skipOptionalPartCharacter &&\r\n pos > 0))\r\n ? determineTestTemplate.call(\r\n inputmask,\r\n pos,\r\n getTests.call(inputmask, pos, ndxIntlzr, pos - 1)\r\n )\r\n : maskset.validPositions[pos];\r\n test = testPos.match;\r\n ndxIntlzr = testPos.locator.slice();\r\n maskTemplate.push(\r\n includeMode === true\r\n ? testPos.input\r\n : includeMode === false\r\n ? test.nativeDef\r\n : getPlaceholder.call(inputmask, pos, test)\r\n );\r\n } else {\r\n testPos = getTestTemplate.call(inputmask, pos, ndxIntlzr, pos - 1);\r\n test = testPos.match;\r\n ndxIntlzr = testPos.locator.slice();\r\n const jitMasking =\r\n noJit === true\r\n ? false\r\n : opts.jitMasking !== false\r\n ? opts.jitMasking\r\n : test.jit;\r\n // check for groupSeparator is a hack for the numerics as we don't want the render of the groupSeparator beforehand\r\n jitRenderStatic =\r\n (jitRenderStatic ||\r\n maskset.validPositions[\r\n pos - 1\r\n ]) /* && getTest.call(inputmask, pos + 1).match.def == \"\" */ &&\r\n test.static &&\r\n test.def !== opts.groupSeparator &&\r\n test.fn === null;\r\n\r\n if (\r\n jitRenderStatic ||\r\n jitMasking === false ||\r\n jitMasking === undefined /* || pos < lvp */ ||\r\n (typeof jitMasking === \"number\" &&\r\n isFinite(jitMasking) &&\r\n jitMasking > pos)\r\n ) {\r\n maskTemplate.push(\r\n includeMode === false\r\n ? test.nativeDef\r\n : getPlaceholder.call(inputmask, maskTemplate.length, test)\r\n );\r\n } else {\r\n jitRenderStatic = false;\r\n }\r\n }\r\n\r\n pos++;\r\n } while (test.static !== true || test.def !== \"\" || minimalPos > pos);\r\n if (maskTemplate[maskTemplate.length - 1] === \"\") {\r\n maskTemplate.pop(); // drop the last one which is empty\r\n }\r\n if (\r\n includeMode !== false || // do not alter the masklength when just retrieving the maskdefinition\r\n maskset.maskLength === undefined\r\n ) {\r\n // just make sure the maskLength gets initialized in all cases (needed for isValid)\r\n maskset.maskLength = pos - 1;\r\n }\r\n\r\n opts.greedy = greedy;\r\n return maskTemplate;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction getTestTemplate(pos, ndxIntlzr, tstPs) {\r\n const inputmask = this,\r\n maskset = this.maskset;\r\n\r\n return (\r\n maskset.validPositions[pos] ||\r\n determineTestTemplate.call(\r\n inputmask,\r\n pos,\r\n getTests.call(\r\n inputmask,\r\n pos,\r\n ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr,\r\n tstPs\r\n )\r\n )\r\n );\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction determineTestTemplate(pos, tests) {\r\n const inputmask = this,\r\n opts = inputmask.opts,\r\n optionalityLevel = determineOptionalityLevel(pos, tests);\r\n\r\n pos = pos > 0 ? pos - 1 : 0;\r\n const longestLocator = Math.max(\r\n ...tests.map((tst) =>\r\n tst.locator === undefined ? 0 : tst.locator.length\r\n )\r\n ),\r\n prevTest = getTest.call(inputmask, pos),\r\n prevLocator = getLocator(prevTest, longestLocator);\r\n\r\n let lenghtOffset = 0,\r\n tstLocator,\r\n closest,\r\n bestMatch;\r\n\r\n if (\r\n opts.greedy &&\r\n tests.length > 1 &&\r\n tests[tests.length - 1].match.def === \"\"\r\n )\r\n lenghtOffset = 1;\r\n // console.log(\" optionality = \" + optionalityLevel);\r\n // console.log(\" - \" + JSON.stringify(tests));\r\n for (let ndx = 0; ndx < tests.length - lenghtOffset; ndx++) {\r\n // find best matching\r\n const tst = tests[ndx];\r\n tstLocator = getLocator(tst, longestLocator);\r\n const distance = Number(tstLocator) - Number(prevLocator); // find the closest match to the previous one\r\n // console.log(\"distance\", distance, tstLocator, prevLocator);\r\n\r\n if (\r\n tst.unMatchedAlternationStopped !== true ||\r\n tests.filter((tst) => tst.unMatchedAlternationStopped !== true).length <=\r\n 1\r\n ) {\r\n // only skip when there are choices outside the alternation\r\n if (\r\n closest === undefined ||\r\n (tstLocator !== \"\" && distance < closest) ||\r\n (bestMatch &&\r\n !opts.greedy &&\r\n bestMatch.match.optionality &&\r\n bestMatch.match.optionality - optionalityLevel > 0 &&\r\n bestMatch.match.newBlockMarker === \"master\" &&\r\n (!tst.match.optionality ||\r\n tst.match.optionality - optionalityLevel < 1 ||\r\n !tst.match.newBlockMarker)) ||\r\n (bestMatch &&\r\n !opts.greedy &&\r\n bestMatch.match.optionalQuantifier &&\r\n !tst.match.optionalQuantifier)\r\n ) {\r\n closest = distance;\r\n bestMatch = tst;\r\n }\r\n }\r\n }\r\n return bestMatch;\r\n}\r\n\r\nfunction determineOptionalityLevel(pos, tests) {\r\n let optionalityLevel = 0,\r\n differentOptionalLevels = false;\r\n tests.forEach((test) => {\r\n if (test.match.optionality) {\r\n if (optionalityLevel !== 0 && optionalityLevel !== test.match.optionality)\r\n differentOptionalLevels = true;\r\n if (optionalityLevel === 0 || optionalityLevel > test.match.optionality) {\r\n optionalityLevel = test.match.optionality;\r\n }\r\n }\r\n });\r\n if (optionalityLevel) {\r\n if (pos == 0) optionalityLevel = 0;\r\n else if (tests.length == 1) optionalityLevel = 0;\r\n else if (!differentOptionalLevels) optionalityLevel = 0;\r\n }\r\n return optionalityLevel;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction getTest(pos, tests) {\r\n const inputmask = this,\r\n maskset = this.maskset;\r\n\r\n if (maskset.validPositions[pos]) {\r\n return maskset.validPositions[pos];\r\n }\r\n return (tests || getTests.call(inputmask, pos))[0];\r\n}\r\n\r\nfunction isSubsetOf(source, target, opts) {\r\n function expand(pattern) {\r\n let expanded = [],\r\n start = -1,\r\n end;\r\n for (let i = 0, l = pattern.length; i < l; i++) {\r\n if (pattern.charAt(i) === \"-\") {\r\n end = pattern.charCodeAt(i + 1);\r\n while (++start < end) expanded.push(String.fromCharCode(start));\r\n } else {\r\n start = pattern.charCodeAt(i);\r\n expanded.push(pattern.charAt(i));\r\n }\r\n }\r\n return expanded.join(\"\");\r\n }\r\n\r\n if (source.match.def === target.match.nativeDef) return true;\r\n\r\n if (\r\n (opts.regex ||\r\n (source.match.fn instanceof RegExp &&\r\n target.match.fn instanceof RegExp)) &&\r\n source.match.static !== true &&\r\n target.match.static !== true\r\n ) {\r\n // is regex a subset\r\n if (target.match.fn.source === \".\") return true;\r\n return (\r\n expand(target.match.fn.source.replace(/[[\\]/]/g, \"\")).indexOf(\r\n expand(source.match.fn.source.replace(/[[\\]/]/g, \"\"))\r\n ) !== -1\r\n );\r\n }\r\n return false;\r\n}\r\n\r\n// tobe put on prototype?\r\nfunction getTests(pos, ndxIntlzr, tstPs) {\r\n let inputmask = this,\r\n $ = this.dependencyLib,\r\n maskset = this.maskset,\r\n opts = this.opts,\r\n el = this.el,\r\n maskTokens = maskset.maskToken,\r\n testPos = ndxIntlzr ? tstPs : 0,\r\n ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [0],\r\n matches = [],\r\n insertStop = false,\r\n insertStopFromAlternation = false,\r\n latestMatch,\r\n cacheDependency = ndxIntlzr ? ndxIntlzr.join(\"\") : \"\",\r\n unMatchedAlternation = false;\r\n\r\n function resolveTestFromToken(\r\n maskToken,\r\n ndxInitializer,\r\n loopNdx,\r\n quantifierRecurse\r\n ) {\r\n // ndxInitializer contains a set of indexes to speedup searches in the mtokens\r\n function handleMatch(match, loopNdx, quantifierRecurse) {\r\n function isFirstMatch(latestMatch, tokenGroup) {\r\n let firstMatch = tokenGroup.matches.indexOf(latestMatch) === 0;\r\n if (!firstMatch) {\r\n tokenGroup.matches.every(function (match, ndx) {\r\n if (match.isQuantifier === true) {\r\n firstMatch = isFirstMatch(\r\n latestMatch,\r\n tokenGroup.matches[ndx - 1]\r\n );\r\n } else if (Object.prototype.hasOwnProperty.call(match, \"matches\")) {\r\n firstMatch = isFirstMatch(latestMatch, match);\r\n }\r\n if (firstMatch) {\r\n if (\r\n tokenGroup.matches[ndx + 1] &&\r\n tokenGroup.matches[ndx + 1].isQuantifier\r\n ) {\r\n firstMatch = ndx === 0;\r\n }\r\n return false;\r\n }\r\n\r\n return true;\r\n });\r\n }\r\n return firstMatch;\r\n }\r\n\r\n function resolveNdxInitializer(pos, alternateNdx, targetAlternation) {\r\n let bestMatch,\r\n distance,\r\n locator,\r\n newAlternateMloc,\r\n alternateMloc = `${alternateNdx}:${targetAlternation}`;\r\n\r\n if (maskset.tests[pos] || maskset.validPositions[pos]) {\r\n (maskset.validPositions[pos]\r\n ? [maskset.validPositions[pos]]\r\n : maskset.tests[pos]\r\n ).every(function (lmnt, ndx) {\r\n if (lmnt.mloc[alternateMloc]) {\r\n bestMatch = lmnt;\r\n return false; // break\r\n }\r\n\r\n // check if an entry in mloc match the alternateNdx on targetAlternation\r\n const mlocMatches = Object.values(lmnt.mloc).filter(\r\n // eslint-disable-next-line eqeqeq\r\n (m) => m[targetAlternation] == alternateNdx\r\n );\r\n // for each mlocMatch check the calculated distance\r\n mlocMatches.every((mlocMatch) => {\r\n let mlocMatchL = mlocMatch.join(\"\").split(\":\")[0]; // strip off alternation marker\r\n locator = locator || mlocMatchL;\r\n while (mlocMatchL.length < locator.length) mlocMatchL += \"0\";\r\n\r\n const mlocDistance = Number(mlocMatchL);\r\n // console.log(\"mlocDistance\", mlocDistance);\r\n if (bestMatch === undefined || mlocDistance < distance) {\r\n distance = mlocDistance;\r\n bestMatch = lmnt;\r\n\r\n // key from mlocMatch\r\n newAlternateMloc = Object.entries(lmnt.mloc).find(\r\n (entry) => entry[1].toString() === mlocMatch.toString()\r\n )[0];\r\n }\r\n\r\n return true; // continue\r\n });\r\n\r\n return true;\r\n });\r\n }\r\n if (bestMatch) {\r\n if (targetAlternation === undefined) {\r\n alternateMloc = `${alternateNdx}:${bestMatch.alternation}`;\r\n }\r\n const bestMatchAltIndex = `${\r\n bestMatch.locator[bestMatch.alternation]\r\n }:${bestMatch.alternation}`,\r\n slocator =\r\n bestMatch.mloc[newAlternateMloc || alternateMloc] ||\r\n bestMatch.mloc[bestMatchAltIndex] ||\r\n bestMatch.locator;\r\n if (slocator[slocator.length - 1].toString().indexOf(\":\") !== -1) {\r\n // eslint-disable-next-line no-unused-vars\r\n const alternation = slocator.pop();\r\n // targetAlternation = parseInt(alternation.substring(1));\r\n }\r\n\r\n const sliceStart =\r\n parseInt(\r\n // newAlternateMloc\r\n // ? newAlternateMloc.split(\":\")[1]\r\n // : targetAlternation ||\r\n bestMatch.alternation\r\n ) + 1;\r\n\r\n // console.log(\r\n // \"resolveNdxInitializer\",\r\n // pos,\r\n // alternateNdx,\r\n // targetAlternation,\r\n // slocator,\r\n // sliceStart,\r\n // bestMatch\r\n // );\r\n\r\n return slocator.slice(sliceStart);\r\n } else {\r\n return targetAlternation !== undefined\r\n ? resolveNdxInitializer(pos, alternateNdx)\r\n : undefined;\r\n }\r\n }\r\n\r\n function staticCanMatchDefinition(source, target) {\r\n return source.match.static === true && target.match.static !== true\r\n ? target.match.fn.test(\r\n source.match.def,\r\n maskset,\r\n pos,\r\n false,\r\n opts,\r\n false\r\n )\r\n : false;\r\n }\r\n\r\n // mergelocators for retrieving the correct locator match when merging\r\n function setMergeLocators(targetMatch, altMatch) {\r\n function mergeLoc(altNdx) {\r\n targetMatch.mloc = targetMatch.mloc || {};\r\n let locNdx = targetMatch.locator[altNdx];\r\n if (locNdx === undefined) {\r\n targetMatch.alternation = undefined;\r\n } else {\r\n if (altMatch === undefined) {\r\n if (typeof locNdx === \"string\") locNdx = locNdx.split(\",\")[0];\r\n locNdx = `${locNdx}:${altNdx}`;\r\n if (targetMatch.mloc[locNdx] === undefined) {\r\n targetMatch.mloc[locNdx] = targetMatch.locator.slice();\r\n targetMatch.mloc[locNdx].push(`:${altNdx}`); // add alternation index\r\n }\r\n } else {\r\n let offset = 0;\r\n for (const ndx in altMatch.mloc) {\r\n // if (typeof ndx === \"string\") ndx = parseInt(ndx.split(\",\")[0]);\r\n if (targetMatch.mloc[ndx] === undefined) {\r\n targetMatch.mloc[ndx] = altMatch.mloc[ndx];\r\n } else {\r\n do {\r\n if (targetMatch.mloc[ndx + offset] === undefined) {\r\n targetMatch.mloc[ndx + offset] = altMatch.mloc[ndx];\r\n break;\r\n }\r\n } while (targetMatch.mloc[ndx + offset++] !== undefined);\r\n }\r\n }\r\n\r\n targetMatch.locator = mergeLocators(testPos, [\r\n targetMatch,\r\n altMatch\r\n ]);\r\n }\r\n if (targetMatch.alternation > altNdx) {\r\n // if the alternation index is higher than the current one resolve it to the alternation\r\n targetMatch.alternation = altNdx;\r\n }\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n let alternationNdx = targetMatch.alternation,\r\n shouldMerge =\r\n altMatch === undefined ||\r\n (alternationNdx <= altMatch.alternation &&\r\n targetMatch.locator[alternationNdx]\r\n .toString()\r\n .indexOf(altMatch.locator[alternationNdx]) === -1);\r\n if (!shouldMerge && alternationNdx > altMatch.alternation) {\r\n for (let i = 0; i < alternationNdx; i++) {\r\n if (targetMatch.locator[i] !== altMatch.locator[i]) {\r\n alternationNdx = i;\r\n shouldMerge = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (shouldMerge) {\r\n return mergeLoc(alternationNdx);\r\n }\r\n return false;\r\n }\r\n\r\n function handleGroup() {\r\n match = handleMatch(\r\n maskToken.matches[maskToken.matches.indexOf(match) + 1],\r\n loopNdx,\r\n quantifierRecurse\r\n );\r\n if (match) return true;\r\n }\r\n\r\n function handleOptional() {\r\n const optionalToken = match,\r\n mtchsNdx = matches.length;\r\n match = resolveTestFromToken(\r\n match,\r\n ndxInitializer,\r\n loopNdx,\r\n quantifierRecurse\r\n );\r\n if (matches.length > 0) {\r\n // check on matches.length instead of match to handle quantifier in a recursive call\r\n // mark optionality in matches\r\n matches.forEach(function (mtch, ndx) {\r\n if (ndx >= mtchsNdx) {\r\n mtch.match.optionality = mtch.match.optionality\r\n ? mtch.match.optionality + 1\r\n : 1;\r\n }\r\n });\r\n latestMatch = matches[matches.length - 1].match;\r\n\r\n if (\r\n quantifierRecurse === undefined &&\r\n isFirstMatch(latestMatch, optionalToken)\r\n ) {\r\n // prevent loop see #698\r\n insertStop = true; // insert a stop\r\n testPos = pos; // match the position after the group\r\n } else {\r\n return match; // make the loop continue when it is deliberately by a quantifier\r\n }\r\n }\r\n }\r\n\r\n function handleAlternator() {\r\n function calculateMatchesLength(matches) {\r\n let matchesLength = 0;\r\n for (let ndx = 0; ndx < matches.length; ndx++) {\r\n const match = matches[ndx];\r\n if (match.isQuantifier && !isNaN(match.quantifier.max)) {\r\n matchesLength += match.quantifier.max;\r\n } else {\r\n matchesLength++;\r\n }\r\n }\r\n return matchesLength;\r\n }\r\n function isUnmatchedAlternation(alternateToken) {\r\n const matchesLength = alternateToken.matches[0].matches\r\n ? calculateMatchesLength(alternateToken.matches[0].matches)\r\n : 1;\r\n let matchesNewLength;\r\n for (let alndx = 0; alndx < alternateToken.matches.length; alndx++) {\r\n matchesNewLength = alternateToken.matches[alndx].matches\r\n ? calculateMatchesLength(alternateToken.matches[alndx].matches)\r\n : 1;\r\n if (matchesLength !== matchesNewLength) {\r\n break;\r\n }\r\n }\r\n\r\n return matchesLength !== matchesNewLength;\r\n }\r\n\r\n inputmask.hasAlternator = true;\r\n const alternateToken = match,\r\n malternateMatches = [],\r\n currentMatches = matches.slice(),\r\n loopNdxCnt = loopNdx.length,\r\n altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;\r\n let maltMatches;\r\n if (altIndex === -1 || typeof altIndex === \"string\") {\r\n const currentPos = testPos,\r\n ndxInitializerClone = ndxInitializer.slice();\r\n let altIndexArr = [],\r\n amndx;\r\n if (typeof altIndex === \"string\") {\r\n altIndexArr = altIndex.split(\",\");\r\n } else {\r\n for (amndx = 0; amndx < alternateToken.matches.length; amndx++) {\r\n altIndexArr.push(amndx.toString());\r\n }\r\n }\r\n\r\n if (maskset.excludes[pos] !== undefined) {\r\n const altIndexArrClone = altIndexArr.slice();\r\n for (let i = 0, exl = maskset.excludes[pos].length; i < exl; i++) {\r\n const excludeSet = maskset.excludes[pos][i].toString().split(\":\");\r\n if (loopNdx.length == excludeSet[1]) {\r\n altIndexArr.splice(altIndexArr.indexOf(excludeSet[0]), 1);\r\n }\r\n }\r\n if (altIndexArr.length === 0) {\r\n // fully alternated => reset\r\n delete maskset.excludes[pos];\r\n altIndexArr = altIndexArrClone;\r\n }\r\n }\r\n if (\r\n opts.keepStatic === true ||\r\n (isFinite(parseInt(opts.keepStatic)) &&\r\n currentPos >= opts.keepStatic)\r\n )\r\n altIndexArr = altIndexArr.slice(0, 1);\r\n for (let ndx = 0; ndx < altIndexArr.length; ndx++) {\r\n amndx = parseInt(altIndexArr[ndx]);\r\n matches = [];\r\n // set the correct ndxInitializer\r\n ndxInitializer =\r\n typeof altIndex === \"string\"\r\n ? resolveNdxInitializer(testPos, amndx, loopNdxCnt) ||\r\n ndxInitializerClone.slice()\r\n : ndxInitializerClone.slice();\r\n // console.log(\"ndxInit\", ndxInitializer);\r\n const tokenMatch = alternateToken.matches[amndx];\r\n if (\r\n tokenMatch &&\r\n handleMatch(\r\n tokenMatch,\r\n [amndx].concat(loopNdx),\r\n quantifierRecurse\r\n )\r\n ) {\r\n match = true;\r\n } else {\r\n // if (currentPos !== 0) {\r\n // only check with the first alternate\r\n unMatchedAlternation = isUnmatchedAlternation(alternateToken);\r\n // }\r\n if (\r\n tokenMatch &&\r\n tokenMatch.matches &&\r\n tokenMatch.matches.length >\r\n alternateToken.matches[0].matches.length\r\n ) {\r\n break;\r\n }\r\n }\r\n\r\n maltMatches = matches.slice();\r\n testPos = currentPos;\r\n matches = [];\r\n\r\n // fuzzy merge matches\r\n for (let ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {\r\n let altMatch = maltMatches[ndx1],\r\n dropMatch = false;\r\n altMatch.alternation = altMatch.alternation || loopNdxCnt;\r\n setMergeLocators(altMatch);\r\n for (let ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {\r\n const altMatch2 = malternateMatches[ndx2];\r\n if (\r\n typeof altIndex !== \"string\" ||\r\n (altMatch.alternation !== undefined &&\r\n altIndex.indexOf(\r\n altMatch.locator[altMatch.alternation].toString()\r\n ) !== -1)\r\n ) {\r\n if (altMatch.match.nativeDef === altMatch2.match.nativeDef) {\r\n dropMatch = true;\r\n setMergeLocators(altMatch2, altMatch);\r\n break;\r\n } else if (isSubsetOf(altMatch, altMatch2, opts)) {\r\n if (setMergeLocators(altMatch, altMatch2)) {\r\n dropMatch = true;\r\n malternateMatches.splice(\r\n malternateMatches.indexOf(altMatch2),\r\n 0,\r\n altMatch\r\n );\r\n }\r\n break;\r\n } else if (isSubsetOf(altMatch2, altMatch, opts)) {\r\n setMergeLocators(altMatch2, altMatch);\r\n break;\r\n } else if (staticCanMatchDefinition(altMatch, altMatch2)) {\r\n if (setMergeLocators(altMatch, altMatch2)) {\r\n // insert match above general match\r\n dropMatch = true;\r\n malternateMatches.splice(\r\n malternateMatches.indexOf(altMatch2),\r\n 0,\r\n altMatch\r\n );\r\n }\r\n break;\r\n } else if (staticCanMatchDefinition(altMatch2, altMatch)) {\r\n setMergeLocators(altMatch2, altMatch);\r\n // hackery to solve a mask like ([0]9)|(2a) ~ note the static 0 is optional ~ see unittest ivaninDarpatov\r\n // this needs a better solution, but his will do for now\r\n if (\r\n altMatch2.match.optionality &&\r\n el.inputmask.userOptions.keepStatic === undefined\r\n ) {\r\n opts.keepStatic = currentPos;\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n if (!dropMatch) {\r\n malternateMatches.push(altMatch);\r\n }\r\n }\r\n }\r\n\r\n matches = currentMatches.concat(malternateMatches);\r\n\r\n testPos = pos;\r\n insertStop =\r\n insertStop || (matches.length > 0 && unMatchedAlternation); // insert a stopelemnt when there is an alternate - needed for non-greedy option\r\n if (!unMatchedAlternation && insertStop)\r\n insertStopFromAlternation = true; // track insertStop set inside a symmetric alternation\r\n match = malternateMatches.length > 0 && !unMatchedAlternation; // set correct match state\r\n\r\n if (unMatchedAlternation && insertStop && !match) {\r\n // mark matches with unMatchedAlternationStopped\r\n matches.forEach(function (mtch, ndx) {\r\n mtch.unMatchedAlternationStopped = true;\r\n });\r\n }\r\n\r\n // cloneback\r\n ndxInitializer = ndxInitializerClone.slice();\r\n } else {\r\n match = handleMatch(\r\n alternateToken.matches[altIndex] || maskToken.matches[altIndex],\r\n [altIndex].concat(loopNdx),\r\n quantifierRecurse\r\n );\r\n }\r\n if (match) {\r\n return true;\r\n }\r\n }\r\n\r\n function handleQuantifier() {\r\n const qt = match;\r\n let breakloop = false;\r\n for (\r\n let qndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0;\r\n qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max) &&\r\n testPos <= pos;\r\n qndx++\r\n ) {\r\n const tokenGroup =\r\n maskToken.matches[maskToken.matches.indexOf(qt) - 1];\r\n match = handleMatch(tokenGroup, [qndx].concat(loopNdx), tokenGroup); // set the tokenGroup as quantifierRecurse marker\r\n if (match) {\r\n matches.forEach(function (mtch, ndx) {\r\n if (IsMatchOf(tokenGroup, mtch.match)) latestMatch = mtch.match;\r\n else latestMatch = matches[matches.length - 1].match;\r\n\r\n // mark optionality\r\n // TODO FIX RECURSIVE QUANTIFIERS\r\n latestMatch.optionalQuantifier = qndx >= qt.quantifier.min;\r\n // console.log(pos + \" \" + qt.quantifier.min + \" \" + latestMatch.optionalQuantifier);\r\n // qndx + 1 as the index starts from 0\r\n latestMatch.jit =\r\n (qndx + 1) * (tokenGroup.matches.indexOf(latestMatch) + 1) >\r\n qt.quantifier.jit;\r\n if (\r\n (latestMatch.optionalQuantifier || latestMatch.optionality) &&\r\n isFirstMatch(latestMatch, tokenGroup)\r\n ) {\r\n insertStop = true;\r\n testPos = pos; // match the position after the group\r\n if (\r\n opts.greedy &&\r\n maskset.validPositions[pos - 1] == undefined &&\r\n qndx > qt.quantifier.min &&\r\n [\"*\", \"+\"].indexOf(qt.quantifier.max) != -1\r\n ) {\r\n matches.pop();\r\n cacheDependency = undefined;\r\n }\r\n breakloop = true; // stop quantifierloop && search for next possible match\r\n match = false; // mark match to false to make sure the loop in optionals continues\r\n }\r\n if (\r\n !breakloop &&\r\n latestMatch.jit /* && !latestMatch.optionalQuantifier */\r\n ) {\r\n // always set jitOffset, isvalid checks when to apply\r\n maskset.jitOffset[pos] =\r\n tokenGroup.matches.length -\r\n tokenGroup.matches.indexOf(latestMatch);\r\n }\r\n });\r\n if (breakloop) break; // search for next possible match\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n if (testPos > pos + opts._maxTestPos) {\r\n throw new Error(\r\n `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}`\r\n );\r\n }\r\n if (testPos === pos && match.matches === undefined) {\r\n matches.push({\r\n match,\r\n locator: loopNdx.reverse(),\r\n cd: cacheDependency,\r\n mloc: {}\r\n });\r\n if (\r\n match.optionality &&\r\n quantifierRecurse === undefined &&\r\n ((opts.definitions &&\r\n opts.definitions[match.nativeDef] &&\r\n opts.definitions[match.nativeDef].optional) ||\r\n (Inputmask.prototype.definitions[match.nativeDef] &&\r\n Inputmask.prototype.definitions[match.nativeDef].optional))\r\n ) {\r\n // prevent loop see #698\r\n insertStop = true; // insert a stop\r\n testPos = pos; // match the position after the group\r\n } else {\r\n return true;\r\n }\r\n } else if (match.matches !== undefined) {\r\n if (match.isGroup && quantifierRecurse !== match) {\r\n // when a group pass along to the quantifier\r\n return handleGroup();\r\n } else if (match.isOptional) {\r\n return handleOptional();\r\n } else if (match.isAlternator) {\r\n return handleAlternator();\r\n } else if (\r\n match.isQuantifier &&\r\n quantifierRecurse !==\r\n maskToken.matches[maskToken.matches.indexOf(match) - 1]\r\n ) {\r\n return handleQuantifier();\r\n } else {\r\n match = resolveTestFromToken(\r\n match,\r\n ndxInitializer,\r\n loopNdx,\r\n quantifierRecurse\r\n );\r\n if (match) return true;\r\n }\r\n } else {\r\n testPos++;\r\n }\r\n }\r\n\r\n // the offset is set in the quantifierloop when git masking is used\r\n for (\r\n let tndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0;\r\n tndx < maskToken.matches.length;\r\n tndx++\r\n ) {\r\n if (maskToken.matches[tndx].isQuantifier !== true) {\r\n const match = handleMatch(\r\n maskToken.matches[tndx],\r\n [tndx].concat(loopNdx),\r\n quantifierRecurse\r\n );\r\n if (match && testPos === pos) {\r\n return match;\r\n } else if (testPos > pos) {\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n function IsMatchOf(tokenGroup, match) {\r\n let isMatch = tokenGroup.matches.indexOf(match) != -1;\r\n if (!isMatch) {\r\n tokenGroup.matches.forEach((mtch, ndx) => {\r\n if (mtch.matches !== undefined && !isMatch) {\r\n isMatch = IsMatchOf(mtch, match);\r\n }\r\n });\r\n }\r\n return isMatch;\r\n }\r\n\r\n function mergeLocators(pos, tests) {\r\n let locator = [];\r\n if (!Array.isArray(tests)) tests = [tests];\r\n\r\n if (tests.length > 0) {\r\n if (\r\n tests[0].alternation === undefined ||\r\n opts.keepStatic === true ||\r\n (isFinite(parseInt(opts.keepStatic)) && pos >= opts.keepStatic)\r\n ) {\r\n locator = determineTestTemplate\r\n .call(inputmask, pos, tests.slice())\r\n .locator.slice();\r\n if (locator.length === 0) locator = tests[0].locator.slice();\r\n } else {\r\n // alternation = tests[0].locator.length - 1;\r\n tests.forEach((mtch) => {\r\n Object.values(mtch.mloc).forEach((mloc) => {\r\n mloc.forEach((loc, locNdx) => {\r\n // if (locNdx > alternation) return;\r\n const mergedPos = locator[locNdx];\r\n if (\r\n loc.toString().includes(\":\") ||\r\n (mergedPos && mergedPos.toString().includes(\":\"))\r\n )\r\n return;\r\n if (mergedPos === undefined) {\r\n locator[locNdx] = loc;\r\n } else if (!mergedPos.toString().includes(loc)) {\r\n locator[locNdx] = locator[locNdx] + \",\" + loc;\r\n }\r\n });\r\n });\r\n });\r\n }\r\n }\r\n // console.log(\"mergeLocators\", pos, tests, locator);\r\n return locator;\r\n }\r\n\r\n if (pos > -1) {\r\n if (ndxIntlzr === undefined) {\r\n // determine index initializer\r\n let previousPos = pos - 1,\r\n test;\r\n while (\r\n (test =\r\n maskset.validPositions[previousPos] || maskset.tests[previousPos]) ===\r\n undefined &&\r\n previousPos > -1\r\n ) {\r\n previousPos--;\r\n }\r\n if (test !== undefined && previousPos > -1) {\r\n ndxInitializer = mergeLocators(previousPos, test);\r\n cacheDependency = ndxInitializer.join(\"\");\r\n testPos = previousPos;\r\n }\r\n }\r\n if (maskset.tests[pos] && maskset.tests[pos][0].cd === cacheDependency) {\r\n // cacheDependency is set on all tests, just check on the first\r\n return maskset.tests[pos];\r\n }\r\n for (\r\n let mtndx = ndxInitializer.shift();\r\n mtndx < maskTokens.length;\r\n mtndx++\r\n ) {\r\n const match = resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [\r\n mtndx\r\n ]);\r\n if ((match && testPos === pos) || testPos > pos) {\r\n break;\r\n }\r\n }\r\n }\r\n if (matches.length === 0 || insertStop) {\r\n matches.push({\r\n match: {\r\n fn: null,\r\n static: true,\r\n optionality: false,\r\n casing: null,\r\n def: \"\",\r\n placeholder: \"\"\r\n },\r\n // mark when there are unmatched alternations ex: mask: \"(a|aa)\"\r\n // this will result in the least distance to select the correct test result in determineTestTemplate\r\n locator:\r\n unMatchedAlternation &&\r\n matches.filter((tst) => tst.unMatchedAlternationStopped !== true)\r\n .length === 0\r\n ? [0]\r\n : insertStopFromAlternation &&\r\n matches.length > 0 &&\r\n matches\r\n .filter((tst) => !tst.match.static)\r\n .every((tst) => tst.match.optionalQuantifier)\r\n ? [0]\r\n : [],\r\n mloc: {},\r\n cd: cacheDependency\r\n });\r\n }\r\n let result;\r\n if (ndxIntlzr !== undefined && maskset.tests[pos]) {\r\n // prioritize full tests for caching\r\n result = $.extend(true, [], matches);\r\n } else {\r\n // console.log(\"stored \" + pos + \" - \" + JSON.stringify(matches));\r\n maskset.tests[pos] = $.extend(true, [], matches); // set a clone to prevent overwriting some props\r\n result = maskset.tests[pos];\r\n }\r\n\r\n // console.log(pos, JSON.stringify(matches));\r\n // cleanup optionality marking\r\n matches.forEach((t) => {\r\n t.match.optionality = t.match.defOptionality || false;\r\n });\r\n\r\n return result;\r\n}\r\n", "import { iphone, mobile } from \"./environment\";\r\nimport { EventHandlers } from \"./eventhandlers\";\r\nimport { EventRuler } from \"./eventruler\";\r\nimport {\r\n applyInputValue,\r\n clearOptionalTail,\r\n writeBuffer\r\n} from \"./inputHandling\";\r\nimport {\r\n caret,\r\n getBuffer,\r\n getBufferTemplate,\r\n getLastValidPosition,\r\n resetMaskSet,\r\n seekNext\r\n} from \"./positioning\";\r\nimport { isComplete } from \"./validation\";\r\n\r\nexport { mask };\r\n\r\n// todo put on the prototype?\r\nfunction mask() {\r\n const inputmask = this,\r\n opts = this.opts,\r\n el = this.el,\r\n $ = this.dependencyLib;\r\n\r\n function isElementTypeSupported(input, opts) {\r\n function patchValueProperty(npt) {\r\n let valueGet, valueSet;\r\n\r\n function patchValhook(type) {\r\n if (\r\n $.valHooks &&\r\n ($.valHooks[type] === undefined ||\r\n $.valHooks[type].inputmaskpatch !== true)\r\n ) {\r\n const valhookGet =\r\n $.valHooks[type] && $.valHooks[type].get\r\n ? $.valHooks[type].get\r\n : function (elem) {\r\n return elem.value;\r\n },\r\n valhookSet =\r\n $.valHooks[type] && $.valHooks[type].set\r\n ? $.valHooks[type].set\r\n : function (elem, value) {\r\n elem.value = value;\r\n return elem;\r\n };\r\n\r\n $.valHooks[type] = {\r\n get: function (elem) {\r\n if (elem.inputmask) {\r\n if (elem.inputmask.opts.autoUnmask) {\r\n return elem.inputmask.unmaskedvalue();\r\n } else {\r\n const result = valhookGet(elem);\r\n return getLastValidPosition.call(\r\n inputmask,\r\n undefined,\r\n undefined,\r\n elem.inputmask.maskset.validPositions\r\n ) !== -1 || opts.nullable !== true\r\n ? result\r\n : \"\";\r\n }\r\n } else {\r\n return valhookGet(elem);\r\n }\r\n },\r\n set: function (elem, value) {\r\n const result = valhookSet(elem, value);\r\n if (elem.inputmask) {\r\n applyInputValue(elem, value);\r\n }\r\n return result;\r\n },\r\n inputmaskpatch: true\r\n };\r\n }\r\n }\r\n\r\n function getter() {\r\n if (this.inputmask) {\r\n return this.inputmask.opts.autoUnmask\r\n ? this.inputmask.unmaskedvalue()\r\n : getLastValidPosition.call(inputmask) !== -1 ||\r\n opts.nullable !== true\r\n ? this.getRootNode().activeElement === this &&\r\n opts.clearMaskOnLostFocus\r\n ? (inputmask.isRTL\r\n ? clearOptionalTail\r\n .call(inputmask, getBuffer.call(inputmask).slice())\r\n .reverse()\r\n : clearOptionalTail.call(\r\n inputmask,\r\n getBuffer.call(inputmask).slice()\r\n )\r\n ).join(\"\")\r\n : valueGet.call(this)\r\n : \"\";\r\n } else {\r\n return valueGet.call(this);\r\n }\r\n }\r\n\r\n function setter(value) {\r\n valueSet.call(this, value);\r\n if (this.inputmask) {\r\n applyInputValue(this, value);\r\n }\r\n }\r\n\r\n function installNativeValueSetFallback(npt) {\r\n EventRuler.on(npt, \"mouseenter\", function () {\r\n const input = this,\r\n value = input.inputmask._valueGet(true),\r\n bufferValue = (\r\n input.inputmask.isRTL\r\n ? getBuffer.call(input.inputmask).slice().reverse()\r\n : getBuffer.call(input.inputmask)\r\n ).join(\"\");\r\n if (value != bufferValue) {\r\n applyInputValue(input, value);\r\n }\r\n });\r\n }\r\n\r\n if (!npt.inputmask.__valueGet) {\r\n if (opts.noValuePatching !== true) {\r\n if (Object.getOwnPropertyDescriptor) {\r\n const valueProperty = Object.getPrototypeOf\r\n ? Object.getOwnPropertyDescriptor(\r\n Object.getPrototypeOf(npt),\r\n \"value\"\r\n )\r\n : undefined;\r\n if (valueProperty && valueProperty.get && valueProperty.set) {\r\n valueGet = valueProperty.get;\r\n valueSet = valueProperty.set;\r\n Object.defineProperty(npt, \"value\", {\r\n get: getter,\r\n set: setter,\r\n configurable: true\r\n });\r\n } else if (npt.tagName.toLowerCase() !== \"input\") {\r\n valueGet = function () {\r\n return this.textContent;\r\n };\r\n valueSet = function (value) {\r\n this.textContent = value;\r\n };\r\n Object.defineProperty(npt, \"value\", {\r\n get: getter,\r\n set: setter,\r\n configurable: true\r\n });\r\n }\r\n } else if (\r\n document.__lookupGetter__ &&\r\n npt.__lookupGetter__(\"value\")\r\n ) {\r\n valueGet = npt.__lookupGetter__(\"value\");\r\n valueSet = npt.__lookupSetter__(\"value\");\r\n\r\n npt.__defineGetter__(\"value\", getter);\r\n npt.__defineSetter__(\"value\", setter);\r\n }\r\n npt.inputmask.__valueGet = valueGet; // store native property getter\r\n npt.inputmask.__valueSet = valueSet; // store native property setter\r\n }\r\n npt.inputmask._valueGet = function (overruleRTL) {\r\n return inputmask.isRTL && overruleRTL !== true\r\n ? valueGet.call(this.el).split(\"\").reverse().join(\"\")\r\n : valueGet.call(this.el);\r\n };\r\n npt.inputmask._valueSet = function (value, overruleRTL) {\r\n // null check is needed for IE8 => otherwise converts to \"null\"\r\n valueSet.call(\r\n this.el,\r\n value === null || value === undefined\r\n ? \"\"\r\n : overruleRTL !== true && inputmask.isRTL\r\n ? value.split(\"\").reverse().join(\"\")\r\n : value\r\n );\r\n };\r\n\r\n if (valueGet === undefined) {\r\n // jquery.val fallback\r\n valueGet = function () {\r\n return this.value;\r\n };\r\n valueSet = function (value) {\r\n this.value = value;\r\n };\r\n patchValhook(npt.type);\r\n installNativeValueSetFallback(npt);\r\n }\r\n }\r\n }\r\n\r\n const elementType = input.getAttribute(\"type\");\r\n let isSupported =\r\n (input.tagName.toLowerCase() === \"input\" &&\r\n opts.supportsInputType.includes(elementType)) ||\r\n input.isContentEditable ||\r\n input.tagName.toLowerCase() === \"textarea\";\r\n if (!isSupported) {\r\n if (input.tagName.toLowerCase() === \"input\") {\r\n let el = document.createElement(\"input\");\r\n el.setAttribute(\"type\", elementType);\r\n isSupported = el.type === \"text\"; // apply mask only if the type is not natively supported\r\n el = null;\r\n } else {\r\n isSupported = \"partial\";\r\n }\r\n }\r\n if (isSupported !== false) {\r\n patchValueProperty(input);\r\n } else {\r\n input.inputmask = undefined;\r\n }\r\n return isSupported;\r\n }\r\n\r\n // unbind all events - to make sure that no other mask will interfere when re-masking\r\n EventRuler.off(el);\r\n const isSupported = isElementTypeSupported(el, opts);\r\n if (isSupported !== false) {\r\n inputmask.originalPlaceholder = el.placeholder;\r\n\r\n // read maxlength prop from el\r\n inputmask.maxLength = el !== undefined ? el.maxLength : undefined;\r\n if (inputmask.maxLength === -1) inputmask.maxLength = undefined;\r\n if (\"inputMode\" in el && el.getAttribute(\"inputmode\") === null) {\r\n el.inputMode = opts.inputmode;\r\n el.setAttribute(\"inputmode\", opts.inputmode);\r\n }\r\n\r\n if (isSupported === true) {\r\n opts.showMaskOnFocus =\r\n opts.showMaskOnFocus &&\r\n [\"cc-number\", \"cc-exp\"].indexOf(el.autocomplete) === -1;\r\n if (iphone) {\r\n // selecting the caret shows as a selection on iphone\r\n opts.insertModeVisual = false;\r\n // disable autocorrect\r\n el.setAttribute(\"autocorrect\", \"off\");\r\n }\r\n\r\n // bind events\r\n EventRuler.on(el, \"submit\", EventHandlers.submitEvent);\r\n EventRuler.on(el, \"reset\", EventHandlers.resetEvent);\r\n EventRuler.on(el, \"blur\", EventHandlers.blurEvent);\r\n EventRuler.on(el, \"focus\", EventHandlers.focusEvent);\r\n EventRuler.on(el, \"invalid\", EventHandlers.invalidEvent);\r\n EventRuler.on(el, \"click\", EventHandlers.clickEvent);\r\n EventRuler.on(el, \"mouseleave\", EventHandlers.mouseleaveEvent);\r\n EventRuler.on(el, \"mouseenter\", EventHandlers.mouseenterEvent);\r\n EventRuler.on(el, \"paste\", EventHandlers.pasteEvent);\r\n EventRuler.on(el, \"cut\", EventHandlers.cutEvent);\r\n EventRuler.on(el, \"complete\", opts.oncomplete);\r\n EventRuler.on(el, \"incomplete\", opts.onincomplete);\r\n EventRuler.on(el, \"cleared\", opts.oncleared);\r\n if (opts.inputEventOnly !== true) {\r\n EventRuler.on(el, \"keydown\", EventHandlers.keyEvent);\r\n }\r\n if (mobile || opts.inputEventOnly) {\r\n el.removeAttribute(\"maxLength\");\r\n }\r\n EventRuler.on(el, \"input\", EventHandlers.inputFallBackEvent);\r\n // EventRuler.on(el, \"beforeinput\", EventHandlers.beforeInputEvent); //https://github.com/w3c/input-events - to implement\r\n }\r\n EventRuler.on(el, \"setvalue\", EventHandlers.setValueEvent);\r\n\r\n // apply mask\r\n inputmask.applyMaskHook === undefined || inputmask.applyMaskHook();\r\n\r\n getBufferTemplate.call(inputmask).join(\"\"); // initialize the buffer and getmasklength\r\n inputmask.undoValue = inputmask._valueGet(true);\r\n const activeElement = el.getRootNode().activeElement;\r\n if (\r\n el.inputmask._valueGet(true) !== \"\" ||\r\n opts.clearMaskOnLostFocus === false ||\r\n activeElement === el\r\n ) {\r\n applyInputValue(el, el.inputmask._valueGet(true));\r\n let buffer = getBuffer.call(inputmask).slice();\r\n if (isComplete.call(inputmask, buffer) === false) {\r\n if (opts.clearIncomplete) {\r\n resetMaskSet.call(inputmask, false);\r\n }\r\n }\r\n if (opts.clearMaskOnLostFocus && activeElement !== el) {\r\n if (getLastValidPosition.call(inputmask) === -1) {\r\n buffer = [];\r\n } else {\r\n clearOptionalTail.call(inputmask, buffer);\r\n }\r\n }\r\n if (\r\n opts.clearMaskOnLostFocus === false ||\r\n (opts.showMaskOnFocus && activeElement === el) ||\r\n el.inputmask._valueGet(true) !== \"\"\r\n ) {\r\n writeBuffer(el, buffer);\r\n }\r\n if (activeElement === el) {\r\n // position the caret when in focus\r\n caret.call(\r\n inputmask,\r\n el,\r\n seekNext.call(inputmask, getLastValidPosition.call(inputmask))\r\n );\r\n } else {\r\n caret.call(inputmask, el, 0);\r\n }\r\n }\r\n }\r\n}\r\n", "import $ from \"./dependencyLibs/inputmask.dependencyLib\";\r\nimport { escapeRegex } from \"./escapeRegex\";\r\nimport Inputmask from \"./inputmask\";\r\nimport MaskToken from \"./masktoken\";\r\n\r\nexport { generateMaskSet, analyseMask };\r\n\r\nfunction generateMaskSet(opts, nocache) {\r\n let ms;\r\n\r\n function preProcessMask(\r\n mask,\r\n { repeat, groupmarker, quantifiermarker, keepStatic }\r\n ) {\r\n if (repeat > 0 || repeat === \"*\" || repeat === \"+\") {\r\n const repeatStart = repeat === \"*\" ? 0 : repeat === \"+\" ? 1 : repeat;\r\n if (repeatStart !== repeat) {\r\n mask =\r\n groupmarker[0] +\r\n mask +\r\n groupmarker[1] +\r\n quantifiermarker[0] +\r\n repeatStart +\r\n \",\" +\r\n repeat +\r\n quantifiermarker[1];\r\n } else {\r\n // repeat the mask n times\r\n const msk = mask;\r\n for (let i = 1; i < repeatStart; i++) {\r\n mask += msk;\r\n }\r\n }\r\n }\r\n if (keepStatic === true) {\r\n const optionalRegex = \"(.)\\\\[([^\\\\]]*)\\\\]\", // \"(?.)\\\\[(?[^\\\\]]*)\\\\]\", remove named capture group @2428\r\n maskMatches = mask.match(new RegExp(optionalRegex, \"g\"));\r\n maskMatches &&\r\n maskMatches.forEach((m, i) => {\r\n let [p1, p2] = m.split(\"[\");\r\n p2 = p2.replace(\"]\", \"\");\r\n mask = mask.replace(\r\n new RegExp(`${escapeRegex(p1)}\\\\[${escapeRegex(p2)}\\\\]`),\r\n p1.charAt(0) === p2.charAt(0)\r\n ? `(${p1}|${p1}${p2})`\r\n : `${p1}[${p2}]`\r\n );\r\n // console.log(mask);\r\n });\r\n }\r\n\r\n return mask;\r\n }\r\n\r\n function generateMask(mask, metadata, opts) {\r\n let regexMask = false;\r\n if (mask === null || mask === \"\") {\r\n regexMask = opts.regex !== null;\r\n if (regexMask) {\r\n mask = opts.regex;\r\n mask = mask.replace(/^(\\^)(.*)(\\$)$/, \"$2\");\r\n } else {\r\n regexMask = true;\r\n mask = \".*\";\r\n }\r\n }\r\n if (mask.length === 1 && opts.greedy === false && opts.repeat !== 0) {\r\n opts.placeholder = \"\";\r\n } // hide placeholder with single non-greedy mask\r\n mask = preProcessMask(mask, opts);\r\n\r\n // console.log(mask);\r\n let masksetDefinition, maskdefKey;\r\n maskdefKey = regexMask\r\n ? \"regex_\" + opts.regex\r\n : opts.numericInput\r\n ? mask.split(\"\").reverse().join(\"\")\r\n : mask;\r\n if (opts.keepStatic !== null) {\r\n // keepstatic modifies the output from the testdefinitions ~ so differentiate in the maskcache\r\n maskdefKey = \"ks_\" + opts.keepStatic + maskdefKey;\r\n }\r\n if (typeof opts.placeholder === \"object\") {\r\n // placeholder object modifies the output from the testdefinitions ~ so differentiate in the maskcache\r\n maskdefKey = \"ph_\" + JSON.stringify(opts.placeholder) + maskdefKey;\r\n }\r\n\r\n if (\r\n Inputmask.prototype.masksCache[maskdefKey] === undefined ||\r\n nocache === true\r\n ) {\r\n masksetDefinition = {\r\n mask,\r\n maskToken: Inputmask.prototype.analyseMask(mask, regexMask, opts),\r\n validPositions: [],\r\n _buffer: undefined,\r\n buffer: undefined,\r\n tests: {},\r\n excludes: {}, // excluded alternations\r\n metadata,\r\n maskLength: undefined,\r\n jitOffset: {}\r\n };\r\n if (nocache !== true) {\r\n Inputmask.prototype.masksCache[maskdefKey] = masksetDefinition;\r\n masksetDefinition = $.extend(\r\n true,\r\n {},\r\n Inputmask.prototype.masksCache[maskdefKey]\r\n );\r\n }\r\n } else {\r\n masksetDefinition = $.extend(\r\n true,\r\n {},\r\n Inputmask.prototype.masksCache[maskdefKey]\r\n );\r\n }\r\n\r\n return masksetDefinition;\r\n }\r\n\r\n if (typeof opts.mask === \"function\") {\r\n // allow mask to be a preprocessing fn - should return a valid mask\r\n opts.mask = opts.mask(opts);\r\n }\r\n if (Array.isArray(opts.mask)) {\r\n if (opts.mask.length > 1) {\r\n if (opts.keepStatic === null) {\r\n // enable by default when passing multiple masks when the option is not explicitly specified\r\n opts.keepStatic = true;\r\n }\r\n let altMask = opts.groupmarker[0];\r\n (opts.isRTL ? opts.mask.reverse() : opts.mask).forEach(function (msk) {\r\n if (altMask.length > 1) {\r\n altMask += opts.alternatormarker;\r\n }\r\n if (msk.mask !== undefined && typeof msk.mask !== \"function\") {\r\n altMask += msk.mask;\r\n } else {\r\n altMask += msk;\r\n }\r\n });\r\n altMask += opts.groupmarker[1];\r\n // console.log(altMask);\r\n return generateMask(altMask, opts.mask, opts);\r\n } else {\r\n opts.mask = opts.mask.pop();\r\n }\r\n }\r\n if (\r\n opts.mask &&\r\n opts.mask.mask !== undefined &&\r\n typeof opts.mask.mask !== \"function\"\r\n ) {\r\n ms = generateMask(opts.mask.mask, opts.mask, opts);\r\n } else {\r\n ms = generateMask(opts.mask, opts.mask, opts);\r\n }\r\n if (opts.keepStatic === null) {\r\n opts.keepStatic = false;\r\n }\r\n return ms;\r\n}\r\n\r\nfunction analyseMask(mask, regexMask, opts) {\r\n const tokenizer =\r\n /(?:[?*+]|\\{[0-9+*]+(?:,[0-9+*]*)?(?:\\|[0-9+*]*)?\\})|[^.?*+^${[]()|\\\\]+|./g,\r\n // Thx to https://github.com/slevithan/regex-colorizer for the regexTokenizer regex\r\n regexTokenizer =\r\n /\\[\\^?]?(?:[^\\\\\\]]+|\\\\[\\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,\r\n currentToken = new MaskToken(),\r\n openenings = [],\r\n maskTokens = [];\r\n let escaped = false,\r\n match,\r\n m,\r\n openingToken,\r\n currentOpeningToken,\r\n alternator,\r\n lastMatch,\r\n closeRegexGroup = false;\r\n\r\n // test definition => {fn: RegExp/function, static: true/false optionality: bool, newBlockMarker: bool, casing: null/upper/lower, def: definitionSymbol, placeholder: placeholder, mask: real maskDefinition}\r\n function insertTestDefinition(mtoken, element, position) {\r\n position = position !== undefined ? position : mtoken.matches.length;\r\n // console.log(element, position, currentToken.matches.length);\r\n // if (typeof opts.placeholder === \"string\")\r\n // \tconsole.log(opts.placeholder.charAt(currentToken.matches.length % opts.placeholder.length));\r\n let prevMatch = mtoken.matches[position - 1],\r\n flag = opts.casing ? \"i\" : \"\";\r\n if (regexMask) {\r\n if (\r\n element.indexOf(\"[\") === 0 ||\r\n (escaped && /\\\\d|\\\\s|\\\\w|\\\\p/i.test(element)) ||\r\n element === \".\"\r\n ) {\r\n if (/\\\\p\\{.*}/i.test(element)) flag += \"u\";\r\n mtoken.matches.splice(position++, 0, {\r\n fn: new RegExp(element, flag),\r\n static: false,\r\n optionality: false,\r\n newBlockMarker:\r\n prevMatch === undefined ? \"master\" : prevMatch.def !== element,\r\n casing: null,\r\n def: element,\r\n placeholder:\r\n typeof opts.placeholder === \"object\"\r\n ? opts.placeholder[currentToken.matches.length]\r\n : undefined,\r\n nativeDef: element\r\n });\r\n } else {\r\n if (escaped) element = element[element.length - 1];\r\n element.split(\"\").forEach(function (lmnt, ndx) {\r\n prevMatch = mtoken.matches[position - 1];\r\n mtoken.matches.splice(position++, 0, {\r\n fn: /[a-z]/i.test(opts.staticDefinitionSymbol || lmnt)\r\n ? new RegExp(\r\n \"[\" + (opts.staticDefinitionSymbol || lmnt) + \"]\",\r\n flag\r\n )\r\n : null,\r\n static: true,\r\n optionality: false,\r\n newBlockMarker:\r\n prevMatch === undefined\r\n ? \"master\"\r\n : prevMatch.def !== lmnt && prevMatch.static !== true,\r\n casing: null,\r\n def: opts.staticDefinitionSymbol || lmnt,\r\n placeholder:\r\n opts.staticDefinitionSymbol !== undefined\r\n ? lmnt\r\n : typeof opts.placeholder === \"object\"\r\n ? opts.placeholder[currentToken.matches.length]\r\n : undefined,\r\n nativeDef: (escaped ? \"'\" : \"\") + lmnt\r\n });\r\n });\r\n }\r\n escaped = false;\r\n } else {\r\n const maskdef =\r\n (opts.definitions && opts.definitions[element]) ||\r\n (opts.usePrototypeDefinitions &&\r\n Inputmask.prototype.definitions[element]);\r\n if (maskdef && !escaped) {\r\n if (\r\n typeof maskdef.validator === \"string\" &&\r\n /\\\\p\\{.*}/i.test(maskdef.validator)\r\n )\r\n flag += \"u\";\r\n mtoken.matches.splice(position++, 0, {\r\n fn: maskdef.validator\r\n ? typeof maskdef.validator === \"string\"\r\n ? new RegExp(maskdef.validator, flag)\r\n : new (function () {\r\n this.test = maskdef.validator;\r\n })()\r\n : /./,\r\n static: maskdef.static || false,\r\n optionality: maskdef.optional || false,\r\n defOptionality: maskdef.optional || false, // indicator for an optional from the definition\r\n newBlockMarker:\r\n prevMatch === undefined || maskdef.optional\r\n ? \"master\"\r\n : prevMatch.def !== (maskdef.definitionSymbol || element),\r\n casing: maskdef.casing,\r\n def: maskdef.definitionSymbol || element,\r\n placeholder: maskdef.placeholder,\r\n nativeDef: element,\r\n generated: maskdef.generated\r\n });\r\n } else {\r\n mtoken.matches.splice(position++, 0, {\r\n fn: /[a-z]/i.test(opts.staticDefinitionSymbol || element)\r\n ? new RegExp(\r\n \"[\" + (opts.staticDefinitionSymbol || element) + \"]\",\r\n flag\r\n )\r\n : null,\r\n static: true,\r\n optionality: false,\r\n newBlockMarker:\r\n prevMatch === undefined\r\n ? \"master\"\r\n : prevMatch.def !== element && prevMatch.static !== true,\r\n casing: null,\r\n def: opts.staticDefinitionSymbol || element,\r\n placeholder:\r\n opts.staticDefinitionSymbol !== undefined ? element : undefined,\r\n nativeDef: (escaped ? \"'\" : \"\") + element\r\n });\r\n escaped = false;\r\n }\r\n }\r\n }\r\n\r\n function verifyGroupMarker(maskToken) {\r\n if (maskToken && maskToken.matches) {\r\n maskToken.matches.forEach(function (token, ndx) {\r\n const nextToken = maskToken.matches[ndx + 1];\r\n if (\r\n (nextToken === undefined ||\r\n nextToken.matches === undefined ||\r\n nextToken.isQuantifier === false) &&\r\n token &&\r\n token.isGroup\r\n ) {\r\n // this is not a group but a normal mask => convert\r\n token.isGroup = false;\r\n if (!regexMask) {\r\n insertTestDefinition(token, opts.groupmarker[0], 0);\r\n if (token.openGroup !== true) {\r\n insertTestDefinition(token, opts.groupmarker[1]);\r\n }\r\n }\r\n }\r\n verifyGroupMarker(token);\r\n });\r\n }\r\n }\r\n\r\n function defaultCase() {\r\n if (openenings.length > 0) {\r\n currentOpeningToken = openenings[openenings.length - 1];\r\n insertTestDefinition(currentOpeningToken, m);\r\n if (currentOpeningToken.isAlternator) {\r\n // handle alternator a | b case\r\n alternator = openenings.pop();\r\n for (let mndx = 0; mndx < alternator.matches.length; mndx++) {\r\n if (alternator.matches[mndx].isGroup)\r\n alternator.matches[mndx].isGroup = false; // don't mark alternate groups as group\r\n }\r\n if (openenings.length > 0) {\r\n currentOpeningToken = openenings[openenings.length - 1];\r\n currentOpeningToken.matches.push(alternator);\r\n } else {\r\n currentToken.matches.push(alternator);\r\n }\r\n }\r\n } else {\r\n insertTestDefinition(currentToken, m);\r\n }\r\n }\r\n\r\n function reverseTokens(maskToken) {\r\n function reverseStatic(st) {\r\n if (st === opts.optionalmarker[0]) {\r\n st = opts.optionalmarker[1];\r\n } else if (st === opts.optionalmarker[1]) {\r\n st = opts.optionalmarker[0];\r\n } else if (st === opts.groupmarker[0]) {\r\n st = opts.groupmarker[1];\r\n } else if (st === opts.groupmarker[1]) st = opts.groupmarker[0];\r\n\r\n return st;\r\n }\r\n\r\n maskToken.matches = maskToken.matches.reverse();\r\n for (const match in maskToken.matches) {\r\n if (Object.prototype.hasOwnProperty.call(maskToken.matches, match)) {\r\n const intMatch = parseInt(match);\r\n if (\r\n maskToken.matches[match].isQuantifier &&\r\n maskToken.matches[intMatch + 1] &&\r\n maskToken.matches[intMatch + 1].isGroup\r\n ) {\r\n // reposition quantifier\r\n const qt = maskToken.matches[match];\r\n maskToken.matches.splice(match, 1);\r\n maskToken.matches.splice(intMatch + 1, 0, qt);\r\n }\r\n if (maskToken.matches[match].matches !== undefined) {\r\n maskToken.matches[match] = reverseTokens(maskToken.matches[match]);\r\n } else {\r\n maskToken.matches[match] = reverseStatic(maskToken.matches[match]);\r\n }\r\n }\r\n }\r\n\r\n return maskToken;\r\n }\r\n\r\n function groupify(matches) {\r\n const groupToken = new MaskToken(true);\r\n groupToken.openGroup = false;\r\n groupToken.matches = matches;\r\n return groupToken;\r\n }\r\n\r\n function closeGroup() {\r\n // Group closing\r\n openingToken = openenings.pop();\r\n openingToken.openGroup = false; // mark group as complete\r\n if (openingToken !== undefined) {\r\n if (openenings.length > 0) {\r\n currentOpeningToken = openenings[openenings.length - 1];\r\n currentOpeningToken.matches.push(openingToken);\r\n if (currentOpeningToken.isAlternator) {\r\n // handle alternator (a) | (b) case\r\n alternator = openenings.pop();\r\n for (let mndx = 0; mndx < alternator.matches.length; mndx++) {\r\n alternator.matches[mndx].isGroup = false; // don't mark alternate groups as group\r\n alternator.matches[mndx].alternatorGroup = false;\r\n }\r\n if (openenings.length > 0) {\r\n currentOpeningToken = openenings[openenings.length - 1];\r\n currentOpeningToken.matches.push(alternator);\r\n } else {\r\n currentToken.matches.push(alternator);\r\n }\r\n }\r\n } else {\r\n currentToken.matches.push(openingToken);\r\n }\r\n } else {\r\n defaultCase();\r\n }\r\n }\r\n\r\n function groupQuantifier(matches) {\r\n let lastMatch = matches.pop();\r\n if (lastMatch.isQuantifier) {\r\n lastMatch = groupify([matches.pop(), lastMatch]);\r\n }\r\n return lastMatch;\r\n }\r\n\r\n if (regexMask) {\r\n opts.optionalmarker[0] = undefined;\r\n opts.optionalmarker[1] = undefined;\r\n }\r\n // console.log(mask);\r\n while (\r\n (match = regexMask ? regexTokenizer.exec(mask) : tokenizer.exec(mask))\r\n ) {\r\n // console.log(match);\r\n m = match[0];\r\n\r\n if (regexMask) {\r\n switch (m.charAt(0)) {\r\n // Quantifier\r\n case \"?\":\r\n m = \"{0,1}\";\r\n break;\r\n case \"+\":\r\n case \"*\":\r\n m = \"{\" + m + \"}\";\r\n break;\r\n case \"|\":\r\n // regex mask alternator ex: [01][0-9]|2[0-3] => ([01][0-9]|2[0-3])\r\n if (openenings.length === 0) {\r\n // wrap the mask in a group to form a regex alternator ([01][0-9]|2[0-3])\r\n const altRegexGroup = groupify(currentToken.matches);\r\n altRegexGroup.openGroup = true;\r\n openenings.push(altRegexGroup);\r\n currentToken.matches = [];\r\n closeRegexGroup = true;\r\n }\r\n break;\r\n }\r\n switch (m) {\r\n case \"\\\\d\":\r\n m = \"[0-9]\";\r\n break;\r\n case \"\\\\p\": // Unicode Categories\r\n m += regexTokenizer.exec(mask)[0]; // {\r\n m += regexTokenizer.exec(mask)[0]; // ?}\r\n break;\r\n case \"(?:\": // non capturing group\r\n case \"(?=\": // lookahead\r\n case \"(?!\": // negative lookahead\r\n case \"(?<=\": // lookbehind\r\n case \"(? 0\r\n ? openenings[openenings.length - 1].matches\r\n : currentToken.matches;\r\n match = matches.pop();\r\n // if (match.isAlternator) { //handle quantifier in an alternation [0-9]{2}|[0-9]{3}\r\n // matches.push(match); //push back alternator\r\n // matches = match.matches; //remap target matches\r\n // var groupToken = new MaskToken(true);\r\n // var tmpMatch = matches.pop();\r\n // matches.push(groupToken); //push the group\r\n // matches = groupToken.matches;\r\n // match = tmpMatch;\r\n // }\r\n if (!match.isGroup) {\r\n match = groupify([match]);\r\n }\r\n matches.push(match);\r\n matches.push(quantifier);\r\n }\r\n break;\r\n case opts.alternatormarker:\r\n if (openenings.length > 0) {\r\n currentOpeningToken = openenings[openenings.length - 1];\r\n const subToken =\r\n currentOpeningToken.matches[currentOpeningToken.matches.length - 1];\r\n if (\r\n currentOpeningToken.openGroup && // regexp alt syntax\r\n (subToken.matches === undefined ||\r\n (subToken.isGroup === false && subToken.isAlternator === false))\r\n ) {\r\n // alternations within group\r\n lastMatch = openenings.pop();\r\n } else {\r\n lastMatch = groupQuantifier(currentOpeningToken.matches);\r\n }\r\n } else {\r\n lastMatch = groupQuantifier(currentToken.matches);\r\n }\r\n if (lastMatch.isAlternator) {\r\n openenings.push(lastMatch);\r\n } else {\r\n if (lastMatch.alternatorGroup) {\r\n alternator = openenings.pop();\r\n lastMatch.alternatorGroup = false;\r\n } else {\r\n alternator = new MaskToken(false, false, false, true);\r\n }\r\n alternator.matches.push(lastMatch);\r\n openenings.push(alternator);\r\n if (lastMatch.openGroup) {\r\n // regexp alt syntax\r\n lastMatch.openGroup = false;\r\n const alternatorGroup = new MaskToken(true);\r\n alternatorGroup.alternatorGroup = true;\r\n openenings.push(alternatorGroup);\r\n }\r\n }\r\n break;\r\n default:\r\n defaultCase();\r\n }\r\n }\r\n\r\n if (closeRegexGroup) closeGroup();\r\n\r\n while (openenings.length > 0) {\r\n openingToken = openenings.pop();\r\n currentToken.matches.push(openingToken);\r\n }\r\n if (currentToken.matches.length > 0) {\r\n verifyGroupMarker(currentToken);\r\n maskTokens.push(currentToken);\r\n }\r\n\r\n if (opts.numericInput || opts.isRTL) {\r\n reverseTokens(maskTokens[0]);\r\n }\r\n // console.log(JSON.stringify(maskTokens));\r\n return maskTokens;\r\n}\r\n", "const escapeRegexRegex = new RegExp(\r\n \"(\\\\\" +\r\n [\r\n \"/\",\r\n \".\",\r\n \"*\",\r\n \"+\",\r\n \"?\",\r\n \"|\",\r\n \"(\",\r\n \")\",\r\n \"[\",\r\n \"]\",\r\n \"{\",\r\n \"}\",\r\n \"\\\\\",\r\n \"$\",\r\n \"^\"\r\n ].join(\"|\\\\\") +\r\n \")\",\r\n \"gim\"\r\n);\r\nexport function escapeRegex(str) {\r\n return str.replace(escapeRegexRegex, \"\\\\$1\");\r\n}\r\n", "export default function (isGroup, isOptional, isQuantifier, isAlternator) {\r\n this.matches = [];\r\n this.openGroup = isGroup || false;\r\n this.alternatorGroup = false;\r\n this.isGroup = isGroup || false;\r\n this.isOptional = isOptional || false;\r\n this.isQuantifier = isQuantifier || false;\r\n this.isAlternator = isAlternator || false;\r\n this.quantifier = {\r\n min: 1,\r\n max: 1\r\n };\r\n}\r\n", "/*\r\n Input Mask plugin extensions\r\n http://github.com/RobinHerbots/inputmask\r\n Copyright (c) Robin Herbots\r\n Licensed under the MIT license\r\n */\r\nimport { escapeRegex } from \"../escapeRegex\";\r\nimport Inputmask from \"../inputmask\";\r\nimport { keyCode, keys } from \"../keycode.js\";\r\nimport { seekNext } from \"../positioning\";\r\nimport { getMaskTemplate, getTest } from \"../validation-tests\";\r\nimport \"./inputmask.date.i18n\";\r\n\r\nconst $ = Inputmask.dependencyLib;\r\n\r\nclass DateObject {\r\n constructor(mask, format, opts, inputmask) {\r\n this.mask = mask;\r\n this.format = format;\r\n this.opts = opts;\r\n this.inputmask = inputmask;\r\n this._date = new Date(1, 0, 1);\r\n this.initDateObject(mask, this.opts, this.inputmask);\r\n }\r\n\r\n get date() {\r\n if (this._date === undefined) {\r\n this._date = new Date(1, 0, 1);\r\n this.initDateObject(undefined, this.opts, this.inputmask);\r\n }\r\n return this._date;\r\n }\r\n\r\n initDateObject(mask, opts, inputmask) {\r\n let match,\r\n lastNdx = -1;\r\n getTokenizer(opts).lastIndex = 0;\r\n while ((match = getTokenizer(opts).exec(this.format))) {\r\n if (match.index >= lastNdx) {\r\n let dynMatches = /\\d+$/.exec(match[0]),\r\n fcode = dynMatches ? match[0][0] + \"x\" : match[0],\r\n value;\r\n if (mask !== undefined) {\r\n // console.log(\"mask\", mask);\r\n if (dynMatches) {\r\n const lastIndex = getTokenizer(opts).lastIndex,\r\n tokenMatch = getTokenMatch.call(\r\n inputmask,\r\n match.index,\r\n opts,\r\n inputmask && inputmask.maskset\r\n );\r\n getTokenizer(opts).lastIndex = lastIndex;\r\n value = mask.slice(0, mask.indexOf(tokenMatch.nextMatch[0]));\r\n } else {\r\n let targetSymbol = match[0][0],\r\n ndx = match.index;\r\n while (\r\n inputmask &&\r\n (opts.placeholder[\r\n `${match.index}'${\r\n getTest.call(inputmask, ndx).match.placeholder\r\n }`\r\n ] || getTest.call(inputmask, ndx).match.placeholder) ===\r\n targetSymbol\r\n ) {\r\n ndx++;\r\n }\r\n lastNdx = ndx;\r\n const targetMatchLength = ndx - match.index;\r\n value = mask.slice(\r\n 0,\r\n targetMatchLength ||\r\n (formatcode(fcode) && formatcode(fcode)[4]) ||\r\n fcode.length\r\n );\r\n }\r\n mask = mask.slice(value.length);\r\n }\r\n\r\n if (Object.prototype.hasOwnProperty.call(formatCode, fcode)) {\r\n this.setValue(\r\n this,\r\n value,\r\n fcode,\r\n formatcode(fcode)[2],\r\n formatcode(fcode)[1]\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n setValue(dateObj, value, fcode, targetProp, dateOperation) {\r\n if (value !== undefined) {\r\n switch (targetProp) {\r\n case \"ampm\":\r\n dateObj[targetProp] = value;\r\n dateObj[\"raw\" + targetProp] = value.replace(/\\s/g, \"_\");\r\n break;\r\n case \"month\":\r\n if (fcode === \"MMM\" || fcode === \"MMMM\") {\r\n fcode === \"MMM\"\r\n ? (dateObj[targetProp] = pad(\r\n i18n.monthNames\r\n .slice(0, 12)\r\n .findIndex(\r\n (item) => value.toLowerCase() === item.toLowerCase()\r\n ) + 1,\r\n 2\r\n ))\r\n : (dateObj[targetProp] = pad(\r\n i18n.monthNames\r\n .slice(12, 24)\r\n .findIndex(\r\n (item) => value.toLowerCase() === item.toLowerCase()\r\n ) + 1,\r\n 2\r\n ));\r\n dateObj[targetProp] =\r\n dateObj[targetProp] === \"00\"\r\n ? \"\"\r\n : dateObj[targetProp].toString();\r\n dateObj[\"raw\" + targetProp] = dateObj[targetProp];\r\n break;\r\n }\r\n // eslint-disable-next-line no-fallthrough\r\n default:\r\n dateObj[targetProp] = value.replace(/[^0-9]/g, \"0\");\r\n dateObj[\"raw\" + targetProp] = value.replace(/\\s/g, \"_\");\r\n }\r\n }\r\n if (dateOperation !== undefined) {\r\n let datavalue = dateObj[targetProp];\r\n if (\r\n (targetProp === \"day\" && parseInt(datavalue) === 29) ||\r\n (targetProp === \"month\" && parseInt(datavalue) === 2)\r\n ) {\r\n if (\r\n parseInt(dateObj.day) === 29 &&\r\n parseInt(dateObj.month) === 2 &&\r\n (dateObj.year === \"\" || dateObj.year === undefined)\r\n ) {\r\n // set temporary leap year in dateObj\r\n dateObj._date.setFullYear(2012, 1, 29);\r\n }\r\n }\r\n if (targetProp === \"day\") {\r\n useDateObject = true;\r\n if (parseInt(datavalue) === 0) datavalue = 1;\r\n }\r\n if (targetProp === \"month\") useDateObject = true;\r\n if (targetProp === \"year\") {\r\n useDateObject = true;\r\n if (datavalue.length < formatcode(fcode)[4])\r\n datavalue = pad(datavalue, formatcode(fcode)[4], true);\r\n }\r\n if ((datavalue !== \"\" && !isNaN(datavalue)) || targetProp === \"ampm\")\r\n dateOperation.call(dateObj._date, datavalue);\r\n }\r\n }\r\n\r\n reset() {\r\n this._date = new Date(1, 0, 1);\r\n }\r\n\r\n reInit() {\r\n this._date = undefined;\r\n // eslint-disable-next-line no-unused-expressions\r\n this.date;\r\n }\r\n}\r\n\r\nlet useDateObject = false;\r\nconst currentYear = new Date().getFullYear(),\r\n i18n = Inputmask.prototype.i18n,\r\n // supported codes for formatting\r\n // https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date-time-string-format\r\n // https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings?view=netframework-4.7\r\n // https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\r\n formatCode = {\r\n // regex, valueSetter, type, displayformatter, #entries (optional)\r\n d: [\r\n \"[1-9]|[12][0-9]|3[01]\",\r\n Date.prototype.setDate,\r\n \"day\",\r\n Date.prototype.getDate\r\n ], // Day of the month as digits; no leading zero for single-digit days.\r\n dd: [\r\n \"0[1-9]|[12][0-9]|3[01]\",\r\n Date.prototype.setDate,\r\n \"day\",\r\n function () {\r\n return pad(Date.prototype.getDate.call(this), 2);\r\n }\r\n ], // Day of the month as digits; leading zero for single-digit days.\r\n ddd: [\"\"], // Day of the week as a three-letter abbreviation.\r\n dddd: [\"\"], // Day of the week as its full name.\r\n M: [\r\n \"[1-9]|1[012]\",\r\n function (val) {\r\n let mval = val ? parseInt(val) : 0;\r\n if (mval > 0) mval--;\r\n return Date.prototype.setMonth.call(this, mval);\r\n },\r\n \"month\",\r\n function () {\r\n return Date.prototype.getMonth.call(this) + 1;\r\n }\r\n ], // Month as digits; no leading zero for single-digit months.\r\n MM: [\r\n \"0[1-9]|1[012]\",\r\n function (val) {\r\n let mval = val ? parseInt(val) : 0;\r\n if (mval > 0) mval--;\r\n return Date.prototype.setMonth.call(this, mval);\r\n },\r\n \"month\",\r\n function () {\r\n return pad(Date.prototype.getMonth.call(this) + 1, 2);\r\n }\r\n ], // Month as digits; leading zero for single-digit months.\r\n MMM: [\r\n i18n.monthNames.slice(0, 12).join(\"|\"),\r\n function (val) {\r\n const mval = i18n.monthNames\r\n .slice(0, 12)\r\n .findIndex((item) => val.toLowerCase() === item.toLowerCase());\r\n return mval !== -1 ? Date.prototype.setMonth.call(this, mval) : false;\r\n },\r\n \"month\",\r\n function () {\r\n return i18n.monthNames.slice(0, 12)[Date.prototype.getMonth.call(this)];\r\n }\r\n ], // Month as a three-letter abbreviation.\r\n MMMM: [\r\n i18n.monthNames.slice(12, 24).join(\"|\"),\r\n function (val) {\r\n const mval = i18n.monthNames\r\n .slice(12, 24)\r\n .findIndex((item) => val.toLowerCase() === item.toLowerCase());\r\n return mval !== -1 ? Date.prototype.setMonth.call(this, mval) : false;\r\n },\r\n \"month\",\r\n function () {\r\n return i18n.monthNames.slice(12, 24)[\r\n Date.prototype.getMonth.call(this)\r\n ];\r\n }\r\n ], // Month as its full name.\r\n yy: [\r\n \"[0-9]{2}\",\r\n function (val) {\r\n const centuryPart = new Date().getFullYear().toString().slice(0, 2);\r\n Date.prototype.setFullYear.call(this, `${centuryPart}${val}`);\r\n },\r\n \"year\",\r\n function () {\r\n return pad(Date.prototype.getFullYear.call(this), 2);\r\n },\r\n 2\r\n ], // Year as last two digits; leading zero for years less than 10.\r\n yyyy: [\r\n \"[0-9]{4}\",\r\n Date.prototype.setFullYear,\r\n \"year\",\r\n function () {\r\n return pad(Date.prototype.getFullYear.call(this), 4);\r\n },\r\n 4\r\n ],\r\n h: [\r\n \"[1-9]|1[0-2]\",\r\n Date.prototype.setHours,\r\n \"hours\",\r\n Date.prototype.getHours\r\n ], // Hours; no leading zero for single-digit hours (12-hour clock).\r\n hh: [\r\n \"0[1-9]|1[0-2]\",\r\n Date.prototype.setHours,\r\n \"hours\",\r\n function () {\r\n return pad(Date.prototype.getHours.call(this), 2);\r\n }\r\n ], // Hours; leading zero for single-digit hours (12-hour clock).\r\n hx: [\r\n function (x) {\r\n return `[0-9]{${x}}`;\r\n },\r\n Date.prototype.setHours,\r\n \"hours\",\r\n function (x) {\r\n return Date.prototype.getHours;\r\n }\r\n ], // Hours; no limit; set maximum digits\r\n H: [\r\n \"1?[0-9]|2[0-3]\",\r\n Date.prototype.setHours,\r\n \"hours\",\r\n Date.prototype.getHours\r\n ], // Hours; no leading zero for single-digit hours (24-hour clock).\r\n HH: [\r\n \"0[0-9]|1[0-9]|2[0-3]\",\r\n Date.prototype.setHours,\r\n \"hours\",\r\n function () {\r\n return pad(Date.prototype.getHours.call(this), 2);\r\n }\r\n ], // Hours; leading zero for single-digit hours (24-hour clock).\r\n Hx: [\r\n function (x) {\r\n return `[0-9]{${x}}`;\r\n },\r\n Date.prototype.setHours,\r\n \"hours\",\r\n function (x) {\r\n return function () {\r\n return pad(Date.prototype.getHours.call(this), x);\r\n };\r\n }\r\n ], // Hours; no limit; set maximum digits\r\n m: [\r\n \"[1-5]?[0-9]\",\r\n Date.prototype.setMinutes,\r\n \"minutes\",\r\n Date.prototype.getMinutes\r\n ], // Minutes; no leading zero for single-digit minutes. Uppercase M unlike CF timeFormat's m to avoid conflict with months.\r\n mm: [\r\n \"0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]\",\r\n Date.prototype.setMinutes,\r\n \"minutes\",\r\n function () {\r\n return pad(Date.prototype.getMinutes.call(this), 2);\r\n }\r\n ], // Minutes; leading zero for single-digit minutes. Uppercase MM unlike CF timeFormat's mm to avoid conflict with months.\r\n s: [\r\n \"[1-5]?[0-9]\",\r\n Date.prototype.setSeconds,\r\n \"seconds\",\r\n Date.prototype.getSeconds\r\n ], // Seconds; no leading zero for single-digit seconds.\r\n ss: [\r\n \"0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]\",\r\n Date.prototype.setSeconds,\r\n \"seconds\",\r\n function () {\r\n return pad(Date.prototype.getSeconds.call(this), 2);\r\n }\r\n ], // Seconds; leading zero for single-digit seconds.\r\n l: [\r\n \"[0-9]{3}\",\r\n Date.prototype.setMilliseconds,\r\n \"milliseconds\",\r\n function () {\r\n return pad(Date.prototype.getMilliseconds.call(this), 3);\r\n },\r\n 3\r\n ], // Milliseconds. 3 digits.\r\n L: [\r\n \"[0-9]{2}\",\r\n Date.prototype.setMilliseconds,\r\n \"milliseconds\",\r\n function () {\r\n return pad(Date.prototype.getMilliseconds.call(this), 2);\r\n },\r\n 2\r\n ], // Milliseconds. 2 digits.\r\n t: [\"[ap]\", setAMPM, \"ampm\", getAMPM, 1], // Lowercase, single-character time marker string: a or p.\r\n tt: [\"[ap]m\", setAMPM, \"ampm\", getAMPM, 2], // two-character time marker string: am or pm.\r\n T: [\"[AP]\", setAMPM, \"ampm\", getAMPM, 1], // single-character time marker string: A or P.\r\n TT: [\"[AP]M\", setAMPM, \"ampm\", getAMPM, 2], // two-character time marker string: AM or PM.\r\n Z: [\".*\", undefined, \"Z\", getTimeZoneAbbreviated], // US timezone abbreviation, e.g. EST or MDT. With non-US timezones or in the Opera browser, the GMT/UTC offset is returned, e.g. GMT-0500\r\n o: [\"\"], // GMT/UTC timezone offset, e.g. -0500 or +0230.\r\n S: [\"\"] // The date's ordinal suffix (st, nd, rd, or th).\r\n },\r\n formatCodeAlias = {\r\n D: \"d\",\r\n DD: \"dd\",\r\n DDD: \"ddd\",\r\n DDDD: \"dddd\",\r\n mmm: \"MMM\",\r\n mmmm: \"MMMM\",\r\n YY: \"yy\",\r\n YYYY: \"yyyy\",\r\n sss: \"L\"\r\n },\r\n formatAlias = {\r\n isoDate: \"yyyy-MM-dd\", // 2007-06-09\r\n isoTime: \"HH:mm:ss\", // 17:46:21\r\n isoDateTime: \"yyyy-MM-dd\\\\THH:mm:ss\", // 2007-06-09T17:46:21\r\n isoUtcDateTime: \"UTC:yyyy-MM-dd\\\\THH:mm:ss\\\\Z\" // 2007-06-09T22:46:21Z\r\n };\r\n\r\nfunction setAMPM(value) {\r\n const hours = this.getHours();\r\n if (value.toLowerCase().includes(\"p\")) {\r\n this.setHours(hours + 12);\r\n // console.log(\"setAMPM + 12\");\r\n } else if (value.toLowerCase().includes(\"a\") && hours >= 12) {\r\n this.setHours(hours - 12);\r\n }\r\n}\r\n\r\nfunction getAMPM() {\r\n let date = this,\r\n hours = date.getHours();\r\n hours = hours || 12;\r\n return hours >= 12 ? \"PM\" : \"AM\";\r\n}\r\n\r\nfunction getTimeZoneAbbreviated() {\r\n // not perfect, but ok for now\r\n let date = this,\r\n { 1: tz } = date.toString().match(/\\((.+)\\)/);\r\n if (tz.includes(\" \")) {\r\n tz = tz.replace(\"-\", \" \").toUpperCase();\r\n tz = tz\r\n .split(\" \")\r\n .map(([first]) => first)\r\n .join(\"\");\r\n }\r\n return tz;\r\n}\r\n\r\nfunction formatcode(match) {\r\n const fcMatch = formatCodeAlias[match] || match,\r\n dynMatches = /\\d+$/.exec(fcMatch);\r\n if (dynMatches && dynMatches[0] !== undefined) {\r\n const fcode = formatCode[fcMatch[0] + \"x\"].slice(\"\");\r\n fcode[0] = fcode[0](dynMatches[0]);\r\n fcode[3] = fcode[3](dynMatches[0]);\r\n\r\n return fcode;\r\n } else if (formatCode[fcMatch]) {\r\n return formatCode[fcMatch];\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\nfunction getTokenizer(opts) {\r\n if (!opts.tokenizer) {\r\n const tokens = [],\r\n dyntokens = [],\r\n formatCodeKeys = Object.keys(formatCode).concat(\r\n Object.keys(formatCodeAlias)\r\n );\r\n\r\n for (const ndx of formatCodeKeys) {\r\n if (/\\.*x$/.test(ndx)) {\r\n const dynToken = ndx[0] + \"\\\\d+\";\r\n if (dyntokens.indexOf(dynToken) === -1) {\r\n dyntokens.push(dynToken);\r\n }\r\n } else if (tokens.indexOf(ndx[0]) === -1) {\r\n tokens.push(ndx[0]);\r\n }\r\n }\r\n opts.tokenizer =\r\n \"(\" +\r\n (dyntokens.length > 0 ? dyntokens.join(\"|\") + \"|\" : \"\") +\r\n tokens.join(\"+|\") +\r\n \"+)+?|.\";\r\n opts.tokenizer = new RegExp(opts.tokenizer, \"g\");\r\n }\r\n\r\n return opts.tokenizer;\r\n}\r\n\r\nfunction prefillYear(dateParts, currentResult, opts) {\r\n if (dateParts.year !== dateParts.rawyear) {\r\n const crrntyear = currentYear.toString(),\r\n enteredPart = dateParts.rawyear.replace(/[^0-9]/g, \"\"),\r\n currentYearPart = crrntyear.slice(0, enteredPart.length),\r\n currentYearNextPart = crrntyear.slice(enteredPart.length);\r\n if (enteredPart.length === 2 && enteredPart === currentYearPart) {\r\n const entryCurrentYear = new Date(\r\n currentYear,\r\n dateParts.month - 1,\r\n dateParts.day\r\n );\r\n if (\r\n dateParts.day == entryCurrentYear.getDate() &&\r\n (!opts.max || opts.max.date.getTime() >= entryCurrentYear.getTime())\r\n ) {\r\n // update dateParts\r\n dateParts.date.setFullYear(currentYear);\r\n dateParts.year = crrntyear;\r\n // update result\r\n currentResult.insert = [\r\n {\r\n pos: currentResult.pos + 1,\r\n c: currentYearNextPart[0]\r\n },\r\n {\r\n pos: currentResult.pos + 2,\r\n c: currentYearNextPart[1]\r\n }\r\n ];\r\n }\r\n }\r\n }\r\n\r\n return currentResult;\r\n}\r\n\r\nfunction isValidDate(dateParts, currentResult, opts) {\r\n const inputmask = this;\r\n if (!useDateObject) return true;\r\n if (\r\n dateParts.rawday === undefined ||\r\n (!isFinite(dateParts.rawday) &&\r\n new Date(\r\n dateParts.date.getFullYear(),\r\n isFinite(dateParts.rawmonth)\r\n ? dateParts.month\r\n : dateParts.date.getMonth() + 1,\r\n 0\r\n ).getDate() >= dateParts.day) ||\r\n (dateParts.day == \"29\" &&\r\n (!isFinite(dateParts.rawyear) ||\r\n dateParts.rawyear === undefined ||\r\n dateParts.rawyear === \"\")) ||\r\n new Date(\r\n dateParts.date.getFullYear(),\r\n isFinite(dateParts.rawmonth)\r\n ? dateParts.month\r\n : dateParts.date.getMonth() + 1,\r\n 0\r\n ).getDate() >= dateParts.day\r\n ) {\r\n return currentResult;\r\n } else {\r\n // take corrective action if possible\r\n if (dateParts.day == \"29\") {\r\n const tokenMatch = getTokenMatch.call(\r\n inputmask,\r\n currentResult.pos,\r\n opts,\r\n inputmask.maskset\r\n );\r\n if (\r\n tokenMatch.targetMatch &&\r\n [\"yyyy\", \"YYYY\"].includes(tokenMatch.targetMatch[0]) &&\r\n currentResult.pos - tokenMatch.targetMatchIndex === 2\r\n ) {\r\n currentResult.remove = currentResult.pos + 1;\r\n return currentResult;\r\n }\r\n } else if (\r\n dateParts.date.getMonth() == 2 &&\r\n dateParts.day == \"30\" &&\r\n currentResult.c !== undefined\r\n ) {\r\n dateParts.day = \"03\";\r\n dateParts.date.setDate(3);\r\n dateParts.date.setMonth(1);\r\n currentResult.insert = [\r\n { pos: currentResult.pos, c: \"0\" },\r\n { pos: currentResult.pos + 1, c: currentResult.c }\r\n ];\r\n currentResult.caret = seekNext.call(this, currentResult.pos + 1);\r\n return currentResult;\r\n }\r\n return false;\r\n }\r\n}\r\n\r\nfunction isDateInRange(dateParts, result, opts, maskset, fromCheckval) {\r\n if (!result) return result;\r\n if (result && opts.min) {\r\n if (\r\n /* useDateObject && (dateParts[\"year\"] === undefined || dateParts[\"yearSet\"]) && */ !isNaN(\r\n opts.min.date.getTime()\r\n )\r\n ) {\r\n let match;\r\n dateParts.reset();\r\n getTokenizer(opts).lastIndex = 0;\r\n while ((match = getTokenizer(opts).exec(opts.inputFormat))) {\r\n var fcode;\r\n if ((fcode = formatcode(match[0]))) {\r\n if (fcode[3]) {\r\n let setFn = fcode[1],\r\n current = dateParts[fcode[2]],\r\n minVal = opts.min[fcode[2]],\r\n maxVal = opts.max ? opts.max[fcode[2]] : minVal + 1,\r\n curVal = [],\r\n forceCurrentValue = false;\r\n for (let i = 0; i < minVal.length; i++) {\r\n if (\r\n maskset.validPositions[i + match.index] === undefined &&\r\n !forceCurrentValue\r\n ) {\r\n if (i + match.index == 0 && current[i] < minVal[i]) {\r\n curVal[i] = current[i];\r\n forceCurrentValue = true;\r\n } else {\r\n curVal[i] = minVal[i];\r\n }\r\n // ADD +1 to whole\r\n if (\r\n fcode[2] === \"year\" &&\r\n current.length - 1 == i &&\r\n minVal != maxVal\r\n )\r\n curVal = (parseInt(curVal.join(\"\")) + 1).toString().split(\"\");\r\n if (\r\n fcode[2] === \"ampm\" &&\r\n minVal != maxVal &&\r\n opts.min.date.getTime() > dateParts.date.getTime()\r\n )\r\n curVal[i] = maxVal[i];\r\n } else {\r\n curVal[i] = current[i];\r\n forceCurrentValue = forceCurrentValue || current[i] > minVal[i];\r\n }\r\n }\r\n\r\n setFn.call(dateParts._date, curVal.join(\"\"));\r\n }\r\n }\r\n }\r\n\r\n result = opts.min.date.getTime() <= dateParts.date.getTime();\r\n dateParts.reInit();\r\n }\r\n }\r\n\r\n if (result && opts.max) {\r\n if (!isNaN(opts.max.date.getTime())) {\r\n result = opts.max.date.getTime() >= dateParts.date.getTime();\r\n }\r\n }\r\n return result;\r\n}\r\n\r\n// parse the given format and return a mask pattern\r\n// when a dateObjValue is passed a datestring in the requested format is returned\r\nfunction parse(format, dateObjValue, opts) {\r\n // parse format to regex string\r\n let mask = \"\",\r\n match,\r\n fcode,\r\n ndx = 0,\r\n escaped = false;\r\n const placeHolder = {};\r\n getTokenizer(opts).lastIndex = 0;\r\n while ((match = getTokenizer(opts).exec(format))) {\r\n if (match[0] === opts.escapeChar) {\r\n escaped = true;\r\n } else {\r\n if (dateObjValue === undefined) {\r\n if (!escaped && (fcode = formatcode(match[0]))) {\r\n mask += \"(\" + fcode[0] + \")\";\r\n // map placeholder to placeholder object and set placeholder mappings\r\n if (opts.placeholder && opts.placeholder !== \"\") {\r\n placeHolder[ndx] =\r\n opts.placeholder[match.index % opts.placeholder.length];\r\n // internal use of datetime alias\r\n placeHolder[\r\n `${match.index}'${\r\n opts.placeholder[match.index % opts.placeholder.length]\r\n }`\r\n ] = match[0].charAt(0);\r\n } else {\r\n placeHolder[ndx] = match[0].charAt(0);\r\n }\r\n } else {\r\n switch (match[0]) {\r\n case \"[\":\r\n mask += \"(\";\r\n break;\r\n case \"]\":\r\n mask += \")?\";\r\n break;\r\n default:\r\n mask += escapeRegex(match[0]);\r\n placeHolder[ndx] = match[0].charAt(0);\r\n }\r\n }\r\n } else {\r\n if (!escaped && (fcode = formatcode(match[0]))) {\r\n if (fcode[3]) {\r\n const getFn = fcode[3];\r\n mask += getFn.call(dateObjValue.date);\r\n } else if (fcode[2] && dateObjValue[\"raw\" + fcode[2]] !== undefined) {\r\n mask += dateObjValue[\"raw\" + fcode[2]];\r\n } else {\r\n mask += match[0];\r\n }\r\n } else {\r\n mask += match[0];\r\n }\r\n }\r\n ndx++;\r\n escaped = false;\r\n }\r\n }\r\n if (dateObjValue === undefined) {\r\n // console.log(JSON.stringify(placeHolder));\r\n opts.placeholder = placeHolder;\r\n }\r\n return mask;\r\n}\r\n\r\n// padding function\r\nfunction pad(val, len, right) {\r\n val = String(val);\r\n len = len || 2;\r\n while (val.length < len) val = right ? val + \"0\" : \"0\" + val;\r\n return val;\r\n}\r\n\r\nfunction analyseMask(mask, format, opts) {\r\n const inputmask = this;\r\n\r\n if (typeof mask === \"string\") {\r\n return new DateObject(mask, format, opts, inputmask);\r\n } else if (\r\n mask &&\r\n typeof mask === \"object\" &&\r\n Object.prototype.hasOwnProperty.call(mask, \"date\")\r\n ) {\r\n return mask;\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction importDate(dateObj, opts) {\r\n return parse(opts.inputFormat, { date: dateObj }, opts);\r\n}\r\n\r\nfunction getTokenMatch(pos, opts, maskset) {\r\n let inputmask = this,\r\n calcPos = 0,\r\n targetMatch,\r\n match,\r\n matchLength = 0;\r\n\r\n getTokenizer(opts).lastIndex = 0;\r\n while ((match = getTokenizer(opts).exec(opts.inputFormat))) {\r\n // console.log(`match.index ${match.index}`);\r\n const dynMatches = /\\d+$/.exec(match[0]);\r\n if (dynMatches) {\r\n matchLength = parseInt(dynMatches[0]);\r\n } else {\r\n let targetSymbol = match[0][0],\r\n ndx = calcPos;\r\n while (\r\n inputmask &&\r\n (opts.placeholder[\r\n `${match.index}'${getTest.call(inputmask, ndx).match.placeholder}`\r\n ] || getTest.call(inputmask, ndx).match.placeholder) === targetSymbol\r\n ) {\r\n ndx++;\r\n }\r\n matchLength = ndx - calcPos;\r\n if (matchLength === 0) matchLength = match[0].length;\r\n }\r\n\r\n calcPos += matchLength;\r\n // console.log(`calcPos ${calcPos}`);\r\n\r\n if (calcPos >= pos + 1) {\r\n let masksetHint = \"\";\r\n if (maskset && maskset.tests[pos]) {\r\n const filteredPlaceholders = Object.keys(opts.placeholder).filter(\r\n (value) => {\r\n for (let i = match.index - 1; i < calcPos; i++) {\r\n if (value === `${i}'${maskset.tests[pos][0].match.placeholder}`) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n );\r\n\r\n masksetHint =\r\n filteredPlaceholders.length > 0\r\n ? opts.placeholder[filteredPlaceholders[0]]\r\n : maskset.tests[pos][0].match.placeholder;\r\n }\r\n // console.log(masksetHint);\r\n if (match[0].indexOf(masksetHint) !== -1) {\r\n // console.log(`match ${masksetHint} ${calcPos} >= ${pos + 1}`);\r\n targetMatch = match;\r\n match = getTokenizer(opts).exec(opts.inputFormat);\r\n break;\r\n } else {\r\n // console.log(`no match ${masksetHint} ${calcPos} >= ${pos + 1}`);\r\n }\r\n }\r\n }\r\n return {\r\n targetMatchIndex: calcPos - matchLength,\r\n nextMatch: match,\r\n targetMatch\r\n };\r\n}\r\n\r\nInputmask.extendAliases({\r\n datetime: {\r\n mask: function (opts) {\r\n // do not allow numeric input in datetime alias\r\n opts.numericInput = false;\r\n\r\n // localize\r\n formatCode.S = i18n.ordinalSuffix.join(\"|\");\r\n\r\n opts.inputFormat = formatAlias[opts.inputFormat] || opts.inputFormat; // resolve possible formatAlias\r\n if (opts.repeat) {\r\n opts.repeat = parseInt(opts.repeat.toString());\r\n if (opts.repeat > 0) {\r\n let inputFormat = \"\";\r\n for (let i = 0; i < opts.repeat; i++) {\r\n inputFormat = inputFormat + opts.inputFormat;\r\n }\r\n opts.inputFormat = inputFormat;\r\n opts.repeat = 0;\r\n }\r\n }\r\n opts.displayFormat =\r\n formatAlias[opts.displayFormat] ||\r\n opts.displayFormat ||\r\n opts.inputFormat; // resolve possible formatAlias\r\n opts.outputFormat =\r\n formatAlias[opts.outputFormat] || opts.outputFormat || opts.inputFormat; // resolve possible formatAlias\r\n // opts.placeholder = opts.placeholder !== \"\" ? opts.placeholder : opts.inputFormat.replace(/[[\\]]/, \"\");\r\n opts.regex = parse(opts.inputFormat, undefined, opts);\r\n // console.log(\"inputFormat\", opts.regex);\r\n opts.min = analyseMask(opts.min, opts.inputFormat, opts);\r\n opts.max = analyseMask(opts.max, opts.inputFormat, opts);\r\n return null; // migrate to regex mask\r\n },\r\n placeholder: \"\", // set default as none (~ auto); when a custom placeholder is passed it will be used\r\n inputFormat: \"isoDateTime\", // format used to input the date\r\n displayFormat: null, // visual format when the input looses focus\r\n outputFormat: null, // unmasking format\r\n min: null, // needs to be in the same format as the inputfornat\r\n max: null, // needs to be in the same format as the inputfornat,\r\n skipOptionalPartCharacter: \"\",\r\n preValidation: function (\r\n buffer,\r\n pos,\r\n c,\r\n isSelection,\r\n opts,\r\n maskset,\r\n caretPos,\r\n strict\r\n ) {\r\n const inputmask = this;\r\n if (strict) return true;\r\n if (isNaN(c) && buffer[pos] !== c) {\r\n const tokenMatch = getTokenMatch.call(inputmask, pos, opts, maskset);\r\n if (\r\n tokenMatch.nextMatch &&\r\n tokenMatch.nextMatch[0] === c &&\r\n tokenMatch.targetMatch[0].length > 1\r\n ) {\r\n const validator = formatcode(tokenMatch.targetMatch[0])[0];\r\n if (new RegExp(validator).test(\"0\" + buffer[pos - 1])) {\r\n buffer[pos] = buffer[pos - 1];\r\n buffer[pos - 1] = \"0\";\r\n return {\r\n fuzzy: true,\r\n buffer,\r\n refreshFromBuffer: { start: pos - 1, end: pos + 1 },\r\n pos: pos + 1\r\n };\r\n }\r\n }\r\n }\r\n return true;\r\n },\r\n postValidation: function (\r\n buffer,\r\n pos,\r\n c,\r\n currentResult,\r\n opts,\r\n maskset,\r\n strict,\r\n fromCheckval\r\n ) {\r\n const inputmask = this;\r\n\r\n if (strict) return true;\r\n let tokenMatch, validator;\r\n if (currentResult === false) {\r\n // try some shifting\r\n tokenMatch = getTokenMatch.call(inputmask, pos + 1, opts, maskset);\r\n if (\r\n tokenMatch.targetMatch &&\r\n tokenMatch.targetMatchIndex === pos &&\r\n tokenMatch.targetMatch[0].length > 1 &&\r\n formatcode(tokenMatch.targetMatch[0]) !== undefined\r\n ) {\r\n validator = formatcode(tokenMatch.targetMatch[0])[0];\r\n } else {\r\n tokenMatch = getTokenMatch.call(inputmask, pos + 2, opts, maskset);\r\n if (\r\n tokenMatch.targetMatch &&\r\n tokenMatch.targetMatchIndex === pos + 1 &&\r\n tokenMatch.targetMatch[0].length > 1 &&\r\n formatcode(tokenMatch.targetMatch[0]) !== undefined\r\n ) {\r\n validator = formatcode(tokenMatch.targetMatch[0]);\r\n }\r\n }\r\n if (validator !== undefined) {\r\n // correct position ~ pos in front of shifted targetMatch\r\n pos = tokenMatch.targetMatchIndex;\r\n if (\r\n maskset.validPositions[pos + 1] !== undefined &&\r\n new RegExp(validator).test(c + \"0\")\r\n ) {\r\n buffer[pos] = c;\r\n buffer[pos + 1] = \"0\";\r\n currentResult = {\r\n // insert: [{pos: pos, c: \"0\"}, {pos: pos + 1, c: c}],\r\n pos: pos + 2, // this will triggeer a refreshfrombuffer\r\n caret: pos + 1\r\n };\r\n } else if (new RegExp(validator).test(\"0\" + c)) {\r\n buffer[pos] = \"0\";\r\n buffer[pos + 1] = c;\r\n currentResult = {\r\n // insert: [{pos: pos, c: \"0\"}, {pos: pos + 1, c: c}],\r\n pos: pos + 2 // this will triggeer a refreshfrombuffer\r\n };\r\n }\r\n }\r\n\r\n if (currentResult === false) return currentResult;\r\n }\r\n\r\n if (currentResult.fuzzy) {\r\n buffer = currentResult.buffer;\r\n pos = currentResult.pos;\r\n }\r\n\r\n // full validate target\r\n tokenMatch = getTokenMatch.call(inputmask, pos, opts, maskset);\r\n if (\r\n tokenMatch.targetMatch &&\r\n tokenMatch.targetMatch[0] &&\r\n formatcode(tokenMatch.targetMatch[0]) !== undefined\r\n ) {\r\n const fcode = formatcode(tokenMatch.targetMatch[0]);\r\n validator = fcode[0];\r\n const part = buffer.slice(\r\n tokenMatch.targetMatchIndex,\r\n tokenMatch.targetMatchIndex + tokenMatch.targetMatch[0].length\r\n );\r\n if (\r\n new RegExp(validator).test(part.join(\"\")) === false &&\r\n tokenMatch.targetMatch[0].length === 2 &&\r\n maskset.validPositions[tokenMatch.targetMatchIndex] &&\r\n maskset.validPositions[tokenMatch.targetMatchIndex + 1]\r\n ) {\r\n maskset.validPositions[tokenMatch.targetMatchIndex + 1].input = \"0\";\r\n }\r\n if (fcode[2] == \"year\") {\r\n const _buffer = getMaskTemplate.call(\r\n inputmask,\r\n false,\r\n 1,\r\n undefined,\r\n true\r\n );\r\n for (let i = pos + 1; i < buffer.length; i++) {\r\n buffer[i] = _buffer[i];\r\n maskset.validPositions.splice(pos + 1, 1);\r\n }\r\n }\r\n }\r\n\r\n let result = currentResult,\r\n dateParts = analyseMask.call(\r\n inputmask,\r\n buffer.join(\"\"),\r\n opts.inputFormat,\r\n opts\r\n );\r\n if (result && !isNaN(dateParts.date.getTime())) {\r\n // check for a valid date ~ an invalid date returns NaN which isn't equal\r\n if (opts.prefillYear) result = prefillYear(dateParts, result, opts);\r\n result = isValidDate.call(inputmask, dateParts, result, opts);\r\n result = isDateInRange(dateParts, result, opts, maskset, fromCheckval);\r\n }\r\n\r\n if (pos !== undefined && result && currentResult.pos !== pos) {\r\n return {\r\n buffer: parse(opts.inputFormat, dateParts, opts).split(\"\"),\r\n refreshFromBuffer: { start: pos, end: currentResult.pos },\r\n pos:\r\n currentResult.caret !== undefined\r\n ? currentResult.caret\r\n : currentResult.pos // correct caret position\r\n };\r\n }\r\n\r\n return result;\r\n },\r\n onKeyDown: function (e, buffer, caretPos, opts) {\r\n const input = this;\r\n if (e.ctrlKey && e.key === keys.ArrowRight) {\r\n input.inputmask._valueSet(importDate(new Date(), opts));\r\n $(input).trigger(\"setvalue\");\r\n }\r\n },\r\n onUnMask: function (maskedValue, unmaskedValue, opts) {\r\n const inputmask = this;\r\n return unmaskedValue\r\n ? parse(\r\n opts.outputFormat,\r\n analyseMask.call(inputmask, maskedValue, opts.inputFormat, opts),\r\n opts\r\n )\r\n : unmaskedValue;\r\n },\r\n casing: \"follow\",\r\n onBeforeMask: function (initialValue, opts) {\r\n if (Object.prototype.toString.call(initialValue) === \"[object Date]\") {\r\n initialValue = importDate(initialValue, opts);\r\n }\r\n\r\n return initialValue;\r\n },\r\n insertMode: false,\r\n insertModeVisual: false,\r\n shiftPositions: false,\r\n keepStatic: false,\r\n inputmode: \"numeric\",\r\n prefillYear: true // Allows to disable prefill for datetime year.\r\n }\r\n});\r\n", "/*\r\n Input Mask plugin extensions\r\n http://github.com/RobinHerbots/inputmask\r\n Copyright (c) Robin Herbots\r\n Licensed under the MIT license\r\n */\r\nimport Inputmask from \"../inputmask\";\r\n\r\nconst $ = Inputmask.dependencyLib;\r\n\r\n$.extend(true, Inputmask.prototype.i18n, {\r\n dayNames: [\r\n \"Mon\",\r\n \"Tue\",\r\n \"Wed\",\r\n \"Thu\",\r\n \"Fri\",\r\n \"Sat\",\r\n \"Sun\",\r\n \"Monday\",\r\n \"Tuesday\",\r\n \"Wednesday\",\r\n \"Thursday\",\r\n \"Friday\",\r\n \"Saturday\",\r\n \"Sunday\"\r\n ],\r\n monthNames: [\r\n \"Jan\",\r\n \"Feb\",\r\n \"Mar\",\r\n \"Apr\",\r\n \"May\",\r\n \"Jun\",\r\n \"Jul\",\r\n \"Aug\",\r\n \"Sep\",\r\n \"Oct\",\r\n \"Nov\",\r\n \"Dec\",\r\n \"January\",\r\n \"February\",\r\n \"March\",\r\n \"April\",\r\n \"May\",\r\n \"June\",\r\n \"July\",\r\n \"August\",\r\n \"September\",\r\n \"October\",\r\n \"November\",\r\n \"December\"\r\n ],\r\n ordinalSuffix: [\"st\", \"nd\", \"rd\", \"th\"]\r\n});\r\n", "/*\r\n Input Mask plugin extensions\r\n http://github.com/RobinHerbots/inputmask\r\n Copyright (c) Robin Herbots\r\n Licensed under the MIT license\r\n */\r\nimport { escapeRegex } from \"../escapeRegex\";\r\nimport Inputmask from \"../inputmask\";\r\nimport { keys } from \"../keycode\";\r\nimport { seekNext } from \"../positioning\";\r\n\r\nconst $ = Inputmask.dependencyLib;\r\n\r\nfunction autoEscape(txt, opts) {\r\n let escapedTxt = \"\";\r\n for (let i = 0; i < txt.length; i++) {\r\n if (\r\n Inputmask.prototype.definitions[txt.charAt(i)] ||\r\n opts.definitions[txt.charAt(i)] ||\r\n opts.optionalmarker[0] === txt.charAt(i) ||\r\n opts.optionalmarker[1] === txt.charAt(i) ||\r\n opts.quantifiermarker[0] === txt.charAt(i) ||\r\n opts.quantifiermarker[1] === txt.charAt(i) ||\r\n opts.groupmarker[0] === txt.charAt(i) ||\r\n opts.groupmarker[1] === txt.charAt(i) ||\r\n opts.alternatormarker === txt.charAt(i)\r\n ) {\r\n escapedTxt += \"\\\\\" + txt.charAt(i);\r\n } else {\r\n escapedTxt += txt.charAt(i);\r\n }\r\n }\r\n return escapedTxt;\r\n}\r\n\r\nfunction alignDigits(buffer, digits, opts, force) {\r\n if (buffer.length > 0 && digits > 0 && (!opts.digitsOptional || force)) {\r\n var radixPosition = buffer.indexOf(opts.radixPoint),\r\n negationBack = false;\r\n if (opts.negationSymbol.back === buffer[buffer.length - 1]) {\r\n negationBack = true;\r\n buffer.length--;\r\n }\r\n\r\n if (radixPosition === -1) {\r\n buffer.push(opts.radixPoint);\r\n radixPosition = buffer.length - 1;\r\n }\r\n for (let i = 1; i <= digits; i++) {\r\n if (!isFinite(buffer[radixPosition + i])) {\r\n buffer[radixPosition + i] = \"0\";\r\n }\r\n }\r\n }\r\n\r\n if (negationBack) buffer.push(opts.negationSymbol.back);\r\n return buffer;\r\n}\r\n\r\nfunction findValidator(symbol, maskset) {\r\n let posNdx = 0;\r\n if (symbol === \"+\") {\r\n posNdx = seekNext.call(this, maskset.validPositions.length - 1);\r\n }\r\n for (let tstNdx in maskset.tests) {\r\n tstNdx = parseInt(tstNdx);\r\n if (tstNdx >= posNdx) {\r\n for (\r\n let ndx = 0, ndxl = maskset.tests[tstNdx].length;\r\n ndx < ndxl;\r\n ndx++\r\n ) {\r\n if (\r\n (maskset.validPositions[tstNdx] === undefined || symbol === \"-\") &&\r\n maskset.tests[tstNdx][ndx].match.def === symbol\r\n ) {\r\n return (\r\n tstNdx +\r\n (maskset.validPositions[tstNdx] !== undefined && symbol !== \"-\"\r\n ? 1\r\n : 0)\r\n );\r\n }\r\n }\r\n }\r\n }\r\n return posNdx;\r\n}\r\n\r\nfunction findValid(symbol, maskset) {\r\n let ret = -1;\r\n for (let ndx = 0, vpl = maskset.validPositions.length; ndx < vpl; ndx++) {\r\n const tst = maskset.validPositions[ndx];\r\n if (tst && tst.match.def === symbol) {\r\n ret = ndx;\r\n break;\r\n }\r\n }\r\n return ret;\r\n}\r\n\r\nfunction parseMinMaxOptions(opts) {\r\n if (opts.parseMinMaxOptions === undefined) {\r\n // convert min and max options\r\n if (opts.min !== null) {\r\n opts.min = opts.min\r\n .toString()\r\n .replace(new RegExp(escapeRegex(opts.groupSeparator), \"g\"), \"\");\r\n if (opts.radixPoint === \",\")\r\n opts.min = opts.min.replace(opts.radixPoint, \".\");\r\n opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN;\r\n if (isNaN(opts.min)) opts.min = Number.MIN_VALUE;\r\n }\r\n if (opts.max !== null) {\r\n opts.max = opts.max\r\n .toString()\r\n .replace(new RegExp(escapeRegex(opts.groupSeparator), \"g\"), \"\");\r\n if (opts.radixPoint === \",\")\r\n opts.max = opts.max.replace(opts.radixPoint, \".\");\r\n opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN;\r\n if (isNaN(opts.max)) opts.max = Number.MAX_VALUE;\r\n }\r\n opts.parseMinMaxOptions = \"done\";\r\n }\r\n}\r\n\r\nfunction genMask(opts) {\r\n opts.repeat = 0;\r\n // treat equal separator and radixpoint\r\n if (\r\n opts.groupSeparator === opts.radixPoint &&\r\n opts.digits &&\r\n opts.digits !== \"0\"\r\n ) {\r\n if (opts.radixPoint === \".\") {\r\n opts.groupSeparator = \",\";\r\n } else if (opts.radixPoint === \",\") {\r\n opts.groupSeparator = \".\";\r\n } else {\r\n opts.groupSeparator = \"\";\r\n }\r\n }\r\n // prevent conflict with default skipOptionalPartCharacter\r\n if (opts.groupSeparator === \" \") {\r\n opts.skipOptionalPartCharacter = undefined;\r\n }\r\n\r\n // enforce placeholder to single\r\n if (opts.placeholder.length > 1) {\r\n opts.placeholder = opts.placeholder.charAt(0);\r\n }\r\n // only allow radixfocus when placeholder = 0\r\n if (opts.positionCaretOnClick === \"radixFocus\" && opts.placeholder === \"\") {\r\n opts.positionCaretOnClick = \"lvp\";\r\n }\r\n\r\n let decimalDef = \"0\",\r\n radixPointDef = opts.radixPoint;\r\n if (opts.numericInput === true && opts.__financeInput === undefined) {\r\n // finance people input style\r\n decimalDef = \"1\";\r\n opts.positionCaretOnClick =\r\n opts.positionCaretOnClick === \"radixFocus\"\r\n ? \"lvp\"\r\n : opts.positionCaretOnClick;\r\n opts.digitsOptional = false;\r\n if (isNaN(opts.digits))\r\n opts.digits =\r\n opts.digits.indexOf(\",\") !== -1 ? opts.digits.split(\",\")[0] : 2;\r\n opts._radixDance = false;\r\n radixPointDef = opts.radixPoint === \",\" ? \"?\" : \"!\";\r\n if (\r\n opts.radixPoint !== \"\" &&\r\n opts.definitions[radixPointDef] === undefined\r\n ) {\r\n // update separator definition\r\n opts.definitions[radixPointDef] = {};\r\n opts.definitions[radixPointDef].validator = \"[\" + opts.radixPoint + \"]\";\r\n opts.definitions[radixPointDef].placeholder = opts.radixPoint;\r\n opts.definitions[radixPointDef].static = true;\r\n opts.definitions[radixPointDef].generated = true; // forced marker as generated input\r\n }\r\n } else {\r\n opts.__financeInput = false; // needed to keep original selection when remasking\r\n opts.numericInput = true;\r\n }\r\n\r\n let mask = \"[+]\",\r\n altMask;\r\n mask += autoEscape(opts.prefix, opts);\r\n if (opts.groupSeparator !== \"\") {\r\n if (opts.definitions[opts.groupSeparator] === undefined) {\r\n // update separator definition\r\n opts.definitions[opts.groupSeparator] = {};\r\n opts.definitions[opts.groupSeparator].validator =\r\n \"[\" + opts.groupSeparator + \"]\";\r\n opts.definitions[opts.groupSeparator].placeholder = opts.groupSeparator;\r\n opts.definitions[opts.groupSeparator].static = true;\r\n opts.definitions[opts.groupSeparator].generated = true; // forced marker as generated input\r\n }\r\n mask += opts._mask(opts);\r\n } else {\r\n mask += \"9{+}\";\r\n }\r\n if (opts.digits !== undefined && opts.digits !== 0) {\r\n const dq = opts.digits.toString().split(\",\");\r\n if (isFinite(dq[0]) && dq[1] && isFinite(dq[1])) {\r\n mask += radixPointDef + decimalDef + \"{\" + opts.digits + \"}\";\r\n } else if (isNaN(opts.digits) || parseInt(opts.digits) > 0) {\r\n if (opts.digitsOptional || opts.jitMasking) {\r\n altMask = mask + radixPointDef + decimalDef + \"{0,\" + opts.digits + \"}\";\r\n // mask += \"[\" + opts.radixPoint + \"]\";\r\n opts.keepStatic = true;\r\n } else {\r\n mask += radixPointDef + decimalDef + \"{\" + opts.digits + \"}\";\r\n }\r\n }\r\n } else {\r\n opts.inputmode = \"numeric\";\r\n }\r\n mask += autoEscape(opts.suffix, opts);\r\n mask += \"[-]\";\r\n\r\n if (altMask) {\r\n mask = [altMask + autoEscape(opts.suffix, opts) + \"[-]\", mask];\r\n }\r\n\r\n opts.greedy = false; // enforce greedy false\r\n\r\n parseMinMaxOptions(opts);\r\n if (opts.radixPoint !== \"\" && opts.substituteRadixPoint)\r\n opts.substitutes[opts.radixPoint == \".\" ? \",\" : \".\"] = opts.radixPoint;\r\n // console.log(mask);\r\n return mask;\r\n}\r\n\r\nfunction handleRadixDance(pos, c, radixPos, maskset, opts) {\r\n if (opts._radixDance && opts.numericInput && c !== opts.negationSymbol.back) {\r\n if (\r\n pos <= radixPos &&\r\n (radixPos > 0 || c == opts.radixPoint) &&\r\n (maskset.validPositions[pos - 1] === undefined ||\r\n maskset.validPositions[pos - 1].input !== opts.negationSymbol.back)\r\n ) {\r\n pos -= 1;\r\n }\r\n }\r\n return pos;\r\n}\r\n\r\nfunction decimalValidator(chrs, maskset, pos, strict, opts) {\r\n const radixPos = maskset.buffer\r\n ? maskset.buffer.indexOf(opts.radixPoint)\r\n : -1,\r\n result =\r\n (radixPos !== -1 || (strict && opts.jitMasking)) &&\r\n new RegExp(opts.definitions[\"9\"].validator).test(chrs);\r\n if (\r\n !strict &&\r\n opts._radixDance &&\r\n radixPos !== -1 &&\r\n result &&\r\n maskset.validPositions[radixPos] == undefined\r\n ) {\r\n return {\r\n insert: {\r\n pos: radixPos === pos ? radixPos + 1 : radixPos,\r\n c: opts.radixPoint\r\n },\r\n pos\r\n };\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction checkForLeadingZeroes(buffer, opts) {\r\n // check leading zeros\r\n let numberMatches = new RegExp(\r\n \"(^\" +\r\n (opts.negationSymbol.front !== \"\"\r\n ? escapeRegex(opts.negationSymbol.front) + \"?\"\r\n : \"\") +\r\n escapeRegex(opts.prefix) +\r\n \")(.*)(\" +\r\n escapeRegex(opts.suffix) +\r\n (opts.negationSymbol.back != \"\"\r\n ? escapeRegex(opts.negationSymbol.back) + \"?\"\r\n : \"\") +\r\n \"$)\"\r\n ).exec(buffer.slice().reverse().join(\"\")),\r\n number = numberMatches ? numberMatches[2] : \"\",\r\n leadingzeroes = false;\r\n if (number) {\r\n number = number.split(opts.radixPoint.charAt(0))[0];\r\n leadingzeroes = new RegExp(\"^[0\" + opts.groupSeparator + \"]*\").exec(number);\r\n }\r\n return leadingzeroes &&\r\n (leadingzeroes[0].length > 1 ||\r\n (leadingzeroes[0].length > 0 && leadingzeroes[0].length < number.length))\r\n ? leadingzeroes\r\n : false;\r\n}\r\n\r\n// number aliases\r\nInputmask.extendAliases({\r\n numeric: {\r\n mask: genMask,\r\n _mask: function (opts) {\r\n return \"(\" + opts.groupSeparator + \"999){+|1}\";\r\n },\r\n digits: \"*\", // number of fractionalDigits\r\n digitsOptional: true,\r\n enforceDigitsOnBlur: false,\r\n radixPoint: \".\",\r\n positionCaretOnClick: \"radixFocus\",\r\n _radixDance: true,\r\n groupSeparator: \"\",\r\n allowMinus: true,\r\n negationSymbol: {\r\n front: \"-\", // \"(\"\r\n back: \"\" // \")\"\r\n },\r\n prefix: \"\",\r\n suffix: \"\",\r\n min: null, // minimum value\r\n max: null, // maximum value\r\n SetMaxOnOverflow: false,\r\n step: 1,\r\n inputType: \"text\", // number ~ specify that values which are set are in textform (radix point is same as in the options) or in numberform (radixpoint = .)\r\n unmaskAsNumber: false,\r\n roundingFN: Math.round, // Math.floor , fn(x)\r\n inputmode: \"decimal\",\r\n shortcuts: { k: \"1000\", m: \"1000000\" },\r\n // global options\r\n placeholder: \"0\",\r\n greedy: false,\r\n rightAlign: true,\r\n insertMode: true,\r\n autoUnmask: false,\r\n skipOptionalPartCharacter: \"\",\r\n usePrototypeDefinitions: false,\r\n stripLeadingZeroes: true,\r\n substituteRadixPoint: true,\r\n definitions: {\r\n 0: {\r\n validator: decimalValidator\r\n },\r\n 1: {\r\n validator: decimalValidator,\r\n definitionSymbol: \"9\"\r\n },\r\n 9: {\r\n // \\uFF11-\\uFF19 #1606\r\n validator: \"[0-9\\uFF10-\\uFF19\\u0660-\\u0669\\u06F0-\\u06F9]\",\r\n definitionSymbol: \"*\"\r\n },\r\n \"+\": {\r\n validator: function (chrs, maskset, pos, strict, opts) {\r\n return (\r\n opts.allowMinus &&\r\n (chrs === \"-\" || chrs === opts.negationSymbol.front)\r\n );\r\n }\r\n },\r\n \"-\": {\r\n validator: function (chrs, maskset, pos, strict, opts) {\r\n return opts.allowMinus && chrs === opts.negationSymbol.back;\r\n }\r\n }\r\n },\r\n preValidation: function (\r\n buffer,\r\n pos,\r\n c,\r\n isSelection,\r\n opts,\r\n maskset,\r\n caretPos,\r\n strict\r\n ) {\r\n const inputmask = this;\r\n\r\n if (opts.__financeInput !== false && c === opts.radixPoint) return false;\r\n const radixPos = buffer.indexOf(opts.radixPoint),\r\n initPos = pos;\r\n pos = handleRadixDance(pos, c, radixPos, maskset, opts);\r\n if (c === \"-\" || c === opts.negationSymbol.front) {\r\n if (opts.allowMinus !== true) return false;\r\n let isNegative = false,\r\n front = findValid(\"+\", maskset),\r\n back = findValid(\"-\", maskset);\r\n if (front !== -1) {\r\n isNegative = [front];\r\n if (back !== -1) isNegative.push(back);\r\n }\r\n\r\n return isNegative !== false\r\n ? {\r\n remove: isNegative,\r\n caret: initPos - opts.negationSymbol.back.length\r\n }\r\n : {\r\n insert: [\r\n {\r\n pos: findValidator.call(inputmask, \"+\", maskset),\r\n c: opts.negationSymbol.front,\r\n fromIsValid: true\r\n },\r\n {\r\n pos: findValidator.call(inputmask, \"-\", maskset),\r\n c: opts.negationSymbol.back,\r\n fromIsValid: undefined\r\n }\r\n ],\r\n caret: initPos + opts.negationSymbol.back.length\r\n };\r\n }\r\n\r\n if (c === opts.groupSeparator) {\r\n return { caret: initPos };\r\n }\r\n\r\n if (strict) return true;\r\n if (\r\n radixPos !== -1 &&\r\n opts._radixDance === true &&\r\n isSelection === false &&\r\n c === opts.radixPoint &&\r\n opts.digits !== undefined &&\r\n (isNaN(opts.digits) || parseInt(opts.digits) > 0) &&\r\n radixPos !== pos\r\n ) {\r\n const radixValidatorPos = findValidator.call(\r\n inputmask,\r\n opts.radixPoint,\r\n maskset\r\n );\r\n if (maskset.validPositions[radixValidatorPos]) {\r\n maskset.validPositions[radixValidatorPos].generatedInput =\r\n maskset.validPositions[radixValidatorPos].generated || false;\r\n }\r\n return {\r\n caret:\r\n opts._radixDance && pos === radixPos - 1 ? radixPos + 1 : radixPos\r\n };\r\n }\r\n if (opts.__financeInput === false) {\r\n if (isSelection) {\r\n if (opts.digitsOptional) {\r\n return { rewritePosition: caretPos.end };\r\n } else if (!opts.digitsOptional) {\r\n if (caretPos.begin > radixPos && caretPos.end <= radixPos) {\r\n if (c === opts.radixPoint) {\r\n return {\r\n insert: { pos: radixPos + 1, c: \"0\", fromIsValid: true },\r\n rewritePosition: radixPos\r\n };\r\n } else {\r\n return { rewritePosition: radixPos + 1 };\r\n }\r\n } else if (caretPos.begin < radixPos) {\r\n return { rewritePosition: caretPos.begin - 1 };\r\n }\r\n }\r\n } else {\r\n if (\r\n !opts.showMaskOnHover &&\r\n !opts.showMaskOnFocus &&\r\n !opts.digitsOptional &&\r\n opts.digits > 0 &&\r\n this.__valueGet.call(this.el) === \"\"\r\n ) {\r\n return { rewritePosition: radixPos };\r\n }\r\n\r\n // Cursor placed at or before the prefix on a field with no digits\r\n // would otherwise fall through to alternation switching and land\r\n // in the decimal part (#2615)\r\n if (\r\n pos >= buffer.length - opts.prefix.length &&\r\n opts.radixPoint !== \"\"\r\n ) {\r\n const digitTest = new RegExp(opts.definitions[\"9\"].validator);\r\n if (\r\n !maskset.validPositions.some(\r\n (vp) => vp && !vp.generatedInput && digitTest.test(vp.input)\r\n )\r\n ) {\r\n return { rewritePosition: radixPos !== -1 ? radixPos : 0 };\r\n }\r\n }\r\n }\r\n }\r\n\r\n return { rewritePosition: pos };\r\n },\r\n postValidation: function (\r\n buffer,\r\n pos,\r\n c,\r\n currentResult,\r\n opts,\r\n maskset,\r\n strict,\r\n fromCheckval,\r\n fromAlternate\r\n ) {\r\n if (currentResult === false) return currentResult;\r\n if (strict) return true;\r\n if (opts.min !== null || opts.max !== null) {\r\n const unmasked = opts.onUnMask(\r\n buffer.slice().reverse().join(\"\"),\r\n undefined,\r\n $.extend({}, opts, {\r\n unmaskAsNumber: true\r\n })\r\n );\r\n if (\r\n opts.min !== null &&\r\n unmasked < opts.min &&\r\n fromAlternate !== true &&\r\n (unmasked.toString().length > opts.min.toString().length || // > instead of >= because we want to allow to type a bigger number\r\n buffer[0] === opts.radixPoint || // disallow radixpoint when value is smaller than min\r\n unmasked < 0)\r\n ) {\r\n return false;\r\n // return {\r\n // \trefreshFromBuffer: true,\r\n // \tbuffer: alignDigits(opts.min.toString().replace(\".\", opts.radixPoint).split(\"\"), opts.digits, opts).reverse()\r\n // };\r\n }\r\n\r\n if (opts.max !== null && opts.max >= 0 && unmasked > opts.max) {\r\n return opts.SetMaxOnOverflow\r\n ? {\r\n refreshFromBuffer: true,\r\n buffer: alignDigits(\r\n opts.max.toString().replace(\".\", opts.radixPoint).split(\"\"),\r\n opts.digits,\r\n opts\r\n ).reverse()\r\n }\r\n : false;\r\n }\r\n }\r\n\r\n return currentResult;\r\n },\r\n onUnMask: function (maskedValue, unmaskedValue, opts) {\r\n if (unmaskedValue === \"\" && opts.nullable === true) {\r\n return unmaskedValue;\r\n }\r\n let processValue = maskedValue.replace(opts.prefix, \"\");\r\n processValue = processValue.replace(opts.suffix, \"\");\r\n processValue = processValue.replace(\r\n new RegExp(escapeRegex(opts.groupSeparator), \"g\"),\r\n \"\"\r\n );\r\n if (opts.placeholder.charAt(0) !== \"\") {\r\n processValue = processValue.replace(\r\n new RegExp(opts.placeholder.charAt(0), \"g\"),\r\n \"0\"\r\n );\r\n }\r\n if (opts.unmaskAsNumber) {\r\n if (\r\n opts.radixPoint !== \"\" &&\r\n processValue.indexOf(opts.radixPoint) !== -1\r\n )\r\n processValue = processValue.replace(\r\n escapeRegex.call(this, opts.radixPoint),\r\n \".\"\r\n );\r\n processValue = processValue.replace(\r\n new RegExp(\"^\" + escapeRegex(opts.negationSymbol.front)),\r\n \"-\"\r\n );\r\n processValue = processValue.replace(\r\n new RegExp(escapeRegex(opts.negationSymbol.back) + \"$\"),\r\n \"\"\r\n );\r\n return Number(processValue);\r\n }\r\n return processValue;\r\n },\r\n isComplete: function (buffer, opts) {\r\n let maskedValue = (\r\n opts.numericInput ? buffer.slice().reverse() : buffer\r\n ).join(\"\");\r\n maskedValue = maskedValue.replace(\r\n new RegExp(\"^\" + escapeRegex(opts.negationSymbol.front)),\r\n \"-\"\r\n );\r\n maskedValue = maskedValue.replace(\r\n new RegExp(escapeRegex(opts.negationSymbol.back) + \"$\"),\r\n \"\"\r\n );\r\n maskedValue = maskedValue.replace(opts.prefix, \"\");\r\n maskedValue = maskedValue.replace(opts.suffix, \"\");\r\n maskedValue = maskedValue.replace(\r\n new RegExp(escapeRegex(opts.groupSeparator) + \"([0-9]{3})\", \"g\"),\r\n \"$1\"\r\n );\r\n if (opts.radixPoint === \",\")\r\n maskedValue = maskedValue.replace(escapeRegex(opts.radixPoint), \".\");\r\n return isFinite(maskedValue);\r\n },\r\n onBeforeMask: function (initialValue, opts) {\r\n initialValue = initialValue ?? \"\";\r\n const radixPoint = opts.radixPoint || \",\";\r\n if (isFinite(opts.digits)) opts.digits = parseInt(opts.digits);\r\n\r\n if (\r\n (typeof initialValue === \"number\" || opts.inputType === \"number\") &&\r\n radixPoint !== \"\"\r\n ) {\r\n initialValue = initialValue.toString().replace(\".\", radixPoint);\r\n }\r\n const isNegative =\r\n initialValue.charAt(0) === \"-\" ||\r\n initialValue.charAt(0) === opts.negationSymbol.front,\r\n valueParts = initialValue.split(radixPoint),\r\n integerPart = valueParts[0].replace(/[^\\-0-9]/g, \"\"),\r\n decimalPart =\r\n valueParts.length > 1 ? valueParts[1].replace(/[^0-9]/g, \"\") : \"\",\r\n forceDigits = valueParts.length > 1;\r\n\r\n initialValue =\r\n integerPart +\r\n (decimalPart !== \"\" ? radixPoint + decimalPart : decimalPart);\r\n\r\n let digits = 0;\r\n if (radixPoint !== \"\") {\r\n digits = !opts.digitsOptional\r\n ? opts.digits\r\n : opts.digits < decimalPart.length\r\n ? opts.digits\r\n : decimalPart.length;\r\n if (decimalPart !== \"\" || !opts.digitsOptional) {\r\n const digitsFactor = Math.pow(10, digits || 1);\r\n\r\n // make the initialValue a valid javascript number for the parsefloat\r\n initialValue = initialValue.replace(escapeRegex(radixPoint), \".\");\r\n if (!isNaN(parseFloat(initialValue))) {\r\n initialValue = (\r\n opts.roundingFN(parseFloat(initialValue) * digitsFactor) /\r\n digitsFactor\r\n ).toFixed(digits);\r\n }\r\n initialValue = initialValue.toString().replace(\".\", radixPoint);\r\n }\r\n }\r\n // this needs to be in a separate part and not directly in decimalPart to allow rounding\r\n if (opts.digits === 0 && initialValue.indexOf(radixPoint) !== -1) {\r\n initialValue = initialValue.substring(\r\n 0,\r\n initialValue.indexOf(radixPoint)\r\n );\r\n }\r\n\r\n if (initialValue !== \"\" && (opts.min !== null || opts.max !== null)) {\r\n const numberValue = initialValue.toString().replace(radixPoint, \".\");\r\n if (opts.min !== null && numberValue < opts.min) {\r\n initialValue = opts.min.toString().replace(\".\", radixPoint);\r\n } else if (opts.max !== null && numberValue > opts.max) {\r\n initialValue = opts.max.toString().replace(\".\", radixPoint);\r\n }\r\n }\r\n\r\n if (isNegative && initialValue.charAt(0) !== \"-\") {\r\n initialValue = \"-\" + initialValue;\r\n }\r\n return alignDigits(\r\n initialValue.toString().split(\"\"),\r\n digits,\r\n opts,\r\n forceDigits\r\n ).join(\"\");\r\n },\r\n onBeforeWrite: function (e, buffer, caretPos, opts) {\r\n function stripBuffer(buffer, stripRadix) {\r\n if (opts.__financeInput !== false || stripRadix) {\r\n var position = buffer.indexOf(opts.radixPoint);\r\n if (position !== -1) {\r\n buffer.splice(position, 1);\r\n }\r\n }\r\n if (opts.groupSeparator !== \"\") {\r\n while ((position = buffer.indexOf(opts.groupSeparator)) !== -1) {\r\n buffer.splice(position, 1);\r\n }\r\n }\r\n\r\n return buffer;\r\n }\r\n\r\n let result, leadingzeroes;\r\n if (\r\n opts.stripLeadingZeroes &&\r\n (leadingzeroes = checkForLeadingZeroes(buffer, opts))\r\n ) {\r\n const caretNdx =\r\n buffer\r\n .join(\"\")\r\n .lastIndexOf(leadingzeroes[0].split(\"\").reverse().join(\"\")) -\r\n (leadingzeroes[0] == leadingzeroes.input ? 0 : 1),\r\n offset = leadingzeroes[0] == leadingzeroes.input ? 1 : 0;\r\n for (let i = leadingzeroes[0].length - offset; i > 0; i--) {\r\n this.maskset.validPositions.splice(caretNdx + i, 1);\r\n delete buffer[caretNdx + i];\r\n }\r\n }\r\n\r\n if (e) {\r\n switch (e.type) {\r\n case \"blur\":\r\n case \"checkval\":\r\n if (opts.min !== null || opts.max !== null) {\r\n const unmasked = opts.onUnMask(\r\n buffer.slice().reverse().join(\"\"),\r\n undefined,\r\n $.extend({}, opts, {\r\n unmaskAsNumber: true\r\n })\r\n );\r\n if (\r\n opts.min !== null &&\r\n unmasked < opts.min &&\r\n buffer.join() !== \"\"\r\n ) {\r\n return {\r\n refreshFromBuffer: true,\r\n buffer: alignDigits(\r\n opts.min.toString().replace(\".\", opts.radixPoint).split(\"\"),\r\n opts.digits,\r\n opts\r\n ).reverse()\r\n };\r\n } else if (opts.max !== null && unmasked > opts.max) {\r\n return {\r\n refreshFromBuffer: true,\r\n buffer: alignDigits(\r\n opts.max.toString().replace(\".\", opts.radixPoint).split(\"\"),\r\n opts.digits,\r\n opts\r\n ).reverse()\r\n };\r\n }\r\n }\r\n if (buffer[buffer.length - 1] === opts.negationSymbol.front) {\r\n // strip negation symbol on blur when value is 0\r\n const nmbrMtchs = new RegExp(\r\n \"(^\" +\r\n (opts.negationSymbol.front != \"\"\r\n ? escapeRegex(opts.negationSymbol.front) + \"?\"\r\n : \"\") +\r\n escapeRegex(opts.prefix) +\r\n \")(.*)(\" +\r\n escapeRegex(opts.suffix) +\r\n (opts.negationSymbol.back != \"\"\r\n ? escapeRegex(opts.negationSymbol.back) + \"?\"\r\n : \"\") +\r\n \"$)\"\r\n ).exec(stripBuffer(buffer.slice(), true).reverse().join(\"\")),\r\n number = nmbrMtchs ? nmbrMtchs[2] : \"\";\r\n if (number == 0) {\r\n result = { refreshFromBuffer: true, buffer: [0] };\r\n }\r\n } else if (opts.radixPoint !== \"\") {\r\n // strip radixpoint on blur when it is the latest char\r\n const radixNDX = buffer.indexOf(opts.radixPoint);\r\n if (radixNDX === opts.suffix.length) {\r\n if (result && result.buffer) {\r\n result.buffer.splice(0, 1 + opts.suffix.length);\r\n } else {\r\n buffer.splice(0, 1 + opts.suffix.length);\r\n result = {\r\n refreshFromBuffer: true,\r\n buffer: stripBuffer(buffer)\r\n };\r\n }\r\n }\r\n }\r\n\r\n if (opts.enforceDigitsOnBlur) {\r\n result = result || {};\r\n const bffr = ((result && result.buffer) || buffer)\r\n .slice()\r\n .reverse();\r\n result.refreshFromBuffer = true;\r\n result.buffer = alignDigits(\r\n bffr,\r\n opts.digits,\r\n opts,\r\n true\r\n ).reverse();\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n },\r\n onKeyDown: function (e, buffer, caretPos, opts) {\r\n let $input = $(this),\r\n bffr;\r\n if (e.location != 3) {\r\n let pattern,\r\n c = e.key;\r\n if ((pattern = opts.shortcuts && opts.shortcuts[c])) {\r\n if (pattern.length > 1) {\r\n this.inputmask.__valueSet.call(\r\n this,\r\n parseFloat(this.inputmask.unmaskedvalue()) * parseInt(pattern)\r\n );\r\n $input.trigger(\"setvalue\");\r\n return false;\r\n }\r\n }\r\n }\r\n if (e.ctrlKey) {\r\n switch (e.key) {\r\n case keys.ArrowUp:\r\n this.inputmask.__valueSet.call(\r\n this,\r\n parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step)\r\n );\r\n $input.trigger(\"setvalue\");\r\n return false;\r\n case keys.ArrowDown:\r\n this.inputmask.__valueSet.call(\r\n this,\r\n parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step)\r\n );\r\n $input.trigger(\"setvalue\");\r\n return false;\r\n }\r\n }\r\n if (\r\n !e.shiftKey &&\r\n (e.key === keys.Delete ||\r\n e.key === keys.Backspace ||\r\n e.key === keys.BACKSPACE_SAFARI) &&\r\n caretPos.begin !== buffer.length\r\n ) {\r\n if (\r\n buffer[e.key === keys.Delete ? caretPos.begin - 1 : caretPos.end] ===\r\n opts.negationSymbol.front\r\n ) {\r\n bffr = buffer.slice().reverse();\r\n if (opts.negationSymbol.front !== \"\") bffr.shift();\r\n if (opts.negationSymbol.back !== \"\") bffr.pop();\r\n $input.trigger(\"setvalue\", [bffr.join(\"\"), caretPos.begin]);\r\n return false;\r\n } else if (opts._radixDance === true) {\r\n const radixPos = buffer.indexOf(opts.radixPoint);\r\n if (!opts.digitsOptional) {\r\n if (\r\n radixPos !== -1 &&\r\n (caretPos.begin < radixPos ||\r\n caretPos.end < radixPos ||\r\n (e.key === keys.Delete &&\r\n (caretPos.begin === radixPos ||\r\n caretPos.begin - 1 === radixPos)))\r\n ) {\r\n let restoreCaretPos;\r\n if (caretPos.begin === caretPos.end) {\r\n // only adjust when not a selection\r\n if (e.key === keys.Backspace || e.key === keys.BACKSPACE_SAFARI)\r\n caretPos.begin++;\r\n else if (\r\n e.key === keys.Delete &&\r\n caretPos.begin - 1 === radixPos\r\n ) {\r\n restoreCaretPos = $.extend({}, caretPos);\r\n caretPos.begin--;\r\n caretPos.end--;\r\n }\r\n }\r\n bffr = buffer.slice().reverse();\r\n bffr.splice(\r\n bffr.length - caretPos.begin,\r\n caretPos.begin - caretPos.end || 1\r\n );\r\n if (e.key === keys.Backspace || e.key === keys.BACKSPACE_SAFARI)\r\n bffr.splice(bffr.length - caretPos.end + 1, 0, \"0\");\r\n // console.log(caretPos);\r\n bffr = alignDigits(bffr, opts.digits, opts).join(\"\");\r\n if (restoreCaretPos) {\r\n caretPos = restoreCaretPos;\r\n }\r\n $input.trigger(\"setvalue\", [\r\n bffr,\r\n caretPos.begin >= bffr.length ? radixPos + 1 : caretPos.begin\r\n ]);\r\n return false;\r\n }\r\n } else if (radixPos === 0) {\r\n bffr = buffer.slice().reverse();\r\n bffr.pop();\r\n $input.trigger(\"setvalue\", [\r\n bffr.join(\"\"),\r\n caretPos.begin >= bffr.length ? bffr.length : caretPos.begin\r\n ]);\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n },\r\n currency: {\r\n prefix: \"\", // \"$ \",\r\n groupSeparator: \",\",\r\n alias: \"numeric\",\r\n digits: 2,\r\n digitsOptional: false\r\n },\r\n decimal: {\r\n alias: \"numeric\"\r\n },\r\n integer: {\r\n alias: \"numeric\",\r\n inputmode: \"numeric\",\r\n digits: 0\r\n },\r\n percentage: {\r\n alias: \"numeric\",\r\n min: 0,\r\n max: 100,\r\n suffix: \" %\",\r\n digits: 0,\r\n allowMinus: false\r\n },\r\n indianns: {\r\n // indian numbering system\r\n alias: \"numeric\",\r\n _mask: function (opts) {\r\n return (\r\n \"(\" +\r\n opts.groupSeparator +\r\n \"99){*|1}(\" +\r\n opts.groupSeparator +\r\n \"999){1|1}\"\r\n );\r\n },\r\n groupSeparator: \",\",\r\n radixPoint: \".\",\r\n placeholder: \"0\",\r\n digits: 2,\r\n digitsOptional: false\r\n }\r\n});\r\n", "import window from \"./global/window\";\r\nimport Inputmask from \"./inputmask\";\r\n\r\nconst document = window.document;\r\n\r\n// add check if it is supported by the browser\r\n// integrate shadowroot into maskcope\r\nif (\r\n document &&\r\n document.head &&\r\n document.head.attachShadow &&\r\n window.customElements &&\r\n window.customElements.get(\"input-mask\") === undefined\r\n) {\r\n class InputmaskElement extends HTMLElement {\r\n constructor() {\r\n super();\r\n const attributeNames = this.getAttributeNames(),\r\n shadow = this.attachShadow({ mode: \"closed\" });\r\n this.input = document.createElement(\"input\");\r\n this.input.type = \"text\";\r\n shadow.appendChild(this.input);\r\n\r\n for (const attr in attributeNames) {\r\n if (Object.prototype.hasOwnProperty.call(attributeNames, attr)) {\r\n this.input.setAttribute(\r\n attributeNames[attr],\r\n this.getAttribute(attributeNames[attr])\r\n );\r\n }\r\n }\r\n\r\n const im = new Inputmask();\r\n im.dataAttribute = \"\";\r\n im.mask(this.input);\r\n }\r\n\r\n attributeChangedCallback(attrName, oldVal, newVal) {\r\n this.input.setAttribute(attrName, newVal);\r\n }\r\n\r\n // bind value\r\n get value() {\r\n return this.input.value;\r\n }\r\n\r\n set value(value) {\r\n this.input.value = value;\r\n }\r\n }\r\n\r\n window.customElements.define(\"input-mask\", InputmaskElement);\r\n}\r\n", "// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n", "import \"./lib/polyfills/Object.getPrototypeOf\";\r\nimport \"./lib/polyfills/Array.includes\";\r\nimport \"./lib/polyfills/Object.entries\";\r\nimport \"./lib/polyfills/String.includes\";\r\n\r\nimport \"./lib/global/FormData\";\r\n\r\nimport \"./lib/extensions/inputmask.extensions\";\r\nimport \"./lib/extensions/inputmask.date.extensions\";\r\nimport \"./lib/extensions/inputmask.numeric.extensions\";\r\nimport \"./lib/inputmaskElement\";\r\nimport Inputmask from \"./lib/inputmask\";\r\n\r\nexport default Inputmask;\r\n", "// Custom TailwindCSS modals for confirm dialogs\n//\n// Example usage:\n//\n// <%= button_to \"Delete\", my_path, method: :delete, form: {\n// data: {\n// turbo_confirm: \"Are you sure?\",\n// turbo_confirm_description: \"This will delete your record. Enter the record name to confirm.\",\n// turbo_confirm_text: \"record name\"\n// }\n// } %>\n\nfunction insertConfirmModal(message, element, button) {\n let confirmInput = \"\"\n\n // button is nil if using link_to with data-turbo-confirm\n let confirmText = button?.dataset?.turboConfirmText || element.dataset.turboConfirmText\n let description = button?.dataset?.turboConfirmDescription || element.dataset.turboConfirmDescription || \"\"\n if (confirmText) {\n confirmInput = ``\n }\n let id = `confirm-modal-${new Date().getTime()}`\n\n let content = `\n
    \n
    \n\n
    \n
    ${message}
    \n

    ${description}

    \n\n ${confirmInput}\n\n
    \n \n \n
    \n
    \n
    \n
    \n `\n\n document.body.insertAdjacentHTML('beforeend', content)\n let modal = document.getElementById(id)\n\n // Focus on the first button in the modal after rendering\n modal.querySelector(\"button\").focus()\n\n // Disable commit button until the value matches confirmText\n if (confirmText) {\n let commitButton = modal.querySelector(\"[data-behavior='commit']\")\n commitButton.disabled = true\n modal.querySelector(\"input[data-behavior='confirm-text']\").addEventListener(\"input\", (event) => {\n commitButton.disabled = (event.target.value != confirmText)\n })\n }\n\n return modal\n}\n\nTurbo.config.forms.confirm = (message, element, button) => {\n let dialog = insertConfirmModal(message, element, button)\n\n return new Promise((resolve, reject) => {\n dialog.querySelector(\"[data-behavior='cancel']\").addEventListener(\"click\", (event) => {\n dialog.remove()\n resolve(false)\n }, { once: true })\n dialog.querySelector(\"[data-behavior='commit']\").addEventListener(\"click\", (event) => {\n dialog.remove()\n resolve(true)\n }, { once: true })\n })\n}\n", "addEventListener(\"direct-upload:initialize\", event => {\n const { target, detail } = event\n const { id, file } = detail\n target.insertAdjacentHTML(\"beforebegin\", `\n
    \n
    \n ${file.name}\n
    \n `)\n})\n\naddEventListener(\"direct-upload:start\", event => {\n const { id } = event.detail\n const element = document.getElementById(`direct-upload-${id}`)\n element.classList.remove(\"direct-upload--pending\")\n})\n\naddEventListener(\"direct-upload:progress\", event => {\n const { id, progress } = event.detail\n const progressElement = document.getElementById(`direct-upload-progress-${id}`)\n progressElement.style.width = `${progress}%`\n})\n\naddEventListener(\"direct-upload:error\", event => {\n event.preventDefault()\n const { id, error } = event.detail\n const element = document.getElementById(`direct-upload-${id}`)\n element.classList.add(\"direct-upload--error\")\n element.setAttribute(\"title\", error)\n})\n\naddEventListener(\"direct-upload:end\", event => {\n const { id } = event.detail\n const element = document.getElementById(`direct-upload-${id}`)\n element.classList.add(\"direct-upload--complete\")\n})\n", "// Lazily loads elements with a data-src attribute.\n// This is useful for speeding up initial page rendering.\n//\n// \n// \n\ndocument.addEventListener(\"turbo:load\", () => {\n document.querySelectorAll('[data-src]').forEach((element) =>{\n element.setAttribute('src', element.getAttribute('data-src'))\n })\n})\n", "(function (root) {/*global exports, Intl*/\n/**\n * This script gives you the zone info key representing your device's time zone setting.\n *\n * @name jsTimezoneDetect\n * @version 1.0.6\n * @author Jon Nylander\n * @license MIT License - https://bitbucket.org/pellepim/jstimezonedetect/src/default/LICENCE.txt\n *\n * For usage and examples, visit:\n * http://pellepim.bitbucket.org/jstz/\n *\n * Copyright (c) Jon Nylander\n */\n\n\n/**\n * Namespace to hold all the code for timezone detection.\n */\nvar jstz = (function () {\n 'use strict';\n var HEMISPHERE_SOUTH = 's',\n\n consts = {\n DAY: 86400000,\n HOUR: 3600000,\n MINUTE: 60000,\n SECOND: 1000,\n BASELINE_YEAR: 2014,\n MAX_SCORE: 864000000, // 10 days\n AMBIGUITIES: {\n 'America/Denver': ['America/Mazatlan'],\n 'Europe/London': ['Africa/Casablanca'],\n 'America/Chicago': ['America/Mexico_City'],\n 'America/Asuncion': ['America/Campo_Grande', 'America/Santiago'],\n 'America/Montevideo': ['America/Sao_Paulo', 'America/Santiago'],\n // Europe/Minsk should not be in this list... but Windows.\n 'Asia/Beirut': ['Asia/Amman', 'Asia/Jerusalem', 'Europe/Helsinki', 'Asia/Damascus', 'Africa/Cairo', 'Asia/Gaza', 'Europe/Minsk'],\n 'Pacific/Auckland': ['Pacific/Fiji'],\n 'America/Los_Angeles': ['America/Santa_Isabel'],\n 'America/New_York': ['America/Havana'],\n 'America/Halifax': ['America/Goose_Bay'],\n 'America/Godthab': ['America/Miquelon'],\n 'Asia/Dubai': ['Asia/Yerevan'],\n 'Asia/Jakarta': ['Asia/Krasnoyarsk'],\n 'Asia/Shanghai': ['Asia/Irkutsk', 'Australia/Perth'],\n 'Australia/Sydney': ['Australia/Lord_Howe'],\n 'Asia/Tokyo': ['Asia/Yakutsk'],\n 'Asia/Dhaka': ['Asia/Omsk'],\n // In the real world Yerevan is not ambigous for Baku... but Windows.\n 'Asia/Baku': ['Asia/Yerevan'],\n 'Australia/Brisbane': ['Asia/Vladivostok'],\n 'Pacific/Noumea': ['Asia/Vladivostok'],\n 'Pacific/Majuro': ['Asia/Kamchatka', 'Pacific/Fiji'],\n 'Pacific/Tongatapu': ['Pacific/Apia'],\n 'Asia/Baghdad': ['Europe/Minsk', 'Europe/Moscow'],\n 'Asia/Karachi': ['Asia/Yekaterinburg'],\n 'Africa/Johannesburg': ['Asia/Gaza', 'Africa/Cairo']\n }\n },\n\n /**\n * Gets the offset in minutes from UTC for a certain date.\n * @param {Date} date\n * @returns {Number}\n */\n get_date_offset = function get_date_offset(date) {\n var offset = -date.getTimezoneOffset();\n return (offset !== null ? offset : 0);\n },\n\n /**\n * This function does some basic calculations to create information about\n * the user's timezone. It uses REFERENCE_YEAR as a solid year for which\n * the script has been tested rather than depend on the year set by the\n * client device.\n *\n * Returns a key that can be used to do lookups in jstz.olson.timezones.\n * eg: \"720,1,2\".\n *\n * @returns {String}\n */\n lookup_key = function lookup_key() {\n var january_offset = get_date_offset(new Date(consts.BASELINE_YEAR, 0, 2)),\n june_offset = get_date_offset(new Date(consts.BASELINE_YEAR, 5, 2)),\n diff = january_offset - june_offset;\n\n if (diff < 0) {\n return january_offset + \",1\";\n } else if (diff > 0) {\n return june_offset + \",1,\" + HEMISPHERE_SOUTH;\n }\n\n return january_offset + \",0\";\n },\n\n\n /**\n * Tries to get the time zone key directly from the operating system for those\n * environments that support the ECMAScript Internationalization API.\n */\n get_from_internationalization_api = function get_from_internationalization_api() {\n var format, timezone;\n if (typeof Intl === \"undefined\" || typeof Intl.DateTimeFormat === \"undefined\") {\n return;\n }\n format = Intl.DateTimeFormat();\n if (typeof format === \"undefined\" || typeof format.resolvedOptions === \"undefined\") {\n return;\n }\n timezone = format.resolvedOptions().timeZone;\n if (timezone && (timezone.indexOf(\"/\") > -1 || timezone === 'UTC') && timezone.indexOf(\"Etc\") != 0) {\n return timezone;\n }\n },\n\n /**\n * Starting point for getting all the DST rules for a specific year\n * for the current timezone (as described by the client system).\n *\n * Returns an object with start and end attributes, or false if no\n * DST rules were found for the year.\n *\n * @param year\n * @returns {Object} || {Boolean}\n */\n dst_dates = function dst_dates(year) {\n var yearstart = new Date(year, 0, 1, 0, 0, 1, 0).getTime();\n var yearend = new Date(year, 12, 31, 23, 59, 59).getTime();\n var current = yearstart;\n var offset = (new Date(current)).getTimezoneOffset();\n var dst_start = null;\n var dst_end = null;\n\n while (current < yearend - 86400000) {\n var dateToCheck = new Date(current);\n var dateToCheckOffset = dateToCheck.getTimezoneOffset();\n\n if (dateToCheckOffset !== offset) {\n if (dateToCheckOffset < offset) {\n dst_start = dateToCheck;\n }\n if (dateToCheckOffset > offset) {\n dst_end = dateToCheck;\n }\n offset = dateToCheckOffset;\n }\n\n current += 86400000;\n }\n\n if (dst_start && dst_end) {\n return {\n s: find_dst_fold(dst_start).getTime(),\n e: find_dst_fold(dst_end).getTime()\n };\n }\n\n return false;\n },\n\n /**\n * Probably completely unnecessary function that recursively finds the\n * exact (to the second) time when a DST rule was changed.\n *\n * @param a_date - The candidate Date.\n * @param padding - integer specifying the padding to allow around the candidate\n * date for finding the fold.\n * @param iterator - integer specifying how many milliseconds to iterate while\n * searching for the fold.\n *\n * @returns {Date}\n */\n find_dst_fold = function find_dst_fold(a_date, padding, iterator) {\n if (typeof padding === 'undefined') {\n padding = consts.DAY;\n iterator = consts.HOUR;\n }\n\n var date_start = new Date(a_date.getTime() - padding).getTime();\n var date_end = a_date.getTime() + padding;\n var offset = new Date(date_start).getTimezoneOffset();\n\n var current = date_start;\n\n var dst_change = null;\n while (current < date_end - iterator) {\n var dateToCheck = new Date(current);\n var dateToCheckOffset = dateToCheck.getTimezoneOffset();\n\n if (dateToCheckOffset !== offset) {\n dst_change = dateToCheck;\n break;\n }\n current += iterator;\n }\n\n if (padding === consts.DAY) {\n return find_dst_fold(dst_change, consts.HOUR, consts.MINUTE);\n }\n\n if (padding === consts.HOUR) {\n return find_dst_fold(dst_change, consts.MINUTE, consts.SECOND);\n }\n\n return dst_change;\n },\n\n windows7_adaptations = function windows7_adaptions(rule_list, preliminary_timezone, score, sample) {\n if (score !== 'N/A') {\n return score;\n }\n if (preliminary_timezone === 'Asia/Beirut') {\n if (sample.name === 'Africa/Cairo') {\n if (rule_list[6].s === 1398376800000 && rule_list[6].e === 1411678800000) {\n return 0;\n }\n }\n if (sample.name === 'Asia/Jerusalem') {\n if (rule_list[6].s === 1395964800000 && rule_list[6].e === 1411858800000) {\n return 0;\n }\n }\n } else if (preliminary_timezone === 'America/Santiago') {\n if (sample.name === 'America/Asuncion') {\n if (rule_list[6].s === 1412481600000 && rule_list[6].e === 1397358000000) {\n return 0;\n }\n }\n if (sample.name === 'America/Campo_Grande') {\n if (rule_list[6].s === 1413691200000 && rule_list[6].e === 1392519600000) {\n return 0;\n }\n }\n } else if (preliminary_timezone === 'America/Montevideo') {\n if (sample.name === 'America/Sao_Paulo') {\n if (rule_list[6].s === 1413687600000 && rule_list[6].e === 1392516000000) {\n return 0;\n }\n }\n } else if (preliminary_timezone === 'Pacific/Auckland') {\n if (sample.name === 'Pacific/Fiji') {\n if (rule_list[6].s === 1414245600000 && rule_list[6].e === 1396101600000) {\n return 0;\n }\n }\n }\n\n return score;\n },\n\n /**\n * Takes the DST rules for the current timezone, and proceeds to find matches\n * in the jstz.olson.dst_rules.zones array.\n *\n * Compares samples to the current timezone on a scoring basis.\n *\n * Candidates are ruled immediately if either the candidate or the current zone\n * has a DST rule where the other does not.\n *\n * Candidates are ruled out immediately if the current zone has a rule that is\n * outside the DST scope of the candidate.\n *\n * Candidates are included for scoring if the current zones rules fall within the\n * span of the samples rules.\n *\n * Low score is best, the score is calculated by summing up the differences in DST\n * rules and if the consts.MAX_SCORE is overreached the candidate is ruled out.\n *\n * Yah follow? :)\n *\n * @param rule_list\n * @param preliminary_timezone\n * @returns {*}\n */\n best_dst_match = function best_dst_match(rule_list, preliminary_timezone) {\n var score_sample = function score_sample(sample) {\n var score = 0;\n\n for (var j = 0; j < rule_list.length; j++) {\n\n // Both sample and current time zone report DST during the year.\n if (!!sample.rules[j] && !!rule_list[j]) {\n\n // The current time zone's DST rules are inside the sample's. Include.\n if (rule_list[j].s >= sample.rules[j].s && rule_list[j].e <= sample.rules[j].e) {\n score = 0;\n score += Math.abs(rule_list[j].s - sample.rules[j].s);\n score += Math.abs(sample.rules[j].e - rule_list[j].e);\n\n // The current time zone's DST rules are outside the sample's. Discard.\n } else {\n score = 'N/A';\n break;\n }\n\n // The max score has been reached. Discard.\n if (score > consts.MAX_SCORE) {\n score = 'N/A';\n break;\n }\n }\n }\n\n score = windows7_adaptations(rule_list, preliminary_timezone, score, sample);\n\n return score;\n };\n var scoreboard = {};\n var dst_zones = jstz.olson.dst_rules.zones;\n var dst_zones_length = dst_zones.length;\n var ambiguities = consts.AMBIGUITIES[preliminary_timezone];\n\n for (var i = 0; i < dst_zones_length; i++) {\n var sample = dst_zones[i];\n var score = score_sample(dst_zones[i]);\n\n if (score !== 'N/A') {\n scoreboard[sample.name] = score;\n }\n }\n\n for (var tz in scoreboard) {\n if (scoreboard.hasOwnProperty(tz)) {\n for (var j = 0; j < ambiguities.length; j++) {\n if (ambiguities[j] === tz) {\n return tz;\n }\n }\n }\n }\n\n return preliminary_timezone;\n },\n\n /**\n * Takes the preliminary_timezone as detected by lookup_key().\n *\n * Builds up the current timezones DST rules for the years defined\n * in the jstz.olson.dst_rules.years array.\n *\n * If there are no DST occurences for those years, immediately returns\n * the preliminary timezone. Otherwise proceeds and tries to solve\n * ambiguities.\n *\n * @param preliminary_timezone\n * @returns {String} timezone_name\n */\n get_by_dst = function get_by_dst(preliminary_timezone) {\n var get_rules = function get_rules() {\n var rule_list = [];\n for (var i = 0; i < jstz.olson.dst_rules.years.length; i++) {\n var year_rules = dst_dates(jstz.olson.dst_rules.years[i]);\n rule_list.push(year_rules);\n }\n return rule_list;\n };\n var check_has_dst = function check_has_dst(rules) {\n for (var i = 0; i < rules.length; i++) {\n if (rules[i] !== false) {\n return true;\n }\n }\n return false;\n };\n var rules = get_rules();\n var has_dst = check_has_dst(rules);\n\n if (has_dst) {\n return best_dst_match(rules, preliminary_timezone);\n }\n\n return preliminary_timezone;\n },\n\n /**\n * Uses get_timezone_info() to formulate a key to use in the olson.timezones dictionary.\n *\n * Returns an object with one function \".name()\"\n *\n * @returns Object\n */\n determine = function determine() {\n var preliminary_tz = get_from_internationalization_api();\n\n if (!preliminary_tz) {\n preliminary_tz = jstz.olson.timezones[lookup_key()];\n\n if (typeof consts.AMBIGUITIES[preliminary_tz] !== 'undefined') {\n preliminary_tz = get_by_dst(preliminary_tz);\n }\n }\n\n return {\n name: function () {\n return preliminary_tz;\n },\n stdTimezoneOffset : function () {\n // negative to match what (new Date).getTimezoneOffset() will return\n return -lookup_key().split(',')[0];\n },\n timezoneOffset : function () {\n // negative to match what (new Date).getTimezoneOffset() will return\n return -get_date_offset(new Date())\n }\n };\n };\n\n return {\n determine: determine\n };\n}());\n\n\njstz.olson = jstz.olson || {};\n\n/**\n * The keys in this dictionary are comma separated as such:\n *\n * First the offset compared to UTC time in minutes.\n *\n * Then a flag which is 0 if the timezone does not take daylight savings into account and 1 if it\n * does.\n *\n * Thirdly an optional 's' signifies that the timezone is in the southern hemisphere,\n * only interesting for timezones with DST.\n *\n * The mapped arrays is used for constructing the jstz.TimeZone object from within\n * jstz.determine();\n */\njstz.olson.timezones = {\n '-720,0': 'Etc/GMT+12',\n '-660,0': 'Pacific/Pago_Pago',\n '-660,1,s': 'Pacific/Apia', // Why? Because windows... cry!\n '-600,1': 'America/Adak',\n '-600,0': 'Pacific/Honolulu',\n '-570,0': 'Pacific/Marquesas',\n '-540,0': 'Pacific/Gambier',\n '-540,1': 'America/Anchorage',\n '-480,1': 'America/Los_Angeles',\n '-480,0': 'Pacific/Pitcairn',\n '-420,0': 'America/Phoenix',\n '-420,1': 'America/Denver',\n '-360,0': 'America/Guatemala',\n '-360,1': 'America/Chicago',\n '-360,1,s': 'Pacific/Easter',\n '-300,0': 'America/Bogota',\n '-300,1': 'America/New_York',\n '-270,0': 'America/Caracas',\n '-240,1': 'America/Halifax',\n '-240,0': 'America/Santo_Domingo',\n '-240,1,s': 'America/Asuncion',\n '-210,1': 'America/St_Johns',\n '-180,1': 'America/Godthab',\n '-180,0': 'America/Argentina/Buenos_Aires',\n '-180,1,s': 'America/Montevideo',\n '-120,0': 'America/Noronha',\n '-120,1': 'America/Noronha',\n '-60,1': 'Atlantic/Azores',\n '-60,0': 'Atlantic/Cape_Verde',\n '0,0': 'UTC',\n '0,1': 'Europe/London',\n '60,1': 'Europe/Berlin',\n '60,0': 'Africa/Lagos',\n '60,1,s': 'Africa/Windhoek',\n '120,1': 'Asia/Beirut',\n '120,0': 'Africa/Johannesburg',\n '180,0': 'Asia/Baghdad',\n '180,1': 'Europe/Moscow',\n '210,1': 'Asia/Tehran',\n '240,0': 'Asia/Dubai',\n '240,1': 'Asia/Baku',\n '270,0': 'Asia/Kabul',\n '300,1': 'Asia/Yekaterinburg',\n '300,0': 'Asia/Karachi',\n '330,0': 'Asia/Kolkata',\n '345,0': 'Asia/Kathmandu',\n '360,0': 'Asia/Dhaka',\n '360,1': 'Asia/Omsk',\n '390,0': 'Asia/Rangoon',\n '420,1': 'Asia/Krasnoyarsk',\n '420,0': 'Asia/Jakarta',\n '480,0': 'Asia/Shanghai',\n '480,1': 'Asia/Irkutsk',\n '525,0': 'Australia/Eucla',\n '525,1,s': 'Australia/Eucla',\n '540,1': 'Asia/Yakutsk',\n '540,0': 'Asia/Tokyo',\n '570,0': 'Australia/Darwin',\n '570,1,s': 'Australia/Adelaide',\n '600,0': 'Australia/Brisbane',\n '600,1': 'Asia/Vladivostok',\n '600,1,s': 'Australia/Sydney',\n '630,1,s': 'Australia/Lord_Howe',\n '660,1': 'Asia/Kamchatka',\n '660,0': 'Pacific/Noumea',\n '690,0': 'Pacific/Norfolk',\n '720,1,s': 'Pacific/Auckland',\n '720,0': 'Pacific/Majuro',\n '765,1,s': 'Pacific/Chatham',\n '780,0': 'Pacific/Tongatapu',\n '780,1,s': 'Pacific/Apia',\n '840,0': 'Pacific/Kiritimati'\n};\n\n/* Build time: 2015-11-02 13:01:00Z Build by invoking python utilities/dst.py generate */\njstz.olson.dst_rules = {\n \"years\": [\n 2008,\n 2009,\n 2010,\n 2011,\n 2012,\n 2013,\n 2014\n ],\n \"zones\": [\n {\n \"name\": \"Africa/Cairo\",\n \"rules\": [\n {\n \"e\": 1219957200000,\n \"s\": 1209074400000\n },\n {\n \"e\": 1250802000000,\n \"s\": 1240524000000\n },\n {\n \"e\": 1285880400000,\n \"s\": 1284069600000\n },\n false,\n false,\n false,\n {\n \"e\": 1411678800000,\n \"s\": 1406844000000\n }\n ]\n },\n {\n \"name\": \"Africa/Casablanca\",\n \"rules\": [\n {\n \"e\": 1220223600000,\n \"s\": 1212278400000\n },\n {\n \"e\": 1250809200000,\n \"s\": 1243814400000\n },\n {\n \"e\": 1281222000000,\n \"s\": 1272758400000\n },\n {\n \"e\": 1312066800000,\n \"s\": 1301788800000\n },\n {\n \"e\": 1348970400000,\n \"s\": 1345428000000\n },\n {\n \"e\": 1382839200000,\n \"s\": 1376100000000\n },\n {\n \"e\": 1414288800000,\n \"s\": 1406944800000\n }\n ]\n },\n {\n \"name\": \"America/Asuncion\",\n \"rules\": [\n {\n \"e\": 1205031600000,\n \"s\": 1224388800000\n },\n {\n \"e\": 1236481200000,\n \"s\": 1255838400000\n },\n {\n \"e\": 1270954800000,\n \"s\": 1286078400000\n },\n {\n \"e\": 1302404400000,\n \"s\": 1317528000000\n },\n {\n \"e\": 1333854000000,\n \"s\": 1349582400000\n },\n {\n \"e\": 1364094000000,\n \"s\": 1381032000000\n },\n {\n \"e\": 1395543600000,\n \"s\": 1412481600000\n }\n ]\n },\n {\n \"name\": \"America/Campo_Grande\",\n \"rules\": [\n {\n \"e\": 1203217200000,\n \"s\": 1224388800000\n },\n {\n \"e\": 1234666800000,\n \"s\": 1255838400000\n },\n {\n \"e\": 1266721200000,\n \"s\": 1287288000000\n },\n {\n \"e\": 1298170800000,\n \"s\": 1318737600000\n },\n {\n \"e\": 1330225200000,\n \"s\": 1350792000000\n },\n {\n \"e\": 1361070000000,\n \"s\": 1382241600000\n },\n {\n \"e\": 1392519600000,\n \"s\": 1413691200000\n }\n ]\n },\n {\n \"name\": \"America/Goose_Bay\",\n \"rules\": [\n {\n \"e\": 1225594860000,\n \"s\": 1205035260000\n },\n {\n \"e\": 1257044460000,\n \"s\": 1236484860000\n },\n {\n \"e\": 1289098860000,\n \"s\": 1268539260000\n },\n {\n \"e\": 1320555600000,\n \"s\": 1299988860000\n },\n {\n \"e\": 1352005200000,\n \"s\": 1331445600000\n },\n {\n \"e\": 1383454800000,\n \"s\": 1362895200000\n },\n {\n \"e\": 1414904400000,\n \"s\": 1394344800000\n }\n ]\n },\n {\n \"name\": \"America/Havana\",\n \"rules\": [\n {\n \"e\": 1224997200000,\n \"s\": 1205643600000\n },\n {\n \"e\": 1256446800000,\n \"s\": 1236488400000\n },\n {\n \"e\": 1288501200000,\n \"s\": 1268542800000\n },\n {\n \"e\": 1321160400000,\n \"s\": 1300597200000\n },\n {\n \"e\": 1352005200000,\n \"s\": 1333256400000\n },\n {\n \"e\": 1383454800000,\n \"s\": 1362891600000\n },\n {\n \"e\": 1414904400000,\n \"s\": 1394341200000\n }\n ]\n },\n {\n \"name\": \"America/Mazatlan\",\n \"rules\": [\n {\n \"e\": 1225008000000,\n \"s\": 1207472400000\n },\n {\n \"e\": 1256457600000,\n \"s\": 1238922000000\n },\n {\n \"e\": 1288512000000,\n \"s\": 1270371600000\n },\n {\n \"e\": 1319961600000,\n \"s\": 1301821200000\n },\n {\n \"e\": 1351411200000,\n \"s\": 1333270800000\n },\n {\n \"e\": 1382860800000,\n \"s\": 1365325200000\n },\n {\n \"e\": 1414310400000,\n \"s\": 1396774800000\n }\n ]\n },\n {\n \"name\": \"America/Mexico_City\",\n \"rules\": [\n {\n \"e\": 1225004400000,\n \"s\": 1207468800000\n },\n {\n \"e\": 1256454000000,\n \"s\": 1238918400000\n },\n {\n \"e\": 1288508400000,\n \"s\": 1270368000000\n },\n {\n \"e\": 1319958000000,\n \"s\": 1301817600000\n },\n {\n \"e\": 1351407600000,\n \"s\": 1333267200000\n },\n {\n \"e\": 1382857200000,\n \"s\": 1365321600000\n },\n {\n \"e\": 1414306800000,\n \"s\": 1396771200000\n }\n ]\n },\n {\n \"name\": \"America/Miquelon\",\n \"rules\": [\n {\n \"e\": 1225598400000,\n \"s\": 1205038800000\n },\n {\n \"e\": 1257048000000,\n \"s\": 1236488400000\n },\n {\n \"e\": 1289102400000,\n \"s\": 1268542800000\n },\n {\n \"e\": 1320552000000,\n \"s\": 1299992400000\n },\n {\n \"e\": 1352001600000,\n \"s\": 1331442000000\n },\n {\n \"e\": 1383451200000,\n \"s\": 1362891600000\n },\n {\n \"e\": 1414900800000,\n \"s\": 1394341200000\n }\n ]\n },\n {\n \"name\": \"America/Santa_Isabel\",\n \"rules\": [\n {\n \"e\": 1225011600000,\n \"s\": 1207476000000\n },\n {\n \"e\": 1256461200000,\n \"s\": 1238925600000\n },\n {\n \"e\": 1288515600000,\n \"s\": 1270375200000\n },\n {\n \"e\": 1319965200000,\n \"s\": 1301824800000\n },\n {\n \"e\": 1351414800000,\n \"s\": 1333274400000\n },\n {\n \"e\": 1382864400000,\n \"s\": 1365328800000\n },\n {\n \"e\": 1414314000000,\n \"s\": 1396778400000\n }\n ]\n },\n {\n \"name\": \"America/Santiago\",\n \"rules\": [\n {\n \"e\": 1206846000000,\n \"s\": 1223784000000\n },\n {\n \"e\": 1237086000000,\n \"s\": 1255233600000\n },\n {\n \"e\": 1270350000000,\n \"s\": 1286683200000\n },\n {\n \"e\": 1304823600000,\n \"s\": 1313899200000\n },\n {\n \"e\": 1335668400000,\n \"s\": 1346558400000\n },\n {\n \"e\": 1367118000000,\n \"s\": 1378612800000\n },\n {\n \"e\": 1398567600000,\n \"s\": 1410062400000\n }\n ]\n },\n {\n \"name\": \"America/Sao_Paulo\",\n \"rules\": [\n {\n \"e\": 1203213600000,\n \"s\": 1224385200000\n },\n {\n \"e\": 1234663200000,\n \"s\": 1255834800000\n },\n {\n \"e\": 1266717600000,\n \"s\": 1287284400000\n },\n {\n \"e\": 1298167200000,\n \"s\": 1318734000000\n },\n {\n \"e\": 1330221600000,\n \"s\": 1350788400000\n },\n {\n \"e\": 1361066400000,\n \"s\": 1382238000000\n },\n {\n \"e\": 1392516000000,\n \"s\": 1413687600000\n }\n ]\n },\n {\n \"name\": \"Asia/Amman\",\n \"rules\": [\n {\n \"e\": 1225404000000,\n \"s\": 1206655200000\n },\n {\n \"e\": 1256853600000,\n \"s\": 1238104800000\n },\n {\n \"e\": 1288303200000,\n \"s\": 1269554400000\n },\n {\n \"e\": 1319752800000,\n \"s\": 1301608800000\n },\n false,\n false,\n {\n \"e\": 1414706400000,\n \"s\": 1395957600000\n }\n ]\n },\n {\n \"name\": \"Asia/Damascus\",\n \"rules\": [\n {\n \"e\": 1225486800000,\n \"s\": 1207260000000\n },\n {\n \"e\": 1256850000000,\n \"s\": 1238104800000\n },\n {\n \"e\": 1288299600000,\n \"s\": 1270159200000\n },\n {\n \"e\": 1319749200000,\n \"s\": 1301608800000\n },\n {\n \"e\": 1351198800000,\n \"s\": 1333058400000\n },\n {\n \"e\": 1382648400000,\n \"s\": 1364508000000\n },\n {\n \"e\": 1414702800000,\n \"s\": 1395957600000\n }\n ]\n },\n {\n \"name\": \"Asia/Dubai\",\n \"rules\": [\n false,\n false,\n false,\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Asia/Gaza\",\n \"rules\": [\n {\n \"e\": 1219957200000,\n \"s\": 1206655200000\n },\n {\n \"e\": 1252015200000,\n \"s\": 1238104800000\n },\n {\n \"e\": 1281474000000,\n \"s\": 1269640860000\n },\n {\n \"e\": 1312146000000,\n \"s\": 1301608860000\n },\n {\n \"e\": 1348178400000,\n \"s\": 1333058400000\n },\n {\n \"e\": 1380229200000,\n \"s\": 1364508000000\n },\n {\n \"e\": 1414098000000,\n \"s\": 1395957600000\n }\n ]\n },\n {\n \"name\": \"Asia/Irkutsk\",\n \"rules\": [\n {\n \"e\": 1224957600000,\n \"s\": 1206813600000\n },\n {\n \"e\": 1256407200000,\n \"s\": 1238263200000\n },\n {\n \"e\": 1288461600000,\n \"s\": 1269712800000\n },\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Asia/Jerusalem\",\n \"rules\": [\n {\n \"e\": 1223161200000,\n \"s\": 1206662400000\n },\n {\n \"e\": 1254006000000,\n \"s\": 1238112000000\n },\n {\n \"e\": 1284246000000,\n \"s\": 1269561600000\n },\n {\n \"e\": 1317510000000,\n \"s\": 1301616000000\n },\n {\n \"e\": 1348354800000,\n \"s\": 1333065600000\n },\n {\n \"e\": 1382828400000,\n \"s\": 1364515200000\n },\n {\n \"e\": 1414278000000,\n \"s\": 1395964800000\n }\n ]\n },\n {\n \"name\": \"Asia/Kamchatka\",\n \"rules\": [\n {\n \"e\": 1224943200000,\n \"s\": 1206799200000\n },\n {\n \"e\": 1256392800000,\n \"s\": 1238248800000\n },\n {\n \"e\": 1288450800000,\n \"s\": 1269698400000\n },\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Asia/Krasnoyarsk\",\n \"rules\": [\n {\n \"e\": 1224961200000,\n \"s\": 1206817200000\n },\n {\n \"e\": 1256410800000,\n \"s\": 1238266800000\n },\n {\n \"e\": 1288465200000,\n \"s\": 1269716400000\n },\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Asia/Omsk\",\n \"rules\": [\n {\n \"e\": 1224964800000,\n \"s\": 1206820800000\n },\n {\n \"e\": 1256414400000,\n \"s\": 1238270400000\n },\n {\n \"e\": 1288468800000,\n \"s\": 1269720000000\n },\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Asia/Vladivostok\",\n \"rules\": [\n {\n \"e\": 1224950400000,\n \"s\": 1206806400000\n },\n {\n \"e\": 1256400000000,\n \"s\": 1238256000000\n },\n {\n \"e\": 1288454400000,\n \"s\": 1269705600000\n },\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Asia/Yakutsk\",\n \"rules\": [\n {\n \"e\": 1224954000000,\n \"s\": 1206810000000\n },\n {\n \"e\": 1256403600000,\n \"s\": 1238259600000\n },\n {\n \"e\": 1288458000000,\n \"s\": 1269709200000\n },\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Asia/Yekaterinburg\",\n \"rules\": [\n {\n \"e\": 1224968400000,\n \"s\": 1206824400000\n },\n {\n \"e\": 1256418000000,\n \"s\": 1238274000000\n },\n {\n \"e\": 1288472400000,\n \"s\": 1269723600000\n },\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Asia/Yerevan\",\n \"rules\": [\n {\n \"e\": 1224972000000,\n \"s\": 1206828000000\n },\n {\n \"e\": 1256421600000,\n \"s\": 1238277600000\n },\n {\n \"e\": 1288476000000,\n \"s\": 1269727200000\n },\n {\n \"e\": 1319925600000,\n \"s\": 1301176800000\n },\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Australia/Lord_Howe\",\n \"rules\": [\n {\n \"e\": 1207407600000,\n \"s\": 1223134200000\n },\n {\n \"e\": 1238857200000,\n \"s\": 1254583800000\n },\n {\n \"e\": 1270306800000,\n \"s\": 1286033400000\n },\n {\n \"e\": 1301756400000,\n \"s\": 1317483000000\n },\n {\n \"e\": 1333206000000,\n \"s\": 1349537400000\n },\n {\n \"e\": 1365260400000,\n \"s\": 1380987000000\n },\n {\n \"e\": 1396710000000,\n \"s\": 1412436600000\n }\n ]\n },\n {\n \"name\": \"Australia/Perth\",\n \"rules\": [\n {\n \"e\": 1206813600000,\n \"s\": 1224957600000\n },\n false,\n false,\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Europe/Helsinki\",\n \"rules\": [\n {\n \"e\": 1224982800000,\n \"s\": 1206838800000\n },\n {\n \"e\": 1256432400000,\n \"s\": 1238288400000\n },\n {\n \"e\": 1288486800000,\n \"s\": 1269738000000\n },\n {\n \"e\": 1319936400000,\n \"s\": 1301187600000\n },\n {\n \"e\": 1351386000000,\n \"s\": 1332637200000\n },\n {\n \"e\": 1382835600000,\n \"s\": 1364691600000\n },\n {\n \"e\": 1414285200000,\n \"s\": 1396141200000\n }\n ]\n },\n {\n \"name\": \"Europe/Minsk\",\n \"rules\": [\n {\n \"e\": 1224979200000,\n \"s\": 1206835200000\n },\n {\n \"e\": 1256428800000,\n \"s\": 1238284800000\n },\n {\n \"e\": 1288483200000,\n \"s\": 1269734400000\n },\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Europe/Moscow\",\n \"rules\": [\n {\n \"e\": 1224975600000,\n \"s\": 1206831600000\n },\n {\n \"e\": 1256425200000,\n \"s\": 1238281200000\n },\n {\n \"e\": 1288479600000,\n \"s\": 1269730800000\n },\n false,\n false,\n false,\n false\n ]\n },\n {\n \"name\": \"Pacific/Apia\",\n \"rules\": [\n false,\n false,\n false,\n {\n \"e\": 1301752800000,\n \"s\": 1316872800000\n },\n {\n \"e\": 1333202400000,\n \"s\": 1348927200000\n },\n {\n \"e\": 1365256800000,\n \"s\": 1380376800000\n },\n {\n \"e\": 1396706400000,\n \"s\": 1411826400000\n }\n ]\n },\n {\n \"name\": \"Pacific/Fiji\",\n \"rules\": [\n false,\n false,\n {\n \"e\": 1269698400000,\n \"s\": 1287842400000\n },\n {\n \"e\": 1327154400000,\n \"s\": 1319292000000\n },\n {\n \"e\": 1358604000000,\n \"s\": 1350741600000\n },\n {\n \"e\": 1390050000000,\n \"s\": 1382796000000\n },\n {\n \"e\": 1421503200000,\n \"s\": 1414850400000\n }\n ]\n },\n {\n \"name\": \"Europe/London\",\n \"rules\": [\n {\n \"e\": 1224982800000,\n \"s\": 1206838800000\n },\n {\n \"e\": 1256432400000,\n \"s\": 1238288400000\n },\n {\n \"e\": 1288486800000,\n \"s\": 1269738000000\n },\n {\n \"e\": 1319936400000,\n \"s\": 1301187600000\n },\n {\n \"e\": 1351386000000,\n \"s\": 1332637200000\n },\n {\n \"e\": 1382835600000,\n \"s\": 1364691600000\n },\n {\n \"e\": 1414285200000,\n \"s\": 1396141200000\n }\n ]\n }\n ]\n};\nif (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {\n module.exports = jstz;\n} else if ((typeof define !== 'undefined' && define !== null) && (define.amd != null)) {\n define([], function() {\n return jstz;\n });\n} else {\n if (typeof root === 'undefined') {\n window.jstz = jstz;\n } else {\n root.jstz = jstz;\n }\n}\n}());\n", "module.exports = require('./dist/jstz.js');\n", "(function(global, factory) {\n typeof exports === \"object\" && typeof module !== \"undefined\" ? factory(exports) : typeof define === \"function\" && define.amd ? define([ \"exports\" ], factory) : (global = typeof globalThis !== \"undefined\" ? globalThis : global || self, \n factory(global.ActiveStorage = {}));\n})(this, (function(exports) {\n \"use strict\";\n var sparkMd5 = {\n exports: {}\n };\n (function(module, exports) {\n (function(factory) {\n {\n module.exports = factory();\n }\n })((function(undefined$1) {\n var hex_chr = [ \"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\" ];\n function md5cycle(x, k) {\n var a = x[0], b = x[1], c = x[2], d = x[3];\n a += (b & c | ~b & d) + k[0] - 680876936 | 0;\n a = (a << 7 | a >>> 25) + b | 0;\n d += (a & b | ~a & c) + k[1] - 389564586 | 0;\n d = (d << 12 | d >>> 20) + a | 0;\n c += (d & a | ~d & b) + k[2] + 606105819 | 0;\n c = (c << 17 | c >>> 15) + d | 0;\n b += (c & d | ~c & a) + k[3] - 1044525330 | 0;\n b = (b << 22 | b >>> 10) + c | 0;\n a += (b & c | ~b & d) + k[4] - 176418897 | 0;\n a = (a << 7 | a >>> 25) + b | 0;\n d += (a & b | ~a & c) + k[5] + 1200080426 | 0;\n d = (d << 12 | d >>> 20) + a | 0;\n c += (d & a | ~d & b) + k[6] - 1473231341 | 0;\n c = (c << 17 | c >>> 15) + d | 0;\n b += (c & d | ~c & a) + k[7] - 45705983 | 0;\n b = (b << 22 | b >>> 10) + c | 0;\n a += (b & c | ~b & d) + k[8] + 1770035416 | 0;\n a = (a << 7 | a >>> 25) + b | 0;\n d += (a & b | ~a & c) + k[9] - 1958414417 | 0;\n d = (d << 12 | d >>> 20) + a | 0;\n c += (d & a | ~d & b) + k[10] - 42063 | 0;\n c = (c << 17 | c >>> 15) + d | 0;\n b += (c & d | ~c & a) + k[11] - 1990404162 | 0;\n b = (b << 22 | b >>> 10) + c | 0;\n a += (b & c | ~b & d) + k[12] + 1804603682 | 0;\n a = (a << 7 | a >>> 25) + b | 0;\n d += (a & b | ~a & c) + k[13] - 40341101 | 0;\n d = (d << 12 | d >>> 20) + a | 0;\n c += (d & a | ~d & b) + k[14] - 1502002290 | 0;\n c = (c << 17 | c >>> 15) + d | 0;\n b += (c & d | ~c & a) + k[15] + 1236535329 | 0;\n b = (b << 22 | b >>> 10) + c | 0;\n a += (b & d | c & ~d) + k[1] - 165796510 | 0;\n a = (a << 5 | a >>> 27) + b | 0;\n d += (a & c | b & ~c) + k[6] - 1069501632 | 0;\n d = (d << 9 | d >>> 23) + a | 0;\n c += (d & b | a & ~b) + k[11] + 643717713 | 0;\n c = (c << 14 | c >>> 18) + d | 0;\n b += (c & a | d & ~a) + k[0] - 373897302 | 0;\n b = (b << 20 | b >>> 12) + c | 0;\n a += (b & d | c & ~d) + k[5] - 701558691 | 0;\n a = (a << 5 | a >>> 27) + b | 0;\n d += (a & c | b & ~c) + k[10] + 38016083 | 0;\n d = (d << 9 | d >>> 23) + a | 0;\n c += (d & b | a & ~b) + k[15] - 660478335 | 0;\n c = (c << 14 | c >>> 18) + d | 0;\n b += (c & a | d & ~a) + k[4] - 405537848 | 0;\n b = (b << 20 | b >>> 12) + c | 0;\n a += (b & d | c & ~d) + k[9] + 568446438 | 0;\n a = (a << 5 | a >>> 27) + b | 0;\n d += (a & c | b & ~c) + k[14] - 1019803690 | 0;\n d = (d << 9 | d >>> 23) + a | 0;\n c += (d & b | a & ~b) + k[3] - 187363961 | 0;\n c = (c << 14 | c >>> 18) + d | 0;\n b += (c & a | d & ~a) + k[8] + 1163531501 | 0;\n b = (b << 20 | b >>> 12) + c | 0;\n a += (b & d | c & ~d) + k[13] - 1444681467 | 0;\n a = (a << 5 | a >>> 27) + b | 0;\n d += (a & c | b & ~c) + k[2] - 51403784 | 0;\n d = (d << 9 | d >>> 23) + a | 0;\n c += (d & b | a & ~b) + k[7] + 1735328473 | 0;\n c = (c << 14 | c >>> 18) + d | 0;\n b += (c & a | d & ~a) + k[12] - 1926607734 | 0;\n b = (b << 20 | b >>> 12) + c | 0;\n a += (b ^ c ^ d) + k[5] - 378558 | 0;\n a = (a << 4 | a >>> 28) + b | 0;\n d += (a ^ b ^ c) + k[8] - 2022574463 | 0;\n d = (d << 11 | d >>> 21) + a | 0;\n c += (d ^ a ^ b) + k[11] + 1839030562 | 0;\n c = (c << 16 | c >>> 16) + d | 0;\n b += (c ^ d ^ a) + k[14] - 35309556 | 0;\n b = (b << 23 | b >>> 9) + c | 0;\n a += (b ^ c ^ d) + k[1] - 1530992060 | 0;\n a = (a << 4 | a >>> 28) + b | 0;\n d += (a ^ b ^ c) + k[4] + 1272893353 | 0;\n d = (d << 11 | d >>> 21) + a | 0;\n c += (d ^ a ^ b) + k[7] - 155497632 | 0;\n c = (c << 16 | c >>> 16) + d | 0;\n b += (c ^ d ^ a) + k[10] - 1094730640 | 0;\n b = (b << 23 | b >>> 9) + c | 0;\n a += (b ^ c ^ d) + k[13] + 681279174 | 0;\n a = (a << 4 | a >>> 28) + b | 0;\n d += (a ^ b ^ c) + k[0] - 358537222 | 0;\n d = (d << 11 | d >>> 21) + a | 0;\n c += (d ^ a ^ b) + k[3] - 722521979 | 0;\n c = (c << 16 | c >>> 16) + d | 0;\n b += (c ^ d ^ a) + k[6] + 76029189 | 0;\n b = (b << 23 | b >>> 9) + c | 0;\n a += (b ^ c ^ d) + k[9] - 640364487 | 0;\n a = (a << 4 | a >>> 28) + b | 0;\n d += (a ^ b ^ c) + k[12] - 421815835 | 0;\n d = (d << 11 | d >>> 21) + a | 0;\n c += (d ^ a ^ b) + k[15] + 530742520 | 0;\n c = (c << 16 | c >>> 16) + d | 0;\n b += (c ^ d ^ a) + k[2] - 995338651 | 0;\n b = (b << 23 | b >>> 9) + c | 0;\n a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;\n a = (a << 6 | a >>> 26) + b | 0;\n d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;\n d = (d << 10 | d >>> 22) + a | 0;\n c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;\n c = (c << 15 | c >>> 17) + d | 0;\n b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;\n b = (b << 21 | b >>> 11) + c | 0;\n a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;\n a = (a << 6 | a >>> 26) + b | 0;\n d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;\n d = (d << 10 | d >>> 22) + a | 0;\n c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;\n c = (c << 15 | c >>> 17) + d | 0;\n b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;\n b = (b << 21 | b >>> 11) + c | 0;\n a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;\n a = (a << 6 | a >>> 26) + b | 0;\n d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;\n d = (d << 10 | d >>> 22) + a | 0;\n c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;\n c = (c << 15 | c >>> 17) + d | 0;\n b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;\n b = (b << 21 | b >>> 11) + c | 0;\n a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;\n a = (a << 6 | a >>> 26) + b | 0;\n d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;\n d = (d << 10 | d >>> 22) + a | 0;\n c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;\n c = (c << 15 | c >>> 17) + d | 0;\n b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;\n b = (b << 21 | b >>> 11) + c | 0;\n x[0] = a + x[0] | 0;\n x[1] = b + x[1] | 0;\n x[2] = c + x[2] | 0;\n x[3] = d + x[3] | 0;\n }\n function md5blk(s) {\n var md5blks = [], i;\n for (i = 0; i < 64; i += 4) {\n md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);\n }\n return md5blks;\n }\n function md5blk_array(a) {\n var md5blks = [], i;\n for (i = 0; i < 64; i += 4) {\n md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);\n }\n return md5blks;\n }\n function md51(s) {\n var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;\n for (i = 64; i <= n; i += 64) {\n md5cycle(state, md5blk(s.substring(i - 64, i)));\n }\n s = s.substring(i - 64);\n length = s.length;\n tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];\n for (i = 0; i < length; i += 1) {\n tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);\n }\n tail[i >> 2] |= 128 << (i % 4 << 3);\n if (i > 55) {\n md5cycle(state, tail);\n for (i = 0; i < 16; i += 1) {\n tail[i] = 0;\n }\n }\n tmp = n * 8;\n tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n lo = parseInt(tmp[2], 16);\n hi = parseInt(tmp[1], 16) || 0;\n tail[14] = lo;\n tail[15] = hi;\n md5cycle(state, tail);\n return state;\n }\n function md51_array(a) {\n var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;\n for (i = 64; i <= n; i += 64) {\n md5cycle(state, md5blk_array(a.subarray(i - 64, i)));\n }\n a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);\n length = a.length;\n tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];\n for (i = 0; i < length; i += 1) {\n tail[i >> 2] |= a[i] << (i % 4 << 3);\n }\n tail[i >> 2] |= 128 << (i % 4 << 3);\n if (i > 55) {\n md5cycle(state, tail);\n for (i = 0; i < 16; i += 1) {\n tail[i] = 0;\n }\n }\n tmp = n * 8;\n tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n lo = parseInt(tmp[2], 16);\n hi = parseInt(tmp[1], 16) || 0;\n tail[14] = lo;\n tail[15] = hi;\n md5cycle(state, tail);\n return state;\n }\n function rhex(n) {\n var s = \"\", j;\n for (j = 0; j < 4; j += 1) {\n s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];\n }\n return s;\n }\n function hex(x) {\n var i;\n for (i = 0; i < x.length; i += 1) {\n x[i] = rhex(x[i]);\n }\n return x.join(\"\");\n }\n if (hex(md51(\"hello\")) !== \"5d41402abc4b2a76b9719d911017c592\") ;\n if (typeof ArrayBuffer !== \"undefined\" && !ArrayBuffer.prototype.slice) {\n (function() {\n function clamp(val, length) {\n val = val | 0 || 0;\n if (val < 0) {\n return Math.max(val + length, 0);\n }\n return Math.min(val, length);\n }\n ArrayBuffer.prototype.slice = function(from, to) {\n var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;\n if (to !== undefined$1) {\n end = clamp(to, length);\n }\n if (begin > end) {\n return new ArrayBuffer(0);\n }\n num = end - begin;\n target = new ArrayBuffer(num);\n targetArray = new Uint8Array(target);\n sourceArray = new Uint8Array(this, begin, num);\n targetArray.set(sourceArray);\n return target;\n };\n })();\n }\n function toUtf8(str) {\n if (/[\\u0080-\\uFFFF]/.test(str)) {\n str = unescape(encodeURIComponent(str));\n }\n return str;\n }\n function utf8Str2ArrayBuffer(str, returnUInt8Array) {\n var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;\n for (i = 0; i < length; i += 1) {\n arr[i] = str.charCodeAt(i);\n }\n return returnUInt8Array ? arr : buff;\n }\n function arrayBuffer2Utf8Str(buff) {\n return String.fromCharCode.apply(null, new Uint8Array(buff));\n }\n function concatenateArrayBuffers(first, second, returnUInt8Array) {\n var result = new Uint8Array(first.byteLength + second.byteLength);\n result.set(new Uint8Array(first));\n result.set(new Uint8Array(second), first.byteLength);\n return returnUInt8Array ? result : result.buffer;\n }\n function hexToBinaryString(hex) {\n var bytes = [], length = hex.length, x;\n for (x = 0; x < length - 1; x += 2) {\n bytes.push(parseInt(hex.substr(x, 2), 16));\n }\n return String.fromCharCode.apply(String, bytes);\n }\n function SparkMD5() {\n this.reset();\n }\n SparkMD5.prototype.append = function(str) {\n this.appendBinary(toUtf8(str));\n return this;\n };\n SparkMD5.prototype.appendBinary = function(contents) {\n this._buff += contents;\n this._length += contents.length;\n var length = this._buff.length, i;\n for (i = 64; i <= length; i += 64) {\n md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));\n }\n this._buff = this._buff.substring(i - 64);\n return this;\n };\n SparkMD5.prototype.end = function(raw) {\n var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;\n for (i = 0; i < length; i += 1) {\n tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);\n }\n this._finish(tail, length);\n ret = hex(this._hash);\n if (raw) {\n ret = hexToBinaryString(ret);\n }\n this.reset();\n return ret;\n };\n SparkMD5.prototype.reset = function() {\n this._buff = \"\";\n this._length = 0;\n this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];\n return this;\n };\n SparkMD5.prototype.getState = function() {\n return {\n buff: this._buff,\n length: this._length,\n hash: this._hash.slice()\n };\n };\n SparkMD5.prototype.setState = function(state) {\n this._buff = state.buff;\n this._length = state.length;\n this._hash = state.hash;\n return this;\n };\n SparkMD5.prototype.destroy = function() {\n delete this._hash;\n delete this._buff;\n delete this._length;\n };\n SparkMD5.prototype._finish = function(tail, length) {\n var i = length, tmp, lo, hi;\n tail[i >> 2] |= 128 << (i % 4 << 3);\n if (i > 55) {\n md5cycle(this._hash, tail);\n for (i = 0; i < 16; i += 1) {\n tail[i] = 0;\n }\n }\n tmp = this._length * 8;\n tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n lo = parseInt(tmp[2], 16);\n hi = parseInt(tmp[1], 16) || 0;\n tail[14] = lo;\n tail[15] = hi;\n md5cycle(this._hash, tail);\n };\n SparkMD5.hash = function(str, raw) {\n return SparkMD5.hashBinary(toUtf8(str), raw);\n };\n SparkMD5.hashBinary = function(content, raw) {\n var hash = md51(content), ret = hex(hash);\n return raw ? hexToBinaryString(ret) : ret;\n };\n SparkMD5.ArrayBuffer = function() {\n this.reset();\n };\n SparkMD5.ArrayBuffer.prototype.append = function(arr) {\n var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i;\n this._length += arr.byteLength;\n for (i = 64; i <= length; i += 64) {\n md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));\n }\n this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);\n return this;\n };\n SparkMD5.ArrayBuffer.prototype.end = function(raw) {\n var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;\n for (i = 0; i < length; i += 1) {\n tail[i >> 2] |= buff[i] << (i % 4 << 3);\n }\n this._finish(tail, length);\n ret = hex(this._hash);\n if (raw) {\n ret = hexToBinaryString(ret);\n }\n this.reset();\n return ret;\n };\n SparkMD5.ArrayBuffer.prototype.reset = function() {\n this._buff = new Uint8Array(0);\n this._length = 0;\n this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];\n return this;\n };\n SparkMD5.ArrayBuffer.prototype.getState = function() {\n var state = SparkMD5.prototype.getState.call(this);\n state.buff = arrayBuffer2Utf8Str(state.buff);\n return state;\n };\n SparkMD5.ArrayBuffer.prototype.setState = function(state) {\n state.buff = utf8Str2ArrayBuffer(state.buff, true);\n return SparkMD5.prototype.setState.call(this, state);\n };\n SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;\n SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;\n SparkMD5.ArrayBuffer.hash = function(arr, raw) {\n var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);\n return raw ? hexToBinaryString(ret) : ret;\n };\n return SparkMD5;\n }));\n })(sparkMd5);\n var SparkMD5 = sparkMd5.exports;\n const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;\n class FileChecksum {\n static create(file, callback) {\n const instance = new FileChecksum(file);\n instance.create(callback);\n }\n constructor(file) {\n this.file = file;\n this.chunkSize = 2097152;\n this.chunkCount = Math.ceil(this.file.size / this.chunkSize);\n this.chunkIndex = 0;\n }\n create(callback) {\n this.callback = callback;\n this.md5Buffer = new SparkMD5.ArrayBuffer;\n this.fileReader = new FileReader;\n this.fileReader.addEventListener(\"load\", (event => this.fileReaderDidLoad(event)));\n this.fileReader.addEventListener(\"error\", (event => this.fileReaderDidError(event)));\n this.readNextChunk();\n }\n fileReaderDidLoad(event) {\n this.md5Buffer.append(event.target.result);\n if (!this.readNextChunk()) {\n const binaryDigest = this.md5Buffer.end(true);\n const base64digest = btoa(binaryDigest);\n this.callback(null, base64digest);\n }\n }\n fileReaderDidError(event) {\n this.callback(`Error reading ${this.file.name}`);\n }\n readNextChunk() {\n if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {\n const start = this.chunkIndex * this.chunkSize;\n const end = Math.min(start + this.chunkSize, this.file.size);\n const bytes = fileSlice.call(this.file, start, end);\n this.fileReader.readAsArrayBuffer(bytes);\n this.chunkIndex++;\n return true;\n } else {\n return false;\n }\n }\n }\n function getMetaValue(name) {\n const element = findElement(document.head, `meta[name=\"${name}\"]`);\n if (element) {\n return element.getAttribute(\"content\");\n }\n }\n function findElements(root, selector) {\n if (typeof root == \"string\") {\n selector = root;\n root = document;\n }\n const elements = root.querySelectorAll(selector);\n return toArray(elements);\n }\n function findElement(root, selector) {\n if (typeof root == \"string\") {\n selector = root;\n root = document;\n }\n return root.querySelector(selector);\n }\n function dispatchEvent(element, type, eventInit = {}) {\n const {disabled: disabled} = element;\n const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;\n const event = document.createEvent(\"Event\");\n event.initEvent(type, bubbles || true, cancelable || true);\n event.detail = detail || {};\n try {\n element.disabled = false;\n element.dispatchEvent(event);\n } finally {\n element.disabled = disabled;\n }\n return event;\n }\n function toArray(value) {\n if (Array.isArray(value)) {\n return value;\n } else if (Array.from) {\n return Array.from(value);\n } else {\n return [].slice.call(value);\n }\n }\n class BlobRecord {\n constructor(file, checksum, url, customHeaders = {}) {\n this.file = file;\n this.attributes = {\n filename: file.name,\n content_type: file.type || \"application/octet-stream\",\n byte_size: file.size,\n checksum: checksum\n };\n this.xhr = new XMLHttpRequest;\n this.xhr.open(\"POST\", url, true);\n this.xhr.responseType = \"json\";\n this.xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n this.xhr.setRequestHeader(\"Accept\", \"application/json\");\n this.xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n Object.keys(customHeaders).forEach((headerKey => {\n this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);\n }));\n const csrfToken = getMetaValue(\"csrf-token\");\n if (csrfToken != undefined) {\n this.xhr.setRequestHeader(\"X-CSRF-Token\", csrfToken);\n }\n this.xhr.addEventListener(\"load\", (event => this.requestDidLoad(event)));\n this.xhr.addEventListener(\"error\", (event => this.requestDidError(event)));\n }\n get status() {\n return this.xhr.status;\n }\n get response() {\n const {responseType: responseType, response: response} = this.xhr;\n if (responseType == \"json\") {\n return response;\n } else {\n return JSON.parse(response);\n }\n }\n create(callback) {\n this.callback = callback;\n this.xhr.send(JSON.stringify({\n blob: this.attributes\n }));\n }\n requestDidLoad(event) {\n if (this.status >= 200 && this.status < 300) {\n const {response: response} = this;\n const {direct_upload: direct_upload} = response;\n delete response.direct_upload;\n this.attributes = response;\n this.directUploadData = direct_upload;\n this.callback(null, this.toJSON());\n } else {\n this.requestDidError(event);\n }\n }\n requestDidError(event) {\n this.callback(`Error creating Blob for \"${this.file.name}\". Status: ${this.status}`);\n }\n toJSON() {\n const result = {};\n for (const key in this.attributes) {\n result[key] = this.attributes[key];\n }\n return result;\n }\n }\n class BlobUpload {\n constructor(blob) {\n this.blob = blob;\n this.file = blob.file;\n const {url: url, headers: headers} = blob.directUploadData;\n this.xhr = new XMLHttpRequest;\n this.xhr.open(\"PUT\", url, true);\n this.xhr.responseType = \"text\";\n for (const key in headers) {\n this.xhr.setRequestHeader(key, headers[key]);\n }\n this.xhr.addEventListener(\"load\", (event => this.requestDidLoad(event)));\n this.xhr.addEventListener(\"error\", (event => this.requestDidError(event)));\n }\n create(callback) {\n this.callback = callback;\n this.xhr.send(this.file.slice());\n }\n requestDidLoad(event) {\n const {status: status, response: response} = this.xhr;\n if (status >= 200 && status < 300) {\n this.callback(null, response);\n } else {\n this.requestDidError(event);\n }\n }\n requestDidError(event) {\n this.callback(`Error storing \"${this.file.name}\". Status: ${this.xhr.status}`);\n }\n }\n let id = 0;\n class DirectUpload {\n constructor(file, url, delegate, customHeaders = {}) {\n this.id = ++id;\n this.file = file;\n this.url = url;\n this.delegate = delegate;\n this.customHeaders = customHeaders;\n }\n create(callback) {\n FileChecksum.create(this.file, ((error, checksum) => {\n if (error) {\n callback(error);\n return;\n }\n const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);\n notify(this.delegate, \"directUploadWillCreateBlobWithXHR\", blob.xhr);\n blob.create((error => {\n if (error) {\n callback(error);\n } else {\n const upload = new BlobUpload(blob);\n notify(this.delegate, \"directUploadWillStoreFileWithXHR\", upload.xhr);\n upload.create((error => {\n if (error) {\n callback(error);\n } else {\n callback(null, blob.toJSON());\n }\n }));\n }\n }));\n }));\n }\n }\n function notify(object, methodName, ...messages) {\n if (object && typeof object[methodName] == \"function\") {\n return object[methodName](...messages);\n }\n }\n class DirectUploadController {\n constructor(input, file) {\n this.input = input;\n this.file = file;\n this.directUpload = new DirectUpload(this.file, this.url, this);\n this.dispatch(\"initialize\");\n }\n start(callback) {\n const hiddenInput = document.createElement(\"input\");\n hiddenInput.type = \"hidden\";\n hiddenInput.name = this.input.name;\n this.input.insertAdjacentElement(\"beforebegin\", hiddenInput);\n this.dispatch(\"start\");\n this.directUpload.create(((error, attributes) => {\n if (error) {\n hiddenInput.parentNode.removeChild(hiddenInput);\n this.dispatchError(error);\n } else {\n hiddenInput.value = attributes.signed_id;\n }\n this.dispatch(\"end\");\n callback(error);\n }));\n }\n uploadRequestDidProgress(event) {\n const progress = event.loaded / event.total * 90;\n if (progress) {\n this.dispatch(\"progress\", {\n progress: progress\n });\n }\n }\n get url() {\n return this.input.getAttribute(\"data-direct-upload-url\");\n }\n dispatch(name, detail = {}) {\n detail.file = this.file;\n detail.id = this.directUpload.id;\n return dispatchEvent(this.input, `direct-upload:${name}`, {\n detail: detail\n });\n }\n dispatchError(error) {\n const event = this.dispatch(\"error\", {\n error: error\n });\n if (!event.defaultPrevented) {\n alert(error);\n }\n }\n directUploadWillCreateBlobWithXHR(xhr) {\n this.dispatch(\"before-blob-request\", {\n xhr: xhr\n });\n }\n directUploadWillStoreFileWithXHR(xhr) {\n this.dispatch(\"before-storage-request\", {\n xhr: xhr\n });\n xhr.upload.addEventListener(\"progress\", (event => this.uploadRequestDidProgress(event)));\n xhr.upload.addEventListener(\"loadend\", (() => {\n this.simulateResponseProgress(xhr);\n }));\n }\n simulateResponseProgress(xhr) {\n let progress = 90;\n const startTime = Date.now();\n const updateProgress = () => {\n const elapsed = Date.now() - startTime;\n const estimatedResponseTime = this.estimateResponseTime();\n const responseProgress = Math.min(elapsed / estimatedResponseTime, 1);\n progress = 90 + responseProgress * 9;\n this.dispatch(\"progress\", {\n progress: progress\n });\n if (xhr.readyState !== XMLHttpRequest.DONE && progress < 99) {\n requestAnimationFrame(updateProgress);\n }\n };\n xhr.addEventListener(\"loadend\", (() => {\n this.dispatch(\"progress\", {\n progress: 100\n });\n }));\n requestAnimationFrame(updateProgress);\n }\n estimateResponseTime() {\n const fileSize = this.file.size;\n const MB = 1024 * 1024;\n if (fileSize < MB) {\n return 1e3;\n } else if (fileSize < 10 * MB) {\n return 2e3;\n } else {\n return 3e3 + fileSize / MB * 50;\n }\n }\n }\n const inputSelector = \"input[type=file][data-direct-upload-url]:not([disabled])\";\n class DirectUploadsController {\n constructor(form) {\n this.form = form;\n this.inputs = findElements(form, inputSelector).filter((input => input.files.length));\n }\n start(callback) {\n const controllers = this.createDirectUploadControllers();\n const startNextController = () => {\n const controller = controllers.shift();\n if (controller) {\n controller.start((error => {\n if (error) {\n callback(error);\n this.dispatch(\"end\");\n } else {\n startNextController();\n }\n }));\n } else {\n callback();\n this.dispatch(\"end\");\n }\n };\n this.dispatch(\"start\");\n startNextController();\n }\n createDirectUploadControllers() {\n const controllers = [];\n this.inputs.forEach((input => {\n toArray(input.files).forEach((file => {\n const controller = new DirectUploadController(input, file);\n controllers.push(controller);\n }));\n }));\n return controllers;\n }\n dispatch(name, detail = {}) {\n return dispatchEvent(this.form, `direct-uploads:${name}`, {\n detail: detail\n });\n }\n }\n const processingAttribute = \"data-direct-uploads-processing\";\n const submitButtonsByForm = new WeakMap;\n let started = false;\n function start() {\n if (!started) {\n started = true;\n document.addEventListener(\"click\", didClick, true);\n document.addEventListener(\"submit\", didSubmitForm, true);\n document.addEventListener(\"ajax:before\", didSubmitRemoteElement);\n }\n }\n function didClick(event) {\n const button = event.target.closest(\"button, input\");\n if (button && button.type === \"submit\" && button.form) {\n submitButtonsByForm.set(button.form, button);\n }\n }\n function didSubmitForm(event) {\n handleFormSubmissionEvent(event);\n }\n function didSubmitRemoteElement(event) {\n if (event.target.tagName == \"FORM\") {\n handleFormSubmissionEvent(event);\n }\n }\n function handleFormSubmissionEvent(event) {\n const form = event.target;\n if (form.hasAttribute(processingAttribute)) {\n event.preventDefault();\n return;\n }\n const controller = new DirectUploadsController(form);\n const {inputs: inputs} = controller;\n if (inputs.length) {\n event.preventDefault();\n form.setAttribute(processingAttribute, \"\");\n inputs.forEach(disable);\n controller.start((error => {\n form.removeAttribute(processingAttribute);\n if (error) {\n inputs.forEach(enable);\n } else {\n submitForm(form);\n }\n }));\n }\n }\n function submitForm(form) {\n let button = submitButtonsByForm.get(form) || findElement(form, \"input[type=submit], button[type=submit]\");\n if (button) {\n const {disabled: disabled} = button;\n button.disabled = false;\n button.focus();\n button.click();\n button.disabled = disabled;\n } else {\n button = document.createElement(\"input\");\n button.type = \"submit\";\n button.style.display = \"none\";\n form.appendChild(button);\n button.click();\n form.removeChild(button);\n }\n submitButtonsByForm.delete(form);\n }\n function disable(input) {\n input.disabled = true;\n }\n function enable(input) {\n input.disabled = false;\n }\n function autostart() {\n if (window.ActiveStorage) {\n start();\n }\n }\n setTimeout(autostart, 1);\n exports.DirectUpload = DirectUpload;\n exports.DirectUploadController = DirectUploadController;\n exports.DirectUploadsController = DirectUploadsController;\n exports.dispatchEvent = dispatchEvent;\n exports.start = start;\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n}));\n", "!function(e,t){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=t():\"function\"==typeof define&&define.amd?define(t):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).LocalTime=t()}(this,(function(){\"use strict\";var e;e={config:{},run:function(){return this.getController().processElements()},process:function(...e){var t,r,n;for(r=0,n=e.length;r11?\"pm\":\"am\")).toUpperCase();case\"P\":return M(\"time.\"+(a>11?\"pm\":\"am\"));case\"S\":return p(o,l);case\"w\":return n;case\"y\":return p(u%100,l);case\"Y\":return u;case\"Z\":return y(e)}}))},p=function(e,t){return\"-\"===t?e:`0${e}`.slice(-2)},y=function(e){var t,r,n;return(r=h(e))?g[r]:(n=v(e,{allowGMT:!1}))||(n=S(e))?n:(t=v(e,{allowGMT:!0}))?t:\"\"},h=function(e){return Object.keys(g).find((function(t){return b?new Date(e).toLocaleString(\"en-US\",{timeZoneName:\"long\"}).includes(t):e.toString().includes(t)}))},v=function(e,{allowGMT:t}){var r;if(b&&(r=new Date(e).toLocaleString(\"en-US\",{timeZoneName:\"short\"}).split(\" \").pop(),t||!r.includes(\"GMT\")))return r},S=function(e){var t,r,n,a,i;return(t=null!=(r=(i=e.toString()).match(/\\(([\\w\\s]+)\\)$/))?r[1]:void 0)?/\\s/.test(t)?t.match(/\\b(\\w)/g).join(\"\"):t:(t=null!=(n=i.match(/(\\w{3,4})\\s\\d{4}$/))?n[1]:void 0)||(t=null!=(a=i.match(/(UTC[\\+\\-]\\d+)/))?a[1]:void 0)?t:void 0},W.CalendarDate=class{static fromDate(e){return new this(e.getFullYear(),e.getMonth()+1,e.getDate())}static today(){return this.fromDate(new Date)}constructor(e,t,r){this.date=new Date(Date.UTC(e,t-1)),this.date.setUTCDate(r),this.year=this.date.getUTCFullYear(),this.month=this.date.getUTCMonth()+1,this.day=this.date.getUTCDate(),this.value=this.date.getTime()}equals(e){return(null!=e?e.value:void 0)===this.value}is(e){return this.equals(e)}isToday(){return this.is(this.constructor.today())}occursOnSameYearAs(e){return this.year===(null!=e?e.year:void 0)}occursThisYear(){return this.occursOnSameYearAs(this.constructor.today())}daysSince(e){if(e)return(this.date-e.date)/864e5}daysPassed(){return this.constructor.today().daysSince(this)}},({strftime:E,translate:I,getI18nValue:w,config:D}=W),W.RelativeTime=class{constructor(e){this.date=e,this.calendarDate=W.CalendarDate.fromDate(this.date)}toString(){var e,t;return(t=this.toTimeElapsedString())?I(\"time.elapsed\",{time:t}):(e=this.toWeekdayString())?(t=this.toTimeString(),I(\"datetime.at\",{date:e,time:t})):I(\"date.on\",{date:this.toDateString()})}toTimeOrDateString(){return this.calendarDate.isToday()?this.toTimeString():this.toDateString()}toTimeElapsedString(){var e,t,r,n,a;return r=(new Date).getTime()-this.date.getTime(),n=Math.round(r/1e3),t=Math.round(n/60),e=Math.round(t/60),r<0?null:n<10?(a=I(\"time.second\"),I(\"time.singular\",{time:a})):n<45?`${n} ${I(\"time.seconds\")}`:n<90?(a=I(\"time.minute\"),I(\"time.singular\",{time:a})):t<45?`${t} ${I(\"time.minutes\")}`:t<90?(a=I(\"time.hour\"),I(\"time.singularAn\",{time:a})):e<24?`${e} ${I(\"time.hours\")}`:\"\"}toWeekdayString(){switch(this.calendarDate.daysPassed()){case 0:return I(\"date.today\");case 1:return I(\"date.yesterday\");case-1:return I(\"date.tomorrow\");case 2:case 3:case 4:case 5:case 6:return E(this.date,\"%A\");default:return\"\"}}toDateString(){var e;return e=this.calendarDate.occursThisYear()?w(\"date.formats.thisYear\"):w(\"date.formats.default\"),E(this.date,e)}toTimeString(){var e;return e=D.useFormat24?\"default_24h\":\"default\",E(this.date,w(`time.formats.${e}`))}},({elementMatchesSelector:C}=W),W.PageObserver=class{constructor(e,t){this.processMutations=this.processMutations.bind(this),this.processInsertion=this.processInsertion.bind(this),this.selector=e,this.callback=t}start(){if(!this.started)return this.observeWithMutationObserver()||this.observeWithMutationEvent(),this.started=!0}observeWithMutationObserver(){if(\"undefined\"!=typeof MutationObserver&&null!==MutationObserver)return new MutationObserver(this.processMutations).observe(document.documentElement,{childList:!0,subtree:!0}),!0}observeWithMutationEvent(){return addEventListener(\"DOMNodeInserted\",this.processInsertion,!1),!0}findSignificantElements(e){var t;return t=[],(null!=e?e.nodeType:void 0)===Node.ELEMENT_NODE&&(C(e,this.selector)&&t.push(e),t.push(...e.querySelectorAll(this.selector))),t}processMutations(e){var t,r,n,a,i,s,o,u;for(t=[],r=0,a=e.length;r\n * \n * Show all expanded messages in this frame.\n * \n *\n *
    \n * Show response from this form within this frame.\n *
    \n * \n */\nclass FrameElement extends HTMLElement {\n static delegateConstructor = undefined\n\n loaded = Promise.resolve()\n\n static get observedAttributes() {\n return [\"disabled\", \"loading\", \"src\"]\n }\n\n constructor() {\n super();\n this.delegate = new FrameElement.delegateConstructor(this);\n }\n\n connectedCallback() {\n this.delegate.connect();\n }\n\n disconnectedCallback() {\n this.delegate.disconnect();\n }\n\n reload() {\n return this.delegate.sourceURLReloaded()\n }\n\n attributeChangedCallback(name) {\n if (name == \"loading\") {\n this.delegate.loadingStyleChanged();\n } else if (name == \"src\") {\n this.delegate.sourceURLChanged();\n } else if (name == \"disabled\") {\n this.delegate.disabledChanged();\n }\n }\n\n /**\n * Gets the URL to lazily load source HTML from\n */\n get src() {\n return this.getAttribute(\"src\")\n }\n\n /**\n * Sets the URL to lazily load source HTML from\n */\n set src(value) {\n if (value) {\n this.setAttribute(\"src\", value);\n } else {\n this.removeAttribute(\"src\");\n }\n }\n\n /**\n * Gets the refresh mode for the frame.\n */\n get refresh() {\n return this.getAttribute(\"refresh\")\n }\n\n /**\n * Sets the refresh mode for the frame.\n */\n set refresh(value) {\n if (value) {\n this.setAttribute(\"refresh\", value);\n } else {\n this.removeAttribute(\"refresh\");\n }\n }\n\n get shouldReloadWithMorph() {\n return this.src && this.refresh === \"morph\"\n }\n\n /**\n * Determines if the element is loading\n */\n get loading() {\n return frameLoadingStyleFromString(this.getAttribute(\"loading\") || \"\")\n }\n\n /**\n * Sets the value of if the element is loading\n */\n set loading(value) {\n if (value) {\n this.setAttribute(\"loading\", value);\n } else {\n this.removeAttribute(\"loading\");\n }\n }\n\n /**\n * Gets the disabled state of the frame.\n *\n * If disabled, no requests will be intercepted by the frame.\n */\n get disabled() {\n return this.hasAttribute(\"disabled\")\n }\n\n /**\n * Sets the disabled state of the frame.\n *\n * If disabled, no requests will be intercepted by the frame.\n */\n set disabled(value) {\n if (value) {\n this.setAttribute(\"disabled\", \"\");\n } else {\n this.removeAttribute(\"disabled\");\n }\n }\n\n /**\n * Gets the autoscroll state of the frame.\n *\n * If true, the frame will be scrolled into view automatically on update.\n */\n get autoscroll() {\n return this.hasAttribute(\"autoscroll\")\n }\n\n /**\n * Sets the autoscroll state of the frame.\n *\n * If true, the frame will be scrolled into view automatically on update.\n */\n set autoscroll(value) {\n if (value) {\n this.setAttribute(\"autoscroll\", \"\");\n } else {\n this.removeAttribute(\"autoscroll\");\n }\n }\n\n /**\n * Determines if the element has finished loading\n */\n get complete() {\n return !this.delegate.isLoading\n }\n\n /**\n * Gets the active state of the frame.\n *\n * If inactive, source changes will not be observed.\n */\n get isActive() {\n return this.ownerDocument === document && !this.isPreview\n }\n\n /**\n * Sets the active state of the frame.\n *\n * If inactive, source changes will not be observed.\n */\n get isPreview() {\n return this.ownerDocument?.documentElement?.hasAttribute(\"data-turbo-preview\")\n }\n}\n\nfunction frameLoadingStyleFromString(style) {\n switch (style.toLowerCase()) {\n case \"lazy\":\n return FrameLoadingStyle.lazy\n default:\n return FrameLoadingStyle.eager\n }\n}\n\nconst drive = {\n enabled: true,\n progressBarDelay: 500,\n unvisitableExtensions: new Set(\n [\n \".7z\", \".aac\", \".apk\", \".avi\", \".bmp\", \".bz2\", \".css\", \".csv\", \".deb\", \".dmg\", \".doc\",\n \".docx\", \".exe\", \".gif\", \".gz\", \".heic\", \".heif\", \".ico\", \".iso\", \".jpeg\", \".jpg\",\n \".js\", \".json\", \".m4a\", \".mkv\", \".mov\", \".mp3\", \".mp4\", \".mpeg\", \".mpg\", \".msi\",\n \".ogg\", \".ogv\", \".pdf\", \".pkg\", \".png\", \".ppt\", \".pptx\", \".rar\", \".rtf\",\n \".svg\", \".tar\", \".tif\", \".tiff\", \".txt\", \".wav\", \".webm\", \".webp\", \".wma\", \".wmv\",\n \".xls\", \".xlsx\", \".xml\", \".zip\"\n ]\n )\n};\n\nfunction activateScriptElement(element) {\n if (element.getAttribute(\"data-turbo-eval\") == \"false\") {\n return element\n } else {\n const createdScriptElement = document.createElement(\"script\");\n const cspNonce = getCspNonce();\n if (cspNonce) {\n createdScriptElement.nonce = cspNonce;\n }\n createdScriptElement.textContent = element.textContent;\n createdScriptElement.async = false;\n copyElementAttributes(createdScriptElement, element);\n return createdScriptElement\n }\n}\n\nfunction copyElementAttributes(destinationElement, sourceElement) {\n for (const { name, value } of sourceElement.attributes) {\n destinationElement.setAttribute(name, value);\n }\n}\n\nfunction createDocumentFragment(html) {\n const template = document.createElement(\"template\");\n template.innerHTML = html;\n return template.content\n}\n\nfunction dispatch(eventName, { target, cancelable, detail } = {}) {\n const event = new CustomEvent(eventName, {\n cancelable,\n bubbles: true,\n composed: true,\n detail\n });\n\n if (target && target.isConnected) {\n target.dispatchEvent(event);\n } else {\n document.documentElement.dispatchEvent(event);\n }\n\n return event\n}\n\nfunction cancelEvent(event) {\n event.preventDefault();\n event.stopImmediatePropagation();\n}\n\nfunction nextRepaint() {\n if (document.visibilityState === \"hidden\") {\n return nextEventLoopTick()\n } else {\n return nextAnimationFrame()\n }\n}\n\nfunction nextAnimationFrame() {\n return new Promise((resolve) => requestAnimationFrame(() => resolve()))\n}\n\nfunction nextEventLoopTick() {\n return new Promise((resolve) => setTimeout(() => resolve(), 0))\n}\n\nfunction parseHTMLDocument(html = \"\") {\n return new DOMParser().parseFromString(html, \"text/html\")\n}\n\nfunction unindent(strings, ...values) {\n const lines = interpolate(strings, values).replace(/^\\n/, \"\").split(\"\\n\");\n const match = lines[0].match(/^\\s+/);\n const indent = match ? match[0].length : 0;\n return lines.map((line) => line.slice(indent)).join(\"\\n\")\n}\n\nfunction interpolate(strings, values) {\n return strings.reduce((result, string, i) => {\n const value = values[i] == undefined ? \"\" : values[i];\n return result + string + value\n }, \"\")\n}\n\nfunction uuid() {\n return Array.from({ length: 36 })\n .map((_, i) => {\n if (i == 8 || i == 13 || i == 18 || i == 23) {\n return \"-\"\n } else if (i == 14) {\n return \"4\"\n } else if (i == 19) {\n return (Math.floor(Math.random() * 4) + 8).toString(16)\n } else {\n return Math.floor(Math.random() * 16).toString(16)\n }\n })\n .join(\"\")\n}\n\nfunction getAttribute(attributeName, ...elements) {\n for (const value of elements.map((element) => element?.getAttribute(attributeName))) {\n if (typeof value == \"string\") return value\n }\n\n return null\n}\n\nfunction hasAttribute(attributeName, ...elements) {\n return elements.some((element) => element && element.hasAttribute(attributeName))\n}\n\nfunction markAsBusy(...elements) {\n for (const element of elements) {\n if (element.localName == \"turbo-frame\") {\n element.setAttribute(\"busy\", \"\");\n }\n element.setAttribute(\"aria-busy\", \"true\");\n }\n}\n\nfunction clearBusyState(...elements) {\n for (const element of elements) {\n if (element.localName == \"turbo-frame\") {\n element.removeAttribute(\"busy\");\n }\n\n element.removeAttribute(\"aria-busy\");\n }\n}\n\nfunction waitForLoad(element, timeoutInMilliseconds = 2000) {\n return new Promise((resolve) => {\n const onComplete = () => {\n element.removeEventListener(\"error\", onComplete);\n element.removeEventListener(\"load\", onComplete);\n resolve();\n };\n\n element.addEventListener(\"load\", onComplete, { once: true });\n element.addEventListener(\"error\", onComplete, { once: true });\n setTimeout(resolve, timeoutInMilliseconds);\n })\n}\n\nfunction getHistoryMethodForAction(action) {\n switch (action) {\n case \"replace\":\n return history.replaceState\n case \"advance\":\n case \"restore\":\n return history.pushState\n }\n}\n\nfunction isAction(action) {\n return action == \"advance\" || action == \"replace\" || action == \"restore\"\n}\n\nfunction getVisitAction(...elements) {\n const action = getAttribute(\"data-turbo-action\", ...elements);\n\n return isAction(action) ? action : null\n}\n\nfunction getMetaElement(name) {\n return document.querySelector(`meta[name=\"${name}\"]`)\n}\n\nfunction getMetaContent(name) {\n const element = getMetaElement(name);\n return element && element.content\n}\n\nfunction getCspNonce() {\n const element = getMetaElement(\"csp-nonce\");\n\n if (element) {\n const { nonce, content } = element;\n return nonce == \"\" ? content : nonce\n }\n}\n\nfunction setMetaContent(name, content) {\n let element = getMetaElement(name);\n\n if (!element) {\n element = document.createElement(\"meta\");\n element.setAttribute(\"name\", name);\n\n document.head.appendChild(element);\n }\n\n element.setAttribute(\"content\", content);\n\n return element\n}\n\nfunction findClosestRecursively(element, selector) {\n if (element instanceof Element) {\n return (\n element.closest(selector) || findClosestRecursively(element.assignedSlot || element.getRootNode()?.host, selector)\n )\n }\n}\n\nfunction elementIsFocusable(element) {\n const inertDisabledOrHidden = \"[inert], :disabled, [hidden], details:not([open]), dialog:not([open])\";\n\n return !!element && element.closest(inertDisabledOrHidden) == null && typeof element.focus == \"function\"\n}\n\nfunction queryAutofocusableElement(elementOrDocumentFragment) {\n return Array.from(elementOrDocumentFragment.querySelectorAll(\"[autofocus]\")).find(elementIsFocusable)\n}\n\nasync function around(callback, reader) {\n const before = reader();\n\n callback();\n\n await nextAnimationFrame();\n\n const after = reader();\n\n return [before, after]\n}\n\nfunction doesNotTargetIFrame(name) {\n if (name === \"_blank\") {\n return false\n } else if (name) {\n for (const element of document.getElementsByName(name)) {\n if (element instanceof HTMLIFrameElement) return false\n }\n\n return true\n } else {\n return true\n }\n}\n\nfunction findLinkFromClickTarget(target) {\n const link = findClosestRecursively(target, \"a[href], a[xlink\\\\:href]\");\n\n if (!link) return null\n if (link.href.startsWith(\"#\")) return null\n if (link.hasAttribute(\"download\")) return null\n\n const linkTarget = link.getAttribute(\"target\");\n if (linkTarget && linkTarget !== \"_self\") return null\n\n return link\n}\n\nfunction debounce(fn, delay) {\n let timeoutId = null;\n\n return (...args) => {\n const callback = () => fn.apply(this, args);\n clearTimeout(timeoutId);\n timeoutId = setTimeout(callback, delay);\n }\n}\n\nconst submitter = {\n \"aria-disabled\": {\n beforeSubmit: submitter => {\n submitter.setAttribute(\"aria-disabled\", \"true\");\n submitter.addEventListener(\"click\", cancelEvent);\n },\n\n afterSubmit: submitter => {\n submitter.removeAttribute(\"aria-disabled\");\n submitter.removeEventListener(\"click\", cancelEvent);\n }\n },\n\n \"disabled\": {\n beforeSubmit: submitter => submitter.disabled = true,\n afterSubmit: submitter => submitter.disabled = false\n }\n};\n\nclass Config {\n #submitter = null\n\n constructor(config) {\n Object.assign(this, config);\n }\n\n get submitter() {\n return this.#submitter\n }\n\n set submitter(value) {\n this.#submitter = submitter[value] || value;\n }\n}\n\nconst forms = new Config({\n mode: \"on\",\n submitter: \"disabled\"\n});\n\nconst config = {\n drive,\n forms\n};\n\nfunction expandURL(locatable) {\n return new URL(locatable.toString(), document.baseURI)\n}\n\nfunction getAnchor(url) {\n let anchorMatch;\n if (url.hash) {\n return url.hash.slice(1)\n // eslint-disable-next-line no-cond-assign\n } else if ((anchorMatch = url.href.match(/#(.*)$/))) {\n return anchorMatch[1]\n }\n}\n\nfunction getAction$1(form, submitter) {\n const action = submitter?.getAttribute(\"formaction\") || form.getAttribute(\"action\") || form.action;\n\n return expandURL(action)\n}\n\nfunction getExtension(url) {\n return (getLastPathComponent(url).match(/\\.[^.]*$/) || [])[0] || \"\"\n}\n\nfunction isPrefixedBy(baseURL, url) {\n const prefix = addTrailingSlash(url.origin + url.pathname);\n return addTrailingSlash(baseURL.href) === prefix || baseURL.href.startsWith(prefix)\n}\n\nfunction locationIsVisitable(location, rootLocation) {\n return isPrefixedBy(location, rootLocation) && !config.drive.unvisitableExtensions.has(getExtension(location))\n}\n\nfunction getLocationForLink(link) {\n return expandURL(link.getAttribute(\"href\") || \"\")\n}\n\nfunction getRequestURL(url) {\n const anchor = getAnchor(url);\n return anchor != null ? url.href.slice(0, -(anchor.length + 1)) : url.href\n}\n\nfunction toCacheKey(url) {\n return getRequestURL(url)\n}\n\nfunction urlsAreEqual(left, right) {\n return expandURL(left).href == expandURL(right).href\n}\n\nfunction getPathComponents(url) {\n return url.pathname.split(\"/\").slice(1)\n}\n\nfunction getLastPathComponent(url) {\n return getPathComponents(url).slice(-1)[0]\n}\n\nfunction addTrailingSlash(value) {\n return value.endsWith(\"/\") ? value : value + \"/\"\n}\n\nclass FetchResponse {\n constructor(response) {\n this.response = response;\n }\n\n get succeeded() {\n return this.response.ok\n }\n\n get failed() {\n return !this.succeeded\n }\n\n get clientError() {\n return this.statusCode >= 400 && this.statusCode <= 499\n }\n\n get serverError() {\n return this.statusCode >= 500 && this.statusCode <= 599\n }\n\n get redirected() {\n return this.response.redirected\n }\n\n get location() {\n return expandURL(this.response.url)\n }\n\n get isHTML() {\n return this.contentType && this.contentType.match(/^(?:text\\/([^\\s;,]+\\b)?html|application\\/xhtml\\+xml)\\b/)\n }\n\n get statusCode() {\n return this.response.status\n }\n\n get contentType() {\n return this.header(\"Content-Type\")\n }\n\n get responseText() {\n return this.response.clone().text()\n }\n\n get responseHTML() {\n if (this.isHTML) {\n return this.response.clone().text()\n } else {\n return Promise.resolve(undefined)\n }\n }\n\n header(name) {\n return this.response.headers.get(name)\n }\n}\n\nclass LimitedSet extends Set {\n constructor(maxSize) {\n super();\n this.maxSize = maxSize;\n }\n\n add(value) {\n if (this.size >= this.maxSize) {\n const iterator = this.values();\n const oldestValue = iterator.next().value;\n this.delete(oldestValue);\n }\n super.add(value);\n }\n}\n\nconst recentRequests = new LimitedSet(20);\n\nfunction fetchWithTurboHeaders(url, options = {}) {\n const modifiedHeaders = new Headers(options.headers || {});\n const requestUID = uuid();\n recentRequests.add(requestUID);\n modifiedHeaders.append(\"X-Turbo-Request-Id\", requestUID);\n\n return window.fetch(url, {\n ...options,\n headers: modifiedHeaders\n })\n}\n\nfunction fetchMethodFromString(method) {\n switch (method.toLowerCase()) {\n case \"get\":\n return FetchMethod.get\n case \"post\":\n return FetchMethod.post\n case \"put\":\n return FetchMethod.put\n case \"patch\":\n return FetchMethod.patch\n case \"delete\":\n return FetchMethod.delete\n }\n}\n\nconst FetchMethod = {\n get: \"get\",\n post: \"post\",\n put: \"put\",\n patch: \"patch\",\n delete: \"delete\"\n};\n\nfunction fetchEnctypeFromString(encoding) {\n switch (encoding.toLowerCase()) {\n case FetchEnctype.multipart:\n return FetchEnctype.multipart\n case FetchEnctype.plain:\n return FetchEnctype.plain\n default:\n return FetchEnctype.urlEncoded\n }\n}\n\nconst FetchEnctype = {\n urlEncoded: \"application/x-www-form-urlencoded\",\n multipart: \"multipart/form-data\",\n plain: \"text/plain\"\n};\n\nclass FetchRequest {\n abortController = new AbortController()\n #resolveRequestPromise = (_value) => {}\n\n constructor(delegate, method, location, requestBody = new URLSearchParams(), target = null, enctype = FetchEnctype.urlEncoded) {\n const [url, body] = buildResourceAndBody(expandURL(location), method, requestBody, enctype);\n\n this.delegate = delegate;\n this.url = url;\n this.target = target;\n this.fetchOptions = {\n credentials: \"same-origin\",\n redirect: \"follow\",\n method: method.toUpperCase(),\n headers: { ...this.defaultHeaders },\n body: body,\n signal: this.abortSignal,\n referrer: this.delegate.referrer?.href\n };\n this.enctype = enctype;\n }\n\n get method() {\n return this.fetchOptions.method\n }\n\n set method(value) {\n const fetchBody = this.isSafe ? this.url.searchParams : this.fetchOptions.body || new FormData();\n const fetchMethod = fetchMethodFromString(value) || FetchMethod.get;\n\n this.url.search = \"\";\n\n const [url, body] = buildResourceAndBody(this.url, fetchMethod, fetchBody, this.enctype);\n\n this.url = url;\n this.fetchOptions.body = body;\n this.fetchOptions.method = fetchMethod.toUpperCase();\n }\n\n get headers() {\n return this.fetchOptions.headers\n }\n\n set headers(value) {\n this.fetchOptions.headers = value;\n }\n\n get body() {\n if (this.isSafe) {\n return this.url.searchParams\n } else {\n return this.fetchOptions.body\n }\n }\n\n set body(value) {\n this.fetchOptions.body = value;\n }\n\n get location() {\n return this.url\n }\n\n get params() {\n return this.url.searchParams\n }\n\n get entries() {\n return this.body ? Array.from(this.body.entries()) : []\n }\n\n cancel() {\n this.abortController.abort();\n }\n\n async perform() {\n const { fetchOptions } = this;\n this.delegate.prepareRequest(this);\n const event = await this.#allowRequestToBeIntercepted(fetchOptions);\n try {\n this.delegate.requestStarted(this);\n\n if (event.detail.fetchRequest) {\n this.response = event.detail.fetchRequest.response;\n } else {\n this.response = fetchWithTurboHeaders(this.url.href, fetchOptions);\n }\n\n const response = await this.response;\n return await this.receive(response)\n } catch (error) {\n if (error.name !== \"AbortError\") {\n if (this.#willDelegateErrorHandling(error)) {\n this.delegate.requestErrored(this, error);\n }\n throw error\n }\n } finally {\n this.delegate.requestFinished(this);\n }\n }\n\n async receive(response) {\n const fetchResponse = new FetchResponse(response);\n const event = dispatch(\"turbo:before-fetch-response\", {\n cancelable: true,\n detail: { fetchResponse },\n target: this.target\n });\n if (event.defaultPrevented) {\n this.delegate.requestPreventedHandlingResponse(this, fetchResponse);\n } else if (fetchResponse.succeeded) {\n this.delegate.requestSucceededWithResponse(this, fetchResponse);\n } else {\n this.delegate.requestFailedWithResponse(this, fetchResponse);\n }\n return fetchResponse\n }\n\n get defaultHeaders() {\n return {\n Accept: \"text/html, application/xhtml+xml\"\n }\n }\n\n get isSafe() {\n return isSafe(this.method)\n }\n\n get abortSignal() {\n return this.abortController.signal\n }\n\n acceptResponseType(mimeType) {\n this.headers[\"Accept\"] = [mimeType, this.headers[\"Accept\"]].join(\", \");\n }\n\n async #allowRequestToBeIntercepted(fetchOptions) {\n const requestInterception = new Promise((resolve) => (this.#resolveRequestPromise = resolve));\n const event = dispatch(\"turbo:before-fetch-request\", {\n cancelable: true,\n detail: {\n fetchOptions,\n url: this.url,\n resume: this.#resolveRequestPromise\n },\n target: this.target\n });\n this.url = event.detail.url;\n if (event.defaultPrevented) await requestInterception;\n\n return event\n }\n\n #willDelegateErrorHandling(error) {\n const event = dispatch(\"turbo:fetch-request-error\", {\n target: this.target,\n cancelable: true,\n detail: { request: this, error: error }\n });\n\n return !event.defaultPrevented\n }\n}\n\nfunction isSafe(fetchMethod) {\n return fetchMethodFromString(fetchMethod) == FetchMethod.get\n}\n\nfunction buildResourceAndBody(resource, method, requestBody, enctype) {\n const searchParams =\n Array.from(requestBody).length > 0 ? new URLSearchParams(entriesExcludingFiles(requestBody)) : resource.searchParams;\n\n if (isSafe(method)) {\n return [mergeIntoURLSearchParams(resource, searchParams), null]\n } else if (enctype == FetchEnctype.urlEncoded) {\n return [resource, searchParams]\n } else {\n return [resource, requestBody]\n }\n}\n\nfunction entriesExcludingFiles(requestBody) {\n const entries = [];\n\n for (const [name, value] of requestBody) {\n if (value instanceof File) continue\n else entries.push([name, value]);\n }\n\n return entries\n}\n\nfunction mergeIntoURLSearchParams(url, requestBody) {\n const searchParams = new URLSearchParams(entriesExcludingFiles(requestBody));\n\n url.search = searchParams.toString();\n\n return url\n}\n\nclass AppearanceObserver {\n started = false\n\n constructor(delegate, element) {\n this.delegate = delegate;\n this.element = element;\n this.intersectionObserver = new IntersectionObserver(this.intersect);\n }\n\n start() {\n if (!this.started) {\n this.started = true;\n this.intersectionObserver.observe(this.element);\n }\n }\n\n stop() {\n if (this.started) {\n this.started = false;\n this.intersectionObserver.unobserve(this.element);\n }\n }\n\n intersect = (entries) => {\n const lastEntry = entries.slice(-1)[0];\n if (lastEntry?.isIntersecting) {\n this.delegate.elementAppearedInViewport(this.element);\n }\n }\n}\n\nclass StreamMessage {\n static contentType = \"text/vnd.turbo-stream.html\"\n\n static wrap(message) {\n if (typeof message == \"string\") {\n return new this(createDocumentFragment(message))\n } else {\n return message\n }\n }\n\n constructor(fragment) {\n this.fragment = importStreamElements(fragment);\n }\n}\n\nfunction importStreamElements(fragment) {\n for (const element of fragment.querySelectorAll(\"turbo-stream\")) {\n const streamElement = document.importNode(element, true);\n\n for (const inertScriptElement of streamElement.templateElement.content.querySelectorAll(\"script\")) {\n inertScriptElement.replaceWith(activateScriptElement(inertScriptElement));\n }\n\n element.replaceWith(streamElement);\n }\n\n return fragment\n}\n\nconst identity = key => key;\n\nclass LRUCache {\n keys = []\n entries = {}\n #toCacheKey\n\n constructor(size, toCacheKey = identity) {\n this.size = size;\n this.#toCacheKey = toCacheKey;\n }\n\n has(key) {\n return this.#toCacheKey(key) in this.entries\n }\n\n get(key) {\n if (this.has(key)) {\n const entry = this.read(key);\n this.touch(key);\n return entry\n }\n }\n\n put(key, entry) {\n this.write(key, entry);\n this.touch(key);\n return entry\n }\n\n clear() {\n for (const key of Object.keys(this.entries)) {\n this.evict(key);\n }\n }\n\n // Private\n\n read(key) {\n return this.entries[this.#toCacheKey(key)]\n }\n\n write(key, entry) {\n this.entries[this.#toCacheKey(key)] = entry;\n }\n\n touch(key) {\n key = this.#toCacheKey(key);\n const index = this.keys.indexOf(key);\n if (index > -1) this.keys.splice(index, 1);\n this.keys.unshift(key);\n this.trim();\n }\n\n trim() {\n for (const key of this.keys.splice(this.size)) {\n this.evict(key);\n }\n }\n\n evict(key) {\n delete this.entries[key];\n }\n}\n\nconst PREFETCH_DELAY = 100;\n\nclass PrefetchCache extends LRUCache {\n #prefetchTimeout = null\n #maxAges = {}\n\n constructor(size = 1, prefetchDelay = PREFETCH_DELAY) {\n super(size, toCacheKey);\n this.prefetchDelay = prefetchDelay;\n }\n\n putLater(url, request, ttl) {\n this.#prefetchTimeout = setTimeout(() => {\n request.perform();\n this.put(url, request, ttl);\n this.#prefetchTimeout = null;\n }, this.prefetchDelay);\n }\n\n put(url, request, ttl = cacheTtl) {\n super.put(url, request);\n this.#maxAges[toCacheKey(url)] = new Date(new Date().getTime() + ttl);\n }\n\n clear() {\n super.clear();\n if (this.#prefetchTimeout) clearTimeout(this.#prefetchTimeout);\n }\n\n evict(key) {\n super.evict(key);\n delete this.#maxAges[key];\n }\n\n has(key) {\n if (super.has(key)) {\n const maxAge = this.#maxAges[toCacheKey(key)];\n\n return maxAge && maxAge > Date.now()\n } else {\n return false\n }\n }\n}\n\nconst cacheTtl = 10 * 1000;\nconst prefetchCache = new PrefetchCache();\n\nconst FormSubmissionState = {\n initialized: \"initialized\",\n requesting: \"requesting\",\n waiting: \"waiting\",\n receiving: \"receiving\",\n stopping: \"stopping\",\n stopped: \"stopped\"\n};\n\nclass FormSubmission {\n state = FormSubmissionState.initialized\n\n static confirmMethod(message) {\n return Promise.resolve(confirm(message))\n }\n\n constructor(delegate, formElement, submitter, mustRedirect = false) {\n const method = getMethod(formElement, submitter);\n const action = getAction(getFormAction(formElement, submitter), method);\n const body = buildFormData(formElement, submitter);\n const enctype = getEnctype(formElement, submitter);\n\n this.delegate = delegate;\n this.formElement = formElement;\n this.submitter = submitter;\n this.fetchRequest = new FetchRequest(this, method, action, body, formElement, enctype);\n this.mustRedirect = mustRedirect;\n }\n\n get method() {\n return this.fetchRequest.method\n }\n\n set method(value) {\n this.fetchRequest.method = value;\n }\n\n get action() {\n return this.fetchRequest.url.toString()\n }\n\n set action(value) {\n this.fetchRequest.url = expandURL(value);\n }\n\n get body() {\n return this.fetchRequest.body\n }\n\n get enctype() {\n return this.fetchRequest.enctype\n }\n\n get isSafe() {\n return this.fetchRequest.isSafe\n }\n\n get location() {\n return this.fetchRequest.url\n }\n\n // The submission process\n\n async start() {\n const { initialized, requesting } = FormSubmissionState;\n const confirmationMessage = getAttribute(\"data-turbo-confirm\", this.submitter, this.formElement);\n\n if (typeof confirmationMessage === \"string\") {\n const confirmMethod = typeof config.forms.confirm === \"function\" ?\n config.forms.confirm :\n FormSubmission.confirmMethod;\n\n const answer = await confirmMethod(confirmationMessage, this.formElement, this.submitter);\n if (!answer) {\n return\n }\n }\n\n if (this.state == initialized) {\n this.state = requesting;\n return this.fetchRequest.perform()\n }\n }\n\n stop() {\n const { stopping, stopped } = FormSubmissionState;\n if (this.state != stopping && this.state != stopped) {\n this.state = stopping;\n this.fetchRequest.cancel();\n return true\n }\n }\n\n // Fetch request delegate\n\n prepareRequest(request) {\n if (!request.isSafe) {\n const token = getCookieValue(getMetaContent(\"csrf-param\")) || getMetaContent(\"csrf-token\");\n if (token) {\n request.headers[\"X-CSRF-Token\"] = token;\n }\n }\n\n if (this.requestAcceptsTurboStreamResponse(request)) {\n request.acceptResponseType(StreamMessage.contentType);\n }\n }\n\n requestStarted(_request) {\n this.state = FormSubmissionState.waiting;\n if (this.submitter) config.forms.submitter.beforeSubmit(this.submitter);\n this.setSubmitsWith();\n markAsBusy(this.formElement);\n dispatch(\"turbo:submit-start\", {\n target: this.formElement,\n detail: { formSubmission: this }\n });\n this.delegate.formSubmissionStarted(this);\n }\n\n requestPreventedHandlingResponse(request, response) {\n prefetchCache.clear();\n\n this.result = { success: response.succeeded, fetchResponse: response };\n }\n\n requestSucceededWithResponse(request, response) {\n if (response.clientError || response.serverError) {\n this.delegate.formSubmissionFailedWithResponse(this, response);\n return\n }\n\n prefetchCache.clear();\n\n if (this.requestMustRedirect(request) && responseSucceededWithoutRedirect(response)) {\n const error = new Error(\"Form responses must redirect to another location\");\n this.delegate.formSubmissionErrored(this, error);\n } else {\n this.state = FormSubmissionState.receiving;\n this.result = { success: true, fetchResponse: response };\n this.delegate.formSubmissionSucceededWithResponse(this, response);\n }\n }\n\n requestFailedWithResponse(request, response) {\n this.result = { success: false, fetchResponse: response };\n this.delegate.formSubmissionFailedWithResponse(this, response);\n }\n\n requestErrored(request, error) {\n this.result = { success: false, error };\n this.delegate.formSubmissionErrored(this, error);\n }\n\n requestFinished(_request) {\n this.state = FormSubmissionState.stopped;\n if (this.submitter) config.forms.submitter.afterSubmit(this.submitter);\n this.resetSubmitterText();\n clearBusyState(this.formElement);\n dispatch(\"turbo:submit-end\", {\n target: this.formElement,\n detail: { formSubmission: this, ...this.result }\n });\n this.delegate.formSubmissionFinished(this);\n }\n\n // Private\n\n setSubmitsWith() {\n if (!this.submitter || !this.submitsWith) return\n\n if (this.submitter.matches(\"button\")) {\n this.originalSubmitText = this.submitter.innerHTML;\n this.submitter.innerHTML = this.submitsWith;\n } else if (this.submitter.matches(\"input\")) {\n const input = this.submitter;\n this.originalSubmitText = input.value;\n input.value = this.submitsWith;\n }\n }\n\n resetSubmitterText() {\n if (!this.submitter || !this.originalSubmitText) return\n\n if (this.submitter.matches(\"button\")) {\n this.submitter.innerHTML = this.originalSubmitText;\n } else if (this.submitter.matches(\"input\")) {\n const input = this.submitter;\n input.value = this.originalSubmitText;\n }\n }\n\n requestMustRedirect(request) {\n return !request.isSafe && this.mustRedirect\n }\n\n requestAcceptsTurboStreamResponse(request) {\n return !request.isSafe || hasAttribute(\"data-turbo-stream\", this.submitter, this.formElement)\n }\n\n get submitsWith() {\n return this.submitter?.getAttribute(\"data-turbo-submits-with\")\n }\n}\n\nfunction buildFormData(formElement, submitter) {\n const formData = new FormData(formElement);\n const name = submitter?.getAttribute(\"name\");\n const value = submitter?.getAttribute(\"value\");\n\n if (name) {\n formData.append(name, value || \"\");\n }\n\n return formData\n}\n\nfunction getCookieValue(cookieName) {\n if (cookieName != null) {\n const cookies = document.cookie ? document.cookie.split(\"; \") : [];\n const cookie = cookies.find((cookie) => cookie.startsWith(cookieName));\n if (cookie) {\n const value = cookie.split(\"=\").slice(1).join(\"=\");\n return value ? decodeURIComponent(value) : undefined\n }\n }\n}\n\nfunction responseSucceededWithoutRedirect(response) {\n return response.statusCode == 200 && !response.redirected\n}\n\nfunction getFormAction(formElement, submitter) {\n const formElementAction = typeof formElement.action === \"string\" ? formElement.action : null;\n\n if (submitter?.hasAttribute(\"formaction\")) {\n return submitter.getAttribute(\"formaction\") || \"\"\n } else {\n return formElement.getAttribute(\"action\") || formElementAction || \"\"\n }\n}\n\nfunction getAction(formAction, fetchMethod) {\n const action = expandURL(formAction);\n\n if (isSafe(fetchMethod)) {\n action.search = \"\";\n }\n\n return action\n}\n\nfunction getMethod(formElement, submitter) {\n const method = submitter?.getAttribute(\"formmethod\") || formElement.getAttribute(\"method\") || \"\";\n return fetchMethodFromString(method.toLowerCase()) || FetchMethod.get\n}\n\nfunction getEnctype(formElement, submitter) {\n return fetchEnctypeFromString(submitter?.getAttribute(\"formenctype\") || formElement.enctype)\n}\n\nclass Snapshot {\n constructor(element) {\n this.element = element;\n }\n\n get activeElement() {\n return this.element.ownerDocument.activeElement\n }\n\n get children() {\n return [...this.element.children]\n }\n\n hasAnchor(anchor) {\n return this.getElementForAnchor(anchor) != null\n }\n\n getElementForAnchor(anchor) {\n return anchor ? this.element.querySelector(`[id='${anchor}'], a[name='${anchor}']`) : null\n }\n\n get isConnected() {\n return this.element.isConnected\n }\n\n get firstAutofocusableElement() {\n return queryAutofocusableElement(this.element)\n }\n\n get permanentElements() {\n return queryPermanentElementsAll(this.element)\n }\n\n getPermanentElementById(id) {\n return getPermanentElementById(this.element, id)\n }\n\n getPermanentElementMapForSnapshot(snapshot) {\n const permanentElementMap = {};\n\n for (const currentPermanentElement of this.permanentElements) {\n const { id } = currentPermanentElement;\n const newPermanentElement = snapshot.getPermanentElementById(id);\n if (newPermanentElement) {\n permanentElementMap[id] = [currentPermanentElement, newPermanentElement];\n }\n }\n\n return permanentElementMap\n }\n}\n\nfunction getPermanentElementById(node, id) {\n return node.querySelector(`#${id}[data-turbo-permanent]`)\n}\n\nfunction queryPermanentElementsAll(node) {\n return node.querySelectorAll(\"[id][data-turbo-permanent]\")\n}\n\nclass FormSubmitObserver {\n started = false\n\n constructor(delegate, eventTarget) {\n this.delegate = delegate;\n this.eventTarget = eventTarget;\n }\n\n start() {\n if (!this.started) {\n this.eventTarget.addEventListener(\"submit\", this.submitCaptured, true);\n this.started = true;\n }\n }\n\n stop() {\n if (this.started) {\n this.eventTarget.removeEventListener(\"submit\", this.submitCaptured, true);\n this.started = false;\n }\n }\n\n submitCaptured = () => {\n this.eventTarget.removeEventListener(\"submit\", this.submitBubbled, false);\n this.eventTarget.addEventListener(\"submit\", this.submitBubbled, false);\n }\n\n submitBubbled = (event) => {\n if (!event.defaultPrevented) {\n const form = event.target instanceof HTMLFormElement ? event.target : undefined;\n const submitter = event.submitter || undefined;\n\n if (\n form &&\n submissionDoesNotDismissDialog(form, submitter) &&\n submissionDoesNotTargetIFrame(form, submitter) &&\n this.delegate.willSubmitForm(form, submitter)\n ) {\n event.preventDefault();\n event.stopImmediatePropagation();\n this.delegate.formSubmitted(form, submitter);\n }\n }\n }\n}\n\nfunction submissionDoesNotDismissDialog(form, submitter) {\n const method = submitter?.getAttribute(\"formmethod\") || form.getAttribute(\"method\");\n\n return method != \"dialog\"\n}\n\nfunction submissionDoesNotTargetIFrame(form, submitter) {\n const target = submitter?.getAttribute(\"formtarget\") || form.getAttribute(\"target\");\n\n return doesNotTargetIFrame(target)\n}\n\nclass View {\n #resolveRenderPromise = (_value) => {}\n #resolveInterceptionPromise = (_value) => {}\n\n constructor(delegate, element) {\n this.delegate = delegate;\n this.element = element;\n }\n\n // Scrolling\n\n scrollToAnchor(anchor) {\n const element = this.snapshot.getElementForAnchor(anchor);\n if (element) {\n this.focusElement(element);\n this.scrollToElement(element);\n } else {\n this.scrollToPosition({ x: 0, y: 0 });\n }\n }\n\n scrollToAnchorFromLocation(location) {\n this.scrollToAnchor(getAnchor(location));\n }\n\n scrollToElement(element) {\n element.scrollIntoView();\n }\n\n focusElement(element) {\n if (element instanceof HTMLElement) {\n if (element.hasAttribute(\"tabindex\")) {\n element.focus();\n } else {\n element.setAttribute(\"tabindex\", \"-1\");\n element.focus();\n element.removeAttribute(\"tabindex\");\n }\n }\n }\n\n scrollToPosition({ x, y }) {\n this.scrollRoot.scrollTo(x, y);\n }\n\n scrollToTop() {\n this.scrollToPosition({ x: 0, y: 0 });\n }\n\n get scrollRoot() {\n return window\n }\n\n // Rendering\n\n async render(renderer) {\n const { isPreview, shouldRender, willRender, newSnapshot: snapshot } = renderer;\n\n // A workaround to ignore tracked element mismatch reloads when performing\n // a promoted Visit from a frame navigation\n const shouldInvalidate = willRender;\n\n if (shouldRender) {\n try {\n this.renderPromise = new Promise((resolve) => (this.#resolveRenderPromise = resolve));\n this.renderer = renderer;\n await this.prepareToRenderSnapshot(renderer);\n\n const renderInterception = new Promise((resolve) => (this.#resolveInterceptionPromise = resolve));\n const options = { resume: this.#resolveInterceptionPromise, render: this.renderer.renderElement, renderMethod: this.renderer.renderMethod };\n const immediateRender = this.delegate.allowsImmediateRender(snapshot, options);\n if (!immediateRender) await renderInterception;\n\n await this.renderSnapshot(renderer);\n this.delegate.viewRenderedSnapshot(snapshot, isPreview, this.renderer.renderMethod);\n this.delegate.preloadOnLoadLinksForView(this.element);\n this.finishRenderingSnapshot(renderer);\n } finally {\n delete this.renderer;\n this.#resolveRenderPromise(undefined);\n delete this.renderPromise;\n }\n } else if (shouldInvalidate) {\n this.invalidate(renderer.reloadReason);\n }\n }\n\n invalidate(reason) {\n this.delegate.viewInvalidated(reason);\n }\n\n async prepareToRenderSnapshot(renderer) {\n this.markAsPreview(renderer.isPreview);\n await renderer.prepareToRender();\n }\n\n markAsPreview(isPreview) {\n if (isPreview) {\n this.element.setAttribute(\"data-turbo-preview\", \"\");\n } else {\n this.element.removeAttribute(\"data-turbo-preview\");\n }\n }\n\n markVisitDirection(direction) {\n this.element.setAttribute(\"data-turbo-visit-direction\", direction);\n }\n\n unmarkVisitDirection() {\n this.element.removeAttribute(\"data-turbo-visit-direction\");\n }\n\n async renderSnapshot(renderer) {\n await renderer.render();\n }\n\n finishRenderingSnapshot(renderer) {\n renderer.finishRendering();\n }\n}\n\nclass FrameView extends View {\n missing() {\n this.element.innerHTML = `Content missing`;\n }\n\n get snapshot() {\n return new Snapshot(this.element)\n }\n}\n\nclass LinkInterceptor {\n constructor(delegate, element) {\n this.delegate = delegate;\n this.element = element;\n }\n\n start() {\n this.element.addEventListener(\"click\", this.clickBubbled);\n document.addEventListener(\"turbo:click\", this.linkClicked);\n document.addEventListener(\"turbo:before-visit\", this.willVisit);\n }\n\n stop() {\n this.element.removeEventListener(\"click\", this.clickBubbled);\n document.removeEventListener(\"turbo:click\", this.linkClicked);\n document.removeEventListener(\"turbo:before-visit\", this.willVisit);\n }\n\n clickBubbled = (event) => {\n if (this.clickEventIsSignificant(event)) {\n this.clickEvent = event;\n } else {\n delete this.clickEvent;\n }\n }\n\n linkClicked = (event) => {\n if (this.clickEvent && this.clickEventIsSignificant(event)) {\n if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url, event.detail.originalEvent)) {\n this.clickEvent.preventDefault();\n event.preventDefault();\n this.delegate.linkClickIntercepted(event.target, event.detail.url, event.detail.originalEvent);\n }\n }\n delete this.clickEvent;\n }\n\n willVisit = (_event) => {\n delete this.clickEvent;\n }\n\n clickEventIsSignificant(event) {\n const target = event.composed ? event.target?.parentElement : event.target;\n const element = findLinkFromClickTarget(target) || target;\n\n return element instanceof Element && element.closest(\"turbo-frame, html\") == this.element\n }\n}\n\nclass LinkClickObserver {\n started = false\n\n constructor(delegate, eventTarget) {\n this.delegate = delegate;\n this.eventTarget = eventTarget;\n }\n\n start() {\n if (!this.started) {\n this.eventTarget.addEventListener(\"click\", this.clickCaptured, true);\n this.started = true;\n }\n }\n\n stop() {\n if (this.started) {\n this.eventTarget.removeEventListener(\"click\", this.clickCaptured, true);\n this.started = false;\n }\n }\n\n clickCaptured = () => {\n this.eventTarget.removeEventListener(\"click\", this.clickBubbled, false);\n this.eventTarget.addEventListener(\"click\", this.clickBubbled, false);\n }\n\n clickBubbled = (event) => {\n if (event instanceof MouseEvent && this.clickEventIsSignificant(event)) {\n const target = (event.composedPath && event.composedPath()[0]) || event.target;\n const link = findLinkFromClickTarget(target);\n if (link && doesNotTargetIFrame(link.target)) {\n const location = getLocationForLink(link);\n if (this.delegate.willFollowLinkToLocation(link, location, event)) {\n event.preventDefault();\n this.delegate.followedLinkToLocation(link, location);\n }\n }\n }\n }\n\n clickEventIsSignificant(event) {\n return !(\n (event.target && event.target.isContentEditable) ||\n event.defaultPrevented ||\n event.which > 1 ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n event.shiftKey\n )\n }\n}\n\nclass FormLinkClickObserver {\n constructor(delegate, element) {\n this.delegate = delegate;\n this.linkInterceptor = new LinkClickObserver(this, element);\n }\n\n start() {\n this.linkInterceptor.start();\n }\n\n stop() {\n this.linkInterceptor.stop();\n }\n\n // Link hover observer delegate\n\n canPrefetchRequestToLocation(link, location) {\n return false\n }\n\n prefetchAndCacheRequestToLocation(link, location) {\n return\n }\n\n // Link click observer delegate\n\n willFollowLinkToLocation(link, location, originalEvent) {\n return (\n this.delegate.willSubmitFormLinkToLocation(link, location, originalEvent) &&\n (link.hasAttribute(\"data-turbo-method\") || link.hasAttribute(\"data-turbo-stream\"))\n )\n }\n\n followedLinkToLocation(link, location) {\n const form = document.createElement(\"form\");\n\n const type = \"hidden\";\n for (const [name, value] of location.searchParams) {\n form.append(Object.assign(document.createElement(\"input\"), { type, name, value }));\n }\n\n const action = Object.assign(location, { search: \"\" });\n form.setAttribute(\"data-turbo\", \"true\");\n form.setAttribute(\"action\", action.href);\n form.setAttribute(\"hidden\", \"\");\n\n const method = link.getAttribute(\"data-turbo-method\");\n if (method) form.setAttribute(\"method\", method);\n\n const turboFrame = link.getAttribute(\"data-turbo-frame\");\n if (turboFrame) form.setAttribute(\"data-turbo-frame\", turboFrame);\n\n const turboAction = getVisitAction(link);\n if (turboAction) form.setAttribute(\"data-turbo-action\", turboAction);\n\n const turboConfirm = link.getAttribute(\"data-turbo-confirm\");\n if (turboConfirm) form.setAttribute(\"data-turbo-confirm\", turboConfirm);\n\n const turboStream = link.hasAttribute(\"data-turbo-stream\");\n if (turboStream) form.setAttribute(\"data-turbo-stream\", \"\");\n\n this.delegate.submittedFormLinkToLocation(link, location, form);\n\n document.body.appendChild(form);\n form.addEventListener(\"turbo:submit-end\", () => form.remove(), { once: true });\n requestAnimationFrame(() => form.requestSubmit());\n }\n}\n\nclass Bardo {\n static async preservingPermanentElements(delegate, permanentElementMap, callback) {\n const bardo = new this(delegate, permanentElementMap);\n bardo.enter();\n await callback();\n bardo.leave();\n }\n\n constructor(delegate, permanentElementMap) {\n this.delegate = delegate;\n this.permanentElementMap = permanentElementMap;\n }\n\n enter() {\n for (const id in this.permanentElementMap) {\n const [currentPermanentElement, newPermanentElement] = this.permanentElementMap[id];\n this.delegate.enteringBardo(currentPermanentElement, newPermanentElement);\n this.replaceNewPermanentElementWithPlaceholder(newPermanentElement);\n }\n }\n\n leave() {\n for (const id in this.permanentElementMap) {\n const [currentPermanentElement] = this.permanentElementMap[id];\n this.replaceCurrentPermanentElementWithClone(currentPermanentElement);\n this.replacePlaceholderWithPermanentElement(currentPermanentElement);\n this.delegate.leavingBardo(currentPermanentElement);\n }\n }\n\n replaceNewPermanentElementWithPlaceholder(permanentElement) {\n const placeholder = createPlaceholderForPermanentElement(permanentElement);\n permanentElement.replaceWith(placeholder);\n }\n\n replaceCurrentPermanentElementWithClone(permanentElement) {\n const clone = permanentElement.cloneNode(true);\n permanentElement.replaceWith(clone);\n }\n\n replacePlaceholderWithPermanentElement(permanentElement) {\n const placeholder = this.getPlaceholderById(permanentElement.id);\n placeholder?.replaceWith(permanentElement);\n }\n\n getPlaceholderById(id) {\n return this.placeholders.find((element) => element.content == id)\n }\n\n get placeholders() {\n return [...document.querySelectorAll(\"meta[name=turbo-permanent-placeholder][content]\")]\n }\n}\n\nfunction createPlaceholderForPermanentElement(permanentElement) {\n const element = document.createElement(\"meta\");\n element.setAttribute(\"name\", \"turbo-permanent-placeholder\");\n element.setAttribute(\"content\", permanentElement.id);\n return element\n}\n\nclass Renderer {\n #activeElement = null\n\n static renderElement(currentElement, newElement) {\n // Abstract method\n }\n\n constructor(currentSnapshot, newSnapshot, isPreview, willRender = true) {\n this.currentSnapshot = currentSnapshot;\n this.newSnapshot = newSnapshot;\n this.isPreview = isPreview;\n this.willRender = willRender;\n this.renderElement = this.constructor.renderElement;\n this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));\n }\n\n get shouldRender() {\n return true\n }\n\n get shouldAutofocus() {\n return true\n }\n\n get reloadReason() {\n return\n }\n\n prepareToRender() {\n return\n }\n\n render() {\n // Abstract method\n }\n\n finishRendering() {\n if (this.resolvingFunctions) {\n this.resolvingFunctions.resolve();\n delete this.resolvingFunctions;\n }\n }\n\n async preservingPermanentElements(callback) {\n await Bardo.preservingPermanentElements(this, this.permanentElementMap, callback);\n }\n\n focusFirstAutofocusableElement() {\n if (this.shouldAutofocus) {\n const element = this.connectedSnapshot.firstAutofocusableElement;\n if (element) {\n element.focus();\n }\n }\n }\n\n // Bardo delegate\n\n enteringBardo(currentPermanentElement) {\n if (this.#activeElement) return\n\n if (currentPermanentElement.contains(this.currentSnapshot.activeElement)) {\n this.#activeElement = this.currentSnapshot.activeElement;\n }\n }\n\n leavingBardo(currentPermanentElement) {\n if (currentPermanentElement.contains(this.#activeElement) && this.#activeElement instanceof HTMLElement) {\n this.#activeElement.focus();\n\n this.#activeElement = null;\n }\n }\n\n get connectedSnapshot() {\n return this.newSnapshot.isConnected ? this.newSnapshot : this.currentSnapshot\n }\n\n get currentElement() {\n return this.currentSnapshot.element\n }\n\n get newElement() {\n return this.newSnapshot.element\n }\n\n get permanentElementMap() {\n return this.currentSnapshot.getPermanentElementMapForSnapshot(this.newSnapshot)\n }\n\n get renderMethod() {\n return \"replace\"\n }\n}\n\nclass FrameRenderer extends Renderer {\n static renderElement(currentElement, newElement) {\n const destinationRange = document.createRange();\n destinationRange.selectNodeContents(currentElement);\n destinationRange.deleteContents();\n\n const frameElement = newElement;\n const sourceRange = frameElement.ownerDocument?.createRange();\n if (sourceRange) {\n sourceRange.selectNodeContents(frameElement);\n currentElement.appendChild(sourceRange.extractContents());\n }\n }\n\n constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {\n super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender);\n this.delegate = delegate;\n }\n\n get shouldRender() {\n return true\n }\n\n async render() {\n await nextRepaint();\n this.preservingPermanentElements(() => {\n this.loadFrameElement();\n });\n this.scrollFrameIntoView();\n await nextRepaint();\n this.focusFirstAutofocusableElement();\n await nextRepaint();\n this.activateScriptElements();\n }\n\n loadFrameElement() {\n this.delegate.willRenderFrame(this.currentElement, this.newElement);\n this.renderElement(this.currentElement, this.newElement);\n }\n\n scrollFrameIntoView() {\n if (this.currentElement.autoscroll || this.newElement.autoscroll) {\n const element = this.currentElement.firstElementChild;\n const block = readScrollLogicalPosition(this.currentElement.getAttribute(\"data-autoscroll-block\"), \"end\");\n const behavior = readScrollBehavior(this.currentElement.getAttribute(\"data-autoscroll-behavior\"), \"auto\");\n\n if (element) {\n element.scrollIntoView({ block, behavior });\n return true\n }\n }\n return false\n }\n\n activateScriptElements() {\n for (const inertScriptElement of this.newScriptElements) {\n const activatedScriptElement = activateScriptElement(inertScriptElement);\n inertScriptElement.replaceWith(activatedScriptElement);\n }\n }\n\n get newScriptElements() {\n return this.currentElement.querySelectorAll(\"script\")\n }\n}\n\nfunction readScrollLogicalPosition(value, defaultValue) {\n if (value == \"end\" || value == \"start\" || value == \"center\" || value == \"nearest\") {\n return value\n } else {\n return defaultValue\n }\n}\n\nfunction readScrollBehavior(value, defaultValue) {\n if (value == \"auto\" || value == \"smooth\") {\n return value\n } else {\n return defaultValue\n }\n}\n\n/**\n * @typedef {object} ConfigHead\n *\n * @property {'merge' | 'append' | 'morph' | 'none'} [style]\n * @property {boolean} [block]\n * @property {boolean} [ignore]\n * @property {function(Element): boolean} [shouldPreserve]\n * @property {function(Element): boolean} [shouldReAppend]\n * @property {function(Element): boolean} [shouldRemove]\n * @property {function(Element, {added: Node[], kept: Element[], removed: Element[]}): void} [afterHeadMorphed]\n */\n\n/**\n * @typedef {object} ConfigCallbacks\n *\n * @property {function(Node): boolean} [beforeNodeAdded]\n * @property {function(Node): void} [afterNodeAdded]\n * @property {function(Element, Node): boolean} [beforeNodeMorphed]\n * @property {function(Element, Node): void} [afterNodeMorphed]\n * @property {function(Element): boolean} [beforeNodeRemoved]\n * @property {function(Element): void} [afterNodeRemoved]\n * @property {function(string, Element, \"update\" | \"remove\"): boolean} [beforeAttributeUpdated]\n */\n\n/**\n * @typedef {object} Config\n *\n * @property {'outerHTML' | 'innerHTML'} [morphStyle]\n * @property {boolean} [ignoreActive]\n * @property {boolean} [ignoreActiveValue]\n * @property {boolean} [restoreFocus]\n * @property {ConfigCallbacks} [callbacks]\n * @property {ConfigHead} [head]\n */\n\n/**\n * @typedef {function} NoOp\n *\n * @returns {void}\n */\n\n/**\n * @typedef {object} ConfigHeadInternal\n *\n * @property {'merge' | 'append' | 'morph' | 'none'} style\n * @property {boolean} [block]\n * @property {boolean} [ignore]\n * @property {(function(Element): boolean) | NoOp} shouldPreserve\n * @property {(function(Element): boolean) | NoOp} shouldReAppend\n * @property {(function(Element): boolean) | NoOp} shouldRemove\n * @property {(function(Element, {added: Node[], kept: Element[], removed: Element[]}): void) | NoOp} afterHeadMorphed\n */\n\n/**\n * @typedef {object} ConfigCallbacksInternal\n *\n * @property {(function(Node): boolean) | NoOp} beforeNodeAdded\n * @property {(function(Node): void) | NoOp} afterNodeAdded\n * @property {(function(Node, Node): boolean) | NoOp} beforeNodeMorphed\n * @property {(function(Node, Node): void) | NoOp} afterNodeMorphed\n * @property {(function(Node): boolean) | NoOp} beforeNodeRemoved\n * @property {(function(Node): void) | NoOp} afterNodeRemoved\n * @property {(function(string, Element, \"update\" | \"remove\"): boolean) | NoOp} beforeAttributeUpdated\n */\n\n/**\n * @typedef {object} ConfigInternal\n *\n * @property {'outerHTML' | 'innerHTML'} morphStyle\n * @property {boolean} [ignoreActive]\n * @property {boolean} [ignoreActiveValue]\n * @property {boolean} [restoreFocus]\n * @property {ConfigCallbacksInternal} callbacks\n * @property {ConfigHeadInternal} head\n */\n\n/**\n * @typedef {Object} IdSets\n * @property {Set} persistentIds\n * @property {Map>} idMap\n */\n\n/**\n * @typedef {Function} Morph\n *\n * @param {Element | Document} oldNode\n * @param {Element | Node | HTMLCollection | Node[] | string | null} newContent\n * @param {Config} [config]\n * @returns {undefined | Node[]}\n */\n\n// base IIFE to define idiomorph\n/**\n *\n * @type {{defaults: ConfigInternal, morph: Morph}}\n */\nvar Idiomorph = (function () {\n\n /**\n * @typedef {object} MorphContext\n *\n * @property {Element} target\n * @property {Element} newContent\n * @property {ConfigInternal} config\n * @property {ConfigInternal['morphStyle']} morphStyle\n * @property {ConfigInternal['ignoreActive']} ignoreActive\n * @property {ConfigInternal['ignoreActiveValue']} ignoreActiveValue\n * @property {ConfigInternal['restoreFocus']} restoreFocus\n * @property {Map>} idMap\n * @property {Set} persistentIds\n * @property {ConfigInternal['callbacks']} callbacks\n * @property {ConfigInternal['head']} head\n * @property {HTMLDivElement} pantry\n * @property {Element[]} activeElementAndParents\n */\n\n //=============================================================================\n // AND NOW IT BEGINS...\n //=============================================================================\n\n const noOp = () => {};\n /**\n * Default configuration values, updatable by users now\n * @type {ConfigInternal}\n */\n const defaults = {\n morphStyle: \"outerHTML\",\n callbacks: {\n beforeNodeAdded: noOp,\n afterNodeAdded: noOp,\n beforeNodeMorphed: noOp,\n afterNodeMorphed: noOp,\n beforeNodeRemoved: noOp,\n afterNodeRemoved: noOp,\n beforeAttributeUpdated: noOp,\n },\n head: {\n style: \"merge\",\n shouldPreserve: (elt) => elt.getAttribute(\"im-preserve\") === \"true\",\n shouldReAppend: (elt) => elt.getAttribute(\"im-re-append\") === \"true\",\n shouldRemove: noOp,\n afterHeadMorphed: noOp,\n },\n restoreFocus: true,\n };\n\n /**\n * Core idiomorph function for morphing one DOM tree to another\n *\n * @param {Element | Document} oldNode\n * @param {Element | Node | HTMLCollection | Node[] | string | null} newContent\n * @param {Config} [config]\n * @returns {Promise | Node[]}\n */\n function morph(oldNode, newContent, config = {}) {\n oldNode = normalizeElement(oldNode);\n const newNode = normalizeParent(newContent);\n const ctx = createMorphContext(oldNode, newNode, config);\n\n const morphedNodes = saveAndRestoreFocus(ctx, () => {\n return withHeadBlocking(\n ctx,\n oldNode,\n newNode,\n /** @param {MorphContext} ctx */ (ctx) => {\n if (ctx.morphStyle === \"innerHTML\") {\n morphChildren(ctx, oldNode, newNode);\n return Array.from(oldNode.childNodes);\n } else {\n return morphOuterHTML(ctx, oldNode, newNode);\n }\n },\n );\n });\n\n ctx.pantry.remove();\n return morphedNodes;\n }\n\n /**\n * Morph just the outerHTML of the oldNode to the newContent\n * We have to be careful because the oldNode could have siblings which need to be untouched\n * @param {MorphContext} ctx\n * @param {Element} oldNode\n * @param {Element} newNode\n * @returns {Node[]}\n */\n function morphOuterHTML(ctx, oldNode, newNode) {\n const oldParent = normalizeParent(oldNode);\n morphChildren(\n ctx,\n oldParent,\n newNode,\n // these two optional params are the secret sauce\n oldNode, // start point for iteration\n oldNode.nextSibling, // end point for iteration\n );\n // this is safe even with siblings, because normalizeParent returns a SlicedParentNode if needed.\n return Array.from(oldParent.childNodes);\n }\n\n /**\n * @param {MorphContext} ctx\n * @param {Function} fn\n * @returns {Promise | Node[]}\n */\n function saveAndRestoreFocus(ctx, fn) {\n if (!ctx.config.restoreFocus) return fn();\n let activeElement =\n /** @type {HTMLInputElement|HTMLTextAreaElement|null} */ (\n document.activeElement\n );\n\n // don't bother if the active element is not an input or textarea\n if (\n !(\n activeElement instanceof HTMLInputElement ||\n activeElement instanceof HTMLTextAreaElement\n )\n ) {\n return fn();\n }\n\n const { id: activeElementId, selectionStart, selectionEnd } = activeElement;\n\n const results = fn();\n\n if (\n activeElementId &&\n activeElementId !== document.activeElement?.getAttribute(\"id\")\n ) {\n activeElement = ctx.target.querySelector(`[id=\"${activeElementId}\"]`);\n activeElement?.focus();\n }\n if (activeElement && !activeElement.selectionEnd && selectionEnd) {\n activeElement.setSelectionRange(selectionStart, selectionEnd);\n }\n\n return results;\n }\n\n const morphChildren = (function () {\n /**\n * This is the core algorithm for matching up children. The idea is to use id sets to try to match up\n * nodes as faithfully as possible. We greedily match, which allows us to keep the algorithm fast, but\n * by using id sets, we are able to better match up with content deeper in the DOM.\n *\n * Basic algorithm:\n * - for each node in the new content:\n * - search self and siblings for an id set match, falling back to a soft match\n * - if match found\n * - remove any nodes up to the match:\n * - pantry persistent nodes\n * - delete the rest\n * - morph the match\n * - elsif no match found, and node is persistent\n * - find its match by querying the old root (future) and pantry (past)\n * - move it and its children here\n * - morph it\n * - else\n * - create a new node from scratch as a last result\n *\n * @param {MorphContext} ctx the merge context\n * @param {Element} oldParent the old content that we are merging the new content into\n * @param {Element} newParent the parent element of the new content\n * @param {Node|null} [insertionPoint] the point in the DOM we start morphing at (defaults to first child)\n * @param {Node|null} [endPoint] the point in the DOM we stop morphing at (defaults to after last child)\n */\n function morphChildren(\n ctx,\n oldParent,\n newParent,\n insertionPoint = null,\n endPoint = null,\n ) {\n // normalize\n if (\n oldParent instanceof HTMLTemplateElement &&\n newParent instanceof HTMLTemplateElement\n ) {\n // @ts-ignore we can pretend the DocumentFragment is an Element\n oldParent = oldParent.content;\n // @ts-ignore ditto\n newParent = newParent.content;\n }\n insertionPoint ||= oldParent.firstChild;\n\n // run through all the new content\n for (const newChild of newParent.childNodes) {\n // once we reach the end of the old parent content skip to the end and insert the rest\n if (insertionPoint && insertionPoint != endPoint) {\n const bestMatch = findBestMatch(\n ctx,\n newChild,\n insertionPoint,\n endPoint,\n );\n if (bestMatch) {\n // if the node to morph is not at the insertion point then remove/move up to it\n if (bestMatch !== insertionPoint) {\n removeNodesBetween(ctx, insertionPoint, bestMatch);\n }\n morphNode(bestMatch, newChild, ctx);\n insertionPoint = bestMatch.nextSibling;\n continue;\n }\n }\n\n // if the matching node is elsewhere in the original content\n if (newChild instanceof Element) {\n // we can pretend the id is non-null because the next `.has` line will reject it if not\n const newChildId = /** @type {String} */ (\n newChild.getAttribute(\"id\")\n );\n if (ctx.persistentIds.has(newChildId)) {\n // move it and all its children here and morph\n const movedChild = moveBeforeById(\n oldParent,\n newChildId,\n insertionPoint,\n ctx,\n );\n morphNode(movedChild, newChild, ctx);\n insertionPoint = movedChild.nextSibling;\n continue;\n }\n }\n\n // last resort: insert the new node from scratch\n const insertedNode = createNode(\n oldParent,\n newChild,\n insertionPoint,\n ctx,\n );\n // could be null if beforeNodeAdded prevented insertion\n if (insertedNode) {\n insertionPoint = insertedNode.nextSibling;\n }\n }\n\n // remove any remaining old nodes that didn't match up with new content\n while (insertionPoint && insertionPoint != endPoint) {\n const tempNode = insertionPoint;\n insertionPoint = insertionPoint.nextSibling;\n removeNode(ctx, tempNode);\n }\n }\n\n /**\n * This performs the action of inserting a new node while handling situations where the node contains\n * elements with persistent ids and possible state info we can still preserve by moving in and then morphing\n *\n * @param {Element} oldParent\n * @param {Node} newChild\n * @param {Node|null} insertionPoint\n * @param {MorphContext} ctx\n * @returns {Node|null}\n */\n function createNode(oldParent, newChild, insertionPoint, ctx) {\n if (ctx.callbacks.beforeNodeAdded(newChild) === false) return null;\n if (ctx.idMap.has(newChild)) {\n // node has children with ids with possible state so create a dummy elt of same type and apply full morph algorithm\n const newEmptyChild = document.createElement(\n /** @type {Element} */ (newChild).tagName,\n );\n oldParent.insertBefore(newEmptyChild, insertionPoint);\n morphNode(newEmptyChild, newChild, ctx);\n ctx.callbacks.afterNodeAdded(newEmptyChild);\n return newEmptyChild;\n } else {\n // optimisation: no id state to preserve so we can just insert a clone of the newChild and its descendants\n const newClonedChild = document.importNode(newChild, true); // importNode to not mutate newParent\n oldParent.insertBefore(newClonedChild, insertionPoint);\n ctx.callbacks.afterNodeAdded(newClonedChild);\n return newClonedChild;\n }\n }\n\n //=============================================================================\n // Matching Functions\n //=============================================================================\n const findBestMatch = (function () {\n /**\n * Scans forward from the startPoint to the endPoint looking for a match\n * for the node. It looks for an id set match first, then a soft match.\n * We abort softmatching if we find two future soft matches, to reduce churn.\n * @param {Node} node\n * @param {MorphContext} ctx\n * @param {Node | null} startPoint\n * @param {Node | null} endPoint\n * @returns {Node | null}\n */\n function findBestMatch(ctx, node, startPoint, endPoint) {\n let softMatch = null;\n let nextSibling = node.nextSibling;\n let siblingSoftMatchCount = 0;\n\n let cursor = startPoint;\n while (cursor && cursor != endPoint) {\n // soft matching is a prerequisite for id set matching\n if (isSoftMatch(cursor, node)) {\n if (isIdSetMatch(ctx, cursor, node)) {\n return cursor; // found an id set match, we're done!\n }\n\n // we haven't yet saved a soft match fallback\n if (softMatch === null) {\n // the current soft match will hard match something else in the future, leave it\n if (!ctx.idMap.has(cursor)) {\n // save this as the fallback if we get through the loop without finding a hard match\n softMatch = cursor;\n }\n }\n }\n if (\n softMatch === null &&\n nextSibling &&\n isSoftMatch(cursor, nextSibling)\n ) {\n // The next new node has a soft match with this node, so\n // increment the count of future soft matches\n siblingSoftMatchCount++;\n nextSibling = nextSibling.nextSibling;\n\n // If there are two future soft matches, block soft matching for this node to allow\n // future siblings to soft match. This is to reduce churn in the DOM when an element\n // is prepended.\n if (siblingSoftMatchCount >= 2) {\n softMatch = undefined;\n }\n }\n\n // if the current node contains active element, stop looking for better future matches,\n // because if one is found, this node will be moved to the pantry, reparenting it and thus losing focus\n // @ts-ignore pretend cursor is Element rather than Node, we're just testing for array inclusion\n if (ctx.activeElementAndParents.includes(cursor)) break;\n\n cursor = cursor.nextSibling;\n }\n\n return softMatch || null;\n }\n\n /**\n *\n * @param {MorphContext} ctx\n * @param {Node} oldNode\n * @param {Node} newNode\n * @returns {boolean}\n */\n function isIdSetMatch(ctx, oldNode, newNode) {\n let oldSet = ctx.idMap.get(oldNode);\n let newSet = ctx.idMap.get(newNode);\n\n if (!newSet || !oldSet) return false;\n\n for (const id of oldSet) {\n // a potential match is an id in the new and old nodes that\n // has not already been merged into the DOM\n // But the newNode content we call this on has not been\n // merged yet and we don't allow duplicate IDs so it is simple\n if (newSet.has(id)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n *\n * @param {Node} oldNode\n * @param {Node} newNode\n * @returns {boolean}\n */\n function isSoftMatch(oldNode, newNode) {\n // ok to cast: if one is not element, `id` and `tagName` will be undefined and we'll just compare that.\n const oldElt = /** @type {Element} */ (oldNode);\n const newElt = /** @type {Element} */ (newNode);\n\n return (\n oldElt.nodeType === newElt.nodeType &&\n oldElt.tagName === newElt.tagName &&\n // If oldElt has an `id` with possible state and it doesn't match newElt.id then avoid morphing.\n // We'll still match an anonymous node with an IDed newElt, though, because if it got this far,\n // its not persistent, and new nodes can't have any hidden state.\n // We can't use .id because of form input shadowing, and we can't count on .getAttribute's presence because it could be a document-fragment\n (!oldElt.getAttribute?.(\"id\") ||\n oldElt.getAttribute?.(\"id\") === newElt.getAttribute?.(\"id\"))\n );\n }\n\n return findBestMatch;\n })();\n\n //=============================================================================\n // DOM Manipulation Functions\n //=============================================================================\n\n /**\n * Gets rid of an unwanted DOM node; strategy depends on nature of its reuse:\n * - Persistent nodes will be moved to the pantry for later reuse\n * - Other nodes will have their hooks called, and then are removed\n * @param {MorphContext} ctx\n * @param {Node} node\n */\n function removeNode(ctx, node) {\n // are we going to id set match this later?\n if (ctx.idMap.has(node)) {\n // skip callbacks and move to pantry\n moveBefore(ctx.pantry, node, null);\n } else {\n // remove for realsies\n if (ctx.callbacks.beforeNodeRemoved(node) === false) return;\n node.parentNode?.removeChild(node);\n ctx.callbacks.afterNodeRemoved(node);\n }\n }\n\n /**\n * Remove nodes between the start and end nodes\n * @param {MorphContext} ctx\n * @param {Node} startInclusive\n * @param {Node} endExclusive\n * @returns {Node|null}\n */\n function removeNodesBetween(ctx, startInclusive, endExclusive) {\n /** @type {Node | null} */\n let cursor = startInclusive;\n // remove nodes until the endExclusive node\n while (cursor && cursor !== endExclusive) {\n let tempNode = /** @type {Node} */ (cursor);\n cursor = cursor.nextSibling;\n removeNode(ctx, tempNode);\n }\n return cursor;\n }\n\n /**\n * Search for an element by id within the document and pantry, and move it using moveBefore.\n *\n * @param {Element} parentNode - The parent node to which the element will be moved.\n * @param {string} id - The ID of the element to be moved.\n * @param {Node | null} after - The reference node to insert the element before.\n * If `null`, the element is appended as the last child.\n * @param {MorphContext} ctx\n * @returns {Element} The found element\n */\n function moveBeforeById(parentNode, id, after, ctx) {\n const target =\n /** @type {Element} - will always be found */\n (\n // ctx.target.id unsafe because of form input shadowing\n // ctx.target could be a document fragment which doesn't have `getAttribute`\n (ctx.target.getAttribute?.(\"id\") === id && ctx.target) ||\n ctx.target.querySelector(`[id=\"${id}\"]`) ||\n ctx.pantry.querySelector(`[id=\"${id}\"]`)\n );\n removeElementFromAncestorsIdMaps(target, ctx);\n moveBefore(parentNode, target, after);\n return target;\n }\n\n /**\n * Removes an element from its ancestors' id maps. This is needed when an element is moved from the\n * \"future\" via `moveBeforeId`. Otherwise, its erstwhile ancestors could be mistakenly moved to the\n * pantry rather than being deleted, preventing their removal hooks from being called.\n *\n * @param {Element} element - element to remove from its ancestors' id maps\n * @param {MorphContext} ctx\n */\n function removeElementFromAncestorsIdMaps(element, ctx) {\n // we know id is non-null String, because this function is only called on elements with ids\n const id = /** @type {String} */ (element.getAttribute(\"id\"));\n /** @ts-ignore - safe to loop in this way **/\n while ((element = element.parentNode)) {\n let idSet = ctx.idMap.get(element);\n if (idSet) {\n idSet.delete(id);\n if (!idSet.size) {\n ctx.idMap.delete(element);\n }\n }\n }\n }\n\n /**\n * Moves an element before another element within the same parent.\n * Uses the proposed `moveBefore` API if available (and working), otherwise falls back to `insertBefore`.\n * This is essentialy a forward-compat wrapper.\n *\n * @param {Element} parentNode - The parent node containing the after element.\n * @param {Node} element - The element to be moved.\n * @param {Node | null} after - The reference node to insert `element` before.\n * If `null`, `element` is appended as the last child.\n */\n function moveBefore(parentNode, element, after) {\n // @ts-ignore - use proposed moveBefore feature\n if (parentNode.moveBefore) {\n try {\n // @ts-ignore - use proposed moveBefore feature\n parentNode.moveBefore(element, after);\n } catch (e) {\n // fall back to insertBefore as some browsers may fail on moveBefore when trying to move Dom disconnected nodes to pantry\n parentNode.insertBefore(element, after);\n }\n } else {\n parentNode.insertBefore(element, after);\n }\n }\n\n return morphChildren;\n })();\n\n //=============================================================================\n // Single Node Morphing Code\n //=============================================================================\n const morphNode = (function () {\n /**\n * @param {Node} oldNode root node to merge content into\n * @param {Node} newContent new content to merge\n * @param {MorphContext} ctx the merge context\n * @returns {Node | null} the element that ended up in the DOM\n */\n function morphNode(oldNode, newContent, ctx) {\n if (ctx.ignoreActive && oldNode === document.activeElement) {\n // don't morph focused element\n return null;\n }\n\n if (ctx.callbacks.beforeNodeMorphed(oldNode, newContent) === false) {\n return oldNode;\n }\n\n if (oldNode instanceof HTMLHeadElement && ctx.head.ignore) ; else if (\n oldNode instanceof HTMLHeadElement &&\n ctx.head.style !== \"morph\"\n ) {\n // ok to cast: if newContent wasn't also a , it would've got caught in the `!isSoftMatch` branch above\n handleHeadElement(\n oldNode,\n /** @type {HTMLHeadElement} */ (newContent),\n ctx,\n );\n } else {\n morphAttributes(oldNode, newContent, ctx);\n if (!ignoreValueOfActiveElement(oldNode, ctx)) {\n // @ts-ignore newContent can be a node here because .firstChild will be null\n morphChildren(ctx, oldNode, newContent);\n }\n }\n ctx.callbacks.afterNodeMorphed(oldNode, newContent);\n return oldNode;\n }\n\n /**\n * syncs the oldNode to the newNode, copying over all attributes and\n * inner element state from the newNode to the oldNode\n *\n * @param {Node} oldNode the node to copy attributes & state to\n * @param {Node} newNode the node to copy attributes & state from\n * @param {MorphContext} ctx the merge context\n */\n function morphAttributes(oldNode, newNode, ctx) {\n let type = newNode.nodeType;\n\n // if is an element type, sync the attributes from the\n // new node into the new node\n if (type === 1 /* element type */) {\n const oldElt = /** @type {Element} */ (oldNode);\n const newElt = /** @type {Element} */ (newNode);\n\n const oldAttributes = oldElt.attributes;\n const newAttributes = newElt.attributes;\n for (const newAttribute of newAttributes) {\n if (ignoreAttribute(newAttribute.name, oldElt, \"update\", ctx)) {\n continue;\n }\n if (oldElt.getAttribute(newAttribute.name) !== newAttribute.value) {\n oldElt.setAttribute(newAttribute.name, newAttribute.value);\n }\n }\n // iterate backwards to avoid skipping over items when a delete occurs\n for (let i = oldAttributes.length - 1; 0 <= i; i--) {\n const oldAttribute = oldAttributes[i];\n\n // toAttributes is a live NamedNodeMap, so iteration+mutation is unsafe\n // e.g. custom element attribute callbacks can remove other attributes\n if (!oldAttribute) continue;\n\n if (!newElt.hasAttribute(oldAttribute.name)) {\n if (ignoreAttribute(oldAttribute.name, oldElt, \"remove\", ctx)) {\n continue;\n }\n oldElt.removeAttribute(oldAttribute.name);\n }\n }\n\n if (!ignoreValueOfActiveElement(oldElt, ctx)) {\n syncInputValue(oldElt, newElt, ctx);\n }\n }\n\n // sync text nodes\n if (type === 8 /* comment */ || type === 3 /* text */) {\n if (oldNode.nodeValue !== newNode.nodeValue) {\n oldNode.nodeValue = newNode.nodeValue;\n }\n }\n }\n\n /**\n * NB: many bothans died to bring us information:\n *\n * https://github.com/patrick-steele-idem/morphdom/blob/master/src/specialElHandlers.js\n * https://github.com/choojs/nanomorph/blob/master/lib/morph.jsL113\n *\n * @param {Element} oldElement the element to sync the input value to\n * @param {Element} newElement the element to sync the input value from\n * @param {MorphContext} ctx the merge context\n */\n function syncInputValue(oldElement, newElement, ctx) {\n if (\n oldElement instanceof HTMLInputElement &&\n newElement instanceof HTMLInputElement &&\n newElement.type !== \"file\"\n ) {\n let newValue = newElement.value;\n let oldValue = oldElement.value;\n\n // sync boolean attributes\n syncBooleanAttribute(oldElement, newElement, \"checked\", ctx);\n syncBooleanAttribute(oldElement, newElement, \"disabled\", ctx);\n\n if (!newElement.hasAttribute(\"value\")) {\n if (!ignoreAttribute(\"value\", oldElement, \"remove\", ctx)) {\n oldElement.value = \"\";\n oldElement.removeAttribute(\"value\");\n }\n } else if (oldValue !== newValue) {\n if (!ignoreAttribute(\"value\", oldElement, \"update\", ctx)) {\n oldElement.setAttribute(\"value\", newValue);\n oldElement.value = newValue;\n }\n }\n // TODO: QUESTION(1cg): this used to only check `newElement` unlike the other branches -- why?\n // did I break something?\n } else if (\n oldElement instanceof HTMLOptionElement &&\n newElement instanceof HTMLOptionElement\n ) {\n syncBooleanAttribute(oldElement, newElement, \"selected\", ctx);\n } else if (\n oldElement instanceof HTMLTextAreaElement &&\n newElement instanceof HTMLTextAreaElement\n ) {\n let newValue = newElement.value;\n let oldValue = oldElement.value;\n if (ignoreAttribute(\"value\", oldElement, \"update\", ctx)) {\n return;\n }\n if (newValue !== oldValue) {\n oldElement.value = newValue;\n }\n if (\n oldElement.firstChild &&\n oldElement.firstChild.nodeValue !== newValue\n ) {\n oldElement.firstChild.nodeValue = newValue;\n }\n }\n }\n\n /**\n * @param {Element} oldElement element to write the value to\n * @param {Element} newElement element to read the value from\n * @param {string} attributeName the attribute name\n * @param {MorphContext} ctx the merge context\n */\n function syncBooleanAttribute(oldElement, newElement, attributeName, ctx) {\n // @ts-ignore this function is only used on boolean attrs that are reflected as dom properties\n const newLiveValue = newElement[attributeName],\n // @ts-ignore ditto\n oldLiveValue = oldElement[attributeName];\n if (newLiveValue !== oldLiveValue) {\n const ignoreUpdate = ignoreAttribute(\n attributeName,\n oldElement,\n \"update\",\n ctx,\n );\n if (!ignoreUpdate) {\n // update attribute's associated DOM property\n // @ts-ignore this function is only used on boolean attrs that are reflected as dom properties\n oldElement[attributeName] = newElement[attributeName];\n }\n if (newLiveValue) {\n if (!ignoreUpdate) {\n // https://developer.mozilla.org/en-US/docs/Glossary/Boolean/HTML\n // this is the correct way to set a boolean attribute to \"true\"\n oldElement.setAttribute(attributeName, \"\");\n }\n } else {\n if (!ignoreAttribute(attributeName, oldElement, \"remove\", ctx)) {\n oldElement.removeAttribute(attributeName);\n }\n }\n }\n }\n\n /**\n * @param {string} attr the attribute to be mutated\n * @param {Element} element the element that is going to be updated\n * @param {\"update\" | \"remove\"} updateType\n * @param {MorphContext} ctx the merge context\n * @returns {boolean} true if the attribute should be ignored, false otherwise\n */\n function ignoreAttribute(attr, element, updateType, ctx) {\n if (\n attr === \"value\" &&\n ctx.ignoreActiveValue &&\n element === document.activeElement\n ) {\n return true;\n }\n return (\n ctx.callbacks.beforeAttributeUpdated(attr, element, updateType) ===\n false\n );\n }\n\n /**\n * @param {Node} possibleActiveElement\n * @param {MorphContext} ctx\n * @returns {boolean}\n */\n function ignoreValueOfActiveElement(possibleActiveElement, ctx) {\n return (\n !!ctx.ignoreActiveValue &&\n possibleActiveElement === document.activeElement &&\n possibleActiveElement !== document.body\n );\n }\n\n return morphNode;\n })();\n\n //=============================================================================\n // Head Management Functions\n //=============================================================================\n /**\n * @param {MorphContext} ctx\n * @param {Element} oldNode\n * @param {Element} newNode\n * @param {function} callback\n * @returns {Node[] | Promise}\n */\n function withHeadBlocking(ctx, oldNode, newNode, callback) {\n if (ctx.head.block) {\n const oldHead = oldNode.querySelector(\"head\");\n const newHead = newNode.querySelector(\"head\");\n if (oldHead && newHead) {\n const promises = handleHeadElement(oldHead, newHead, ctx);\n // when head promises resolve, proceed ignoring the head tag\n return Promise.all(promises).then(() => {\n const newCtx = Object.assign(ctx, {\n head: {\n block: false,\n ignore: true,\n },\n });\n return callback(newCtx);\n });\n }\n }\n // just proceed if we not head blocking\n return callback(ctx);\n }\n\n /**\n * The HEAD tag can be handled specially, either w/ a 'merge' or 'append' style\n *\n * @param {Element} oldHead\n * @param {Element} newHead\n * @param {MorphContext} ctx\n * @returns {Promise[]}\n */\n function handleHeadElement(oldHead, newHead, ctx) {\n let added = [];\n let removed = [];\n let preserved = [];\n let nodesToAppend = [];\n\n // put all new head elements into a Map, by their outerHTML\n let srcToNewHeadNodes = new Map();\n for (const newHeadChild of newHead.children) {\n srcToNewHeadNodes.set(newHeadChild.outerHTML, newHeadChild);\n }\n\n // for each elt in the current head\n for (const currentHeadElt of oldHead.children) {\n // If the current head element is in the map\n let inNewContent = srcToNewHeadNodes.has(currentHeadElt.outerHTML);\n let isReAppended = ctx.head.shouldReAppend(currentHeadElt);\n let isPreserved = ctx.head.shouldPreserve(currentHeadElt);\n if (inNewContent || isPreserved) {\n if (isReAppended) {\n // remove the current version and let the new version replace it and re-execute\n removed.push(currentHeadElt);\n } else {\n // this element already exists and should not be re-appended, so remove it from\n // the new content map, preserving it in the DOM\n srcToNewHeadNodes.delete(currentHeadElt.outerHTML);\n preserved.push(currentHeadElt);\n }\n } else {\n if (ctx.head.style === \"append\") {\n // we are appending and this existing element is not new content\n // so if and only if it is marked for re-append do we do anything\n if (isReAppended) {\n removed.push(currentHeadElt);\n nodesToAppend.push(currentHeadElt);\n }\n } else {\n // if this is a merge, we remove this content since it is not in the new head\n if (ctx.head.shouldRemove(currentHeadElt) !== false) {\n removed.push(currentHeadElt);\n }\n }\n }\n }\n\n // Push the remaining new head elements in the Map into the\n // nodes to append to the head tag\n nodesToAppend.push(...srcToNewHeadNodes.values());\n\n let promises = [];\n for (const newNode of nodesToAppend) {\n // TODO: This could theoretically be null, based on type\n let newElt = /** @type {ChildNode} */ (\n document.createRange().createContextualFragment(newNode.outerHTML)\n .firstChild\n );\n if (ctx.callbacks.beforeNodeAdded(newElt) !== false) {\n if (\n (\"href\" in newElt && newElt.href) ||\n (\"src\" in newElt && newElt.src)\n ) {\n /** @type {(result?: any) => void} */ let resolve;\n let promise = new Promise(function (_resolve) {\n resolve = _resolve;\n });\n newElt.addEventListener(\"load\", function () {\n resolve();\n });\n promises.push(promise);\n }\n oldHead.appendChild(newElt);\n ctx.callbacks.afterNodeAdded(newElt);\n added.push(newElt);\n }\n }\n\n // remove all removed elements, after we have appended the new elements to avoid\n // additional network requests for things like style sheets\n for (const removedElement of removed) {\n if (ctx.callbacks.beforeNodeRemoved(removedElement) !== false) {\n oldHead.removeChild(removedElement);\n ctx.callbacks.afterNodeRemoved(removedElement);\n }\n }\n\n ctx.head.afterHeadMorphed(oldHead, {\n added: added,\n kept: preserved,\n removed: removed,\n });\n return promises;\n }\n\n //=============================================================================\n // Create Morph Context Functions\n //=============================================================================\n const createMorphContext = (function () {\n /**\n *\n * @param {Element} oldNode\n * @param {Element} newContent\n * @param {Config} config\n * @returns {MorphContext}\n */\n function createMorphContext(oldNode, newContent, config) {\n const { persistentIds, idMap } = createIdMaps(oldNode, newContent);\n\n const mergedConfig = mergeDefaults(config);\n const morphStyle = mergedConfig.morphStyle || \"outerHTML\";\n if (![\"innerHTML\", \"outerHTML\"].includes(morphStyle)) {\n throw `Do not understand how to morph style ${morphStyle}`;\n }\n\n return {\n target: oldNode,\n newContent: newContent,\n config: mergedConfig,\n morphStyle: morphStyle,\n ignoreActive: mergedConfig.ignoreActive,\n ignoreActiveValue: mergedConfig.ignoreActiveValue,\n restoreFocus: mergedConfig.restoreFocus,\n idMap: idMap,\n persistentIds: persistentIds,\n pantry: createPantry(),\n activeElementAndParents: createActiveElementAndParents(oldNode),\n callbacks: mergedConfig.callbacks,\n head: mergedConfig.head,\n };\n }\n\n /**\n * Deep merges the config object and the Idiomorph.defaults object to\n * produce a final configuration object\n * @param {Config} config\n * @returns {ConfigInternal}\n */\n function mergeDefaults(config) {\n let finalConfig = Object.assign({}, defaults);\n\n // copy top level stuff into final config\n Object.assign(finalConfig, config);\n\n // copy callbacks into final config (do this to deep merge the callbacks)\n finalConfig.callbacks = Object.assign(\n {},\n defaults.callbacks,\n config.callbacks,\n );\n\n // copy head config into final config (do this to deep merge the head)\n finalConfig.head = Object.assign({}, defaults.head, config.head);\n\n return finalConfig;\n }\n\n /**\n * @returns {HTMLDivElement}\n */\n function createPantry() {\n const pantry = document.createElement(\"div\");\n pantry.hidden = true;\n document.body.insertAdjacentElement(\"afterend\", pantry);\n return pantry;\n }\n\n /**\n * @param {Element} oldNode\n * @returns {Element[]}\n */\n function createActiveElementAndParents(oldNode) {\n /** @type {Element[]} */\n let activeElementAndParents = [];\n let elt = document.activeElement;\n if (elt?.tagName !== \"BODY\" && oldNode.contains(elt)) {\n while (elt) {\n activeElementAndParents.push(elt);\n if (elt === oldNode) break;\n elt = elt.parentElement;\n }\n }\n return activeElementAndParents;\n }\n\n /**\n * Returns all elements with an ID contained within the root element and its descendants\n *\n * @param {Element} root\n * @returns {Element[]}\n */\n function findIdElements(root) {\n let elements = Array.from(root.querySelectorAll(\"[id]\"));\n // root could be a document fragment which doesn't have `getAttribute`\n if (root.getAttribute?.(\"id\")) {\n elements.push(root);\n }\n return elements;\n }\n\n /**\n * A bottom-up algorithm that populates a map of Element -> IdSet.\n * The idSet for a given element is the set of all IDs contained within its subtree.\n * As an optimzation, we filter these IDs through the given list of persistent IDs,\n * because we don't need to bother considering IDed elements that won't be in the new content.\n *\n * @param {Map>} idMap\n * @param {Set} persistentIds\n * @param {Element} root\n * @param {Element[]} elements\n */\n function populateIdMapWithTree(idMap, persistentIds, root, elements) {\n for (const elt of elements) {\n // we can pretend id is non-null String, because the .has line will reject it immediately if not\n const id = /** @type {String} */ (elt.getAttribute(\"id\"));\n if (persistentIds.has(id)) {\n /** @type {Element|null} */\n let current = elt;\n // walk up the parent hierarchy of that element, adding the id\n // of element to the parent's id set\n while (current) {\n let idSet = idMap.get(current);\n // if the id set doesn't exist, create it and insert it in the map\n if (idSet == null) {\n idSet = new Set();\n idMap.set(current, idSet);\n }\n idSet.add(id);\n\n if (current === root) break;\n current = current.parentElement;\n }\n }\n }\n }\n\n /**\n * This function computes a map of nodes to all ids contained within that node (inclusive of the\n * node). This map can be used to ask if two nodes have intersecting sets of ids, which allows\n * for a looser definition of \"matching\" than tradition id matching, and allows child nodes\n * to contribute to a parent nodes matching.\n *\n * @param {Element} oldContent the old content that will be morphed\n * @param {Element} newContent the new content to morph to\n * @returns {IdSets}\n */\n function createIdMaps(oldContent, newContent) {\n const oldIdElements = findIdElements(oldContent);\n const newIdElements = findIdElements(newContent);\n\n const persistentIds = createPersistentIds(oldIdElements, newIdElements);\n\n /** @type {Map>} */\n let idMap = new Map();\n populateIdMapWithTree(idMap, persistentIds, oldContent, oldIdElements);\n\n /** @ts-ignore - if newContent is a duck-typed parent, pass its single child node as the root to halt upwards iteration */\n const newRoot = newContent.__idiomorphRoot || newContent;\n populateIdMapWithTree(idMap, persistentIds, newRoot, newIdElements);\n\n return { persistentIds, idMap };\n }\n\n /**\n * This function computes the set of ids that persist between the two contents excluding duplicates\n *\n * @param {Element[]} oldIdElements\n * @param {Element[]} newIdElements\n * @returns {Set}\n */\n function createPersistentIds(oldIdElements, newIdElements) {\n let duplicateIds = new Set();\n\n /** @type {Map} */\n let oldIdTagNameMap = new Map();\n for (const { id, tagName } of oldIdElements) {\n if (oldIdTagNameMap.has(id)) {\n duplicateIds.add(id);\n } else {\n oldIdTagNameMap.set(id, tagName);\n }\n }\n\n let persistentIds = new Set();\n for (const { id, tagName } of newIdElements) {\n if (persistentIds.has(id)) {\n duplicateIds.add(id);\n } else if (oldIdTagNameMap.get(id) === tagName) {\n persistentIds.add(id);\n }\n // skip if tag types mismatch because its not possible to morph one tag into another\n }\n\n for (const id of duplicateIds) {\n persistentIds.delete(id);\n }\n return persistentIds;\n }\n\n return createMorphContext;\n })();\n\n //=============================================================================\n // HTML Normalization Functions\n //=============================================================================\n const { normalizeElement, normalizeParent } = (function () {\n /** @type {WeakSet} */\n const generatedByIdiomorph = new WeakSet();\n\n /**\n *\n * @param {Element | Document} content\n * @returns {Element}\n */\n function normalizeElement(content) {\n if (content instanceof Document) {\n return content.documentElement;\n } else {\n return content;\n }\n }\n\n /**\n *\n * @param {null | string | Node | HTMLCollection | Node[] | Document & {generatedByIdiomorph:boolean}} newContent\n * @returns {Element}\n */\n function normalizeParent(newContent) {\n if (newContent == null) {\n return document.createElement(\"div\"); // dummy parent element\n } else if (typeof newContent === \"string\") {\n return normalizeParent(parseContent(newContent));\n } else if (\n generatedByIdiomorph.has(/** @type {Element} */ (newContent))\n ) {\n // the template tag created by idiomorph parsing can serve as a dummy parent\n return /** @type {Element} */ (newContent);\n } else if (newContent instanceof Node) {\n if (newContent.parentNode) {\n // we can't use the parent directly because newContent may have siblings\n // that we don't want in the morph, and reparenting might be expensive (TODO is it?),\n // so instead we create a fake parent node that only sees a slice of its children.\n /** @type {Element} */\n return /** @type {any} */ (new SlicedParentNode(newContent));\n } else {\n // a single node is added as a child to a dummy parent\n const dummyParent = document.createElement(\"div\");\n dummyParent.append(newContent);\n return dummyParent;\n }\n } else {\n // all nodes in the array or HTMLElement collection are consolidated under\n // a single dummy parent element\n const dummyParent = document.createElement(\"div\");\n for (const elt of [...newContent]) {\n dummyParent.append(elt);\n }\n return dummyParent;\n }\n }\n\n /**\n * A fake duck-typed parent element to wrap a single node, without actually reparenting it.\n * This is useful because the node may have siblings that we don't want in the morph, and it may also be moved\n * or replaced with one or more elements during the morph. This class effectively allows us a window into\n * a slice of a node's children.\n * \"If it walks like a duck, and quacks like a duck, then it must be a duck!\" -- James Whitcomb Riley (1849\u20131916)\n */\n class SlicedParentNode {\n /** @param {Node} node */\n constructor(node) {\n this.originalNode = node;\n this.realParentNode = /** @type {Element} */ (node.parentNode);\n this.previousSibling = node.previousSibling;\n this.nextSibling = node.nextSibling;\n }\n\n /** @returns {Node[]} */\n get childNodes() {\n // return slice of realParent's current childNodes, based on previousSibling and nextSibling\n const nodes = [];\n let cursor = this.previousSibling\n ? this.previousSibling.nextSibling\n : this.realParentNode.firstChild;\n while (cursor && cursor != this.nextSibling) {\n nodes.push(cursor);\n cursor = cursor.nextSibling;\n }\n return nodes;\n }\n\n /**\n * @param {string} selector\n * @returns {Element[]}\n */\n querySelectorAll(selector) {\n return this.childNodes.reduce((results, node) => {\n if (node instanceof Element) {\n if (node.matches(selector)) results.push(node);\n const nodeList = node.querySelectorAll(selector);\n for (let i = 0; i < nodeList.length; i++) {\n results.push(nodeList[i]);\n }\n }\n return results;\n }, /** @type {Element[]} */ ([]));\n }\n\n /**\n * @param {Node} node\n * @param {Node} referenceNode\n * @returns {Node}\n */\n insertBefore(node, referenceNode) {\n return this.realParentNode.insertBefore(node, referenceNode);\n }\n\n /**\n * @param {Node} node\n * @param {Node} referenceNode\n * @returns {Node}\n */\n moveBefore(node, referenceNode) {\n // @ts-ignore - use new moveBefore feature\n return this.realParentNode.moveBefore(node, referenceNode);\n }\n\n /**\n * for later use with populateIdMapWithTree to halt upwards iteration\n * @returns {Node}\n */\n get __idiomorphRoot() {\n return this.originalNode;\n }\n }\n\n /**\n *\n * @param {string} newContent\n * @returns {Node | null | DocumentFragment}\n */\n function parseContent(newContent) {\n let parser = new DOMParser();\n\n // remove svgs to avoid false-positive matches on head, etc.\n let contentWithSvgsRemoved = newContent.replace(\n /]*>|>)([\\s\\S]*?)<\\/svg>/gim,\n \"\",\n );\n\n // if the newContent contains a html, head or body tag, we can simply parse it w/o wrapping\n if (\n contentWithSvgsRemoved.match(/<\\/html>/) ||\n contentWithSvgsRemoved.match(/<\\/head>/) ||\n contentWithSvgsRemoved.match(/<\\/body>/)\n ) {\n let content = parser.parseFromString(newContent, \"text/html\");\n // if it is a full HTML document, return the document itself as the parent container\n if (contentWithSvgsRemoved.match(/<\\/html>/)) {\n generatedByIdiomorph.add(content);\n return content;\n } else {\n // otherwise return the html element as the parent container\n let htmlElement = content.firstChild;\n if (htmlElement) {\n generatedByIdiomorph.add(htmlElement);\n }\n return htmlElement;\n }\n } else {\n // if it is partial HTML, wrap it in a template tag to provide a parent element and also to help\n // deal with touchy tags like tr, tbody, etc.\n let responseDoc = parser.parseFromString(\n \"\",\n \"text/html\",\n );\n let content = /** @type {HTMLTemplateElement} */ (\n responseDoc.body.querySelector(\"template\")\n ).content;\n generatedByIdiomorph.add(content);\n return content;\n }\n }\n\n return { normalizeElement, normalizeParent };\n })();\n\n //=============================================================================\n // This is what ends up becoming the Idiomorph global object\n //=============================================================================\n return {\n morph,\n defaults,\n };\n})();\n\n/**\n * Morph the state of the currentElement based on the attributes and contents of\n * the newElement. Morphing may dispatch turbo:before-morph-element,\n * turbo:before-morph-attribute, and turbo:morph-element events.\n *\n * @param currentElement Element destination of morphing changes\n * @param newElement Element source of morphing changes\n */\nfunction morphElements(currentElement, newElement, { callbacks, ...options } = {}) {\n Idiomorph.morph(currentElement, newElement, {\n ...options,\n callbacks: new DefaultIdiomorphCallbacks(callbacks)\n });\n}\n\n/**\n * Morph the child elements of the currentElement based on the child elements of\n * the newElement. Morphing children may dispatch turbo:before-morph-element,\n * turbo:before-morph-attribute, and turbo:morph-element events.\n *\n * @param currentElement Element destination of morphing children changes\n * @param newElement Element source of morphing children changes\n */\nfunction morphChildren(currentElement, newElement, options = {}) {\n morphElements(currentElement, newElement.childNodes, {\n ...options,\n morphStyle: \"innerHTML\"\n });\n}\n\nfunction shouldRefreshFrameWithMorphing(currentFrame, newFrame) {\n return currentFrame instanceof FrameElement &&\n currentFrame.shouldReloadWithMorph && (!newFrame || areFramesCompatibleForRefreshing(currentFrame, newFrame)) &&\n !currentFrame.closest(\"[data-turbo-permanent]\")\n}\n\nfunction areFramesCompatibleForRefreshing(currentFrame, newFrame) {\n // newFrame cannot yet be an instance of FrameElement because custom\n // elements don't get initialized until they're attached to the DOM, so\n // test its Element#nodeName instead\n return newFrame instanceof Element && newFrame.nodeName === \"TURBO-FRAME\" && currentFrame.id === newFrame.id &&\n (!newFrame.getAttribute(\"src\") || urlsAreEqual(currentFrame.src, newFrame.getAttribute(\"src\")))\n}\n\nfunction closestFrameReloadableWithMorphing(node) {\n return node.parentElement.closest(\"turbo-frame[src][refresh=morph]\")\n}\n\nclass DefaultIdiomorphCallbacks {\n #beforeNodeMorphed\n\n constructor({ beforeNodeMorphed } = {}) {\n this.#beforeNodeMorphed = beforeNodeMorphed || (() => true);\n }\n\n beforeNodeAdded = (node) => {\n return !(node.id && node.hasAttribute(\"data-turbo-permanent\") && document.getElementById(node.id))\n }\n\n beforeNodeMorphed = (currentElement, newElement) => {\n if (currentElement instanceof Element) {\n if (!currentElement.hasAttribute(\"data-turbo-permanent\") && this.#beforeNodeMorphed(currentElement, newElement)) {\n const event = dispatch(\"turbo:before-morph-element\", {\n cancelable: true,\n target: currentElement,\n detail: { currentElement, newElement }\n });\n\n return !event.defaultPrevented\n } else {\n return false\n }\n }\n }\n\n beforeAttributeUpdated = (attributeName, target, mutationType) => {\n const event = dispatch(\"turbo:before-morph-attribute\", {\n cancelable: true,\n target,\n detail: { attributeName, mutationType }\n });\n\n return !event.defaultPrevented\n }\n\n beforeNodeRemoved = (node) => {\n return this.beforeNodeMorphed(node)\n }\n\n afterNodeMorphed = (currentElement, newElement) => {\n if (currentElement instanceof Element) {\n dispatch(\"turbo:morph-element\", {\n target: currentElement,\n detail: { currentElement, newElement }\n });\n }\n }\n}\n\nclass MorphingFrameRenderer extends FrameRenderer {\n static renderElement(currentElement, newElement) {\n dispatch(\"turbo:before-frame-morph\", {\n target: currentElement,\n detail: { currentElement, newElement }\n });\n\n morphChildren(currentElement, newElement, {\n callbacks: {\n beforeNodeMorphed: (node, newNode) => {\n if (\n shouldRefreshFrameWithMorphing(node, newNode) &&\n closestFrameReloadableWithMorphing(node) === currentElement\n ) {\n node.reload();\n return false\n }\n return true\n }\n }\n });\n }\n\n async preservingPermanentElements(callback) {\n return await callback()\n }\n}\n\nclass ProgressBar {\n static animationDuration = 300 /*ms*/\n\n static get defaultCSS() {\n return unindent`\n .turbo-progress-bar {\n position: fixed;\n display: block;\n top: 0;\n left: 0;\n height: 3px;\n background: #0076ff;\n z-index: 2147483647;\n transition:\n width ${ProgressBar.animationDuration}ms ease-out,\n opacity ${ProgressBar.animationDuration / 2}ms ${ProgressBar.animationDuration / 2}ms ease-in;\n transform: translate3d(0, 0, 0);\n }\n `\n }\n\n hiding = false\n value = 0\n visible = false\n\n constructor() {\n this.stylesheetElement = this.createStylesheetElement();\n this.progressElement = this.createProgressElement();\n this.installStylesheetElement();\n this.setValue(0);\n }\n\n show() {\n if (!this.visible) {\n this.visible = true;\n this.installProgressElement();\n this.startTrickling();\n }\n }\n\n hide() {\n if (this.visible && !this.hiding) {\n this.hiding = true;\n this.fadeProgressElement(() => {\n this.uninstallProgressElement();\n this.stopTrickling();\n this.visible = false;\n this.hiding = false;\n });\n }\n }\n\n setValue(value) {\n this.value = value;\n this.refresh();\n }\n\n // Private\n\n installStylesheetElement() {\n document.head.insertBefore(this.stylesheetElement, document.head.firstChild);\n }\n\n installProgressElement() {\n this.progressElement.style.width = \"0\";\n this.progressElement.style.opacity = \"1\";\n document.documentElement.insertBefore(this.progressElement, document.body);\n this.refresh();\n }\n\n fadeProgressElement(callback) {\n this.progressElement.style.opacity = \"0\";\n setTimeout(callback, ProgressBar.animationDuration * 1.5);\n }\n\n uninstallProgressElement() {\n if (this.progressElement.parentNode) {\n document.documentElement.removeChild(this.progressElement);\n }\n }\n\n startTrickling() {\n if (!this.trickleInterval) {\n this.trickleInterval = window.setInterval(this.trickle, ProgressBar.animationDuration);\n }\n }\n\n stopTrickling() {\n window.clearInterval(this.trickleInterval);\n delete this.trickleInterval;\n }\n\n trickle = () => {\n this.setValue(this.value + Math.random() / 100);\n }\n\n refresh() {\n requestAnimationFrame(() => {\n this.progressElement.style.width = `${10 + this.value * 90}%`;\n });\n }\n\n createStylesheetElement() {\n const element = document.createElement(\"style\");\n element.type = \"text/css\";\n element.textContent = ProgressBar.defaultCSS;\n const cspNonce = getCspNonce();\n if (cspNonce) {\n element.nonce = cspNonce;\n }\n return element\n }\n\n createProgressElement() {\n const element = document.createElement(\"div\");\n element.className = \"turbo-progress-bar\";\n return element\n }\n}\n\nclass HeadSnapshot extends Snapshot {\n detailsByOuterHTML = this.children\n .filter((element) => !elementIsNoscript(element))\n .map((element) => elementWithoutNonce(element))\n .reduce((result, element) => {\n const { outerHTML } = element;\n const details =\n outerHTML in result\n ? result[outerHTML]\n : {\n type: elementType(element),\n tracked: elementIsTracked(element),\n elements: []\n };\n return {\n ...result,\n [outerHTML]: {\n ...details,\n elements: [...details.elements, element]\n }\n }\n }, {})\n\n get trackedElementSignature() {\n return Object.keys(this.detailsByOuterHTML)\n .filter((outerHTML) => this.detailsByOuterHTML[outerHTML].tracked)\n .join(\"\")\n }\n\n getScriptElementsNotInSnapshot(snapshot) {\n return this.getElementsMatchingTypeNotInSnapshot(\"script\", snapshot)\n }\n\n getStylesheetElementsNotInSnapshot(snapshot) {\n return this.getElementsMatchingTypeNotInSnapshot(\"stylesheet\", snapshot)\n }\n\n getElementsMatchingTypeNotInSnapshot(matchedType, snapshot) {\n return Object.keys(this.detailsByOuterHTML)\n .filter((outerHTML) => !(outerHTML in snapshot.detailsByOuterHTML))\n .map((outerHTML) => this.detailsByOuterHTML[outerHTML])\n .filter(({ type }) => type == matchedType)\n .map(({ elements: [element] }) => element)\n }\n\n get provisionalElements() {\n return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => {\n const { type, tracked, elements } = this.detailsByOuterHTML[outerHTML];\n if (type == null && !tracked) {\n return [...result, ...elements]\n } else if (elements.length > 1) {\n return [...result, ...elements.slice(1)]\n } else {\n return result\n }\n }, [])\n }\n\n getMetaValue(name) {\n const element = this.findMetaElementByName(name);\n return element ? element.getAttribute(\"content\") : null\n }\n\n findMetaElementByName(name) {\n return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => {\n const {\n elements: [element]\n } = this.detailsByOuterHTML[outerHTML];\n return elementIsMetaElementWithName(element, name) ? element : result\n }, undefined | undefined)\n }\n}\n\nfunction elementType(element) {\n if (elementIsScript(element)) {\n return \"script\"\n } else if (elementIsStylesheet(element)) {\n return \"stylesheet\"\n }\n}\n\nfunction elementIsTracked(element) {\n return element.getAttribute(\"data-turbo-track\") == \"reload\"\n}\n\nfunction elementIsScript(element) {\n const tagName = element.localName;\n return tagName == \"script\"\n}\n\nfunction elementIsNoscript(element) {\n const tagName = element.localName;\n return tagName == \"noscript\"\n}\n\nfunction elementIsStylesheet(element) {\n const tagName = element.localName;\n return tagName == \"style\" || (tagName == \"link\" && element.getAttribute(\"rel\") == \"stylesheet\")\n}\n\nfunction elementIsMetaElementWithName(element, name) {\n const tagName = element.localName;\n return tagName == \"meta\" && element.getAttribute(\"name\") == name\n}\n\nfunction elementWithoutNonce(element) {\n if (element.hasAttribute(\"nonce\")) {\n element.setAttribute(\"nonce\", \"\");\n }\n\n return element\n}\n\nclass PageSnapshot extends Snapshot {\n static fromHTMLString(html = \"\") {\n return this.fromDocument(parseHTMLDocument(html))\n }\n\n static fromElement(element) {\n return this.fromDocument(element.ownerDocument)\n }\n\n static fromDocument({ documentElement, body, head }) {\n return new this(documentElement, body, new HeadSnapshot(head))\n }\n\n constructor(documentElement, body, headSnapshot) {\n super(body);\n this.documentElement = documentElement;\n this.headSnapshot = headSnapshot;\n }\n\n clone() {\n const clonedElement = this.element.cloneNode(true);\n\n const selectElements = this.element.querySelectorAll(\"select\");\n const clonedSelectElements = clonedElement.querySelectorAll(\"select\");\n\n for (const [index, source] of selectElements.entries()) {\n const clone = clonedSelectElements[index];\n for (const option of clone.selectedOptions) option.selected = false;\n for (const option of source.selectedOptions) clone.options[option.index].selected = true;\n }\n\n for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type=\"password\"]')) {\n clonedPasswordInput.value = \"\";\n }\n\n for (const clonedNoscriptElement of clonedElement.querySelectorAll(\"noscript\")) {\n clonedNoscriptElement.remove();\n }\n\n return new PageSnapshot(this.documentElement, clonedElement, this.headSnapshot)\n }\n\n get lang() {\n return this.documentElement.getAttribute(\"lang\")\n }\n\n get dir() {\n return this.documentElement.getAttribute(\"dir\")\n }\n\n get headElement() {\n return this.headSnapshot.element\n }\n\n get rootLocation() {\n const root = this.getSetting(\"root\") ?? \"/\";\n return expandURL(root)\n }\n\n get cacheControlValue() {\n return this.getSetting(\"cache-control\")\n }\n\n get isPreviewable() {\n return this.cacheControlValue != \"no-preview\"\n }\n\n get isCacheable() {\n return this.cacheControlValue != \"no-cache\"\n }\n\n get isVisitable() {\n return this.getSetting(\"visit-control\") != \"reload\"\n }\n\n get prefersViewTransitions() {\n const viewTransitionEnabled = this.getSetting(\"view-transition\") === \"true\" || this.headSnapshot.getMetaValue(\"view-transition\") === \"same-origin\";\n return viewTransitionEnabled && !window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n }\n\n get refreshMethod() {\n return this.getSetting(\"refresh-method\")\n }\n\n get refreshScroll() {\n return this.getSetting(\"refresh-scroll\")\n }\n\n // Private\n\n getSetting(name) {\n return this.headSnapshot.getMetaValue(`turbo-${name}`)\n }\n}\n\nclass ViewTransitioner {\n #viewTransitionStarted = false\n #lastOperation = Promise.resolve()\n\n renderChange(useViewTransition, render) {\n if (useViewTransition && this.viewTransitionsAvailable && !this.#viewTransitionStarted) {\n this.#viewTransitionStarted = true;\n this.#lastOperation = this.#lastOperation.then(async () => {\n await document.startViewTransition(render).finished;\n });\n } else {\n this.#lastOperation = this.#lastOperation.then(render);\n }\n\n return this.#lastOperation\n }\n\n get viewTransitionsAvailable() {\n return document.startViewTransition\n }\n}\n\nconst defaultOptions = {\n action: \"advance\",\n historyChanged: false,\n visitCachedSnapshot: () => {},\n willRender: true,\n updateHistory: true,\n shouldCacheSnapshot: true,\n acceptsStreamResponse: false,\n refresh: {}\n};\n\nconst TimingMetric = {\n visitStart: \"visitStart\",\n requestStart: \"requestStart\",\n requestEnd: \"requestEnd\",\n visitEnd: \"visitEnd\"\n};\n\nconst VisitState = {\n initialized: \"initialized\",\n started: \"started\",\n canceled: \"canceled\",\n failed: \"failed\",\n completed: \"completed\"\n};\n\nconst SystemStatusCode = {\n networkFailure: 0,\n timeoutFailure: -1,\n contentTypeMismatch: -2\n};\n\nconst Direction = {\n advance: \"forward\",\n restore: \"back\",\n replace: \"none\"\n};\n\nclass Visit {\n identifier = uuid() // Required by turbo-ios\n timingMetrics = {}\n\n followedRedirect = false\n historyChanged = false\n scrolled = false\n shouldCacheSnapshot = true\n acceptsStreamResponse = false\n snapshotCached = false\n state = VisitState.initialized\n viewTransitioner = new ViewTransitioner()\n\n constructor(delegate, location, restorationIdentifier, options = {}) {\n this.delegate = delegate;\n this.location = location;\n this.restorationIdentifier = restorationIdentifier || uuid();\n\n const {\n action,\n historyChanged,\n referrer,\n snapshot,\n snapshotHTML,\n response,\n visitCachedSnapshot,\n willRender,\n updateHistory,\n shouldCacheSnapshot,\n acceptsStreamResponse,\n direction,\n refresh\n } = {\n ...defaultOptions,\n ...options\n };\n this.action = action;\n this.historyChanged = historyChanged;\n this.referrer = referrer;\n this.snapshot = snapshot;\n this.snapshotHTML = snapshotHTML;\n this.response = response;\n this.isPageRefresh = this.view.isPageRefresh(this);\n this.visitCachedSnapshot = visitCachedSnapshot;\n this.willRender = willRender;\n this.updateHistory = updateHistory;\n this.scrolled = !willRender;\n this.shouldCacheSnapshot = shouldCacheSnapshot;\n this.acceptsStreamResponse = acceptsStreamResponse;\n this.direction = direction || Direction[action];\n this.refresh = refresh;\n }\n\n get adapter() {\n return this.delegate.adapter\n }\n\n get view() {\n return this.delegate.view\n }\n\n get history() {\n return this.delegate.history\n }\n\n get restorationData() {\n return this.history.getRestorationDataForIdentifier(this.restorationIdentifier)\n }\n\n start() {\n if (this.state == VisitState.initialized) {\n this.recordTimingMetric(TimingMetric.visitStart);\n this.state = VisitState.started;\n this.adapter.visitStarted(this);\n this.delegate.visitStarted(this);\n }\n }\n\n cancel() {\n if (this.state == VisitState.started) {\n if (this.request) {\n this.request.cancel();\n }\n this.cancelRender();\n this.state = VisitState.canceled;\n }\n }\n\n complete() {\n if (this.state == VisitState.started) {\n this.recordTimingMetric(TimingMetric.visitEnd);\n this.adapter.visitCompleted(this);\n this.state = VisitState.completed;\n this.followRedirect();\n\n if (!this.followedRedirect) {\n this.delegate.visitCompleted(this);\n }\n }\n }\n\n fail() {\n if (this.state == VisitState.started) {\n this.state = VisitState.failed;\n this.adapter.visitFailed(this);\n this.delegate.visitCompleted(this);\n }\n }\n\n changeHistory() {\n if (!this.historyChanged && this.updateHistory) {\n const actionForHistory = this.location.href === this.referrer?.href ? \"replace\" : this.action;\n const method = getHistoryMethodForAction(actionForHistory);\n this.history.update(method, this.location, this.restorationIdentifier);\n this.historyChanged = true;\n }\n }\n\n issueRequest() {\n if (this.hasPreloadedResponse()) {\n this.simulateRequest();\n } else if (this.shouldIssueRequest() && !this.request) {\n this.request = new FetchRequest(this, FetchMethod.get, this.location);\n this.request.perform();\n }\n }\n\n simulateRequest() {\n if (this.response) {\n this.startRequest();\n this.recordResponse();\n this.finishRequest();\n }\n }\n\n startRequest() {\n this.recordTimingMetric(TimingMetric.requestStart);\n this.adapter.visitRequestStarted(this);\n }\n\n recordResponse(response = this.response) {\n this.response = response;\n if (response) {\n const { statusCode } = response;\n if (isSuccessful(statusCode)) {\n this.adapter.visitRequestCompleted(this);\n } else {\n this.adapter.visitRequestFailedWithStatusCode(this, statusCode);\n }\n }\n }\n\n finishRequest() {\n this.recordTimingMetric(TimingMetric.requestEnd);\n this.adapter.visitRequestFinished(this);\n }\n\n loadResponse() {\n if (this.response) {\n const { statusCode, responseHTML } = this.response;\n this.render(async () => {\n if (this.shouldCacheSnapshot) this.cacheSnapshot();\n if (this.view.renderPromise) await this.view.renderPromise;\n\n if (isSuccessful(statusCode) && responseHTML != null) {\n const snapshot = PageSnapshot.fromHTMLString(responseHTML);\n await this.renderPageSnapshot(snapshot, false);\n\n this.adapter.visitRendered(this);\n this.complete();\n } else {\n await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML), this);\n this.adapter.visitRendered(this);\n this.fail();\n }\n });\n }\n }\n\n getCachedSnapshot() {\n const snapshot = this.view.getCachedSnapshotForLocation(this.location) || this.getPreloadedSnapshot();\n\n if (snapshot && (!getAnchor(this.location) || snapshot.hasAnchor(getAnchor(this.location)))) {\n if (this.action == \"restore\" || snapshot.isPreviewable) {\n return snapshot\n }\n }\n }\n\n getPreloadedSnapshot() {\n if (this.snapshotHTML) {\n return PageSnapshot.fromHTMLString(this.snapshotHTML)\n }\n }\n\n hasCachedSnapshot() {\n return this.getCachedSnapshot() != null\n }\n\n loadCachedSnapshot() {\n const snapshot = this.getCachedSnapshot();\n if (snapshot) {\n const isPreview = this.shouldIssueRequest();\n this.render(async () => {\n this.cacheSnapshot();\n if (this.isPageRefresh) {\n this.adapter.visitRendered(this);\n } else {\n if (this.view.renderPromise) await this.view.renderPromise;\n\n await this.renderPageSnapshot(snapshot, isPreview);\n\n this.adapter.visitRendered(this);\n if (!isPreview) {\n this.complete();\n }\n }\n });\n }\n }\n\n followRedirect() {\n if (this.redirectedToLocation && !this.followedRedirect && this.response?.redirected) {\n this.adapter.visitProposedToLocation(this.redirectedToLocation, {\n action: \"replace\",\n response: this.response,\n shouldCacheSnapshot: false,\n willRender: false\n });\n this.followedRedirect = true;\n }\n }\n\n // Fetch request delegate\n\n prepareRequest(request) {\n if (this.acceptsStreamResponse) {\n request.acceptResponseType(StreamMessage.contentType);\n }\n }\n\n requestStarted() {\n this.startRequest();\n }\n\n requestPreventedHandlingResponse(_request, _response) {}\n\n async requestSucceededWithResponse(request, response) {\n const responseHTML = await response.responseHTML;\n const { redirected, statusCode } = response;\n if (responseHTML == undefined) {\n this.recordResponse({\n statusCode: SystemStatusCode.contentTypeMismatch,\n redirected\n });\n } else {\n this.redirectedToLocation = response.redirected ? response.location : undefined;\n this.recordResponse({ statusCode: statusCode, responseHTML, redirected });\n }\n }\n\n async requestFailedWithResponse(request, response) {\n const responseHTML = await response.responseHTML;\n const { redirected, statusCode } = response;\n if (responseHTML == undefined) {\n this.recordResponse({\n statusCode: SystemStatusCode.contentTypeMismatch,\n redirected\n });\n } else {\n this.recordResponse({ statusCode: statusCode, responseHTML, redirected });\n }\n }\n\n requestErrored(_request, _error) {\n this.recordResponse({\n statusCode: SystemStatusCode.networkFailure,\n redirected: false\n });\n }\n\n requestFinished() {\n this.finishRequest();\n }\n\n // Scrolling\n\n performScroll() {\n if (!this.scrolled && !this.view.forceReloaded && !this.view.shouldPreserveScrollPosition(this)) {\n if (this.action == \"restore\") {\n this.scrollToRestoredPosition() || this.scrollToAnchor() || this.view.scrollToTop();\n } else {\n this.scrollToAnchor() || this.view.scrollToTop();\n }\n\n this.scrolled = true;\n }\n }\n\n scrollToRestoredPosition() {\n const { scrollPosition } = this.restorationData;\n if (scrollPosition) {\n this.view.scrollToPosition(scrollPosition);\n return true\n }\n }\n\n scrollToAnchor() {\n const anchor = getAnchor(this.location);\n if (anchor != null) {\n this.view.scrollToAnchor(anchor);\n return true\n }\n }\n\n // Instrumentation\n\n recordTimingMetric(metric) {\n this.timingMetrics[metric] = new Date().getTime();\n }\n\n getTimingMetrics() {\n return { ...this.timingMetrics }\n }\n\n // Private\n\n hasPreloadedResponse() {\n return typeof this.response == \"object\"\n }\n\n shouldIssueRequest() {\n if (this.action == \"restore\") {\n return !this.hasCachedSnapshot()\n } else {\n return this.willRender\n }\n }\n\n cacheSnapshot() {\n if (!this.snapshotCached) {\n this.view.cacheSnapshot(this.snapshot).then((snapshot) => snapshot && this.visitCachedSnapshot(snapshot));\n this.snapshotCached = true;\n }\n }\n\n async render(callback) {\n this.cancelRender();\n await new Promise((resolve) => {\n this.frame =\n document.visibilityState === \"hidden\" ? setTimeout(() => resolve(), 0) : requestAnimationFrame(() => resolve());\n });\n await callback();\n delete this.frame;\n }\n\n async renderPageSnapshot(snapshot, isPreview) {\n await this.viewTransitioner.renderChange(this.view.shouldTransitionTo(snapshot), async () => {\n await this.view.renderPage(snapshot, isPreview, this.willRender, this);\n this.performScroll();\n });\n }\n\n cancelRender() {\n if (this.frame) {\n cancelAnimationFrame(this.frame);\n delete this.frame;\n }\n }\n}\n\nfunction isSuccessful(statusCode) {\n return statusCode >= 200 && statusCode < 300\n}\n\nclass BrowserAdapter {\n progressBar = new ProgressBar()\n\n constructor(session) {\n this.session = session;\n }\n\n visitProposedToLocation(location, options) {\n if (locationIsVisitable(location, this.navigator.rootLocation)) {\n this.navigator.startVisit(location, options?.restorationIdentifier || uuid(), options);\n } else {\n window.location.href = location.toString();\n }\n }\n\n visitStarted(visit) {\n this.location = visit.location;\n this.redirectedToLocation = null;\n\n visit.loadCachedSnapshot();\n visit.issueRequest();\n }\n\n visitRequestStarted(visit) {\n this.progressBar.setValue(0);\n if (visit.hasCachedSnapshot() || visit.action != \"restore\") {\n this.showVisitProgressBarAfterDelay();\n } else {\n this.showProgressBar();\n }\n }\n\n visitRequestCompleted(visit) {\n visit.loadResponse();\n\n if (visit.response.redirected) {\n this.redirectedToLocation = visit.redirectedToLocation;\n }\n }\n\n visitRequestFailedWithStatusCode(visit, statusCode) {\n switch (statusCode) {\n case SystemStatusCode.networkFailure:\n case SystemStatusCode.timeoutFailure:\n case SystemStatusCode.contentTypeMismatch:\n return this.reload({\n reason: \"request_failed\",\n context: {\n statusCode\n }\n })\n default:\n return visit.loadResponse()\n }\n }\n\n visitRequestFinished(_visit) {}\n\n visitCompleted(_visit) {\n this.progressBar.setValue(1);\n this.hideVisitProgressBar();\n }\n\n pageInvalidated(reason) {\n this.reload(reason);\n }\n\n visitFailed(_visit) {\n this.progressBar.setValue(1);\n this.hideVisitProgressBar();\n }\n\n visitRendered(_visit) {}\n\n // Link prefetching\n\n linkPrefetchingIsEnabledForLocation(location) {\n return true\n }\n\n // Form Submission Delegate\n\n formSubmissionStarted(_formSubmission) {\n this.progressBar.setValue(0);\n this.showFormProgressBarAfterDelay();\n }\n\n formSubmissionFinished(_formSubmission) {\n this.progressBar.setValue(1);\n this.hideFormProgressBar();\n }\n\n // Private\n\n showVisitProgressBarAfterDelay() {\n this.visitProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);\n }\n\n hideVisitProgressBar() {\n this.progressBar.hide();\n if (this.visitProgressBarTimeout != null) {\n window.clearTimeout(this.visitProgressBarTimeout);\n delete this.visitProgressBarTimeout;\n }\n }\n\n showFormProgressBarAfterDelay() {\n if (this.formProgressBarTimeout == null) {\n this.formProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);\n }\n }\n\n hideFormProgressBar() {\n this.progressBar.hide();\n if (this.formProgressBarTimeout != null) {\n window.clearTimeout(this.formProgressBarTimeout);\n delete this.formProgressBarTimeout;\n }\n }\n\n showProgressBar = () => {\n this.progressBar.show();\n }\n\n reload(reason) {\n dispatch(\"turbo:reload\", { detail: reason });\n\n window.location.href = (this.redirectedToLocation || this.location)?.toString() || window.location.href;\n }\n\n get navigator() {\n return this.session.navigator\n }\n}\n\nclass CacheObserver {\n selector = \"[data-turbo-temporary]\"\n\n started = false\n\n start() {\n if (!this.started) {\n this.started = true;\n addEventListener(\"turbo:before-cache\", this.removeTemporaryElements, false);\n }\n }\n\n stop() {\n if (this.started) {\n this.started = false;\n removeEventListener(\"turbo:before-cache\", this.removeTemporaryElements, false);\n }\n }\n\n removeTemporaryElements = (_event) => {\n for (const element of this.temporaryElements) {\n element.remove();\n }\n }\n\n get temporaryElements() {\n return [...document.querySelectorAll(this.selector)]\n }\n}\n\nclass FrameRedirector {\n constructor(session, element) {\n this.session = session;\n this.element = element;\n this.linkInterceptor = new LinkInterceptor(this, element);\n this.formSubmitObserver = new FormSubmitObserver(this, element);\n }\n\n start() {\n this.linkInterceptor.start();\n this.formSubmitObserver.start();\n }\n\n stop() {\n this.linkInterceptor.stop();\n this.formSubmitObserver.stop();\n }\n\n // Link interceptor delegate\n\n shouldInterceptLinkClick(element, _location, _event) {\n return this.#shouldRedirect(element)\n }\n\n linkClickIntercepted(element, url, event) {\n const frame = this.#findFrameElement(element);\n if (frame) {\n frame.delegate.linkClickIntercepted(element, url, event);\n }\n }\n\n // Form submit observer delegate\n\n willSubmitForm(element, submitter) {\n return (\n element.closest(\"turbo-frame\") == null &&\n this.#shouldSubmit(element, submitter) &&\n this.#shouldRedirect(element, submitter)\n )\n }\n\n formSubmitted(element, submitter) {\n const frame = this.#findFrameElement(element, submitter);\n if (frame) {\n frame.delegate.formSubmitted(element, submitter);\n }\n }\n\n #shouldSubmit(form, submitter) {\n const action = getAction$1(form, submitter);\n const meta = this.element.ownerDocument.querySelector(`meta[name=\"turbo-root\"]`);\n const rootLocation = expandURL(meta?.content ?? \"/\");\n\n return this.#shouldRedirect(form, submitter) && locationIsVisitable(action, rootLocation)\n }\n\n #shouldRedirect(element, submitter) {\n const isNavigatable =\n element instanceof HTMLFormElement\n ? this.session.submissionIsNavigatable(element, submitter)\n : this.session.elementIsNavigatable(element);\n\n if (isNavigatable) {\n const frame = this.#findFrameElement(element, submitter);\n return frame ? frame != element.closest(\"turbo-frame\") : false\n } else {\n return false\n }\n }\n\n #findFrameElement(element, submitter) {\n const id = submitter?.getAttribute(\"data-turbo-frame\") || element.getAttribute(\"data-turbo-frame\");\n if (id && id != \"_top\") {\n const frame = this.element.querySelector(`#${id}:not([disabled])`);\n if (frame instanceof FrameElement) {\n return frame\n }\n }\n }\n}\n\nclass History {\n location\n restorationIdentifier = uuid()\n restorationData = {}\n started = false\n currentIndex = 0\n\n constructor(delegate) {\n this.delegate = delegate;\n }\n\n start() {\n if (!this.started) {\n addEventListener(\"popstate\", this.onPopState, false);\n this.currentIndex = history.state?.turbo?.restorationIndex || 0;\n this.started = true;\n this.replace(new URL(window.location.href));\n }\n }\n\n stop() {\n if (this.started) {\n removeEventListener(\"popstate\", this.onPopState, false);\n this.started = false;\n }\n }\n\n push(location, restorationIdentifier) {\n this.update(history.pushState, location, restorationIdentifier);\n }\n\n replace(location, restorationIdentifier) {\n this.update(history.replaceState, location, restorationIdentifier);\n }\n\n update(method, location, restorationIdentifier = uuid()) {\n if (method === history.pushState) ++this.currentIndex;\n\n const state = { turbo: { restorationIdentifier, restorationIndex: this.currentIndex } };\n method.call(history, state, \"\", location.href);\n this.location = location;\n this.restorationIdentifier = restorationIdentifier;\n }\n\n // Restoration data\n\n getRestorationDataForIdentifier(restorationIdentifier) {\n return this.restorationData[restorationIdentifier] || {}\n }\n\n updateRestorationData(additionalData) {\n const { restorationIdentifier } = this;\n const restorationData = this.restorationData[restorationIdentifier];\n this.restorationData[restorationIdentifier] = {\n ...restorationData,\n ...additionalData\n };\n }\n\n // Scroll restoration\n\n assumeControlOfScrollRestoration() {\n if (!this.previousScrollRestoration) {\n this.previousScrollRestoration = history.scrollRestoration ?? \"auto\";\n history.scrollRestoration = \"manual\";\n }\n }\n\n relinquishControlOfScrollRestoration() {\n if (this.previousScrollRestoration) {\n history.scrollRestoration = this.previousScrollRestoration;\n delete this.previousScrollRestoration;\n }\n }\n\n // Event handlers\n\n onPopState = (event) => {\n const { turbo } = event.state || {};\n this.location = new URL(window.location.href);\n\n if (turbo) {\n const { restorationIdentifier, restorationIndex } = turbo;\n this.restorationIdentifier = restorationIdentifier;\n const direction = restorationIndex > this.currentIndex ? \"forward\" : \"back\";\n this.delegate.historyPoppedToLocationWithRestorationIdentifierAndDirection(this.location, restorationIdentifier, direction);\n this.currentIndex = restorationIndex;\n } else {\n this.currentIndex++;\n this.delegate.historyPoppedWithEmptyState(this.location);\n }\n }\n}\n\nclass LinkPrefetchObserver {\n started = false\n #prefetchedLink = null\n\n constructor(delegate, eventTarget) {\n this.delegate = delegate;\n this.eventTarget = eventTarget;\n }\n\n start() {\n if (this.started) return\n\n if (this.eventTarget.readyState === \"loading\") {\n this.eventTarget.addEventListener(\"DOMContentLoaded\", this.#enable, { once: true });\n } else {\n this.#enable();\n }\n }\n\n stop() {\n if (!this.started) return\n\n this.eventTarget.removeEventListener(\"mouseenter\", this.#tryToPrefetchRequest, {\n capture: true,\n passive: true\n });\n this.eventTarget.removeEventListener(\"mouseleave\", this.#cancelRequestIfObsolete, {\n capture: true,\n passive: true\n });\n\n this.eventTarget.removeEventListener(\"turbo:before-fetch-request\", this.#tryToUsePrefetchedRequest, true);\n this.started = false;\n }\n\n #enable = () => {\n this.eventTarget.addEventListener(\"mouseenter\", this.#tryToPrefetchRequest, {\n capture: true,\n passive: true\n });\n this.eventTarget.addEventListener(\"mouseleave\", this.#cancelRequestIfObsolete, {\n capture: true,\n passive: true\n });\n\n this.eventTarget.addEventListener(\"turbo:before-fetch-request\", this.#tryToUsePrefetchedRequest, true);\n this.started = true;\n }\n\n #tryToPrefetchRequest = (event) => {\n if (getMetaContent(\"turbo-prefetch\") === \"false\") return\n\n const target = event.target;\n const isLink = target.matches && target.matches(\"a[href]:not([target^=_]):not([download])\");\n\n if (isLink && this.#isPrefetchable(target)) {\n const link = target;\n const location = getLocationForLink(link);\n\n if (this.delegate.canPrefetchRequestToLocation(link, location)) {\n this.#prefetchedLink = link;\n\n const fetchRequest = new FetchRequest(\n this,\n FetchMethod.get,\n location,\n new URLSearchParams(),\n target\n );\n\n fetchRequest.fetchOptions.priority = \"low\";\n\n prefetchCache.putLater(location, fetchRequest, this.#cacheTtl);\n }\n }\n }\n\n #cancelRequestIfObsolete = (event) => {\n if (event.target === this.#prefetchedLink) this.#cancelPrefetchRequest();\n }\n\n #cancelPrefetchRequest = () => {\n prefetchCache.clear();\n this.#prefetchedLink = null;\n }\n\n #tryToUsePrefetchedRequest = (event) => {\n if (event.target.tagName !== \"FORM\" && event.detail.fetchOptions.method === \"GET\") {\n const cached = prefetchCache.get(event.detail.url);\n\n if (cached) {\n // User clicked link, use cache response\n event.detail.fetchRequest = cached;\n }\n\n prefetchCache.clear();\n }\n }\n\n prepareRequest(request) {\n const link = request.target;\n\n request.headers[\"X-Sec-Purpose\"] = \"prefetch\";\n\n const turboFrame = link.closest(\"turbo-frame\");\n const turboFrameTarget = link.getAttribute(\"data-turbo-frame\") || turboFrame?.getAttribute(\"target\") || turboFrame?.id;\n\n if (turboFrameTarget && turboFrameTarget !== \"_top\") {\n request.headers[\"Turbo-Frame\"] = turboFrameTarget;\n }\n }\n\n // Fetch request interface\n\n requestSucceededWithResponse() {}\n\n requestStarted(fetchRequest) {}\n\n requestErrored(fetchRequest) {}\n\n requestFinished(fetchRequest) {}\n\n requestPreventedHandlingResponse(fetchRequest, fetchResponse) {}\n\n requestFailedWithResponse(fetchRequest, fetchResponse) {}\n\n get #cacheTtl() {\n return Number(getMetaContent(\"turbo-prefetch-cache-time\")) || cacheTtl\n }\n\n #isPrefetchable(link) {\n const href = link.getAttribute(\"href\");\n\n if (!href) return false\n\n if (unfetchableLink(link)) return false\n if (linkToTheSamePage(link)) return false\n if (linkOptsOut(link)) return false\n if (nonSafeLink(link)) return false\n if (eventPrevented(link)) return false\n\n return true\n }\n}\n\nconst unfetchableLink = (link) => {\n return link.origin !== document.location.origin || ![\"http:\", \"https:\"].includes(link.protocol) || link.hasAttribute(\"target\")\n};\n\nconst linkToTheSamePage = (link) => {\n return (link.pathname + link.search === document.location.pathname + document.location.search) || link.href.startsWith(\"#\")\n};\n\nconst linkOptsOut = (link) => {\n if (link.getAttribute(\"data-turbo-prefetch\") === \"false\") return true\n if (link.getAttribute(\"data-turbo\") === \"false\") return true\n\n const turboPrefetchParent = findClosestRecursively(link, \"[data-turbo-prefetch]\");\n if (turboPrefetchParent && turboPrefetchParent.getAttribute(\"data-turbo-prefetch\") === \"false\") return true\n\n return false\n};\n\nconst nonSafeLink = (link) => {\n const turboMethod = link.getAttribute(\"data-turbo-method\");\n if (turboMethod && turboMethod.toLowerCase() !== \"get\") return true\n\n if (isUJS(link)) return true\n if (link.hasAttribute(\"data-turbo-confirm\")) return true\n if (link.hasAttribute(\"data-turbo-stream\")) return true\n\n return false\n};\n\nconst isUJS = (link) => {\n return link.hasAttribute(\"data-remote\") || link.hasAttribute(\"data-behavior\") || link.hasAttribute(\"data-confirm\") || link.hasAttribute(\"data-method\")\n};\n\nconst eventPrevented = (link) => {\n const event = dispatch(\"turbo:before-prefetch\", { target: link, cancelable: true });\n return event.defaultPrevented\n};\n\nclass Navigator {\n constructor(delegate) {\n this.delegate = delegate;\n }\n\n proposeVisit(location, options = {}) {\n if (this.delegate.allowsVisitingLocationWithAction(location, options.action)) {\n this.delegate.visitProposedToLocation(location, options);\n }\n }\n\n startVisit(locatable, restorationIdentifier, options = {}) {\n this.stop();\n this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, {\n referrer: this.location,\n ...options\n });\n this.currentVisit.start();\n }\n\n submitForm(form, submitter) {\n this.stop();\n this.formSubmission = new FormSubmission(this, form, submitter, true);\n\n this.formSubmission.start();\n }\n\n stop() {\n if (this.formSubmission) {\n this.formSubmission.stop();\n delete this.formSubmission;\n }\n\n if (this.currentVisit) {\n this.currentVisit.cancel();\n delete this.currentVisit;\n }\n }\n\n get adapter() {\n return this.delegate.adapter\n }\n\n get view() {\n return this.delegate.view\n }\n\n get rootLocation() {\n return this.view.snapshot.rootLocation\n }\n\n get history() {\n return this.delegate.history\n }\n\n // Form submission delegate\n\n formSubmissionStarted(formSubmission) {\n // Not all adapters implement formSubmissionStarted\n if (typeof this.adapter.formSubmissionStarted === \"function\") {\n this.adapter.formSubmissionStarted(formSubmission);\n }\n }\n\n async formSubmissionSucceededWithResponse(formSubmission, fetchResponse) {\n if (formSubmission == this.formSubmission) {\n const responseHTML = await fetchResponse.responseHTML;\n if (responseHTML) {\n const shouldCacheSnapshot = formSubmission.isSafe;\n if (!shouldCacheSnapshot) {\n this.view.clearSnapshotCache();\n }\n\n const { statusCode, redirected } = fetchResponse;\n const action = this.#getActionForFormSubmission(formSubmission, fetchResponse);\n const visitOptions = {\n action,\n shouldCacheSnapshot,\n response: { statusCode, responseHTML, redirected }\n };\n this.proposeVisit(fetchResponse.location, visitOptions);\n }\n }\n }\n\n async formSubmissionFailedWithResponse(formSubmission, fetchResponse) {\n const responseHTML = await fetchResponse.responseHTML;\n\n if (responseHTML) {\n const snapshot = PageSnapshot.fromHTMLString(responseHTML);\n if (fetchResponse.serverError) {\n await this.view.renderError(snapshot, this.currentVisit);\n } else {\n await this.view.renderPage(snapshot, false, true, this.currentVisit);\n }\n if (snapshot.refreshScroll !== \"preserve\") {\n this.view.scrollToTop();\n }\n this.view.clearSnapshotCache();\n }\n }\n\n formSubmissionErrored(formSubmission, error) {\n console.error(error);\n }\n\n formSubmissionFinished(formSubmission) {\n // Not all adapters implement formSubmissionFinished\n if (typeof this.adapter.formSubmissionFinished === \"function\") {\n this.adapter.formSubmissionFinished(formSubmission);\n }\n }\n\n // Link prefetching\n\n linkPrefetchingIsEnabledForLocation(location) {\n // Not all adapters implement linkPrefetchingIsEnabledForLocation\n if (typeof this.adapter.linkPrefetchingIsEnabledForLocation === \"function\") {\n return this.adapter.linkPrefetchingIsEnabledForLocation(location)\n }\n\n return true\n }\n\n // Visit delegate\n\n visitStarted(visit) {\n this.delegate.visitStarted(visit);\n }\n\n visitCompleted(visit) {\n this.delegate.visitCompleted(visit);\n delete this.currentVisit;\n }\n\n // Same-page links are no longer handled with a Visit.\n // This method is still needed for Turbo Native adapters.\n locationWithActionIsSamePage(location, action) {\n return false\n }\n\n // Visits\n\n get location() {\n return this.history.location\n }\n\n get restorationIdentifier() {\n return this.history.restorationIdentifier\n }\n\n #getActionForFormSubmission(formSubmission, fetchResponse) {\n const { submitter, formElement } = formSubmission;\n return getVisitAction(submitter, formElement) || this.#getDefaultAction(fetchResponse)\n }\n\n #getDefaultAction(fetchResponse) {\n const sameLocationRedirect = fetchResponse.redirected && fetchResponse.location.href === this.location?.href;\n return sameLocationRedirect ? \"replace\" : \"advance\"\n }\n}\n\nconst PageStage = {\n initial: 0,\n loading: 1,\n interactive: 2,\n complete: 3\n};\n\nclass PageObserver {\n stage = PageStage.initial\n started = false\n\n constructor(delegate) {\n this.delegate = delegate;\n }\n\n start() {\n if (!this.started) {\n if (this.stage == PageStage.initial) {\n this.stage = PageStage.loading;\n }\n document.addEventListener(\"readystatechange\", this.interpretReadyState, false);\n addEventListener(\"pagehide\", this.pageWillUnload, false);\n this.started = true;\n }\n }\n\n stop() {\n if (this.started) {\n document.removeEventListener(\"readystatechange\", this.interpretReadyState, false);\n removeEventListener(\"pagehide\", this.pageWillUnload, false);\n this.started = false;\n }\n }\n\n interpretReadyState = () => {\n const { readyState } = this;\n if (readyState == \"interactive\") {\n this.pageIsInteractive();\n } else if (readyState == \"complete\") {\n this.pageIsComplete();\n }\n }\n\n pageIsInteractive() {\n if (this.stage == PageStage.loading) {\n this.stage = PageStage.interactive;\n this.delegate.pageBecameInteractive();\n }\n }\n\n pageIsComplete() {\n this.pageIsInteractive();\n if (this.stage == PageStage.interactive) {\n this.stage = PageStage.complete;\n this.delegate.pageLoaded();\n }\n }\n\n pageWillUnload = () => {\n this.delegate.pageWillUnload();\n }\n\n get readyState() {\n return document.readyState\n }\n}\n\nclass ScrollObserver {\n started = false\n\n constructor(delegate) {\n this.delegate = delegate;\n }\n\n start() {\n if (!this.started) {\n addEventListener(\"scroll\", this.onScroll, false);\n this.onScroll();\n this.started = true;\n }\n }\n\n stop() {\n if (this.started) {\n removeEventListener(\"scroll\", this.onScroll, false);\n this.started = false;\n }\n }\n\n onScroll = () => {\n this.updatePosition({ x: window.pageXOffset, y: window.pageYOffset });\n }\n\n // Private\n\n updatePosition(position) {\n this.delegate.scrollPositionChanged(position);\n }\n}\n\nclass StreamMessageRenderer {\n render({ fragment }) {\n Bardo.preservingPermanentElements(this, getPermanentElementMapForFragment(fragment), () => {\n withAutofocusFromFragment(fragment, () => {\n withPreservedFocus(() => {\n document.documentElement.appendChild(fragment);\n });\n });\n });\n }\n\n // Bardo delegate\n\n enteringBardo(currentPermanentElement, newPermanentElement) {\n newPermanentElement.replaceWith(currentPermanentElement.cloneNode(true));\n }\n\n leavingBardo() {}\n}\n\nfunction getPermanentElementMapForFragment(fragment) {\n const permanentElementsInDocument = queryPermanentElementsAll(document.documentElement);\n const permanentElementMap = {};\n for (const permanentElementInDocument of permanentElementsInDocument) {\n const { id } = permanentElementInDocument;\n\n for (const streamElement of fragment.querySelectorAll(\"turbo-stream\")) {\n const elementInStream = getPermanentElementById(streamElement.templateElement.content, id);\n\n if (elementInStream) {\n permanentElementMap[id] = [permanentElementInDocument, elementInStream];\n }\n }\n }\n\n return permanentElementMap\n}\n\nasync function withAutofocusFromFragment(fragment, callback) {\n const generatedID = `turbo-stream-autofocus-${uuid()}`;\n const turboStreams = fragment.querySelectorAll(\"turbo-stream\");\n const elementWithAutofocus = firstAutofocusableElementInStreams(turboStreams);\n let willAutofocusId = null;\n\n if (elementWithAutofocus) {\n if (elementWithAutofocus.id) {\n willAutofocusId = elementWithAutofocus.id;\n } else {\n willAutofocusId = generatedID;\n }\n\n elementWithAutofocus.id = willAutofocusId;\n }\n\n callback();\n await nextRepaint();\n\n const hasNoActiveElement = document.activeElement == null || document.activeElement == document.body;\n\n if (hasNoActiveElement && willAutofocusId) {\n const elementToAutofocus = document.getElementById(willAutofocusId);\n\n if (elementIsFocusable(elementToAutofocus)) {\n elementToAutofocus.focus();\n }\n if (elementToAutofocus && elementToAutofocus.id == generatedID) {\n elementToAutofocus.removeAttribute(\"id\");\n }\n }\n}\n\nasync function withPreservedFocus(callback) {\n const [activeElementBeforeRender, activeElementAfterRender] = await around(callback, () => document.activeElement);\n\n const restoreFocusTo = activeElementBeforeRender && activeElementBeforeRender.id;\n\n if (restoreFocusTo) {\n const elementToFocus = document.getElementById(restoreFocusTo);\n\n if (elementIsFocusable(elementToFocus) && elementToFocus != activeElementAfterRender) {\n elementToFocus.focus();\n }\n }\n}\n\nfunction firstAutofocusableElementInStreams(nodeListOfStreamElements) {\n for (const streamElement of nodeListOfStreamElements) {\n const elementWithAutofocus = queryAutofocusableElement(streamElement.templateElement.content);\n\n if (elementWithAutofocus) return elementWithAutofocus\n }\n\n return null\n}\n\nclass StreamObserver {\n sources = new Set()\n #started = false\n\n constructor(delegate) {\n this.delegate = delegate;\n }\n\n start() {\n if (!this.#started) {\n this.#started = true;\n addEventListener(\"turbo:before-fetch-response\", this.inspectFetchResponse, false);\n }\n }\n\n stop() {\n if (this.#started) {\n this.#started = false;\n removeEventListener(\"turbo:before-fetch-response\", this.inspectFetchResponse, false);\n }\n }\n\n connectStreamSource(source) {\n if (!this.streamSourceIsConnected(source)) {\n this.sources.add(source);\n source.addEventListener(\"message\", this.receiveMessageEvent, false);\n }\n }\n\n disconnectStreamSource(source) {\n if (this.streamSourceIsConnected(source)) {\n this.sources.delete(source);\n source.removeEventListener(\"message\", this.receiveMessageEvent, false);\n }\n }\n\n streamSourceIsConnected(source) {\n return this.sources.has(source)\n }\n\n inspectFetchResponse = (event) => {\n const response = fetchResponseFromEvent(event);\n if (response && fetchResponseIsStream(response)) {\n event.preventDefault();\n this.receiveMessageResponse(response);\n }\n }\n\n receiveMessageEvent = (event) => {\n if (this.#started && typeof event.data == \"string\") {\n this.receiveMessageHTML(event.data);\n }\n }\n\n async receiveMessageResponse(response) {\n const html = await response.responseHTML;\n if (html) {\n this.receiveMessageHTML(html);\n }\n }\n\n receiveMessageHTML(html) {\n this.delegate.receivedMessageFromStream(StreamMessage.wrap(html));\n }\n}\n\nfunction fetchResponseFromEvent(event) {\n const fetchResponse = event.detail?.fetchResponse;\n if (fetchResponse instanceof FetchResponse) {\n return fetchResponse\n }\n}\n\nfunction fetchResponseIsStream(response) {\n const contentType = response.contentType ?? \"\";\n return contentType.startsWith(StreamMessage.contentType)\n}\n\nclass ErrorRenderer extends Renderer {\n static renderElement(currentElement, newElement) {\n const { documentElement, body } = document;\n\n documentElement.replaceChild(newElement, body);\n }\n\n async render() {\n this.replaceHeadAndBody();\n this.activateScriptElements();\n }\n\n replaceHeadAndBody() {\n const { documentElement, head } = document;\n documentElement.replaceChild(this.newHead, head);\n this.renderElement(this.currentElement, this.newElement);\n }\n\n activateScriptElements() {\n for (const replaceableElement of this.scriptElements) {\n const parentNode = replaceableElement.parentNode;\n if (parentNode) {\n const element = activateScriptElement(replaceableElement);\n parentNode.replaceChild(element, replaceableElement);\n }\n }\n }\n\n get newHead() {\n return this.newSnapshot.headSnapshot.element\n }\n\n get scriptElements() {\n return document.documentElement.querySelectorAll(\"script\")\n }\n}\n\nclass PageRenderer extends Renderer {\n static renderElement(currentElement, newElement) {\n if (document.body && newElement instanceof HTMLBodyElement) {\n document.body.replaceWith(newElement);\n } else {\n document.documentElement.appendChild(newElement);\n }\n }\n\n get shouldRender() {\n return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical\n }\n\n get reloadReason() {\n if (!this.newSnapshot.isVisitable) {\n return {\n reason: \"turbo_visit_control_is_reload\"\n }\n }\n\n if (!this.trackedElementsAreIdentical) {\n return {\n reason: \"tracked_element_mismatch\"\n }\n }\n }\n\n async prepareToRender() {\n this.#setLanguage();\n await this.mergeHead();\n }\n\n async render() {\n if (this.willRender) {\n await this.replaceBody();\n }\n }\n\n finishRendering() {\n super.finishRendering();\n if (!this.isPreview) {\n this.focusFirstAutofocusableElement();\n }\n }\n\n get currentHeadSnapshot() {\n return this.currentSnapshot.headSnapshot\n }\n\n get newHeadSnapshot() {\n return this.newSnapshot.headSnapshot\n }\n\n get newElement() {\n return this.newSnapshot.element\n }\n\n #setLanguage() {\n const { documentElement } = this.currentSnapshot;\n const { dir, lang } = this.newSnapshot;\n\n if (lang) {\n documentElement.setAttribute(\"lang\", lang);\n } else {\n documentElement.removeAttribute(\"lang\");\n }\n if (dir) {\n documentElement.setAttribute(\"dir\", dir);\n } else {\n documentElement.removeAttribute(\"dir\");\n }\n }\n\n async mergeHead() {\n const mergedHeadElements = this.mergeProvisionalElements();\n const newStylesheetElements = this.copyNewHeadStylesheetElements();\n this.copyNewHeadScriptElements();\n\n await mergedHeadElements;\n await newStylesheetElements;\n\n if (this.willRender) {\n this.removeUnusedDynamicStylesheetElements();\n }\n }\n\n async replaceBody() {\n await this.preservingPermanentElements(async () => {\n this.activateNewBody();\n await this.assignNewBody();\n });\n }\n\n get trackedElementsAreIdentical() {\n return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature\n }\n\n async copyNewHeadStylesheetElements() {\n const loadingElements = [];\n\n for (const element of this.newHeadStylesheetElements) {\n loadingElements.push(waitForLoad(element));\n\n document.head.appendChild(element);\n }\n\n await Promise.all(loadingElements);\n }\n\n copyNewHeadScriptElements() {\n for (const element of this.newHeadScriptElements) {\n document.head.appendChild(activateScriptElement(element));\n }\n }\n\n removeUnusedDynamicStylesheetElements() {\n for (const element of this.unusedDynamicStylesheetElements) {\n document.head.removeChild(element);\n }\n }\n\n async mergeProvisionalElements() {\n const newHeadElements = [...this.newHeadProvisionalElements];\n\n for (const element of this.currentHeadProvisionalElements) {\n if (!this.isCurrentElementInElementList(element, newHeadElements)) {\n document.head.removeChild(element);\n }\n }\n\n for (const element of newHeadElements) {\n document.head.appendChild(element);\n }\n }\n\n isCurrentElementInElementList(element, elementList) {\n for (const [index, newElement] of elementList.entries()) {\n // if title element...\n if (element.tagName == \"TITLE\") {\n if (newElement.tagName != \"TITLE\") {\n continue\n }\n if (element.innerHTML == newElement.innerHTML) {\n elementList.splice(index, 1);\n return true\n }\n }\n\n // if any other element...\n if (newElement.isEqualNode(element)) {\n elementList.splice(index, 1);\n return true\n }\n }\n\n return false\n }\n\n removeCurrentHeadProvisionalElements() {\n for (const element of this.currentHeadProvisionalElements) {\n document.head.removeChild(element);\n }\n }\n\n copyNewHeadProvisionalElements() {\n for (const element of this.newHeadProvisionalElements) {\n document.head.appendChild(element);\n }\n }\n\n activateNewBody() {\n document.adoptNode(this.newElement);\n this.removeNoscriptElements();\n this.activateNewBodyScriptElements();\n }\n\n removeNoscriptElements() {\n for (const noscriptElement of this.newElement.querySelectorAll(\"noscript\")) {\n noscriptElement.remove();\n }\n }\n\n activateNewBodyScriptElements() {\n for (const inertScriptElement of this.newBodyScriptElements) {\n const activatedScriptElement = activateScriptElement(inertScriptElement);\n inertScriptElement.replaceWith(activatedScriptElement);\n }\n }\n\n async assignNewBody() {\n await this.renderElement(this.currentElement, this.newElement);\n }\n\n get unusedDynamicStylesheetElements() {\n return this.oldHeadStylesheetElements.filter((element) => {\n return element.getAttribute(\"data-turbo-track\") === \"dynamic\"\n })\n }\n\n get oldHeadStylesheetElements() {\n return this.currentHeadSnapshot.getStylesheetElementsNotInSnapshot(this.newHeadSnapshot)\n }\n\n get newHeadStylesheetElements() {\n return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot)\n }\n\n get newHeadScriptElements() {\n return this.newHeadSnapshot.getScriptElementsNotInSnapshot(this.currentHeadSnapshot)\n }\n\n get currentHeadProvisionalElements() {\n return this.currentHeadSnapshot.provisionalElements\n }\n\n get newHeadProvisionalElements() {\n return this.newHeadSnapshot.provisionalElements\n }\n\n get newBodyScriptElements() {\n return this.newElement.querySelectorAll(\"script\")\n }\n}\n\nclass MorphingPageRenderer extends PageRenderer {\n static renderElement(currentElement, newElement) {\n morphElements(currentElement, newElement, {\n callbacks: {\n beforeNodeMorphed: (node, newNode) => {\n if (\n shouldRefreshFrameWithMorphing(node, newNode) &&\n !closestFrameReloadableWithMorphing(node)\n ) {\n node.reload();\n return false\n }\n return true\n }\n }\n });\n\n dispatch(\"turbo:morph\", { detail: { currentElement, newElement } });\n }\n\n async preservingPermanentElements(callback) {\n return await callback()\n }\n\n get renderMethod() {\n return \"morph\"\n }\n\n get shouldAutofocus() {\n return false\n }\n}\n\nclass SnapshotCache extends LRUCache {\n constructor(size) {\n super(size, toCacheKey);\n }\n\n get snapshots() {\n return this.entries\n }\n}\n\nclass PageView extends View {\n snapshotCache = new SnapshotCache(10)\n lastRenderedLocation = new URL(location.href)\n forceReloaded = false\n\n shouldTransitionTo(newSnapshot) {\n return this.snapshot.prefersViewTransitions && newSnapshot.prefersViewTransitions\n }\n\n renderPage(snapshot, isPreview = false, willRender = true, visit) {\n const shouldMorphPage = this.isPageRefresh(visit) && (visit?.refresh?.method || this.snapshot.refreshMethod) === \"morph\";\n const rendererClass = shouldMorphPage ? MorphingPageRenderer : PageRenderer;\n\n const renderer = new rendererClass(this.snapshot, snapshot, isPreview, willRender);\n\n if (!renderer.shouldRender) {\n this.forceReloaded = true;\n } else {\n visit?.changeHistory();\n }\n\n return this.render(renderer)\n }\n\n renderError(snapshot, visit) {\n visit?.changeHistory();\n const renderer = new ErrorRenderer(this.snapshot, snapshot, false);\n return this.render(renderer)\n }\n\n clearSnapshotCache() {\n this.snapshotCache.clear();\n }\n\n async cacheSnapshot(snapshot = this.snapshot) {\n if (snapshot.isCacheable) {\n this.delegate.viewWillCacheSnapshot();\n const { lastRenderedLocation: location } = this;\n await nextEventLoopTick();\n const cachedSnapshot = snapshot.clone();\n this.snapshotCache.put(location, cachedSnapshot);\n return cachedSnapshot\n }\n }\n\n getCachedSnapshotForLocation(location) {\n return this.snapshotCache.get(location)\n }\n\n isPageRefresh(visit) {\n return !visit || (this.lastRenderedLocation.pathname === visit.location.pathname && visit.action === \"replace\")\n }\n\n shouldPreserveScrollPosition(visit) {\n return this.isPageRefresh(visit) && (visit?.refresh?.scroll || this.snapshot.refreshScroll) === \"preserve\"\n }\n\n get snapshot() {\n return PageSnapshot.fromElement(this.element)\n }\n}\n\nclass Preloader {\n selector = \"a[data-turbo-preload]\"\n\n constructor(delegate, snapshotCache) {\n this.delegate = delegate;\n this.snapshotCache = snapshotCache;\n }\n\n start() {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", this.#preloadAll);\n } else {\n this.preloadOnLoadLinksForView(document.body);\n }\n }\n\n stop() {\n document.removeEventListener(\"DOMContentLoaded\", this.#preloadAll);\n }\n\n preloadOnLoadLinksForView(element) {\n for (const link of element.querySelectorAll(this.selector)) {\n if (this.delegate.shouldPreloadLink(link)) {\n this.preloadURL(link);\n }\n }\n }\n\n async preloadURL(link) {\n const location = new URL(link.href);\n\n if (this.snapshotCache.has(location)) {\n return\n }\n\n const fetchRequest = new FetchRequest(this, FetchMethod.get, location, new URLSearchParams(), link);\n await fetchRequest.perform();\n }\n\n // Fetch request delegate\n\n prepareRequest(fetchRequest) {\n fetchRequest.headers[\"X-Sec-Purpose\"] = \"prefetch\";\n }\n\n async requestSucceededWithResponse(fetchRequest, fetchResponse) {\n try {\n const responseHTML = await fetchResponse.responseHTML;\n const snapshot = PageSnapshot.fromHTMLString(responseHTML);\n\n this.snapshotCache.put(fetchRequest.url, snapshot);\n } catch (_) {\n // If we cannot preload that is ok!\n }\n }\n\n requestStarted(fetchRequest) {}\n\n requestErrored(fetchRequest) {}\n\n requestFinished(fetchRequest) {}\n\n requestPreventedHandlingResponse(fetchRequest, fetchResponse) {}\n\n requestFailedWithResponse(fetchRequest, fetchResponse) {}\n\n #preloadAll = () => {\n this.preloadOnLoadLinksForView(document.body);\n }\n}\n\nclass Cache {\n constructor(session) {\n this.session = session;\n }\n\n clear() {\n this.session.clearCache();\n }\n\n resetCacheControl() {\n this.#setCacheControl(\"\");\n }\n\n exemptPageFromCache() {\n this.#setCacheControl(\"no-cache\");\n }\n\n exemptPageFromPreview() {\n this.#setCacheControl(\"no-preview\");\n }\n\n #setCacheControl(value) {\n setMetaContent(\"turbo-cache-control\", value);\n }\n}\n\nclass Session {\n navigator = new Navigator(this)\n history = new History(this)\n view = new PageView(this, document.documentElement)\n adapter = new BrowserAdapter(this)\n\n pageObserver = new PageObserver(this)\n cacheObserver = new CacheObserver()\n linkPrefetchObserver = new LinkPrefetchObserver(this, document)\n linkClickObserver = new LinkClickObserver(this, window)\n formSubmitObserver = new FormSubmitObserver(this, document)\n scrollObserver = new ScrollObserver(this)\n streamObserver = new StreamObserver(this)\n formLinkClickObserver = new FormLinkClickObserver(this, document.documentElement)\n frameRedirector = new FrameRedirector(this, document.documentElement)\n streamMessageRenderer = new StreamMessageRenderer()\n cache = new Cache(this)\n\n enabled = true\n started = false\n #pageRefreshDebouncePeriod = 150\n\n constructor(recentRequests) {\n this.recentRequests = recentRequests;\n this.preloader = new Preloader(this, this.view.snapshotCache);\n this.debouncedRefresh = this.refresh;\n this.pageRefreshDebouncePeriod = this.pageRefreshDebouncePeriod;\n }\n\n start() {\n if (!this.started) {\n this.pageObserver.start();\n this.cacheObserver.start();\n this.linkPrefetchObserver.start();\n this.formLinkClickObserver.start();\n this.linkClickObserver.start();\n this.formSubmitObserver.start();\n this.scrollObserver.start();\n this.streamObserver.start();\n this.frameRedirector.start();\n this.history.start();\n this.preloader.start();\n this.started = true;\n this.enabled = true;\n }\n }\n\n disable() {\n this.enabled = false;\n }\n\n stop() {\n if (this.started) {\n this.pageObserver.stop();\n this.cacheObserver.stop();\n this.linkPrefetchObserver.stop();\n this.formLinkClickObserver.stop();\n this.linkClickObserver.stop();\n this.formSubmitObserver.stop();\n this.scrollObserver.stop();\n this.streamObserver.stop();\n this.frameRedirector.stop();\n this.history.stop();\n this.preloader.stop();\n this.started = false;\n }\n }\n\n registerAdapter(adapter) {\n this.adapter = adapter;\n }\n\n visit(location, options = {}) {\n const frameElement = options.frame ? document.getElementById(options.frame) : null;\n\n if (frameElement instanceof FrameElement) {\n const action = options.action || getVisitAction(frameElement);\n\n frameElement.delegate.proposeVisitIfNavigatedWithAction(frameElement, action);\n frameElement.src = location.toString();\n } else {\n this.navigator.proposeVisit(expandURL(location), options);\n }\n }\n\n refresh(url, options = {}) {\n options = typeof options === \"string\" ? { requestId: options } : options;\n\n const { method, requestId, scroll } = options;\n const isRecentRequest = requestId && this.recentRequests.has(requestId);\n const isCurrentUrl = url === document.baseURI;\n if (!isRecentRequest && !this.navigator.currentVisit && isCurrentUrl) {\n this.visit(url, { action: \"replace\", shouldCacheSnapshot: false, refresh: { method, scroll } });\n }\n }\n\n connectStreamSource(source) {\n this.streamObserver.connectStreamSource(source);\n }\n\n disconnectStreamSource(source) {\n this.streamObserver.disconnectStreamSource(source);\n }\n\n renderStreamMessage(message) {\n this.streamMessageRenderer.render(StreamMessage.wrap(message));\n }\n\n clearCache() {\n this.view.clearSnapshotCache();\n }\n\n setProgressBarDelay(delay) {\n console.warn(\n \"Please replace `session.setProgressBarDelay(delay)` with `session.progressBarDelay = delay`. The function is deprecated and will be removed in a future version of Turbo.`\"\n );\n\n this.progressBarDelay = delay;\n }\n\n set progressBarDelay(delay) {\n config.drive.progressBarDelay = delay;\n }\n\n get progressBarDelay() {\n return config.drive.progressBarDelay\n }\n\n set drive(value) {\n config.drive.enabled = value;\n }\n\n get drive() {\n return config.drive.enabled\n }\n\n set formMode(value) {\n config.forms.mode = value;\n }\n\n get formMode() {\n return config.forms.mode\n }\n\n get location() {\n return this.history.location\n }\n\n get restorationIdentifier() {\n return this.history.restorationIdentifier\n }\n\n get pageRefreshDebouncePeriod() {\n return this.#pageRefreshDebouncePeriod\n }\n\n set pageRefreshDebouncePeriod(value) {\n this.refresh = debounce(this.debouncedRefresh.bind(this), value);\n this.#pageRefreshDebouncePeriod = value;\n }\n\n // Preloader delegate\n\n shouldPreloadLink(element) {\n const isUnsafe = element.hasAttribute(\"data-turbo-method\");\n const isStream = element.hasAttribute(\"data-turbo-stream\");\n const frameTarget = element.getAttribute(\"data-turbo-frame\");\n const frame = frameTarget == \"_top\" ?\n null :\n document.getElementById(frameTarget) || findClosestRecursively(element, \"turbo-frame:not([disabled])\");\n\n if (isUnsafe || isStream || frame instanceof FrameElement) {\n return false\n } else {\n const location = new URL(element.href);\n\n return this.elementIsNavigatable(element) && locationIsVisitable(location, this.snapshot.rootLocation)\n }\n }\n\n // History delegate\n\n historyPoppedToLocationWithRestorationIdentifierAndDirection(location, restorationIdentifier, direction) {\n if (this.enabled) {\n this.navigator.startVisit(location, restorationIdentifier, {\n action: \"restore\",\n historyChanged: true,\n direction\n });\n } else {\n this.adapter.pageInvalidated({\n reason: \"turbo_disabled\"\n });\n }\n }\n\n historyPoppedWithEmptyState(location) {\n this.history.replace(location);\n this.view.lastRenderedLocation = location;\n this.view.cacheSnapshot();\n }\n\n // Scroll observer delegate\n\n scrollPositionChanged(position) {\n this.history.updateRestorationData({ scrollPosition: position });\n }\n\n // Form click observer delegate\n\n willSubmitFormLinkToLocation(link, location) {\n return this.elementIsNavigatable(link) && locationIsVisitable(location, this.snapshot.rootLocation)\n }\n\n submittedFormLinkToLocation() {}\n\n // Link hover observer delegate\n\n canPrefetchRequestToLocation(link, location) {\n return (\n this.elementIsNavigatable(link) &&\n locationIsVisitable(location, this.snapshot.rootLocation) &&\n this.navigator.linkPrefetchingIsEnabledForLocation(location)\n )\n }\n\n // Link click observer delegate\n\n willFollowLinkToLocation(link, location, event) {\n return (\n this.elementIsNavigatable(link) &&\n locationIsVisitable(location, this.snapshot.rootLocation) &&\n this.applicationAllowsFollowingLinkToLocation(link, location, event)\n )\n }\n\n followedLinkToLocation(link, location) {\n const action = this.getActionForLink(link);\n const acceptsStreamResponse = link.hasAttribute(\"data-turbo-stream\");\n\n this.visit(location.href, { action, acceptsStreamResponse });\n }\n\n // Navigator delegate\n\n allowsVisitingLocationWithAction(location, action) {\n return this.applicationAllowsVisitingLocation(location)\n }\n\n visitProposedToLocation(location, options) {\n extendURLWithDeprecatedProperties(location);\n this.adapter.visitProposedToLocation(location, options);\n }\n\n // Visit delegate\n\n visitStarted(visit) {\n if (!visit.acceptsStreamResponse) {\n markAsBusy(document.documentElement);\n this.view.markVisitDirection(visit.direction);\n }\n extendURLWithDeprecatedProperties(visit.location);\n this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);\n }\n\n visitCompleted(visit) {\n this.view.unmarkVisitDirection();\n clearBusyState(document.documentElement);\n this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());\n }\n\n // Form submit observer delegate\n\n willSubmitForm(form, submitter) {\n const action = getAction$1(form, submitter);\n\n return (\n this.submissionIsNavigatable(form, submitter) &&\n locationIsVisitable(expandURL(action), this.snapshot.rootLocation)\n )\n }\n\n formSubmitted(form, submitter) {\n this.navigator.submitForm(form, submitter);\n }\n\n // Page observer delegate\n\n pageBecameInteractive() {\n this.view.lastRenderedLocation = this.location;\n this.notifyApplicationAfterPageLoad();\n }\n\n pageLoaded() {\n this.history.assumeControlOfScrollRestoration();\n }\n\n pageWillUnload() {\n this.history.relinquishControlOfScrollRestoration();\n }\n\n // Stream observer delegate\n\n receivedMessageFromStream(message) {\n this.renderStreamMessage(message);\n }\n\n // Page view delegate\n\n viewWillCacheSnapshot() {\n this.notifyApplicationBeforeCachingSnapshot();\n }\n\n allowsImmediateRender({ element }, options) {\n const event = this.notifyApplicationBeforeRender(element, options);\n const {\n defaultPrevented,\n detail: { render }\n } = event;\n\n if (this.view.renderer && render) {\n this.view.renderer.renderElement = render;\n }\n\n return !defaultPrevented\n }\n\n viewRenderedSnapshot(_snapshot, _isPreview, renderMethod) {\n this.view.lastRenderedLocation = this.history.location;\n this.notifyApplicationAfterRender(renderMethod);\n }\n\n preloadOnLoadLinksForView(element) {\n this.preloader.preloadOnLoadLinksForView(element);\n }\n\n viewInvalidated(reason) {\n this.adapter.pageInvalidated(reason);\n }\n\n // Frame element\n\n frameLoaded(frame) {\n this.notifyApplicationAfterFrameLoad(frame);\n }\n\n frameRendered(fetchResponse, frame) {\n this.notifyApplicationAfterFrameRender(fetchResponse, frame);\n }\n\n // Application events\n\n applicationAllowsFollowingLinkToLocation(link, location, ev) {\n const event = this.notifyApplicationAfterClickingLinkToLocation(link, location, ev);\n return !event.defaultPrevented\n }\n\n applicationAllowsVisitingLocation(location) {\n const event = this.notifyApplicationBeforeVisitingLocation(location);\n return !event.defaultPrevented\n }\n\n notifyApplicationAfterClickingLinkToLocation(link, location, event) {\n return dispatch(\"turbo:click\", {\n target: link,\n detail: { url: location.href, originalEvent: event },\n cancelable: true\n })\n }\n\n notifyApplicationBeforeVisitingLocation(location) {\n return dispatch(\"turbo:before-visit\", {\n detail: { url: location.href },\n cancelable: true\n })\n }\n\n notifyApplicationAfterVisitingLocation(location, action) {\n return dispatch(\"turbo:visit\", { detail: { url: location.href, action } })\n }\n\n notifyApplicationBeforeCachingSnapshot() {\n return dispatch(\"turbo:before-cache\")\n }\n\n notifyApplicationBeforeRender(newBody, options) {\n return dispatch(\"turbo:before-render\", {\n detail: { newBody, ...options },\n cancelable: true\n })\n }\n\n notifyApplicationAfterRender(renderMethod) {\n return dispatch(\"turbo:render\", { detail: { renderMethod } })\n }\n\n notifyApplicationAfterPageLoad(timing = {}) {\n return dispatch(\"turbo:load\", {\n detail: { url: this.location.href, timing }\n })\n }\n\n notifyApplicationAfterFrameLoad(frame) {\n return dispatch(\"turbo:frame-load\", { target: frame })\n }\n\n notifyApplicationAfterFrameRender(fetchResponse, frame) {\n return dispatch(\"turbo:frame-render\", {\n detail: { fetchResponse },\n target: frame,\n cancelable: true\n })\n }\n\n // Helpers\n\n submissionIsNavigatable(form, submitter) {\n if (config.forms.mode == \"off\") {\n return false\n } else {\n const submitterIsNavigatable = submitter ? this.elementIsNavigatable(submitter) : true;\n\n if (config.forms.mode == \"optin\") {\n return submitterIsNavigatable && form.closest('[data-turbo=\"true\"]') != null\n } else {\n return submitterIsNavigatable && this.elementIsNavigatable(form)\n }\n }\n }\n\n elementIsNavigatable(element) {\n const container = findClosestRecursively(element, \"[data-turbo]\");\n const withinFrame = findClosestRecursively(element, \"turbo-frame\");\n\n // Check if Drive is enabled on the session or we're within a Frame.\n if (config.drive.enabled || withinFrame) {\n // Element is navigatable by default, unless `data-turbo=\"false\"`.\n if (container) {\n return container.getAttribute(\"data-turbo\") != \"false\"\n } else {\n return true\n }\n } else {\n // Element isn't navigatable by default, unless `data-turbo=\"true\"`.\n if (container) {\n return container.getAttribute(\"data-turbo\") == \"true\"\n } else {\n return false\n }\n }\n }\n\n // Private\n\n getActionForLink(link) {\n return getVisitAction(link) || \"advance\"\n }\n\n get snapshot() {\n return this.view.snapshot\n }\n}\n\n// Older versions of the Turbo Native adapters referenced the\n// `Location#absoluteURL` property in their implementations of\n// the `Adapter#visitProposedToLocation()` and `#visitStarted()`\n// methods. The Location class has since been removed in favor\n// of the DOM URL API, and accordingly all Adapter methods now\n// receive URL objects.\n//\n// We alias #absoluteURL to #toString() here to avoid crashing\n// older adapters which do not expect URL objects. We should\n// consider removing this support at some point in the future.\n\nfunction extendURLWithDeprecatedProperties(url) {\n Object.defineProperties(url, deprecatedLocationPropertyDescriptors);\n}\n\nconst deprecatedLocationPropertyDescriptors = {\n absoluteURL: {\n get() {\n return this.toString()\n }\n }\n};\n\nconst session = new Session(recentRequests);\nconst { cache, navigator } = session;\n\n/**\n * Starts the main session.\n * This initialises any necessary observers such as those to monitor\n * link interactions.\n */\nfunction start() {\n session.start();\n}\n\n/**\n * Registers an adapter for the main session.\n *\n * @param adapter Adapter to register\n */\nfunction registerAdapter(adapter) {\n session.registerAdapter(adapter);\n}\n\n/**\n * Performs an application visit to the given location.\n *\n * @param location Location to visit (a URL or path)\n * @param options Options to apply\n * @param options.action Type of history navigation to apply (\"restore\",\n * \"replace\" or \"advance\")\n * @param options.historyChanged Specifies whether the browser history has\n * already been changed for this visit or not\n * @param options.referrer Specifies the referrer of this visit such that\n * navigations to the same page will not result in a new history entry.\n * @param options.snapshotHTML Cached snapshot to render\n * @param options.response Response of the specified location\n */\nfunction visit(location, options) {\n session.visit(location, options);\n}\n\n/**\n * Connects a stream source to the main session.\n *\n * @param source Stream source to connect\n */\nfunction connectStreamSource(source) {\n session.connectStreamSource(source);\n}\n\n/**\n * Disconnects a stream source from the main session.\n *\n * @param source Stream source to disconnect\n */\nfunction disconnectStreamSource(source) {\n session.disconnectStreamSource(source);\n}\n\n/**\n * Renders a stream message to the main session by appending it to the\n * current document.\n *\n * @param message Message to render\n */\nfunction renderStreamMessage(message) {\n session.renderStreamMessage(message);\n}\n\n/**\n * Sets the delay after which the progress bar will appear during navigation.\n *\n * The progress bar appears after 500ms by default.\n *\n * Note that this method has no effect when used with the iOS or Android\n * adapters.\n *\n * @param delay Time to delay in milliseconds\n */\nfunction setProgressBarDelay(delay) {\n console.warn(\n \"Please replace `Turbo.setProgressBarDelay(delay)` with `Turbo.config.drive.progressBarDelay = delay`. The top-level function is deprecated and will be removed in a future version of Turbo.`\"\n );\n config.drive.progressBarDelay = delay;\n}\n\nfunction setConfirmMethod(confirmMethod) {\n console.warn(\n \"Please replace `Turbo.setConfirmMethod(confirmMethod)` with `Turbo.config.forms.confirm = confirmMethod`. The top-level function is deprecated and will be removed in a future version of Turbo.`\"\n );\n config.forms.confirm = confirmMethod;\n}\n\nfunction setFormMode(mode) {\n console.warn(\n \"Please replace `Turbo.setFormMode(mode)` with `Turbo.config.forms.mode = mode`. The top-level function is deprecated and will be removed in a future version of Turbo.`\"\n );\n config.forms.mode = mode;\n}\n\n/**\n * Morph the state of the currentBody based on the attributes and contents of\n * the newBody. Morphing body elements may dispatch turbo:morph,\n * turbo:before-morph-element, turbo:before-morph-attribute, and\n * turbo:morph-element events.\n *\n * @param currentBody HTMLBodyElement destination of morphing changes\n * @param newBody HTMLBodyElement source of morphing changes\n */\nfunction morphBodyElements(currentBody, newBody) {\n MorphingPageRenderer.renderElement(currentBody, newBody);\n}\n\n/**\n * Morph the child elements of the currentFrame based on the child elements of\n * the newFrame. Morphing turbo-frame elements may dispatch turbo:before-frame-morph,\n * turbo:before-morph-element, turbo:before-morph-attribute, and\n * turbo:morph-element events.\n *\n * @param currentFrame FrameElement destination of morphing children changes\n * @param newFrame FrameElement source of morphing children changes\n */\nfunction morphTurboFrameElements(currentFrame, newFrame) {\n MorphingFrameRenderer.renderElement(currentFrame, newFrame);\n}\n\nvar Turbo = /*#__PURE__*/Object.freeze({\n __proto__: null,\n navigator: navigator,\n session: session,\n cache: cache,\n PageRenderer: PageRenderer,\n PageSnapshot: PageSnapshot,\n FrameRenderer: FrameRenderer,\n fetch: fetchWithTurboHeaders,\n config: config,\n start: start,\n registerAdapter: registerAdapter,\n visit: visit,\n connectStreamSource: connectStreamSource,\n disconnectStreamSource: disconnectStreamSource,\n renderStreamMessage: renderStreamMessage,\n setProgressBarDelay: setProgressBarDelay,\n setConfirmMethod: setConfirmMethod,\n setFormMode: setFormMode,\n morphBodyElements: morphBodyElements,\n morphTurboFrameElements: morphTurboFrameElements,\n morphChildren: morphChildren,\n morphElements: morphElements\n});\n\nclass TurboFrameMissingError extends Error {}\n\nclass FrameController {\n fetchResponseLoaded = (_fetchResponse) => Promise.resolve()\n #currentFetchRequest = null\n #resolveVisitPromise = () => {}\n #connected = false\n #hasBeenLoaded = false\n #ignoredAttributes = new Set()\n #shouldMorphFrame = false\n action = null\n\n constructor(element) {\n this.element = element;\n this.view = new FrameView(this, this.element);\n this.appearanceObserver = new AppearanceObserver(this, this.element);\n this.formLinkClickObserver = new FormLinkClickObserver(this, this.element);\n this.linkInterceptor = new LinkInterceptor(this, this.element);\n this.restorationIdentifier = uuid();\n this.formSubmitObserver = new FormSubmitObserver(this, this.element);\n }\n\n // Frame delegate\n\n connect() {\n if (!this.#connected) {\n this.#connected = true;\n if (this.loadingStyle == FrameLoadingStyle.lazy) {\n this.appearanceObserver.start();\n } else {\n this.#loadSourceURL();\n }\n this.formLinkClickObserver.start();\n this.linkInterceptor.start();\n this.formSubmitObserver.start();\n }\n }\n\n disconnect() {\n if (this.#connected) {\n this.#connected = false;\n this.appearanceObserver.stop();\n this.formLinkClickObserver.stop();\n this.linkInterceptor.stop();\n this.formSubmitObserver.stop();\n\n if (!this.element.hasAttribute(\"recurse\")) {\n this.#currentFetchRequest?.cancel();\n }\n }\n }\n\n disabledChanged() {\n if (this.disabled) {\n this.#currentFetchRequest?.cancel();\n } else if (this.loadingStyle == FrameLoadingStyle.eager) {\n this.#loadSourceURL();\n }\n }\n\n sourceURLChanged() {\n if (this.#isIgnoringChangesTo(\"src\")) return\n\n if (!this.sourceURL) {\n this.#currentFetchRequest?.cancel();\n }\n\n if (this.element.isConnected) {\n this.complete = false;\n }\n\n if (this.loadingStyle == FrameLoadingStyle.eager || this.#hasBeenLoaded) {\n this.#loadSourceURL();\n }\n }\n\n sourceURLReloaded() {\n const { refresh, src } = this.element;\n\n this.#shouldMorphFrame = src && refresh === \"morph\";\n\n this.element.removeAttribute(\"complete\");\n this.element.src = null;\n this.element.src = src;\n return this.element.loaded\n }\n\n loadingStyleChanged() {\n if (this.loadingStyle == FrameLoadingStyle.lazy) {\n this.appearanceObserver.start();\n } else {\n this.appearanceObserver.stop();\n this.#loadSourceURL();\n }\n }\n\n async #loadSourceURL() {\n if (this.enabled && this.isActive && !this.complete && this.sourceURL) {\n this.element.loaded = this.#visit(expandURL(this.sourceURL));\n this.appearanceObserver.stop();\n await this.element.loaded;\n this.#hasBeenLoaded = true;\n }\n }\n\n async loadResponse(fetchResponse) {\n if (fetchResponse.redirected || (fetchResponse.succeeded && fetchResponse.isHTML)) {\n this.sourceURL = fetchResponse.response.url;\n }\n\n try {\n const html = await fetchResponse.responseHTML;\n if (html) {\n const document = parseHTMLDocument(html);\n const pageSnapshot = PageSnapshot.fromDocument(document);\n\n if (pageSnapshot.isVisitable) {\n await this.#loadFrameResponse(fetchResponse, document);\n } else {\n await this.#handleUnvisitableFrameResponse(fetchResponse);\n }\n }\n } finally {\n this.#shouldMorphFrame = false;\n this.fetchResponseLoaded = () => Promise.resolve();\n }\n }\n\n // Appearance observer delegate\n\n elementAppearedInViewport(element) {\n this.proposeVisitIfNavigatedWithAction(element, getVisitAction(element));\n this.#loadSourceURL();\n }\n\n // Form link click observer delegate\n\n willSubmitFormLinkToLocation(link) {\n return this.#shouldInterceptNavigation(link)\n }\n\n submittedFormLinkToLocation(link, _location, form) {\n const frame = this.#findFrameElement(link);\n if (frame) form.setAttribute(\"data-turbo-frame\", frame.id);\n }\n\n // Link interceptor delegate\n\n shouldInterceptLinkClick(element, _location, _event) {\n return this.#shouldInterceptNavigation(element)\n }\n\n linkClickIntercepted(element, location) {\n this.#navigateFrame(element, location);\n }\n\n // Form submit observer delegate\n\n willSubmitForm(element, submitter) {\n return element.closest(\"turbo-frame\") == this.element && this.#shouldInterceptNavigation(element, submitter)\n }\n\n formSubmitted(element, submitter) {\n if (this.formSubmission) {\n this.formSubmission.stop();\n }\n\n this.formSubmission = new FormSubmission(this, element, submitter);\n\n const { fetchRequest } = this.formSubmission;\n const frame = this.#findFrameElement(element, submitter);\n\n this.prepareRequest(fetchRequest, frame);\n this.formSubmission.start();\n }\n\n // Fetch request delegate\n\n prepareRequest(request, frame = this) {\n request.headers[\"Turbo-Frame\"] = frame.id;\n\n if (this.currentNavigationElement?.hasAttribute(\"data-turbo-stream\")) {\n request.acceptResponseType(StreamMessage.contentType);\n }\n }\n\n requestStarted(_request) {\n markAsBusy(this.element);\n }\n\n requestPreventedHandlingResponse(_request, _response) {\n this.#resolveVisitPromise();\n }\n\n async requestSucceededWithResponse(request, response) {\n await this.loadResponse(response);\n this.#resolveVisitPromise();\n }\n\n async requestFailedWithResponse(request, response) {\n await this.loadResponse(response);\n this.#resolveVisitPromise();\n }\n\n requestErrored(request, error) {\n console.error(error);\n this.#resolveVisitPromise();\n }\n\n requestFinished(_request) {\n clearBusyState(this.element);\n }\n\n // Form submission delegate\n\n formSubmissionStarted({ formElement }) {\n markAsBusy(formElement, this.#findFrameElement(formElement));\n }\n\n formSubmissionSucceededWithResponse(formSubmission, response) {\n const frame = this.#findFrameElement(formSubmission.formElement, formSubmission.submitter);\n\n frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(formSubmission.submitter, formSubmission.formElement, frame));\n frame.delegate.loadResponse(response);\n\n if (!formSubmission.isSafe) {\n session.clearCache();\n }\n }\n\n formSubmissionFailedWithResponse(formSubmission, fetchResponse) {\n this.element.delegate.loadResponse(fetchResponse);\n session.clearCache();\n }\n\n formSubmissionErrored(formSubmission, error) {\n console.error(error);\n }\n\n formSubmissionFinished({ formElement }) {\n clearBusyState(formElement, this.#findFrameElement(formElement));\n }\n\n // View delegate\n\n allowsImmediateRender({ element: newFrame }, options) {\n const event = dispatch(\"turbo:before-frame-render\", {\n target: this.element,\n detail: { newFrame, ...options },\n cancelable: true\n });\n\n const {\n defaultPrevented,\n detail: { render }\n } = event;\n\n if (this.view.renderer && render) {\n this.view.renderer.renderElement = render;\n }\n\n return !defaultPrevented\n }\n\n viewRenderedSnapshot(_snapshot, _isPreview, _renderMethod) {}\n\n preloadOnLoadLinksForView(element) {\n session.preloadOnLoadLinksForView(element);\n }\n\n viewInvalidated() {}\n\n // Frame renderer delegate\n\n willRenderFrame(currentElement, _newElement) {\n this.previousFrameElement = currentElement.cloneNode(true);\n }\n\n visitCachedSnapshot = ({ element }) => {\n const frame = element.querySelector(\"#\" + this.element.id);\n\n if (frame && this.previousFrameElement) {\n frame.replaceChildren(...this.previousFrameElement.children);\n }\n\n delete this.previousFrameElement;\n }\n\n // Private\n\n async #loadFrameResponse(fetchResponse, document) {\n const newFrameElement = await this.extractForeignFrameElement(document.body);\n const rendererClass = this.#shouldMorphFrame ? MorphingFrameRenderer : FrameRenderer;\n\n if (newFrameElement) {\n const snapshot = new Snapshot(newFrameElement);\n const renderer = new rendererClass(this, this.view.snapshot, snapshot, false, false);\n if (this.view.renderPromise) await this.view.renderPromise;\n this.changeHistory();\n\n await this.view.render(renderer);\n this.complete = true;\n session.frameRendered(fetchResponse, this.element);\n session.frameLoaded(this.element);\n await this.fetchResponseLoaded(fetchResponse);\n } else if (this.#willHandleFrameMissingFromResponse(fetchResponse)) {\n this.#handleFrameMissingFromResponse(fetchResponse);\n }\n }\n\n async #visit(url) {\n const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams(), this.element);\n\n this.#currentFetchRequest?.cancel();\n this.#currentFetchRequest = request;\n\n return new Promise((resolve) => {\n this.#resolveVisitPromise = () => {\n this.#resolveVisitPromise = () => {};\n this.#currentFetchRequest = null;\n resolve();\n };\n request.perform();\n })\n }\n\n #navigateFrame(element, url, submitter) {\n const frame = this.#findFrameElement(element, submitter);\n\n frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(submitter, element, frame));\n\n this.#withCurrentNavigationElement(element, () => {\n frame.src = url;\n });\n }\n\n proposeVisitIfNavigatedWithAction(frame, action = null) {\n this.action = action;\n\n if (this.action) {\n const pageSnapshot = PageSnapshot.fromElement(frame).clone();\n const { visitCachedSnapshot } = frame.delegate;\n\n frame.delegate.fetchResponseLoaded = async (fetchResponse) => {\n if (frame.src) {\n const { statusCode, redirected } = fetchResponse;\n const responseHTML = await fetchResponse.responseHTML;\n const response = { statusCode, redirected, responseHTML };\n const options = {\n response,\n visitCachedSnapshot,\n willRender: false,\n updateHistory: false,\n restorationIdentifier: this.restorationIdentifier,\n snapshot: pageSnapshot\n };\n\n if (this.action) options.action = this.action;\n\n session.visit(frame.src, options);\n }\n };\n }\n }\n\n changeHistory() {\n if (this.action) {\n const method = getHistoryMethodForAction(this.action);\n session.history.update(method, expandURL(this.element.src || \"\"), this.restorationIdentifier);\n }\n }\n\n async #handleUnvisitableFrameResponse(fetchResponse) {\n console.warn(\n `The response (${fetchResponse.statusCode}) from is performing a full page visit due to turbo-visit-control.`\n );\n\n await this.#visitResponse(fetchResponse.response);\n }\n\n #willHandleFrameMissingFromResponse(fetchResponse) {\n this.element.setAttribute(\"complete\", \"\");\n\n const response = fetchResponse.response;\n const visit = async (url, options) => {\n if (url instanceof Response) {\n this.#visitResponse(url);\n } else {\n session.visit(url, options);\n }\n };\n\n const event = dispatch(\"turbo:frame-missing\", {\n target: this.element,\n detail: { response, visit },\n cancelable: true\n });\n\n return !event.defaultPrevented\n }\n\n #handleFrameMissingFromResponse(fetchResponse) {\n this.view.missing();\n this.#throwFrameMissingError(fetchResponse);\n }\n\n #throwFrameMissingError(fetchResponse) {\n const message = `The response (${fetchResponse.statusCode}) did not contain the expected and will be ignored. To perform a full page visit instead, set turbo-visit-control to reload.`;\n throw new TurboFrameMissingError(message)\n }\n\n async #visitResponse(response) {\n const wrapped = new FetchResponse(response);\n const responseHTML = await wrapped.responseHTML;\n const { location, redirected, statusCode } = wrapped;\n\n return session.visit(location, { response: { redirected, statusCode, responseHTML } })\n }\n\n #findFrameElement(element, submitter) {\n const id = getAttribute(\"data-turbo-frame\", submitter, element) || this.element.getAttribute(\"target\");\n const target = this.#getFrameElementById(id);\n\n return target instanceof FrameElement ? target : this.element\n }\n\n async extractForeignFrameElement(container) {\n let element;\n const id = CSS.escape(this.id);\n\n try {\n element = activateElement(container.querySelector(`turbo-frame#${id}`), this.sourceURL);\n if (element) {\n return element\n }\n\n element = activateElement(container.querySelector(`turbo-frame[src][recurse~=${id}]`), this.sourceURL);\n if (element) {\n await element.loaded;\n return await this.extractForeignFrameElement(element)\n }\n } catch (error) {\n console.error(error);\n return new FrameElement()\n }\n\n return null\n }\n\n #formActionIsVisitable(form, submitter) {\n const action = getAction$1(form, submitter);\n\n return locationIsVisitable(expandURL(action), this.rootLocation)\n }\n\n #shouldInterceptNavigation(element, submitter) {\n const id = getAttribute(\"data-turbo-frame\", submitter, element) || this.element.getAttribute(\"target\");\n\n if (element instanceof HTMLFormElement && !this.#formActionIsVisitable(element, submitter)) {\n return false\n }\n\n if (!this.enabled || id == \"_top\") {\n return false\n }\n\n if (id) {\n const frameElement = this.#getFrameElementById(id);\n if (frameElement) {\n return !frameElement.disabled\n } else if (id == \"_parent\") {\n return false\n }\n }\n\n if (!session.elementIsNavigatable(element)) {\n return false\n }\n\n if (submitter && !session.elementIsNavigatable(submitter)) {\n return false\n }\n\n return true\n }\n\n // Computed properties\n\n get id() {\n return this.element.id\n }\n\n get disabled() {\n return this.element.disabled\n }\n\n get enabled() {\n return !this.disabled\n }\n\n get sourceURL() {\n if (this.element.src) {\n return this.element.src\n }\n }\n\n set sourceURL(sourceURL) {\n this.#ignoringChangesToAttribute(\"src\", () => {\n this.element.src = sourceURL ?? null;\n });\n }\n\n get loadingStyle() {\n return this.element.loading\n }\n\n get isLoading() {\n return this.formSubmission !== undefined || this.#resolveVisitPromise() !== undefined\n }\n\n get complete() {\n return this.element.hasAttribute(\"complete\")\n }\n\n set complete(value) {\n if (value) {\n this.element.setAttribute(\"complete\", \"\");\n } else {\n this.element.removeAttribute(\"complete\");\n }\n }\n\n get isActive() {\n return this.element.isActive && this.#connected\n }\n\n get rootLocation() {\n const meta = this.element.ownerDocument.querySelector(`meta[name=\"turbo-root\"]`);\n const root = meta?.content ?? \"/\";\n return expandURL(root)\n }\n\n #isIgnoringChangesTo(attributeName) {\n return this.#ignoredAttributes.has(attributeName)\n }\n\n #ignoringChangesToAttribute(attributeName, callback) {\n this.#ignoredAttributes.add(attributeName);\n callback();\n this.#ignoredAttributes.delete(attributeName);\n }\n\n #withCurrentNavigationElement(element, callback) {\n this.currentNavigationElement = element;\n callback();\n delete this.currentNavigationElement;\n }\n\n #getFrameElementById(id) {\n if (id != null) {\n const element = id === \"_parent\" ?\n this.element.parentElement.closest(\"turbo-frame\") :\n document.getElementById(id);\n if (element instanceof FrameElement) {\n return element\n }\n }\n }\n}\n\nfunction activateElement(element, currentURL) {\n if (element) {\n const src = element.getAttribute(\"src\");\n if (src != null && currentURL != null && urlsAreEqual(src, currentURL)) {\n throw new Error(`Matching element has a source URL which references itself`)\n }\n if (element.ownerDocument !== document) {\n element = document.importNode(element, true);\n }\n\n if (element instanceof FrameElement) {\n element.connectedCallback();\n element.disconnectedCallback();\n return element\n }\n }\n}\n\nconst StreamActions = {\n after() {\n this.removeDuplicateTargetSiblings();\n this.targetElements.forEach((e) => e.parentElement?.insertBefore(this.templateContent, e.nextSibling));\n },\n\n append() {\n this.removeDuplicateTargetChildren();\n this.targetElements.forEach((e) => e.append(this.templateContent));\n },\n\n before() {\n this.removeDuplicateTargetSiblings();\n this.targetElements.forEach((e) => e.parentElement?.insertBefore(this.templateContent, e));\n },\n\n prepend() {\n this.removeDuplicateTargetChildren();\n this.targetElements.forEach((e) => e.prepend(this.templateContent));\n },\n\n remove() {\n this.targetElements.forEach((e) => e.remove());\n },\n\n replace() {\n const method = this.getAttribute(\"method\");\n\n this.targetElements.forEach((targetElement) => {\n if (method === \"morph\") {\n morphElements(targetElement, this.templateContent);\n } else {\n targetElement.replaceWith(this.templateContent);\n }\n });\n },\n\n update() {\n const method = this.getAttribute(\"method\");\n\n this.targetElements.forEach((targetElement) => {\n if (method === \"morph\") {\n morphChildren(targetElement, this.templateContent);\n } else {\n targetElement.innerHTML = \"\";\n targetElement.append(this.templateContent);\n }\n });\n },\n\n refresh() {\n const method = this.getAttribute(\"method\");\n const requestId = this.requestId;\n const scroll = this.getAttribute(\"scroll\");\n\n session.refresh(this.baseURI, { method, requestId, scroll });\n }\n};\n\n//