tabulator-tables 5.4.3 → 5.4.4

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 (253) hide show
  1. package/.babelrc.json +3 -3
  2. package/.editorconfig +6 -6
  3. package/.eslintignore +3 -3
  4. package/.eslintrc.js +28 -28
  5. package/.github/ISSUE_TEMPLATE/bug_report.md +58 -58
  6. package/.github/ISSUE_TEMPLATE/documentation.md +14 -14
  7. package/.github/ISSUE_TEMPLATE/feature_request.md +24 -24
  8. package/.github/ISSUE_TEMPLATE/question.md +12 -12
  9. package/.github/workflows/bad-files-check.yml +39 -39
  10. package/.github/workflows/lint-and-test.yml +30 -30
  11. package/CODE_OF_CONDUCT.md +46 -46
  12. package/CONTRIBUTING.md +22 -22
  13. package/LICENSE +20 -20
  14. package/README.md +76 -76
  15. package/bower.json +40 -40
  16. package/build/Bundler.js +185 -185
  17. package/build/rollup.js +6 -6
  18. package/dist/css/tabulator.css +0 -5
  19. package/dist/css/tabulator.css.map +1 -1
  20. package/dist/css/tabulator.min.css +1 -1
  21. package/dist/css/tabulator.min.css.map +1 -1
  22. package/dist/css/tabulator_bootstrap3.css +0 -5
  23. package/dist/css/tabulator_bootstrap3.css.map +1 -1
  24. package/dist/css/tabulator_bootstrap3.min.css +1 -1
  25. package/dist/css/tabulator_bootstrap3.min.css.map +1 -1
  26. package/dist/css/tabulator_bootstrap4.css +0 -5
  27. package/dist/css/tabulator_bootstrap4.css.map +1 -1
  28. package/dist/css/tabulator_bootstrap4.min.css +1 -1
  29. package/dist/css/tabulator_bootstrap4.min.css.map +1 -1
  30. package/dist/css/tabulator_bootstrap5.css +0 -5
  31. package/dist/css/tabulator_bootstrap5.css.map +1 -1
  32. package/dist/css/tabulator_bootstrap5.min.css +1 -1
  33. package/dist/css/tabulator_bootstrap5.min.css.map +1 -1
  34. package/dist/css/tabulator_bulma.css +0 -5
  35. package/dist/css/tabulator_bulma.css.map +1 -1
  36. package/dist/css/tabulator_bulma.min.css +1 -1
  37. package/dist/css/tabulator_bulma.min.css.map +1 -1
  38. package/dist/css/tabulator_materialize.css +0 -5
  39. package/dist/css/tabulator_materialize.css.map +1 -1
  40. package/dist/css/tabulator_materialize.min.css +1 -1
  41. package/dist/css/tabulator_materialize.min.css.map +1 -1
  42. package/dist/css/tabulator_midnight.css +0 -5
  43. package/dist/css/tabulator_midnight.css.map +1 -1
  44. package/dist/css/tabulator_midnight.min.css +1 -1
  45. package/dist/css/tabulator_midnight.min.css.map +1 -1
  46. package/dist/css/tabulator_modern.css +0 -5
  47. package/dist/css/tabulator_modern.css.map +1 -1
  48. package/dist/css/tabulator_modern.min.css +1 -1
  49. package/dist/css/tabulator_modern.min.css.map +1 -1
  50. package/dist/css/tabulator_semanticui.css +102 -107
  51. package/dist/css/tabulator_semanticui.css.map +1 -1
  52. package/dist/css/tabulator_semanticui.min.css +1 -1
  53. package/dist/css/tabulator_semanticui.min.css.map +1 -1
  54. package/dist/css/tabulator_simple.css +0 -5
  55. package/dist/css/tabulator_simple.css.map +1 -1
  56. package/dist/css/tabulator_simple.min.css +1 -1
  57. package/dist/css/tabulator_simple.min.css.map +1 -1
  58. package/dist/css/tabulator_site.css +0 -5
  59. package/dist/css/tabulator_site.css.map +1 -1
  60. package/dist/css/tabulator_site.min.css +1 -1
  61. package/dist/css/tabulator_site.min.css.map +1 -1
  62. package/dist/js/jquery_wrapper.js +55 -55
  63. package/dist/js/tabulator.js +25847 -25711
  64. package/dist/js/tabulator.js.map +1 -1
  65. package/dist/js/tabulator.min.js +2 -2
  66. package/dist/js/tabulator.min.js.map +1 -1
  67. package/dist/js/tabulator_esm.js +25926 -25790
  68. package/dist/js/tabulator_esm.js.map +1 -1
  69. package/dist/js/tabulator_esm.min.js +2 -2
  70. package/dist/js/tabulator_esm.min.js.map +1 -1
  71. package/package.json +65 -65
  72. package/src/js/builds/esm.js +14 -14
  73. package/src/js/builds/jquery_wrapper.js +55 -55
  74. package/src/js/core/ColumnManager.js +730 -730
  75. package/src/js/core/CoreFeature.js +138 -138
  76. package/src/js/core/FooterManager.js +101 -101
  77. package/src/js/core/Module.js +141 -141
  78. package/src/js/core/RowManager.js +1112 -1101
  79. package/src/js/core/Tabulator.js +895 -892
  80. package/src/js/core/TabulatorFull.js +10 -10
  81. package/src/js/core/cell/Cell.js +295 -295
  82. package/src/js/core/cell/CellComponent.js +76 -76
  83. package/src/js/core/column/Column.js +949 -949
  84. package/src/js/core/column/ColumnComponent.js +152 -152
  85. package/src/js/core/column/defaults/options.js +17 -17
  86. package/src/js/core/defaults/options.js +65 -65
  87. package/src/js/core/modules/core.js +2 -2
  88. package/src/js/core/modules/optional.js +34 -34
  89. package/src/js/core/rendering/Renderer.js +203 -203
  90. package/src/js/core/rendering/renderers/BasicHorizontal.js +19 -19
  91. package/src/js/core/rendering/renderers/BasicVertical.js +79 -78
  92. package/src/js/core/rendering/renderers/VirtualDomHorizontal.js +577 -577
  93. package/src/js/core/rendering/renderers/VirtualDomVertical.js +579 -579
  94. package/src/js/core/row/PseudoRow.js +44 -44
  95. package/src/js/core/row/Row.js +457 -457
  96. package/src/js/core/row/RowComponent.js +93 -93
  97. package/src/js/core/tools/Alert.js +61 -61
  98. package/src/js/core/tools/ComponentFunctionBinder.js +32 -32
  99. package/src/js/core/tools/DataLoader.js +119 -119
  100. package/src/js/core/tools/DeprecationAdvisor.js +46 -46
  101. package/src/js/core/tools/ExternalEventBus.js +104 -104
  102. package/src/js/core/tools/Helpers.js +46 -46
  103. package/src/js/core/tools/InteractionMonitor.js +321 -321
  104. package/src/js/core/tools/InternalEventBus.js +161 -161
  105. package/src/js/core/tools/ModuleBinder.js +104 -104
  106. package/src/js/core/tools/OptionsList.js +44 -40
  107. package/src/js/core/tools/Popup.js +304 -304
  108. package/src/js/core/tools/TableRegistry.js +61 -61
  109. package/src/js/modules/Accessor/Accessor.js +115 -115
  110. package/src/js/modules/Ajax/Ajax.js +143 -143
  111. package/src/js/modules/Ajax/defaults/config.js +2 -2
  112. package/src/js/modules/Ajax/defaults/contentTypeFormatters.js +44 -44
  113. package/src/js/modules/Ajax/defaults/loaderPromise.js +86 -86
  114. package/src/js/modules/Ajax/defaults/urlGenerator.js +43 -43
  115. package/src/js/modules/Clipboard/Clipboard.js +279 -279
  116. package/src/js/modules/Clipboard/defaults/pasteActions.js +10 -10
  117. package/src/js/modules/Clipboard/defaults/pasteParsers.js +74 -74
  118. package/src/js/modules/ColumnCalcs/CalcComponent.js +47 -47
  119. package/src/js/modules/ColumnCalcs/ColumnCalcs.js +581 -568
  120. package/src/js/modules/ColumnCalcs/defaults/calculations.js +85 -85
  121. package/src/js/modules/Comms/Comms.js +51 -51
  122. package/src/js/modules/DataTree/DataTree.js +603 -603
  123. package/src/js/modules/Download/Download.js +148 -148
  124. package/src/js/modules/Download/defaults/downloaders/csv.js +61 -61
  125. package/src/js/modules/Download/defaults/downloaders/html.js +4 -4
  126. package/src/js/modules/Download/defaults/downloaders/json.js +33 -33
  127. package/src/js/modules/Download/defaults/downloaders/jsonLines.js +31 -31
  128. package/src/js/modules/Download/defaults/downloaders/pdf.js +111 -111
  129. package/src/js/modules/Download/defaults/downloaders/xlsx.js +98 -98
  130. package/src/js/modules/Download/defaults/downloaders.js +14 -14
  131. package/src/js/modules/Edit/Edit.js +735 -736
  132. package/src/js/modules/Edit/List.js +1037 -1033
  133. package/src/js/modules/Edit/defaults/editors/autocomplete.js +11 -11
  134. package/src/js/modules/Edit/defaults/editors/date.js +138 -110
  135. package/src/js/modules/Edit/defaults/editors/datetime.js +125 -97
  136. package/src/js/modules/Edit/defaults/editors/input.js +76 -74
  137. package/src/js/modules/Edit/defaults/editors/list.js +6 -6
  138. package/src/js/modules/Edit/defaults/editors/number.js +109 -107
  139. package/src/js/modules/Edit/defaults/editors/progress.js +126 -126
  140. package/src/js/modules/Edit/defaults/editors/range.js +80 -78
  141. package/src/js/modules/Edit/defaults/editors/select.js +9 -9
  142. package/src/js/modules/Edit/defaults/editors/star.js +145 -145
  143. package/src/js/modules/Edit/defaults/editors/textarea.js +122 -120
  144. package/src/js/modules/Edit/defaults/editors/tickCross.js +94 -96
  145. package/src/js/modules/Edit/defaults/editors/time.js +126 -98
  146. package/src/js/modules/Edit/defaults/editors.js +28 -28
  147. package/src/js/modules/Edit/inputMask.js +73 -73
  148. package/src/js/modules/Export/Export.js +623 -623
  149. package/src/js/modules/Export/ExportColumn.js +10 -10
  150. package/src/js/modules/Export/ExportRow.js +9 -9
  151. package/src/js/modules/Filter/Filter.js +892 -892
  152. package/src/js/modules/Filter/defaults/filters.js +107 -107
  153. package/src/js/modules/Format/Format.js +212 -212
  154. package/src/js/modules/Format/defaults/formatters/buttonCross.js +2 -2
  155. package/src/js/modules/Format/defaults/formatters/buttonTick.js +2 -2
  156. package/src/js/modules/Format/defaults/formatters/color.js +3 -3
  157. package/src/js/modules/Format/defaults/formatters/datetime.js +36 -36
  158. package/src/js/modules/Format/defaults/formatters/datetimediff.js +40 -40
  159. package/src/js/modules/Format/defaults/formatters/handle.js +3 -3
  160. package/src/js/modules/Format/defaults/formatters/html.js +2 -2
  161. package/src/js/modules/Format/defaults/formatters/image.js +39 -39
  162. package/src/js/modules/Format/defaults/formatters/link.js +77 -77
  163. package/src/js/modules/Format/defaults/formatters/lookup.js +9 -9
  164. package/src/js/modules/Format/defaults/formatters/money.js +36 -36
  165. package/src/js/modules/Format/defaults/formatters/plaintext.js +2 -2
  166. package/src/js/modules/Format/defaults/formatters/progress.js +132 -132
  167. package/src/js/modules/Format/defaults/formatters/responsiveCollapse.js +43 -43
  168. package/src/js/modules/Format/defaults/formatters/rowSelection.js +59 -59
  169. package/src/js/modules/Format/defaults/formatters/rownum.js +9 -9
  170. package/src/js/modules/Format/defaults/formatters/star.js +37 -37
  171. package/src/js/modules/Format/defaults/formatters/textarea.js +3 -3
  172. package/src/js/modules/Format/defaults/formatters/tickCross.js +21 -21
  173. package/src/js/modules/Format/defaults/formatters/traffic.js +46 -46
  174. package/src/js/modules/Format/defaults/formatters.js +42 -42
  175. package/src/js/modules/FrozenColumns/FrozenColumns.js +299 -299
  176. package/src/js/modules/FrozenRows/FrozenRows.js +169 -159
  177. package/src/js/modules/GroupRows/Group.js +597 -598
  178. package/src/js/modules/GroupRows/GroupComponent.js +66 -66
  179. package/src/js/modules/GroupRows/GroupRows.js +639 -639
  180. package/src/js/modules/History/History.js +171 -171
  181. package/src/js/modules/History/defaults/redoers.js +24 -24
  182. package/src/js/modules/History/defaults/undoers.js +24 -24
  183. package/src/js/modules/HtmlTableImport/HtmlTableImport.js +181 -181
  184. package/src/js/modules/Import/Import.js +193 -193
  185. package/src/js/modules/Import/defaults/importers/array.js +4 -4
  186. package/src/js/modules/Import/defaults/importers/csv.js +62 -62
  187. package/src/js/modules/Import/defaults/importers/json.js +7 -7
  188. package/src/js/modules/Import/defaults/importers.js +8 -8
  189. package/src/js/modules/Interaction/Interaction.js +325 -325
  190. package/src/js/modules/Keybindings/Keybindings.js +172 -172
  191. package/src/js/modules/Keybindings/defaults/actions.js +118 -118
  192. package/src/js/modules/Keybindings/defaults/bindings.js +12 -12
  193. package/src/js/modules/Layout/Layout.js +49 -49
  194. package/src/js/modules/Layout/defaults/modes/fitColumns.js +171 -171
  195. package/src/js/modules/Layout/defaults/modes/fitData.js +9 -9
  196. package/src/js/modules/Layout/defaults/modes/fitDataGeneral.js +9 -9
  197. package/src/js/modules/Layout/defaults/modes/fitDataStretch.js +39 -39
  198. package/src/js/modules/Layout/defaults/modes.js +11 -11
  199. package/src/js/modules/Localize/Localize.js +185 -185
  200. package/src/js/modules/Localize/defaults/langs.js +36 -36
  201. package/src/js/modules/Menu/Menu.js +302 -302
  202. package/src/js/modules/MoveColumns/MoveColumns.js +299 -299
  203. package/src/js/modules/MoveRows/MoveRows.js +635 -635
  204. package/src/js/modules/Mutator/Mutator.js +161 -161
  205. package/src/js/modules/Page/Page.js +881 -881
  206. package/src/js/modules/Page/defaults/pageCounters/pages.js +32 -32
  207. package/src/js/modules/Page/defaults/pageCounters/rows.js +39 -39
  208. package/src/js/modules/Page/defaults/pageCounters.js +7 -7
  209. package/src/js/modules/Persistence/Persistence.js +458 -458
  210. package/src/js/modules/Persistence/defaults/readers.js +29 -29
  211. package/src/js/modules/Persistence/defaults/writers.js +12 -12
  212. package/src/js/modules/Popup/Popup.js +231 -231
  213. package/src/js/modules/Print/Print.js +137 -137
  214. package/src/js/modules/ReactiveData/ReactiveData.js +408 -408
  215. package/src/js/modules/ResizeColumns/ResizeColumns.js +309 -309
  216. package/src/js/modules/ResizeRows/ResizeRows.js +111 -111
  217. package/src/js/modules/ResizeTable/ResizeTable.js +159 -159
  218. package/src/js/modules/ResponsiveLayout/ResponsiveLayout.js +345 -345
  219. package/src/js/modules/SelectRow/SelectRow.js +446 -444
  220. package/src/js/modules/Sort/Sort.js +470 -470
  221. package/src/js/modules/Sort/defaults/sorters/alphanum.js +43 -43
  222. package/src/js/modules/Sort/defaults/sorters/array.js +53 -53
  223. package/src/js/modules/Sort/defaults/sorters/boolean.js +6 -6
  224. package/src/js/modules/Sort/defaults/sorters/date.js +9 -9
  225. package/src/js/modules/Sort/defaults/sorters/datetime.js +43 -43
  226. package/src/js/modules/Sort/defaults/sorters/exists.js +6 -6
  227. package/src/js/modules/Sort/defaults/sorters/number.js +39 -39
  228. package/src/js/modules/Sort/defaults/sorters/string.js +33 -33
  229. package/src/js/modules/Sort/defaults/sorters/time.js +9 -9
  230. package/src/js/modules/Sort/defaults/sorters.js +20 -20
  231. package/src/js/modules/Tooltip/Tooltip.js +130 -130
  232. package/src/js/modules/Validate/Validate.js +305 -305
  233. package/src/js/modules/Validate/defaults/validators.js +138 -138
  234. package/src/scss/tabulator.scss +1464 -1467
  235. package/src/scss/themes/bootstrap/functions4.scss +118 -118
  236. package/src/scss/themes/bootstrap/functions5.scss +302 -302
  237. package/src/scss/themes/bootstrap/tabulator_bootstrap3.scss +284 -284
  238. package/src/scss/themes/bootstrap/tabulator_bootstrap4.scss +544 -544
  239. package/src/scss/themes/bootstrap/tabulator_bootstrap5.scss +574 -574
  240. package/src/scss/themes/bootstrap/variables3.scss +870 -870
  241. package/src/scss/themes/bootstrap/variables4.scss +930 -930
  242. package/src/scss/themes/bootstrap/variables5.scss +1641 -1641
  243. package/src/scss/themes/bulma/tabulator_bulma.scss +252 -252
  244. package/src/scss/themes/bulma/variables.scss +197 -197
  245. package/src/scss/themes/materialize/tabulator_materialize.scss +265 -265
  246. package/src/scss/themes/materialize/variables.scss +70 -70
  247. package/src/scss/themes/semanticui/tabulator_semanticui.scss +561 -561
  248. package/src/scss/themes/semanticui/variables.scss +839 -839
  249. package/src/scss/themes/semanticui/variables_table.scss +247 -247
  250. package/src/scss/themes/tabulator_midnight.scss +158 -158
  251. package/src/scss/themes/tabulator_modern.scss +231 -231
  252. package/src/scss/themes/tabulator_simple.scss +102 -102
  253. package/src/scss/themes/tabulator_site.scss +189 -189
