tabulator-tables 6.5.0 → 6.5.1

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 (222) hide show
  1. package/dist/js/tabulator.js +1 -1
  2. package/dist/js/tabulator.min.js +1 -1
  3. package/dist/js/tabulator_esm.js +1 -1
  4. package/dist/js/tabulator_esm.min.js +1 -1
  5. package/dist/js/tabulator_esm.min.mjs +1 -1
  6. package/dist/js/tabulator_esm.mjs +1 -1
  7. package/package.json +2 -1
  8. package/src/js/builds/esm.js +16 -0
  9. package/src/js/builds/jquery_wrapper.js +63 -0
  10. package/src/js/builds/usd.js +1 -0
  11. package/src/js/core/ColumnManager.js +789 -0
  12. package/src/js/core/CoreFeature.js +140 -0
  13. package/src/js/core/FooterManager.js +102 -0
  14. package/src/js/core/Module.js +140 -0
  15. package/src/js/core/RowManager.js +1140 -0
  16. package/src/js/core/Tabulator.js +928 -0
  17. package/src/js/core/TabulatorFull.js +21 -0
  18. package/src/js/core/cell/Cell.js +299 -0
  19. package/src/js/core/cell/CellComponent.js +79 -0
  20. package/src/js/core/column/Column.js +978 -0
  21. package/src/js/core/column/ColumnComponent.js +151 -0
  22. package/src/js/core/column/defaults/options.js +18 -0
  23. package/src/js/core/defaults/options.js +66 -0
  24. package/src/js/core/modules/core.js +3 -0
  25. package/src/js/core/modules/optional.js +37 -0
  26. package/src/js/core/rendering/Renderer.js +204 -0
  27. package/src/js/core/rendering/renderers/BasicHorizontal.js +27 -0
  28. package/src/js/core/rendering/renderers/BasicVertical.js +103 -0
  29. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +587 -0
  30. package/src/js/core/rendering/renderers/VirtualDomVertical.js +642 -0
  31. package/src/js/core/row/PseudoRow.js +47 -0
  32. package/src/js/core/row/Row.js +487 -0
  33. package/src/js/core/row/RowComponent.js +94 -0
  34. package/src/js/core/tools/Alert.js +66 -0
  35. package/src/js/core/tools/ComponentFunctionBinder.js +32 -0
  36. package/src/js/core/tools/DataLoader.js +128 -0
  37. package/src/js/core/tools/DependencyRegistry.js +82 -0
  38. package/src/js/core/tools/DeprecationAdvisor.js +51 -0
  39. package/src/js/core/tools/ExternalEventBus.js +105 -0
  40. package/src/js/core/tools/Helpers.js +66 -0
  41. package/src/js/core/tools/InteractionMonitor.js +329 -0
  42. package/src/js/core/tools/InternalEventBus.js +162 -0
  43. package/src/js/core/tools/ModuleBinder.js +153 -0
  44. package/src/js/core/tools/OptionsList.js +45 -0
  45. package/src/js/core/tools/Popup.js +317 -0
  46. package/src/js/core/tools/TableRegistry.js +65 -0
  47. package/src/js/modules/Accessor/Accessor.js +115 -0
  48. package/src/js/modules/Accessor/defaults/accessors.js +5 -0
  49. package/src/js/modules/Ajax/Ajax.js +142 -0
  50. package/src/js/modules/Ajax/defaults/config.js +3 -0
  51. package/src/js/modules/Ajax/defaults/contentTypeFormatters.js +45 -0
  52. package/src/js/modules/Ajax/defaults/loaderPromise.js +87 -0
  53. package/src/js/modules/Ajax/defaults/urlGenerator.js +44 -0
  54. package/src/js/modules/Clipboard/Clipboard.js +282 -0
  55. package/src/js/modules/Clipboard/defaults/pasteActions.js +11 -0
  56. package/src/js/modules/Clipboard/defaults/pasteParsers.js +75 -0
  57. package/src/js/modules/Clipboard/extensions/extensions.js +9 -0
  58. package/src/js/modules/Clipboard/extensions/keybindings/actions.js +9 -0
  59. package/src/js/modules/Clipboard/extensions/keybindings/bindings.js +3 -0
  60. package/src/js/modules/ColumnCalcs/CalcComponent.js +46 -0
  61. package/src/js/modules/ColumnCalcs/ColumnCalcs.js +586 -0
  62. package/src/js/modules/ColumnCalcs/defaults/calculations.js +93 -0
  63. package/src/js/modules/Comms/Comms.js +49 -0
  64. package/src/js/modules/DataTree/DataTree.js +620 -0
  65. package/src/js/modules/Download/Download.js +146 -0
  66. package/src/js/modules/Download/defaults/downloaders/csv.js +61 -0
  67. package/src/js/modules/Download/defaults/downloaders/html.js +5 -0
  68. package/src/js/modules/Download/defaults/downloaders/json.js +34 -0
  69. package/src/js/modules/Download/defaults/downloaders/jsonLines.js +32 -0
  70. package/src/js/modules/Download/defaults/downloaders/pdf.js +113 -0
  71. package/src/js/modules/Download/defaults/downloaders/xlsx.js +103 -0
  72. package/src/js/modules/Download/defaults/downloaders.js +15 -0
  73. package/src/js/modules/Edit/Edit.js +845 -0
  74. package/src/js/modules/Edit/List.js +1060 -0
  75. package/src/js/modules/Edit/defaults/editors/adaptable.js +37 -0
  76. package/src/js/modules/Edit/defaults/editors/date.js +144 -0
  77. package/src/js/modules/Edit/defaults/editors/datetime.js +131 -0
  78. package/src/js/modules/Edit/defaults/editors/input.js +77 -0
  79. package/src/js/modules/Edit/defaults/editors/list.js +7 -0
  80. package/src/js/modules/Edit/defaults/editors/number.js +110 -0
  81. package/src/js/modules/Edit/defaults/editors/progress.js +127 -0
  82. package/src/js/modules/Edit/defaults/editors/range.js +81 -0
  83. package/src/js/modules/Edit/defaults/editors/star.js +146 -0
  84. package/src/js/modules/Edit/defaults/editors/textarea.js +123 -0
  85. package/src/js/modules/Edit/defaults/editors/tickCross.js +95 -0
  86. package/src/js/modules/Edit/defaults/editors/time.js +132 -0
  87. package/src/js/modules/Edit/defaults/editors.js +27 -0
  88. package/src/js/modules/Edit/inputMask.js +74 -0
  89. package/src/js/modules/Export/Export.js +654 -0
  90. package/src/js/modules/Export/ExportColumn.js +9 -0
  91. package/src/js/modules/Export/ExportRow.js +8 -0
  92. package/src/js/modules/Export/defaults/columnLookups.js +3 -0
  93. package/src/js/modules/Export/defaults/rowLookups.js +18 -0
  94. package/src/js/modules/Filter/Filter.js +902 -0
  95. package/src/js/modules/Filter/defaults/filters.js +215 -0
  96. package/src/js/modules/Format/Format.js +200 -0
  97. package/src/js/modules/Format/defaults/formatters/adaptable.js +32 -0
  98. package/src/js/modules/Format/defaults/formatters/array.js +30 -0
  99. package/src/js/modules/Format/defaults/formatters/buttonCross.js +3 -0
  100. package/src/js/modules/Format/defaults/formatters/buttonTick.js +3 -0
  101. package/src/js/modules/Format/defaults/formatters/color.js +4 -0
  102. package/src/js/modules/Format/defaults/formatters/datetime.js +39 -0
  103. package/src/js/modules/Format/defaults/formatters/datetimediff.js +43 -0
  104. package/src/js/modules/Format/defaults/formatters/handle.js +4 -0
  105. package/src/js/modules/Format/defaults/formatters/html.js +3 -0
  106. package/src/js/modules/Format/defaults/formatters/image.js +40 -0
  107. package/src/js/modules/Format/defaults/formatters/json.js +12 -0
  108. package/src/js/modules/Format/defaults/formatters/link.js +82 -0
  109. package/src/js/modules/Format/defaults/formatters/lookup.js +10 -0
  110. package/src/js/modules/Format/defaults/formatters/money.js +44 -0
  111. package/src/js/modules/Format/defaults/formatters/plaintext.js +3 -0
  112. package/src/js/modules/Format/defaults/formatters/progress.js +133 -0
  113. package/src/js/modules/Format/defaults/formatters/rownum.js +14 -0
  114. package/src/js/modules/Format/defaults/formatters/star.js +38 -0
  115. package/src/js/modules/Format/defaults/formatters/textarea.js +4 -0
  116. package/src/js/modules/Format/defaults/formatters/tickCross.js +22 -0
  117. package/src/js/modules/Format/defaults/formatters/toggle.js +48 -0
  118. package/src/js/modules/Format/defaults/formatters/traffic.js +47 -0
  119. package/src/js/modules/Format/defaults/formatters.js +47 -0
  120. package/src/js/modules/FrozenColumns/FrozenColumns.js +302 -0
  121. package/src/js/modules/FrozenRows/FrozenRows.js +175 -0
  122. package/src/js/modules/GroupRows/Group.js +615 -0
  123. package/src/js/modules/GroupRows/GroupComponent.js +69 -0
  124. package/src/js/modules/GroupRows/GroupRows.js +636 -0
  125. package/src/js/modules/History/History.js +172 -0
  126. package/src/js/modules/History/defaults/redoers.js +31 -0
  127. package/src/js/modules/History/defaults/undoers.js +33 -0
  128. package/src/js/modules/History/extensions/extensions.js +9 -0
  129. package/src/js/modules/History/extensions/keybindings/actions.js +27 -0
  130. package/src/js/modules/History/extensions/keybindings/bindings.js +4 -0
  131. package/src/js/modules/HtmlTableImport/HtmlTableImport.js +180 -0
  132. package/src/js/modules/Import/Import.js +303 -0
  133. package/src/js/modules/Import/defaults/importers/array.js +3 -0
  134. package/src/js/modules/Import/defaults/importers/csv.js +61 -0
  135. package/src/js/modules/Import/defaults/importers/json.js +8 -0
  136. package/src/js/modules/Import/defaults/importers/xlsx.js +7 -0
  137. package/src/js/modules/Import/defaults/importers.js +11 -0
  138. package/src/js/modules/Interaction/Interaction.js +339 -0
  139. package/src/js/modules/Keybindings/Keybindings.js +198 -0
  140. package/src/js/modules/Keybindings/defaults/actions.js +90 -0
  141. package/src/js/modules/Keybindings/defaults/bindings.js +12 -0
  142. package/src/js/modules/Layout/Layout.js +66 -0
  143. package/src/js/modules/Layout/defaults/modes/fitColumns.js +171 -0
  144. package/src/js/modules/Layout/defaults/modes/fitData.js +10 -0
  145. package/src/js/modules/Layout/defaults/modes/fitDataGeneral.js +10 -0
  146. package/src/js/modules/Layout/defaults/modes/fitDataStretch.js +40 -0
  147. package/src/js/modules/Layout/defaults/modes.js +12 -0
  148. package/src/js/modules/Localize/Localize.js +184 -0
  149. package/src/js/modules/Localize/defaults/langs.js +37 -0
  150. package/src/js/modules/Menu/Menu.js +302 -0
  151. package/src/js/modules/MoveColumns/MoveColumns.js +311 -0
  152. package/src/js/modules/MoveRows/MoveRows.js +604 -0
  153. package/src/js/modules/MoveRows/defaults/receivers.js +30 -0
  154. package/src/js/modules/MoveRows/defaults/senders.js +5 -0
  155. package/src/js/modules/Mutator/Mutator.js +164 -0
  156. package/src/js/modules/Mutator/defaults/mutators.js +1 -0
  157. package/src/js/modules/Page/Page.js +891 -0
  158. package/src/js/modules/Page/defaults/pageCounters/pages.js +33 -0
  159. package/src/js/modules/Page/defaults/pageCounters/rows.js +40 -0
  160. package/src/js/modules/Page/defaults/pageCounters.js +8 -0
  161. package/src/js/modules/Persistence/Persistence.js +473 -0
  162. package/src/js/modules/Persistence/defaults/readers.js +29 -0
  163. package/src/js/modules/Persistence/defaults/writers.js +13 -0
  164. package/src/js/modules/Popup/Popup.js +227 -0
  165. package/src/js/modules/Print/Print.js +136 -0
  166. package/src/js/modules/ReactiveData/ReactiveData.js +416 -0
  167. package/src/js/modules/ResizeColumns/ResizeColumns.js +365 -0
  168. package/src/js/modules/ResizeRows/ResizeRows.js +145 -0
  169. package/src/js/modules/ResizeTable/ResizeTable.js +158 -0
  170. package/src/js/modules/ResponsiveLayout/ResponsiveLayout.js +354 -0
  171. package/src/js/modules/ResponsiveLayout/extensions/extensions.js +9 -0
  172. package/src/js/modules/ResponsiveLayout/extensions/formatters/responsiveCollapse.js +44 -0
  173. package/src/js/modules/SelectRange/Range.js +366 -0
  174. package/src/js/modules/SelectRange/RangeComponent.js +91 -0
  175. package/src/js/modules/SelectRange/SelectRange.js +993 -0
  176. package/src/js/modules/SelectRange/extensions/clipboard/pasteActions.js +45 -0
  177. package/src/js/modules/SelectRange/extensions/clipboard/pasteParsers.js +57 -0
  178. package/src/js/modules/SelectRange/extensions/export/columnLookups.js +11 -0
  179. package/src/js/modules/SelectRange/extensions/export/rowLookups.js +5 -0
  180. package/src/js/modules/SelectRange/extensions/extensions.js +21 -0
  181. package/src/js/modules/SelectRange/extensions/keybindings/actions.js +38 -0
  182. package/src/js/modules/SelectRange/extensions/keybindings/bindings.js +14 -0
  183. package/src/js/modules/SelectRow/SelectRow.js +499 -0
  184. package/src/js/modules/SelectRow/extensions/extensions.js +9 -0
  185. package/src/js/modules/SelectRow/extensions/formatters/rowSelection.js +60 -0
  186. package/src/js/modules/Sort/Sort.js +480 -0
  187. package/src/js/modules/Sort/defaults/sorters/alphanum.js +44 -0
  188. package/src/js/modules/Sort/defaults/sorters/array.js +82 -0
  189. package/src/js/modules/Sort/defaults/sorters/boolean.js +7 -0
  190. package/src/js/modules/Sort/defaults/sorters/date.js +10 -0
  191. package/src/js/modules/Sort/defaults/sorters/datetime.js +48 -0
  192. package/src/js/modules/Sort/defaults/sorters/exists.js +7 -0
  193. package/src/js/modules/Sort/defaults/sorters/number.js +40 -0
  194. package/src/js/modules/Sort/defaults/sorters/string.js +34 -0
  195. package/src/js/modules/Sort/defaults/sorters/time.js +10 -0
  196. package/src/js/modules/Sort/defaults/sorters.js +21 -0
  197. package/src/js/modules/Spreadsheet/GridCalculator.js +64 -0
  198. package/src/js/modules/Spreadsheet/Sheet.js +243 -0
  199. package/src/js/modules/Spreadsheet/SheetComponent.js +59 -0
  200. package/src/js/modules/Spreadsheet/Spreadsheet.js +309 -0
  201. package/src/js/modules/Tooltip/Tooltip.js +128 -0
  202. package/src/js/modules/Validate/Validate.js +303 -0
  203. package/src/js/modules/Validate/defaults/validators.js +150 -0
  204. package/src/scss/tabulator.scss +1693 -0
  205. package/src/scss/themes/bootstrap/tabulator_bootstrap3.scss +302 -0
  206. package/src/scss/themes/bootstrap/tabulator_bootstrap4.scss +589 -0
  207. package/src/scss/themes/bootstrap/tabulator_bootstrap5.scss +979 -0
  208. package/src/scss/themes/bootstrap/variables3.scss +872 -0
  209. package/src/scss/themes/bootstrap/variables4.scss +1059 -0
  210. package/src/scss/themes/bootstrap/variables5.scss +1967 -0
  211. package/src/scss/themes/bulma/tabulator_bulma.scss +316 -0
  212. package/src/scss/themes/bulma/variables.scss +198 -0
  213. package/src/scss/themes/materialize/tabulator_materialize.scss +318 -0
  214. package/src/scss/themes/materialize/variables.scss +71 -0
  215. package/src/scss/themes/semanticui/tabulator_semanticui.scss +623 -0
  216. package/src/scss/themes/semanticui/variables.scss +843 -0
  217. package/src/scss/themes/semanticui/variables_table.scss +248 -0
  218. package/src/scss/themes/tabulator_midnight.scss +235 -0
  219. package/src/scss/themes/tabulator_modern.scss +308 -0
  220. package/src/scss/themes/tabulator_simple.scss +143 -0
  221. package/src/scss/themes/tabulator_site.scss +267 -0
  222. package/src/scss/themes/tabulator_site_dark.scss +496 -0
