tom-select-rails 2.2.2 → 2.4.3

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