tabulator-tables 5.2.7 → 5.3.2

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 (214) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.js +28 -0
  3. package/.github/workflows/bad-files-check.yml +39 -0
  4. package/.github/workflows/lint-and-test.yml +31 -0
  5. package/README.md +3 -3
  6. package/bower.json +1 -1
  7. package/build/Bundler.js +77 -77
  8. package/dist/css/tabulator.css +12 -7
  9. package/dist/css/tabulator.css.map +1 -1
  10. package/dist/css/tabulator.min.css +1 -1
  11. package/dist/css/tabulator.min.css.map +1 -1
  12. package/dist/css/tabulator_bootstrap3.css +12 -7
  13. package/dist/css/tabulator_bootstrap3.css.map +1 -1
  14. package/dist/css/tabulator_bootstrap3.min.css +1 -1
  15. package/dist/css/tabulator_bootstrap3.min.css.map +1 -1
  16. package/dist/css/tabulator_bootstrap4.css +12 -7
  17. package/dist/css/tabulator_bootstrap4.css.map +1 -1
  18. package/dist/css/tabulator_bootstrap4.min.css +1 -1
  19. package/dist/css/tabulator_bootstrap4.min.css.map +1 -1
  20. package/dist/css/tabulator_bootstrap5.css +12 -7
  21. package/dist/css/tabulator_bootstrap5.css.map +1 -1
  22. package/dist/css/tabulator_bootstrap5.min.css +1 -1
  23. package/dist/css/tabulator_bootstrap5.min.css.map +1 -1
  24. package/dist/css/tabulator_bulma.css +12 -7
  25. package/dist/css/tabulator_bulma.css.map +1 -1
  26. package/dist/css/tabulator_bulma.min.css +1 -1
  27. package/dist/css/tabulator_bulma.min.css.map +1 -1
  28. package/dist/css/tabulator_materialize.css +12 -7
  29. package/dist/css/tabulator_materialize.css.map +1 -1
  30. package/dist/css/tabulator_materialize.min.css +1 -1
  31. package/dist/css/tabulator_materialize.min.css.map +1 -1
  32. package/dist/css/tabulator_midnight.css +12 -7
  33. package/dist/css/tabulator_midnight.css.map +1 -1
  34. package/dist/css/tabulator_midnight.min.css +1 -1
  35. package/dist/css/tabulator_midnight.min.css.map +1 -1
  36. package/dist/css/tabulator_modern.css +12 -7
  37. package/dist/css/tabulator_modern.css.map +1 -1
  38. package/dist/css/tabulator_modern.min.css +1 -1
  39. package/dist/css/tabulator_modern.min.css.map +1 -1
  40. package/dist/css/tabulator_semanticui.css +12 -7
  41. package/dist/css/tabulator_semanticui.css.map +1 -1
  42. package/dist/css/tabulator_semanticui.min.css +1 -1
  43. package/dist/css/tabulator_semanticui.min.css.map +1 -1
  44. package/dist/css/tabulator_simple.css +12 -7
  45. package/dist/css/tabulator_simple.css.map +1 -1
  46. package/dist/css/tabulator_simple.min.css +1 -1
  47. package/dist/css/tabulator_simple.min.css.map +1 -1
  48. package/dist/css/tabulator_site.css +12 -7
  49. package/dist/css/tabulator_site.css.map +1 -1
  50. package/dist/css/tabulator_site.min.css +1 -1
  51. package/dist/css/tabulator_site.min.css.map +1 -1
  52. package/dist/js/jquery_wrapper.js +37 -37
  53. package/dist/js/tabulator.js +1551 -793
  54. package/dist/js/tabulator.js.map +1 -1
  55. package/dist/js/tabulator.min.js +2 -2
  56. package/dist/js/tabulator.min.js.map +1 -1
  57. package/dist/js/tabulator_esm.js +4300 -3581
  58. package/dist/js/tabulator_esm.js.map +1 -1
  59. package/dist/js/tabulator_esm.min.js +2 -2
  60. package/dist/js/tabulator_esm.min.js.map +1 -1
  61. package/package.json +4 -1
  62. package/src/js/builds/jquery_wrapper.js +37 -37
  63. package/src/js/core/ColumnManager.js +270 -232
  64. package/src/js/core/CoreFeature.js +16 -2
  65. package/src/js/core/FooterManager.js +10 -10
  66. package/src/js/core/Module.js +8 -8
  67. package/src/js/core/RowManager.js +139 -156
  68. package/src/js/core/Tabulator.js +88 -74
  69. package/src/js/core/TabulatorFull.js +1 -1
  70. package/src/js/core/cell/Cell.js +15 -16
  71. package/src/js/core/cell/CellComponent.js +2 -2
  72. package/src/js/core/column/Column.js +81 -68
  73. package/src/js/core/column/ColumnComponent.js +4 -4
  74. package/src/js/core/column/defaults/options.js +1 -1
  75. package/src/js/core/defaults/options.js +4 -2
  76. package/src/js/core/rendering/Renderer.js +19 -19
  77. package/src/js/core/rendering/renderers/BasicHorizontal.js +1 -2
  78. package/src/js/core/rendering/renderers/BasicVertical.js +1 -1
  79. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +42 -58
  80. package/src/js/core/rendering/renderers/VirtualDomVertical.js +31 -22
  81. package/src/js/core/row/Row.js +32 -8
  82. package/src/js/core/row/RowComponent.js +8 -4
  83. package/src/js/core/tools/Alert.js +44 -45
  84. package/src/js/core/tools/ComponentFunctionBinder.js +4 -2
  85. package/src/js/core/tools/DataLoader.js +3 -3
  86. package/src/js/core/tools/DeprecationAdvisor.js +47 -0
  87. package/src/js/core/tools/ExternalEventBus.js +5 -5
  88. package/src/js/core/tools/InteractionMonitor.js +41 -39
  89. package/src/js/core/tools/InternalEventBus.js +5 -5
  90. package/src/js/core/tools/ModuleBinder.js +6 -6
  91. package/src/js/core/tools/OptionsList.js +4 -4
  92. package/src/js/core/tools/Popup.js +211 -202
  93. package/src/js/modules/Accessor/Accessor.js +16 -16
  94. package/src/js/modules/Accessor/defaults/accessors.js +1 -1
  95. package/src/js/modules/Ajax/Ajax.js +7 -7
  96. package/src/js/modules/Ajax/defaults/loaderPromise.js +19 -19
  97. package/src/js/modules/Ajax/defaults/urlGenerator.js +1 -1
  98. package/src/js/modules/Clipboard/Clipboard.js +23 -23
  99. package/src/js/modules/Clipboard/defaults/pasteParsers.js +0 -2
  100. package/src/js/modules/ColumnCalcs/CalcComponent.js +2 -2
  101. package/src/js/modules/ColumnCalcs/ColumnCalcs.js +55 -51
  102. package/src/js/modules/ColumnCalcs/defaults/calculations.js +1 -1
  103. package/src/js/modules/DataTree/DataTree.js +24 -15
  104. package/src/js/modules/Download/Download.js +15 -8
  105. package/src/js/modules/Download/defaults/downloaders/csv.js +28 -28
  106. package/src/js/modules/Download/defaults/downloaders/html.js +2 -2
  107. package/src/js/modules/Download/defaults/downloaders/json.js +14 -14
  108. package/src/js/modules/Download/defaults/downloaders/jsonLines.js +1 -1
  109. package/src/js/modules/Download/defaults/downloaders/pdf.js +17 -19
  110. package/src/js/modules/Download/defaults/downloaders/xlsx.js +2 -2
  111. package/src/js/modules/Edit/Edit.js +219 -201
  112. package/src/js/modules/Edit/List.js +1026 -1006
  113. package/src/js/modules/Edit/defaults/editors/autocomplete.js +3 -3
  114. package/src/js/modules/Edit/defaults/editors/date.js +110 -0
  115. package/src/js/modules/Edit/defaults/editors/datetime.js +97 -0
  116. package/src/js/modules/Edit/defaults/editors/input.js +7 -7
  117. package/src/js/modules/Edit/defaults/editors/list.js +2 -2
  118. package/src/js/modules/Edit/defaults/editors/number.js +12 -12
  119. package/src/js/modules/Edit/defaults/editors/progress.js +11 -11
  120. package/src/js/modules/Edit/defaults/editors/range.js +5 -5
  121. package/src/js/modules/Edit/defaults/editors/select.js +3 -3
  122. package/src/js/modules/Edit/defaults/editors/star.js +9 -9
  123. package/src/js/modules/Edit/defaults/editors/textarea.js +97 -92
  124. package/src/js/modules/Edit/defaults/editors/tickCross.js +1 -3
  125. package/src/js/modules/Edit/defaults/editors/time.js +98 -0
  126. package/src/js/modules/Edit/defaults/editors.js +8 -2
  127. package/src/js/modules/Edit/inputMask.js +19 -26
  128. package/src/js/modules/Export/Export.js +69 -65
  129. package/src/js/modules/Filter/Filter.js +88 -95
  130. package/src/js/modules/Format/Format.js +24 -26
  131. package/src/js/modules/Format/defaults/formatters/buttonCross.js +1 -1
  132. package/src/js/modules/Format/defaults/formatters/buttonTick.js +1 -1
  133. package/src/js/modules/Format/defaults/formatters/color.js +1 -1
  134. package/src/js/modules/Format/defaults/formatters/datetime.js +7 -7
  135. package/src/js/modules/Format/defaults/formatters/datetimediff.js +7 -7
  136. package/src/js/modules/Format/defaults/formatters/handle.js +1 -1
  137. package/src/js/modules/Format/defaults/formatters/html.js +1 -1
  138. package/src/js/modules/Format/defaults/formatters/image.js +9 -9
  139. package/src/js/modules/Format/defaults/formatters/link.js +10 -10
  140. package/src/js/modules/Format/defaults/formatters/lookup.js +1 -1
  141. package/src/js/modules/Format/defaults/formatters/money.js +1 -1
  142. package/src/js/modules/Format/defaults/formatters/plaintext.js +1 -1
  143. package/src/js/modules/Format/defaults/formatters/progress.js +41 -42
  144. package/src/js/modules/Format/defaults/formatters/responsiveCollapse.js +3 -3
  145. package/src/js/modules/Format/defaults/formatters/rowSelection.js +1 -1
  146. package/src/js/modules/Format/defaults/formatters/rownum.js +9 -2
  147. package/src/js/modules/Format/defaults/formatters/star.js +1 -1
  148. package/src/js/modules/Format/defaults/formatters/textarea.js +1 -1
  149. package/src/js/modules/Format/defaults/formatters/tickCross.js +1 -1
  150. package/src/js/modules/Format/defaults/formatters/traffic.js +14 -14
  151. package/src/js/modules/FrozenColumns/FrozenColumns.js +6 -8
  152. package/src/js/modules/FrozenRows/FrozenRows.js +37 -7
  153. package/src/js/modules/GroupRows/Group.js +7 -7
  154. package/src/js/modules/GroupRows/GroupComponent.js +2 -2
  155. package/src/js/modules/GroupRows/GroupRows.js +34 -11
  156. package/src/js/modules/History/History.js +2 -2
  157. package/src/js/modules/HtmlTableImport/HtmlTableImport.js +3 -6
  158. package/src/js/modules/Import/Import.js +158 -159
  159. package/src/js/modules/Import/defaults/importers/array.js +5 -0
  160. package/src/js/modules/Import/defaults/importers/csv.js +49 -49
  161. package/src/js/modules/Import/defaults/importers/json.js +6 -6
  162. package/src/js/modules/Import/defaults/importers.js +2 -0
  163. package/src/js/modules/Interaction/Interaction.js +42 -43
  164. package/src/js/modules/Keybindings/Keybindings.js +14 -14
  165. package/src/js/modules/Keybindings/defaults/actions.js +1 -2
  166. package/src/js/modules/Layout/Layout.js +4 -5
  167. package/src/js/modules/Layout/defaults/modes/fitColumns.js +13 -16
  168. package/src/js/modules/Layout/defaults/modes/fitData.js +6 -4
  169. package/src/js/modules/Layout/defaults/modes/fitDataGeneral.js +2 -2
  170. package/src/js/modules/Layout/defaults/modes/fitDataStretch.js +2 -2
  171. package/src/js/modules/Localize/Localize.js +7 -7
  172. package/src/js/modules/Menu/Menu.js +8 -11
  173. package/src/js/modules/MoveColumns/MoveColumns.js +3 -6
  174. package/src/js/modules/MoveRows/MoveRows.js +30 -36
  175. package/src/js/modules/Mutator/Mutator.js +9 -9
  176. package/src/js/modules/Page/Page.js +73 -80
  177. package/src/js/modules/Page/defaults/pageCounters/pages.js +2 -2
  178. package/src/js/modules/Page/defaults/pageCounters/rows.js +1 -1
  179. package/src/js/modules/Persistence/Persistence.js +40 -44
  180. package/src/js/modules/Persistence/defaults/readers.js +1 -1
  181. package/src/js/modules/Popup/Popup.js +4 -5
  182. package/src/js/modules/Print/Print.js +2 -2
  183. package/src/js/modules/ReactiveData/ReactiveData.js +178 -115
  184. package/src/js/modules/ResizeColumns/ResizeColumns.js +3 -3
  185. package/src/js/modules/ResizeRows/ResizeRows.js +1 -1
  186. package/src/js/modules/ResizeTable/ResizeTable.js +77 -46
  187. package/src/js/modules/ResponsiveLayout/ResponsiveLayout.js +3 -5
  188. package/src/js/modules/SelectRow/SelectRow.js +26 -28
  189. package/src/js/modules/Sort/Sort.js +113 -85
  190. package/src/js/modules/Sort/defaults/sorters/alphanum.js +1 -1
  191. package/src/js/modules/Sort/defaults/sorters/array.js +24 -28
  192. package/src/js/modules/Sort/defaults/sorters/boolean.js +1 -1
  193. package/src/js/modules/Sort/defaults/sorters/date.js +1 -1
  194. package/src/js/modules/Sort/defaults/sorters/datetime.js +13 -13
  195. package/src/js/modules/Sort/defaults/sorters/exists.js +1 -1
  196. package/src/js/modules/Sort/defaults/sorters/number.js +1 -1
  197. package/src/js/modules/Sort/defaults/sorters/string.js +7 -7
  198. package/src/js/modules/Sort/defaults/sorters/time.js +1 -1
  199. package/src/js/modules/Tooltip/Tooltip.js +5 -7
  200. package/src/js/modules/Validate/Validate.js +10 -13
  201. package/src/js/modules/Validate/defaults/validators.js +8 -3
  202. package/src/scss/tabulator.scss +28 -17
  203. package/src/scss/themes/bootstrap/functions4.scss +1 -1
  204. package/src/scss/themes/bootstrap/tabulator_bootstrap3.scss +8 -8
  205. package/src/scss/themes/bootstrap/tabulator_bootstrap4.scss +8 -8
  206. package/src/scss/themes/bootstrap/tabulator_bootstrap5.scss +8 -8
  207. package/src/scss/themes/bulma/tabulator_bulma.scss +7 -7
  208. package/src/scss/themes/materialize/tabulator_materialize.scss +6 -6
  209. package/src/scss/themes/materialize/variables.scss +1 -1
  210. package/src/scss/themes/semanticui/tabulator_semanticui.scss +7 -7
  211. package/src/scss/themes/tabulator_midnight.scss +7 -7
  212. package/src/scss/themes/tabulator_modern.scss +14 -14
  213. package/src/scss/themes/tabulator_simple.scss +8 -8
  214. package/src/scss/themes/tabulator_site.scss +15 -15
