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