\");\n const dropdown = this._render(\"dropdown\");\n const dropdown_content = getDom(`
`);\n const classes = this.input.getAttribute(\"class\") || \"\";\n const inputMode = settings.mode;\n var control_input;\n addClasses(wrapper, settings.wrapperClass, classes, inputMode);\n addClasses(control, settings.controlClass);\n append(wrapper, control);\n addClasses(dropdown, settings.dropdownClass, inputMode);\n if (settings.copyClassesToDropdown) {\n addClasses(dropdown, classes);\n }\n addClasses(dropdown_content, settings.dropdownContentClass);\n append(dropdown, dropdown_content);\n getDom(settings.dropdownParent || wrapper).appendChild(dropdown);\n if (isHtmlString(settings.controlInput)) {\n control_input = getDom(settings.controlInput);\n var attrs = [\"autocorrect\", \"autocapitalize\", \"autocomplete\", \"spellcheck\", \"aria-label\"];\n iterate(attrs, (attr) => {\n if (input.getAttribute(attr)) {\n setAttr(control_input, { [attr]: input.getAttribute(attr) });\n }\n });\n control_input.tabIndex = -1;\n control.appendChild(control_input);\n this.focus_node = control_input;\n } else if (settings.controlInput) {\n control_input = getDom(settings.controlInput);\n this.focus_node = control_input;\n } else {\n control_input = getDom(\"
\");\n this.focus_node = control;\n }\n this.wrapper = wrapper;\n this.dropdown = dropdown;\n this.dropdown_content = dropdown_content;\n this.control = control;\n this.control_input = control_input;\n this.setup();\n }\n /**\n * set up event bindings.\n *\n */\n setup() {\n const self = this;\n const settings = self.settings;\n const control_input = self.control_input;\n const dropdown = self.dropdown;\n const dropdown_content = self.dropdown_content;\n const wrapper = self.wrapper;\n const control = self.control;\n const input = self.input;\n const focus_node = self.focus_node;\n const passive_event = { passive: true };\n const listboxId = self.inputId + \"-ts-dropdown\";\n setAttr(dropdown_content, {\n id: listboxId\n });\n setAttr(focus_node, {\n role: \"combobox\",\n \"aria-haspopup\": \"listbox\",\n \"aria-expanded\": \"false\",\n \"aria-controls\": listboxId\n });\n const control_id = getId(focus_node, self.inputId + \"-ts-control\");\n const query = \"label[for='\" + escapeQuery(self.inputId) + \"']\";\n const label = document.querySelector(query);\n const label_click = self.focus.bind(self);\n if (label) {\n addEvent(label, \"click\", label_click);\n setAttr(label, { for: control_id });\n const label_id = getId(label, self.inputId + \"-ts-label\");\n setAttr(focus_node, { \"aria-labelledby\": label_id });\n setAttr(dropdown_content, { \"aria-labelledby\": label_id });\n }\n wrapper.style.width = input.style.width;\n wrapper.style.minWidth = input.style.minWidth;\n wrapper.style.maxWidth = input.style.maxWidth;\n if (self.plugins.names.length) {\n const classes_plugins = \"plugin-\" + self.plugins.names.join(\" plugin-\");\n addClasses([wrapper, dropdown], classes_plugins);\n }\n if ((settings.maxItems === null || settings.maxItems > 1) && self.is_select_tag) {\n setAttr(input, { multiple: \"multiple\" });\n }\n if (settings.placeholder) {\n setAttr(control_input, { placeholder: settings.placeholder });\n }\n if (!settings.splitOn && settings.delimiter) {\n settings.splitOn = new RegExp(\"\\\\s*\" + escape_regex(settings.delimiter) + \"+\\\\s*\");\n }\n if (settings.load && settings.loadThrottle) {\n settings.load = loadDebounce(settings.load, settings.loadThrottle);\n }\n addEvent(dropdown, \"mousemove\", () => {\n self.ignoreHover = false;\n });\n addEvent(dropdown, \"mouseenter\", (e) => {\n var target_match = parentMatch(e.target, \"[data-selectable]\", dropdown);\n if (target_match)\n self.onOptionHover(e, target_match);\n }, { capture: true });\n addEvent(dropdown, \"click\", (evt) => {\n const option = parentMatch(evt.target, \"[data-selectable]\");\n if (option) {\n self.onOptionSelect(evt, option);\n preventDefault(evt, true);\n }\n });\n addEvent(control, \"click\", (evt) => {\n var target_match = parentMatch(evt.target, \"[data-ts-item]\", control);\n if (target_match && self.onItemSelect(evt, target_match)) {\n preventDefault(evt, true);\n return;\n }\n if (control_input.value != \"\") {\n return;\n }\n self.onClick();\n preventDefault(evt, true);\n });\n addEvent(focus_node, \"keydown\", (e) => self.onKeyDown(e));\n addEvent(control_input, \"keypress\", (e) => self.onKeyPress(e));\n addEvent(control_input, \"input\", (e) => self.onInput(e));\n addEvent(focus_node, \"blur\", (e) => self.onBlur(e));\n addEvent(focus_node, \"focus\", (e) => self.onFocus(e));\n addEvent(control_input, \"paste\", (e) => self.onPaste(e));\n const doc_mousedown = (evt) => {\n const target = evt.composedPath()[0];\n if (!wrapper.contains(target) && !dropdown.contains(target)) {\n if (self.isFocused) {\n self.blur();\n }\n self.inputState();\n return;\n }\n if (target == control_input && self.isOpen) {\n evt.stopPropagation();\n } else {\n preventDefault(evt, true);\n }\n };\n const win_scroll = () => {\n if (self.isOpen) {\n self.positionDropdown();\n }\n };\n const input_invalid = () => {\n if (self.isValid) {\n self.isValid = false;\n self.isInvalid = true;\n self.refreshState();\n }\n };\n addEvent(input, \"invalid\", input_invalid);\n addEvent(document, \"mousedown\", doc_mousedown);\n addEvent(window, \"scroll\", win_scroll, passive_event);\n addEvent(window, \"resize\", win_scroll, passive_event);\n this._destroy = () => {\n input.removeEventListener(\"invalid\", input_invalid);\n document.removeEventListener(\"mousedown\", doc_mousedown);\n window.removeEventListener(\"scroll\", win_scroll);\n window.removeEventListener(\"resize\", win_scroll);\n if (label)\n label.removeEventListener(\"click\", label_click);\n };\n this.revertSettings = {\n innerHTML: input.innerHTML,\n tabIndex: input.tabIndex\n };\n input.tabIndex = -1;\n input.insertAdjacentElement(\"afterend\", self.wrapper);\n self.sync(false);\n settings.items = [];\n delete settings.optgroups;\n delete settings.options;\n self.refreshItems();\n self.close(false);\n self.inputState();\n self.isSetup = true;\n self.on(\"change\", this.onChange);\n addClasses(input, \"tomselected\", \"ts-hidden-accessible\");\n self.trigger(\"initialize\");\n if (settings.preload === true) {\n self.preload();\n }\n }\n /**\n * Register options and optgroups\n *\n */\n setupOptions(options = [], optgroups = []) {\n this.addOptions(options);\n iterate(optgroups, (optgroup) => {\n this.registerOptionGroup(optgroup);\n });\n }\n /**\n * Sets up default rendering functions.\n */\n setupTemplates() {\n var self = this;\n var field_label = self.settings.labelField;\n var field_optgroup = self.settings.optgroupLabelField;\n var templates = {\n \"optgroup\": (data) => {\n let optgroup = document.createElement(\"div\");\n optgroup.className = \"optgroup\";\n optgroup.appendChild(data.options);\n return optgroup;\n },\n \"optgroup_header\": (data, escape) => {\n return '\";\n },\n \"option\": (data, escape) => {\n return \"
\" + escape(data[field_label]) + \"
\";\n },\n \"item\": (data, escape) => {\n return \"
\" + escape(data[field_label]) + \"
\";\n },\n \"option_create\": (data, escape) => {\n return '
Add ' + escape(data.input) + \"…
\";\n },\n \"no_results\": () => {\n return '
No results found
';\n },\n \"loading\": () => {\n return '
';\n },\n \"not_loading\": () => {\n },\n \"dropdown\": () => {\n return \"
\";\n }\n };\n self.settings.render = Object.assign({}, templates, self.settings.render);\n }\n /**\n * Maps fired events to callbacks provided\n * in the settings used when creating the control.\n */\n setupCallbacks() {\n var key, fn;\n var callbacks = {\n \"initialize\": \"onInitialize\",\n \"change\": \"onChange\",\n \"item_add\": \"onItemAdd\",\n \"item_remove\": \"onItemRemove\",\n \"item_select\": \"onItemSelect\",\n \"clear\": \"onClear\",\n \"option_add\": \"onOptionAdd\",\n \"option_remove\": \"onOptionRemove\",\n \"option_clear\": \"onOptionClear\",\n \"optgroup_add\": \"onOptionGroupAdd\",\n \"optgroup_remove\": \"onOptionGroupRemove\",\n \"optgroup_clear\": \"onOptionGroupClear\",\n \"dropdown_open\": \"onDropdownOpen\",\n \"dropdown_close\": \"onDropdownClose\",\n \"type\": \"onType\",\n \"load\": \"onLoad\",\n \"focus\": \"onFocus\",\n \"blur\": \"onBlur\"\n };\n for (key in callbacks) {\n fn = this.settings[callbacks[key]];\n if (fn)\n this.on(key, fn);\n }\n }\n /**\n * Sync the Tom Select instance with the original input or select\n *\n */\n sync(get_settings = true) {\n const self = this;\n const settings = get_settings ? getSettings(self.input, { delimiter: self.settings.delimiter, allowEmptyOption: self.settings.allowEmptyOption }) : self.settings;\n self.setupOptions(settings.options, settings.optgroups);\n self.setValue(settings.items || [], true);\n if (self.input.disabled) {\n self.disable();\n } else if (self.input.readOnly) {\n self.setReadOnly(true);\n } else {\n self.enable();\n }\n self.lastQuery = null;\n }\n /**\n * Triggered when the main control element\n * has a click event.\n *\n */\n onClick() {\n var self = this;\n if (self.activeItems.length > 0) {\n self.clearActiveItems();\n self.focus();\n return;\n }\n if (self.isFocused && self.isOpen) {\n self.blur();\n } else {\n self.focus();\n }\n }\n /**\n * @deprecated v1.7\n *\n */\n onMouseDown() {\n }\n /**\n * Triggered when the value of the control has been changed.\n * This should propagate the event to the original DOM\n * input / select element.\n */\n onChange() {\n triggerEvent(this.input, \"input\");\n triggerEvent(this.input, \"change\");\n }\n /**\n * Triggered on
paste.\n *\n */\n onPaste(e) {\n var self = this;\n if (self.isInputHidden || self.isLocked) {\n preventDefault(e);\n return;\n }\n if (!self.settings.splitOn) {\n return;\n }\n setTimeout(() => {\n var pastedText = self.inputValue();\n if (!pastedText.match(self.settings.splitOn)) {\n return;\n }\n var splitInput = pastedText.trim().split(self.settings.splitOn);\n iterate(splitInput, (piece) => {\n const hash = hash_key(piece);\n if (hash) {\n if (this.options[piece]) {\n self.addItem(piece);\n } else {\n self.createItem(piece);\n }\n }\n });\n }, 0);\n }\n /**\n * Triggered on
keypress.\n *\n */\n onKeyPress(e) {\n var self = this;\n if (self.isLocked) {\n preventDefault(e);\n return;\n }\n var character = String.fromCharCode(e.keyCode || e.which);\n if (self.settings.create && self.settings.mode === \"multi\" && character === self.settings.delimiter) {\n self.createItem();\n preventDefault(e);\n return;\n }\n }\n /**\n * Triggered on
keydown.\n *\n */\n onKeyDown(e) {\n var self = this;\n self.ignoreHover = true;\n if (self.isLocked) {\n if (e.keyCode !== constants.KEY_TAB) {\n preventDefault(e);\n }\n return;\n }\n switch (e.keyCode) {\n // ctrl+A: select all\n case constants.KEY_A:\n if (isKeyDown(constants.KEY_SHORTCUT, e)) {\n if (self.control_input.value == \"\") {\n preventDefault(e);\n self.selectAll();\n return;\n }\n }\n break;\n // esc: close dropdown\n case constants.KEY_ESC:\n if (self.isOpen) {\n preventDefault(e, true);\n self.close();\n }\n self.clearActiveItems();\n return;\n // down: open dropdown or move selection down\n case constants.KEY_DOWN:\n if (!self.isOpen && self.hasOptions) {\n self.open();\n } else if (self.activeOption) {\n let next = self.getAdjacent(self.activeOption, 1);\n if (next)\n self.setActiveOption(next);\n }\n preventDefault(e);\n return;\n // up: move selection up\n case constants.KEY_UP:\n if (self.activeOption) {\n let prev = self.getAdjacent(self.activeOption, -1);\n if (prev)\n self.setActiveOption(prev);\n }\n preventDefault(e);\n return;\n // return: select active option\n case constants.KEY_RETURN:\n if (self.canSelect(self.activeOption)) {\n self.onOptionSelect(e, self.activeOption);\n preventDefault(e);\n } else if (self.settings.create && self.createItem()) {\n preventDefault(e);\n } else if (document.activeElement == self.control_input && self.isOpen) {\n preventDefault(e);\n }\n return;\n // left: modifiy item selection to the left\n case constants.KEY_LEFT:\n self.advanceSelection(-1, e);\n return;\n // right: modifiy item selection to the right\n case constants.KEY_RIGHT:\n self.advanceSelection(1, e);\n return;\n // tab: select active option and/or create item\n case constants.KEY_TAB:\n if (self.settings.selectOnTab) {\n if (self.canSelect(self.activeOption)) {\n self.onOptionSelect(e, self.activeOption);\n preventDefault(e);\n } else if (self.settings.create && self.createItem()) {\n preventDefault(e);\n }\n }\n return;\n // delete|backspace: delete items\n case constants.KEY_BACKSPACE:\n case constants.KEY_DELETE:\n self.deleteSelection(e);\n return;\n }\n if (self.isInputHidden && !isKeyDown(constants.KEY_SHORTCUT, e)) {\n preventDefault(e);\n }\n }\n /**\n * Triggered on
keyup.\n *\n */\n onInput(e) {\n if (this.isLocked) {\n return;\n }\n const value = this.inputValue();\n if (this.lastValue === value)\n return;\n this.lastValue = value;\n if (value == \"\") {\n this._onInput();\n return;\n }\n if (this.refreshTimeout) {\n window.clearTimeout(this.refreshTimeout);\n }\n this.refreshTimeout = timeout(() => {\n this.refreshTimeout = null;\n this._onInput();\n }, this.settings.refreshThrottle);\n }\n _onInput() {\n const value = this.lastValue;\n if (this.settings.shouldLoad.call(this, value)) {\n this.load(value);\n }\n this.refreshOptions();\n this.trigger(\"type\", value);\n }\n /**\n * Triggered when the user rolls over\n * an option in the autocomplete dropdown menu.\n *\n */\n onOptionHover(evt, option) {\n if (this.ignoreHover)\n return;\n this.setActiveOption(option, false);\n }\n /**\n * Triggered on
focus.\n *\n */\n onFocus(e) {\n var self = this;\n var wasFocused = self.isFocused;\n if (self.isDisabled || self.isReadOnly) {\n self.blur();\n preventDefault(e);\n return;\n }\n if (self.ignoreFocus)\n return;\n self.isFocused = true;\n if (self.settings.preload === \"focus\")\n self.preload();\n if (!wasFocused)\n self.trigger(\"focus\");\n if (!self.activeItems.length) {\n self.inputState();\n self.refreshOptions(!!self.settings.openOnFocus);\n }\n self.refreshState();\n }\n /**\n * Triggered on
blur.\n *\n */\n onBlur(e) {\n if (document.hasFocus() === false)\n return;\n var self = this;\n if (!self.isFocused)\n return;\n self.isFocused = false;\n self.ignoreFocus = false;\n var deactivate = () => {\n self.close();\n self.setActiveItem();\n self.setCaret(self.items.length);\n self.trigger(\"blur\");\n };\n if (self.settings.create && self.settings.createOnBlur) {\n self.createItem(null, deactivate);\n } else {\n deactivate();\n }\n }\n /**\n * Triggered when the user clicks on an option\n * in the autocomplete dropdown menu.\n *\n */\n onOptionSelect(evt, option) {\n var value, self = this;\n if (option.parentElement && option.parentElement.matches(\"[data-disabled]\")) {\n return;\n }\n if (option.classList.contains(\"create\")) {\n self.createItem(null, () => {\n if (self.settings.closeAfterSelect) {\n self.close();\n } else if (self.settings.clearAfterSelect) {\n self.setTextboxValue();\n }\n });\n } else {\n value = option.dataset.value;\n if (typeof value !== \"undefined\") {\n self.isDropdownContentStale = self.settings.hideSelected;\n self.addItem(value);\n if (self.settings.closeAfterSelect) {\n self.close();\n } else if (self.settings.clearAfterSelect) {\n self.setTextboxValue();\n }\n if (!self.settings.hideSelected && evt.type && /click/.test(evt.type)) {\n self.setActiveOption(option);\n }\n }\n }\n }\n /**\n * Return true if the given option can be selected\n *\n */\n canSelect(option) {\n if (this.isOpen && option && this.dropdown_content.contains(option)) {\n return true;\n }\n return false;\n }\n /**\n * Triggered when the user clicks on an item\n * that has been selected.\n *\n */\n onItemSelect(evt, item) {\n var self = this;\n if (!self.isLocked && self.settings.mode === \"multi\") {\n preventDefault(evt);\n self.setActiveItem(item, evt);\n return true;\n }\n return false;\n }\n /**\n * Determines whether or not to invoke\n * the user-provided option provider / loader\n *\n * Note, there is a subtle difference between\n * this.canLoad() and this.settings.shouldLoad();\n *\n *\t- settings.shouldLoad() is a user-input validator.\n *\tWhen false is returned, the not_loading template\n *\twill be added to the dropdown\n *\n *\t- canLoad() is lower level validator that checks\n * \tthe Tom Select instance. There is no inherent user\n *\tfeedback when canLoad returns false\n *\n */\n canLoad(value) {\n if (!this.settings.load)\n return false;\n if (this.loadedSearches.hasOwnProperty(value))\n return false;\n return true;\n }\n /**\n * Invokes the user-provided option provider / loader.\n *\n */\n load(value) {\n const self = this;\n if (!self.canLoad(value))\n return;\n addClasses(self.wrapper, self.settings.loadingClass);\n self.loading++;\n const callback = self.loadCallback.bind(self);\n self.settings.load.call(self, value, callback);\n }\n /**\n * Invoked by the user-provided option provider\n *\n */\n loadCallback(options, optgroups) {\n const self = this;\n self.loading = Math.max(self.loading - 1, 0);\n self.isDropdownContentStale = true;\n self.clearActiveOption();\n self.setupOptions(options, optgroups);\n self.refreshOptions(self.isFocused && !self.isInputHidden);\n if (!self.loading) {\n removeClasses(self.wrapper, self.settings.loadingClass);\n }\n self.trigger(\"load\", options, optgroups);\n }\n preload() {\n var classList = this.wrapper.classList;\n if (classList.contains(\"preloaded\"))\n return;\n classList.add(\"preloaded\");\n this.load(\"\");\n }\n /**\n * Sets the input field of the control to the specified value.\n *\n */\n setTextboxValue(value = \"\") {\n var input = this.control_input;\n var changed = input.value !== value;\n if (changed) {\n input.value = value;\n triggerEvent(input, \"update\");\n this.lastValue = value;\n }\n }\n /**\n * Returns the value of the control. If multiple items\n * can be selected (e.g.