@@ -1,736 +1,735 @@
1
- import Module from '../../core/Module.js';
2
- import Helpers from '../../core/tools/Helpers.js';
3
-
4
- import defaultEditors from './defaults/editors.js';
5
-
6
- class Edit extends Module{
7
-
8
- constructor(table){
9
- super(table);
10
-
11
- this.currentCell = false; //hold currently editing cell
12
- this.mouseClick = false; //hold mousedown state to prevent click binding being overridden by editor opening
13
- this.recursionBlock = false; //prevent focus recursion
14
- this.invalidEdit = false;
15
- this.editedCells = [];
16
-
17
- this.editors = Edit.editors;
18
-
19
- this.registerColumnOption("editable");
20
- this.registerColumnOption("editor");
21
- this.registerColumnOption("editorParams");
22
-
23
- this.registerColumnOption("cellEditing");
24
- this.registerColumnOption("cellEdited");
25
- this.registerColumnOption("cellEditCancelled");
26
-
27
- this.registerTableFunction("getEditedCells", this.getEditedCells.bind(this));
28
- this.registerTableFunction("clearCellEdited", this.clearCellEdited.bind(this));
29
- this.registerTableFunction("navigatePrev", this.navigatePrev.bind(this));
30
- this.registerTableFunction("navigateNext", this.navigateNext.bind(this));
31
- this.registerTableFunction("navigateLeft", this.navigateLeft.bind(this));
32
- this.registerTableFunction("navigateRight", this.navigateRight.bind(this));
33
- this.registerTableFunction("navigateUp", this.navigateUp.bind(this));
34
- this.registerTableFunction("navigateDown", this.navigateDown.bind(this));
35
-
36
- this.registerComponentFunction("cell", "isEdited", this.cellIsEdited.bind(this));
37
- this.registerComponentFunction("cell", "clearEdited", this.clearEdited.bind(this));
38
- this.registerComponentFunction("cell", "edit", this.editCell.bind(this));
39
- this.registerComponentFunction("cell", "cancelEdit", this.cellCancelEdit.bind(this));
40
-
41
- this.registerComponentFunction("cell", "navigatePrev", this.navigatePrev.bind(this));
42
- this.registerComponentFunction("cell", "navigateNext", this.navigateNext.bind(this));
43
- this.registerComponentFunction("cell", "navigateLeft", this.navigateLeft.bind(this));
44
- this.registerComponentFunction("cell", "navigateRight", this.navigateRight.bind(this));
45
- this.registerComponentFunction("cell", "navigateUp", this.navigateUp.bind(this));
46
- this.registerComponentFunction("cell", "navigateDown", this.navigateDown.bind(this));
47
- }
48
-
49
- initialize(){
50
- this.subscribe("cell-init", this.bindEditor.bind(this));
51
- this.subscribe("cell-delete", this.clearEdited.bind(this));
52
- this.subscribe("cell-value-changed", this.updateCellClass.bind(this));
53
- this.subscribe("column-layout", this.initializeColumnCheck.bind(this));
54
- this.subscribe("column-delete", this.columnDeleteCheck.bind(this));
55
- this.subscribe("row-deleting", this.rowDeleteCheck.bind(this));
56
- this.subscribe("row-layout", this.rowEditableCheck.bind(this));
57
- this.subscribe("data-refreshing", this.cancelEdit.bind(this));
58
-
59
- this.subscribe("keybinding-nav-prev", this.navigatePrev.bind(this, undefined));
60
- this.subscribe("keybinding-nav-next", this.keybindingNavigateNext.bind(this));
61
- this.subscribe("keybinding-nav-left", this.navigateLeft.bind(this, undefined));
62
- this.subscribe("keybinding-nav-right", this.navigateRight.bind(this, undefined));
63
- this.subscribe("keybinding-nav-up", this.navigateUp.bind(this, undefined));
64
- this.subscribe("keybinding-nav-down", this.navigateDown.bind(this, undefined));
65
- }
66
-
67
-
68
- ///////////////////////////////////
69
- ////// Keybinding Functions ///////
70
- ///////////////////////////////////
71
-
72
- keybindingNavigateNext(e){
73
- var cell = this.currentCell,
74
- newRow = this.options("tabEndNewRow");
75
-
76
- if(cell){
77
- if(!this.navigateNext(cell, e)){
78
- if(newRow){
79
- cell.getElement().firstChild.blur();
80
-
81
- if(newRow === true){
82
- newRow = this.table.addRow({});
83
- }else{
84
- if(typeof newRow == "function"){
85
- newRow = this.table.addRow(newRow(cell.row.getComponent()));
86
- }else{
87
- newRow = this.table.addRow(Object.assign({}, newRow));
88
- }
89
- }
90
-
91
- newRow.then(() => {
92
- setTimeout(() => {
93
- cell.getComponent().navigateNext();
94
- });
95
- });
96
- }
97
- }
98
- }
99
- }
100
-
101
- ///////////////////////////////////
102
- ///////// Cell Functions //////////
103
- ///////////////////////////////////
104
-
105
- cellIsEdited(cell){
106
- return !! cell.modules.edit && cell.modules.edit.edited;
107
- }
108
-
109
- cellCancelEdit(cell){
110
- if(cell === this.currentCell){
111
- this.table.modules.edit.cancelEdit();
112
- }else{
113
- console.warn("Cancel Editor Error - This cell is not currently being edited ");
114
- }
115
- }
116
-
117
-
118
- ///////////////////////////////////
119
- ///////// Table Functions /////////
120
- ///////////////////////////////////
121
- updateCellClass(cell){
122
- if(this.allowEdit(cell)) {
123
- cell.getElement().classList.add("tabulator-editable");
124
- }
125
- else {
126
- cell.getElement().classList.remove("tabulator-editable");
127
- }
128
- }
129
-
130
- clearCellEdited(cells){
131
- if(!cells){
132
- cells = this.table.modules.edit.getEditedCells();
133
- }
134
-
135
- if(!Array.isArray(cells)){
136
- cells = [cells];
137
- }
138
-
139
- cells.forEach((cell) => {
140
- this.table.modules.edit.clearEdited(cell._getSelf());
141
- });
142
- }
143
-
144
- navigatePrev(cell = this.currentCell, e){
145
- var nextCell, prevRow;
146
-
147
- if(cell){
148
-
149
- if(e){
150
- e.preventDefault();
151
- }
152
-
153
- nextCell = this.navigateLeft();
154
-
155
- if(nextCell){
156
- return true;
157
- }else{
158
- prevRow = this.table.rowManager.prevDisplayRow(cell.row, true);
159
-
160
- if(prevRow){
161
- nextCell = this.findPrevEditableCell(prevRow, prevRow.cells.length);
162
-
163
- if(nextCell){
164
- nextCell.getComponent().edit();
165
- return true;
166
- }
167
- }
168
- }
169
- }
170
-
171
- return false;
172
- }
173
-
174
- navigateNext(cell = this.currentCell, e){
175
- var nextCell, nextRow;
176
-
177
- if(cell){
178
-
179
- if(e){
180
- e.preventDefault();
181
- }
182
-
183
- nextCell = this.navigateRight();
184
-
185
- if(nextCell){
186
- return true;
187
- }else{
188
- nextRow = this.table.rowManager.nextDisplayRow(cell.row, true);
189
-
190
- if(nextRow){
191
- nextCell = this.findNextEditableCell(nextRow, -1);
192
-
193
- if(nextCell){
194
- nextCell.getComponent().edit();
195
- return true;
196
- }
197
- }
198
- }
199
- }
200
-
201
- return false;
202
- }
203
-
204
- navigateLeft(cell = this.currentCell, e){
205
- var index, nextCell;
206
-
207
- if(cell){
208
-
209
- if(e){
210
- e.preventDefault();
211
- }
212
-
213
- index = cell.getIndex();
214
- nextCell = this.findPrevEditableCell(cell.row, index);
215
-
216
- if(nextCell){
217
- nextCell.getComponent().edit();
218
- return true;
219
- }
220
- }
221
-
222
- return false;
223
- }
224
-
225
- navigateRight(cell = this.currentCell, e){
226
- var index, nextCell;
227
-
228
- if(cell){
229
-
230
- if(e){
231
- e.preventDefault();
232
- }
233
-
234
- index = cell.getIndex();
235
- nextCell = this.findNextEditableCell(cell.row, index);
236
-
237
- if(nextCell){
238
- nextCell.getComponent().edit();
239
- return true;
240
- }
241
- }
242
-
243
- return false;
244
- }
245
-
246
- navigateUp(cell = this.currentCell, e){
247
- var index, nextRow;
248
-
249
- if(cell){
250
-
251
- if(e){
252
- e.preventDefault();
253
- }
254
-
255
- index = cell.getIndex();
256
- nextRow = this.table.rowManager.prevDisplayRow(cell.row, true);
257
-
258
- if(nextRow){
259
- nextRow.cells[index].getComponent().edit();
260
- return true;
261
- }
262
- }
263
-
264
- return false;
265
- }
266
-
267
- navigateDown(cell = this.currentCell, e){
268
- var index, nextRow;
269
-
270
- if(cell){
271
-
272
- if(e){
273
- e.preventDefault();
274
- }
275
-
276
- index = cell.getIndex();
277
- nextRow = this.table.rowManager.nextDisplayRow(cell.row, true);
278
-
279
- if(nextRow){
280
- nextRow.cells[index].getComponent().edit();
281
- return true;
282
- }
283
- }
284
-
285
- return false;
286
- }
287
-
288
- findNextEditableCell(row, index){
289
- var nextCell = false;
290
-
291
- if(index < row.cells.length-1){
292
- for(var i = index+1; i < row.cells.length; i++){
293
- let cell = row.cells[i];
294
-
295
- if(cell.column.modules.edit && Helpers.elVisible(cell.getElement())){
296
- let allowEdit = this.allowEdit(cell);
297
-
298
- if(allowEdit){
299
- nextCell = cell;
300
- break;
301
- }
302
- }
303
- }
304
- }
305
-
306
- return nextCell;
307
- }
308
-
309
- findPrevEditableCell(row, index){
310
- var prevCell = false;
311
-
312
- if(index > 0){
313
- for(var i = index-1; i >= 0; i--){
314
- let cell = row.cells[i];
315
-
316
- if(cell.column.modules.edit && Helpers.elVisible(cell.getElement())){
317
- let allowEdit = this.allowEdit(cell);
318
-
319
- if(allowEdit){
320
- prevCell = cell;
321
- break;
322
- }
323
- }
324
- }
325
- }
326
-
327
- return prevCell;
328
- }
329
-
330
- ///////////////////////////////////
331
- ///////// Internal Logic //////////
332
- ///////////////////////////////////
333
-
334
- initializeColumnCheck(column){
335
- if(typeof column.definition.editor !== "undefined"){
336
- this.initializeColumn(column);
337
- }
338
- }
339
-
340
- columnDeleteCheck(column){
341
- if(this.currentCell && this.currentCell.column === column){
342
- this.cancelEdit();
343
- }
344
- }
345
-
346
- rowDeleteCheck(row){
347
- if(this.currentCell && this.currentCell.row === row){
348
- this.cancelEdit();
349
- }
350
- }
351
-
352
- rowEditableCheck(row){
353
- row.getCells().forEach((cell) => {
354
- if(cell.column.modules.edit && typeof cell.column.modules.edit.check === "function"){
355
- this.updateCellClass(cell);
356
- }
357
- });
358
- }
359
-
360
- //initialize column editor
361
- initializeColumn(column){
362
- var config = {
363
- editor:false,
364
- blocked:false,
365
- check:column.definition.editable,
366
- params:column.definition.editorParams || {}
367
- };
368
-
369
- //set column editor
370
- switch(typeof column.definition.editor){
371
- case "string":
372
- if(this.editors[column.definition.editor]){
373
- config.editor = this.editors[column.definition.editor];
374
- }else{
375
- console.warn("Editor Error - No such editor found: ", column.definition.editor);
376
- }
377
- break;
378
-
379
- case "function":
380
- config.editor = column.definition.editor;
381
- break;
382
-
383
- case "boolean":
384
- if(column.definition.editor === true){
385
- if(typeof column.definition.formatter !== "function"){
386
- if(this.editors[column.definition.formatter]){
387
- config.editor = this.editors[column.definition.formatter];
388
- }else{
389
- config.editor = this.editors["input"];
390
- }
391
- }else{
392
- console.warn("Editor Error - Cannot auto lookup editor for a custom formatter: ", column.definition.formatter);
393
- }
394
- }
395
- break;
396
- }
397
-
398
- if(config.editor){
399
- column.modules.edit = config;
400
- }
401
- }
402
-
403
- getCurrentCell(){
404
- return this.currentCell ? this.currentCell.getComponent() : false;
405
- }
406
-
407
- clearEditor(cancel){
408
- var cell = this.currentCell,
409
- cellEl;
410
-
411
- this.invalidEdit = false;
412
-
413
- if(cell){
414
- this.currentCell = false;
415
-
416
- cellEl = cell.getElement();
417
-
418
- this.dispatch("edit-editor-clear", cell, cancel);
419
-
420
- cellEl.classList.remove("tabulator-editing");
421
-
422
- while(cellEl.firstChild) cellEl.removeChild(cellEl.firstChild);
423
-
424
- cell.row.getElement().classList.remove("tabulator-editing");
425
-
426
- cell.table.element.classList.remove("tabulator-editing");
427
- }
428
- }
429
-
430
- cancelEdit(){
431
- if(this.currentCell){
432
- var cell = this.currentCell;
433
- var component = this.currentCell.getComponent();
434
-
435
- this.clearEditor(true);
436
- cell.setValueActual(cell.getValue());
437
- cell.cellRendered();
438
-
439
- if(cell.column.definition.editor == "textarea" || cell.column.definition.variableHeight){
440
- cell.row.normalizeHeight(true);
441
- }
442
-
443
- if(cell.column.definition.cellEditCancelled){
444
- cell.column.definition.cellEditCancelled.call(this.table, component);
445
- }
446
-
447
- this.dispatch("edit-cancelled", cell);
448
- this.dispatchExternal("cellEditCancelled", component);
449
- }
450
- }
451
-
452
- //return a formatted value for a cell
453
- bindEditor(cell){
454
- if(cell.column.modules.edit){
455
- var self = this,
456
- element = cell.getElement(true);
457
-
458
- this.updateCellClass(cell);
459
- element.setAttribute("tabindex", 0);
460
-
461
- element.addEventListener("click", function(e){
462
- if(!element.classList.contains("tabulator-editing")){
463
- element.focus({preventScroll: true});
464
- }
465
- });
466
-
467
- element.addEventListener("mousedown", function(e){
468
- if (e.button === 2) {
469
- e.preventDefault();
470
- }else{
471
- self.mouseClick = true;
472
- }
473
- });
474
-
475
- element.addEventListener("focus", function(e){
476
- if(!self.recursionBlock){
477
- self.edit(cell, e, false);
478
- }
479
- });
480
- }
481
- }
482
-
483
- focusCellNoEvent(cell, block){
484
- this.recursionBlock = true;
485
-
486
- if(!(block && this.table.browser === "ie")){
487
- cell.getElement().focus({preventScroll: true});
488
- }
489
-
490
- this.recursionBlock = false;
491
- }
492
-
493
- editCell(cell, forceEdit){
494
- this.focusCellNoEvent(cell);
495
- this.edit(cell, false, forceEdit);
496
- }
497
-
498
- focusScrollAdjust(cell){
499
- if(this.table.rowManager.getRenderMode() == "virtual"){
500
- var topEdge = this.table.rowManager.element.scrollTop,
501
- bottomEdge = this.table.rowManager.element.clientHeight + this.table.rowManager.element.scrollTop,
502
- rowEl = cell.row.getElement();
503
-
504
- if(rowEl.offsetTop < topEdge){
505
- this.table.rowManager.element.scrollTop -= (topEdge - rowEl.offsetTop);
506
- }else{
507
- if(rowEl.offsetTop + rowEl.offsetHeight > bottomEdge){
508
- this.table.rowManager.element.scrollTop += (rowEl.offsetTop + rowEl.offsetHeight - bottomEdge);
509
- }
510
- }
511
-
512
- var leftEdge = this.table.rowManager.element.scrollLeft,
513
- rightEdge = this.table.rowManager.element.clientWidth + this.table.rowManager.element.scrollLeft,
514
- cellEl = cell.getElement();
515
-
516
- if(this.table.modExists("frozenColumns")){
517
- leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin);
518
- rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin);
519
- }
520
-
521
- if(this.table.options.renderHorizontal === "virtual"){
522
- leftEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft);
523
- rightEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft);
524
- }
525
-
526
- if(cellEl.offsetLeft < leftEdge){
527
-
528
- this.table.rowManager.element.scrollLeft -= (leftEdge - cellEl.offsetLeft);
529
- }else{
530
- if(cellEl.offsetLeft + cellEl.offsetWidth > rightEdge){
531
- this.table.rowManager.element.scrollLeft += (cellEl.offsetLeft + cellEl.offsetWidth - rightEdge);
532
- }
533
- }
534
- }
535
- }
536
-
537
- allowEdit(cell) {
538
- var check = cell.column.modules.edit ? true : false;
539
-
540
- if(cell.column.modules.edit){
541
- switch(typeof cell.column.modules.edit.check){
542
- case "function":
543
- if(cell.row.initialized){
544
- check = cell.column.modules.edit.check(cell.getComponent());
545
- }
546
- break;
547
-
548
- case "string":
549
- check = !!cell.row.data[cell.column.modules.edit.check];
550
- break;
551
-
552
- case "boolean":
553
- check = cell.column.modules.edit.check;
554
- break;
555
- }
556
- }
557
-
558
- return check;
559
- }
560
-
561
- edit(cell, e, forceEdit){
562
- var self = this,
563
- allowEdit = true,
564
- rendered = function(){},
565
- element = cell.getElement(),
566
- cellEditor, component, params;
567
-
568
- //prevent editing if another cell is refusing to leave focus (eg. validation fail)
569
- if(this.currentCell){
570
- if(!this.invalidEdit){
571
- this.cancelEdit();
572
- }
573
- return;
574
- }
575
-
576
- //handle successful value change
577
- function success(value){
578
- if(self.currentCell === cell){
579
- var valid = self.chain("edit-success", [cell, value], true, true);
580
-
581
- if(valid === true || self.table.options.validationMode === "highlight"){
582
- self.clearEditor();
583
-
584
-
585
- if(!cell.modules.edit){
586
- cell.modules.edit = {};
587
- }
588
-
589
- cell.modules.edit.edited = true;
590
-
591
- if(self.editedCells.indexOf(cell) == -1){
592
- self.editedCells.push(cell);
593
- }
594
-
595
- cell.setValue(value, true);
596
-
597
- return valid === true;
598
- }else{
599
- self.invalidEdit = true;
600
- self.focusCellNoEvent(cell, true);
601
- rendered();
602
- return false;
603
- }
604
- }else{
605
- // console.warn("Edit Success Error - cannot call success on a cell that is no longer being edited");
606
- }
607
- }
608
-
609
- //handle aborted edit
610
- function cancel(){
611
- if(self.currentCell === cell){
612
- self.cancelEdit();
613
- }else{
614
- // console.warn("Edit Success Error - cannot call cancel on a cell that is no longer being edited");
615
- }
616
- }
617
-
618
- function onRendered(callback){
619
- rendered = callback;
620
- }
621
-
622
- if(!cell.column.modules.edit.blocked){
623
- if(e){
624
- e.stopPropagation();
625
- }
626
-
627
- allowEdit = this.allowEdit(cell);
628
-
629
- if(allowEdit || forceEdit){
630
-
631
- self.cancelEdit();
632
-
633
- self.currentCell = cell;
634
-
635
- this.focusScrollAdjust(cell);
636
-
637
- component = cell.getComponent();
638
-
639
- if(this.mouseClick){
640
- this.mouseClick = false;
641
-
642
- if(cell.column.definition.cellClick){
643
- cell.column.definition.cellClick.call(this.table, e, component);
644
- }
645
- }
646
-
647
- if(cell.column.definition.cellEditing){
648
- cell.column.definition.cellEditing.call(this.table, component);
649
- }
650
-
651
- this.dispatch("cell-editing", cell);
652
- this.dispatchExternal("cellEditing", component);
653
-
654
- params = typeof cell.column.modules.edit.params === "function" ? cell.column.modules.edit.params(component) : cell.column.modules.edit.params;
655
-
656
- cellEditor = cell.column.modules.edit.editor.call(self, component, onRendered, success, cancel, params);
657
-
658
- //if editor returned, add to DOM, if false, abort edit
659
- if(cellEditor !== false){
660
-
661
- if(cellEditor instanceof Node){
662
- element.classList.add("tabulator-editing");
663
- cell.row.getElement().classList.add("tabulator-editing");
664
- cell.table.element.classList.add("tabulator-editing");
665
- while(element.firstChild) element.removeChild(element.firstChild);
666
- element.appendChild(cellEditor);
667
-
668
- //trigger onRendered Callback
669
- rendered();
670
-
671
- //prevent editing from triggering rowClick event
672
- var children = element.children;
673
-
674
- for (var i = 0; i < children.length; i++) {
675
- children[i].addEventListener("click", function(e){
676
- e.stopPropagation();
677
- });
678
- }
679
- }else{
680
- console.warn("Edit Error - Editor should return an instance of Node, the editor returned:", cellEditor);
681
- element.blur();
682
- return false;
683
- }
684
-
685
- }else{
686
- element.blur();
687
- return false;
688
- }
689
-
690
- return true;
691
- }else{
692
- this.mouseClick = false;
693
- element.blur();
694
- return false;
695
- }
696
- }else{
697
- this.mouseClick = false;
698
- element.blur();
699
- return false;
700
- }
701
- }
702
-
703
- getEditedCells(){
704
- var output = [];
705
-
706
- this.editedCells.forEach((cell) => {
707
- output.push(cell.getComponent());
708
- });
709
-
710
- return output;
711
- }
712
-
713
- clearEdited(cell){
714
- var editIndex;
715
-
716
- if(cell.modules.edit && cell.modules.edit.edited){
717
- cell.modules.edit.edited = false;
718
-
719
- this.dispatch("edit-edited-clear", cell);
720
- }
721
-
722
- editIndex = this.editedCells.indexOf(cell);
723
-
724
- if(editIndex > -1){
725
- this.editedCells.splice(editIndex, 1);
726
- }
727
- }
728
- }
729
-
730
- Edit.moduleName = "edit";
731
-
732
- //load defaults
733
- Edit.editors = defaultEditors;
734
-
735
-
736
- export default Edit;
1
+ import Module from '../../core/Module.js';
2
+ import Helpers from '../../core/tools/Helpers.js';
3
+
4
+ import defaultEditors from './defaults/editors.js';
5
+
6
+ class Edit extends Module{
7
+
8
+ constructor(table){
9
+ super(table);
10
+
11
+ this.currentCell = false; //hold currently editing cell
12
+ this.mouseClick = false; //hold mousedown state to prevent click binding being overridden by editor opening
13
+ this.recursionBlock = false; //prevent focus recursion
14
+ this.invalidEdit = false;
15
+ this.editedCells = [];
16
+
17
+ this.editors = Edit.editors;
18
+
19
+ this.registerColumnOption("editable");
20
+ this.registerColumnOption("editor");
21
+ this.registerColumnOption("editorParams");
22
+
23
+ this.registerColumnOption("cellEditing");
24
+ this.registerColumnOption("cellEdited");
25
+ this.registerColumnOption("cellEditCancelled");
26
+
27
+ this.registerTableFunction("getEditedCells", this.getEditedCells.bind(this));
28
+ this.registerTableFunction("clearCellEdited", this.clearCellEdited.bind(this));
29
+ this.registerTableFunction("navigatePrev", this.navigatePrev.bind(this));
30
+ this.registerTableFunction("navigateNext", this.navigateNext.bind(this));
31
+ this.registerTableFunction("navigateLeft", this.navigateLeft.bind(this));
32
+ this.registerTableFunction("navigateRight", this.navigateRight.bind(this));
33
+ this.registerTableFunction("navigateUp", this.navigateUp.bind(this));
34
+ this.registerTableFunction("navigateDown", this.navigateDown.bind(this));
35
+
36
+ this.registerComponentFunction("cell", "isEdited", this.cellIsEdited.bind(this));
37
+ this.registerComponentFunction("cell", "clearEdited", this.clearEdited.bind(this));
38
+ this.registerComponentFunction("cell", "edit", this.editCell.bind(this));
39
+ this.registerComponentFunction("cell", "cancelEdit", this.cellCancelEdit.bind(this));
40
+
41
+ this.registerComponentFunction("cell", "navigatePrev", this.navigatePrev.bind(this));
42
+ this.registerComponentFunction("cell", "navigateNext", this.navigateNext.bind(this));
43
+ this.registerComponentFunction("cell", "navigateLeft", this.navigateLeft.bind(this));
44
+ this.registerComponentFunction("cell", "navigateRight", this.navigateRight.bind(this));
45
+ this.registerComponentFunction("cell", "navigateUp", this.navigateUp.bind(this));
46
+ this.registerComponentFunction("cell", "navigateDown", this.navigateDown.bind(this));
47
+ }
48
+
49
+ initialize(){
50
+ this.subscribe("cell-init", this.bindEditor.bind(this));
51
+ this.subscribe("cell-delete", this.clearEdited.bind(this));
52
+ this.subscribe("cell-value-changed", this.updateCellClass.bind(this));
53
+ this.subscribe("column-layout", this.initializeColumnCheck.bind(this));
54
+ this.subscribe("column-delete", this.columnDeleteCheck.bind(this));
55
+ this.subscribe("row-deleting", this.rowDeleteCheck.bind(this));
56
+ this.subscribe("row-layout", this.rowEditableCheck.bind(this));
57
+ this.subscribe("data-refreshing", this.cancelEdit.bind(this));
58
+
59
+ this.subscribe("keybinding-nav-prev", this.navigatePrev.bind(this, undefined));
60
+ this.subscribe("keybinding-nav-next", this.keybindingNavigateNext.bind(this));
61
+ this.subscribe("keybinding-nav-left", this.navigateLeft.bind(this, undefined));
62
+ this.subscribe("keybinding-nav-right", this.navigateRight.bind(this, undefined));
63
+ this.subscribe("keybinding-nav-up", this.navigateUp.bind(this, undefined));
64
+ this.subscribe("keybinding-nav-down", this.navigateDown.bind(this, undefined));
65
+ }
66
+
67
+
68
+ ///////////////////////////////////
69
+ ////// Keybinding Functions ///////
70
+ ///////////////////////////////////
71
+
72
+ keybindingNavigateNext(e){
73
+ var cell = this.currentCell,
74
+ newRow = this.options("tabEndNewRow");
75
+
76
+ if(cell){
77
+ if(!this.navigateNext(cell, e)){
78
+ if(newRow){
79
+ cell.getElement().firstChild.blur();
80
+
81
+ if(newRow === true){
82
+ newRow = this.table.addRow({});
83
+ }else{
84
+ if(typeof newRow == "function"){
85
+ newRow = this.table.addRow(newRow(cell.row.getComponent()));
86
+ }else{
87
+ newRow = this.table.addRow(Object.assign({}, newRow));
88
+ }
89
+ }
90
+
91
+ newRow.then(() => {
92
+ setTimeout(() => {
93
+ cell.getComponent().navigateNext();
94
+ });
95
+ });
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ ///////////////////////////////////
102
+ ///////// Cell Functions //////////
103
+ ///////////////////////////////////
104
+
105
+ cellIsEdited(cell){
106
+ return !! cell.modules.edit && cell.modules.edit.edited;
107
+ }
108
+
109
+ cellCancelEdit(cell){
110
+ if(cell === this.currentCell){
111
+ this.table.modules.edit.cancelEdit();
112
+ }else{
113
+ console.warn("Cancel Editor Error - This cell is not currently being edited ");
114
+ }
115
+ }
116
+
117
+
118
+ ///////////////////////////////////
119
+ ///////// Table Functions /////////
120
+ ///////////////////////////////////
121
+ updateCellClass(cell){
122
+ if(this.allowEdit(cell)) {
123
+ cell.getElement().classList.add("tabulator-editable");
124
+ }
125
+ else {
126
+ cell.getElement().classList.remove("tabulator-editable");
127
+ }
128
+ }
129
+
130
+ clearCellEdited(cells){
131
+ if(!cells){
132
+ cells = this.table.modules.edit.getEditedCells();
133
+ }
134
+
135
+ if(!Array.isArray(cells)){
136
+ cells = [cells];
137
+ }
138
+
139
+ cells.forEach((cell) => {
140
+ this.table.modules.edit.clearEdited(cell._getSelf());
141
+ });
142
+ }
143
+
144
+ navigatePrev(cell = this.currentCell, e){
145
+ var nextCell, prevRow;
146
+
147
+ if(cell){
148
+
149
+ if(e){
150
+ e.preventDefault();
151
+ }
152
+
153
+ nextCell = this.navigateLeft();
154
+
155
+ if(nextCell){
156
+ return true;
157
+ }else{
158
+ prevRow = this.table.rowManager.prevDisplayRow(cell.row, true);
159
+
160
+ if(prevRow){
161
+ nextCell = this.findPrevEditableCell(prevRow, prevRow.cells.length);
162
+
163
+ if(nextCell){
164
+ nextCell.getComponent().edit();
165
+ return true;
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+ return false;
172
+ }
173
+
174
+ navigateNext(cell = this.currentCell, e){
175
+ var nextCell, nextRow;
176
+
177
+ if(cell){
178
+
179
+ if(e){
180
+ e.preventDefault();
181
+ }
182
+
183
+ nextCell = this.navigateRight();
184
+
185
+ if(nextCell){
186
+ return true;
187
+ }else{
188
+ nextRow = this.table.rowManager.nextDisplayRow(cell.row, true);
189
+
190
+ if(nextRow){
191
+ nextCell = this.findNextEditableCell(nextRow, -1);
192
+
193
+ if(nextCell){
194
+ nextCell.getComponent().edit();
195
+ return true;
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ return false;
202
+ }
203
+
204
+ navigateLeft(cell = this.currentCell, e){
205
+ var index, nextCell;
206
+
207
+ if(cell){
208
+
209
+ if(e){
210
+ e.preventDefault();
211
+ }
212
+
213
+ index = cell.getIndex();
214
+ nextCell = this.findPrevEditableCell(cell.row, index);
215
+
216
+ if(nextCell){
217
+ nextCell.getComponent().edit();
218
+ return true;
219
+ }
220
+ }
221
+
222
+ return false;
223
+ }
224
+
225
+ navigateRight(cell = this.currentCell, e){
226
+ var index, nextCell;
227
+
228
+ if(cell){
229
+
230
+ if(e){
231
+ e.preventDefault();
232
+ }
233
+
234
+ index = cell.getIndex();
235
+ nextCell = this.findNextEditableCell(cell.row, index);
236
+
237
+ if(nextCell){
238
+ nextCell.getComponent().edit();
239
+ return true;
240
+ }
241
+ }
242
+
243
+ return false;
244
+ }
245
+
246
+ navigateUp(cell = this.currentCell, e){
247
+ var index, nextRow;
248
+
249
+ if(cell){
250
+
251
+ if(e){
252
+ e.preventDefault();
253
+ }
254
+
255
+ index = cell.getIndex();
256
+ nextRow = this.table.rowManager.prevDisplayRow(cell.row, true);
257
+
258
+ if(nextRow){
259
+ nextRow.cells[index].getComponent().edit();
260
+ return true;
261
+ }
262
+ }
263
+
264
+ return false;
265
+ }
266
+
267
+ navigateDown(cell = this.currentCell, e){
268
+ var index, nextRow;
269
+
270
+ if(cell){
271
+
272
+ if(e){
273
+ e.preventDefault();
274
+ }
275
+
276
+ index = cell.getIndex();
277
+ nextRow = this.table.rowManager.nextDisplayRow(cell.row, true);
278
+
279
+ if(nextRow){
280
+ nextRow.cells[index].getComponent().edit();
281
+ return true;
282
+ }
283
+ }
284
+
285
+ return false;
286
+ }
287
+
288
+ findNextEditableCell(row, index){
289
+ var nextCell = false;
290
+
291
+ if(index < row.cells.length-1){
292
+ for(var i = index+1; i < row.cells.length; i++){
293
+ let cell = row.cells[i];
294
+
295
+ if(cell.column.modules.edit && Helpers.elVisible(cell.getElement())){
296
+ let allowEdit = this.allowEdit(cell);
297
+
298
+ if(allowEdit){
299
+ nextCell = cell;
300
+ break;
301
+ }
302
+ }
303
+ }
304
+ }
305
+
306
+ return nextCell;
307
+ }
308
+
309
+ findPrevEditableCell(row, index){
310
+ var prevCell = false;
311
+
312
+ if(index > 0){
313
+ for(var i = index-1; i >= 0; i--){
314
+ let cell = row.cells[i];
315
+
316
+ if(cell.column.modules.edit && Helpers.elVisible(cell.getElement())){
317
+ let allowEdit = this.allowEdit(cell);
318
+
319
+ if(allowEdit){
320
+ prevCell = cell;
321
+ break;
322
+ }
323
+ }
324
+ }
325
+ }
326
+
327
+ return prevCell;
328
+ }
329
+
330
+ ///////////////////////////////////
331
+ ///////// Internal Logic //////////
332
+ ///////////////////////////////////
333
+
334
+ initializeColumnCheck(column){
335
+ if(typeof column.definition.editor !== "undefined"){
336
+ this.initializeColumn(column);
337
+ }
338
+ }
339
+
340
+ columnDeleteCheck(column){
341
+ if(this.currentCell && this.currentCell.column === column){
342
+ this.cancelEdit();
343
+ }
344
+ }
345
+
346
+ rowDeleteCheck(row){
347
+ if(this.currentCell && this.currentCell.row === row){
348
+ this.cancelEdit();
349
+ }
350
+ }
351
+
352
+ rowEditableCheck(row){
353
+ row.getCells().forEach((cell) => {
354
+ if(cell.column.modules.edit && typeof cell.column.modules.edit.check === "function"){
355
+ this.updateCellClass(cell);
356
+ }
357
+ });
358
+ }
359
+
360
+ //initialize column editor
361
+ initializeColumn(column){
362
+ var config = {
363
+ editor:false,
364
+ blocked:false,
365
+ check:column.definition.editable,
366
+ params:column.definition.editorParams || {}
367
+ };
368
+
369
+ //set column editor
370
+ switch(typeof column.definition.editor){
371
+ case "string":
372
+ if(this.editors[column.definition.editor]){
373
+ config.editor = this.editors[column.definition.editor];
374
+ }else{
375
+ console.warn("Editor Error - No such editor found: ", column.definition.editor);
376
+ }
377
+ break;
378
+
379
+ case "function":
380
+ config.editor = column.definition.editor;
381
+ break;
382
+
383
+ case "boolean":
384
+ if(column.definition.editor === true){
385
+ if(typeof column.definition.formatter !== "function"){
386
+ if(this.editors[column.definition.formatter]){
387
+ config.editor = this.editors[column.definition.formatter];
388
+ }else{
389
+ config.editor = this.editors["input"];
390
+ }
391
+ }else{
392
+ console.warn("Editor Error - Cannot auto lookup editor for a custom formatter: ", column.definition.formatter);
393
+ }
394
+ }
395
+ break;
396
+ }
397
+
398
+ if(config.editor){
399
+ column.modules.edit = config;
400
+ }
401
+ }
402
+
403
+ getCurrentCell(){
404
+ return this.currentCell ? this.currentCell.getComponent() : false;
405
+ }
406
+
407
+ clearEditor(cancel){
408
+ var cell = this.currentCell,
409
+ cellEl;
410
+
411
+ this.invalidEdit = false;
412
+
413
+ if(cell){
414
+ this.currentCell = false;
415
+
416
+ cellEl = cell.getElement();
417
+
418
+ this.dispatch("edit-editor-clear", cell, cancel);
419
+
420
+ cellEl.classList.remove("tabulator-editing");
421
+
422
+ while(cellEl.firstChild) cellEl.removeChild(cellEl.firstChild);
423
+
424
+ cell.row.getElement().classList.remove("tabulator-editing");
425
+
426
+ cell.table.element.classList.remove("tabulator-editing");
427
+ }
428
+ }
429
+
430
+ cancelEdit(){
431
+ if(this.currentCell){
432
+ var cell = this.currentCell;
433
+ var component = this.currentCell.getComponent();
434
+
435
+ this.clearEditor(true);
436
+ cell.setValueActual(cell.getValue());
437
+ cell.cellRendered();
438
+
439
+ if(cell.column.definition.editor == "textarea" || cell.column.definition.variableHeight){
440
+ cell.row.normalizeHeight(true);
441
+ }
442
+
443
+ if(cell.column.definition.cellEditCancelled){
444
+ cell.column.definition.cellEditCancelled.call(this.table, component);
445
+ }
446
+
447
+ this.dispatch("edit-cancelled", cell);
448
+ this.dispatchExternal("cellEditCancelled", component);
449
+ }
450
+ }
451
+
452
+ //return a formatted value for a cell
453
+ bindEditor(cell){
454
+ if(cell.column.modules.edit){
455
+ var self = this,
456
+ element = cell.getElement(true);
457
+
458
+ this.updateCellClass(cell);
459
+ element.setAttribute("tabindex", 0);
460
+
461
+ element.addEventListener("click", function(e){
462
+ if(!element.classList.contains("tabulator-editing")){
463
+ element.focus({preventScroll: true});
464
+ }
465
+ });
466
+
467
+ element.addEventListener("mousedown", function(e){
468
+ if (e.button === 2) {
469
+ e.preventDefault();
470
+ }else{
471
+ self.mouseClick = true;
472
+ }
473
+ });
474
+
475
+ element.addEventListener("focus", function(e){
476
+ if(!self.recursionBlock){
477
+ self.edit(cell, e, false);
478
+ }
479
+ });
480
+ }
481
+ }
482
+
483
+ focusCellNoEvent(cell, block){
484
+ this.recursionBlock = true;
485
+
486
+ if(!(block && this.table.browser === "ie")){
487
+ cell.getElement().focus({preventScroll: true});
488
+ }
489
+
490
+ this.recursionBlock = false;
491
+ }
492
+
493
+ editCell(cell, forceEdit){
494
+ this.focusCellNoEvent(cell);
495
+ this.edit(cell, false, forceEdit);
496
+ }
497
+
498
+ focusScrollAdjust(cell){
499
+ if(this.table.rowManager.getRenderMode() == "virtual"){
500
+ var topEdge = this.table.rowManager.element.scrollTop,
501
+ bottomEdge = this.table.rowManager.element.clientHeight + this.table.rowManager.element.scrollTop,
502
+ rowEl = cell.row.getElement();
503
+
504
+ if(rowEl.offsetTop < topEdge){
505
+ this.table.rowManager.element.scrollTop -= (topEdge - rowEl.offsetTop);
506
+ }else{
507
+ if(rowEl.offsetTop + rowEl.offsetHeight > bottomEdge){
508
+ this.table.rowManager.element.scrollTop += (rowEl.offsetTop + rowEl.offsetHeight - bottomEdge);
509
+ }
510
+ }
511
+
512
+ var leftEdge = this.table.rowManager.element.scrollLeft,
513
+ rightEdge = this.table.rowManager.element.clientWidth + this.table.rowManager.element.scrollLeft,
514
+ cellEl = cell.getElement();
515
+
516
+ if(this.table.modExists("frozenColumns")){
517
+ leftEdge += parseInt(this.table.modules.frozenColumns.leftMargin);
518
+ rightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin);
519
+ }
520
+
521
+ if(this.table.options.renderHorizontal === "virtual"){
522
+ leftEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft);
523
+ rightEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft);
524
+ }
525
+
526
+ if(cellEl.offsetLeft < leftEdge){
527
+
528
+ this.table.rowManager.element.scrollLeft -= (leftEdge - cellEl.offsetLeft);
529
+ }else{
530
+ if(cellEl.offsetLeft + cellEl.offsetWidth > rightEdge){
531
+ this.table.rowManager.element.scrollLeft += (cellEl.offsetLeft + cellEl.offsetWidth - rightEdge);
532
+ }
533
+ }
534
+ }
535
+ }
536
+
537
+ allowEdit(cell) {
538
+ var check = cell.column.modules.edit ? true : false;
539
+
540
+ if(cell.column.modules.edit){
541
+ switch(typeof cell.column.modules.edit.check){
542
+ case "function":
543
+ if(cell.row.initialized){
544
+ check = cell.column.modules.edit.check(cell.getComponent());
545
+ }
546
+ break;
547
+
548
+ case "string":
549
+ check = !!cell.row.data[cell.column.modules.edit.check];
550
+ break;
551
+
552
+ case "boolean":
553
+ check = cell.column.modules.edit.check;
554
+ break;
555
+ }
556
+ }
557
+
558
+ return check;
559
+ }
560
+
561
+ edit(cell, e, forceEdit){
562
+ var self = this,
563
+ allowEdit = true,
564
+ rendered = function(){},
565
+ element = cell.getElement(),
566
+ cellEditor, component, params;
567
+
568
+ //prevent editing if another cell is refusing to leave focus (eg. validation fail)
569
+
570
+ if(this.currentCell){
571
+ if(!this.invalidEdit && this.currentCell !== cell){
572
+ this.cancelEdit();
573
+ }
574
+ return;
575
+ }
576
+
577
+ //handle successful value change
578
+ function success(value){
579
+ if(self.currentCell === cell){
580
+ var valid = self.chain("edit-success", [cell, value], true, true);
581
+
582
+ if(valid === true || self.table.options.validationMode === "highlight"){
583
+ self.clearEditor();
584
+
585
+
586
+ if(!cell.modules.edit){
587
+ cell.modules.edit = {};
588
+ }
589
+
590
+ cell.modules.edit.edited = true;
591
+
592
+ if(self.editedCells.indexOf(cell) == -1){
593
+ self.editedCells.push(cell);
594
+ }
595
+
596
+ cell.setValue(value, true);
597
+
598
+ return valid === true;
599
+ }else{
600
+ self.invalidEdit = true;
601
+ self.focusCellNoEvent(cell, true);
602
+ rendered();
603
+ return false;
604
+ }
605
+ }else{
606
+ // console.warn("Edit Success Error - cannot call success on a cell that is no longer being edited");
607
+ }
608
+ }
609
+
610
+ //handle aborted edit
611
+ function cancel(){
612
+ if(self.currentCell === cell){
613
+ self.cancelEdit();
614
+ }else{
615
+ // console.warn("Edit Success Error - cannot call cancel on a cell that is no longer being edited");
616
+ }
617
+ }
618
+
619
+ function onRendered(callback){
620
+ rendered = callback;
621
+ }
622
+
623
+ if(!cell.column.modules.edit.blocked){
624
+ if(e){
625
+ e.stopPropagation();
626
+ }
627
+
628
+ allowEdit = this.allowEdit(cell);
629
+
630
+ if(allowEdit || forceEdit){
631
+
632
+ self.cancelEdit();
633
+
634
+ self.currentCell = cell;
635
+
636
+ this.focusScrollAdjust(cell);
637
+
638
+ component = cell.getComponent();
639
+
640
+ if(this.mouseClick){
641
+ this.mouseClick = false;
642
+
643
+ if(cell.column.definition.cellClick){
644
+ cell.column.definition.cellClick.call(this.table, e, component);
645
+ }
646
+ }
647
+
648
+ if(cell.column.definition.cellEditing){
649
+ cell.column.definition.cellEditing.call(this.table, component);
650
+ }
651
+
652
+ this.dispatch("cell-editing", cell);
653
+ this.dispatchExternal("cellEditing", component);
654
+
655
+ params = typeof cell.column.modules.edit.params === "function" ? cell.column.modules.edit.params(component) : cell.column.modules.edit.params;
656
+
657
+ cellEditor = cell.column.modules.edit.editor.call(self, component, onRendered, success, cancel, params);
658
+
659
+ //if editor returned, add to DOM, if false, abort edit
660
+ if(this.currentCell && cellEditor !== false){
661
+ if(cellEditor instanceof Node){
662
+ element.classList.add("tabulator-editing");
663
+ cell.row.getElement().classList.add("tabulator-editing");
664
+ cell.table.element.classList.add("tabulator-editing");
665
+ while(element.firstChild) element.removeChild(element.firstChild);
666
+ element.appendChild(cellEditor);
667
+
668
+ //trigger onRendered Callback
669
+ rendered();
670
+
671
+ //prevent editing from triggering rowClick event
672
+ var children = element.children;
673
+
674
+ for (var i = 0; i < children.length; i++) {
675
+ children[i].addEventListener("click", function(e){
676
+ e.stopPropagation();
677
+ });
678
+ }
679
+ }else{
680
+ console.warn("Edit Error - Editor should return an instance of Node, the editor returned:", cellEditor);
681
+ element.blur();
682
+ return false;
683
+ }
684
+ }else{
685
+ element.blur();
686
+ return false;
687
+ }
688
+
689
+ return true;
690
+ }else{
691
+ this.mouseClick = false;
692
+ element.blur();
693
+ return false;
694
+ }
695
+ }else{
696
+ this.mouseClick = false;
697
+ element.blur();
698
+ return false;
699
+ }
700
+ }
701
+
702
+ getEditedCells(){
703
+ var output = [];
704
+
705
+ this.editedCells.forEach((cell) => {
706
+ output.push(cell.getComponent());
707
+ });
708
+
709
+ return output;
710
+ }
711
+
712
+ clearEdited(cell){
713
+ var editIndex;
714
+
715
+ if(cell.modules.edit && cell.modules.edit.edited){
716
+ cell.modules.edit.edited = false;
717
+
718
+ this.dispatch("edit-edited-clear", cell);
719
+ }
720
+
721
+ editIndex = this.editedCells.indexOf(cell);
722
+
723
+ if(editIndex > -1){
724
+ this.editedCells.splice(editIndex, 1);
725
+ }
726
+ }
727
+ }
728
+
729
+ Edit.moduleName = "edit";
730
+
731
+ //load defaults
732
+ Edit.editors = defaultEditors;
733
+
734
+
735
+ export default Edit;