@@ -2,1011 +2,1031 @@ import maskInput from './inputMask.js';
2
2
  import urlBuilder from '../Ajax/defaults/urlGenerator.js';
3
3
 
4
4
  export default class Edit{
5
- constructor(editor, cell, onRendered, success, cancel, editorParams){
6
- this.edit = editor;
7
- this.table = editor.table;
8
- this.cell = cell;
9
- this.params = this._initializeParams(editorParams);
10
-
11
- this.data = [];
12
- this.displayItems = [];
13
- this.currentItems = [];
14
- this.focusedItem = null;
15
-
16
- this.input = this._createInputElement();
17
- this.listEl = this._createListElement();
18
-
19
- this.initialValues = null;
20
-
21
- this.isFilter = !cell._getSelf;
22
-
23
- this.filterTimeout = null;
24
- this.filtered = false;
25
- this.typing = false;
26
-
27
- this.values = [];
28
- this.popup = null;
29
-
30
- this.listIteration = 0;
31
-
32
- this.lastAction="";
33
-
34
- this.blurable = true;
35
-
36
- this.actions = {
37
- success:success,
38
- cancel:cancel
39
- }
40
-
41
- this._deprecationCheck();
42
- this._initializeValue();
43
-
44
- onRendered(this._onRendered.bind(this));
45
- }
46
-
47
- _deprecationCheck(){
48
- if(this.params.listItemFormatter){
49
- console.warn("The listItemFormatter editor param has been deprecated, please see the latest editor documentation for updated options");
50
- }
51
-
52
- if(this.params.sortValuesList){
53
- console.warn("The sortValuesList editor param has been deprecated, please see the latest editor documentation for updated options");
54
- }
55
-
56
- if(this.params.searchFunc){
57
- console.warn("The searchFunc editor param has been deprecated, please see the latest editor documentation for updated options");
58
- }
59
-
60
- if(this.params.searchingPlaceholder){
61
- console.warn("The searchingPlaceholder editor param has been deprecated, please see the latest editor documentation for updated options");
62
- }
63
- }
64
-
65
- _initializeValue(){
66
- var initialValue = this.cell.getValue();
67
-
68
- if(typeof initialValue === "undefined" && typeof this.params.defaultValue !== "undefined"){
69
- initialValue = this.params.defaultValue;
70
- }
71
-
72
- this.initialValues = this.params.multiselect ? initialValue : [initialValue];
73
-
74
- if(this.isFilter){
75
- this.input.value = this.initialValues ? this.initialValues.join(",") : "";
76
- this.headerFilterInitialListGen();
77
- }
78
- }
79
-
80
- _onRendered(){
81
- var cellEl = this.cell.getElement();
82
-
83
- function clickStop(e){
84
- e.stopPropagation();
85
- }
86
-
87
- this.input.style.height = "100%";
88
- this.input.focus({preventScroll: true});
89
-
90
-
91
- cellEl.addEventListener("click", clickStop);
92
-
93
- setTimeout(() => {
94
- cellEl.removeEventListener("click", clickStop);
95
- }, 1000)
96
- }
97
-
98
- _createListElement(){
99
- var listEl = document.createElement("div");
100
- listEl.classList.add("tabulator-edit-list");
101
-
102
- listEl.addEventListener("mousedown", this._preventBlur.bind(this));
103
- listEl.addEventListener("keydown", this._inputKeyDown.bind(this))
104
-
105
- return listEl;
106
- }
107
-
108
- _setListWidth(){
109
- var element = this.isFilter ? this.input : this.cell.getElement();
110
-
111
- this.listEl.style.minWidth = element.offsetWidth + "px";
112
-
113
- if(this.params.maxWidth){
114
- if(this.params.maxWidth === true){
115
- this.listEl.style.maxWidth = element.offsetWidth + "px";
116
- }else if(typeof this.params.maxWidth === "number"){
117
- this.listEl.style.maxWidth = this.params.maxWidth + "px";
118
- }else{
119
- this.listEl.style.maxWidth = this.params.maxWidth;
120
- }
121
- }
122
-
123
- }
124
-
125
- _createInputElement(){
126
- var attribs = this.params.elementAttributes;
127
- var input = document.createElement("input");
128
-
129
- input.setAttribute("type", this.params.clearable ? "search" : "text");
130
-
131
- input.style.padding = "4px";
132
- input.style.width = "100%";
133
- input.style.boxSizing = "border-box";
134
-
135
- if(!this.params.autocomplete){
136
- input.style.cursor = "default";
137
- input.style.caretColor = "transparent";
138
- // input.readOnly = (this.edit.currentCell != false);
139
- }
140
-
141
- if(attribs && typeof attribs == "object"){
142
- for (let key in attribs){
143
- if(key.charAt(0) == "+"){
144
- key = key.slice(1);
145
- input.setAttribute(key, input.getAttribute(key) + attribs["+" + key]);
146
- }else{
147
- input.setAttribute(key, attribs[key]);
148
- }
149
- }
150
- }
151
-
152
- if(this.params.mask){
153
- maskInput(input, this.params);
154
- }
155
-
156
- this._bindInputEvents(input);
157
-
158
- return input;
159
- }
160
-
161
- _initializeParams(params){
162
- var valueKeys = ["values", "valuesURL", "valuesLookup"],
163
- valueCheck;
164
-
165
- params = Object.assign({}, params);
166
-
167
- params.verticalNavigation = params.verticalNavigation || "editor";
168
- params.placeholderLoading = typeof params.placeholderLoading === "undefined" ? "Searching ..." : params.placeholderLoading;
169
- params.placeholderEmpty = typeof params.placeholderEmpty === "undefined" ? "No Results Found" : params.placeholderEmpty;
170
- params.filterDelay = typeof params.filterDelay === "undefined" ? 300 : params.filterDelay;
171
-
172
- params.emptyValue = Object.keys(params).includes("emptyValue") ? params.emptyValue : "";
173
-
174
- valueCheck = Object.keys(params).filter(key => valueKeys.includes(key)).length;
175
-
176
- if(!valueCheck){
177
- console.warn("list editor config error - either the values, valuesURL, or valuesLookup option must be set")
178
- }else if(valueCheck > 1){
179
- console.warn("list editor config error - only one of the values, valuesURL, or valuesLookup options can be set on the same editor")
180
- }
181
-
182
- if(params.autocomplete){
183
- if(params.multiselect){
184
- params.multiselect = false;
185
- console.warn("list editor config error - multiselect option is not available when autocomplete is enabled")
186
- }
187
- }else{
188
- if(params.freetext){
189
- params.freetext = false;
190
- console.warn("list editor config error - freetext option is only available when autocomplete is enabled");
191
- }
192
-
193
- if(params.filterFunc){
194
- params.filterFunc = false;
195
- console.warn("list editor config error - filterFunc option is only available when autocomplete is enabled");
196
- }
197
-
198
- if(params.filterRemote){
199
- params.filterRemote = false;
200
- console.warn("list editor config error - filterRemote option is only available when autocomplete is enabled");
201
- }
202
-
203
- if(params.mask){
204
- params.mask = false;
205
- console.warn("list editor config error - mask option is only available when autocomplete is enabled");
206
- }
207
-
208
- if(params.allowEmpty){
209
- params.allowEmpty = false;
210
- console.warn("list editor config error - allowEmpty option is only available when autocomplete is enabled");
211
- }
212
-
213
- if(params.listOnEmpty){
214
- params.listOnEmpty = false;
215
- console.warn("list editor config error - listOnEmpty option is only available when autocomplete is enabled");
216
- }
217
- }
218
-
219
- if(params.filterRemote && !(typeof params.valuesLookup === "function" || typeof params.valuesURL)){
220
- params.filterRemote = false;
221
- console.warn("list editor config error - filterRemote option should only be used when values list is populated from a remote source");
222
- }
223
- return params;
224
- }
225
- //////////////////////////////////////
226
- ////////// Event Handling ////////////
227
- //////////////////////////////////////
228
-
229
- _bindInputEvents(input){
230
- input.addEventListener("focus", this._inputFocus.bind(this))
231
- input.addEventListener("click", this._inputClick.bind(this))
232
- input.addEventListener("blur", this._inputBlur.bind(this))
233
- input.addEventListener("keydown", this._inputKeyDown.bind(this))
234
- input.addEventListener("search", this._inputSearch.bind(this))
235
-
236
- if(this.params.autocomplete){
237
- input.addEventListener("keyup", this._inputKeyUp.bind(this))
238
- }
239
- }
240
-
241
-
242
- _inputFocus(e){
243
- this.rebuildOptionsList();
244
- }
245
-
246
- _filter(){
247
- if(this.params.filterRemote){
248
- clearTimeout(this.filterTimeout);
249
-
250
- this.filterTimeout = setTimeout(() => {
251
- this.rebuildOptionsList();
252
- }, this.params.filterDelay);
253
- }else{
254
- this._filterList();
255
- }
256
- }
257
-
258
- _inputClick(e){
259
- e.stopPropagation();
260
- }
261
-
262
- _inputBlur(e){
263
- if(this.blurable && this.popup){
264
- this.popup.hide();
265
- }
266
- }
267
-
268
- _inputSearch(){
269
- this._clearChoices();
270
- }
271
-
272
- _inputKeyDown(e){
273
- switch(e.keyCode){
274
-
275
- case 38: //up arrow
276
- this._keyUp(e);
277
- break
278
-
279
- case 40: //down arrow
280
- this._keyDown(e);
281
- break;
282
-
283
- case 37: //left arrow
284
- case 39: //right arrow
285
- this._keySide(e);
286
- break;
287
-
288
- case 13: //enter
289
- this._keyEnter();
290
- break;
291
-
292
- case 27: //escape
293
- this._keyEsc();
294
- break;
295
-
296
- case 36: //home
297
- case 35: //end
298
- this._keyHomeEnd(e);
299
- break;
300
-
301
- case 9: //tab
302
- break;
303
-
304
- default:
305
- this._keySelectLetter(e);
306
- }
307
- }
308
-
309
- _inputKeyUp(e){
310
- switch(e.keyCode){
311
- case 38: //up arrow
312
- case 37: //left arrow
313
- case 39: //up arrow
314
- case 40: //right arrow
315
- case 13: //enter
316
- case 27: //escape
317
- break;
318
-
319
- default:
320
- this._keyAutoCompLetter(e);
321
- }
322
- }
323
-
324
- _preventBlur(){
325
- this.blurable = false;
326
-
327
- setTimeout(function(){
328
- this.blurable = true;
329
- }, 10);
330
- }
331
-
332
- //////////////////////////////////////
333
- //////// Keyboard Navigation /////////
334
- //////////////////////////////////////
335
-
336
- _keyUp(e){
337
- var index = this.displayItems.indexOf(this.focusedItem);
338
-
339
- if(this.params.verticalNavigation == "editor" || (this.params.verticalNavigation == "hybrid" && index)){
340
- e.stopImmediatePropagation();
341
- e.stopPropagation();
342
- e.preventDefault();
343
-
344
- if(index > 0){
345
- this._focusItem(this.displayItems[index - 1]);
346
- }
347
- }
348
- }
349
-
350
- _keyDown(e){
351
- var index = this.displayItems.indexOf(this.focusedItem);
352
-
353
- if(this.params.verticalNavigation == "editor" || (this.params.verticalNavigation == "hybrid" && index < this.displayItems.length - 1)){
354
- e.stopImmediatePropagation();
355
- e.stopPropagation();
356
- e.preventDefault();
357
-
358
- if(index < this.displayItems.length - 1){
359
- if(index == -1){
360
- this._focusItem(this.displayItems[0]);
361
- }else{
362
- this._focusItem(this.displayItems[index + 1]);
363
- }
364
- }
365
- }
366
- }
367
-
368
- _keySide(e){
369
- e.stopImmediatePropagation();
370
- e.stopPropagation();
371
- e.preventDefault();
372
- }
373
-
374
- _keyEnter(e){
375
- if(this.params.autocomplete && this.lastAction === "typing"){
376
- this._resolveValue(true);
377
- }else{
378
- if(this.focusedItem){
379
- this._chooseItem(this.focusedItem);
380
- }
381
- }
382
- }
383
-
384
- _keyEsc(e){
385
- this._cancel();
386
- }
387
-
388
- _keyHomeEnd(e){
389
- if(this.params.autocomplete){
390
- //prevent table navigation while using input element
391
- e.stopImmediatePropagation();
392
- }
393
- }
394
-
395
- _keySelectLetter(e){
396
- if(!this.params.autocomplete){
397
- // if(this.edit.currentCell === false){
398
- e.preventDefault();
399
- // }
400
-
401
- if(e.keyCode >= 38 && e.keyCode <= 90){
402
- this._scrollToValue(e.keyCode);
403
- }
404
- }
405
- }
406
-
407
- _keyAutoCompLetter(e){
408
- this._filter();
409
- this.lastAction = "typing";
410
- this.typing = true;
411
- }
412
-
413
-
414
- _scrollToValue(char){
415
- clearTimeout(this.filterTimeout);
416
-
417
- var character = String.fromCharCode(char).toLowerCase();
418
- this.filterTerm += character.toLowerCase();
419
-
420
- var match = this.displayItems.find((item) => {
421
- return typeof item.label !== "undefined" && item.label.toLowerCase().startsWith(this.filterTerm);
422
- });
423
-
424
- if(match){
425
- this._focusItem(match);
426
- }
427
-
428
- this.filterTimeout = setTimeout(() => {
429
- this.filterTerm = "";
430
- }, 800)
431
- }
432
-
433
- _focusItem(item){
434
- this.lastAction = "focus";
435
-
436
- if(this.focusedItem && this.focusedItem.element){
437
- this.focusedItem.element.classList.remove("focused");
438
- }
439
-
440
- this.focusedItem = item;
441
-
442
- if(item && item.element){
443
- item.element.classList.add("focused");
444
- item.element.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'start'});
445
- }
446
- }
447
-
448
-
449
- //////////////////////////////////////
450
- /////// Data List Generation /////////
451
- //////////////////////////////////////
452
- headerFilterInitialListGen(){
453
- this._generateOptions(true);
454
- }
455
-
456
- rebuildOptionsList(){
457
- this._generateOptions()
458
- .then(this._sortOptions.bind(this))
459
- .then(this._buildList.bind(this))
460
- .then(this._showList.bind(this))
461
- .catch((e) => {
462
- if(!Number.isInteger(e)){
463
- console.error("List generation error", e);
464
- }
465
- })
466
- }
467
-
468
- _filterList(){
469
- this._buildList(this._filterOptions());
470
- this._showList();
471
- }
472
-
473
- _generateOptions(silent){
474
- var values = [];
475
- var itteration = ++ this.listIteration;
476
-
477
- this.filtered = false;
478
-
479
- if(this.params.values){
480
- values = this.params.values;
481
- }else if (this.params.valuesURL){
482
- values = this._ajaxRequest(this.params.valuesURL, this.input.value);
483
- }else{
484
- if(typeof this.params.valuesLookup === "function"){
485
- values = this.params.valuesLookup(this.cell, this.input.value);
486
- }else if(this.params.valuesLookup){
487
- values = this._uniqueColumnValues(this.params.valuesLookupField);
488
- }
489
- }
490
-
491
- if(values instanceof Promise){
492
- if(!silent){
493
- this._addPlaceholder(this.params.placeholderLoading);
494
- }
495
-
496
- return values.then()
497
- .then((responseValues) => {
498
- if(this.listIteration === itteration){
499
- return this._parseList(responseValues);
500
- }else{
501
- return Promise.reject(itteration);
502
- }
503
- });
504
- }else{
505
- return Promise.resolve(this._parseList(values))
506
- }
507
- }
508
-
509
- _addPlaceholder(contents){
510
- var placeholder = document.createElement("div");
511
-
512
- if(typeof contents === "function"){
513
- contents = contents(cell.getComponent(), this.listEl);
514
- }
515
-
516
- if(contents){
517
- this._clearList();
518
-
519
- if(contents instanceof HTMLElement){
520
- placeholder = contents;
521
- }else{
522
- placeholder.classList.add("tabulator-edit-list-placeholder")
523
- placeholder.innerHTML = contents;
524
- }
525
-
526
- this.listEl.appendChild(placeholder);
527
-
528
- this._showList();
529
- }
530
- }
531
-
532
- _ajaxRequest(url, term){
533
- var params = this.params.filterRemote ? {term:term} : {};
534
- url = urlBuilder(url, {}, params);
535
-
536
- return fetch(url)
537
- .then((response)=>{
538
- if(response.ok) {
539
- return response.json()
540
- .catch((error)=>{
541
- console.warn("List Ajax Load Error - Invalid JSON returned", error);
542
- return Promise.reject(error);
543
- });
544
- }else{
545
- console.error("List Ajax Load Error - Connection Error: " + response.status, response.statusText);
546
- return Promise.reject(response);
547
- }
548
- })
549
- .catch((error)=>{
550
- console.error("List Ajax Load Error - Connection Error: ", error);
551
- return Promise.reject(error);
552
- });
553
- }
554
-
555
- _uniqueColumnValues(field){
556
- var output = {},
557
- data = this.table.getData(this.params.valuesLookup),
558
- column;
559
-
560
- if(field){
561
- column = this.table.columnManager.getColumnByField(field);
562
- }else{
563
- column = this.cell.getColumn()._getSelf();
564
- }
565
-
566
- if(column){
567
- data.forEach((row) => {
568
- var val = column.getFieldValue(row);
569
-
570
- if(val !== null && typeof val !== "undefined" && val !== ""){
571
- output[val] = true;
572
- }
573
- });
574
- }else{
575
- console.warn("unable to find matching column to create select lookup list:", field);
576
- output = [];
577
- }
578
-
579
- return Object.keys(output);
580
- }
581
-
582
-
583
- _parseList(inputValues){
584
- var data = [];
585
-
586
- if(!Array.isArray(inputValues)){
587
- inputValues = Object.entries(inputValues).map(([key, value]) => {
588
- return {
589
- label:value,
590
- value:key,
591
- };
592
- });
593
- }
594
-
595
- inputValues.forEach((value) => {
596
- if(typeof value !== "object"){
597
- value = {
598
- label:value,
599
- value:value,
600
- };
601
- }
602
-
603
- this._parseListItem(value, data, 0);
604
- });
5
+ constructor(editor, cell, onRendered, success, cancel, editorParams){
6
+ this.edit = editor;
7
+ this.table = editor.table;
8
+ this.cell = cell;
9
+ this.params = this._initializeParams(editorParams);
10
+
11
+ this.data = [];
12
+ this.displayItems = [];
13
+ this.currentItems = [];
14
+ this.focusedItem = null;
15
+
16
+ this.input = this._createInputElement();
17
+ this.listEl = this._createListElement();
18
+
19
+ this.initialValues = null;
20
+
21
+ this.isFilter = !cell._getSelf;
22
+
23
+ this.filterTimeout = null;
24
+ this.filtered = false;
25
+ this.typing = false;
26
+
27
+ this.values = [];
28
+ this.popup = null;
29
+
30
+ this.listIteration = 0;
31
+
32
+ this.lastAction="";
33
+
34
+ this.blurable = true;
35
+
36
+ this.actions = {
37
+ success:success,
38
+ cancel:cancel
39
+ };
40
+
41
+ this._deprecatedOptionsCheck();
42
+ this._initializeValue();
43
+
44
+ onRendered(this._onRendered.bind(this));
45
+ }
46
+
47
+ _deprecatedOptionsCheck(){
48
+ if(this.params.listItemFormatter){
49
+ this.cell.getTable().deprecationAdvisor.msg("The listItemFormatter editor param has been deprecated, please see the latest editor documentation for updated options");
50
+ }
51
+
52
+ if(this.params.sortValuesList){
53
+ this.cell.getTable().deprecationAdvisor.msg("The sortValuesList editor param has been deprecated, please see the latest editor documentation for updated options");
54
+ }
55
+
56
+ if(this.params.searchFunc){
57
+ this.cell.getTable().deprecationAdvisor.msg("The searchFunc editor param has been deprecated, please see the latest editor documentation for updated options");
58
+ }
59
+
60
+ if(this.params.searchingPlaceholder){
61
+ this.cell.getTable().deprecationAdvisor.msg("The searchingPlaceholder editor param has been deprecated, please see the latest editor documentation for updated options");
62
+ }
63
+ }
64
+
65
+ _initializeValue(){
66
+ var initialValue = this.cell.getValue();
67
+
68
+ if(typeof initialValue === "undefined" && typeof this.params.defaultValue !== "undefined"){
69
+ initialValue = this.params.defaultValue;
70
+ }
71
+
72
+ this.initialValues = this.params.multiselect ? initialValue : [initialValue];
73
+
74
+ if(this.isFilter){
75
+ this.input.value = this.initialValues ? this.initialValues.join(",") : "";
76
+ this.headerFilterInitialListGen();
77
+ }
78
+ }
79
+
80
+ _onRendered(){
81
+ var cellEl = this.cell.getElement();
82
+
83
+ function clickStop(e){
84
+ e.stopPropagation();
85
+ }
86
+
87
+ this.input.style.height = "100%";
88
+ this.input.focus({preventScroll: true});
89
+
90
+
91
+ cellEl.addEventListener("click", clickStop);
92
+
93
+ setTimeout(() => {
94
+ cellEl.removeEventListener("click", clickStop);
95
+ }, 1000);
96
+
97
+ this.input.addEventListener("mousedown", this._preventPopupBlur.bind(this));
98
+ }
99
+
100
+ _createListElement(){
101
+ var listEl = document.createElement("div");
102
+ listEl.classList.add("tabulator-edit-list");
103
+
104
+ listEl.addEventListener("mousedown", this._preventBlur.bind(this));
105
+ listEl.addEventListener("keydown", this._inputKeyDown.bind(this));
106
+
107
+ return listEl;
108
+ }
109
+
110
+ _setListWidth(){
111
+ var element = this.isFilter ? this.input : this.cell.getElement();
112
+
113
+ this.listEl.style.minWidth = element.offsetWidth + "px";
114
+
115
+ if(this.params.maxWidth){
116
+ if(this.params.maxWidth === true){
117
+ this.listEl.style.maxWidth = element.offsetWidth + "px";
118
+ }else if(typeof this.params.maxWidth === "number"){
119
+ this.listEl.style.maxWidth = this.params.maxWidth + "px";
120
+ }else{
121
+ this.listEl.style.maxWidth = this.params.maxWidth;
122
+ }
123
+ }
124
+
125
+ }
126
+
127
+ _createInputElement(){
128
+ var attribs = this.params.elementAttributes;
129
+ var input = document.createElement("input");
130
+
131
+ input.setAttribute("type", this.params.clearable ? "search" : "text");
132
+
133
+ input.style.padding = "4px";
134
+ input.style.width = "100%";
135
+ input.style.boxSizing = "border-box";
136
+
137
+ if(!this.params.autocomplete){
138
+ input.style.cursor = "default";
139
+ input.style.caretColor = "transparent";
140
+ // input.readOnly = (this.edit.currentCell != false);
141
+ }
142
+
143
+ if(attribs && typeof attribs == "object"){
144
+ for (let key in attribs){
145
+ if(key.charAt(0) == "+"){
146
+ key = key.slice(1);
147
+ input.setAttribute(key, input.getAttribute(key) + attribs["+" + key]);
148
+ }else{
149
+ input.setAttribute(key, attribs[key]);
150
+ }
151
+ }
152
+ }
153
+
154
+ if(this.params.mask){
155
+ maskInput(input, this.params);
156
+ }
157
+
158
+ this._bindInputEvents(input);
159
+
160
+ return input;
161
+ }
162
+
163
+ _initializeParams(params){
164
+ var valueKeys = ["values", "valuesURL", "valuesLookup"],
165
+ valueCheck;
166
+
167
+ params = Object.assign({}, params);
168
+
169
+ params.verticalNavigation = params.verticalNavigation || "editor";
170
+ params.placeholderLoading = typeof params.placeholderLoading === "undefined" ? "Searching ..." : params.placeholderLoading;
171
+ params.placeholderEmpty = typeof params.placeholderEmpty === "undefined" ? "No Results Found" : params.placeholderEmpty;
172
+ params.filterDelay = typeof params.filterDelay === "undefined" ? 300 : params.filterDelay;
173
+
174
+ params.emptyValue = Object.keys(params).includes("emptyValue") ? params.emptyValue : "";
175
+
176
+ valueCheck = Object.keys(params).filter(key => valueKeys.includes(key)).length;
177
+
178
+ if(!valueCheck){
179
+ console.warn("list editor config error - either the values, valuesURL, or valuesLookup option must be set");
180
+ }else if(valueCheck > 1){
181
+ console.warn("list editor config error - only one of the values, valuesURL, or valuesLookup options can be set on the same editor");
182
+ }
183
+
184
+ if(params.autocomplete){
185
+ if(params.multiselect){
186
+ params.multiselect = false;
187
+ console.warn("list editor config error - multiselect option is not available when autocomplete is enabled");
188
+ }
189
+ }else{
190
+ if(params.freetext){
191
+ params.freetext = false;
192
+ console.warn("list editor config error - freetext option is only available when autocomplete is enabled");
193
+ }
194
+
195
+ if(params.filterFunc){
196
+ params.filterFunc = false;
197
+ console.warn("list editor config error - filterFunc option is only available when autocomplete is enabled");
198
+ }
199
+
200
+ if(params.filterRemote){
201
+ params.filterRemote = false;
202
+ console.warn("list editor config error - filterRemote option is only available when autocomplete is enabled");
203
+ }
204
+
205
+ if(params.mask){
206
+ params.mask = false;
207
+ console.warn("list editor config error - mask option is only available when autocomplete is enabled");
208
+ }
209
+
210
+ if(params.allowEmpty){
211
+ params.allowEmpty = false;
212
+ console.warn("list editor config error - allowEmpty option is only available when autocomplete is enabled");
213
+ }
214
+
215
+ if(params.listOnEmpty){
216
+ params.listOnEmpty = false;
217
+ console.warn("list editor config error - listOnEmpty option is only available when autocomplete is enabled");
218
+ }
219
+ }
220
+
221
+ if(params.filterRemote && !(typeof params.valuesLookup === "function" || params.valuesURL)){
222
+ params.filterRemote = false;
223
+ console.warn("list editor config error - filterRemote option should only be used when values list is populated from a remote source");
224
+ }
225
+ return params;
226
+ }
227
+ //////////////////////////////////////
228
+ ////////// Event Handling ////////////
229
+ //////////////////////////////////////
230
+
231
+ _bindInputEvents(input){
232
+ input.addEventListener("focus", this._inputFocus.bind(this));
233
+ input.addEventListener("click", this._inputClick.bind(this));
234
+ input.addEventListener("blur", this._inputBlur.bind(this));
235
+ input.addEventListener("keydown", this._inputKeyDown.bind(this));
236
+ input.addEventListener("search", this._inputSearch.bind(this));
237
+
238
+ if(this.params.autocomplete){
239
+ input.addEventListener("keyup", this._inputKeyUp.bind(this));
240
+ }
241
+ }
242
+
243
+
244
+ _inputFocus(e){
245
+ this.rebuildOptionsList();
246
+ }
247
+
248
+ _filter(){
249
+ if(this.params.filterRemote){
250
+ clearTimeout(this.filterTimeout);
251
+
252
+ this.filterTimeout = setTimeout(() => {
253
+ this.rebuildOptionsList();
254
+ }, this.params.filterDelay);
255
+ }else{
256
+ this._filterList();
257
+ }
258
+ }
259
+
260
+ _inputClick(e){
261
+ e.stopPropagation();
262
+ }
263
+
264
+ _inputBlur(e){
265
+ if(this.blurable){
266
+ if(this.popup){
267
+ this.popup.hide();
268
+ }else{
269
+ this._resolveValue(true);
270
+ }
271
+ }
272
+ }
273
+
274
+ _inputSearch(){
275
+ this._clearChoices();
276
+ }
277
+
278
+ _inputKeyDown(e){
279
+ switch(e.keyCode){
280
+
281
+ case 38: //up arrow
282
+ this._keyUp(e);
283
+ break;
284
+
285
+ case 40: //down arrow
286
+ this._keyDown(e);
287
+ break;
288
+
289
+ case 37: //left arrow
290
+ case 39: //right arrow
291
+ this._keySide(e);
292
+ break;
293
+
294
+ case 13: //enter
295
+ this._keyEnter();
296
+ break;
297
+
298
+ case 27: //escape
299
+ this._keyEsc();
300
+ break;
301
+
302
+ case 36: //home
303
+ case 35: //end
304
+ this._keyHomeEnd(e);
305
+ break;
306
+
307
+ case 9: //tab
308
+ break;
309
+
310
+ default:
311
+ this._keySelectLetter(e);
312
+ }
313
+ }
314
+
315
+ _inputKeyUp(e){
316
+ switch(e.keyCode){
317
+ case 38: //up arrow
318
+ case 37: //left arrow
319
+ case 39: //up arrow
320
+ case 40: //right arrow
321
+ case 13: //enter
322
+ case 27: //escape
323
+ break;
324
+
325
+ default:
326
+ this._keyAutoCompLetter(e);
327
+ }
328
+ }
329
+
330
+ _preventPopupBlur(){
331
+ if(this.popup){
332
+ this.popup.blockHide();
333
+ }
334
+
335
+ setTimeout(() =>{
336
+ if(this.popup){
337
+ this.popup.restoreHide();
338
+ }
339
+ }, 10);
340
+ }
341
+
342
+ _preventBlur(){
343
+ this.blurable = false;
344
+
345
+ setTimeout(() =>{
346
+ this.blurable = true;
347
+ }, 10);
348
+ }
349
+
350
+ //////////////////////////////////////
351
+ //////// Keyboard Navigation /////////
352
+ //////////////////////////////////////
353
+
354
+ _keyUp(e){
355
+ var index = this.displayItems.indexOf(this.focusedItem);
356
+
357
+ if(this.params.verticalNavigation == "editor" || (this.params.verticalNavigation == "hybrid" && index)){
358
+ e.stopImmediatePropagation();
359
+ e.stopPropagation();
360
+ e.preventDefault();
361
+
362
+ if(index > 0){
363
+ this._focusItem(this.displayItems[index - 1]);
364
+ }
365
+ }
366
+ }
367
+
368
+ _keyDown(e){
369
+ var index = this.displayItems.indexOf(this.focusedItem);
370
+
371
+ if(this.params.verticalNavigation == "editor" || (this.params.verticalNavigation == "hybrid" && index < this.displayItems.length - 1)){
372
+ e.stopImmediatePropagation();
373
+ e.stopPropagation();
374
+ e.preventDefault();
375
+
376
+ if(index < this.displayItems.length - 1){
377
+ if(index == -1){
378
+ this._focusItem(this.displayItems[0]);
379
+ }else{
380
+ this._focusItem(this.displayItems[index + 1]);
381
+ }
382
+ }
383
+ }
384
+ }
385
+
386
+ _keySide(e){
387
+ e.stopImmediatePropagation();
388
+ e.stopPropagation();
389
+ e.preventDefault();
390
+ }
391
+
392
+ _keyEnter(e){
393
+ if(this.params.autocomplete && this.lastAction === "typing"){
394
+ this._resolveValue(true);
395
+ }else{
396
+ if(this.focusedItem){
397
+ this._chooseItem(this.focusedItem);
398
+ }
399
+ }
400
+ }
401
+
402
+ _keyEsc(e){
403
+ this._cancel();
404
+ }
405
+
406
+ _keyHomeEnd(e){
407
+ if(this.params.autocomplete){
408
+ //prevent table navigation while using input element
409
+ e.stopImmediatePropagation();
410
+ }
411
+ }
412
+
413
+ _keySelectLetter(e){
414
+ if(!this.params.autocomplete){
415
+ // if(this.edit.currentCell === false){
416
+ e.preventDefault();
417
+ // }
418
+
419
+ if(e.keyCode >= 38 && e.keyCode <= 90){
420
+ this._scrollToValue(e.keyCode);
421
+ }
422
+ }
423
+ }
424
+
425
+ _keyAutoCompLetter(e){
426
+ this._filter();
427
+ this.lastAction = "typing";
428
+ this.typing = true;
429
+ }
430
+
431
+
432
+ _scrollToValue(char){
433
+ clearTimeout(this.filterTimeout);
434
+
435
+ var character = String.fromCharCode(char).toLowerCase();
436
+ this.filterTerm += character.toLowerCase();
437
+
438
+ var match = this.displayItems.find((item) => {
439
+ return typeof item.label !== "undefined" && item.label.toLowerCase().startsWith(this.filterTerm);
440
+ });
441
+
442
+ if(match){
443
+ this._focusItem(match);
444
+ }
445
+
446
+ this.filterTimeout = setTimeout(() => {
447
+ this.filterTerm = "";
448
+ }, 800);
449
+ }
450
+
451
+ _focusItem(item){
452
+ this.lastAction = "focus";
453
+
454
+ if(this.focusedItem && this.focusedItem.element){
455
+ this.focusedItem.element.classList.remove("focused");
456
+ }
457
+
458
+ this.focusedItem = item;
459
+
460
+ if(item && item.element){
461
+ item.element.classList.add("focused");
462
+ item.element.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'start'});
463
+ }
464
+ }
465
+
466
+
467
+ //////////////////////////////////////
468
+ /////// Data List Generation /////////
469
+ //////////////////////////////////////
470
+ headerFilterInitialListGen(){
471
+ this._generateOptions(true);
472
+ }
473
+
474
+ rebuildOptionsList(){
475
+ this._generateOptions()
476
+ .then(this._sortOptions.bind(this))
477
+ .then(this._buildList.bind(this))
478
+ .then(this._showList.bind(this))
479
+ .catch((e) => {
480
+ if(!Number.isInteger(e)){
481
+ console.error("List generation error", e);
482
+ }
483
+ });
484
+ }
485
+
486
+ _filterList(){
487
+ this._buildList(this._filterOptions());
488
+ this._showList();
489
+ }
490
+
491
+ _generateOptions(silent){
492
+ var values = [];
493
+ var iteration = ++ this.listIteration;
494
+
495
+ this.filtered = false;
496
+
497
+ if(this.params.values){
498
+ values = this.params.values;
499
+ }else if (this.params.valuesURL){
500
+ values = this._ajaxRequest(this.params.valuesURL, this.input.value);
501
+ }else{
502
+ if(typeof this.params.valuesLookup === "function"){
503
+ values = this.params.valuesLookup(this.cell, this.input.value);
504
+ }else if(this.params.valuesLookup){
505
+ values = this._uniqueColumnValues(this.params.valuesLookupField);
506
+ }
507
+ }
508
+
509
+ if(values instanceof Promise){
510
+ if(!silent){
511
+ this._addPlaceholder(this.params.placeholderLoading);
512
+ }
513
+
514
+ return values.then()
515
+ .then((responseValues) => {
516
+ if(this.listIteration === iteration){
517
+ return this._parseList(responseValues);
518
+ }else{
519
+ return Promise.reject(iteration);
520
+ }
521
+ });
522
+ }else{
523
+ return Promise.resolve(this._parseList(values));
524
+ }
525
+ }
526
+
527
+ _addPlaceholder(contents){
528
+ var placeholder = document.createElement("div");
529
+
530
+ if(typeof contents === "function"){
531
+ contents = contents(this.cell.getComponent(), this.listEl);
532
+ }
533
+
534
+ if(contents){
535
+ this._clearList();
536
+
537
+ if(contents instanceof HTMLElement){
538
+ placeholder = contents;
539
+ }else{
540
+ placeholder.classList.add("tabulator-edit-list-placeholder");
541
+ placeholder.innerHTML = contents;
542
+ }
543
+
544
+ this.listEl.appendChild(placeholder);
545
+
546
+ this._showList();
547
+ }
548
+ }
549
+
550
+ _ajaxRequest(url, term){
551
+ var params = this.params.filterRemote ? {term:term} : {};
552
+ url = urlBuilder(url, {}, params);
553
+
554
+ return fetch(url)
555
+ .then((response)=>{
556
+ if(response.ok) {
557
+ return response.json()
558
+ .catch((error)=>{
559
+ console.warn("List Ajax Load Error - Invalid JSON returned", error);
560
+ return Promise.reject(error);
561
+ });
562
+ }else{
563
+ console.error("List Ajax Load Error - Connection Error: " + response.status, response.statusText);
564
+ return Promise.reject(response);
565
+ }
566
+ })
567
+ .catch((error)=>{
568
+ console.error("List Ajax Load Error - Connection Error: ", error);
569
+ return Promise.reject(error);
570
+ });
571
+ }
572
+
573
+ _uniqueColumnValues(field){
574
+ var output = {},
575
+ data = this.table.getData(this.params.valuesLookup),
576
+ column;
577
+
578
+ if(field){
579
+ column = this.table.columnManager.getColumnByField(field);
580
+ }else{
581
+ column = this.cell.getColumn()._getSelf();
582
+ }
583
+
584
+ if(column){
585
+ data.forEach((row) => {
586
+ var val = column.getFieldValue(row);
587
+
588
+ if(val !== null && typeof val !== "undefined" && val !== ""){
589
+ output[val] = true;
590
+ }
591
+ });
592
+ }else{
593
+ console.warn("unable to find matching column to create select lookup list:", field);
594
+ output = [];
595
+ }
596
+
597
+ return Object.keys(output);
598
+ }
599
+
600
+
601
+ _parseList(inputValues){
602
+ var data = [];
603
+
604
+ if(!Array.isArray(inputValues)){
605
+ inputValues = Object.entries(inputValues).map(([key, value]) => {
606
+ return {
607
+ label:value,
608
+ value:key,
609
+ };
610
+ });
611
+ }
612
+
613
+ inputValues.forEach((value) => {
614
+ if(typeof value !== "object"){
615
+ value = {
616
+ label:value,
617
+ value:value,
618
+ };
619
+ }
620
+
621
+ this._parseListItem(value, data, 0);
622
+ });
623
+
624
+ if(!this.currentItems.length && this.params.freetext){
625
+ this.input.value = this.initialValues;
626
+ this.typing = true;
627
+ this.lastAction = "typing";
628
+ }
629
+
630
+ this.data = data;
631
+
632
+ return data;
633
+ }
634
+
635
+ _parseListItem(option, data, level){
636
+ var item = {};
637
+
638
+ if(option.options){
639
+ item = this._parseListGroup(option, level + 1);
640
+ }else{
641
+ item = {
642
+ label:option.label,
643
+ value:option.value,
644
+ itemParams:option.itemParams,
645
+ elementAttributes: option.elementAttributes,
646
+ element:false,
647
+ selected:false,
648
+ visible:true,
649
+ level:level,
650
+ original:option,
651
+ };
652
+
653
+ if(this.initialValues && this.initialValues.indexOf(option.value) > -1){
654
+ this._chooseItem(item, true);
655
+ }
656
+ }
657
+
658
+ data.push(item);
659
+ }
660
+
661
+ _parseListGroup(option, level){
662
+ var item = {
663
+ label:option.label,
664
+ group:true,
665
+ itemParams:option.itemParams,
666
+ elementAttributes:option.elementAttributes,
667
+ element:false,
668
+ visible:true,
669
+ level:level,
670
+ options:[],
671
+ original:option,
672
+ };
673
+
674
+ option.options.forEach((child) => {
675
+ this._parseListItem(child, item.options, level);
676
+ });
677
+
678
+ return item;
679
+ }
680
+
681
+ _sortOptions(options){
682
+ var sorter;
683
+
684
+ if(this.params.sort){
685
+ sorter = typeof this.params.sort === "function" ? this.params.sort : this._defaultSortFunction.bind(this);
686
+
687
+ this._sortGroup(sorter, options);
688
+ }
689
+
690
+ return options;
691
+ }
692
+
693
+ _sortGroup(sorter, options){
694
+ options.sort((a,b) => {
695
+ return sorter(a.label, b.label, a.value, b.value, a.original, b.original);
696
+ });
697
+
698
+ options.forEach((option) => {
699
+ if(option.group){
700
+ this._sortGroup(sorter, option.options);
701
+ }
702
+ });
703
+ }
704
+
705
+ _defaultSortFunction(as, bs){
706
+ var a, b, a1, b1, i= 0, L, rx = /(\d+)|(\D+)/g, rd = /\d/;
707
+ var emptyAlign = 0;
708
+
709
+ if(this.params.sort === "desc"){
710
+ [as, bs] = [bs, as];
711
+ }
712
+
713
+ //handle empty values
714
+ if(!as && as!== 0){
715
+ emptyAlign = !bs && bs!== 0 ? 0 : -1;
716
+ }else if(!bs && bs!== 0){
717
+ emptyAlign = 1;
718
+ }else{
719
+ if(isFinite(as) && isFinite(bs)) return as - bs;
720
+ a = String(as).toLowerCase();
721
+ b = String(bs).toLowerCase();
722
+ if(a === b) return 0;
723
+ if(!(rd.test(a) && rd.test(b))) return a > b ? 1 : -1;
724
+ a = a.match(rx);
725
+ b = b.match(rx);
726
+ L = a.length > b.length ? b.length : a.length;
727
+ while(i < L){
728
+ a1= a[i];
729
+ b1= b[i++];
730
+ if(a1 !== b1){
731
+ if(isFinite(a1) && isFinite(b1)){
732
+ if(a1.charAt(0) === "0") a1 = "." + a1;
733
+ if(b1.charAt(0) === "0") b1 = "." + b1;
734
+ return a1 - b1;
735
+ }
736
+ else return a1 > b1 ? 1 : -1;
737
+ }
738
+ }
739
+
740
+ return a.length > b.length;
741
+ }
742
+
743
+ return emptyAlign;
744
+ }
745
+
746
+ _filterOptions(){
747
+ var filterFunc = this.params.filterFunc || this._defaultFilterFunc,
748
+ term = this.input.value;
749
+
750
+ if(term){
751
+ this.filtered = true;
752
+
753
+ this.data.forEach((item) => {
754
+ this._filterItem(filterFunc, term, item);
755
+ });
756
+ }else{
757
+ this.filtered = false;
758
+ }
759
+
760
+ return this.data;
761
+ }
762
+
763
+ _filterItem(func, term, item){
764
+ var matches = false;
765
+
766
+ if(!item.group){
767
+ item.visible = func(term, item.label, item.value, item.original);
768
+ }else{
769
+ item.options.forEach((option) => {
770
+ if(this._filterItem(func, term, option)){
771
+ matches = true;
772
+ }
773
+ });
774
+
775
+ item.visible = matches;
776
+ }
777
+
778
+ return item.visible;
779
+ }
780
+
781
+ _defaultFilterFunc(term, label, value, item){
782
+ term = String(term).toLowerCase();
783
+
784
+ if(label !== null && typeof label !== "undefined"){
785
+ if(String(label).toLowerCase().indexOf(term) > -1 || String(value).toLowerCase().indexOf(term) > -1){
786
+ return true;
787
+ }
788
+ }
789
+
790
+ return false;
791
+ }
792
+
793
+ //////////////////////////////////////
794
+ /////////// Display List /////////////
795
+ //////////////////////////////////////
796
+
797
+ _clearList(){
798
+ while(this.listEl.firstChild) this.listEl.removeChild(this.listEl.firstChild);
799
+
800
+ this.displayItems = [];
801
+ }
802
+
803
+ _buildList(data){
804
+ this._clearList();
805
+
806
+ data.forEach((option) => {
807
+ this._buildItem(option);
808
+ });
809
+
810
+ if(!this.displayItems.length){
811
+ this._addPlaceholder(this.params.placeholderEmpty);
812
+ }
813
+ }
814
+
815
+ _buildItem(item){
816
+ var el = item.element,
817
+ contents;
818
+
819
+ if(!this.filtered || item.visible){
820
+
821
+ if(!el){
822
+ el = document.createElement("div");
823
+ el.tabIndex = 0;
824
+
825
+ contents = this.params.itemFormatter ? this.params.itemFormatter(item.label, item.value, item.original, el) : item.label;
826
+
827
+ if(contents instanceof HTMLElement){
828
+ el.appendChild(contents);
829
+ }else{
830
+ el.innerHTML = contents;
831
+ }
832
+
833
+ if(item.group){
834
+ el.classList.add("tabulator-edit-list-group");
835
+ }else{
836
+ el.classList.add("tabulator-edit-list-item");
837
+ }
838
+
839
+ el.classList.add("tabulator-edit-list-group-level-" + item.level);
840
+
841
+ if(item.elementAttributes && typeof item.elementAttributes == "object"){
842
+ for (let key in item.elementAttributes){
843
+ if(key.charAt(0) == "+"){
844
+ key = key.slice(1);
845
+ el.setAttribute(key, this.input.getAttribute(key) + item.elementAttributes["+" + key]);
846
+ }else{
847
+ el.setAttribute(key, item.elementAttributes[key]);
848
+ }
849
+ }
850
+ }
851
+
852
+ if(item.group){
853
+ el.addEventListener("click", this._groupClick.bind(this, item));
854
+ }else{
855
+ el.addEventListener("click", this._itemClick.bind(this, item));
856
+ }
857
+
858
+ el.addEventListener("mousedown", this._preventBlur.bind(this));
859
+
860
+ item.element = el;
861
+ }
862
+
863
+ this._styleItem(item);
864
+
865
+ this.listEl.appendChild(el);
866
+
867
+ if(item.group){
868
+ item.options.forEach((option) => {
869
+ this._buildItem(option);
870
+ });
871
+ }else{
872
+ this.displayItems.push(item);
873
+ }
874
+ }
875
+ }
876
+
877
+ _showList(){
878
+ var startVis = this.popup && this.popup.isVisible();
879
+
880
+ if(this.input.parentNode){
881
+ if(this.params.autocomplete && this.input.value === "" && !this.params.listOnEmpty){
882
+ if(this.popup){
883
+ this.popup.hide(true);
884
+ }
885
+ return;
886
+ }
887
+
888
+ this._setListWidth();
889
+
890
+ if(!this.popup){
891
+ this.popup = this.edit.popup(this.listEl);
892
+ }
893
+
894
+ this.popup.show(this.cell.getElement(), "bottom");
895
+
896
+ if(!startVis){
897
+ setTimeout(() => {
898
+ this.popup.hideOnBlur(this._resolveValue.bind(this, true));
899
+ }, 10);
900
+ }
901
+ }
902
+ }
903
+
904
+ _styleItem(item){
905
+ if(item && item.element){
906
+ if(item.selected){
907
+ item.element.classList.add("active");
908
+ }else{
909
+ item.element.classList.remove("active");
910
+ }
911
+ }
912
+ }
913
+
914
+ //////////////////////////////////////
915
+ ///////// User Interaction ///////////
916
+ //////////////////////////////////////
917
+
918
+ _itemClick(item, e){
919
+ e.stopPropagation();
920
+
921
+ this._chooseItem(item);
922
+ }
923
+
924
+ _groupClick(item, e){
925
+ e.stopPropagation();
926
+ }
927
+
928
+
929
+ //////////////////////////////////////
930
+ ////// Current Item Management ///////
931
+ //////////////////////////////////////
932
+
933
+ _cancel(){
934
+ this.popup.hide(true);
935
+ this.actions.cancel();
936
+ }
937
+
938
+ _clearChoices(){
939
+ this.typing = true;
940
+
941
+ this.currentItems.forEach((item) => {
942
+ item.selected = false;
943
+ this._styleItem(item);
944
+ });
945
+
946
+ this.currentItems = [];
947
+
948
+ this.focusedItem = null;
949
+ }
950
+
951
+ _chooseItem(item, silent){
952
+ var index;
953
+
954
+ this.typing = false;
955
+
956
+ if(this.params.multiselect){
957
+ index = this.currentItems.indexOf(item);
958
+
959
+ if(index > -1){
960
+ this.currentItems.splice(index, 1);
961
+ item.selected = false;
962
+ }else{
963
+ this.currentItems.push(item);
964
+ item.selected = true;
965
+ }
966
+
967
+ this.input.value = this.currentItems.map(item => item.label).join(",");
968
+
969
+ this._styleItem(item);
970
+
971
+ }else{
972
+ this.currentItems = [item];
973
+ item.selected = true;
974
+
975
+ this.input.value = item.label;
976
+
977
+ this._styleItem(item);
978
+
979
+ if(!silent){
980
+ this._resolveValue();
981
+ }
982
+ }
983
+
984
+ this._focusItem(item);
985
+ }
986
+
987
+ _resolveValue(blur){
988
+ var output, initialValue;
605
989
 
606
- if(!this.currentItems.length && this.params.freetext){
607
- this.input.value = this.initialValues;
608
- this.typing = true;
609
- this.lastAction = "typing";
610
- }
611
-
612
- this.data = data;
613
-
614
- return data;
615
- }
616
-
617
- _parseListItem(option, data, level){
618
- var item = {};
619
-
620
- if(option.options){
621
- item = this._parseListGroup(option, level + 1);
622
- }else{
623
- item = {
624
- label:option.label,
625
- value:option.value,
626
- itemParams:option.itemParams,
627
- elementAttributes: option.elementAttributes,
628
- element:false,
629
- selected:false,
630
- visible:true,
631
- level:level,
632
- original:option,
633
- };
634
-
635
- if(this.initialValues && this.initialValues.indexOf(option.value) > -1){
636
- this._chooseItem(item, true);
637
- }
638
- }
639
-
640
- data.push(item);
641
- }
642
-
643
- _parseListGroup(option, level){
644
- var item = {
645
- label:option.label,
646
- group:true,
647
- itemParams:option.itemParams,
648
- elementAttributes:option.elementAttributes,
649
- element:false,
650
- visible:true,
651
- level:level,
652
- options:[],
653
- original:option,
654
- };
655
-
656
- option.options.forEach((child) => {
657
- this._parseListItem(child, item.options, level);
658
- });
659
-
660
- return item;
661
- }
662
-
663
- _sortOptions(options){
664
- var sorter;
665
-
666
- if(this.params.sort){
667
- sorter = typeof this.params.sort === "function" ? this.params.sort : this._defaultSortFunction.bind(this);
668
-
669
- this._sortGroup(sorter, options);
670
- }
671
-
672
- return options;
673
- }
674
-
675
- _sortGroup(sorter, options){
676
- options.sort((a,b) => {
677
- return sorter(a.label, b.label, a.value, b.value, a.original, b.original);
678
- });
679
-
680
- options.forEach((option) => {
681
- if(option.group){
682
- this._sortGroup(sorter, option.options);
683
- }
684
- })
685
- }
686
-
687
- _defaultSortFunction(as, bs){
688
- var a, b, a1, b1, i= 0, L, rx = /(\d+)|(\D+)/g, rd = /\d/;
689
- var emptyAlign = 0;
690
-
691
- if(this.params.sort === "desc"){
692
- [as, bs] = [bs, as];
693
- }
694
-
695
- //handle empty values
696
- if(!as && as!== 0){
697
- emptyAlign = !bs && bs!== 0 ? 0 : -1;
698
- }else if(!bs && bs!== 0){
699
- emptyAlign = 1;
700
- }else{
701
- if(isFinite(as) && isFinite(bs)) return as - bs;
702
- a = String(as).toLowerCase();
703
- b = String(bs).toLowerCase();
704
- if(a === b) return 0;
705
- if(!(rd.test(a) && rd.test(b))) return a > b ? 1 : -1;
706
- a = a.match(rx);
707
- b = b.match(rx);
708
- L = a.length > b.length ? b.length : a.length;
709
- while(i < L){
710
- a1= a[i];
711
- b1= b[i++];
712
- if(a1 !== b1){
713
- if(isFinite(a1) && isFinite(b1)){
714
- if(a1.charAt(0) === "0") a1 = "." + a1;
715
- if(b1.charAt(0) === "0") b1 = "." + b1;
716
- return a1 - b1;
717
- }
718
- else return a1 > b1 ? 1 : -1;
719
- }
720
- }
721
-
722
- return a.length > b.length;
723
- }
724
-
725
- return emptyAlign;
726
- }
727
-
728
- _filterOptions(){
729
- var filterFunc = this.params.filterFunc || this._defaultFilterFunc;
730
- var term = this.input.value;
731
- var results = [];
732
-
733
- if(term){
734
- this.filtered = true;
735
-
736
- this.data.forEach((item) => {
737
- this._filterItem(filterFunc, term, item);
738
- });
739
- }else{
740
- this.filtered = false;
741
- }
742
-
743
- return this.data;
744
- }
745
-
746
- _filterItem(func, term, item){
747
- var matches = false;
748
-
749
- if(!item.group){
750
- item.visible = func(term, item.label, item.value, item.original);
751
- }else{
752
- item.options.forEach((option) => {
753
- if(this._filterItem(func, term, option)){
754
- matches = true;
755
- }
756
- });
757
-
758
- item.visible = matches;
759
- }
760
-
761
- return item.visible;
762
- }
763
-
764
- _defaultFilterFunc(term, label, value, item){
765
- var term = String(term).toLowerCase();
766
-
767
- if(label !== null || typeof label !== "undefined"){
768
- if(String(label).toLowerCase().indexOf(term) > -1 || String(value).toLowerCase(term).indexOf() > -1){
769
- return true;
770
- }
771
- }
772
-
773
- return false;
774
- }
775
-
776
- //////////////////////////////////////
777
- /////////// Display List /////////////
778
- //////////////////////////////////////
779
-
780
- _clearList(){
781
- while(this.listEl.firstChild) this.listEl.removeChild(this.listEl.firstChild);
782
-
783
- this.displayItems = [];
784
- }
785
-
786
- _buildList(data){
787
- this._clearList();
788
-
789
- data.forEach((option) => {
790
- this._buildItem(option);
791
- });
792
-
793
- if(!this.displayItems.length){
794
- this._addPlaceholder(this.params.placeholderEmpty);
795
- }
796
- }
797
-
798
- _buildItem(item){
799
- var el = item.element,
800
- contents;
801
-
802
- if(!this.filtered || item.visible){
803
-
804
- if(!el){
805
- el = document.createElement("div");
806
- el.tabIndex = 0;
807
-
808
- contents = this.params.itemFormatter ? this.params.itemFormatter(item.label, item.value, item.original, el) : item.label;
809
-
810
- if(contents instanceof HTMLElement){
811
- el.appendChild(contents)
812
- }else{
813
- el.innerHTML = contents;
814
- }
815
-
816
- if(item.group){
817
- el.classList.add("tabulator-edit-list-group");
818
- }else{
819
- el.classList.add("tabulator-edit-list-item");
820
- }
821
-
822
- el.classList.add("tabulator-edit-list-group-level-" + item.level);
823
-
824
- if(item.elementAttributes && typeof item.elementAttributes == "object"){
825
- for (let key in item.elementAttributes){
826
- if(key.charAt(0) == "+"){
827
- key = key.slice(1);
828
- el.setAttribute(key, this.input.getAttribute(key) + item.elementAttributes["+" + key]);
829
- }else{
830
- el.setAttribute(key, item.elementAttributes[key]);
831
- }
832
- }
833
- }
834
-
835
- if(item.group){
836
- el.addEventListener("click", this._groupClick.bind(this, item));
837
- }else{
838
- el.addEventListener("click", this._itemClick.bind(this, item));
839
- }
840
-
841
- el.addEventListener("mousedown", this._preventBlur.bind(this));
842
-
843
- item.element = el;
844
- }
845
-
846
- this._styleItem(item);
847
-
848
- this.listEl.appendChild(el);
849
-
850
- if(item.group){
851
- item.options.forEach((option) => {
852
- this._buildItem(option);
853
- });
854
- }else{
855
- this.displayItems.push(item);
856
- }
857
- }
858
- }
859
-
860
- _showList(){
861
- var startVis = this.popup && this.popup.isVisible();
862
-
863
- if(this.input.parentNode){
864
- if(this.params.autocomplete && this.input.value === "" && !this.params.listOnEmpty){
865
- if(this.popup){
866
- this.popup.hide(true);
867
- return;
868
- }
869
- }
870
-
871
- this._setListWidth();
872
-
873
- if(!this.popup){
874
- this.popup = this.edit.popup(this.listEl);
875
- }
876
-
877
- this.popup.show(this.cell.getElement(), "bottom")
878
-
879
- if(!startVis){
880
- this.popup.hideOnBlur(this._resolveValue.bind(this, true));
881
- }
882
- }
883
- }
884
-
885
- _styleItem(item){
886
- if(item && item.element){
887
- if(item.selected){
888
- item.element.classList.add("active");
889
- }else{
890
- item.element.classList.remove("active");
891
- }
892
- }
893
- }
894
-
895
- //////////////////////////////////////
896
- ///////// User Interaction ///////////
897
- //////////////////////////////////////
898
-
899
- _itemClick(item, e){
900
- e.stopPropagation();
901
-
902
- this._chooseItem(item);
903
- }
904
-
905
- _groupClick(item, e){
906
- e.stopPropagation();
907
- }
908
-
909
-
910
- //////////////////////////////////////
911
- ////// Current Item Management ///////
912
- //////////////////////////////////////
913
-
914
- _cancel(){
915
- this.popup.hide(true);
916
- this.actions.cancel();
917
- }
918
-
919
- _clearChoices(){
920
- this.typing = true;
921
-
922
- this.currentItems.forEach((item) => {
923
- item.selected = false;
924
- this._styleItem(item);
925
- });
926
-
927
- this.currentItems = [];
928
-
929
- this.focusedItem = null;
930
- }
931
-
932
- _chooseItem(item, silent){
933
- var index;
934
-
935
- this.typing = false;
936
-
937
- if(this.params.multiselect){
938
- index = this.currentItems.indexOf(item);
939
-
940
- if(index > -1){
941
- this.currentItems.splice(index, 1);
942
- item.selected = false;
943
- }else{
944
- this.currentItems.push(item);
945
- item.selected = true;
946
- }
947
-
948
- this.input.value = this.currentItems.map(item => item.label).join(",");
949
-
950
- this._styleItem(item);
951
-
952
- }else{
953
- this.currentItems = [item];
954
- item.selected = true;
955
-
956
- console.log("choose")
957
-
958
- this.input.value = item.label;
959
-
960
- this._styleItem(item);
961
-
962
- if(!silent){
963
- this._resolveValue();
964
- }
965
- }
966
-
967
- this._focusItem(item);
968
- }
969
-
970
- _resolveValue(blur){
971
- var output, initialValue;
972
-
973
- this.popup.hide(true);
974
-
975
- if(this.params.multiselect){
976
- output = this.currentItems.map(item => item.value);
977
- }else{
978
- if(blur && this.params.autocomplete && this.typing){
979
- if(this.params.freetext || (this.params.allowEmpty && this.input.value === "")){
980
- output = this.input.value;
981
- }else{
982
- this.actions.cancel();
983
- return;
984
- }
985
- }else{
986
- if(this.currentItems[0]){
987
- output = this.currentItems[0].value;
988
- }else{
989
- initialValue = this.initialValues[0];
990
-
991
- if(initialValue === null || typeof initialValue === "undefined" || initialValue === ""){
992
- output = initialValue;
993
- }else{
994
- output = this.params.emptyValue;
995
- }
996
- }
997
-
998
- }
999
- }
1000
-
1001
- if(output === ""){
1002
- output = this.params.emptyValue;
1003
- }
1004
-
1005
- this.actions.success(output);
1006
-
1007
- if(this.isFilter){
1008
- this.initialValues = output && !Array.isArray[output] ? [output] : output;
1009
- }
1010
- }
1011
-
990
+ if(this.popup){
991
+ this.popup.hide(true);
992
+ }
993
+
994
+ if(this.params.multiselect){
995
+ output = this.currentItems.map(item => item.value);
996
+ }else{
997
+ if(blur && this.params.autocomplete && this.typing){
998
+ if(this.params.freetext || (this.params.allowEmpty && this.input.value === "")){
999
+ output = this.input.value;
1000
+ }else{
1001
+ this.actions.cancel();
1002
+ return;
1003
+ }
1004
+ }else{
1005
+ if(this.currentItems[0]){
1006
+ output = this.currentItems[0].value;
1007
+ }else{
1008
+ initialValue = this.initialValues[0];
1009
+
1010
+ if(initialValue === null || typeof initialValue === "undefined" || initialValue === ""){
1011
+ output = initialValue;
1012
+ }else{
1013
+ output = this.params.emptyValue;
1014
+ }
1015
+ }
1016
+
1017
+ }
1018
+ }
1019
+
1020
+ if(output === ""){
1021
+ output = this.params.emptyValue;
1022
+ }
1023
+
1024
+ this.actions.success(output);
1025
+
1026
+ if(this.isFilter){
1027
+ this.initialValues = output && !Array.isArray(output) ? [output] : output;
1028
+ this.currentItems = [];
1029
+ }
1030
+ }
1031
+
1012
1032
  }