@@ -0,0 +1,902 @@
1
+ import Module from '../../core/Module.js';
2
+
3
+ import defaultFilters from './defaults/filters.js';
4
+
5
+ export default class Filter extends Module{
6
+
7
+ static moduleName = "filter";
8
+
9
+ //load defaults
10
+ static filters = defaultFilters;
11
+
12
+ constructor(table){
13
+ super(table);
14
+
15
+ this.filterList = []; //hold filter list
16
+ this.headerFilters = {}; //hold column filters
17
+ this.headerFilterColumns = []; //hold columns that use header filters
18
+
19
+ this.prevHeaderFilterChangeCheck = "";
20
+ this.prevHeaderFilterChangeCheck = "{}";
21
+
22
+ this.changed = false; //has filtering changed since last render
23
+ this.tableInitialized = false;
24
+
25
+ this.registerTableOption("filterMode", "local"); //local or remote filtering
26
+
27
+ this.registerTableOption("initialFilter", false); //initial filtering criteria
28
+ this.registerTableOption("initialHeaderFilter", false); //initial header filtering criteria
29
+ this.registerTableOption("headerFilterLiveFilterDelay", 300); //delay before updating column after user types in header filter
30
+ this.registerTableOption("placeholderHeaderFilter", false); //placeholder when header filter is empty
31
+
32
+ this.registerColumnOption("headerFilter");
33
+ this.registerColumnOption("headerFilterPlaceholder");
34
+ this.registerColumnOption("headerFilterParams");
35
+ this.registerColumnOption("headerFilterEmptyCheck");
36
+ this.registerColumnOption("headerFilterFunc");
37
+ this.registerColumnOption("headerFilterFuncParams");
38
+ this.registerColumnOption("headerFilterLiveFilter");
39
+
40
+ this.registerTableFunction("searchRows", this.searchRows.bind(this));
41
+ this.registerTableFunction("searchData", this.searchData.bind(this));
42
+
43
+ this.registerTableFunction("setFilter", this.userSetFilter.bind(this));
44
+ this.registerTableFunction("refreshFilter", this.userRefreshFilter.bind(this));
45
+ this.registerTableFunction("addFilter", this.userAddFilter.bind(this));
46
+ this.registerTableFunction("getFilters", this.getFilters.bind(this));
47
+ this.registerTableFunction("setHeaderFilterFocus", this.userSetHeaderFilterFocus.bind(this));
48
+ this.registerTableFunction("getHeaderFilterValue", this.userGetHeaderFilterValue.bind(this));
49
+ this.registerTableFunction("setHeaderFilterValue", this.userSetHeaderFilterValue.bind(this));
50
+ this.registerTableFunction("getHeaderFilters", this.getHeaderFilters.bind(this));
51
+ this.registerTableFunction("removeFilter", this.userRemoveFilter.bind(this));
52
+ this.registerTableFunction("clearFilter", this.userClearFilter.bind(this));
53
+ this.registerTableFunction("clearHeaderFilter", this.userClearHeaderFilter.bind(this));
54
+
55
+ this.registerComponentFunction("column", "headerFilterFocus", this.setHeaderFilterFocus.bind(this));
56
+ this.registerComponentFunction("column", "reloadHeaderFilter", this.reloadHeaderFilter.bind(this));
57
+ this.registerComponentFunction("column", "getHeaderFilterValue", this.getHeaderFilterValue.bind(this));
58
+ this.registerComponentFunction("column", "setHeaderFilterValue", this.setHeaderFilterValue.bind(this));
59
+ }
60
+
61
+ initialize(){
62
+ this.subscribe("column-init", this.initializeColumnHeaderFilter.bind(this));
63
+ this.subscribe("column-width-fit-before", this.hideHeaderFilterElements.bind(this));
64
+ this.subscribe("column-width-fit-after", this.showHeaderFilterElements.bind(this));
65
+ this.subscribe("table-built", this.tableBuilt.bind(this));
66
+ this.subscribe("placeholder", this.generatePlaceholder.bind(this));
67
+
68
+ if(this.table.options.filterMode === "remote"){
69
+ this.subscribe("data-params", this.remoteFilterParams.bind(this));
70
+ }
71
+
72
+ this.registerDataHandler(this.filter.bind(this), 10);
73
+ }
74
+
75
+ tableBuilt(){
76
+ if(this.table.options.initialFilter){
77
+ this.setFilter(this.table.options.initialFilter);
78
+ }
79
+
80
+ if(this.table.options.initialHeaderFilter){
81
+ this.table.options.initialHeaderFilter.forEach((item) => {
82
+
83
+ var column = this.table.columnManager.findColumn(item.field);
84
+
85
+ if(column){
86
+ this.setHeaderFilterValue(column, item.value);
87
+ }else{
88
+ console.warn("Column Filter Error - No matching column found:", item.field);
89
+ return false;
90
+ }
91
+ });
92
+ }
93
+
94
+ this.tableInitialized = true;
95
+ }
96
+
97
+ remoteFilterParams(data, config, silent, params){
98
+ params.filter = this.getFilters(true, true);
99
+ return params;
100
+ }
101
+
102
+ generatePlaceholder(text){
103
+ if(this.table.options.placeholderHeaderFilter && Object.keys(this.headerFilters).length){
104
+ return this.table.options.placeholderHeaderFilter;
105
+ }
106
+ }
107
+
108
+ ///////////////////////////////////
109
+ ///////// Table Functions /////////
110
+ ///////////////////////////////////
111
+
112
+ //set standard filters
113
+ userSetFilter(field, type, value, params){
114
+ this.setFilter(field, type, value, params);
115
+ this.refreshFilter();
116
+ }
117
+
118
+ //set standard filters
119
+ userRefreshFilter(){
120
+ this.refreshFilter();
121
+ }
122
+
123
+ //add filter to array
124
+ userAddFilter(field, type, value, params){
125
+ this.addFilter(field, type, value, params);
126
+ this.refreshFilter();
127
+ }
128
+
129
+ userSetHeaderFilterFocus(field){
130
+ var column = this.table.columnManager.findColumn(field);
131
+
132
+ if(column){
133
+ this.setHeaderFilterFocus(column);
134
+ }else{
135
+ console.warn("Column Filter Focus Error - No matching column found:", field);
136
+ return false;
137
+ }
138
+ }
139
+
140
+ userGetHeaderFilterValue(field) {
141
+ var column = this.table.columnManager.findColumn(field);
142
+
143
+ if(column){
144
+ return this.getHeaderFilterValue(column);
145
+ }else{
146
+ console.warn("Column Filter Error - No matching column found:", field);
147
+ }
148
+ }
149
+
150
+ userSetHeaderFilterValue(field, value){
151
+ var column = this.table.columnManager.findColumn(field);
152
+
153
+ if(column){
154
+ this.setHeaderFilterValue(column, value);
155
+ }else{
156
+ console.warn("Column Filter Error - No matching column found:", field);
157
+ return false;
158
+ }
159
+ }
160
+
161
+ //remove filter from array
162
+ userRemoveFilter(field, type, value){
163
+ this.removeFilter(field, type, value);
164
+ this.refreshFilter();
165
+ }
166
+
167
+ //clear filters
168
+ userClearFilter(all){
169
+ this.clearFilter(all);
170
+ this.refreshFilter();
171
+ }
172
+
173
+ //clear header filters
174
+ userClearHeaderFilter(){
175
+ this.clearHeaderFilter();
176
+ this.refreshFilter();
177
+ }
178
+
179
+
180
+ //search for specific row components
181
+ searchRows(field, type, value){
182
+ return this.search("rows", field, type, value);
183
+ }
184
+
185
+ //search for specific data
186
+ searchData(field, type, value){
187
+ return this.search("data", field, type, value);
188
+ }
189
+
190
+ ///////////////////////////////////
191
+ ///////// Internal Logic //////////
192
+ ///////////////////////////////////
193
+
194
+ initializeColumnHeaderFilter(column){
195
+ var def = column.definition;
196
+
197
+ if(def.headerFilter){
198
+ this.initializeColumn(column);
199
+ }
200
+ }
201
+
202
+ //initialize column header filter
203
+ initializeColumn(column, value){
204
+ var self = this,
205
+ field = column.getField();
206
+
207
+ //handle successfully value change
208
+ function success(value){
209
+ var filterType = (column.modules.filter.tagType == "input" && column.modules.filter.attrType == "text") || column.modules.filter.tagType == "textarea" ? "partial" : "match",
210
+ type = "",
211
+ filterChangeCheck = "",
212
+ filterFunc;
213
+
214
+ if(typeof column.modules.filter.prevSuccess === "undefined" || column.modules.filter.prevSuccess !== value){
215
+
216
+ column.modules.filter.prevSuccess = value;
217
+
218
+ if(!column.modules.filter.emptyFunc(value)){
219
+ column.modules.filter.value = value;
220
+
221
+ switch(typeof column.definition.headerFilterFunc){
222
+ case "string":
223
+ if(Filter.filters[column.definition.headerFilterFunc]){
224
+ type = column.definition.headerFilterFunc;
225
+ filterFunc = function(data){
226
+ var params = column.definition.headerFilterFuncParams || {};
227
+ var fieldVal = column.getFieldValue(data);
228
+
229
+ params = typeof params === "function" ? params(value, fieldVal, data) : params;
230
+
231
+ return Filter.filters[column.definition.headerFilterFunc](value, fieldVal, data, params);
232
+ };
233
+ }else{
234
+ console.warn("Header Filter Error - Matching filter function not found: ", column.definition.headerFilterFunc);
235
+ }
236
+ break;
237
+
238
+ case "function":
239
+ filterFunc = function(data){
240
+ var params = column.definition.headerFilterFuncParams || {};
241
+ var fieldVal = column.getFieldValue(data);
242
+
243
+ params = typeof params === "function" ? params(value, fieldVal, data) : params;
244
+
245
+ return column.definition.headerFilterFunc(value, fieldVal, data, params);
246
+ };
247
+
248
+ type = filterFunc;
249
+ break;
250
+ }
251
+
252
+ if(!filterFunc){
253
+ switch(filterType){
254
+ case "partial":
255
+ filterFunc = function(data){
256
+ var colVal = column.getFieldValue(data);
257
+
258
+ if(typeof colVal !== 'undefined' && colVal !== null){
259
+ return String(colVal).toLowerCase().indexOf(String(value).toLowerCase()) > -1;
260
+ }else{
261
+ return false;
262
+ }
263
+ };
264
+ type = "like";
265
+ break;
266
+
267
+ default:
268
+ filterFunc = function(data){
269
+ return column.getFieldValue(data) == value;
270
+ };
271
+ type = "=";
272
+ }
273
+ }
274
+
275
+ self.headerFilters[field] = {value:value, func:filterFunc, type:type};
276
+ }else{
277
+ delete self.headerFilters[field];
278
+ }
279
+
280
+ column.modules.filter.value = value;
281
+
282
+ filterChangeCheck = JSON.stringify(self.headerFilters);
283
+
284
+ if(self.prevHeaderFilterChangeCheck !== filterChangeCheck){
285
+ self.prevHeaderFilterChangeCheck = filterChangeCheck;
286
+
287
+ self.trackChanges();
288
+ self.refreshFilter();
289
+ }
290
+ }
291
+
292
+ return true;
293
+ }
294
+
295
+ column.modules.filter = {
296
+ success:success,
297
+ attrType:false,
298
+ tagType:false,
299
+ emptyFunc:false,
300
+ };
301
+
302
+ this.generateHeaderFilterElement(column);
303
+ }
304
+
305
+ generateHeaderFilterElement(column, initialValue, reinitialize){
306
+ var self = this,
307
+ success = column.modules.filter.success,
308
+ field = column.getField(),
309
+ filterElement, editor, editorElement, cellWrapper, typingTimer, searchTrigger, params, onRenderedCallback;
310
+
311
+ column.modules.filter.value = initialValue;
312
+
313
+ //handle aborted edit
314
+ function cancel(){}
315
+
316
+ function onRendered(callback){
317
+ onRenderedCallback = callback;
318
+ }
319
+
320
+ if(column.modules.filter.headerElement && column.modules.filter.headerElement.parentNode){
321
+ column.contentElement.removeChild(column.modules.filter.headerElement.parentNode);
322
+ }
323
+
324
+ if(field){
325
+
326
+ //set empty value function
327
+ column.modules.filter.emptyFunc = column.definition.headerFilterEmptyCheck || function(value){
328
+ return !value && value !== 0;
329
+ };
330
+
331
+ filterElement = document.createElement("div");
332
+ filterElement.classList.add("tabulator-header-filter");
333
+
334
+ //set column editor
335
+ switch(typeof column.definition.headerFilter){
336
+ case "string":
337
+ if(self.table.modules.edit.editors[column.definition.headerFilter]){
338
+ editor = self.table.modules.edit.editors[column.definition.headerFilter];
339
+
340
+ if((column.definition.headerFilter === "tick" || column.definition.headerFilter === "tickCross") && !column.definition.headerFilterEmptyCheck){
341
+ column.modules.filter.emptyFunc = function(value){
342
+ return value !== true && value !== false;
343
+ };
344
+ }
345
+ }else{
346
+ console.warn("Filter Error - Cannot build header filter, No such editor found: ", column.definition.editor);
347
+ }
348
+ break;
349
+
350
+ case "function":
351
+ editor = column.definition.headerFilter;
352
+ break;
353
+
354
+ case "boolean":
355
+ if(column.modules.edit && column.modules.edit.editor){
356
+ editor = column.modules.edit.editor;
357
+ }else{
358
+ if(column.definition.formatter && self.table.modules.edit.editors[column.definition.formatter]){
359
+ editor = self.table.modules.edit.editors[column.definition.formatter];
360
+
361
+ if((column.definition.formatter === "tick" || column.definition.formatter === "tickCross") && !column.definition.headerFilterEmptyCheck){
362
+ column.modules.filter.emptyFunc = function(value){
363
+ return value !== true && value !== false;
364
+ };
365
+ }
366
+ }else{
367
+ editor = self.table.modules.edit.editors["input"];
368
+ }
369
+ }
370
+ break;
371
+ }
372
+
373
+ if(editor){
374
+
375
+ cellWrapper = {
376
+ getValue:function(){
377
+ return typeof initialValue !== "undefined" ? initialValue : "";
378
+ },
379
+ getField:function(){
380
+ return column.definition.field;
381
+ },
382
+ getElement:function(){
383
+ return filterElement;
384
+ },
385
+ getColumn:function(){
386
+ return column.getComponent();
387
+ },
388
+ getTable:() => {
389
+ return this.table;
390
+ },
391
+ getType:() => {
392
+ return "header";
393
+ },
394
+ getRow:function(){
395
+ return {
396
+ normalizeHeight:function(){
397
+
398
+ }
399
+ };
400
+ }
401
+ };
402
+
403
+ params = column.definition.headerFilterParams || {};
404
+
405
+ params = typeof params === "function" ? params.call(self.table, cellWrapper) : params;
406
+
407
+ editorElement = editor.call(this.table.modules.edit, cellWrapper, onRendered, success, cancel, params);
408
+
409
+ if(!editorElement){
410
+ console.warn("Filter Error - Cannot add filter to " + field + " column, editor returned a value of false");
411
+ return;
412
+ }
413
+
414
+ if(!(editorElement instanceof Node)){
415
+ console.warn("Filter Error - Cannot add filter to " + field + " column, editor should return an instance of Node, the editor returned:", editorElement);
416
+ return;
417
+ }
418
+
419
+ //set Placeholder Text
420
+ self.langBind("headerFilters|columns|" + column.definition.field, function(value){
421
+ editorElement.setAttribute("placeholder", typeof value !== "undefined" && value ? value : (column.definition.headerFilterPlaceholder || self.langText("headerFilters|default")));
422
+ });
423
+
424
+ //focus on element on click
425
+ editorElement.addEventListener("click", function(e){
426
+ e.stopPropagation();
427
+ editorElement.focus();
428
+ });
429
+
430
+ editorElement.addEventListener("focus", (e) => {
431
+ var left = this.table.columnManager.contentsElement.scrollLeft;
432
+
433
+ var headerPos = this.table.rowManager.element.scrollLeft;
434
+
435
+ if(left !== headerPos){
436
+ this.table.rowManager.scrollHorizontal(left);
437
+ this.table.columnManager.scrollHorizontal(left);
438
+ }
439
+ });
440
+
441
+ //live update filters as user types
442
+ typingTimer = false;
443
+
444
+ searchTrigger = function(e){
445
+ if(typingTimer){
446
+ clearTimeout(typingTimer);
447
+ }
448
+
449
+ typingTimer = setTimeout(function(){
450
+ success(editorElement.value);
451
+ },self.table.options.headerFilterLiveFilterDelay);
452
+ };
453
+
454
+ column.modules.filter.headerElement = editorElement;
455
+ column.modules.filter.attrType = editorElement.hasAttribute("type") ? editorElement.getAttribute("type").toLowerCase() : "" ;
456
+ column.modules.filter.tagType = editorElement.tagName.toLowerCase();
457
+
458
+ if(column.definition.headerFilterLiveFilter !== false){
459
+
460
+ if (
461
+ !(
462
+ column.definition.headerFilter === 'autocomplete' ||
463
+ column.definition.headerFilter === 'tickCross' ||
464
+ ((column.definition.editor === 'autocomplete' ||
465
+ column.definition.editor === 'tickCross') &&
466
+ column.definition.headerFilter === true)
467
+ )
468
+ ) {
469
+ editorElement.addEventListener("keyup", searchTrigger);
470
+ editorElement.addEventListener("search", searchTrigger);
471
+
472
+
473
+ //update number filtered columns on change
474
+ if(column.modules.filter.attrType == "number"){
475
+ editorElement.addEventListener("change", function(e){
476
+ success(editorElement.value);
477
+ });
478
+ }
479
+
480
+ //change text inputs to search inputs to allow for clearing of field
481
+ if(column.modules.filter.attrType == "text" && this.table.browser !== "ie"){
482
+ editorElement.setAttribute("type", "search");
483
+ // editorElement.off("change blur"); //prevent blur from triggering filter and preventing selection click
484
+ }
485
+
486
+ }
487
+
488
+ //prevent input and select elements from propagating click to column sorters etc
489
+ if(column.modules.filter.tagType == "input" || column.modules.filter.tagType == "select" || column.modules.filter.tagType == "textarea"){
490
+ editorElement.addEventListener("mousedown",function(e){
491
+ e.stopPropagation();
492
+ });
493
+ }
494
+ }
495
+
496
+ filterElement.appendChild(editorElement);
497
+
498
+ column.contentElement.appendChild(filterElement);
499
+
500
+ if(!reinitialize){
501
+ self.headerFilterColumns.push(column);
502
+ }
503
+
504
+ if(onRenderedCallback){
505
+ onRenderedCallback();
506
+ }
507
+ }
508
+ }else{
509
+ console.warn("Filter Error - Cannot add header filter, column has no field set:", column.definition.title);
510
+ }
511
+ }
512
+
513
+ //hide all header filter elements (used to ensure correct column widths in "fitData" layout mode)
514
+ hideHeaderFilterElements(){
515
+ this.headerFilterColumns.forEach(function(column){
516
+ if(column.modules.filter && column.modules.filter.headerElement){
517
+ column.modules.filter.headerElement.style.display = 'none';
518
+ }
519
+ });
520
+ }
521
+
522
+ //show all header filter elements (used to ensure correct column widths in "fitData" layout mode)
523
+ showHeaderFilterElements(){
524
+ this.headerFilterColumns.forEach(function(column){
525
+ if(column.modules.filter && column.modules.filter.headerElement){
526
+ column.modules.filter.headerElement.style.display = '';
527
+ }
528
+ });
529
+ }
530
+
531
+ //programmatically set focus of header filter
532
+ setHeaderFilterFocus(column){
533
+ if(column.modules.filter && column.modules.filter.headerElement){
534
+ column.modules.filter.headerElement.focus();
535
+ }else{
536
+ console.warn("Column Filter Focus Error - No header filter set on column:", column.getField());
537
+ }
538
+ }
539
+
540
+ //programmatically get value of header filter
541
+ getHeaderFilterValue(column){
542
+ if(column.modules.filter && column.modules.filter.headerElement){
543
+ return column.modules.filter.value;
544
+ } else {
545
+ console.warn("Column Filter Error - No header filter set on column:", column.getField());
546
+ }
547
+ }
548
+
549
+ //programmatically set value of header filter
550
+ setHeaderFilterValue(column, value){
551
+ if (column){
552
+ if(column.modules.filter && column.modules.filter.headerElement){
553
+ this.generateHeaderFilterElement(column, value, true);
554
+ column.modules.filter.success(value);
555
+ }else{
556
+ console.warn("Column Filter Error - No header filter set on column:", column.getField());
557
+ }
558
+ }
559
+ }
560
+
561
+ reloadHeaderFilter(column){
562
+ if (column){
563
+ if(column.modules.filter && column.modules.filter.headerElement){
564
+ this.generateHeaderFilterElement(column, column.modules.filter.value, true);
565
+ }else{
566
+ console.warn("Column Filter Error - No header filter set on column:", column.getField());
567
+ }
568
+ }
569
+ }
570
+
571
+ refreshFilter(){
572
+ if(this.tableInitialized){
573
+ if(this.table.options.filterMode === "remote"){
574
+ this.reloadData(null, false, false);
575
+ }else{
576
+ this.refreshData(true);
577
+ }
578
+ }
579
+
580
+ //TODO - Persist left position of row manager
581
+ // left = this.scrollLeft;
582
+ // this.scrollHorizontal(left);
583
+ }
584
+
585
+ //check if the filters has changed since last use
586
+ trackChanges(){
587
+ this.changed = true;
588
+ this.dispatch("filter-changed");
589
+ }
590
+
591
+ //check if the filters has changed since last use
592
+ hasChanged(){
593
+ var changed = this.changed;
594
+ this.changed = false;
595
+ return changed;
596
+ }
597
+
598
+ //set standard filters
599
+ setFilter(field, type, value, params){
600
+ this.filterList = [];
601
+
602
+ if(!Array.isArray(field)){
603
+ field = [{field:field, type:type, value:value, params:params}];
604
+ }
605
+
606
+ this.addFilter(field);
607
+ }
608
+
609
+ //add filter to array
610
+ addFilter(field, type, value, params){
611
+ var changed = false;
612
+
613
+ if(!Array.isArray(field)){
614
+ field = [{field:field, type:type, value:value, params:params}];
615
+ }
616
+
617
+ field.forEach((filter) => {
618
+ filter = this.findFilter(filter);
619
+
620
+ if(filter){
621
+ this.filterList.push(filter);
622
+ changed = true;
623
+ }
624
+ });
625
+
626
+ if(changed){
627
+ this.trackChanges();
628
+ }
629
+ }
630
+
631
+ findFilter(filter){
632
+ var column;
633
+
634
+ if(Array.isArray(filter)){
635
+ return this.findSubFilters(filter);
636
+ }
637
+
638
+ var filterFunc = false;
639
+
640
+ if(typeof filter.field == "function"){
641
+ filterFunc = function(data){
642
+ return filter.field(data, filter.type || {});// pass params to custom filter function
643
+ };
644
+ }else{
645
+
646
+ if(Filter.filters[filter.type]){
647
+
648
+ column = this.table.columnManager.getColumnByField(filter.field);
649
+
650
+ if(column){
651
+ filterFunc = function(data){
652
+ return Filter.filters[filter.type](filter.value, column.getFieldValue(data), data, filter.params || {});
653
+ };
654
+ }else{
655
+ filterFunc = function(data){
656
+ return Filter.filters[filter.type](filter.value, data[filter.field], data, filter.params || {});
657
+ };
658
+ }
659
+
660
+
661
+ }else{
662
+ console.warn("Filter Error - No such filter type found, ignoring: ", filter.type);
663
+ }
664
+ }
665
+
666
+ filter.func = filterFunc;
667
+
668
+ return filter.func ? filter : false;
669
+ }
670
+
671
+ findSubFilters(filters){
672
+ var output = [];
673
+
674
+ filters.forEach((filter) => {
675
+ filter = this.findFilter(filter);
676
+
677
+ if(filter){
678
+ output.push(filter);
679
+ }
680
+ });
681
+
682
+ return output.length ? output : false;
683
+ }
684
+
685
+ //get all filters
686
+ getFilters(all, ajax){
687
+ var output = [];
688
+
689
+ if(all){
690
+ output = this.getHeaderFilters();
691
+ }
692
+
693
+ if(ajax){
694
+ output.forEach(function(item){
695
+ if(typeof item.type == "function"){
696
+ item.type = "function";
697
+ }
698
+ });
699
+ }
700
+
701
+ output = output.concat(this.filtersToArray(this.filterList, ajax));
702
+
703
+ return output;
704
+ }
705
+
706
+ //filter to Object
707
+ filtersToArray(filterList, ajax){
708
+ var output = [];
709
+
710
+ filterList.forEach((filter) => {
711
+ var item;
712
+
713
+ if(Array.isArray(filter)){
714
+ output.push(this.filtersToArray(filter, ajax));
715
+ }else{
716
+ item = {field:filter.field, type:filter.type, value:filter.value};
717
+
718
+ if(ajax){
719
+ if(typeof item.type == "function"){
720
+ item.type = "function";
721
+ }
722
+ }
723
+
724
+ output.push(item);
725
+ }
726
+ });
727
+
728
+ return output;
729
+ }
730
+
731
+ //get all filters
732
+ getHeaderFilters(){
733
+ var output = [];
734
+
735
+ for(var key in this.headerFilters){
736
+ output.push({field:key, type:this.headerFilters[key].type, value:this.headerFilters[key].value});
737
+ }
738
+
739
+ return output;
740
+ }
741
+
742
+ //remove filter from array
743
+ removeFilter(field, type, value){
744
+ if(!Array.isArray(field)){
745
+ field = [{field:field, type:type, value:value}];
746
+ }
747
+
748
+ field.forEach((filter) => {
749
+ var index = -1;
750
+
751
+ if(typeof filter.field == "object"){
752
+ index = this.filterList.findIndex((element) => {
753
+ return filter === element;
754
+ });
755
+ }else{
756
+ index = this.filterList.findIndex((element) => {
757
+ return filter.field === element.field && filter.type === element.type && filter.value === element.value;
758
+ });
759
+ }
760
+
761
+ if(index > -1){
762
+ this.filterList.splice(index, 1);
763
+ }else{
764
+ console.warn("Filter Error - No matching filter type found, ignoring: ", filter.type);
765
+ }
766
+ });
767
+
768
+ this.trackChanges();
769
+ }
770
+
771
+ //clear filters
772
+ clearFilter(all){
773
+ this.filterList = [];
774
+
775
+ if(all){
776
+ this.clearHeaderFilter();
777
+ }
778
+
779
+ this.trackChanges();
780
+ }
781
+
782
+ //clear header filters
783
+ clearHeaderFilter(){
784
+ this.headerFilters = {};
785
+ this.prevHeaderFilterChangeCheck = "{}";
786
+
787
+ this.headerFilterColumns.forEach((column) => {
788
+ if(typeof column.modules.filter.value !== "undefined"){
789
+ delete column.modules.filter.value;
790
+ }
791
+ column.modules.filter.prevSuccess = undefined;
792
+ this.reloadHeaderFilter(column);
793
+ });
794
+
795
+ this.trackChanges();
796
+ }
797
+
798
+ //search data and return matching rows
799
+ search (searchType, field, type, value){
800
+ var activeRows = [],
801
+ filterList = [];
802
+
803
+ if(!Array.isArray(field)){
804
+ field = [{field:field, type:type, value:value}];
805
+ }
806
+
807
+ field.forEach((filter) => {
808
+ filter = this.findFilter(filter);
809
+
810
+ if(filter){
811
+ filterList.push(filter);
812
+ }
813
+ });
814
+
815
+ this.table.rowManager.rows.forEach((row) => {
816
+ var match = true;
817
+
818
+ filterList.forEach((filter) => {
819
+ if(!this.filterRecurse(filter, row.getData())){
820
+ match = false;
821
+ }
822
+ });
823
+
824
+ if(match){
825
+ activeRows.push(searchType === "data" ? row.getData("data") : row.getComponent());
826
+ }
827
+
828
+ });
829
+
830
+ return activeRows;
831
+ }
832
+
833
+ //filter row array
834
+ filter(rowList, filters){
835
+ var activeRows = [],
836
+ activeRowComponents = [];
837
+
838
+ if(this.subscribedExternal("dataFiltering")){
839
+ this.dispatchExternal("dataFiltering", this.getFilters(true));
840
+ }
841
+
842
+ if(this.table.options.filterMode !== "remote" && (this.filterList.length || Object.keys(this.headerFilters).length)){
843
+
844
+ rowList.forEach((row) => {
845
+ if(this.filterRow(row)){
846
+ activeRows.push(row);
847
+ }
848
+ });
849
+
850
+ }else{
851
+ activeRows = rowList.slice(0);
852
+ }
853
+
854
+ if(this.subscribedExternal("dataFiltered")){
855
+
856
+ activeRows.forEach((row) => {
857
+ activeRowComponents.push(row.getComponent());
858
+ });
859
+
860
+ this.dispatchExternal("dataFiltered", this.getFilters(true), activeRowComponents);
861
+ }
862
+
863
+ return activeRows;
864
+ }
865
+
866
+ //filter individual row
867
+ filterRow(row, filters){
868
+ var match = true,
869
+ data = row.getData();
870
+
871
+ this.filterList.forEach((filter) => {
872
+ if(!this.filterRecurse(filter, data)){
873
+ match = false;
874
+ }
875
+ });
876
+
877
+
878
+ for(var field in this.headerFilters){
879
+ if(!this.headerFilters[field].func(data)){
880
+ match = false;
881
+ }
882
+ }
883
+
884
+ return match;
885
+ }
886
+
887
+ filterRecurse(filter, data){
888
+ var match = false;
889
+
890
+ if(Array.isArray(filter)){
891
+ filter.forEach((subFilter) => {
892
+ if(this.filterRecurse(subFilter, data)){
893
+ match = true;
894
+ }
895
+ });
896
+ }else{
897
+ match = filter.func(data);
898
+ }
899
+
900
+ return match;
901
+ }
902
+ }