tom-select-rails 2.3.1 → 2.4.3

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