tom-select-rails 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/lib/tom-select-rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/tom-select-rails/cjs/tom-select.complete.js +168 -84
  4. data/vendor/assets/javascripts/tom-select-rails/cjs/tom-select.complete.js.map +1 -1
  5. data/vendor/assets/javascripts/tom-select-rails/cjs/tom-select.js +132 -59
  6. data/vendor/assets/javascripts/tom-select-rails/cjs/tom-select.js.map +1 -1
  7. data/vendor/assets/javascripts/tom-select-rails/cjs/tom-select.popular.js +140 -65
  8. data/vendor/assets/javascripts/tom-select-rails/cjs/tom-select.popular.js.map +1 -1
  9. data/vendor/assets/javascripts/tom-select-rails/cjs/utils.js +1 -1
  10. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/caret_position/plugin.js +3 -3
  11. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/caret_position/plugin.js.map +1 -1
  12. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/change_listener/plugin.js +1 -1
  13. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/checkbox_options/plugin.js +9 -7
  14. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/checkbox_options/plugin.js.map +1 -1
  15. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/clear_button/plugin.js +3 -3
  16. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/clear_button/plugin.js.map +1 -1
  17. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/drag_drop/plugin.js +1 -1
  18. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/dropdown_header/plugin.js +3 -3
  19. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/dropdown_header/plugin.js.map +1 -1
  20. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/dropdown_input/plugin.js +6 -4
  21. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/dropdown_input/plugin.js.map +1 -1
  22. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/input_autogrow/plugin.js +3 -7
  23. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/input_autogrow/plugin.js.map +1 -1
  24. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/no_active_items/plugin.js +1 -1
  25. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/no_backspace_delete/plugin.js +1 -1
  26. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/optgroup_columns/plugin.js +4 -3
  27. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/optgroup_columns/plugin.js.map +1 -1
  28. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/remove_button/plugin.js +8 -8
  29. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/remove_button/plugin.js.map +1 -1
  30. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/restore_on_backspace/plugin.js +1 -1
  31. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/virtual_scroll/plugin.js +22 -12
  32. data/vendor/assets/javascripts/tom-select-rails/esm/plugins/virtual_scroll/plugin.js.map +1 -1
  33. data/vendor/assets/javascripts/tom-select-rails/esm/tom-select.complete.js +168 -84
  34. data/vendor/assets/javascripts/tom-select-rails/esm/tom-select.complete.js.map +1 -1
  35. data/vendor/assets/javascripts/tom-select-rails/esm/tom-select.js +132 -59
  36. data/vendor/assets/javascripts/tom-select-rails/esm/tom-select.js.map +1 -1
  37. data/vendor/assets/javascripts/tom-select-rails/esm/tom-select.popular.js +140 -65
  38. data/vendor/assets/javascripts/tom-select-rails/esm/tom-select.popular.js.map +1 -1
  39. data/vendor/assets/javascripts/tom-select-rails/esm/utils.js +1 -1
  40. data/vendor/assets/javascripts/tom-select-rails/js/plugins/caret_position.js +3 -3
  41. data/vendor/assets/javascripts/tom-select-rails/js/plugins/caret_position.js.map +1 -1
  42. data/vendor/assets/javascripts/tom-select-rails/js/plugins/change_listener.js +1 -1
  43. data/vendor/assets/javascripts/tom-select-rails/js/plugins/checkbox_options.js +9 -7
  44. data/vendor/assets/javascripts/tom-select-rails/js/plugins/checkbox_options.js.map +1 -1
  45. data/vendor/assets/javascripts/tom-select-rails/js/plugins/clear_button.js +3 -3
  46. data/vendor/assets/javascripts/tom-select-rails/js/plugins/clear_button.js.map +1 -1
  47. data/vendor/assets/javascripts/tom-select-rails/js/plugins/drag_drop.js +1 -1
  48. data/vendor/assets/javascripts/tom-select-rails/js/plugins/dropdown_header.js +3 -3
  49. data/vendor/assets/javascripts/tom-select-rails/js/plugins/dropdown_header.js.map +1 -1
  50. data/vendor/assets/javascripts/tom-select-rails/js/plugins/dropdown_input.js +6 -4
  51. data/vendor/assets/javascripts/tom-select-rails/js/plugins/dropdown_input.js.map +1 -1
  52. data/vendor/assets/javascripts/tom-select-rails/js/plugins/input_autogrow.js +3 -7
  53. data/vendor/assets/javascripts/tom-select-rails/js/plugins/input_autogrow.js.map +1 -1
  54. data/vendor/assets/javascripts/tom-select-rails/js/plugins/no_active_items.js +1 -1
  55. data/vendor/assets/javascripts/tom-select-rails/js/plugins/no_backspace_delete.js +1 -1
  56. data/vendor/assets/javascripts/tom-select-rails/js/plugins/optgroup_columns.js +4 -3
  57. data/vendor/assets/javascripts/tom-select-rails/js/plugins/optgroup_columns.js.map +1 -1
  58. data/vendor/assets/javascripts/tom-select-rails/js/plugins/remove_button.js +8 -8
  59. data/vendor/assets/javascripts/tom-select-rails/js/plugins/remove_button.js.map +1 -1
  60. data/vendor/assets/javascripts/tom-select-rails/js/plugins/restore_on_backspace.js +1 -1
  61. data/vendor/assets/javascripts/tom-select-rails/js/plugins/virtual_scroll.js +22 -12
  62. data/vendor/assets/javascripts/tom-select-rails/js/plugins/virtual_scroll.js.map +1 -1
  63. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.base.js +132 -59
  64. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.base.js.map +1 -1
  65. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.base.min.js +142 -142
  66. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.base.min.js.map +1 -1
  67. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.complete.js +168 -84
  68. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.complete.js.map +1 -1
  69. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.complete.min.js +157 -156
  70. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.complete.min.js.map +1 -1
  71. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.popular.js +140 -65
  72. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.popular.js.map +1 -1
  73. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.popular.min.js +142 -143
  74. data/vendor/assets/javascripts/tom-select-rails/js/tom-select.popular.min.js.map +1 -1
  75. data/vendor/assets/javascripts/tom-select-rails/types/tom-select.d.ts +20 -3
  76. data/vendor/assets/javascripts/tom-select-rails/types/types/core.d.ts +2 -1
  77. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.bootstrap4.css +3 -7
  78. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.bootstrap4.css.map +1 -1
  79. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.bootstrap4.min.css +1 -1
  80. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.bootstrap4.min.css.map +1 -1
  81. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.bootstrap5.css +3 -7
  82. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.bootstrap5.css.map +1 -1
  83. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.bootstrap5.min.css +1 -1
  84. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.bootstrap5.min.css.map +1 -1
  85. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.css +7 -11
  86. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.css.map +1 -1
  87. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.default.css +3 -7
  88. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.default.css.map +1 -1
  89. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.default.min.css +1 -1
  90. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.default.min.css.map +1 -1
  91. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.min.css +1 -1
  92. data/vendor/assets/stylesheets/tom-select-rails/css/tom-select.min.css.map +1 -1
  93. data/vendor/assets/stylesheets/tom-select-rails/scss/_dropdown.scss +0 -2
  94. data/vendor/assets/stylesheets/tom-select-rails/scss/tom-select.scss +4 -4
  95. metadata +3 -3
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Tom Select v2.0.3
2
+ * Tom Select v2.1.0
3
3
  * Licensed under the Apache License, Version 2.0 (the "License");
