PageSourceSearch

https://ism.gov.in/lib/tomselect/tom-select.complete.min.js

js ism.gov.in collected 2026-09-24 10:26:04 UTC 155,449 bytes, 5,113 lines download raw bytes

1/**
2* Tom Select v2.6.1
vendor: 63,268 bytes, lines 2-2071
2
3* Licensed under the Apache License, Version 2.0 (the "License");
4*/
5
6(function (global, factory) {
7	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8	typeof define === 'function' && define.amd ? define(factory) :
9	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.TomSelect = factory());
10})(this, (function () { 'use strict';
11
12	/**
13	 * MicroEvent - to make any js object an event emitter
14	 *
15	 * - pure javascript - server compatible, browser compatible
16	 * - dont rely on the browser doms
17	 * - super simple - you get it immediatly, no mistery, no magic involved
18	 *
19	 * @author Jerome Etienne (https://github.com/jeromeetienne)
20	 */
21
22	/**
23	 * Execute callback for each event in space separated list of event names
24	 *
25	 */
26	function forEvents(events, callback) {
27	  events.split(/\s+/).forEach(event => {
28	    callback(event);
29	  });
30	}
31	class MicroEvent {
32	  constructor() {
33	    this._events = {};
34	  }
35	  on(events, fct) {
36	    forEvents(events, event => {
37	      const event_array = this._events[event] || [];
38	      event_array.push(fct);
39	      this._events[event] = event_array;
40	    });
41	  }
42	  off(events, fct) {
43	    var n = arguments.length;
44	    if (n === 0) {
45	      this._events = {};
46	      return;
47	    }
48	    forEvents(events, event => {
49	      if (n === 1) {
50	        delete this._events[event];
51	        return;
52	      }
53	      const event_array = this._events[event];
54	      if (event_array === undefined) return;
55	      event_array.splice(event_array.indexOf(fct), 1);
56	      this._events[event] = event_array;
57	    });
58	  }
59	  trigger(events, ...args) {
60	    var self = this;
61	    forEvents(events, event => {
62	      const event_array = self._events[event];
63	      if (event_array === undefined) return;
64	      event_array.forEach(fct => {
65	        fct.apply(self, args);
66	      });
67	    });
68	  }
69	}
70
71	/**
72	 * microplugin.js
73	 * Copyright (c) 2013 Brian Reavis & contributors
74	 *
75	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
76	 * file except in compliance with the License. You may obtain a copy of the License at:
77	 * http://www.apache.org/licenses/LICENSE-2.0
78	 *
79	 * Unless required by applicable law or agreed to in writing, software distributed under
80	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
81	 * ANY KIND, either express or implied. See the License for the specific language
82	 * governing permissions and limitations under the License.
83	 *
84	 * @author Brian Reavis <[email protected]>
85	 */
86
87	function MicroPlugin(Interface) {
88	  Interface.plugins = {};
89	  return class extends Interface {
90	    constructor(...args) {
91	      super(...args);
92	      this.plugins = {
93	        names: [],
94	        settings: {},
95	        requested: {},
96	        loaded: {}
97	      };
98	    }
99	    /**
100	     * Registers a plugin.
101	     *
102	     * @param {function} fn
103	     */
104	    static define(name, fn) {
105	      Interface.plugins[name] = {
106	        'name': name,
107	        'fn': fn
108	      };
109	    }
110
111	    /**
112	     * Initializes the listed plugins (with options).
113	     * Acceptable formats:
114	     *
115	     * List (without options):
116	     *   ['a', 'b', 'c']
117	     *
118	     * List (with options):
119	     *   [{'name': 'a', options: {}}, {'name': 'b', options: {}}]
120	     *
121	     * Hash (with options):
122	     *   {'a': { ... }, 'b': { ... }, 'c': { ... }}
123	     *
124	     * @param {array|object} plugins
125	     */
126	    initializePlugins(plugins) {
127	      var key, name;
128	      const self = this;
129	      const queue = [];
130	      if (Array.isArray(plugins)) {
131	        plugins.forEach(plugin => {
132	          if (typeof plugin === 'string') {
133	            queue.push(plugin);
134	          } else {
135	            self.plugins.settings[plugin.name] = plugin.options;
136	            queue.push(plugin.name);
137	          }
138	        });
139	      } else if (plugins) {
140	        for (key in plugins) {
141	          if (plugins.hasOwnProperty(key)) {
142	            self.plugins.settings[key] = plugins[key];
143	            queue.push(key);
144	          }
145	        }
146	      }
147	      while (name = queue.shift()) {
148	        self.require(name);
149	      }
150	    }
151	    loadPlugin(name) {
152	      var self = this;
153	      var plugins = self.plugins;
154	      var plugin = Interface.plugins[name];
155	      if (!Interface.plugins.hasOwnProperty(name)) {
156	        throw new Error('Unable to find "' + name + '" plugin');
157	      }
158	      plugins.requested[name] = true;
159	      plugins.loaded[name] = plugin.fn.apply(self, [self.plugins.settings[name] || {}]);
160	      plugins.names.push(name);
161	    }
162
163	    /**
164	     * Initializes a plugin.
165	     *
166	     */
167	    require(name) {
168	      var self = this;
169	      var plugins = self.plugins;
170	      if (!self.plugins.loaded.hasOwnProperty(name)) {
171	        if (plugins.requested[name]) {
172	          throw new Error('Plugin has circular dependency ("' + name + '")');
173	        }
174	        self.loadPlugin(name);
175	      }
176	      return plugins.loaded[name];
177	    }
178	  };
179	}
180
181	/**
182	 * Convert array of strings to a regular expression
183	 *	ex ['ab','a'] => (?:ab|a)
184	 * 	ex ['a','b'] => [ab]
185	 */
186	const arrayToPattern = (chars) => {
187	    chars = chars.filter(Boolean);
188	    if (chars.length < 2) {
189	        return chars[0] || '';
190	    }
191	    return (maxValueLength(chars) == 1) ? '[' + chars.join('') + ']' : '(?:' + chars.join('|') + ')';
192	};
193	const sequencePattern = (array) => {
194	    if (!hasDuplicates(array)) {
195	        return array.join('');
196	    }
197	    let pattern = '';
198	    let prev_char_count = 0;
199	    const prev_pattern = () => {
200	        if (prev_char_count > 1) {
201	            pattern += '{' + prev_char_count + '}';
202	        }
203	    };
204	    array.forEach((char, i) => {
205	        if (char === array[i - 1]) {
206	            prev_char_count++;
207	            return;
208	        }
209	        prev_pattern();
210	        pattern += char;
211	        prev_char_count = 1;
212	    });
213	    prev_pattern();
214	    return pattern;
215	};
216	/**
217	 * Convert array of strings to a regular expression
218	 *	ex ['ab','a'] => (?:ab|a)
219	 * 	ex ['a','b'] => [ab]
220	 */
221	const setToPattern = (chars) => {
222	    let array = Array.from(chars);
223	    return arrayToPattern(array);
224	};
225	/**
226	 * https://stackoverflow.com/questions/7376598/in-javascript-how-do-i-check-if-an-array-has-duplicate-values
227	 */
228	const hasDuplicates = (array) => {
229	    return (new Set(array)).size !== array.length;
230	};
231	/**
232	 * https://stackoverflow.com/questions/63006601/why-does-u-throw-an-invalid-escape-error
233	 */
234	const escape_regex = (str) => {
235	    return (str + '').replace(/([\$\(\)\*\+\.\?\[\]\^\{\|\}\\])/gu, '\\$1');
236	};
237	/**
238	 * Return the max length of array values
239	 */
240	const maxValueLength = (array) => {
241	    return array.reduce((longest, value) => Math.max(longest, unicodeLength(value)), 0);
242	};
243	const unicodeLength = (str) => {
244	    return Array.from(str).length;
245	};
246
247	/**
248	 * Get all possible combinations of substrings that add up to the given string
249	 * https://stackoverflow.com/questions/30169587/find-all-the-combination-of-substrings-that-add-up-to-the-given-string
250	 */
251	const allSubstrings = (input) => {
252	    if (input.length === 1)
253	        return [[input]];
254	    let result = [];
255	    const start = input.substring(1);
256	    const suba = allSubstrings(start);
257	    suba.forEach(function (subresult) {
258	        let tmp = subresult.slice(0);
259	        tmp[0] = input.charAt(0) + tmp[0];
260	        result.push(tmp);
261	        tmp = subresult.slice(0);
262	        tmp.unshift(input.charAt(0));
263	        result.push(tmp);
264	    });
265	    return result;
266	};
267
268	const code_points = [[0, 65535]];
269	const accent_pat = '[\u0300-\u036F\u{b7}\u{2be}\u{2bc}]';
270	let unicode_map;
271	let multi_char_reg;
272	const max_char_length = 3;
273	const latin_convert = {};
274	const latin_condensed = {
275	    '/': '⁄∕',
276	    '0': '߀',
277	    "a": "ⱥɐɑ",
278	    "aa": "ꜳ",
279	    "ae": "æǽǣ",
280	    "ao": "ꜵ",
281	    "au": "ꜷ",
282	    "av": "ꜹꜻ",
283	    "ay": "ꜽ",
284	    "b": "ƀɓƃ",
285	    "c": "ꜿƈȼↄ",
286	    "d": "đɗɖᴅƌꮷԁɦ",
287	    "e": "ɛǝᴇɇ",
288	    "f": "ꝼƒ",
289	    "g": "ǥɠꞡᵹꝿɢ",
290	    "h": "ħⱨⱶɥ",
291	    "i": "ɨı",
292	    "j": "ɉȷ",
293	    "k": "ƙⱪꝁꝃꝅꞣ",
294	    "l": "łƚɫⱡꝉꝇꞁɭ",
295	    "m": "ɱɯϻ",
296	    "n": "ꞥƞɲꞑᴎлԉ",
297	    "o": "øǿɔɵꝋꝍᴑ",
298	    "oe": "œ",
299	    "oi": "Æ£",
300	    "oo": "ꝏ",
301	    "ou": "È£",
302	    "p": "ƥᵽꝑꝓꝕρ",
303	    "q": "ꝗꝙɋ",
304	    "r": "ɍɽꝛꞧꞃ",
305	    "s": "ßȿꞩꞅʂ",
306	    "t": "ŧƭʈⱦꞇ",
307	    "th": "þ",
308	    "tz": "ꜩ",
309	    "u": "ʉ",
310	    "v": "ʋꝟʌ",
311	    "vy": "ꝡ",
312	    "w": "â±³",
313	    "y": "ƴɏỿ",
314	    "z": "ƶȥɀⱬꝣ",
315	    "hv": "ƕ"
316	};
317	for (let latin in latin_condensed) {
318	    let unicode = latin_condensed[latin] || '';
319	    for (let i = 0; i < unicode.length; i++) {
320	        let char = unicode.substring(i, i + 1);
321	        latin_convert[char] = latin;
322	    }
323	}
324	const convert_pat = new RegExp(Object.keys(latin_convert).join('|') + '|' + accent_pat, 'gu');
325	/**
326	 * Initialize the unicode_map from the give code point ranges
327	 */
328	const initialize = (_code_points) => {
329	    if (unicode_map !== undefined)
330	        return;
331	    unicode_map = generateMap(code_points);
332	};
333	/**
334	 * Helper method for normalize a string
335	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
336	 */
337	const normalize = (str, form = 'NFKD') => str.normalize(form);
338	/**
339	 * Remove accents without reordering string
340	 * calling str.normalize('NFKD') on \u{594}\u{595}\u{596} becomes \u{596}\u{594}\u{595}
341	 * via https://github.com/krisk/Fuse/issues/133#issuecomment-318692703
342	 */
343	const asciifold = (str) => {
344	    return Array.from(str).reduce(
345	    /**
346	     * @param {string} result
347	     * @param {string} char
348	     */
349	    (result, char) => {
350	        return result + _asciifold(char);
351	    }, '');
352	};
353	const _asciifold = (str) => {
354	    str = normalize(str)
355	        .toLowerCase()
356	        .replace(convert_pat, (/** @type {string} */ char) => {
357	        return latin_convert[char] || '';
358	    });
359	    //return str;
360	    return normalize(str, 'NFC');
361	};
362	/**
363	 * Generate a list of unicode variants from the list of code points
364	 */
365	function* generator(code_points) {
366	    for (const [code_point_min, code_point_max] of code_points) {
367	        for (let i = code_point_min; i <= code_point_max; i++) {
368	            let composed = String.fromCharCode(i);
369	            let folded = asciifold(composed);
370	            if (folded == composed.toLowerCase()) {
371	                continue;
372	            }
373	            // skip when folded is a string longer than 3 characters long
374	            // bc the resulting regex patterns will be long
375	            // eg:
376	            // folded صلى الله عليه وسلم length 18 code point 65018
377	            // folded جل جلاله length 8 code point 65019
378	            if (folded.length > max_char_length) {
379	                continue;
380	            }
381	            if (folded.length == 0) {
382	                continue;
383	            }
384	            yield { folded: folded, composed: composed, code_point: i };
385	        }
386	    }
387	}
388	/**
389	 * Generate a unicode map from the list of code points
390	 */
391	const generateSets = (code_points) => {
392	    const unicode_sets = {};
393	    const addMatching = (folded, to_add) => {
394	        /** @type {Set<string>} */
395	        const folded_set = unicode_sets[folded] || new Set();
396	        const patt = new RegExp('^' + setToPattern(folded_set) + '$', 'iu');
397	        if (to_add.match(patt)) {
398	            return;
399	        }
400	        folded_set.add(escape_regex(to_add));
401	        unicode_sets[folded] = folded_set;
402	    };
403	    for (let value of generator(code_points)) {
404	        addMatching(value.folded, value.folded);
405	        addMatching(value.folded, value.composed);
406	    }
407	    return unicode_sets;
408	};
409	/**
410	 * Generate a unicode map from the list of code points
411	 * ae => (?:(?:ae|Æ|Ǽ|Ǣ)|(?:A|Ⓐ|A...)(?:E|ɛ|Ⓔ...))
412	 */
413	const generateMap = (code_points) => {
414	    const unicode_sets = generateSets(code_points);
415	    const unicode_map = {};
416	    let multi_char = [];
417	    for (let folded in unicode_sets) {
418	        let set = unicode_sets[folded];
419	        if (set) {
420	            unicode_map[folded] = setToPattern(set);
421	        }
422	        if (folded.length > 1) {
423	            multi_char.push(escape_regex(folded));
424	        }
425	    }
426	    multi_char.sort((a, b) => b.length - a.length);
427	    const multi_char_patt = arrayToPattern(multi_char);
428	    multi_char_reg = new RegExp('^' + multi_char_patt, 'u');
429	    return unicode_map;
430	};
431	/**
432	 * Map each element of an array from its folded value to all possible unicode matches
433	 */
434	const mapSequence = (strings, min_replacement = 1) => {
435	    let chars_replaced = 0;
436	    strings = strings.map((str) => {
437	        if (unicode_map[str]) {
438	            chars_replaced += str.length;
439	        }
440	        return unicode_map[str] || str;
441	    });
442	    if (chars_replaced >= min_replacement) {
443	        return sequencePattern(strings);
444	    }
445	    return '';
446	};
447	/**
448	 * Convert a short string and split it into all possible patterns
449	 * Keep a pattern only if min_replacement is met
450	 *
451	 * 'abc'
452	 * 		=> [['abc'],['ab','c'],['a','bc'],['a','b','c']]
453	 *		=> ['abc-pattern','ab-c-pattern'...]
454	 */
455	const substringsToPattern = (str, min_replacement = 1) => {
456	    min_replacement = Math.max(min_replacement, str.length - 1);
457	    return arrayToPattern(allSubstrings(str).map((sub_pat) => {
458	        return mapSequence(sub_pat, min_replacement);
459	    }));
460	};
461	/**
462	 * Convert an array of sequences into a pattern
463	 * [{start:0,end:3,length:3,substr:'iii'}...] => (?:iii...)
464	 */
465	const sequencesToPattern = (sequences, all = true) => {
466	    let min_replacement = sequences.length > 1 ? 1 : 0;
467	    return arrayToPattern(sequences.map((sequence) => {
468	        let seq = [];
469	        const len = all ? sequence.length() : sequence.length() - 1;
470	        for (let j = 0; j < len; j++) {
471	            seq.push(substringsToPattern(sequence.substrs[j] || '', min_replacement));
472	        }
473	        return sequencePattern(seq);
474	    }));
475	};
476	/**
477	 * Return true if the sequence is already in the sequences
478	 */
479	const inSequences = (needle_seq, sequences) => {
480	    for (const seq of sequences) {
481	        if (seq.start != needle_seq.start || seq.end != needle_seq.end) {
482	            continue;
483	        }
484	        if (seq.substrs.join('') !== needle_seq.substrs.join('')) {
485	            continue;
486	        }
487	        let needle_parts = needle_seq.parts;
488	        const filter = (part) => {
489	            for (const needle_part of needle_parts) {
490	                if (needle_part.start === part.start && needle_part.substr === part.substr) {
491	                    return false;
492	                }
493	                if (part.length == 1 || needle_part.length == 1) {
494	                    continue;
495	                }
496	                // check for overlapping parts
497	                // a = ['::=','==']
498	                // b = ['::','===']
499	                // a = ['r','sm']
500	                // b = ['rs','m']
501	                if (part.start < needle_part.start && part.end > needle_part.start) {
502	                    return true;
503	                }
504	                if (needle_part.start < part.start && needle_part.end > part.start) {
505	                    return true;
506	                }
507	            }
508	            return false;
509	        };
510	        let filtered = seq.parts.filter(filter);
511	        if (filtered.length > 0) {
512	            continue;
513	        }
514	        return true;
515	    }
516	    return false;
517	};
518	class Sequence {
519	    parts;
520	    substrs;
521	    start;
522	    end;
523	    constructor() {
524	        this.parts = [];
525	        this.substrs = [];
526	        this.start = 0;
527	        this.end = 0;
528	    }
529	    add(part) {
530	        if (part) {
531	            this.parts.push(part);
532	            this.substrs.push(part.substr);
533	            this.start = Math.min(part.start, this.start);
534	            this.end = Math.max(part.end, this.end);
535	        }
536	    }
537	    last() {
538	        return this.parts[this.parts.length - 1];
539	    }
540	    length() {
541	        return this.parts.length;
542	    }
543	    clone(position, last_piece) {
544	        let clone = new Sequence();
545	        let parts = JSON.parse(JSON.stringify(this.parts));
546	        let last_part = parts.pop();
547	        for (const part of parts) {
548	            clone.add(part);
549	        }
550	        let last_substr = last_piece.substr.substring(0, position - last_part.start);
551	        let clone_last_len = last_substr.length;
552	        clone.add({ start: last_part.start, end: last_part.start + clone_last_len, length: clone_last_len, substr: last_substr });
553	        return clone;
554	    }
555	}
556	/**
557	 * Expand a regular expression pattern to include unicode variants
558	 * 	eg /a/ becomes /aⓐaẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐɑAⒶAÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄȺⱯ/
559	 *
560	 * Issue:
561	 *  ﺊﺋ [ 'ﺊ = \\u{fe8a}', 'ﺋ = \\u{fe8b}' ]
562	 *	becomes:	ئئ [ 'ي = \\u{64a}', 'ٔ = \\u{654}', 'ي = \\u{64a}', 'ٔ = \\u{654}' ]
563	 *
564	 *	İIJ = IIJ = ⅡJ
565	 *
566	 * 	1/2/4
567	 */
568	const getPattern = (str) => {
569	    initialize();
570	    str = asciifold(str);
571	    let pattern = '';
572	    let sequences = [new Sequence()];
573	    for (let i = 0; i < str.length; i++) {
574	        let substr = str.substring(i);
575	        let match = substr.match(multi_char_reg);
576	        const char = str.substring(i, i + 1);
577	        const match_str = match ? match[0] : null;
578	        // loop through sequences
579	        // add either the char or multi_match
580	        let overlapping = [];
581	        let added_types = new Set();
582	        for (const sequence of sequences) {
583	            const last_piece = sequence.last();
584	            if (!last_piece || last_piece.length == 1 || last_piece.end <= i) {
585	                // if we have a multi match
586	                if (match_str) {
587	                    const len = match_str.length;
588	                    sequence.add({ start: i, end: i + len, length: len, substr: match_str });
589	                    added_types.add('1');
590	                }
591	                else {
592	                    sequence.add({ start: i, end: i + 1, length: 1, substr: char });
593	                    added_types.add('2');
594	                }
595	            }
596	            else if (match_str) {
597	                let clone = sequence.clone(i, last_piece);
598	                const len = match_str.length;
599	                clone.add({ start: i, end: i + len, length: len, substr: match_str });
600	                overlapping.push(clone);
601	            }
602	            else {
603	                // don't add char
604	                // adding would create invalid patterns: 234 => [2,34,4]
605	                added_types.add('3');
606	            }
607	        }
608	        // if we have overlapping
609	        if (overlapping.length > 0) {
610	            // ['ii','iii'] before ['i','i','iii']
611	            overlapping = overlapping.sort((a, b) => {
612	                return a.length() - b.length();
613	            });
614	            for (let clone of overlapping) {
615	                // don't add if we already have an equivalent sequence
616	                if (inSequences(clone, sequences)) {
617	                    continue;
618	                }
619	                sequences.push(clone);
620	            }
621	            continue;
622	        }
623	        // if we haven't done anything unique
624	        // clean up the patterns
625	        // helps keep patterns smaller
626	        // if str = 'r₨㎧aarss', pattern will be 446 instead of 655
627	        if (i > 0 && added_types.size == 1 && !added_types.has('3')) {
628	            pattern += sequencesToPattern(sequences, false);
629	            let new_seq = new Sequence();
630	            const old_seq = sequences[0];
631	            if (old_seq) {
632	                new_seq.add(old_seq.last());
633	            }
634	            sequences = [new_seq];
635	        }
636	    }
637	    pattern += sequencesToPattern(sequences, true);
638	    return pattern;
639	};
640
641	/**
642	 * A property getter resolving dot-notation
643	 * @param  {Object}  obj     The root object to fetch property on
644	 * @param  {String}  name    The optionally dotted property name to fetch
645	 * @return {Object}          The resolved property value
646	 */
647	const getAttr = (obj, name) => {
648	    if (!obj)
649	        return;
650	    return obj[name];
651	};
652	/**
653	 * A property getter resolving dot-notation
654	 * @param  {Object}  obj     The root object to fetch property on
655	 * @param  {String}  name    The optionally dotted property name to fetch
656	 * @return {Object}          The resolved property value
657	 */
658	const getAttrNesting = (obj, name) => {
659	    if (!obj)
660	        return;
661	    var part, names = name.split(".");
662	    while ((part = names.shift()) && (obj = obj[part]))
663	        ;
664	    return obj;
665	};
666	/**
667	 * Calculates how close of a match the
668	 * given value is against a search token.
669	 *
670	 */
671	const scoreValue = (value, token, weight) => {
672	    var score, pos;
673	    if (!value)
674	        return 0;
675	    value = value + '';
676	    if (token.regex == null)
677	        return 0;
678	    pos = value.search(token.regex);
679	    if (pos === -1)
680	        return 0;
681	    score = token.string.length / value.length;
682	    if (pos === 0)
683	        score += 0.5;
684	    return score * weight;
685	};
686	/**
687	 * Cast object property to an array if it exists and has a value
688	 *
689	 */
690	const propToArray = (obj, key) => {
691	    var value = obj[key];
692	    if (typeof value == 'function')
693	        return value;
694	    if (value && !Array.isArray(value)) {
695	        obj[key] = [value];
696	    }
697	};
698	/**
699	 * Iterates over arrays and hashes.
700	 *
701	 * ```
702	 * iterate(this.items, function(item, id) {
703	 *    // invoked for each item
704	 * });
705	 * ```
706	 *
707	 */
708	const iterate$1 = (object, callback) => {
709	    if (Array.isArray(object)) {
710	        object.forEach(callback);
711	    }
712	    else {
713	        for (var key in object) {
714	            if (object.hasOwnProperty(key)) {
715	                callback(object[key], key);
716	            }
717	        }
718	    }
719	};
720	const cmp = (a, b) => {
721	    if (typeof a === 'number' && typeof b === 'number') {
722	        return a > b ? 1 : (a < b ? -1 : 0);
723	    }
724	    a = asciifold(a + '').toLowerCase();
725	    b = asciifold(b + '').toLowerCase();
726	    if (a > b)
727	        return 1;
728	    if (b > a)
729	        return -1;
730	    return 0;
731	};
732
733	/**
734	 * sifter.js
735	 * Copyright (c) 2013–2020 Brian Reavis & contributors
736	 *
737	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
738	 * file except in compliance with the License. You may obtain a copy of the License at:
739	 * http://www.apache.org/licenses/LICENSE-2.0
740	 *
741	 * Unless required by applicable law or agreed to in writing, software distributed under
742	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
743	 * ANY KIND, either express or implied. See the License for the specific language
744	 * governing permissions and limitations under the License.
745	 *
746	 * @author Brian Reavis <[email protected]>
747	 */
748	class Sifter {
749	    items; // []|{};
750	    settings;
751	    /**
752	     * Textually searches arrays and hashes of objects
753	     * by property (or multiple properties). Designed
754	     * specifically for autocomplete.
755	     *
756	     */
757	    constructor(items, settings) {
758	        this.items = items;
759	        this.settings = settings || { diacritics: true };
760	    }
761	    ;
762	    /**
763	     * Splits a search string into an array of individual
764	     * regexps to be used to match results.
765	     *
766	     */
767	    tokenize(query, respect_word_boundaries, weights) {
768	        if (!query || !query.length)
769	            return [];
770	        const tokens = [];
771	        const words = query.split(/\s+/);
772	        var field_regex;
773	        if (weights) {
774	            field_regex = new RegExp('^(' + Object.keys(weights).map(escape_regex).join('|') + ')\:(.*)$');
775	        }
776	        words.forEach((word) => {
777	            let field_match;
778	            let field = null;
779	            let regex = null;
780	            // look for "field:query" tokens
781	            if (field_regex && (field_match = word.match(field_regex))) {
782	                field = field_match[1];
783	                word = field_match[2];
784	            }
785	            if (word.length > 0) {
786	                if (this.settings.diacritics) {
787	                    regex = getPattern(word) || null;
788	                }
789	                else {
790	                    regex = escape_regex(word);
791	                }
792	                if (regex && respect_word_boundaries)
793	                    regex = "\\b" + regex;
794	            }
795	            tokens.push({
796	                string: word,
797	                regex: regex ? new RegExp(regex, 'iu') : null,
798	                field: field,
799	            });
800	        });
801	        return tokens;
802	    }
803	    ;
804	    /**
805	     * Returns a function to be used to score individual results.
806	     *
807	     * Good matches will have a higher score than poor matches.
808	     * If an item is not a match, 0 will be returned by the function.
809	     *
810	     * @returns {T.ScoreFn}
811	     */
812	    getScoreFunction(query, options) {
813	        var search = this.prepareSearch(query, options);
814	        return this._getScoreFunction(search);
815	    }
816	    /**
817	     * @returns {T.ScoreFn}
818	     *
819	     */
820	    _getScoreFunction(search) {
821	        const tokens = search.tokens, token_count = tokens.length;
822	        if (!token_count) {
823	            return function () { return 0; };
824	        }
825	        const fields = search.options.fields, weights = search.weights, field_count = fields.length, getAttrFn = search.getAttrFn;
826	        if (!field_count) {
827	            return function () { return 1; };
828	        }
829	        /**
830	         * Calculates the score of an object
831	         * against the search query.
832	         *
833	         */
834	        const scoreObject = (function () {
835	            if (field_count === 1) {
836	                return function (token, data) {
837	                    const field = fields[0].field;
838	                    return scoreValue(getAttrFn(data, field), token, weights[field] || 1);
839	                };
840	            }
841	            return function (token, data) {
842	                var sum = 0;
843	                // is the token specific to a field?
844	                if (token.field) {
845	                    const value = getAttrFn(data, token.field);
846	                    if (!token.regex && value) {
847	                        sum += (1 / field_count);
848	                    }
849	                    else {
850	                        sum += scoreValue(value, token, 1);
851	                    }
852	                }
853	                else {
854	                    iterate$1(weights, (weight, field) => {
855	                        sum += scoreValue(getAttrFn(data, field), token, weight);
856	                    });
857	                }
858	                return sum / field_count;
859	            };
860	        })();
861	        if (token_count === 1) {
862	            return function (data) {
863	                return scoreObject(tokens[0], data);
864	            };
865	        }
866	        if (search.options.conjunction === 'and') {
867	            return function (data) {
868	                var score, sum = 0;
869	                for (let token of tokens) {
870	                    score = scoreObject(token, data);
871	                    if (score <= 0)
872	                        return 0;
873	                    sum += score;
874	                }
875	                return sum / token_count;
876	            };
877	        }
878	        else {
879	            return function (data) {
880	                var sum = 0;
881	                iterate$1(tokens, (token) => {
882	                    sum += scoreObject(token, data);
883	                });
884	                return sum / token_count;
885	            };
886	        }
887	    }
888	    ;
889	    /**
890	     * Returns a function that can be used to compare two
891	     * results, for sorting purposes. If no sorting should
892	     * be performed, `null` will be returned.
893	     *
894	     * @return function(a,b)
895	     */
896	    getSortFunction(query, options) {
897	        var search = this.prepareSearch(query, options);
898	        return this._getSortFunction(search);
899	    }
900	    _getSortFunction(search) {
901	        var implicit_score, sort_flds = [];
902	        const self = this, options = search.options, sort = (!search.query && options.sort_empty) ? options.sort_empty : options.sort;
903	        if (typeof sort == 'function') {
904	            return sort.bind(this);
905	        }
906	        /**
907	         * Fetches the specified sort field value
908	         * from a search result item.
909	         *
910	         */
911	        const get_field = function (name, result) {
912	            if (name === '$score')
913	                return result.score;
914	            return search.getAttrFn(self.items[result.id], name);
915	        };
916	        // parse options
917	        if (sort) {
918	            for (let s of sort) {
919	                if (search.query || s.field !== '$score') {
920	                    sort_flds.push(s);
921	                }
922	            }
923	        }
924	        // the "$score" field is implied to be the primary
925	        // sort field, unless it's manually specified
926	        if (search.query) {
927	            implicit_score = true;
928	            for (let fld of sort_flds) {
929	                if (fld.field === '$score') {
930	                    implicit_score = false;
931	                    break;
932	                }
933	            }
934	            if (implicit_score) {
935	                sort_flds.unshift({ field: '$score', direction: 'desc' });
936	            }
937	            // without a search.query, all items will have the same score
938	        }
939	        else {
940	            sort_flds = sort_flds.filter((fld) => fld.field !== '$score');
941	        }
942	        // build function
943	        const sort_flds_count = sort_flds.length;
944	        if (!sort_flds_count) {
945	            return null;
946	        }
947	        return function (a, b) {
948	            var result, field;
949	            for (let sort_fld of sort_flds) {
950	                field = sort_fld.field;
951	                let multiplier = sort_fld.direction === 'desc' ? -1 : 1;
952	                result = multiplier * cmp(get_field(field, a), get_field(field, b));
953	                if (result)
954	                    return result;
955	            }
956	            return 0;
957	        };
958	    }
959	    ;
960	    /**
961	     * Parses a search query and returns an object
962	     * with tokens and fields ready to be populated
963	     * with results.
964	     *
965	     */
966	    prepareSearch(query, optsUser) {
967	        const weights = {};
968	        var options = Object.assign({}, optsUser);
969	        propToArray(options, 'sort');
970	        propToArray(options, 'sort_empty');
971	        // convert fields to new format
972	        if (options.fields) {
973	            propToArray(options, 'fields');
974	            const fields = [];
975	            options.fields.forEach((field) => {
976	                if (typeof field == 'string') {
977	                    field = { field: field, weight: 1 };
978	                }
979	                fields.push(field);
980	                weights[field.field] = ('weight' in field) ? field.weight : 1;
981	            });
982	            options.fields = fields;
983	        }
984	        return {
985	            options: options,
986	            query: query.toLowerCase().trim(),
987	            tokens: this.tokenize(query, options.respect_word_boundaries, weights),
988	            total: 0,
989	            items: [],
990	            weights: weights,
991	            getAttrFn: (options.nesting) ? getAttrNesting : getAttr,
992	        };
993	    }
994	    ;
995	    /**
996	     * Searches through all items and returns a sorted array of matches.
997	     *
998	     */
999	    search(query, options) {
1000	        var self = this, score, search;
1001	        search = this.prepareSearch(query, options);
1002	        options = search.options;
1003	        query = search.query;
1004	        // generate result scoring function
1005	        const fn_score = options.score || self._getScoreFunction(search);
1006	        // perform search and sort
1007	        if (query.length) {
1008	            iterate$1(self.items, (item, id) => {
1009	                score = fn_score(item);
1010	                if (options.filter === false || score > 0) {
1011	                    search.items.push({ 'score': score, 'id': id });
1012	                }
1013	            });
1014	        }
1015	        else {
1016	            iterate$1(self.items, (_, id) => {
1017	                search.items.push({ 'score': 1, 'id': id });
1018	            });
1019	        }
1020	        const fn_sort = self._getSortFunction(search);
1021	        if (fn_sort)
1022	            search.items.sort(fn_sort);
1023	        // apply limits
1024	        search.total = search.items.length;
1025	        if (typeof options.limit === 'number') {
1026	            search.items = search.items.slice(0, options.limit);
1027	        }
1028	        return search;
1029	    }
1030	    ;
1031	}
1032
1033	/**
1034	 * Converts a scalar to its best string representation
1035	 * for hash keys and HTML attribute values.
1036	 *
1037	 * Transformations:
1038	 *   'str'     -> 'str'
1039	 *   null      -> ''
1040	 *   undefined -> ''
1041	 *   true      -> '1'
1042	 *   false     -> '0'
1043	 *   0         -> '0'
1044	 *   1         -> '1'
1045	 *
1046	 */
1047	const hash_key = value => {
1048	  if (typeof value === 'undefined' || value === null) return null;
1049	  return get_hash(value);
1050	};
1051	const get_hash = value => {
1052	  if (typeof value === 'boolean') return value ? '1' : '0';
1053	  return value + '';
1054	};
1055
1056	/**
1057	 * Escapes a string for use within HTML.
1058	 *
1059	 */
1060	const escape_html = str => {
1061	  return (str + '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
1062	};
1063
1064	/**
1065	 * use setTimeout if timeout > 0 
1066	 */
1067	const timeout = (fn, timeout) => {
1068	  if (timeout > 0) {
1069	    return window.setTimeout(fn, timeout);
1070	  }
1071	  fn.call(null);
1072	  return null;
1073	};
1074
1075	/**
1076	 * Debounce the user provided load function
1077	 *
1078	 */
1079	const loadDebounce = (fn, delay) => {
1080	  var timeout;
1081	  return function (value, callback) {
1082	    var self = this;
1083	    if (timeout) {
1084	      self.loading = Math.max(self.loading - 1, 0);
1085	      clearTimeout(timeout);
1086	    }
1087	    timeout = setTimeout(function () {
1088	      timeout = null;
1089	      self.loadedSearches[value] = true;
1090	      fn.call(self, value, callback);
1091	    }, delay);
1092	  };
1093	};
1094
1095	/**
1096	 * Debounce all fired events types listed in `types`
1097	 * while executing the provided `fn`.
1098	 *
1099	 */
1100	const debounce_events = (self, types, fn) => {
1101	  var type;
1102	  var trigger = self.trigger;
1103	  var event_args = {};
1104
1105	  // override trigger method
1106	  self.trigger = function () {
1107	    var type = arguments[0];
1108	    if (types.indexOf(type) !== -1) {
1109	      event_args[type] = arguments;
1110	    } else {
1111	      return trigger.apply(self, arguments);
1112	    }
1113	  };
1114
1115	  // invoke provided function
1116	  fn.apply(self, []);
1117	  self.trigger = trigger;
1118
1119	  // trigger queued events
1120	  for (type of types) {
1121	    if (type in event_args) {
1122	      trigger.apply(self, event_args[type]);
1123	    }
1124	  }
1125	};
1126
1127	/**
1128	 * Determines the current selection within a text input control.
1129	 * Returns an object containing:
1130	 *   - start
1131	 *   - length
1132	 *
1133	 * Note: "selectionStart, selectionEnd ... apply only to inputs of types text, search, URL, tel and password"
1134	 * 	- https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange
1135	 */
1136	const getSelection = input => {
1137	  return {
1138	    start: input.selectionStart || 0,
1139	    length: (input.selectionEnd || 0) - (input.selectionStart || 0)
1140	  };
1141	};
1142
1143	/**
1144	 * Prevent default
1145	 *
1146	 */
1147	const preventDefault = (evt, stop = false) => {
1148	  if (evt) {
1149	    evt.preventDefault();
1150	    if (stop) {
1151	      evt.stopPropagation();
1152	    }
1153	  }
1154	};
1155
1156	/**
1157	 * Add event helper
1158	 *
1159	 */
1160	const addEvent = (target, type, callback, options) => {
1161	  target.addEventListener(type, callback, options);
1162	};
1163
1164	/**
1165	 * Return true if the requested key is down
1166	 * Will return false if more than one control character is pressed ( when [ctrl+shift+a] != [ctrl+a] )
1167	 * The current evt may not always set ( eg calling advanceSelection() )
1168	 *
1169	 */
1170	const isKeyDown = (key_name, evt) => {
1171	  if (!evt) {
1172	    return false;
1173	  }
1174	  if (!evt[key_name]) {
1175	    return false;
1176	  }
1177	  var count = (evt.altKey ? 1 : 0) + (evt.ctrlKey ? 1 : 0) + (evt.shiftKey ? 1 : 0) + (evt.metaKey ? 1 : 0);
1178	  if (count === 1) {
1179	    return true;
1180	  }
1181	  return false;
1182	};
1183
1184	/**
1185	 * Get the id of an element
1186	 * If the id attribute is not set, set the attribute with the given id
1187	 *
1188	 */
1189	const getId = (el, id) => {
1190	  const existing_id = el.getAttribute('id');
1191	  if (existing_id) {
1192	    return existing_id;
1193	  }
1194	  el.setAttribute('id', id);
1195	  return id;
1196	};
1197
1198	/**
1199	 * Returns a string with backslashes added before characters that need to be escaped.
1200	 */
1201	const addSlashes = str => {
1202	  return str.replace(/[\\"']/g, '\\$&');
1203	};
1204
1205	/**
1206	 *
1207	 */
1208	const append = (parent, node) => {
1209	  if (node) parent.append(node);
1210	};
1211
1212	/**
1213	 * Iterates over arrays and hashes.
1214	 *
1215	 * ```
1216	 * iterate(this.items, function(item, id) {
1217	 *    // invoked for each item
1218	 * });
1219	 * ```
1220	 *
1221	 */
1222	const iterate = (object, callback) => {
1223	  if (Array.isArray(object)) {
1224	    object.forEach(callback);
1225	  } else {
1226	    for (var key in object) {
1227	      if (object.hasOwnProperty(key)) {
1228	        callback(object[key], key);
1229	      }
1230	    }
1231	  }
1232	};
1233
1234	/**
1235	 * Return a dom element from either a dom query string, jQuery object, a dom element or html string
1236	 * https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518
1237	 *
1238	 * param query should be {}
1239	 */
1240	const getDom = query => {
1241	  if (query.jquery) {
1242	    return query[0];
1243	  }
1244	  if (query instanceof HTMLElement) {
1245	    return query;
1246	  }
1247	  if (isHtmlString(query)) {
1248	    var tpl = document.createElement('template');
1249	    tpl.innerHTML = query.trim(); // Never return a text node of whitespace as the result
1250	    return tpl.content.firstChild;
1251	  }
1252	  return document.querySelector(query);
1253	};
1254	const isHtmlString = arg => {
1255	  if (typeof arg === 'string' && arg.indexOf('<') > -1) {
1256	    return true;
1257	  }
1258	  return false;
1259	};
1260	const escapeQuery = query => {
1261	  return query.replace(/['"\\]/g, '\\$&');
1262	};
1263
1264	/**
1265	 * Dispatch an event
1266	 *
1267	 */
1268	const triggerEvent = (dom_el, event_name) => {
1269	  var event = document.createEvent('HTMLEvents');
1270	  event.initEvent(event_name, true, false);
1271	  dom_el.dispatchEvent(event);
1272	};
1273
1274	/**
1275	 * Apply CSS rules to a dom element
1276	 *
1277	 */
1278	const applyCSS = (dom_el, css) => {
1279	  Object.assign(dom_el.style, css);
1280	};
1281
1282	/**
1283	 * Add css classes
1284	 *
1285	 */
1286	const addClasses = (elmts, ...classes) => {
1287	  var norm_classes = classesArray(classes);
1288	  elmts = castAsArray(elmts);
1289	  elmts.map(el => {
1290	    norm_classes.map(cls => {
1291	      el.classList.add(cls);
1292	    });
1293	  });
1294	};
1295
1296	/**
1297	 * Remove css classes
1298	 *
1299	 */
1300	const removeClasses = (elmts, ...classes) => {
1301	  var norm_classes = classesArray(classes);
1302	  elmts = castAsArray(elmts);
1303	  elmts.map(el => {
1304	    norm_classes.map(cls => {
1305	      el.classList.remove(cls);
1306	    });
1307	  });
1308	};
1309
1310	/**
1311	 * Return arguments
1312	 *
1313	 */
1314	const classesArray = args => {
1315	  var classes = [];
1316	  iterate(args, _classes => {
1317	    if (typeof _classes === 'string') {
1318	      _classes = _classes.trim().split(/[\t\n\f\r\s]/);
1319	    }
1320	    if (Array.isArray(_classes)) {
1321	      classes = classes.concat(_classes);
1322	    }
1323	  });
1324	  return classes.filter(Boolean);
1325	};
1326
1327	/**
1328	 * Create an array from arg if it's not already an array
1329	 *
1330	 */
1331	const castAsArray = arg => {
1332	  if (!Array.isArray(arg)) {
1333	    arg = [arg];
1334	  }
1335	  return arg;
1336	};
1337
1338	/**
1339	 * Get the closest node to the evt.target matching the selector
1340	 * Stops at wrapper
1341	 *
1342	 */
1343	const parentMatch = (target, selector, wrapper) => {
1344	  if (wrapper && !wrapper.contains(target)) {
1345	    return;
1346	  }
1347	  while (target && target.matches) {
1348	    if (target.matches(selector)) {
1349	      return target;
1350	    }
1351	    target = target.parentNode;
1352	  }
1353	};
1354
1355	/**
1356	 * Get the first or last item from an array
1357	 *
1358	 * > 0 - right (last)
1359	 * <= 0 - left (first)
1360	 *
1361	 */
1362	const getTail = (list, direction = 0) => {
1363	  if (direction > 0) {
1364	    return list[list.length - 1];
1365	  }
1366	  return list[0];
1367	};
1368
1369	/**
1370	 * Return true if an object is empty
1371	 *
1372	 */
1373	const isEmptyObject = obj => {
1374	  return Object.keys(obj).length === 0;
1375	};
1376
1377	/**
1378	 * Get the index of an element amongst sibling nodes of the same type
1379	 *
1380	 */
1381	const nodeIndex = (el, amongst) => {
1382	  if (!el) return -1;
1383	  amongst = amongst || el.nodeName;
1384	  var i = 0;
1385	  while (el = el.previousElementSibling) {
1386	    if (el.matches(amongst)) {
1387	      i++;
1388	    }
1389	  }
1390	  return i;
1391	};
1392
1393	/**
1394	 * Set attributes of an element
1395	 *
1396	 */
1397	const setAttr = (el, attrs) => {
1398	  iterate(attrs, (val, attr) => {
1399	    if (val == null) {
1400	      el.removeAttribute(attr);
1401	    } else {
1402	      el.setAttribute(attr, '' + val);
1403	    }
1404	  });
1405	};
1406
1407	/**
1408	 * Replace a node
1409	 */
1410	const replaceNode = (existing, replacement) => {
1411	  if (existing.parentNode) existing.parentNode.replaceChild(replacement, existing);
1412	};
1413
1414	/**
1415	 * highlight v3 | MIT license | Johann Burkard <[email protected]>
1416	 * Highlights arbitrary terms in a node.
1417	 *
1418	 * - Modified by Marshal <[email protected]> 2011-6-24 (added regex)
1419	 * - Modified by Brian Reavis <[email protected]> 2012-8-27 (cleanup)
1420	 */
1421
1422	const highlight = (element, regex) => {
1423	  if (regex === null) return;
1424
1425	  // convet string to regex
1426	  if (typeof regex === 'string') {
1427	    if (!regex.length) return;
1428	    regex = new RegExp(regex, 'i');
1429	  }
1430
1431	  // Wrap matching part of text node with highlighting <span>, e.g.
1432	  // Soccer  ->  <span class="highlight">Soc</span>cer  for regex = /soc/i
1433	  const highlightText = node => {
1434	    var match = node.data.match(regex);
1435	    if (match && node.data.length > 0) {
1436	      var spannode = document.createElement('span');
1437	      spannode.className = 'highlight';
1438	      var middlebit = node.splitText(match.index);
1439	      middlebit.splitText(match[0].length);
1440	      var middleclone = middlebit.cloneNode(true);
1441	      spannode.appendChild(middleclone);
1442	      replaceNode(middlebit, spannode);
1443	      return 1;
1444	    }
1445	    return 0;
1446	  };
1447
1448	  // Recurse element node, looking for child text nodes to highlight, unless element
1449	  // is childless, <script>, <style>, or already highlighted: <span class="hightlight">
1450	  const highlightChildren = node => {
1451	    if (node.nodeType === 1 && node.childNodes && !/(script|style)/i.test(node.tagName) && (node.className !== 'highlight' || node.tagName !== 'SPAN')) {
1452	      Array.from(node.childNodes).forEach(element => {
1453	        highlightRecursive(element);
1454	      });
1455	    }
1456	  };
1457	  const highlightRecursive = node => {
1458	    if (node.nodeType === 3) {
1459	      return highlightText(node);
1460	    }
1461	    highlightChildren(node);
1462	    return 0;
1463	  };
1464	  highlightRecursive(element);
1465	};
1466
1467	/**
1468	 * removeHighlight fn copied from highlight v5 and
1469	 * edited to remove with(), pass js strict mode, and use without jquery
1470	 */
1471	const removeHighlight = el => {
1472	  var elements = el.querySelectorAll("span.highlight");
1473	  Array.prototype.forEach.call(elements, function (el) {
1474	    var parent = el.parentNode;
1475	    parent.replaceChild(el.firstChild, el);
1476	    parent.normalize();
1477	  });
1478	};
1479
1480	const KEY_A = 65;
1481	const KEY_RETURN = 13;
1482	const KEY_ESC = 27;
1483	const KEY_LEFT = 37;
1484	const KEY_UP = 38;
1485	const KEY_RIGHT = 39;
1486	const KEY_DOWN = 40;
1487	const KEY_BACKSPACE = 8;
1488	const KEY_DELETE = 46;
1489	const KEY_TAB = 9;
1490	const IS_MAC = typeof navigator === 'undefined' ? false : /Mac/.test(navigator.userAgent);
1491	const KEY_SHORTCUT = IS_MAC ? 'metaKey' : 'ctrlKey'; // ctrl key or apple key for ma
1492
1493	var defaults = {
1494	  options: [],
1495	  optgroups: [],
1496	  plugins: [],
1497	  delimiter: ',',
1498	  splitOn: null,
1499	  // regexp or string for splitting up values from a paste command
1500	  persist: true,
1501	  diacritics: true,
1502	  create: null,
1503	  createOnBlur: false,
1504	  createFilter: null,
1505	  clearAfterSelect: false,
1506	  highlight: true,
1507	  openOnFocus: true,
1508	  shouldOpen: null,
1509	  maxOptions: 50,
1510	  maxItems: null,
1511	  hideSelected: null,
1512	  duplicates: false,
1513	  addPrecedence: false,
1514	  selectOnTab: false,
1515	  preload: null,
1516	  allowEmptyOption: false,
1517	  //closeAfterSelect: false,
1518	  refreshThrottle: 300,
1519	  loadThrottle: 300,
1520	  loadingClass: 'loading',
1521	  dataAttr: null,
1522	  //'data-data',
1523	  optgroupField: 'optgroup',
1524	  valueField: 'value',
1525	  labelField: 'text',
1526	  disabledField: 'disabled',
1527	  optgroupLabelField: 'label',
1528	  optgroupValueField: 'value',
1529	  lockOptgroupOrder: false,
1530	  sortField: '$order',
1531	  searchField: ['text'],
1532	  searchConjunction: 'and',
1533	  mode: null,
1534	  wrapperClass: 'ts-wrapper',
1535	  controlClass: 'ts-control',
1536	  dropdownClass: 'ts-dropdown',
1537	  dropdownContentClass: 'ts-dropdown-content',
1538	  itemClass: 'item',
1539	  optionClass: 'option',
1540	  dropdownParent: null,
1541	  controlInput: '<input type="text" autocomplete="off" size="1" />',
1542	  copyClassesToDropdown: false,
1543	  placeholder: null,
1544	  hidePlaceholder: null,
1545	  shouldLoad: function (query) {
1546	    return query.length > 0;
1547	  },
1548	  /*
1549	  load                 : null, // function(query, callback) { ... }
1550	  score                : null, // function(search) { ... }
1551	  onInitialize         : null, // function() { ... }
1552	  onChange             : null, // function(value) { ... }
1553	  onItemAdd            : null, // function(value, $item) { ... }
1554	  onItemRemove         : null, // function(value) { ... }
1555	  onClear              : null, // function() { ... }
1556	  onOptionAdd          : null, // function(value, data) { ... }
1557	  onOptionRemove       : null, // function(value) { ... }
1558	  onOptionClear        : null, // function() { ... }
1559	  onOptionGroupAdd     : null, // function(id, data) { ... }
1560	  onOptionGroupRemove  : null, // function(id) { ... }
1561	  onOptionGroupClear   : null, // function() { ... }
1562	  onDropdownOpen       : null, // function(dropdown) { ... }
1563	  onDropdownClose      : null, // function(dropdown) { ... }
1564	  onType               : null, // function(str) { ... }
1565	  onDelete             : null, // function(values) { ... }
1566	  */
1567
1568	  render: {
1569	    /*
1570	    item: null,
1571	    optgroup: null,
1572	    optgroup_header: null,
1573	    option: null,
1574	    option_create: null
1575	    */
1576	  }
1577	};
1578
1579	function getSettings(input, settings_user) {
1580	  var settings = Object.assign({}, defaults, settings_user);
1581	  var attr_data = settings.dataAttr;
1582	  var field_label = settings.labelField;
1583	  var field_value = settings.valueField;
1584	  var field_disabled = settings.disabledField;
1585	  var field_optgroup = settings.optgroupField;
1586	  var field_optgroup_label = settings.optgroupLabelField;
1587	  var field_optgroup_value = settings.optgroupValueField;
1588	  var tag_name = input.tagName.toLowerCase();
1589	  var placeholder = input.getAttribute('placeholder') || input.getAttribute('data-placeholder');
1590	  if (!placeholder && !settings.allowEmptyOption) {
1591	    let option = input.querySelector('option[value=""]');
1592	    if (option) {
1593	      placeholder = option.textContent;
1594	    }
1595	  }
1596	  var settings_element = {
1597	    placeholder: placeholder,
1598	    options: [],
1599	    optgroups: [],
1600	    items: [],
1601	    maxItems: null
1602	  };
1603
1604	  /**
1605	   * Initialize from a <select> element.
1606	   *
1607	   */
1608	  var init_select = () => {
1609	    var tagName;
1610	    var options = settings_element.options;
1611	    var optionsMap = {};
1612	    var group_count = 1;
1613	    let $order = 0;
1614	    var readData = el => {
1615	      var data = Object.assign({}, el.dataset); // get plain object from DOMStringMap
1616	      var json = attr_data && data[attr_data];
1617	      if (typeof json === 'string' && json.length) {
1618	        data = Object.assign(data, JSON.parse(json));
1619	      }
1620	      return data;
1621	    };
1622	    var addOption = (option, group) => {
1623	      var value = hash_key(option.value);
1624	      if (value == null) return;
1625	      if (!value && !settings.allowEmptyOption) return;
1626
1627	      // if the option already exists, it's probably been
1628	      // duplicated in another optgroup. in this case, push
1629	      // the current group to the "optgroup" property on the
1630	      // existing option so that it's rendered in both places.
1631	      if (optionsMap.hasOwnProperty(value)) {
1632	        if (group) {
1633	          var arr = optionsMap[value][field_optgroup];
1634	          if (!arr) {
1635	            optionsMap[value][field_optgroup] = group;
1636	          } else if (!Array.isArray(arr)) {
1637	            optionsMap[value][field_optgroup] = [arr, group];
1638	          } else {
1639	            arr.push(group);
1640	          }
1641	        }
1642	      } else {
1643	        var option_data = readData(option);
1644	        option_data[field_label] = option_data[field_label] || option.textContent;
1645	        option_data[field_value] = option_data[field_value] || value;
1646	        option_data[field_disabled] = option_data[field_disabled] || option.disabled;
1647	        option_data[field_optgroup] = option_data[field_optgroup] || group;
1648	        option_data.$option = option;
1649	        option_data.$order = option_data.$order || ++$order;
1650	        optionsMap[value] = option_data;
1651	        options.push(option_data);
1652	      }
1653	      if (option.selected) {
1654	        settings_element.items.push(value);
1655	      }
1656	    };
1657	    var addGroup = optgroup => {
1658	      var id, optgroup_data;
1659	      optgroup_data = readData(optgroup);
1660	      optgroup_data[field_optgroup_label] = optgroup_data[field_optgroup_label] || optgroup.getAttribute('label') || '';
1661	      optgroup_data[field_optgroup_value] = optgroup_data[field_optgroup_value] || group_count++;
1662	      optgroup_data[field_disabled] = optgroup_data[field_disabled] || optgroup.disabled;
1663	      optgroup_data.$order = optgroup_data.$order || ++$order;
1664	      settings_element.optgroups.push(optgroup_data);
1665	      id = optgroup_data[field_optgroup_value];
1666	      iterate(optgroup.children, option => {
1667	        addOption(option, id);
1668	      });
1669	    };
1670	    settings_element.maxItems = input.hasAttribute('multiple') ? null : 1;
1671	    iterate(input.children, child => {
1672	      tagName = child.tagName.toLowerCase();
1673	      if (tagName === 'optgroup') {
1674	        addGroup(child);
1675	      } else if (tagName === 'option') {
1676	        addOption(child);
1677	      }
1678	    });
1679	  };
1680
1681	  /**
1682	   * Initialize from a <input type="text"> element.
1683	   *
1684	   */
1685	  var init_textbox = () => {
1686	    const data_raw = input.getAttribute(attr_data);
1687	    if (!data_raw) {
1688	      var _input$value$trim, _input$value;
1689	      var value = (_input$value$trim = input == null || (_input$value = input.value) == null ? void 0 : _input$value.trim()) != null ? _input$value$trim : '';
1690	      if (!settings.allowEmptyOption && !value.length) return;
1691	      const values = value.split(settings.delimiter);
1692	      iterate(values, value => {
1693	        const option = {};
1694	        option[field_label] = value;
1695	        option[field_value] = value;
1696	        settings_element.options.push(option);
1697	      });
1698	      settings_element.items = values;
1699	    } else {
1700	      settings_element.options = JSON.parse(data_raw);
1701	      iterate(settings_element.options, opt => {
1702	        settings_element.items.push(opt[field_value]);
1703	      });
1704	    }
1705	  };
1706	  if (tag_name === 'select') {
1707	    init_select();
1708	  } else {
1709	    init_textbox();
1710	  }
1711	  return Object.assign({}, defaults, settings_element, settings_user);
1712	}
1713
1714	var instance_i = 0;
1715	class TomSelect extends MicroPlugin(MicroEvent) {
1716	  constructor(input_arg, user_settings) {
1717	    super();
1718	    this.order = 0;
1719	    this.isOpen = false;
1720	    this.isDisabled = false;
1721	    this.isReadOnly = false;
1722	    this.isInvalid = false;
1723	    // @deprecated 1.8
1724	    this.isValid = true;
1725	    this.isLocked = false;
1726	    this.isFocused = false;
1727	    this.isInputHidden = false;
1728	    this.isSetup = false;
1729	    this.isDropdownContentStale = true;
1730	    this.ignoreFocus = false;
1731	    this.ignoreHover = false;
1732	    this.hasOptions = false;
1733	    this.lastValue = '';
1734	    this.caretPos = 0;
1735	    this.loading = 0;
1736	    this.loadedSearches = {};
1737	    this.activeOption = null;
1738	    this.activeItems = [];
1739	    this.optgroups = {};
1740	    this.options = {};
1741	    this.userOptions = {};
1742	    this.items = [];
1743	    this.refreshTimeout = null;
1744	    instance_i++;
1745	    var dir;
1746	    var input = getDom(input_arg);
1747	    if (input.tomselect) {
1748	      throw new Error('Tom Select already initialized on this element');
1749	    }
1750	    input.tomselect = this;
1751
1752	    // detect rtl environment
1753	    var computedStyle = window.getComputedStyle && window.getComputedStyle(input, null);
1754	    dir = computedStyle.getPropertyValue('direction');
1755
1756	    // setup default state
1757	    const settings = getSettings(input, user_settings);
1758	    this.settings = settings;
1759	    this.input = input;
1760	    this.tabIndex = input.tabIndex || 0;
1761	    this.is_select_tag = input.tagName.toLowerCase() === 'select';
1762	    this.rtl = /rtl/i.test(dir);
1763	    this.inputId = getId(input, 'tomselect-' + instance_i);
1764	    this.isRequired = input.required;
1765
1766	    // search system
1767	    this.sifter = new Sifter(this.options, {
1768	      diacritics: settings.diacritics
1769	    });
1770
1771	    // option-dependent defaults
1772	    settings.mode = settings.mode || (settings.maxItems === 1 ? 'single' : 'multi');
1773	    if (typeof settings.hideSelected !== 'boolean') {
1774	      settings.hideSelected = settings.mode === 'multi';
1775	    }
1776	    if (typeof settings.hidePlaceholder !== 'boolean') {
1777	      settings.hidePlaceholder = settings.mode !== 'multi';
1778	    }
1779
1780	    // set up createFilter callback
1781	    var filter = settings.createFilter;
1782	    if (typeof filter !== 'function') {
1783	      if (typeof filter === 'string') {
1784	        filter = new RegExp(filter);
1785	      }
1786	      if (filter instanceof RegExp) {
1787	        settings.createFilter = input => filter.test(input);
1788	      } else {
1789	        settings.createFilter = value => {
1790	          return this.settings.duplicates || !this.options[value];
1791	        };
1792	      }
1793	    }
1794	    this.initializePlugins(settings.plugins);
1795	    this.setupCallbacks();
1796	    this.setupTemplates();
1797
1798	    // Create all elements
1799	    const wrapper = getDom('<div>');
1800	    const control = getDom('<div>');
1801	    const dropdown = this._render('dropdown');
1802	    const dropdown_content = getDom(`<div role="listbox" tabindex="-1">`);
1803	    const classes = this.input.getAttribute('class') || '';
1804	    const inputMode = settings.mode;
1805	    var control_input;
1806	    addClasses(wrapper, settings.wrapperClass, classes, inputMode);
1807	    addClasses(control, settings.controlClass);
1808	    append(wrapper, control);
1809	    addClasses(dropdown, settings.dropdownClass, inputMode);
1810	    if (settings.copyClassesToDropdown) {
1811	      addClasses(dropdown, classes);
1812	    }
1813	    addClasses(dropdown_content, settings.dropdownContentClass);
1814	    append(dropdown, dropdown_content);
1815	    getDom(settings.dropdownParent || wrapper).appendChild(dropdown);
1816
1817	    // default controlInput
1818	    if (isHtmlString(settings.controlInput)) {
1819	      control_input = getDom(settings.controlInput);
1820
1821	      // set attributes
1822	      var attrs = ['autocorrect', 'autocapitalize', 'autocomplete', 'spellcheck', 'aria-label'];
1823	      iterate(attrs, attr => {
1824	        if (input.getAttribute(attr)) {
1825	          setAttr(control_input, {
1826	            [attr]: input.getAttribute(attr)
1827	          });
1828	        }
1829	      });
1830	      control_input.tabIndex = -1;
1831	      control.appendChild(control_input);
1832	      this.focus_node = control_input;
1833
1834	      // dom element
1835	    } else if (settings.controlInput) {
1836	      control_input = getDom(settings.controlInput);
1837	      this.focus_node = control_input;
1838	    } else {
1839	      control_input = getDom('<input/>');
1840	      this.focus_node = control;
1841	    }
1842	    this.wrapper = wrapper;
1843	    this.dropdown = dropdown;
1844	    this.dropdown_content = dropdown_content;
1845	    this.control = control;
1846	    this.control_input = control_input;
1847	    this.setup();
1848	  }
1849
1850	  /**
1851	   * set up event bindings.
1852	   *
1853	   */
1854	  setup() {
1855	    const self = this;
1856	    const settings = self.settings;
1857	    const control_input = self.control_input;
1858	    const dropdown = self.dropdown;
1859	    const dropdown_content = self.dropdown_content;
1860	    const wrapper = self.wrapper;
1861	    const control = self.control;
1862	    const input = self.input;
1863	    const focus_node = self.focus_node;
1864	    const passive_event = {
1865	      passive: true
1866	    };
1867	    const listboxId = self.inputId + '-ts-dropdown';
1868	    setAttr(dropdown_content, {
1869	      id: listboxId
1870	    });
1871	    setAttr(focus_node, {
1872	      role: 'combobox',
1873	      'aria-haspopup': 'listbox',
1874	      'aria-expanded': 'false',
1875	      'aria-controls': listboxId
1876	    });
1877	    const control_id = getId(focus_node, self.inputId + '-ts-control');
1878	    const query = "label[for='" + escapeQuery(self.inputId) + "']";
1879	    const label = document.querySelector(query);
1880	    const label_click = self.focus.bind(self);
1881	    if (label) {
1882	      addEvent(label, 'click', label_click);
1883	      setAttr(label, {
1884	        for: control_id
1885	      });
1886	      const label_id = getId(label, self.inputId + '-ts-label');
1887	      setAttr(focus_node, {
1888	        'aria-labelledby': label_id
1889	      });
1890	      setAttr(dropdown_content, {
1891	        'aria-labelledby': label_id
1892	      });
1893	    }
1894	    wrapper.style.width = input.style.width;
1895	    wrapper.style.minWidth = input.style.minWidth;
1896	    wrapper.style.maxWidth = input.style.maxWidth;
1897	    if (self.plugins.names.length) {
1898	      const classes_plugins = 'plugin-' + self.plugins.names.join(' plugin-');
1899	      addClasses([wrapper, dropdown], classes_plugins);
1900	    }
1901	    if ((settings.maxItems === null || settings.maxItems > 1) && self.is_select_tag) {
1902	      setAttr(input, {
1903	        multiple: 'multiple'
1904	      });
1905	    }
1906	    if (settings.placeholder) {
1907	      setAttr(control_input, {
1908	        placeholder: settings.placeholder
1909	      });
1910	    }
1911
1912	    // if splitOn was not passed in, construct it from the delimiter to allow pasting universally
1913	    if (!settings.splitOn && settings.delimiter) {
1914	      settings.splitOn = new RegExp('\\s*' + escape_regex(settings.delimiter) + '+\\s*');
1915	    }
1916
1917	    // debounce user defined load() if loadThrottle > 0
1918	    // after initializePlugins() so plugins can create/modify user defined loaders
1919	    if (settings.load && settings.loadThrottle) {
1920	      settings.load = loadDebounce(settings.load, settings.loadThrottle);
1921	    }
1922	    addEvent(dropdown, 'mousemove', () => {
1923	      self.ignoreHover = false;
1924	    });
1925	    addEvent(dropdown, 'mouseenter', e => {
1926	      var target_match = parentMatch(e.target, '[data-selectable]', dropdown);
1927	      if (target_match) self.onOptionHover(e, target_match);
1928	    }, {
1929	      capture: true
1930	    });
1931
1932	    // clicking on an option should select it
1933	    addEvent(dropdown, 'click', evt => {
1934	      const option = parentMatch(evt.target, '[data-selectable]');
1935	      if (option) {
1936	        self.onOptionSelect(evt, option);
1937	        preventDefault(evt, true);
1938	      }
1939	    });
1940	    addEvent(control, 'click', evt => {
1941	      var target_match = parentMatch(evt.target, '[data-ts-item]', control);
1942	      if (target_match && self.onItemSelect(evt, target_match)) {
1943	        preventDefault(evt, true);
1944	        return;
1945	      }
1946
1947	      // retain focus (see control_input mousedown)
1948	      if (control_input.value != '') {
1949	        return;
1950	      }
1951	      self.onClick();
1952	      preventDefault(evt, true);
1953	    });
1954
1955	    // keydown on focus_node for arrow_down/arrow_up
1956	    addEvent(focus_node, 'keydown', e => self.onKeyDown(e));
1957
1958	    // keypress and input/keyup
1959	    addEvent(control_input, 'keypress', e => self.onKeyPress(e));
1960	    addEvent(control_input, 'input', e => self.onInput(e));
1961	    addEvent(focus_node, 'blur', e => self.onBlur(e));
1962	    addEvent(focus_node, 'focus', e => self.onFocus(e));
1963	    addEvent(control_input, 'paste', e => self.onPaste(e));
1964	    const doc_mousedown = evt => {
1965	      // blur if target is outside of this instance
1966	      // dropdown is not always inside wrapper
1967	      const target = evt.composedPath()[0];
1968	      if (!wrapper.contains(target) && !dropdown.contains(target)) {
1969	        if (self.isFocused) {
1970	          self.blur();
1971	        }
1972	        self.inputState();
1973	        return;
1974	      }
1975
1976	      // retain focus by preventing native handling. if the
1977	      // event target is the input it should not be modified.
1978	      // otherwise, text selection within the input won't work.
1979	      // Fixes bug #212 which is no covered by tests
1980	      if (target == control_input && self.isOpen) {
1981	        evt.stopPropagation();
1982
1983	        // clicking anywhere in the control should not blur the control_input (which would close the dropdown)
1984	      } else {
1985	        preventDefault(evt, true);
1986	      }
1987	    };
1988	    const win_scroll = () => {
1989	      if (self.isOpen) {
1990	        self.positionDropdown();
1991	      }
1992	    };
1993	    const input_invalid = () => {
1994	      if (self.isValid) {
1995	        self.isValid = false;
1996	        self.isInvalid = true;
1997	        self.refreshState();
1998	      }
1999	    };
2000	    addEvent(input, 'invalid', input_invalid);
2001	    addEvent(document, 'mousedown', doc_mousedown);
2002	    addEvent(window, 'scroll', win_scroll, passive_event);
2003	    addEvent(window, 'resize', win_scroll, passive_event);
2004	    this._destroy = () => {
2005	      input.removeEventListener('invalid', input_invalid);
2006	      document.removeEventListener('mousedown', doc_mousedown);
2007	      window.removeEventListener('scroll', win_scroll);
2008	      window.removeEventListener('resize', win_scroll);
2009	      if (label) label.removeEventListener('click', label_click);
2010	    };
2011
2012	    // store original html and tab index so that they can be
2013	    // restored when the destroy() method is called.
2014	    this.revertSettings = {
2015	      innerHTML: input.innerHTML,
2016	      tabIndex: input.tabIndex
2017	    };
2018	    input.tabIndex = -1;
2019	    input.insertAdjacentElement('afterend', self.wrapper);
2020	    self.sync(false);
2021	    settings.items = [];
2022	    delete settings.optgroups;
2023	    delete settings.options;
2024	    self.refreshItems();
2025	    self.close(false);
2026	    self.inputState();
2027	    self.isSetup = true;
2028	    self.on('change', this.onChange);
2029	    addClasses(input, 'tomselected', 'ts-hidden-accessible');
2030	    self.trigger('initialize');
2031
2032	    // preload options
2033	    if (settings.preload === true) {
2034	      self.preload();
2035	    }
2036	  }
2037
2038	  /**
2039	   * Register options and optgroups
2040	   *
2041	   */
2042	  setupOptions(options = [], optgroups = []) {
2043	    // build options table
2044	    this.addOptions(options);
2045
2046	    // build optgroup table
2047	    iterate(optgroups, optgroup => {
2048	      this.registerOptionGroup(optgroup);
2049	    });
2050	  }
2051
2052	  /**
2053	   * Sets up default rendering functions.
2054	   */
2055	  setupTemplates() {
2056	    var self = this;
2057	    var field_label = self.settings.labelField;
2058	    var field_optgroup = self.settings.optgroupLabelField;
2059	    var templates = {
2060	      'optgroup': data => {
2061	        let optgroup = document.createElement('div');
2062	        optgroup.className = 'optgroup';
2063	        optgroup.appendChild(data.options);
2064	        return optgroup;
2065	      },
2066	      'optgroup_header': (data, escape) => {
2067	        return '<div class="optgroup-header">' + escape(data[field_optgroup]) + '</div>';
2068	      },
2069	      'option': (data, escape) => {
2070	        return '<div>' + escape(data[field_label]) + '</div>';
2071	      },
vendor: 1,416 bytes, lines 2072-2114
2072	      'item': (data, escape) => {
2073	        return '<div>' + escape(data[field_label]) + '</div>';
2074	      },
2075	      'option_create': (data, escape) => {
2076	        return '<div class="create">Add <strong>' + escape(data.input) + '</strong>&hellip;</div>';
2077	      },
2078	      'no_results': () => {
2079	        return '<div class="no-results">No results found</div>';
2080	      },
2081	      'loading': () => {
2082	        return '<div class="spinner"></div>';
2083	      },
2084	      'not_loading': () => {},
2085	      'dropdown': () => {
2086	        return '<div></div>';
2087	      }
2088	    };
2089	    self.settings.render = Object.assign({}, templates, self.settings.render);
2090	  }
2091
2092	  /**
2093	   * Maps fired events to callbacks provided
2094	   * in the settings used when creating the control.
2095	   */
2096	  setupCallbacks() {
2097	    var key, fn;
2098	    var callbacks = {
2099	      'initialize': 'onInitialize',
2100	      'change': 'onChange',
2101	      'item_add': 'onItemAdd',
2102	      'item_remove': 'onItemRemove',
2103	      'item_select': 'onItemSelect',
2104	      'clear': 'onClear',
2105	      'option_add': 'onOptionAdd',
2106	      'option_remove': 'onOptionRemove',
2107	      'option_clear': 'onOptionClear',
2108	      'optgroup_add': 'onOptionGroupAdd',
2109	      'optgroup_remove': 'onOptionGroupRemove',
2110	      'optgroup_clear': 'onOptionGroupClear',
2111	      'dropdown_open': 'onDropdownOpen',
2112	      'dropdown_close': 'onDropdownClose',
2113	      'type': 'onType',
2114	      'load': 'onLoad',
vendor: 49,433 bytes, lines 2115-3851
2115	      'focus': 'onFocus',
2116	      'blur': 'onBlur'
2117	    };
2118	    for (key in callbacks) {
2119	      fn = this.settings[callbacks[key]];
2120	      if (fn) this.on(key, fn);
2121	    }
2122	  }
2123
2124	  /**
2125	   * Sync the Tom Select instance with the original input or select
2126	   *
2127	   */
2128	  sync(get_settings = true) {
2129	    const self = this;
2130	    const settings = get_settings ? getSettings(self.input, {
2131	      delimiter: self.settings.delimiter,
2132	      allowEmptyOption: self.settings.allowEmptyOption
2133	    }) : self.settings;
2134	    self.setupOptions(settings.options, settings.optgroups);
2135	    self.setValue(settings.items || [], true); // silent prevents recursion
2136
2137	    if (self.input.disabled) {
2138	      self.disable();
2139	    } else if (self.input.readOnly) {
2140	      self.setReadOnly(true);
2141	    } else {
2142	      self.enable(); //sets tabIndex
2143	    }
2144	    self.lastQuery = null; // so updated options will be displayed in dropdown
2145	  }
2146
2147	  /**
2148	   * Triggered when the main control element
2149	   * has a click event.
2150	   *
2151	   */
2152	  onClick() {
2153	    var self = this;
2154	    if (self.activeItems.length > 0) {
2155	      self.clearActiveItems();
2156	      self.focus();
2157	      return;
2158	    }
2159	    if (self.isFocused && self.isOpen) {
2160	      self.blur();
2161	    } else {
2162	      self.focus();
2163	    }
2164	  }
2165
2166	  /**
2167	   * @deprecated v1.7
2168	   *
2169	   */
2170	  onMouseDown() {}
2171
2172	  /**
2173	   * Triggered when the value of the control has been changed.
2174	   * This should propagate the event to the original DOM
2175	   * input / select element.
2176	   */
2177	  onChange() {
2178	    triggerEvent(this.input, 'input');
2179	    triggerEvent(this.input, 'change');
2180	  }
2181
2182	  /**
2183	   * Triggered on <input> paste.
2184	   *
2185	   */
2186	  onPaste(e) {
2187	    var self = this;
2188	    if (self.isInputHidden || self.isLocked) {
2189	      preventDefault(e);
2190	      return;
2191	    }
2192
2193	    // If a regex or string is included, this will split the pasted
2194	    // input and create Items for each separate value
2195	    if (!self.settings.splitOn) {
2196	      return;
2197	    }
2198
2199	    // Wait for pasted text to be recognized in value
2200	    setTimeout(() => {
2201	      var pastedText = self.inputValue();
2202	      if (!pastedText.match(self.settings.splitOn)) {
2203	        return;
2204	      }
2205	      var splitInput = pastedText.trim().split(self.settings.splitOn);
2206	      iterate(splitInput, piece => {
2207	        const hash = hash_key(piece);
2208	        if (hash) {
2209	          if (this.options[piece]) {
2210	            self.addItem(piece);
2211	          } else {
2212	            self.createItem(piece);
2213	          }
2214	        }
2215	      });
2216	    }, 0);
2217	  }
2218
2219	  /**
2220	   * Triggered on <input> keypress.
2221	   *
2222	   */
2223	  onKeyPress(e) {
2224	    var self = this;
2225	    if (self.isLocked) {
2226	      preventDefault(e);
2227	      return;
2228	    }
2229	    var character = String.fromCharCode(e.keyCode || e.which);
2230	    if (self.settings.create && self.settings.mode === 'multi' && character === self.settings.delimiter) {
2231	      self.createItem();
2232	      preventDefault(e);
2233	      return;
2234	    }
2235	  }
2236
2237	  /**
2238	   * Triggered on <input> keydown.
2239	   *
2240	   */
2241	  onKeyDown(e) {
2242	    var self = this;
2243	    self.ignoreHover = true;
2244	    if (self.isLocked) {
2245	      if (e.keyCode !== KEY_TAB) {
2246	        preventDefault(e);
2247	      }
2248	      return;
2249	    }
2250	    switch (e.keyCode) {
2251	      // ctrl+A: select all
2252	      case KEY_A:
2253	        if (isKeyDown(KEY_SHORTCUT, e)) {
2254	          if (self.control_input.value == '') {
2255	            preventDefault(e);
2256	            self.selectAll();
2257	            return;
2258	          }
2259	        }
2260	        break;
2261
2262	      // esc: close dropdown
2263	      case KEY_ESC:
2264	        if (self.isOpen) {
2265	          preventDefault(e, true);
2266	          self.close();
2267	        }
2268	        self.clearActiveItems();
2269	        return;
2270
2271	      // down: open dropdown or move selection down
2272	      case KEY_DOWN:
2273	        if (!self.isOpen && self.hasOptions) {
2274	          self.open();
2275	        } else if (self.activeOption) {
2276	          let next = self.getAdjacent(self.activeOption, 1);
2277	          if (next) self.setActiveOption(next);
2278	        }
2279	        preventDefault(e);
2280	        return;
2281
2282	      // up: move selection up
2283	      case KEY_UP:
2284	        if (self.activeOption) {
2285	          let prev = self.getAdjacent(self.activeOption, -1);
2286	          if (prev) self.setActiveOption(prev);
2287	        }
2288	        preventDefault(e);
2289	        return;
2290
2291	      // return: select active option
2292	      case KEY_RETURN:
2293	        if (self.canSelect(self.activeOption)) {
2294	          self.onOptionSelect(e, self.activeOption);
2295	          preventDefault(e);
2296
2297	          // if the option_create=null, the dropdown might be closed
2298	        } else if (self.settings.create && self.createItem()) {
2299	          preventDefault(e);
2300
2301	          // don't submit form when searching for a value
2302	        } else if (document.activeElement == self.control_input && self.isOpen) {
2303	          preventDefault(e);
2304	        }
2305	        return;
2306
2307	      // left: modifiy item selection to the left
2308	      case KEY_LEFT:
2309	        self.advanceSelection(-1, e);
2310	        return;
2311
2312	      // right: modifiy item selection to the right
2313	      case KEY_RIGHT:
2314	        self.advanceSelection(1, e);
2315	        return;
2316
2317	      // tab: select active option and/or create item
2318	      case KEY_TAB:
2319	        if (self.settings.selectOnTab) {
2320	          if (self.canSelect(self.activeOption)) {
2321	            self.onOptionSelect(e, self.activeOption);
2322
2323	            // prevent default [tab] behaviour of jump to the next field
2324	            // if select isFull, then the dropdown won't be open and [tab] will work normally
2325	            preventDefault(e);
2326	          } else if (self.settings.create && self.createItem()) {
2327	            preventDefault(e);
2328	          }
2329	        }
2330	        return;
2331
2332	      // delete|backspace: delete items
2333	      case KEY_BACKSPACE:
2334	      case KEY_DELETE:
2335	        self.deleteSelection(e);
2336	        return;
2337	    }
2338
2339	    // don't enter text in the control_input when active items are selected
2340	    if (self.isInputHidden && !isKeyDown(KEY_SHORTCUT, e)) {
2341	      preventDefault(e);
2342	    }
2343	  }
2344
2345	  /**
2346	   * Triggered on <input> keyup.
2347	   *
2348	   */
2349	  onInput(e) {
2350	    if (this.isLocked) {
2351	      return;
2352	    }
2353	    const value = this.inputValue();
2354	    if (this.lastValue === value) return;
2355	    this.lastValue = value;
2356	    if (value == '') {
2357	      this._onInput();
2358	      return;
2359	    }
2360	    if (this.refreshTimeout) {
2361	      window.clearTimeout(this.refreshTimeout);
2362	    }
2363	    this.refreshTimeout = timeout(() => {
2364	      this.refreshTimeout = null;
2365	      this._onInput();
2366	    }, this.settings.refreshThrottle);
2367	  }
2368	  _onInput() {
2369	    const value = this.lastValue;
2370	    if (this.settings.shouldLoad.call(this, value)) {
2371	      this.load(value);
2372	    }
2373	    this.refreshOptions();
2374	    this.trigger('type', value);
2375	  }
2376
2377	  /**
2378	   * Triggered when the user rolls over
2379	   * an option in the autocomplete dropdown menu.
2380	   *
2381	   */
2382	  onOptionHover(evt, option) {
2383	    if (this.ignoreHover) return;
2384	    this.setActiveOption(option, false);
2385	  }
2386
2387	  /**
2388	   * Triggered on <input> focus.
2389	   *
2390	   */
2391	  onFocus(e) {
2392	    var self = this;
2393	    var wasFocused = self.isFocused;
2394	    if (self.isDisabled || self.isReadOnly) {
2395	      self.blur();
2396	      preventDefault(e);
2397	      return;
2398	    }
2399	    if (self.ignoreFocus) return;
2400	    self.isFocused = true;
2401	    if (self.settings.preload === 'focus') self.preload();
2402	    if (!wasFocused) self.trigger('focus');
2403	    if (!self.activeItems.length) {
2404	      self.inputState();
2405	      self.refreshOptions(!!self.settings.openOnFocus);
2406	    }
2407	    self.refreshState();
2408	  }
2409
2410	  /**
2411	   * Triggered on <input> blur.
2412	   *
2413	   */
2414	  onBlur(e) {
2415	    if (document.hasFocus() === false) return;
2416	    var self = this;
2417	    if (!self.isFocused) return;
2418	    self.isFocused = false;
2419	    self.ignoreFocus = false;
2420	    var deactivate = () => {
2421	      self.close();
2422	      self.setActiveItem();
2423	      self.setCaret(self.items.length);
2424	      self.trigger('blur');
2425	    };
2426	    if (self.settings.create && self.settings.createOnBlur) {
2427	      self.createItem(null, deactivate);
2428	    } else {
2429	      deactivate();
2430	    }
2431	  }
2432
2433	  /**
2434	   * Triggered when the user clicks on an option
2435	   * in the autocomplete dropdown menu.
2436	   *
2437	   */
2438	  onOptionSelect(evt, option) {
2439	    var value,
2440	      self = this;
2441
2442	    // should not be possible to trigger a option under a disabled optgroup
2443	    if (option.parentElement && option.parentElement.matches('[data-disabled]')) {
2444	      return;
2445	    }
2446	    if (option.classList.contains('create')) {
2447	      self.createItem(null, () => {
2448	        if (self.settings.closeAfterSelect) {
2449	          self.close();
2450	        } else if (self.settings.clearAfterSelect) {
2451	          self.setTextboxValue();
2452	        }
2453	      });
2454	    } else {
2455	      value = option.dataset.value;
2456	      if (typeof value !== 'undefined') {
2457	        self.isDropdownContentStale = self.settings.hideSelected;
2458	        self.addItem(value);
2459	        if (self.settings.closeAfterSelect) {
2460	          self.close();
2461	        } else if (self.settings.clearAfterSelect) {
2462	          self.setTextboxValue();
2463	        }
2464	        if (!self.settings.hideSelected && evt.type && /click/.test(evt.type)) {
2465	          self.setActiveOption(option);
2466	        }
2467	      }
2468	    }
2469	  }
2470
2471	  /**
2472	   * Return true if the given option can be selected
2473	   *
2474	   */
2475	  canSelect(option) {
2476	    if (this.isOpen && option && this.dropdown_content.contains(option)) {
2477	      return true;
2478	    }
2479	    return false;
2480	  }
2481
2482	  /**
2483	   * Triggered when the user clicks on an item
2484	   * that has been selected.
2485	   *
2486	   */
2487	  onItemSelect(evt, item) {
2488	    var self = this;
2489	    if (!self.isLocked && self.settings.mode === 'multi') {
2490	      preventDefault(evt);
2491	      self.setActiveItem(item, evt);
2492	      return true;
2493	    }
2494	    return false;
2495	  }
2496
2497	  /**
2498	   * Determines whether or not to invoke
2499	   * the user-provided option provider / loader
2500	   *
2501	   * Note, there is a subtle difference between
2502	   * this.canLoad() and this.settings.shouldLoad();
2503	   *
2504	   *	- settings.shouldLoad() is a user-input validator.
2505	   *	When false is returned, the not_loading template
2506	   *	will be added to the dropdown
2507	   *
2508	   *	- canLoad() is lower level validator that checks
2509	   * 	the Tom Select instance. There is no inherent user
2510	   *	feedback when canLoad returns false
2511	   *
2512	   */
2513	  canLoad(value) {
2514	    if (!this.settings.load) return false;
2515	    if (this.loadedSearches.hasOwnProperty(value)) return false;
2516	    return true;
2517	  }
2518
2519	  /**
2520	   * Invokes the user-provided option provider / loader.
2521	   *
2522	   */
2523	  load(value) {
2524	    const self = this;
2525	    if (!self.canLoad(value)) return;
2526	    addClasses(self.wrapper, self.settings.loadingClass);
2527	    self.loading++;
2528	    const callback = self.loadCallback.bind(self);
2529	    self.settings.load.call(self, value, callback);
2530	  }
2531
2532	  /**
2533	   * Invoked by the user-provided option provider
2534	   *
2535	   */
2536	  loadCallback(options, optgroups) {
2537	    const self = this;
2538	    self.loading = Math.max(self.loading - 1, 0);
2539	    self.isDropdownContentStale = true;
2540	    self.clearActiveOption(); // when new results load, focus should be on first option
2541	    self.setupOptions(options, optgroups);
2542	    self.refreshOptions(self.isFocused && !self.isInputHidden);
2543	    if (!self.loading) {
2544	      removeClasses(self.wrapper, self.settings.loadingClass);
2545	    }
2546	    self.trigger('load', options, optgroups);
2547	  }
2548	  preload() {
2549	    var classList = this.wrapper.classList;
2550	    if (classList.contains('preloaded')) return;
2551	    classList.add('preloaded');
2552	    this.load('');
2553	  }
2554
2555	  /**
2556	   * Sets the input field of the control to the specified value.
2557	   *
2558	   */
2559	  setTextboxValue(value = '') {
2560	    var input = this.control_input;
2561	    var changed = input.value !== value;
2562	    if (changed) {
2563	      input.value = value;
2564	      triggerEvent(input, 'update');
2565	      this.lastValue = value;
2566	    }
2567	  }
2568
2569	  /**
2570	   * Returns the value of the control. If multiple items
2571	   * can be selected (e.g. <select multiple>), this returns
2572	   * an array. If only one item can be selected, this
2573	   * returns a string.
2574	   *
2575	   */
2576	  getValue() {
2577	    if (this.is_select_tag && this.input.hasAttribute('multiple')) {
2578	      return this.items;
2579	    }
2580	    return this.items.join(this.settings.delimiter);
2581	  }
2582
2583	  /**
2584	   * Resets the selected items to the given value.
2585	   *
2586	   */
2587	  setValue(value, silent) {
2588	    var events = silent ? [] : ['change'];
2589	    debounce_events(this, events, () => {
2590	      this.clear(silent);
2591	      this.addItems(value, silent);
2592	    });
2593	  }
2594
2595	  /**
2596	   * Resets the number of max items to the given value
2597	   *
2598	   */
2599	  setMaxItems(value) {
2600	    if (value === 0) value = null; //reset to unlimited items.
2601	    this.settings.maxItems = value;
2602	    this.refreshState();
2603	  }
2604
2605	  /**
2606	   * Sets the selected item.
2607	   *
2608	   */
2609	  setActiveItem(item, e) {
2610	    var self = this;
2611	    var eventName;
2612	    var i, begin, end, swap;
2613	    var last;
2614	    if (self.settings.mode === 'single') return;
2615
2616	    // clear the active selection
2617	    if (!item) {
2618	      self.clearActiveItems();
2619	      if (self.isFocused) {
2620	        self.inputState();
2621	      }
2622	      return;
2623	    }
2624
2625	    // modify selection
2626	    eventName = e && e.type.toLowerCase();
2627	    if (eventName === 'click' && isKeyDown('shiftKey', e) && self.activeItems.length) {
2628	      last = self.getLastActive();
2629	      begin = Array.prototype.indexOf.call(self.control.children, last);
2630	      end = Array.prototype.indexOf.call(self.control.children, item);
2631	      if (begin > end) {
2632	        swap = begin;
2633	        begin = end;
2634	        end = swap;
2635	      }
2636	      for (i = begin; i <= end; i++) {
2637	        item = self.control.children[i];
2638	        if (self.activeItems.indexOf(item) === -1) {
2639	          self.setActiveItemClass(item);
2640	        }
2641	      }
2642	      preventDefault(e);
2643	    } else if (eventName === 'click' && isKeyDown(KEY_SHORTCUT, e) || eventName === 'keydown' && isKeyDown('shiftKey', e)) {
2644	      if (item.classList.contains('active')) {
2645	        self.removeActiveItem(item);
2646	      } else {
2647	        self.setActiveItemClass(item);
2648	      }
2649	    } else {
2650	      self.clearActiveItems();
2651	      self.setActiveItemClass(item);
2652	    }
2653
2654	    // ensure control has focus
2655	    self.inputState();
2656	    if (!self.isFocused) {
2657	      self.focus();
2658	    }
2659	  }
2660
2661	  /**
2662	   * Set the active and last-active classes
2663	   *
2664	   */
2665	  setActiveItemClass(item) {
2666	    const self = this;
2667	    const last_active = self.control.querySelector('.last-active');
2668	    if (last_active) removeClasses(last_active, 'last-active');
2669	    addClasses(item, 'active last-active');
2670	    self.trigger('item_select', item);
2671	    if (self.activeItems.indexOf(item) == -1) {
2672	      self.activeItems.push(item);
2673	    }
2674	  }
2675
2676	  /**
2677	   * Remove active item
2678	   *
2679	   */
2680	  removeActiveItem(item) {
2681	    var idx = this.activeItems.indexOf(item);
2682	    this.activeItems.splice(idx, 1);
2683	    removeClasses(item, 'active');
2684	  }
2685
2686	  /**
2687	   * Clears all the active items
2688	   *
2689	   */
2690	  clearActiveItems() {
2691	    removeClasses(this.activeItems, 'active');
2692	    this.activeItems = [];
2693	  }
2694
2695	  /**
2696	   * Sets the selected item in the dropdown menu
2697	   * of available options.
2698	   *
2699	   */
2700	  setActiveOption(option, scroll = true) {
2701	    if (option === this.activeOption) {
2702	      return;
2703	    }
2704	    this.clearActiveOption();
2705	    if (!option) return;
2706	    this.activeOption = option;
2707	    setAttr(this.focus_node, {
2708	      'aria-activedescendant': option.getAttribute('id')
2709	    });
2710	    setAttr(option, {
2711	      'aria-selected': 'true'
2712	    });
2713	    addClasses(option, 'active');
2714	    if (scroll) this.scrollToOption(option);
2715	  }
2716
2717	  /**
2718	   * Sets the dropdown_content scrollTop to display the option
2719	   *
2720	   */
2721	  scrollToOption(option, behavior) {
2722	    if (!option) return;
2723	    const content = this.dropdown_content;
2724	    const height_menu = content.clientHeight;
2725	    const scrollTop = content.scrollTop || 0;
2726	    const height_item = option.offsetHeight;
2727	    const y = option.getBoundingClientRect().top - content.getBoundingClientRect().top + scrollTop;
2728	    if (y + height_item > height_menu + scrollTop) {
2729	      this.scroll(y - height_menu + height_item, behavior);
2730	    } else if (y < scrollTop) {
2731	      this.scroll(y, behavior);
2732	    }
2733	  }
2734
2735	  /**
2736	   * Scroll the dropdown to the given position
2737	   *
2738	   */
2739	  scroll(scrollTop, behavior) {
2740	    const content = this.dropdown_content;
2741	    if (behavior) {
2742	      content.style.scrollBehavior = behavior;
2743	    }
2744	    content.scrollTop = scrollTop;
2745	    content.style.scrollBehavior = '';
2746	  }
2747
2748	  /**
2749	   * Clears the active option
2750	   *
2751	   */
2752	  clearActiveOption() {
2753	    if (this.activeOption) {
2754	      removeClasses(this.activeOption, 'active');
2755	      setAttr(this.activeOption, {
2756	        'aria-selected': null
2757	      });
2758	    }
2759	    this.activeOption = null;
2760	    setAttr(this.focus_node, {
2761	      'aria-activedescendant': null
2762	    });
2763	  }
2764
2765	  /**
2766	   * Selects all items (CTRL + A).
2767	   */
2768	  selectAll() {
2769	    const self = this;
2770	    if (self.settings.mode === 'single') return;
2771	    const activeItems = self.controlChildren();
2772	    if (!activeItems.length) return;
2773	    self.inputState();
2774	    self.close();
2775	    self.activeItems = activeItems;
2776	    iterate(activeItems, item => {
2777	      self.setActiveItemClass(item);
2778	    });
2779	  }
2780
2781	  /**
2782	   * Determines if the control_input should be in a hidden or visible state
2783	   *
2784	   */
2785	  inputState() {
2786	    var self = this;
2787	    if (!self.control.contains(self.control_input)) return;
2788	    setAttr(self.control_input, {
2789	      placeholder: self.settings.placeholder
2790	    });
2791	    if (self.activeItems.length > 0 || !self.isFocused && self.settings.hidePlaceholder && self.items.length > 0) {
2792	      self.setTextboxValue();
2793	      self.isInputHidden = true;
2794	    } else {
2795	      if (self.settings.hidePlaceholder && self.items.length > 0) {
2796	        setAttr(self.control_input, {
2797	          placeholder: ''
2798	        });
2799	      }
2800	      self.isInputHidden = false;
2801	    }
2802	    self.wrapper.classList.toggle('input-hidden', self.isInputHidden);
2803	  }
2804
2805	  /**
2806	   * Get the input value
2807	   */
2808	  inputValue() {
2809	    return this.control_input.value.trim();
2810	  }
2811
2812	  /**
2813	   * Gives the control focus.
2814	   */
2815	  focus() {
2816	    var self = this;
2817	    if (self.isDisabled || self.isReadOnly) return;
2818	    self.ignoreFocus = true;
2819	    const focusTarget = this.control_input.offsetWidth ? this.control_input : this.focus_node;
2820	    focusTarget.focus();
2821	    setTimeout(() => {
2822	      self.ignoreFocus = false;
2823	      // Fix https://github.com/orchidjs/tom-select/issues/806
2824	      // Only proceed if this instance's element is still the active element. If Edge autofill
2825	      // (or anything else) has moved focus to a different element in the interim, calling
2826	      // onFocus() here would steal focus back and restart the cascade loop.
2827	      const root = focusTarget.getRootNode();
2828	      if (root.activeElement !== focusTarget) {
2829	        return;
2830	      }
2831	      this.onFocus();
2832	    }, 0);
2833	  }
2834
2835	  /**
2836	   * Forces the control out of focus.
2837	   *
2838	   */
2839	  blur() {
2840	    this.focus_node.blur();
2841	    this.onBlur();
2842	  }
2843
2844	  /**
2845	   * Returns a function that scores an object
2846	   * to show how good of a match it is to the
2847	   * provided query.
2848	   *
2849	   * @return {function}
2850	   */
2851	  getScoreFunction(query) {
2852	    return this.sifter.getScoreFunction(query, this.getSearchOptions());
2853	  }
2854
2855	  /**
2856	   * Returns search options for sifter (the system
2857	   * for scoring and sorting results).
2858	   *
2859	   * @see https://github.com/orchidjs/sifter.js
2860	   * @return {object}
2861	   */
2862	  getSearchOptions() {
2863	    var settings = this.settings;
2864	    var sort = settings.sortField;
2865	    if (typeof settings.sortField === 'string') {
2866	      sort = [{
2867	        field: settings.sortField
2868	      }];
2869	    }
2870	    return {
2871	      fields: settings.searchField,
2872	      conjunction: settings.searchConjunction,
2873	      sort: sort,
2874	      nesting: settings.nesting
2875	    };
2876	  }
2877
2878	  /**
2879	   * Searches through available options and returns
2880	   * a sorted array of matches.
2881	   *
2882	   */
2883	  search(query) {
2884	    var result, calculateScore;
2885	    var self = this;
2886	    var options = this.getSearchOptions();
2887
2888	    // validate user-provided result scoring function
2889	    if (self.settings.score) {
2890	      calculateScore = self.settings.score.call(self, query);
2891	      if (typeof calculateScore !== 'function') {
2892	        throw new Error('Tom Select "score" setting must be a function that returns a function');
2893	      }
2894	    }
2895
2896	    // perform search
2897	    if (self.isDropdownContentStale || query !== self.lastQuery) {
2898	      self.lastQuery = query;
2899	      // temp fix for https://github.com/orchidjs/tom-select/issues/987
2900	      // UI crashed when more than 30 same chars in a row, prevent search and return empt result
2901	      if (/(.)\1{15,}/.test(query)) {
2902	        query = '';
2903	      }
2904	      result = self.sifter.search(query, Object.assign(options, {
2905	        score: calculateScore
2906	      }));
2907	      self.currentResults = result;
2908	    } else {
2909	      result = Object.assign({}, self.currentResults);
2910	    }
2911
2912	    // filter out selected items
2913	    if (self.settings.hideSelected) {
2914	      result.items = result.items.filter(item => {
2915	        let hashed = hash_key(item.id);
2916	        return !(hashed !== null && self.items.indexOf(hashed) !== -1);
2917	      });
2918	    }
2919	    return result;
2920	  }
2921
2922	  /**
2923	   * Refreshes the list of available options shown
2924	   * in the autocomplete dropdown menu.
2925	   *
2926	   */
2927	  refreshOptions(triggerDropdown = true) {
2928	    var i, j, k, n, optgroup, optgroups, html, has_create_option, active_group;
2929	    var create;
2930	    const groups = {};
2931	    const groups_order = [];
2932	    var self = this;
2933	    var query = self.inputValue();
2934	    const same_query = query === self.lastQuery || query == '' && self.lastQuery == null;
2935	    var results = self.search(query);
2936	    var active_option = null;
2937	    var show_dropdown = self.settings.shouldOpen || false;
2938	    var dropdown_content = self.dropdown_content;
2939	    if (same_query) {
2940	      active_option = self.activeOption;
2941	      if (active_option) {
2942	        active_group = active_option.closest('[data-group]');
2943	      }
2944	    }
2945
2946	    // build markup
2947	    n = results.items.length;
2948	    if (typeof self.settings.maxOptions === 'number') {
2949	      n = Math.min(n, self.settings.maxOptions);
2950	    }
2951	    if (n > 0) {
2952	      show_dropdown = true;
2953	    }
2954
2955	    // get fragment for group and the position of the group in group_order
2956	    const getGroupFragment = (optgroup, order) => {
2957	      let group_order_i = groups[optgroup];
2958	      if (group_order_i !== undefined) {
2959	        let order_group = groups_order[group_order_i];
2960	        if (order_group !== undefined) {
2961	          return [group_order_i, order_group.fragment];
2962	        }
2963	      }
2964	      let group_fragment = document.createDocumentFragment();
2965	      group_order_i = groups_order.length;
2966	      groups_order.push({
2967	        fragment: group_fragment,
2968	        order,
2969	        optgroup
2970	      });
2971	      return [group_order_i, group_fragment];
2972	    };
2973
2974	    // render and group available options individually
2975	    for (i = 0; i < n; i++) {
2976	      // get option dom element
2977	      let item = results.items[i];
2978	      if (!item) continue;
2979	      let opt_value = item.id;
2980	      let option = self.options[opt_value];
2981	      if (option === undefined) continue;
2982	      let opt_hash = get_hash(opt_value);
2983	      let option_el = self.getOption(opt_hash, true);
2984
2985	      // toggle 'selected' class
2986	      if (!self.settings.hideSelected) {
2987	        option_el.classList.toggle('selected', self.items.includes(opt_hash));
2988	      }
2989	      optgroup = option[self.settings.optgroupField] || '';
2990	      optgroups = Array.isArray(optgroup) ? optgroup : [optgroup];
2991	      for (j = 0, k = optgroups && optgroups.length; j < k; j++) {
2992	        optgroup = optgroups[j];
2993	        let order = option.$order;
2994	        let self_optgroup = self.optgroups[optgroup];
2995	        if (self_optgroup === undefined && typeof self.settings.optionGroupRegister === 'function') {
2996	          var regGroup;
2997	          if (regGroup = self.settings.optionGroupRegister.apply(self, [optgroup])) {
2998	            self.registerOptionGroup(regGroup);
2999	          }
3000	        }
3001	        self_optgroup = self.optgroups[optgroup];
3002	        if (self_optgroup === undefined) {
3003	          optgroup = '';
3004	        } else {
3005	          order = self_optgroup.$order;
3006	        }
3007	        const [group_order_i, group_fragment] = getGroupFragment(optgroup, order);
3008
3009	        // nodes can only have one parent, so if the option is in mutple groups, we need a clone
3010	        if (j > 0) {
3011	          option_el = option_el.cloneNode(true);
3012	          setAttr(option_el, {
3013	            id: option.$id + '-clone-' + j,
3014	            'aria-selected': null
3015	          });
3016	          option_el.classList.add('ts-cloned');
3017	          removeClasses(option_el, 'active');
3018
3019	          // make sure we keep the activeOption in the same group
3020	          if (self.activeOption && self.activeOption.dataset.value == opt_value) {
3021	            if (active_group && active_group.dataset.group === optgroup.toString()) {
3022	              active_option = option_el;
3023	            }
3024	          }
3025	        }
3026	        group_fragment.appendChild(option_el);
3027	        if (optgroup != '') {
3028	          groups[optgroup] = group_order_i;
3029	        }
3030	      }
3031	    }
3032
3033	    // sort optgroups
3034	    if (self.settings.lockOptgroupOrder) {
3035	      groups_order.sort((a, b) => {
3036	        return a.order - b.order;
3037	      });
3038	    }
3039
3040	    // render optgroup headers & join groups
3041	    html = document.createDocumentFragment();
3042	    iterate(groups_order, group_order => {
3043	      let group_fragment = group_order.fragment;
3044	      let optgroup = group_order.optgroup;
3045	      if (!group_fragment || !group_fragment.children.length) return;
3046	      let group_heading = self.optgroups[optgroup];
3047	      if (group_heading !== undefined) {
3048	        let group_options = document.createDocumentFragment();
3049	        let header = self.render('optgroup_header', group_heading);
3050	        append(group_options, header);
3051	        append(group_options, group_fragment);
3052	        let group_html = self.render('optgroup', {
3053	          group: group_heading,
3054	          options: group_options
3055	        });
3056	        append(html, group_html);
3057	      } else {
3058	        append(html, group_fragment);
3059	      }
3060	    });
3061	    dropdown_content.innerHTML = '';
3062	    append(dropdown_content, html);
3063	    self.isDropdownContentStale = false;
3064
3065	    // highlight matching terms inline
3066	    if (self.settings.highlight) {
3067	      removeHighlight(dropdown_content);
3068	      if (results.query.length && results.tokens.length) {
3069	        iterate(results.tokens, tok => {
3070	          highlight(dropdown_content, tok.regex);
3071	        });
3072	      }
3073	    }
3074
3075	    // helper method for adding templates to dropdown
3076	    var add_template = template => {
3077	      let content = self.render(template, {
3078	        input: query
3079	      });
3080	      if (content) {
3081	        show_dropdown = true;
3082	        dropdown_content.insertBefore(content, dropdown_content.firstChild);
3083	      }
3084	      return content;
3085	    };
3086
3087	    // add loading message
3088	    if (self.loading) {
3089	      add_template('loading');
3090
3091	      // invalid query
3092	    } else if (!self.settings.shouldLoad.call(self, query)) {
3093	      add_template('not_loading');
3094
3095	      // add no_results message
3096	    } else if (results.items.length === 0) {
3097	      add_template('no_results');
3098	    }
3099
3100	    // add create option
3101	    has_create_option = self.canCreate(query);
3102	    if (has_create_option) {
3103	      create = add_template('option_create');
3104	    }
3105
3106	    // activate
3107	    self.hasOptions = results.items.length > 0 || has_create_option;
3108	    if (show_dropdown) {
3109	      if (results.items.length > 0) {
3110	        if (!active_option && self.settings.mode === 'single' && self.items[0] != undefined) {
3111	          active_option = self.getOption(self.items[0]);
3112	        }
3113	        if (!dropdown_content.contains(active_option)) {
3114	          let active_index = 0;
3115	          if (create && !self.settings.addPrecedence) {
3116	            active_index = 1;
3117	          }
3118	          active_option = self.selectable()[active_index];
3119	        }
3120	      } else if (create) {
3121	        active_option = create;
3122	      }
3123	      if (triggerDropdown && !self.isOpen) {
3124	        self.open();
3125	        self.scrollToOption(active_option, 'auto');
3126	      }
3127	      self.setActiveOption(active_option);
3128	    } else {
3129	      self.clearActiveOption();
3130	      if (triggerDropdown && self.isOpen) {
3131	        self.close(false); // if create_option=null, we want the dropdown to close but not reset the textbox value
3132	      }
3133	    }
3134	  }
3135
3136	  /**
3137	   * Return list of selectable options
3138	   *
3139	   */
3140	  selectable() {
3141	    return this.dropdown_content.querySelectorAll('[data-selectable]');
3142	  }
3143
3144	  /**
3145	   * Adds an available option. If it already exists,
3146	   * nothing will happen. Note: this does not refresh
3147	   * the options list dropdown (use `refreshOptions`
3148	   * for that).
3149	   *
3150	   * Usage:
3151	   *
3152	   *   this.addOption(data)
3153	   *
3154	   */
3155	  addOption(data, user_created = false) {
3156	    const self = this;
3157
3158	    // @deprecated 1.7.7
3159	    // use addOptions( array, user_created ) for adding multiple options
3160	    if (Array.isArray(data)) {
3161	      self.addOptions(data, user_created);
3162	      return false;
3163	    }
3164	    const key = hash_key(data[self.settings.valueField]);
3165	    if (key === null || self.options.hasOwnProperty(key)) {
3166	      self.updateOption(data[self.settings.valueField], data);
3167	      return false;
3168	    }
3169	    data.$order = data.$order || ++self.order;
3170	    data.$id = self.inputId + '-opt-' + data.$order;
3171	    self.options[key] = data;
3172	    self.isDropdownContentStale = true;
3173	    if (user_created) {
3174	      self.userOptions[key] = user_created;
3175	      self.trigger('option_add', key, data);
3176	    }
3177	    return key;
3178	  }
3179
3180	  /**
3181	   * Add multiple options
3182	   *
3183	   */
3184	  addOptions(data, user_created = false) {
3185	    iterate(data, dat => {
3186	      this.addOption(dat, user_created);
3187	    });
3188	  }
3189
3190	  /**
3191	   * @deprecated 1.7.7
3192	   */
3193	  registerOption(data) {
3194	    return this.addOption(data);
3195	  }
3196
3197	  /**
3198	   * Registers an option group to the pool of option groups.
3199	   *
3200	   * @return {boolean|string}
3201	   */
3202	  registerOptionGroup(data) {
3203	    var key = hash_key(data[this.settings.optgroupValueField]);
3204	    if (key === null) return false;
3205	    data.$order = data.$order || ++this.order;
3206	    this.optgroups[key] = data;
3207	    return key;
3208	  }
3209
3210	  /**
3211	   * Registers a new optgroup for options
3212	   * to be bucketed into.
3213	   *
3214	   */
3215	  addOptionGroup(id, data) {
3216	    var hashed_id;
3217	    data[this.settings.optgroupValueField] = id;
3218	    if (hashed_id = this.registerOptionGroup(data)) {
3219	      this.trigger('optgroup_add', hashed_id, data);
3220	    }
3221	  }
3222
3223	  /**
3224	   * Removes an existing option group.
3225	   *
3226	   */
3227	  removeOptionGroup(id) {
3228	    if (this.optgroups.hasOwnProperty(id)) {
3229	      delete this.optgroups[id];
3230	      this.clearCache();
3231	      this.trigger('optgroup_remove', id);
3232	    }
3233	  }
3234
3235	  /**
3236	   * Clears all existing option groups.
3237	   */
3238	  clearOptionGroups() {
3239	    this.optgroups = {};
3240	    this.clearCache();
3241	    this.trigger('optgroup_clear');
3242	  }
3243
3244	  /**
3245	   * Updates an option available for selection. If
3246	   * it is visible in the selected items or options
3247	   * dropdown, it will be re-rendered automatically.
3248	   *
3249	   */
3250	  updateOption(value, data) {
3251	    const self = this;
3252	    var item_new;
3253	    var index_item;
3254	    const value_old = hash_key(value);
3255	    const value_new = hash_key(data[self.settings.valueField]);
3256
3257	    // sanity checks
3258	    if (value_old === null) return;
3259	    const data_old = self.options[value_old];
3260	    if (data_old == undefined) return;
3261	    if (typeof value_new !== 'string') throw new Error('Value must be set in option data');
3262	    const option = self.getOption(value_old);
3263	    const item = self.getItem(value_old);
3264	    data.$order = data.$order || data_old.$order;
3265	    delete self.options[value_old];
3266
3267	    // invalidate render cache
3268	    // don't remove existing node yet, we'll remove it after replacing it
3269	    self.uncacheValue(value_new);
3270	    self.options[value_new] = data;
3271
3272	    // update the option if it's in the dropdown
3273	    if (option) {
3274	      if (self.dropdown_content.contains(option)) {
3275	        const option_new = self._render('option', data);
3276	        replaceNode(option, option_new);
3277	        if (self.activeOption === option) {
3278	          self.setActiveOption(option_new);
3279	        }
3280	      }
3281	      option.remove();
3282	    }
3283
3284	    // update the item if we have one
3285	    if (item) {
3286	      index_item = self.items.indexOf(value_old);
3287	      if (index_item !== -1) {
3288	        self.items.splice(index_item, 1, value_new);
3289	      }
3290	      item_new = self._render('item', data);
3291	      if (item.classList.contains('active')) addClasses(item_new, 'active');
3292	      replaceNode(item, item_new);
3293	    }
3294
3295	    // we might have updated the sortField
3296	    self.isDropdownContentStale = true;
3297	  }
3298
3299	  /**
3300	   * Removes a single option.
3301	   *
3302	   */
3303	  removeOption(value, silent) {
3304	    const self = this;
3305	    value = get_hash(value);
3306	    self.uncacheValue(value);
3307	    delete self.userOptions[value];
3308	    delete self.options[value];
3309	    self.isDropdownContentStale = true;
3310	    self.trigger('option_remove', value);
3311	    self.removeItem(value, silent);
3312	  }
3313
3314	  /**
3315	   * Clears all options.
3316	   */
3317	  clearOptions(filter) {
3318	    const boundFilter = (filter || this.clearFilter).bind(this);
3319	    this.loadedSearches = {};
3320	    this.userOptions = {};
3321	    this.clearCache();
3322	    const selected = {};
3323	    iterate(this.options, (option, key) => {
3324	      if (boundFilter(option, key)) {
3325	        selected[key] = option;
3326	      }
3327	    });
3328	    this.options = this.sifter.items = selected;
3329	    this.isDropdownContentStale = true;
3330	    this.trigger('option_clear');
3331	  }
3332
3333	  /**
3334	   * Used by clearOptions() to decide whether or not an option should be removed
3335	   * Return true to keep an option, false to remove
3336	   *
3337	   */
3338	  clearFilter(option, value) {
3339	    if (this.items.indexOf(value) >= 0) {
3340	      return true;
3341	    }
3342	    return false;
3343	  }
3344
3345	  /**
3346	   * Returns the dom element of the option
3347	   * matching the given value.
3348	   *
3349	   */
3350	  getOption(value, create = false) {
3351	    const hashed = hash_key(value);
3352	    if (hashed === null) return null;
3353	    const option = this.options[hashed];
3354	    if (option != undefined) {
3355	      if (option.$div) {
3356	        return option.$div;
3357	      }
3358	      if (create) {
3359	        return this._render('option', option);
3360	      }
3361	    }
3362	    return null;
3363	  }
3364
3365	  /**
3366	   * Returns the dom element of the next or previous dom element of the same type
3367	   * Note: adjacent options may not be adjacent DOM elements (optgroups)
3368	   *
3369	   */
3370	  getAdjacent(option, direction, type = 'option') {
3371	    var self = this,
3372	      all;
3373	    if (!option) {
3374	      return null;
3375	    }
3376	    if (type == 'item') {
3377	      all = self.controlChildren();
3378	    } else {
3379	      all = self.dropdown_content.querySelectorAll('[data-selectable]');
3380	    }
3381	    for (let i = 0; i < all.length; i++) {
3382	      if (all[i] != option) {
3383	        continue;
3384	      }
3385	      if (direction > 0) {
3386	        return all[i + 1];
3387	      }
3388	      return all[i - 1];
3389	    }
3390	    return null;
3391	  }
3392
3393	  /**
3394	   * Returns the dom element of the item
3395	   * matching the given value.
3396	   *
3397	   */
3398	  getItem(item) {
3399	    if (typeof item == 'object') {
3400	      return item;
3401	    }
3402	    var value = hash_key(item);
3403	    return value !== null ? this.control.querySelector(`[data-value="${addSlashes(value)}"]`) : null;
3404	  }
3405
3406	  /**
3407	   * "Selects" multiple items at once. Adds them to the list
3408	   * at the current caret position.
3409	   *
3410	   */
3411	  addItems(values, silent) {
3412	    var self = this;
3413	    var items = Array.isArray(values) ? values : [values];
3414	    items = items.filter(x => self.items.indexOf(x) === -1);
3415	    const last_item = items[items.length - 1];
3416	    items.forEach(item => {
3417	      self.isPending = item !== last_item;
3418	      self.addItem(item, silent);
3419	    });
3420	  }
3421
3422	  /**
3423	   * "Selects" an item. Adds it to the list
3424	   * at the current caret position.
3425	   *
3426	   */
3427	  addItem(value, silent) {
3428	    var events = silent ? [] : ['change', 'dropdown_close'];
3429	    debounce_events(this, events, () => {
3430	      var item, wasFull;
3431	      const self = this;
3432	      const inputMode = self.settings.mode;
3433	      const hashed = hash_key(value);
3434	      if (hashed && self.items.indexOf(hashed) !== -1) {
3435	        if (inputMode === 'single') {
3436	          self.close();
3437	        }
3438	        if (inputMode === 'single' || !self.settings.duplicates) {
3439	          return;
3440	        }
3441	      }
3442	      if (hashed === null || !self.options.hasOwnProperty(hashed)) return;
3443	      if (inputMode === 'single') self.clear(silent);
3444	      if (inputMode === 'multi' && self.isFull()) return;
3445	      item = self._render('item', self.options[hashed]);
3446	      if (self.control.contains(item)) {
3447	        // duplicates
3448	        item = item.cloneNode(true);
3449	      }
3450	      wasFull = self.isFull();
3451	      self.items.splice(self.caretPos, 0, hashed);
3452	      self.insertAtCaret(item);
3453	      if (self.isSetup) {
3454	        // update menu / remove the option (if this is not one item being added as part of series)
3455	        if (!self.isPending && self.settings.hideSelected) {
3456	          let option = self.getOption(hashed);
3457	          let next = self.getAdjacent(option, 1);
3458	          if (next) {
3459	            self.setActiveOption(next);
3460	          }
3461	        }
3462
3463	        //remove input value when enabled
3464	        if (self.settings.clearAfterSelect) {
3465	          self.setTextboxValue();
3466	        }
3467
3468	        // refreshOptions after setActiveOption(),
3469	        // otherwise setActiveOption() will be called by refreshOptions() with the wrong value
3470	        if (!self.isPending && !self.settings.closeAfterSelect) {
3471	          self.refreshOptions(self.isFocused && inputMode !== 'single');
3472	        }
3473
3474	        // hide the menu if the maximum number of items have been selected or no options are left
3475	        if (self.settings.closeAfterSelect != false && self.isFull()) {
3476	          self.close();
3477	        } else if (!self.isPending) {
3478	          self.positionDropdown();
3479	        }
3480	        self.trigger('item_add', hashed, item);
3481	        if (!self.isPending) {
3482	          self.updateOriginalInput({
3483	            silent: silent
3484	          });
3485	        }
3486	      }
3487	      if (!self.isPending || !wasFull && self.isFull()) {
3488	        self.inputState();
3489	        self.refreshState();
3490	      }
3491	    });
3492	  }
3493
3494	  /**
3495	   * Removes the selected item matching
3496	   * the provided value.
3497	   *
3498	   */
3499	  removeItem(item = null, silent) {
3500	    const self = this;
3501	    item = self.getItem(item);
3502	    if (!item) return;
3503	    var i, idx;
3504	    const value = item.dataset.value;
3505	    i = nodeIndex(item);
3506	    item.remove();
3507	    if (item.classList.contains('active')) {
3508	      idx = self.activeItems.indexOf(item);
3509	      self.activeItems.splice(idx, 1);
3510	      removeClasses(item, 'active');
3511	    }
3512	    self.items.splice(i, 1);
3513	    self.isDropdownContentStale = true;
3514	    if (!self.settings.persist && self.userOptions.hasOwnProperty(value)) {
3515	      self.removeOption(value, silent);
3516	    }
3517	    if (i < self.caretPos) {
3518	      self.setCaret(self.caretPos - 1);
3519	    }
3520	    self.updateOriginalInput({
3521	      silent: silent
3522	    });
3523	    self.refreshState();
3524	    self.positionDropdown();
3525	    self.trigger('item_remove', value, item);
3526	  }
3527
3528	  /**
3529	   * Invokes the `create` method provided in the
3530	   * TomSelect options that should provide the data
3531	   * for the new item, given the user input.
3532	   *
3533	   * Once this completes, it will be added
3534	   * to the item list.
3535	   *
3536	   */
3537	  createItem(input = null, callback = () => {}) {
3538	    // triggerDropdown parameter @deprecated 2.1.1
3539	    if (arguments.length === 3) {
3540	      callback = arguments[2];
3541	    }
3542	    if (typeof callback != 'function') {
3543	      callback = () => {};
3544	    }
3545	    var self = this;
3546	    var caret = self.caretPos;
3547	    var output;
3548	    input = input || self.inputValue();
3549	    if (!self.canCreate(input)) {
3550	      const hash = hash_key(input);
3551	      if (hash) {
3552	        if (this.options[input]) {
3553	          self.addItem(input);
3554	        }
3555	      }
3556	      callback();
3557	      return false;
3558	    }
3559	    self.lock();
3560	    var created = false;
3561	    var create = data => {
3562	      self.unlock();
3563	      if (!data || typeof data !== 'object') return callback();
3564	      var value = hash_key(data[self.settings.valueField]);
3565	      if (typeof value !== 'string') {
3566	        return callback();
3567	      }
3568	      self.setTextboxValue();
3569	      self.addOption(data, true);
3570	      self.setCaret(caret);
3571	      self.addItem(value);
3572	      callback(data);
3573	      created = true;
3574	    };
3575	    if (typeof self.settings.create === 'function') {
3576	      output = self.settings.create.call(this, input, create);
3577	    } else {
3578	      output = {
3579	        [self.settings.labelField]: input,
3580	        [self.settings.valueField]: input
3581	      };
3582	    }
3583	    if (!created) {
3584	      create(output);
3585	    }
3586	    return true;
3587	  }
3588
3589	  /**
3590	   * Re-renders the selected item lists.
3591	   */
3592	  refreshItems() {
3593	    var self = this;
3594	    self.isDropdownContentStale = true;
3595	    if (self.isSetup) {
3596	      self.addItems(self.items);
3597	    }
3598	    self.updateOriginalInput();
3599	    self.refreshState();
3600	  }
3601
3602	  /**
3603	   * Updates all state-dependent attributes
3604	   * and CSS classes.
3605	   */
3606	  refreshState() {
3607	    const self = this;
3608	    self.refreshValidityState();
3609	    const isFull = self.isFull();
3610	    const isLocked = self.isLocked;
3611	    self.wrapper.classList.toggle('rtl', self.rtl);
3612	    const wrap_classList = self.wrapper.classList;
3613	    wrap_classList.toggle('focus', self.isFocused);
3614	    wrap_classList.toggle('disabled', self.isDisabled);
3615	    wrap_classList.toggle('readonly', self.isReadOnly);
3616	    wrap_classList.toggle('required', self.isRequired);
3617	    wrap_classList.toggle('invalid', !self.isValid);
3618	    wrap_classList.toggle('locked', isLocked);
3619	    wrap_classList.toggle('full', isFull);
3620	    wrap_classList.toggle('input-active', self.isFocused && !self.isInputHidden);
3621	    wrap_classList.toggle('dropdown-active', self.isOpen);
3622	    wrap_classList.toggle('has-options', isEmptyObject(self.options));
3623	    wrap_classList.toggle('has-items', self.items.length > 0);
3624	  }
3625
3626	  /**
3627	   * Update the `required` attribute of both input and control input.
3628	   *
3629	   * The `required` property needs to be activated on the control input
3630	   * for the error to be displayed at the right place. `required` also
3631	   * needs to be temporarily deactivated on the input since the input is
3632	   * hidden and can't show errors.
3633	   */
3634	  refreshValidityState() {
3635	    var self = this;
3636	    if (!self.input.validity) {
3637	      return;
3638	    }
3639	    self.isValid = self.input.validity.valid;
3640	    self.isInvalid = !self.isValid;
3641	  }
3642
3643	  /**
3644	   * Determines whether or not more items can be added
3645	   * to the control without exceeding the user-defined maximum.
3646	   *
3647	   * @returns {boolean}
3648	   */
3649	  isFull() {
3650	    return this.settings.maxItems !== null && this.items.length >= this.settings.maxItems;
3651	  }
3652
3653	  /**
3654	   * Refreshes the original <select> or <input>
3655	   * element to reflect the current state.
3656	   *
3657	   */
3658	  updateOriginalInput(opts = {}) {
3659	    const self = this;
3660	    var option, label;
3661	    const empty_option = self.input.querySelector('option[value=""]');
3662	    if (self.is_select_tag) {
3663	      const selected = [];
3664	      const has_selected = self.input.querySelectorAll('option:checked').length;
3665	      function AddSelected(option_el, value, label) {
3666	        if (!option_el) {
3667	          option_el = getDom('<option value="' + escape_html(value) + '">' + escape_html(label) + '</option>');
3668	        }
3669
3670	        // don't move empty option from top of list
3671	        // fixes bug in firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1725293
3672	        if (option_el != empty_option) {
3673	          self.input.append(option_el);
3674	        }
3675	        selected.push(option_el);
3676
3677	        // marking empty option as selected can break validation
3678	        // fixes https://github.com/orchidjs/tom-select/issues/303
3679	        if (option_el != empty_option || has_selected > 0) {
3680	          option_el.selected = true;
3681	        }
3682	        return option_el;
3683	      }
3684
3685	      // unselect all selected options
3686	      self.input.querySelectorAll('option:checked').forEach(option_el => {
3687	        option_el.selected = false;
3688	      });
3689
3690	      // nothing selected?
3691	      if (self.items.length == 0 && self.settings.mode == 'single') {
3692	        AddSelected(empty_option, "", "");
3693
3694	        // order selected <option> tags for values in self.items
3695	      } else {
3696	        self.items.forEach(value => {
3697	          option = self.options[value];
3698	          label = option[self.settings.labelField] || '';
3699	          if (selected.includes(option.$option)) {
3700	            const reuse_opt = self.input.querySelector(`option[value="${addSlashes(value)}"]:not(:checked)`);
3701	            AddSelected(reuse_opt, value, label);
3702	          } else {
3703	            option.$option = AddSelected(option.$option, value, label);
3704	          }
3705	        });
3706	      }
3707	    } else {
3708	      self.input.value = self.getValue();
3709	    }
3710	    if (self.isSetup) {
3711	      if (!opts.silent) {
3712	        self.trigger('change', self.getValue());
3713	      }
3714	    }
3715	  }
3716
3717	  /**
3718	   * Shows the autocomplete dropdown containing
3719	   * the available options.
3720	   */
3721	  open() {
3722	    var self = this;
3723	    if (self.isLocked || self.isOpen || self.settings.mode === 'multi' && self.isFull()) return;
3724	    self.isOpen = true;
3725	    setAttr(self.focus_node, {
3726	      'aria-expanded': 'true'
3727	    });
3728	    self.refreshState();
3729	    applyCSS(self.dropdown, {
3730	      visibility: 'hidden',
3731	      display: 'block'
3732	    });
3733	    self.positionDropdown();
3734	    applyCSS(self.dropdown, {
3735	      visibility: 'visible',
3736	      display: 'block'
3737	    });
3738	    self.focus();
3739	    self.trigger('dropdown_open', self.dropdown);
3740	  }
3741
3742	  /**
3743	   * Closes the autocomplete dropdown menu.
3744	   */
3745	  close(setTextboxValue = true) {
3746	    var self = this;
3747	    var trigger = self.isOpen;
3748	    if (setTextboxValue) {
3749	      // before blur() to prevent form onchange event
3750	      self.setTextboxValue();
3751	      if (self.settings.mode === 'single' && self.items.length) {
3752	        self.inputState();
3753	      }
3754	    }
3755	    self.isOpen = false;
3756	    setAttr(self.focus_node, {
3757	      'aria-expanded': 'false'
3758	    });
3759	    applyCSS(self.dropdown, {
3760	      display: 'none'
3761	    });
3762	    if (self.settings.hideSelected) {
3763	      self.clearActiveOption();
3764	    }
3765	    self.refreshState();
3766	    if (trigger) self.trigger('dropdown_close', self.dropdown);
3767	  }
3768
3769	  /**
3770	   * Calculates and applies the appropriate
3771	   * position of the dropdown if dropdownParent = 'body'.
3772	   * Otherwise, position is determined by css
3773	   */
3774	  positionDropdown() {
3775	    if (this.settings.dropdownParent !== 'body') {
3776	      return;
3777	    }
3778	    var context = this.control;
3779	    var rect = context.getBoundingClientRect();
3780	    var top = context.offsetHeight + rect.top + window.scrollY;
3781	    var left = rect.left + window.scrollX;
3782	    applyCSS(this.dropdown, {
3783	      width: rect.width + 'px',
3784	      top: top + 'px',
3785	      left: left + 'px'
3786	    });
3787	  }
3788
3789	  /**
3790	   * Resets / clears all selected items
3791	   * from the control.
3792	   *
3793	   */
3794	  clear(silent) {
3795	    var self = this;
3796	    if (!self.items.length) return;
3797	    var items = self.controlChildren();
3798	    iterate(items, item => {
3799	      self.removeItem(item, true);
3800	    });
3801	    self.inputState();
3802	    if (!silent) self.updateOriginalInput();
3803	    self.trigger('clear');
3804	  }
3805
3806	  /**
3807	   * A helper method for inserting an element
3808	   * at the current caret position.
3809	   *
3810	   */
3811	  insertAtCaret(el) {
3812	    const self = this;
3813	    const caret = self.caretPos;
3814	    const target = self.control;
3815	    target.insertBefore(el, target.children[caret] || null);
3816	    self.setCaret(caret + 1);
3817	  }
3818
3819	  /**
3820	   * Removes the current selected item(s).
3821	   *
3822	   */
3823	  deleteSelection(e) {
3824	    var direction, selection, caret, tail;
3825	    var self = this;
3826	    direction = e && e.keyCode === KEY_BACKSPACE ? -1 : 1;
3827	    selection = getSelection(self.control_input);
3828
3829	    // determine items that will be removed
3830	    const rm_items = [];
3831	    if (self.activeItems.length) {
3832	      tail = getTail(self.activeItems, direction);
3833	      caret = nodeIndex(tail);
3834	      if (direction > 0) {
3835	        caret++;
3836	      }
3837	      iterate(self.activeItems, item => rm_items.push(item));
3838	    } else if ((self.isFocused || self.settings.mode === 'single') && self.items.length) {
3839	      const items = self.controlChildren();
3840	      let rm_item;
3841	      if (direction < 0 && selection.start === 0 && selection.length === 0) {
3842	        rm_item = items[self.caretPos - 1];
3843	      } else if (direction > 0 && selection.start === self.inputValue().length) {
3844	        rm_item = items[self.caretPos];
3845	      }
3846	      if (rm_item !== undefined) {
3847	        rm_items.push(rm_item);
3848	      }
3849	    }
3850	    if (!self.shouldDelete(rm_items, e)) {
3851	      return false;
vendor: 8,053 bytes, lines 3852-4171
3852	    }
3853	    preventDefault(e, true);
3854
3855	    // perform removal
3856	    if (typeof caret !== 'undefined') {
3857	      self.setCaret(caret);
3858	    }
3859	    while (rm_items.length) {
3860	      self.removeItem(rm_items.pop());
3861	    }
3862	    self.inputState();
3863	    self.positionDropdown();
3864	    self.refreshOptions(false);
3865	    return true;
3866	  }
3867
3868	  /**
3869	   * Return true if the items should be deleted
3870	   */
3871	  shouldDelete(items, evt) {
3872	    const values = items.map(item => item.dataset.value);
3873
3874	    // allow the callback to abort
3875	    if (!values.length || typeof this.settings.onDelete === 'function' && this.settings.onDelete.call(this, values, evt) === false) {
3876	      return false;
3877	    }
3878	    return true;
3879	  }
3880
3881	  /**
3882	   * Selects the previous / next item (depending on the `direction` argument).
3883	   *
3884	   * > 0 - right
3885	   * < 0 - left
3886	   *
3887	   */
3888	  advanceSelection(direction, e) {
3889	    var last_active,
3890	      adjacent,
3891	      self = this;
3892	    if (self.rtl) direction *= -1;
3893	    if (self.inputValue().length) return;
3894
3895	    // add or remove to active items
3896	    if (isKeyDown(KEY_SHORTCUT, e) || isKeyDown('shiftKey', e)) {
3897	      last_active = self.getLastActive(direction);
3898	      if (last_active) {
3899	        if (!last_active.classList.contains('active')) {
3900	          adjacent = last_active;
3901	        } else {
3902	          adjacent = self.getAdjacent(last_active, direction, 'item');
3903	        }
3904
3905	        // if no active item, get items adjacent to the control input
3906	      } else if (direction > 0) {
3907	        adjacent = self.control_input.nextElementSibling;
3908	      } else {
3909	        adjacent = self.control_input.previousElementSibling;
3910	      }
3911	      if (adjacent) {
3912	        if (adjacent.classList.contains('active')) {
3913	          self.removeActiveItem(last_active);
3914	        }
3915	        self.setActiveItemClass(adjacent); // mark as last_active !! after removeActiveItem() on last_active
3916	      }
3917
3918	      // move caret to the left or right
3919	    } else {
3920	      self.moveCaret(direction);
3921	    }
3922	  }
3923	  moveCaret(direction) {}
3924
3925	  /**
3926	   * Get the last active item
3927	   *
3928	   */
3929	  getLastActive(direction) {
3930	    let last_active = this.control.querySelector('.last-active');
3931	    if (last_active) {
3932	      return last_active;
3933	    }
3934	    var result = this.control.querySelectorAll('.active');
3935	    if (result) {
3936	      return getTail(result, direction);
3937	    }
3938	  }
3939
3940	  /**
3941	   * Moves the caret to the specified index.
3942	   *
3943	   * The input must be moved by leaving it in place and moving the
3944	   * siblings, due to the fact that focus cannot be restored once lost
3945	   * on mobile webkit devices
3946	   *
3947	   */
3948	  setCaret(new_pos) {
3949	    this.caretPos = this.items.length;
3950	  }
3951
3952	  /**
3953	   * Return list of item dom elements
3954	   *
3955	   */
3956	  controlChildren() {
3957	    return Array.from(this.control.querySelectorAll('[data-ts-item]'));
3958	  }
3959
3960	  /**
3961	   * Disables user input on the control. Used while
3962	   * items are being asynchronously created.
3963	   */
3964	  lock() {
3965	    this.setLocked(true);
3966	  }
3967
3968	  /**
3969	   * Re-enables user input on the control.
3970	   */
3971	  unlock() {
3972	    this.setLocked(false);
3973	  }
3974
3975	  /**
3976	   * Disable or enable user input on the control
3977	   */
3978	  setLocked(lock = this.isReadOnly || this.isDisabled) {
3979	    this.isLocked = lock;
3980	    this.refreshState();
3981	  }
3982
3983	  /**
3984	   * Disables user input on the control completely.
3985	   * While disabled, it cannot receive focus.
3986	   */
3987	  disable() {
3988	    this.setDisabled(true);
3989	    this.close();
3990	  }
3991
3992	  /**
3993	   * Enables the control so that it can respond
3994	   * to focus and user input.
3995	   */
3996	  enable() {
3997	    this.setDisabled(false);
3998	  }
3999	  setDisabled(disabled) {
4000	    this.focus_node.tabIndex = disabled ? -1 : this.tabIndex;
4001	    this.isDisabled = disabled;
4002	    this.input.disabled = disabled;
4003	    this.control_input.disabled = disabled;
4004	    this.setLocked();
4005	  }
4006	  setReadOnly(isReadOnly) {
4007	    this.isReadOnly = isReadOnly;
4008	    this.input.readOnly = isReadOnly;
4009	    this.control_input.readOnly = isReadOnly;
4010	    this.setLocked();
4011	  }
4012
4013	  /**
4014	   * Completely destroys the control and
4015	   * unbinds all event listeners so that it can
4016	   * be garbage collected.
4017	   */
4018	  destroy() {
4019	    var self = this;
4020	    var revertSettings = self.revertSettings;
4021	    self.trigger('destroy');
4022	    self.off();
4023	    self.wrapper.remove();
4024	    self.dropdown.remove();
4025	    self.input.innerHTML = revertSettings.innerHTML;
4026	    self.input.tabIndex = revertSettings.tabIndex;
4027	    removeClasses(self.input, 'tomselected', 'ts-hidden-accessible');
4028	    self._destroy();
4029	    delete self.input.tomselect;
4030	  }
4031
4032	  /**
4033	   * A helper method for rendering "item" and
4034	   * "option" templates, given the data.
4035	   *
4036	   */
4037	  render(templateName, data) {
4038	    var id, html;
4039	    const self = this;
4040	    if (typeof this.settings.render[templateName] !== 'function') {
4041	      return null;
4042	    }
4043
4044	    // render markup
4045	    html = self.settings.render[templateName].call(this, data, escape_html);
4046	    if (!html) {
4047	      return null;
4048	    }
4049	    html = getDom(html);
4050
4051	    // add mandatory attributes
4052	    if (templateName === 'option' || templateName === 'option_create') {
4053	      if (data[self.settings.disabledField]) {
4054	        setAttr(html, {
4055	          'aria-disabled': 'true'
4056	        });
4057	      } else {
4058	        setAttr(html, {
4059	          'data-selectable': ''
4060	        });
4061	      }
4062	    } else if (templateName === 'optgroup') {
4063	      id = data.group[self.settings.optgroupValueField];
4064	      setAttr(html, {
4065	        'data-group': id
4066	      });
4067	      if (data.group[self.settings.disabledField]) {
4068	        setAttr(html, {
4069	          'data-disabled': ''
4070	        });
4071	      }
4072	    }
4073	    if (templateName === 'option' || templateName === 'item') {
4074	      const value = get_hash(data[self.settings.valueField]);
4075	      setAttr(html, {
4076	        'data-value': value
4077	      });
4078
4079	      // make sure we have some classes if a template is overwritten
4080	      if (templateName === 'item') {
4081	        addClasses(html, self.settings.itemClass);
4082	        setAttr(html, {
4083	          'data-ts-item': ''
4084	        });
4085	      } else {
4086	        addClasses(html, self.settings.optionClass);
4087	        setAttr(html, {
4088	          role: 'option',
4089	          id: data.$id
4090	        });
4091
4092	        // update cache
4093	        data.$div = html;
4094	        self.options[value] = data;
4095	      }
4096	    }
4097	    return html;
4098	  }
4099
4100	  /**
4101	   * Type guarded rendering
4102	   *
4103	   */
4104	  _render(templateName, data) {
4105	    const html = this.render(templateName, data);
4106	    if (html == null) {
4107	      throw 'HTMLElement expected';
4108	    }
4109	    return html;
4110	  }
4111
4112	  /**
4113	   * Clears the render cache for a template. If
4114	   * no template is given, clears all render
4115	   * caches.
4116	   *
4117	   */
4118	  clearCache() {
4119	    iterate(this.options, option => {
4120	      if (option.$div) {
4121	        option.$div.remove();
4122	        delete option.$div;
4123	      }
4124	    });
4125	  }
4126
4127	  /**
4128	   * Removes a value from item and option caches
4129	   *
4130	   */
4131	  uncacheValue(value) {
4132	    const option_el = this.getOption(value);
4133	    if (option_el) option_el.remove();
4134	  }
4135
4136	  /**
4137	   * Determines whether or not to display the
4138	   * create item prompt, given a user input.
4139	   *
4140	   */
4141	  canCreate(input) {
4142	    return this.settings.create && input.length > 0 && this.settings.createFilter.call(this, input);
4143	  }
4144
4145	  /**
4146	   * Wraps this.`method` so that `new_fn` can be invoked 'before', 'after', or 'instead' of the original method
4147	   *
4148	   * this.hook('instead','onKeyDown',function( arg1, arg2 ...){
4149	   *
4150	   * });
4151	   */
4152	  hook(when, method, new_fn) {
4153	    var self = this;
4154	    var orig_method = self[method];
4155	    self[method] = function () {
4156	      var result, result_new;
4157	      if (when === 'after') {
4158	        result = orig_method.apply(self, arguments);
4159	      }
4160	      result_new = new_fn.apply(self, arguments);
4161	      if (when === 'instead') {
4162	        return result_new;
4163	      }
4164	      if (when === 'before') {
4165	        result = orig_method.apply(self, arguments);
4166	      }
4167	      return result;
4168	    };
4169	  }
4170	}
4171
vendor: 12,839 bytes, lines 4172-4529
4172	/**
4173	 * Plugin: "change_listener" (Tom Select)
4174	 * Copyright (c) contributors
4175	 *
4176	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4177	 * file except in compliance with the License. You may obtain a copy of the License at:
4178	 * http://www.apache.org/licenses/LICENSE-2.0
4179	 *
4180	 * Unless required by applicable law or agreed to in writing, software distributed under
4181	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4182	 * ANY KIND, either express or implied. See the License for the specific language
4183	 * governing permissions and limitations under the License.
4184	 *
4185	 */
4186
4187	function change_listener () {
4188	  addEvent(this.input, 'change', () => {
4189	    this.sync();
4190	  });
4191	}
4192
4193	/**
4194	 * Plugin: "checkbox_options" (Tom Select)
4195	 * Copyright (c) contributors
4196	 *
4197	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4198	 * file except in compliance with the License. You may obtain a copy of the License at:
4199	 * http://www.apache.org/licenses/LICENSE-2.0
4200	 *
4201	 * Unless required by applicable law or agreed to in writing, software distributed under
4202	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4203	 * ANY KIND, either express or implied. See the License for the specific language
4204	 * governing permissions and limitations under the License.
4205	 *
4206	 */
4207
4208	function checkbox_options (userOptions) {
4209	  var self = this;
4210	  var orig_onOptionSelect = self.onOptionSelect;
4211	  self.settings.hideSelected = false;
4212	  const cbOptions = Object.assign({
4213	    // so that the user may add different ones as well
4214	    className: "tomselect-checkbox",
4215	    // the following default to the historic plugin's values
4216	    checkedClassNames: undefined,
4217	    uncheckedClassNames: undefined
4218	  }, userOptions);
4219	  var UpdateChecked = function UpdateChecked(checkbox, toCheck) {
4220	    if (toCheck) {
4221	      checkbox.checked = true;
4222	      if (cbOptions.uncheckedClassNames) {
4223	        checkbox.classList.remove(...cbOptions.uncheckedClassNames);
4224	      }
4225	      if (cbOptions.checkedClassNames) {
4226	        checkbox.classList.add(...cbOptions.checkedClassNames);
4227	      }
4228	    } else {
4229	      checkbox.checked = false;
4230	      if (cbOptions.checkedClassNames) {
4231	        checkbox.classList.remove(...cbOptions.checkedClassNames);
4232	      }
4233	      if (cbOptions.uncheckedClassNames) {
4234	        checkbox.classList.add(...cbOptions.uncheckedClassNames);
4235	      }
4236	    }
4237	  };
4238
4239	  // update the checkbox for an option
4240	  var UpdateCheckbox = function UpdateCheckbox(option) {
4241	    setTimeout(() => {
4242	      var checkbox = option.querySelector('input.' + cbOptions.className);
4243	      if (checkbox instanceof HTMLInputElement) {
4244	        UpdateChecked(checkbox, option.classList.contains('selected'));
4245	      }
4246	    }, 1);
4247	  };
4248
4249	  // add checkbox to option template
4250	  self.hook('after', 'setupTemplates', () => {
4251	    var orig_render_option = self.settings.render.option;
4252	    self.settings.render.option = (data, escape_html) => {
4253	      var rendered = getDom(orig_render_option.call(self, data, escape_html));
4254	      var checkbox = document.createElement('input');
4255	      if (cbOptions.className) {
4256	        checkbox.classList.add(cbOptions.className);
4257	      }
4258	      checkbox.addEventListener('click', function (evt) {
4259	        preventDefault(evt);
4260	      });
4261	      checkbox.type = 'checkbox';
4262	      const hashed = hash_key(data[self.settings.valueField]);
4263	      UpdateChecked(checkbox, !!(hashed && self.items.indexOf(hashed) > -1));
4264	      rendered.prepend(checkbox);
4265	      return rendered;
4266	    };
4267	  });
4268
4269	  // uncheck when item removed
4270	  self.on('item_remove', value => {
4271	    var option = self.getOption(value);
4272	    if (option) {
4273	      // if dropdown hasn't been opened yet, the option won't exist
4274	      option.classList.remove('selected'); // selected class won't be removed yet
4275	      UpdateCheckbox(option);
4276	    }
4277	  });
4278
4279	  // check when item added
4280	  self.on('item_add', value => {
4281	    var option = self.getOption(value);
4282	    if (option) {
4283	      // if dropdown hasn't been opened yet, the option won't exist
4284	      UpdateCheckbox(option);
4285	    }
4286	  });
4287
4288	  // remove items when selected option is clicked
4289	  self.hook('instead', 'onOptionSelect', (evt, option) => {
4290	    if (option.classList.contains('selected')) {
4291	      option.classList.remove('selected');
4292	      self.removeItem(option.dataset.value);
4293	      self.refreshOptions();
4294	      preventDefault(evt, true);
4295	      return;
4296	    }
4297	    orig_onOptionSelect.call(self, evt, option);
4298	    UpdateCheckbox(option);
4299	  });
4300	}
4301
4302	/**
4303	 * Plugin: "dropdown_header" (Tom Select)
4304	 * Copyright (c) contributors
4305	 *
4306	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4307	 * file except in compliance with the License. You may obtain a copy of the License at:
4308	 * http://www.apache.org/licenses/LICENSE-2.0
4309	 *
4310	 * Unless required by applicable law or agreed to in writing, software distributed under
4311	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4312	 * ANY KIND, either express or implied. See the License for the specific language
4313	 * governing permissions and limitations under the License.
4314	 *
4315	 */
4316
4317	function clear_button (userOptions) {
4318	  const self = this;
4319	  const options = Object.assign({
4320	    className: 'clear-button',
4321	    title: 'Clear All',
4322	    role: 'button',
4323	    tabindex: 0,
4324	    html: data => {
4325	      return `<div class="${data.className}" title="${data.title}" role="${data.role}" tabindex="${data.tabindex}">&times;</div>`;
4326	    }
4327	  }, userOptions);
4328	  self.on('initialize', () => {
4329	    var button = getDom(options.html(options));
4330	    button.addEventListener('click', evt => {
4331	      if (self.isLocked) return;
4332	      self.clear();
4333	      if (self.settings.mode === 'single' && self.settings.allowEmptyOption) {
4334	        self.addItem('');
4335	      }
4336	      self.refreshOptions(false);
4337	      evt.preventDefault();
4338	      evt.stopPropagation();
4339	    });
4340	    self.control.appendChild(button);
4341	  });
4342	}
4343
4344	/**
4345	 * Plugin: "drag_drop" (Tom Select)
4346	 * Copyright (c) contributors
4347	 *
4348	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4349	 * file except in compliance with the License. You may obtain a copy of the License at:
4350	 * http://www.apache.org/licenses/LICENSE-2.0
4351	 *
4352	 * Unless required by applicable law or agreed to in writing, software distributed under
4353	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4354	 * ANY KIND, either express or implied. See the License for the specific language
4355	 * governing permissions and limitations under the License.
4356	 *
4357	 */
4358
4359	const insertAfter = (referenceNode, newNode) => {
4360	  var _referenceNode$parent;
4361	  (_referenceNode$parent = referenceNode.parentNode) == null || _referenceNode$parent.insertBefore(newNode, referenceNode.nextSibling);
4362	};
4363	const insertBefore = (referenceNode, newNode) => {
4364	  var _referenceNode$parent2;
4365	  (_referenceNode$parent2 = referenceNode.parentNode) == null || _referenceNode$parent2.insertBefore(newNode, referenceNode);
4366	};
4367	const isBefore = (referenceNode, newNode) => {
4368	  do {
4369	    var _newNode;
4370	    newNode = (_newNode = newNode) == null ? void 0 : _newNode.previousElementSibling;
4371	    if (referenceNode == newNode) {
4372	      return true;
4373	    }
4374	  } while (newNode && newNode.previousElementSibling);
4375	  return false;
4376	};
4377	function drag_drop () {
4378	  var self = this;
4379	  if (self.settings.mode !== 'multi') return;
4380	  var orig_lock = self.lock;
4381	  var orig_unlock = self.unlock;
4382	  let sortable = true;
4383	  let drag_item;
4384
4385	  /**
4386	   * Add draggable attribute to item
4387	   */
4388	  self.hook('after', 'setupTemplates', () => {
4389	    var orig_render_item = self.settings.render.item;
4390	    self.settings.render.item = (data, escape) => {
4391	      const item = getDom(orig_render_item.call(self, data, escape));
4392	      setAttr(item, {
4393	        'draggable': 'true'
4394	      });
4395
4396	      // prevent doc_mousedown (see tom-select.ts)
4397	      const mousedown = evt => {
4398	        if (!sortable) preventDefault(evt);
4399	        evt.stopPropagation();
4400	      };
4401	      const dragStart = evt => {
4402	        drag_item = item;
4403	        setTimeout(() => {
4404	          item.classList.add('ts-dragging');
4405	        }, 0);
4406	      };
4407	      const dragOver = evt => {
4408	        evt.preventDefault();
4409	        item.classList.add('ts-drag-over');
4410	        moveitem(item, drag_item);
4411	      };
4412	      const dragLeave = () => {
4413	        item.classList.remove('ts-drag-over');
4414	      };
4415	      const moveitem = (targetitem, dragitem) => {
4416	        if (dragitem === undefined) return;
4417	        if (isBefore(dragitem, item)) {
4418	          insertAfter(targetitem, dragitem);
4419	        } else {
4420	          insertBefore(targetitem, dragitem);
4421	        }
4422	      };
4423	      const dragend = () => {
4424	        var _drag_item;
4425	        document.querySelectorAll('.ts-drag-over').forEach(el => el.classList.remove('ts-drag-over'));
4426	        (_drag_item = drag_item) == null || _drag_item.classList.remove('ts-dragging');
4427	        drag_item = undefined;
4428	        var values = [];
4429	        self.control.querySelectorAll(`[data-value]`).forEach(el => {
4430	          if (el.dataset.value) {
4431	            let value = el.dataset.value;
4432	            if (value) {
4433	              values.push(value);
4434	            }
4435	          }
4436	        });
4437	        self.setValue(values);
4438	      };
4439	      addEvent(item, 'mousedown', mousedown);
4440	      addEvent(item, 'dragstart', dragStart);
4441	      addEvent(item, 'dragenter', dragOver);
4442	      addEvent(item, 'dragover', dragOver);
4443	      addEvent(item, 'dragleave', dragLeave);
4444	      addEvent(item, 'dragend', dragend);
4445	      return item;
4446	    };
4447	  });
4448	  self.hook('instead', 'lock', () => {
4449	    sortable = false;
4450	    return orig_lock.call(self);
4451	  });
4452	  self.hook('instead', 'unlock', () => {
4453	    sortable = true;
4454	    return orig_unlock.call(self);
4455	  });
4456	}
4457
4458	/**
4459	 * Plugin: "dropdown_header" (Tom Select)
4460	 * Copyright (c) contributors
4461	 *
4462	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4463	 * file except in compliance with the License. You may obtain a copy of the License at:
4464	 * http://www.apache.org/licenses/LICENSE-2.0
4465	 *
4466	 * Unless required by applicable law or agreed to in writing, software distributed under
4467	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4468	 * ANY KIND, either express or implied. See the License for the specific language
4469	 * governing permissions and limitations under the License.
4470	 *
4471	 */
4472
4473	function dropdown_header (userOptions) {
4474	  const self = this;
4475	  const options = Object.assign({
4476	    title: 'Untitled',
4477	    headerClass: 'dropdown-header',
4478	    titleRowClass: 'dropdown-header-title',
4479	    labelClass: 'dropdown-header-label',
4480	    closeClass: 'dropdown-header-close',
4481	    html: data => {
4482	      return '<div class="' + data.headerClass + '">' + '<div class="' + data.titleRowClass + '">' + '<span class="' + data.labelClass + '">' + data.title + '</span>' + '<a class="' + data.closeClass + '">&times;</a>' + '</div>' + '</div>';
4483	    }
4484	  }, userOptions);
4485	  self.on('initialize', () => {
4486	    var header = getDom(options.html(options));
4487	    var close_link = header.querySelector('.' + options.closeClass);
4488	    if (close_link) {
4489	      close_link.addEventListener('click', evt => {
4490	        preventDefault(evt, true);
4491	        self.close();
4492	      });
4493	    }
4494	    self.dropdown.insertBefore(header, self.dropdown.firstChild);
4495	  });
4496	}
4497
4498	/**
4499	 * Plugin: "dropdown_input" (Tom Select)
4500	 * Copyright (c) contributors
4501	 *
4502	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4503	 * file except in compliance with the License. You may obtain a copy of the License at:
4504	 * http://www.apache.org/licenses/LICENSE-2.0
4505	 *
4506	 * Unless required by applicable law or agreed to in writing, software distributed under
4507	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4508	 * ANY KIND, either express or implied. See the License for the specific language
4509	 * governing permissions and limitations under the License.
4510	 *
4511	 */
4512
4513	function caret_position () {
4514	  var self = this;
4515
4516	  /**
4517	   * Moves the caret to the specified index.
4518	   *
4519	   * The input must be moved by leaving it in place and moving the
4520	   * siblings, due to the fact that focus cannot be restored once lost
4521	   * on mobile webkit devices
4522	   *
4523	   */
4524	  self.hook('instead', 'setCaret', new_pos => {
4525	    if (self.settings.mode === 'single' || !self.control.contains(self.control_input)) {
4526	      new_pos = self.items.length;
4527	    } else {
4528	      new_pos = Math.max(0, Math.min(self.items.length, new_pos));
4529	      if (new_pos != self.caretPos && !self.isPending) {
vendor: 4,332 bytes, lines 4530-4648
4530	        self.controlChildren().forEach((child, j) => {
4531	          if (j < new_pos) {
4532	            self.control_input.insertAdjacentElement('beforebegin', child);
4533	          } else {
4534	            self.control.appendChild(child);
4535	          }
4536	        });
4537	      }
4538	    }
4539	    self.caretPos = new_pos;
4540	  });
4541	  self.hook('instead', 'moveCaret', direction => {
4542	    if (!self.isFocused) return;
4543
4544	    // move caret before or after selected items
4545	    const last_active = self.getLastActive(direction);
4546	    if (last_active) {
4547	      const idx = nodeIndex(last_active);
4548	      self.setCaret(direction > 0 ? idx + 1 : idx);
4549	      self.setActiveItem();
4550	      removeClasses(last_active, 'last-active');
4551
4552	      // move caret left or right of current position
4553	    } else {
4554	      self.setCaret(self.caretPos + direction);
4555	    }
4556	  });
4557	}
4558
4559	/**
4560	 * Plugin: "dropdown_input" (Tom Select)
4561	 * Copyright (c) contributors
4562	 *
4563	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4564	 * file except in compliance with the License. You may obtain a copy of the License at:
4565	 * http://www.apache.org/licenses/LICENSE-2.0
4566	 *
4567	 * Unless required by applicable law or agreed to in writing, software distributed under
4568	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4569	 * ANY KIND, either express or implied. See the License for the specific language
4570	 * governing permissions and limitations under the License.
4571	 *
4572	 */
4573
4574	function dropdown_input () {
4575	  const self = this;
4576	  self.settings.shouldOpen = true; // make sure the input is shown even if there are no options to display in the dropdown
4577
4578	  self.hook('before', 'setup', () => {
4579	    var _self$input;
4580	    self.focus_node = self.control;
4581	    addClasses(self.control_input, 'dropdown-input');
4582	    const div = getDom('<div class="dropdown-input-wrap">');
4583	    div.append(self.control_input);
4584	    self.dropdown.insertBefore(div, self.dropdown.firstChild);
4585
4586	    // set a placeholder in the select control
4587	    const placeholder = getDom('<input class="items-placeholder" tabindex="-1" />');
4588	    placeholder.placeholder = self.settings.placeholder || '';
4589	    self.control.append(placeholder);
4590	    /**
4591	     * TomSelect renders a custom control with a focusable <input class="items-placeholder">.
4592	     * The source <select>'s aria-label is not automatically propagated to that input,
4593	     * which triggers "Missing form label" accessibility warnings.
4594	     * This helper copies the label from the <select> onto the generated input.
4595	     */
4596	    const label = (_self$input = self.input) == null ? void 0 : _self$input.getAttribute('aria-label');
4597	    if (!label) return;
4598	    placeholder.setAttribute('aria-label', label);
4599	  });
4600	  self.on('initialize', () => {
4601	    // set tabIndex on control to -1, otherwise [shift+tab] will put focus right back on control_input
4602	    self.control_input.addEventListener('keydown', evt => {
4603	      //addEvent(self.control_input,'keydown' as const,(evt:KeyboardEvent) =>{
4604	      switch (evt.keyCode) {
4605	        case KEY_ESC:
4606	          if (self.isOpen) {
4607	            preventDefault(evt, true);
4608	            self.close();
4609	          }
4610	          self.clearActiveItems();
4611	          return;
4612	        case KEY_TAB:
4613	          self.focus_node.tabIndex = -1;
4614	          break;
4615	      }
4616	      return self.onKeyDown.call(self, evt);
4617	    });
4618	    self.on('blur', () => {
4619	      self.focus_node.tabIndex = self.isDisabled ? -1 : self.tabIndex;
4620	    });
4621
4622	    // give the control_input focus when the dropdown is open
4623	    self.on('dropdown_open', () => {
4624	      self.control_input.focus();
4625	    });
4626
4627	    // prevent onBlur from closing when focus is on the control_input
4628	    const orig_onBlur = self.onBlur;
4629	    self.hook('instead', 'onBlur', evt => {
4630	      if (evt && evt.relatedTarget == self.control_input) return;
4631	      return orig_onBlur.call(self);
4632	    });
4633	    addEvent(self.control_input, 'blur', () => self.onBlur());
4634
4635	    // return focus to control to allow further keyboard input
4636	    self.hook('before', 'close', () => {
4637	      if (!self.isOpen) return;
4638	      self.focus_node.focus({
4639	        preventScroll: true
4640	      });
4641	    });
4642	  });
4643	}
4644
4645	/**
4646	 * Plugin: "input_autogrow" (Tom Select)
4647	 *
4648	 * Licensed under the Apache License, Version 2.0 (the "License");
vendor: 5,457 bytes, lines 4648-4794
4648 you may not use this
4649	 * file except in compliance with the License. You may obtain a copy of the License at:
4650	 * http://www.apache.org/licenses/LICENSE-2.0
4651	 *
4652	 * Unless required by applicable law or agreed to in writing, software distributed under
4653	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4654	 * ANY KIND, either express or implied. See the License for the specific language
4655	 * governing permissions and limitations under the License.
4656	 *
4657	 */
4658
4659	function input_autogrow () {
4660	  var self = this;
4661	  self.on('initialize', () => {
4662	    var test_input = document.createElement('span');
4663	    var control = self.control_input;
4664	    test_input.style.cssText = 'position:absolute; top:-99999px; left:-99999px; width:auto; padding:0; white-space:pre; ';
4665	    self.wrapper.appendChild(test_input);
4666	    var transfer_styles = ['letterSpacing', 'fontSize', 'fontFamily', 'fontWeight', 'textTransform'];
4667	    for (const style_name of transfer_styles) {
4668	      // @ts-ignore TS7015 https://stackoverflow.com/a/50506154/697576
4669	      test_input.style[style_name] = control.style[style_name];
4670	    }
4671
4672	    /**
4673	     * Set the control width
4674	     *
4675	     */
4676	    var resize = () => {
4677	      test_input.textContent = control.value;
4678	      control.style.width = test_input.clientWidth + 'px';
4679	    };
4680	    resize();
4681	    self.on('update item_add item_remove', resize);
4682	    addEvent(control, 'input', resize);
4683	    addEvent(control, 'keyup', resize);
4684	    addEvent(control, 'blur', resize);
4685	    addEvent(control, 'update', resize);
4686	  });
4687	}
4688
4689	/**
4690	 * Plugin: "input_autogrow" (Tom Select)
4691	 *
4692	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4693	 * file except in compliance with the License. You may obtain a copy of the License at:
4694	 * http://www.apache.org/licenses/LICENSE-2.0
4695	 *
4696	 * Unless required by applicable law or agreed to in writing, software distributed under
4697	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4698	 * ANY KIND, either express or implied. See the License for the specific language
4699	 * governing permissions and limitations under the License.
4700	 *
4701	 */
4702
4703	function no_backspace_delete () {
4704	  var self = this;
4705	  var orig_deleteSelection = self.deleteSelection;
4706	  this.hook('instead', 'deleteSelection', evt => {
4707	    if (self.activeItems.length) {
4708	      return orig_deleteSelection.call(self, evt);
4709	    }
4710	    return false;
4711	  });
4712	}
4713
4714	/**
4715	 * Plugin: "no_active_items" (Tom Select)
4716	 *
4717	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4718	 * file except in compliance with the License. You may obtain a copy of the License at:
4719	 * http://www.apache.org/licenses/LICENSE-2.0
4720	 *
4721	 * Unless required by applicable law or agreed to in writing, software distributed under
4722	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4723	 * ANY KIND, either express or implied. See the License for the specific language
4724	 * governing permissions and limitations under the License.
4725	 *
4726	 */
4727
4728	function no_active_items () {
4729	  this.hook('instead', 'setActiveItem', () => {});
4730	  this.hook('instead', 'selectAll', () => {});
4731	}
4732
4733	/**
4734	 * Plugin: "optgroup_columns" (Tom Select.js)
4735	 * Copyright (c) contributors
4736	 *
4737	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4738	 * file except in compliance with the License. You may obtain a copy of the License at:
4739	 * http://www.apache.org/licenses/LICENSE-2.0
4740	 *
4741	 * Unless required by applicable law or agreed to in writing, software distributed under
4742	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4743	 * ANY KIND, either express or implied. See the License for the specific language
4744	 * governing permissions and limitations under the License.
4745	 *
4746	 */
4747
4748	function optgroup_columns () {
4749	  var self = this;
4750	  var orig_keydown = self.onKeyDown;
4751	  self.hook('instead', 'onKeyDown', evt => {
4752	    var index, option, options, optgroup;
4753	    if (!self.isOpen || !(evt.keyCode === KEY_LEFT || evt.keyCode === KEY_RIGHT)) {
4754	      return orig_keydown.call(self, evt);
4755	    }
4756	    self.ignoreHover = true;
4757	    optgroup = parentMatch(self.activeOption, '[data-group]');
4758	    index = nodeIndex(self.activeOption, '[data-selectable]');
4759	    if (!optgroup) {
4760	      return;
4761	    }
4762	    if (evt.keyCode === KEY_LEFT) {
4763	      optgroup = optgroup.previousSibling;
4764	    } else {
4765	      optgroup = optgroup.nextSibling;
4766	    }
4767	    if (!optgroup) {
4768	      return;
4769	    }
4770	    options = optgroup.querySelectorAll('[data-selectable]');
4771	    option = options[Math.min(options.length - 1, index)];
4772	    if (option) {
4773	      self.setActiveOption(option);
4774	    }
4775	  });
4776	}
4777
4778	/**
4779	 * Plugin: "remove_button" (Tom Select)
4780	 * Copyright (c) contributors
4781	 *
4782	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4783	 * file except in compliance with the License. You may obtain a copy of the License at:
4784	 * http://www.apache.org/licenses/LICENSE-2.0
4785	 *
4786	 * Unless required by applicable law or agreed to in writing, software distributed under
4787	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4788	 * ANY KIND, either express or implied. See the License for the specific language
4789	 * governing permissions and limitations under the License.
4790	 *
4791	 */
4792
4793	function remove_button (userOptions) {
4794	  const 
vendor: 4,084 bytes, lines 4794-4910
4794options = Object.assign({
4795	    label: '&times;',
4796	    title: 'Remove',
4797	    className: 'remove',
4798	    append: true
4799	  }, userOptions);
4800
4801	  //options.className = 'remove-single';
4802	  var self = this;
4803
4804	  // override the render method to add remove button to each item
4805	  if (!options.append) {
4806	    return;
4807	  }
4808	  var html = '<a href="javascript:void(0)" class="' + options.className + '" tabindex="-1" title="' + escape_html(options.title) + '">' + options.label + '</a>';
4809	  self.hook('after', 'setupTemplates', () => {
4810	    var orig_render_item = self.settings.render.item;
4811	    self.settings.render.item = (data, escape) => {
4812	      var item = getDom(orig_render_item.call(self, data, escape));
4813	      var close_button = getDom(html);
4814	      item.appendChild(close_button);
4815	      addEvent(close_button, 'mousedown', evt => {
4816	        preventDefault(evt, true);
4817	      });
4818	      addEvent(close_button, 'click', evt => {
4819	        if (self.isLocked) return;
4820
4821	        // propagating will trigger the dropdown to show for single mode
4822	        preventDefault(evt, true);
4823	        if (self.isLocked) return;
4824	        if (!self.shouldDelete([item], evt)) return;
4825	        self.removeItem(item);
4826	        self.refreshOptions(false);
4827	        self.inputState();
4828	      });
4829	      return item;
4830	    };
4831	  });
4832	}
4833
4834	/**
4835	 * Plugin: "restore_on_backspace" (Tom Select)
4836	 * Copyright (c) contributors
4837	 *
4838	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4839	 * file except in compliance with the License. You may obtain a copy of the License at:
4840	 * http://www.apache.org/licenses/LICENSE-2.0
4841	 *
4842	 * Unless required by applicable law or agreed to in writing, software distributed under
4843	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4844	 * ANY KIND, either express or implied. See the License for the specific language
4845	 * governing permissions and limitations under the License.
4846	 *
4847	 */
4848
4849	function restore_on_backspace (userOptions) {
4850	  const self = this;
4851	  const options = Object.assign({
4852	    text: option => {
4853	      return option[self.settings.labelField];
4854	    }
4855	  }, userOptions);
4856	  self.on('item_remove', function (value) {
4857	    if (!self.isFocused) {
4858	      return;
4859	    }
4860	    if (self.control_input.value.trim() === '') {
4861	      var option = self.options[value];
4862	      if (option) {
4863	        self.setTextboxValue(options.text.call(self, option));
4864	      }
4865	    }
4866	  });
4867	}
4868
4869	/**
4870	 * Plugin: "virtual_scroll" (Tom Select)
4871	 * Copyright (c) contributors
4872	 *
4873	 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
4874	 * file except in compliance with the License. You may obtain a copy of the License at:
4875	 * http://www.apache.org/licenses/LICENSE-2.0
4876	 *
4877	 * Unless required by applicable law or agreed to in writing, software distributed under
4878	 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
4879	 * ANY KIND, either express or implied. See the License for the specific language
4880	 * governing permissions and limitations under the License.
4881	 *
4882	 */
4883
4884	function virtual_scroll () {
4885	  const self = this;
4886	  const orig_canLoad = self.canLoad;
4887	  const orig_clearActiveOption = self.clearActiveOption;
4888	  const orig_loadCallback = self.loadCallback;
4889	  var pagination = {};
4890	  var dropdown_content;
4891	  var loading_more = false;
4892	  var load_more_opt;
4893	  var default_values = [];
4894	  var default_values_loaded = false;
4895	  var default_pagination;
4896	  if (!self.settings.shouldLoadMore) {
4897	    // return true if additional results should be loaded
4898	    self.settings.shouldLoadMore = () => {
4899	      const scroll_percent = dropdown_content.clientHeight / (dropdown_content.scrollHeight - dropdown_content.scrollTop);
4900	      if (scroll_percent > 0.9) {
4901	        return true;
4902	      }
4903	      if (self.activeOption) {
4904	        var selectable = self.selectable();
4905	        var index = Array.from(selectable).indexOf(self.activeOption);
4906	        if (index >= selectable.length - 2) {
4907	          return true;
4908	        }
4909	      }
4910	      return false;
vendor: 4,903 bytes, lines 4911-5068
4911	    };
4912	  }
4913	  if (!self.settings.firstUrl) {
4914	    throw 'virtual_scroll plugin requires a firstUrl() method';
4915	  }
4916
4917	  // in order for virtual scrolling to work,
4918	  // options need to be ordered the same way they're returned from the remote data source
4919	  self.settings.sortField = [{
4920	    field: '$order'
4921	  }, {
4922	    field: '$score'
4923	  }];
4924
4925	  // can we load more results for given query?
4926	  const canLoadMore = query => {
4927	    if (typeof self.settings.maxOptions === 'number' && dropdown_content.children.length >= self.settings.maxOptions) {
4928	      return false;
4929	    }
4930	    if (query in pagination && pagination[query]) {
4931	      return true;
4932	    }
4933	    return false;
4934	  };
4935	  const clearFilter = (option, value) => {
4936	    if (self.items.indexOf(value) >= 0 || default_values.indexOf(value) >= 0) {
4937	      return true;
4938	    }
4939	    return false;
4940	  };
4941
4942	  // set the next url that will be
4943	  self.setNextUrl = (value, next_url) => {
4944	    pagination[value] = next_url;
4945	  };
4946
4947	  // getUrl() to be used in settings.load()
4948	  self.getUrl = query => {
4949	    if (query in pagination) {
4950	      const next_url = pagination[query];
4951	      pagination[query] = false;
4952	      return next_url;
4953	    }
4954
4955	    // if the user goes back to a previous query
4956	    // we need to load the first page again
4957	    self.clearPagination();
4958	    return self.settings.firstUrl.call(self, query);
4959	  };
4960
4961	  // clear pagination
4962	  self.clearPagination = () => {
4963	    pagination = {};
4964	  };
4965
4966	  // don't clear the active option (and cause unwanted dropdown scroll)
4967	  // while loading more results
4968	  self.hook('instead', 'clearActiveOption', () => {
4969	    if (loading_more) {
4970	      return;
4971	    }
4972	    return orig_clearActiveOption.call(self);
4973	  });
4974
4975	  // override the canLoad method
4976	  self.hook('instead', 'canLoad', query => {
4977	    // first time the query has been seen
4978	    if (!(query in pagination)) {
4979	      return orig_canLoad.call(self, query);
4980	    }
4981	    return canLoadMore(query);
4982	  });
4983
4984	  // wrap the load
4985	  self.hook('instead', 'loadCallback', (options, optgroups) => {
4986	    if (!loading_more) {
4987	      self.clearOptions(clearFilter);
4988	    } else if (load_more_opt) {
4989	      const first_option = options[0];
4990	      if (first_option !== undefined) {
4991	        load_more_opt.dataset.value = first_option[self.settings.valueField];
4992	      }
4993	    }
4994	    orig_loadCallback.call(self, options, optgroups);
4995
4996	    // After the initial preload (empty query), update default_values to include
4997	    // preloaded options, not just the HTML <option> elements captured on initialize
4998	    if (!loading_more && !default_values_loaded) {
4999	      default_values_loaded = true;
5000	      if (self.lastValue === '') {
5001	        default_values = Object.keys(self.options);
5002	        default_pagination = pagination[''];
5003	      }
5004	    }
5005	    loading_more = false;
5006	  });
5007
5008	  // as the “loading_more” element will be removed from the dropdown,
5009	  // we activate the previous option if needed
5010	  // to avoid the dropdown being scrolled back to the first one
5011	  self.hook('before', 'refreshOptions', () => {
5012	    if (self.activeOption && "option" !== self.activeOption.getAttribute("role")) {
5013	      self.setActiveOption(self.activeOption.previousElementSibling);
5014	    }
5015	  });
5016
5017	  // add templates to dropdown
5018	  //	loading_more if we have another url in the queue
5019	  //	no_more_results if we don't have another url in the queue
5020	  self.hook('after', 'refreshOptions', () => {
5021	    const query = self.lastValue;
5022	    var option;
5023	    if (canLoadMore(query)) {
5024	      option = self.render('loading_more', {
5025	        query: query
5026	      });
5027	      if (option) {
5028	        option.setAttribute('data-selectable', ''); // so that navigating dropdown with [down] keypresses can navigate to this node
5029	        load_more_opt = option;
5030	      }
5031	    } else if (query in pagination && !dropdown_content.querySelector('.no-results')) {
5032	      option = self.render('no_more_results', {
5033	        query: query
5034	      });
5035	    }
5036	    if (option) {
5037	      addClasses(option, self.settings.optionClass);
5038	      dropdown_content.append(option);
5039	    }
5040	  });
5041
5042	  // Restore preloaded options and pagination when clearing search
5043	  const restoreDefaults = () => {
5044	    if (!default_values_loaded) {
5045	      return;
5046	    }
5047	    self.clearOptions(clearFilter);
5048	    if (default_pagination) {
5049	      pagination[''] = default_pagination;
5050	    }
5051	  };
5052	  self.on('type', query => {
5053	    if (query === '') {
5054	      restoreDefaults();
5055	      self.refreshOptions(false);
5056	    }
5057	  });
5058	  self.on('dropdown_close', restoreDefaults);
5059
5060	  // add scroll listener and default templates
5061	  self.on('initialize', () => {
5062	    default_values = Object.keys(self.options);
5063	    dropdown_content = self.dropdown_content;
5064
5065	    // default templates
5066	    self.settings.render = Object.assign({}, {
5067	      loading_more: () => {
5068	        return `<div class="loading-more-results">
5068Loading more results ... </div>`;
5069	      },
5070	      no_more_results: () => {
5071	        return `<div class="no-more-results">No more results</div>`;
5072	      }
5073	    }, self.settings.render);
5074
5075	    // watch dropdown content scroll position
5076	    dropdown_content.addEventListener('scroll', () => {
5077	      if (!self.settings.shouldLoadMore.call(self)) {
5078	        return;
5079	      }
5080
5081	      // !important: this will get checked again in load() but we still need to check here otherwise loading_more will be set to true
5082	      if (!canLoadMore(self.lastValue)) {
5083	        return;
5084	      }
5085
5086	      // don't call load() too much
5087	      if (loading_more) return;
5088	      loading_more = true;
5089	      self.load.call(self, self.lastValue);
5090	    });
5091	  });
5092	}
5093
5094	TomSelect.define('change_listener', change_listener);
5095	TomSelect.define('checkbox_options', checkbox_options);
5096	TomSelect.define('clear_button', clear_button);
5097	TomSelect.define('drag_drop', drag_drop);
5098	TomSelect.define('dropdown_header', dropdown_header);
5099	TomSelect.define('caret_position', caret_position);
5100	TomSelect.define('dropdown_input', dropdown_input);
5101	TomSelect.define('input_autogrow', input_autogrow);
5102	TomSelect.define('no_backspace_delete', no_backspace_delete);
5103	TomSelect.define('no_active_items', no_active_items);
5104	TomSelect.define('optgroup_columns', optgroup_columns);
5105	TomSelect.define('remove_button', remove_button);
5106	TomSelect.define('restore_on_backspace', restore_on_backspace);
5107	TomSelect.define('virtual_scroll', virtual_scroll);
5108
5109	return TomSelect;
5110
5111}));
5112var tomSelect=function(el,opts){return new TomSelect(el,opts);} 
5113//# sourceMappingURL=tom-select.complete.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.