4
4
  */
5
5
 
@@ -187,24 +187,20 @@ function MicroPlugin(Interface) {
187
187
  };
188
188
  }
189
189
 
190
+ // @ts-ignore TS2691 "An import path cannot end with a '.ts' extension"
190
191
  // https://github.com/andrewrk/node-diacritics/blob/master/index.js
191
192
  var latin_pat;
192
193
  const accent_pat = '[\u0300-\u036F\u{b7}\u{2be}]'; // \u{2bc}
193
194
 
194
- const accent_reg = new RegExp(accent_pat, 'g');
195
+ const accent_reg = new RegExp(accent_pat, 'gu');
195
196
  var diacritic_patterns;
196
197
  const latin_convert = {
197
198
  'æ': 'ae',
198
199
  'ⱥ': 'a',
199
200
  'ø': 'o'
200
201
  };
201
- const convert_pat = new RegExp(Object.keys(latin_convert).join('|'), 'g');
202
- /**
203
- * code points generated from toCodePoints();
204
- * removed 65339 to 65345
205
- */
206
-
207
- const code_points = [[67, 67], [160, 160], [192, 438], [452, 652], [961, 961], [1019, 1019], [1083, 1083], [1281, 1289], [1984, 1984], [5095, 5095], [7429, 7441], [7545, 7549], [7680, 7935], [8580, 8580], [9398, 9449], [11360, 11391], [42792, 42793], [42802, 42851], [42873, 42897], [42912, 42922], [64256, 64260], [65313, 65338], [65345, 65370]];
202
+ const convert_pat = new RegExp(Object.keys(latin_convert).join('|'), 'gu');
203
+ const code_points = [[0, 65535]];
208
204
  /**
209
205
  * Remove accents
210
206
  * via https://github.com/krisk/Fuse/issues/133#issuecomment-318692703
@@ -223,7 +219,6 @@ const asciifold = str => {
223
219
  *
224
220
  */
225
221
 
226
-
227
222
  const arrayToPattern = (chars, glue = '|') => {
228
223
  if (chars.length == 1) {
229
224
  return chars[0];
@@ -240,6 +235,10 @@ const arrayToPattern = (chars, glue = '|') => {
240
235
 
241
236
  return '(?:' + chars.join(glue) + ')';
242
237
  };
238
+ const escapeToPattern = chars => {
239
+ const escaped = chars.map(diacritic => escape_regex(diacritic));
240
+ return arrayToPattern(escaped);
241
+ };
243
242
  /**
244
243
  * Get all possible combinations of substrings that add up to the given string
245
244
  * https://stackoverflow.com/questions/30169587/find-all-the-combination-of-substrings-that-add-up-to-the-given-string
@@ -264,7 +263,7 @@ const allSubstrings = input => {
264
263
  *
265
264
  */
266
265
 
267
- const generateDiacritics = () => {
266
+ const generateDiacritics = code_points => {
268
267
  var diacritics = {};
269
268
  code_points.forEach(code_range => {
270
269
  for (let i = code_range[0]; i <= code_range[1]; i++) {
@@ -273,13 +272,22 @@ const generateDiacritics = () => {
273
272
 
274
273
  if (latin == diacritic.toLowerCase()) {
275
274
  continue;
275
+ } // skip when latin is a string longer than 3 characters long
276
+ // bc the resulting regex patterns will be long
277
+ // eg:
278
+ // latin صلى الله عليه وسلم length 18 code point 65018
279
+ // latin جل جلاله length 8 code point 65019
280
+
281
+
282
+ if (latin.length > 3) {
283
+ continue;
276
284
  }
277
285
 
278
286
  if (!(latin in diacritics)) {
279
287
  diacritics[latin] = [latin];
280
288
  }
281
289
 
282
- var patt = new RegExp(arrayToPattern(diacritics[latin]), 'iu');
290
+ var patt = new RegExp(escapeToPattern(diacritics[latin]), 'iu');
283
291
 
284
292
  if (diacritic.match(patt)) {
285
293
  continue;
@@ -287,13 +295,23 @@ const generateDiacritics = () => {
287
295
 
288
296
  diacritics[latin].push(diacritic);
289
297
  }
290
- });
291
- var latin_chars = Object.keys(diacritics); // latin character pattern
298
+ }); // filter out if there's only one character in the list
299
+
300
+ let latin_chars = Object.keys(diacritics);
301
+
302
+ for (let i = 0; i < latin_chars.length; i++) {
303
+ const latin = latin_chars[i];
304
+
305
+ if (diacritics[latin].length < 2) {
306
+ delete diacritics[latin];
307
+ }
308
+ } // latin character pattern
292
309
  // match longer substrings first
293
310
 
294
- latin_chars = latin_chars.sort((a, b) => b.length - a.length);
295
- latin_pat = new RegExp('(' + arrayToPattern(latin_chars) + accent_pat + '*)', 'g'); // build diacritic patterns
296
- // ae needs:
311
+
312
+ latin_chars = Object.keys(diacritics).sort((a, b) => b.length - a.length);
313
+ latin_pat = new RegExp('(' + escapeToPattern(latin_chars) + accent_pat + '*)', 'gu'); // build diacritic patterns
314
+ // ae needs:
297
315
  // (?:(?:ae|Æ|Ǽ|Ǣ)|(?:A|Ⓐ|A...)(?:E|ɛ|Ⓔ...))
298
316
 
299
317
  var diacritic_patterns = {};
@@ -302,7 +320,7 @@ const generateDiacritics = () => {
302
320
  var pattern = substrings.map(sub_pat => {
303
321
  sub_pat = sub_pat.map(l => {
304
322
  if (diacritics.hasOwnProperty(l)) {
305
- return arrayToPattern(diacritics[l]);
323
+ return escapeToPattern(diacritics[l]);
306
324
  }
307
325
 
308
326
  return l;
@@ -321,27 +339,20 @@ const generateDiacritics = () => {
321
339
 
322
340
  const diacriticRegexPoints = regex => {
323
341
  if (diacritic_patterns === undefined) {
324
- diacritic_patterns = generateDiacritics();
342
+ diacritic_patterns = generateDiacritics(code_points);
325
343
  }
326
344
 
327
345
  const decomposed = regex.normalize('NFKD').toLowerCase();
328
346
  return decomposed.split(latin_pat).map(part => {
329
- if (part == '') {
330
- return '';
331
- } // "ffl" or "ffl"
332
-
333
-
347
+ // "ffl" or "ffl"
334
348
  const no_accent = asciifold(part);
335
349
 
350
+ if (no_accent == '') {
351
+ return '';
352
+ }
353
+
336
354
  if (diacritic_patterns.hasOwnProperty(no_accent)) {
337
355
  return diacritic_patterns[no_accent];
338
- } // 'أهلا' (\u{623}\u{647}\u{644}\u{627}) or 'أهلا' (\u{627}\u{654}\u{647}\u{644}\u{627})
339
-
340
-
341
- const composed_part = part.normalize('NFC');
342
-
343
- if (composed_part != part) {
344
- return arrayToPattern([part, composed_part]);
345
356
  }
346
357
 
347
358
  return part;
@@ -507,10 +518,10 @@ class Sifter {
507
518
  }
508
519
 
509
520
  if (word.length > 0) {
510
- regex = escape_regex(word);
511
-
512
521
  if (this.settings.diacritics) {
513
- regex = diacriticRegexPoints(regex);
522
+ regex = diacriticRegexPoints(word);
523
+ } else {
524
+ regex = escape_regex(word);
514
525
  }
515
526
 
516
527
  if (respect_word_boundaries) regex = "\\b" + regex;
@@ -1526,6 +1537,7 @@ class TomSelect extends MicroPlugin(MicroEvent) {
1526
1537
  this.isInputHidden = false;
1527
1538
  this.isSetup = false;
1528
1539
  this.ignoreFocus = false;
1540
+ this.ignoreHover = false;
1529
1541
  this.hasOptions = false;
1530
1542
  this.currentResults = void 0;
1531
1543
  this.lastValue = '';
@@ -1724,7 +1736,13 @@ class TomSelect extends MicroPlugin(MicroEvent) {
1724
1736
  settings.load = loadDebounce(settings.load, settings.loadThrottle);
1725
1737
  }
1726
1738
 
1727
- self.control_input.type = input.type; // clicking on an option should select it
1739
+ self.control_input.type = input.type;
1740
+ addEvent(dropdown, 'mouseenter', e => {
1741
+ var target_match = parentMatch(e.target, '[data-selectable]', dropdown);
1742
+ if (target_match) self.onOptionHover(e, target_match);
1743
+ }, {
1744
+ capture: true
1745
+ }); // clicking on an option should select it
1728
1746
 
1729
1747
  addEvent(dropdown, 'click', evt => {
1730
1748
  const option = parentMatch(evt.target, '[data-selectable]');
@@ -1758,7 +1776,7 @@ class TomSelect extends MicroPlugin(MicroEvent) {
1758
1776
  addEvent(focus_node, 'resize', () => self.positionDropdown(), passive_event);
1759
1777
  addEvent(focus_node, 'blur', e => self.onBlur(e));
1760
1778
  addEvent(focus_node, 'focus', e => self.onFocus(e));
1761
- addEvent(focus_node, 'paste', e => self.onPaste(e));
1779
+ addEvent(control_input, 'paste', e => self.onPaste(e));
1762
1780
 
1763
1781
  const doc_mousedown = evt => {
1764
1782
  // blur if target is outside of this instance
@@ -1785,18 +1803,24 @@ class TomSelect extends MicroPlugin(MicroEvent) {
1785
1803
  }
1786
1804
  };
1787
1805
 
1788
- var win_scroll = () => {
1806
+ const win_scroll = () => {
1789
1807
  if (self.isOpen) {
1790
1808
  self.positionDropdown();
1791
1809
  }
1792
1810
  };
1793
1811
 
1812
+ const win_hover = () => {
1813
+ self.ignoreHover = false;
1814
+ };
1815
+
1794
1816
  addEvent(document, 'mousedown', doc_mousedown);
1795
1817
  addEvent(window, 'scroll', win_scroll, passive_event);
1796
1818
  addEvent(window, 'resize', win_scroll, passive_event);
1819
+ addEvent(window, 'mousemove', win_hover, passive_event);
1797
1820
 
1798
1821
  this._destroy = () => {
1799
1822
  document.removeEventListener('mousedown', doc_mousedown);
1823
+ window.removeEventListener('mousemove', win_hover);
1800
1824
  window.removeEventListener('scroll', win_scroll);
1801
1825
  window.removeEventListener('resize', win_scroll);
1802
1826
  if (label) label.removeEventListener('click', label_click);
@@ -2002,21 +2026,29 @@ class TomSelect extends MicroPlugin(MicroEvent) {
2002
2026
  // input and create Items for each separate value
2003
2027
 
2004
2028
 
2005
- if (self.settings.splitOn) {
2006
- // Wait for pasted text to be recognized in value
2007
- setTimeout(() => {
2008
- var pastedText = self.inputValue();
2029
+ if (!self.settings.splitOn) {
2030
+ return;
2031
+ } // Wait for pasted text to be recognized in value
2009
2032
 
2010
- if (!pastedText.match(self.settings.splitOn)) {
2011
- return;
2012
- }
2013
2033
 
2014
- var splitInput = pastedText.trim().split(self.settings.splitOn);
2015
- iterate(splitInput, piece => {
2034
+ setTimeout(() => {
2035
+ var pastedText = self.inputValue();
2036
+
2037
+ if (!pastedText.match(self.settings.splitOn)) {
2038
+ return;
2039
+ }
2040
+
2041
+ var splitInput = pastedText.trim().split(self.settings.splitOn);
2042
+ iterate(splitInput, piece => {
2043
+ piece = hash_key(piece);
2044
+
2045
+ if (this.options[piece]) {
2046
+ self.addItem(piece);
2047
+ } else {
2016
2048
  self.createItem(piece);
2017
- });
2018
- }, 0);
2019
- }
2049
+ }
2050
+ });
2051
+ }, 0);
2020
2052
  }
2021
2053
  /**
2022
2054
  * Triggered on <input> keypress.
@@ -2048,6 +2080,7 @@ class TomSelect extends MicroPlugin(MicroEvent) {
2048
2080
 
2049
2081
  onKeyDown(e) {
2050
2082
  var self = this;
2083
+ self.ignoreHover = true;
2051
2084
 
2052
2085
  if (self.isLocked) {
2053
2086
  if (e.keyCode !== KEY_TAB) {
@@ -2108,6 +2141,8 @@ class TomSelect extends MicroPlugin(MicroEvent) {
2108
2141
  self.onOptionSelect(e, self.activeOption);
2109
2142
  preventDefault(e); // if the option_create=null, the dropdown might be closed
2110
2143
  } else if (self.settings.create && self.createItem()) {
2144
+ preventDefault(e); // don't submit form when searching for a value
2145
+ } else if (document.activeElement == self.control_input && self.isOpen) {
2111
2146
  preventDefault(e);
2112
2147
  }
2113
2148
 
@@ -2178,6 +2213,17 @@ class TomSelect extends MicroPlugin(MicroEvent) {
2178
2213
  self.trigger('type', value);
2179
2214
  }
2180
2215
  }
2216
+ /**
2217
+ * Triggered when the user rolls over
2218
+ * an option in the autocomplete dropdown menu.
2219
+ *
2220
+ */
2221
+
2222
+
2223
+ onOptionHover(evt, option) {
2224
+ if (this.ignoreHover) return;
2225
+ this.setActiveOption(option, false);
2226
+ }
2181
2227
  /**
2182
2228
  * Triggered on <input> focus.
2183
2229
  *
@@ -2532,7 +2578,7 @@ class TomSelect extends MicroPlugin(MicroEvent) {
2532
2578
  */
2533
2579
 
2534
2580
 
2535
- setActiveOption(option) {
2581
+ setActiveOption(option, scroll = true) {
2536
2582
  if (option === this.activeOption) {
2537
2583
  return;
2538
2584
  }
@@ -2547,7 +2593,7 @@ class TomSelect extends MicroPlugin(MicroEvent) {
2547
2593
  'aria-selected': 'true'
2548
2594
  });
2549
2595
  addClasses(option, 'active');
2550
- this.scrollToOption(option);
2596
+ if (scroll) this.scrollToOption(option);
2551
2597
  }
2552
2598
  /**
2553
2599
  * Sets the dropdown_content scrollTop to display the option
@@ -3180,13 +3226,14 @@ class TomSelect extends MicroPlugin(MicroEvent) {
3180
3226
  */
3181
3227
 
3182
3228
 
3183
- clearOptions() {
3229
+ clearOptions(filter) {
3230
+ const boundFilter = (filter || this.clearFilter).bind(this);
3184
3231
  this.loadedSearches = {};
3185
3232
  this.userOptions = {};
3186
3233
  this.clearCache();
3187
- var selected = {};
3234
+ const selected = {};
3188
3235
  iterate(this.options, (option, key) => {
3189
- if (this.items.indexOf(key) >= 0) {
3236
+ if (boundFilter(option, key)) {
3190
3237
  selected[key] = this.options[key];
3191
3238
  }
3192
3239
  });
@@ -3194,6 +3241,20 @@ class TomSelect extends MicroPlugin(MicroEvent) {
3194
3241
  this.lastQuery = null;
3195
3242
  this.trigger('option_clear');
3196
3243
  }
3244
+ /**
3245
+ * Used by clearOptions() to decide whether or not an option should be removed
3246
+ * Return true to keep an option, false to remove
3247
+ *
3248
+ */
3249
+
3250
+
3251
+ clearFilter(option, value) {
3252
+ if (this.items.indexOf(value) >= 0) {
3253
+ return true;
3254
+ }
3255
+
3256
+ return false;
3257
+ }
3197
3258
  /**
3198
3259
  * Returns the dom element of the option
3199
3260
  * matching the given value.
@@ -3513,11 +3574,11 @@ class TomSelect extends MicroPlugin(MicroEvent) {
3513
3574
  refreshValidityState() {
3514
3575
  var self = this;
3515
3576
 
3516
- if (!self.input.checkValidity) {
3577
+ if (!self.input.validity) {
3517
3578
  return;
3518
3579
  }
3519
3580
 
3520
- self.isValid = self.input.checkValidity();
3581
+ self.isValid = self.input.validity.valid;
3521
3582
  self.isInvalid = !self.isValid;
3522
3583
  }
3523
3584
  /**
@@ -3744,9 +3805,7 @@ class TomSelect extends MicroPlugin(MicroEvent) {
3744
3805
  }
3745
3806
  }
3746
3807
 
3747
- const values = rm_items.map(item => item.dataset.value); // allow the callback to abort
3748
-
3749
- if (!values.length || typeof self.settings.onDelete === 'function' && self.settings.onDelete.call(self, values, e) === false) {
3808
+ if (!self.shouldDelete(rm_items, e)) {
3750
3809
  return false;
3751
3810
  }
3752
3811
 
@@ -3765,6 +3824,20 @@ class TomSelect extends MicroPlugin(MicroEvent) {
3765
3824
  self.refreshOptions(false);
3766
3825
  return true;
3767
3826
  }
3827
+ /**
3828
+ * Return true if the items should be deleted
3829
+ */
3830
+
3831
+
3832
+ shouldDelete(items, evt) {
3833
+ const values = items.map(item => item.dataset.value); // allow the callback to abort
3834
+
3835
+ if (!values.length || typeof this.settings.onDelete === 'function' && this.settings.onDelete(values, evt) === false) {
3836
+ return false;
3837
+ }
3838
+
3839
+ return true;
3840
+ }
3768
3841
  /**
3769
3842
  * Selects the previous / next item (depending on the `direction` argument).
3770
3843
  *
@@ -4122,10 +4195,12 @@ function checkbox_options () {
4122
4195
  setTimeout(() => {
4123
4196
  var checkbox = option.querySelector('input');
4124
4197
 
4125
- if (option.classList.contains('selected')) {
4126
- checkbox.checked = true;
4127
- } else {
4128
- checkbox.checked = false;
4198
+ if (checkbox instanceof HTMLInputElement) {
4199
+ if (option.classList.contains('selected')) {
4200
+ checkbox.checked = true;
4201
+ } else {
4202
+ checkbox.checked = false;
4203
+ }
4129
4204
  }
4130
4205
  }, 1);
4131
4206
  }; // add checkbox to option template
@@ -4452,7 +4527,9 @@ function dropdown_input () {
4452
4527
 
4453
4528
  self.hook('before', 'close', () => {
4454
4529
  if (!self.isOpen) return;
4455
- self.focus_node.focus();
4530
+ self.focus_node.focus({
4531
+ preventScroll: true
4532
+ });
4456
4533
  });
4457
4534
  });
4458
4535
  }
@@ -4490,12 +4567,8 @@ function input_autogrow () {
4490
4567
 
4491
4568
 
4492
4569
  var resize = () => {
4493
- if (self.items.length > 0) {
4494
- test_input.textContent = control.value;
4495
- control.style.width = test_input.clientWidth + 'px';
4496
- } else {
4497
- control.style.width = '';
4498
- }
4570
+ test_input.textContent = control.value;
4571
+ control.style.width = test_input.clientWidth + 'px';
4499
4572
  };
4500
4573
 
4501
4574
  resize();
@@ -4574,6 +4647,7 @@ function optgroup_columns () {
4574
4647
  return orig_keydown.call(self, evt);
4575
4648
  }
4576
4649
 
4650
+ self.ignoreHover = true;
4577
4651
  optgroup = parentMatch(self.activeOption, '[data-group]');
4578
4652
  index = nodeIndex(self.activeOption, '[data-selectable]');
4579
4653
 
@@ -4633,9 +4707,9 @@ function remove_button (userOptions) {
4633
4707
  var orig_render_item = self.settings.render.item;
4634
4708
 
4635
4709
  self.settings.render.item = (data, escape) => {
4636
- var rendered = getDom(orig_render_item.call(self, data, escape));
4710
+ var item = getDom(orig_render_item.call(self, data, escape));
4637
4711
  var close_button = getDom(html);
4638
- rendered.appendChild(close_button);
4712
+ item.appendChild(close_button);
4639
4713
  addEvent(close_button, 'mousedown', evt => {
4640
4714
  preventDefault(evt, true);
4641
4715
  });
@@ -4643,12 +4717,12 @@ function remove_button (userOptions) {
4643
4717
  // propagating will trigger the dropdown to show for single mode
4644
4718
  preventDefault(evt, true);
4645
4719
  if (self.isLocked) return;
4646
- var value = rendered.dataset.value;
4647
- self.removeItem(value);
4720
+ if (!self.shouldDelete([item], evt)) return;
4721
+ self.removeItem(item);
4648
4722
  self.refreshOptions(false);
4649
4723
  self.inputState();
4650
4724
  });
4651
- return rendered;
4725
+ return item;
4652
4726
  };
4653
4727
  });
4654
4728
  }
@@ -4712,10 +4786,11 @@ function virtual_scroll () {
4712
4786
  var dropdown_content;
4713
4787
  var loading_more = false;
4714
4788
  var load_more_opt;
4789
+ var default_values = [];
4715
4790
 
4716
4791
  if (!self.settings.shouldLoadMore) {
4717
4792
  // return true if additional results should be loaded
4718
- self.settings.shouldLoadMore = function () {
4793
+ self.settings.shouldLoadMore = () => {
4719
4794
  const scroll_percent = dropdown_content.clientHeight / (dropdown_content.scrollHeight - dropdown_content.scrollTop);
4720
4795
 
4721
4796
  if (scroll_percent > 0.9) {
@@ -4747,7 +4822,7 @@ function virtual_scroll () {
4747
4822
  field: '$score'
4748
4823
  }]; // can we load more results for given query?
4749
4824
 
4750
- function canLoadMore(query) {
4825
+ const canLoadMore = query => {
4751
4826
  if (typeof self.settings.maxOptions === 'number' && dropdown_content.children.length >= self.settings.maxOptions) {
4752
4827
  return false;
4753
4828
  }
@@ -4757,15 +4832,23 @@ function virtual_scroll () {
4757
4832
  }
4758
4833
 
4759
4834
  return false;
4760
- } // set the next url that will be
4835
+ };
4836
+
4837
+ const clearFilter = (option, value) => {
4838
+ if (self.items.indexOf(value) >= 0 || default_values.indexOf(value) >= 0) {
4839
+ return true;
4840
+ }
4841
+
4842
+ return false;
4843
+ }; // set the next url that will be
4761
4844
 
4762
4845
 
4763
- self.setNextUrl = function (value, next_url) {
4846
+ self.setNextUrl = (value, next_url) => {
4764
4847
  pagination[value] = next_url;
4765
4848
  }; // getUrl() to be used in settings.load()
4766
4849
 
4767
4850
 
4768
- self.getUrl = function (query) {
4851
+ self.getUrl = query => {
4769
4852
  if (query in pagination) {
4770
4853
  const next_url = pagination[query];
4771
4854
  pagination[query] = false;
@@ -4799,7 +4882,7 @@ function virtual_scroll () {
4799
4882
 
4800
4883
  self.hook('instead', 'loadCallback', (options, optgroups) => {
4801
4884
  if (!loading_more) {
4802
- self.clearOptions();
4885
+ self.clearOptions(clearFilter);
4803
4886
  } else if (load_more_opt && options.length > 0) {
4804
4887
  load_more_opt.dataset.value = options[0][self.settings.valueField];
4805
4888
  }
@@ -4837,18 +4920,19 @@ function virtual_scroll () {
4837
4920
  }); // add scroll listener and default templates
4838
4921
 
4839
4922
  self.on('initialize', () => {
4923
+ default_values = Object.keys(self.options);
4840
4924
  dropdown_content = self.dropdown_content; // default templates
4841
4925
 
4842
4926
  self.settings.render = Object.assign({}, {
4843
- loading_more: function () {
4927
+ loading_more: () => {
4844
4928
  return `<div class="loading-more-results">Loading more results ... </div>`;
4845
4929
  },
4846
- no_more_results: function () {
4930
+ no_more_results: () => {
4847
4931
  return `<div class="no-more-results">No more results</div>`;
4848
4932
  }
4849
4933
  }, self.settings.render); // watch dropdown content scroll position
4850
4934
 
4851
- dropdown_content.addEventListener('scroll', function () {
4935
+ dropdown_content.addEventListener('scroll', () => {
4852
4936
  if (!self.settings.shouldLoadMore.call(self)) {
4853
4937
  return;
4854
4938
  } // !important: this will get checked again in load() but we still need to check here otherwise loading_more will be set to true