@highcharts/grid-pro 2.0.1 → 2.1.0

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 (164) hide show
  1. package/css/grid-pro.css +69 -85
  2. package/es-modules/Accessibility/Components/SeriesComponent/ForcedMarkers.js +2 -0
  3. package/es-modules/Accessibility/Options/LangDefaults.js +6 -1
  4. package/es-modules/Accessibility/Utils/ChartUtilities.js +3 -3
  5. package/es-modules/Core/Color/ColorString.d.ts +25 -0
  6. package/es-modules/Core/Color/ColorType.d.ts +43 -0
  7. package/es-modules/Core/Color/GradientColor.d.ts +57 -0
  8. package/es-modules/Core/Globals.js +1 -1
  9. package/es-modules/Core/Renderer/AlignObject.d.ts +37 -0
  10. package/es-modules/Core/Renderer/BBoxObject.d.ts +40 -0
  11. package/es-modules/Core/Renderer/CSSObject.d.ts +130 -0
  12. package/es-modules/Core/Renderer/DOMElementType.d.ts +36 -0
  13. package/es-modules/Core/Renderer/DashStyleValue.d.ts +28 -0
  14. package/es-modules/Core/Renderer/FontMetricsObject.d.ts +38 -0
  15. package/es-modules/Core/Renderer/HTML/HTMLAttributes.d.ts +57 -0
  16. package/es-modules/Core/Renderer/PolygonBoxObject.d.ts +19 -0
  17. package/es-modules/Core/Renderer/Position3DObject.d.ts +35 -0
  18. package/es-modules/Core/Renderer/PositionObject.d.ts +28 -0
  19. package/es-modules/Core/Renderer/RectangleObject.d.ts +35 -0
  20. package/es-modules/Core/Renderer/RendererType.d.ts +53 -0
  21. package/es-modules/Core/Renderer/SVG/ButtonThemeObject.d.ts +43 -0
  22. package/es-modules/Core/Renderer/SVG/SVGArc3D.d.ts +44 -0
  23. package/es-modules/Core/Renderer/SVG/SVGAttributes.d.ts +147 -0
  24. package/es-modules/Core/Renderer/SVG/SVGAttributes3D.d.ts +42 -0
  25. package/es-modules/Core/Renderer/SVG/SVGCuboid.d.ts +42 -0
  26. package/es-modules/Core/Renderer/SVG/SVGElementBase.d.ts +31 -0
  27. package/es-modules/Core/Renderer/SVG/SVGPath.d.ts +97 -0
  28. package/es-modules/Core/Renderer/SVG/SVGPath3D.d.ts +40 -0
  29. package/es-modules/Core/Renderer/SVG/SVGRendererBase.d.ts +31 -0
  30. package/es-modules/Core/Renderer/SVG/SymbolOptions.d.ts +41 -0
  31. package/es-modules/Core/Renderer/SVG/SymbolType.d.ts +50 -0
  32. package/es-modules/Core/Renderer/ShadowOptionsObject.d.ts +40 -0
  33. package/es-modules/Core/Renderer/SizeObject.d.ts +28 -0
  34. package/es-modules/Core/Templating.js +6 -7
  35. package/es-modules/Data/Connectors/DataConnector.js +3 -2
  36. package/es-modules/Data/Connectors/DataConnectorOptions.d.ts +1 -1
  37. package/es-modules/Data/DataTable.d.ts +1 -1
  38. package/es-modules/Data/DataTable.js +3 -2
  39. package/es-modules/Data/DataTableCore.js +15 -6
  40. package/es-modules/Grid/Core/Accessibility/Accessibility.d.ts +13 -15
  41. package/es-modules/Grid/Core/Credits.d.ts +0 -2
  42. package/es-modules/Grid/Core/Defaults.d.ts +20 -17
  43. package/es-modules/Grid/Core/Defaults.js +116 -114
  44. package/es-modules/Grid/Core/Globals.d.ts +108 -32
  45. package/es-modules/Grid/Core/Globals.js +98 -111
  46. package/es-modules/Grid/Core/Grid.d.ts +51 -17
  47. package/es-modules/Grid/Core/Grid.js +369 -79
  48. package/es-modules/Grid/Core/GridUtils.d.ts +96 -89
  49. package/es-modules/Grid/Core/GridUtils.js +143 -155
  50. package/es-modules/Grid/Core/Options.d.ts +3 -7
  51. package/es-modules/Grid/Core/Pagination/Icons.d.ts +4 -4
  52. package/es-modules/Grid/Core/Pagination/Pagination.d.ts +32 -57
  53. package/es-modules/Grid/Core/Pagination/Pagination.js +206 -214
  54. package/es-modules/Grid/Core/Pagination/PaginationOptions.d.ts +22 -15
  55. package/es-modules/Grid/Core/Querying/PaginationController.d.ts +32 -9
  56. package/es-modules/Grid/Core/Querying/PaginationController.js +58 -18
  57. package/es-modules/Grid/Core/Querying/SortingController.d.ts +7 -15
  58. package/es-modules/Grid/Core/Querying/SortingController.js +2 -3
  59. package/es-modules/Grid/Core/Table/Actions/ColumnFiltering/ColumnFiltering.d.ts +1 -1
  60. package/es-modules/Grid/Core/Table/Actions/ColumnFiltering/ColumnFiltering.js +32 -4
  61. package/es-modules/Grid/Core/Table/Actions/ColumnFiltering/FilteringTypes.d.ts +3 -3
  62. package/es-modules/Grid/Core/Table/Actions/ColumnSorting.d.ts +3 -5
  63. package/es-modules/Grid/Core/Table/Actions/ColumnSorting.js +1 -5
  64. package/es-modules/Grid/Core/Table/Body/TableCell.d.ts +14 -10
  65. package/es-modules/Grid/Core/Table/Body/TableCell.js +19 -21
  66. package/es-modules/Grid/Core/Table/Body/TableRow.d.ts +0 -2
  67. package/es-modules/Grid/Core/Table/Cell.js +30 -0
  68. package/es-modules/Grid/Core/Table/CellContent/TextContent.d.ts +2 -7
  69. package/es-modules/Grid/Core/Table/CellContent/TextContent.js +25 -14
  70. package/es-modules/Grid/Core/Table/Column.d.ts +7 -9
  71. package/es-modules/Grid/Core/Table/Column.js +23 -1
  72. package/es-modules/Grid/Core/Table/ColumnResizing/AdjacentResizingMode.js +2 -2
  73. package/es-modules/Grid/Core/Table/ColumnResizing/ColumnResizing.d.ts +30 -23
  74. package/es-modules/Grid/Core/Table/ColumnResizing/ColumnResizing.js +39 -39
  75. package/es-modules/Grid/Core/Table/ColumnResizing/DistributedResizingMode.js +1 -1
  76. package/es-modules/Grid/Core/Table/ColumnResizing/IndependentResizingMode.js +2 -2
  77. package/es-modules/Grid/Core/Table/ColumnResizing/ResizingMode.d.ts +6 -1
  78. package/es-modules/Grid/Core/Table/Header/ColumnToolbar/ColumnToolbar.js +10 -0
  79. package/es-modules/Grid/Core/Table/Header/ColumnToolbar/FilterPopup.d.ts +2 -2
  80. package/es-modules/Grid/Core/Table/Header/ColumnToolbar/StateHelpers.d.ts +26 -24
  81. package/es-modules/Grid/Core/Table/Header/ColumnToolbar/StateHelpers.js +37 -39
  82. package/es-modules/Grid/Core/Table/Header/ColumnToolbar/ToolbarButtons/FilterToolbarButton.d.ts +1 -1
  83. package/es-modules/Grid/Core/Table/Header/ColumnToolbar/ToolbarButtons/MenuToolbarButton.d.ts +1 -1
  84. package/es-modules/Grid/Core/Table/Header/ColumnToolbar/ToolbarButtons/SortToolbarButton.d.ts +1 -1
  85. package/es-modules/Grid/Core/Table/Header/HeaderRow.d.ts +0 -2
  86. package/es-modules/Grid/Core/Table/Header/TableHeader.d.ts +0 -2
  87. package/es-modules/Grid/Core/Table/Table.d.ts +11 -13
  88. package/es-modules/Grid/Core/Table/Table.js +9 -5
  89. package/es-modules/Grid/Core/UI/Button.d.ts +1 -1
  90. package/es-modules/Grid/Core/UI/ContextMenu.d.ts +1 -1
  91. package/es-modules/Grid/Core/UI/ContextMenu.js +1 -1
  92. package/es-modules/Grid/Core/UI/ContextMenuButton.d.ts +39 -44
  93. package/es-modules/Grid/Core/UI/ContextMenuButton.js +4 -4
  94. package/es-modules/Grid/Core/UI/Popup.d.ts +17 -19
  95. package/es-modules/Grid/Core/UI/Popup.js +2 -1
  96. package/es-modules/Grid/Core/UI/SvgIcons.d.ts +49 -50
  97. package/es-modules/Grid/Core/UI/SvgIcons.js +114 -123
  98. package/es-modules/Grid/Core/UI/ToolbarButton.d.ts +46 -52
  99. package/es-modules/Grid/Core/UI/ToolbarButton.js +4 -3
  100. package/es-modules/Grid/Pro/CellEditing/CellEditing.d.ts +6 -8
  101. package/es-modules/Grid/Pro/CellEditing/CellEditing.js +8 -11
  102. package/es-modules/Grid/Pro/CellEditing/CellEditingComposition.d.ts +27 -1
  103. package/es-modules/Grid/Pro/CellEditing/CellEditingComposition.js +149 -149
  104. package/es-modules/Grid/Pro/CellRendering/CellRenderer.d.ts +18 -20
  105. package/es-modules/Grid/Pro/CellRendering/CellRenderer.js +1 -1
  106. package/es-modules/Grid/Pro/CellRendering/CellRendererRegistry.d.ts +19 -17
  107. package/es-modules/Grid/Pro/CellRendering/CellRendererRegistry.js +28 -34
  108. package/es-modules/Grid/Pro/CellRendering/CellRenderersComposition.d.ts +12 -1
  109. package/es-modules/Grid/Pro/CellRendering/CellRenderersComposition.js +41 -46
  110. package/es-modules/Grid/Pro/CellRendering/ContentTypes/CheckboxContent.js +2 -2
  111. package/es-modules/Grid/Pro/CellRendering/ContentTypes/DateInputContent.d.ts +2 -2
  112. package/es-modules/Grid/Pro/CellRendering/ContentTypes/DateInputContentBase.d.ts +2 -2
  113. package/es-modules/Grid/Pro/CellRendering/ContentTypes/DateInputContentBase.js +4 -2
  114. package/es-modules/Grid/Pro/CellRendering/ContentTypes/DateTimeInputContent.d.ts +2 -2
  115. package/es-modules/Grid/Pro/CellRendering/ContentTypes/NumberInputContent.js +3 -1
  116. package/es-modules/Grid/Pro/CellRendering/ContentTypes/SelectContent.js +3 -1
  117. package/es-modules/Grid/Pro/CellRendering/ContentTypes/SparklineContent.d.ts +19 -8
  118. package/es-modules/Grid/Pro/CellRendering/ContentTypes/SparklineContent.js +17 -13
  119. package/es-modules/Grid/Pro/CellRendering/ContentTypes/TextInputContent.js +3 -1
  120. package/es-modules/Grid/Pro/CellRendering/ContentTypes/TimeInputContent.d.ts +2 -2
  121. package/es-modules/Grid/Pro/CellRendering/Renderers/CheckboxRenderer.d.ts +18 -20
  122. package/es-modules/Grid/Pro/CellRendering/Renderers/CheckboxRenderer.js +3 -3
  123. package/es-modules/Grid/Pro/CellRendering/Renderers/DateInputRenderer.d.ts +10 -12
  124. package/es-modules/Grid/Pro/CellRendering/Renderers/DateInputRenderer.js +3 -3
  125. package/es-modules/Grid/Pro/CellRendering/Renderers/DateInputRendererBase.d.ts +17 -20
  126. package/es-modules/Grid/Pro/CellRendering/Renderers/DateTimeInputRenderer.d.ts +10 -12
  127. package/es-modules/Grid/Pro/CellRendering/Renderers/DateTimeInputRenderer.js +3 -3
  128. package/es-modules/Grid/Pro/CellRendering/Renderers/NumberInputRenderer.d.ts +20 -22
  129. package/es-modules/Grid/Pro/CellRendering/Renderers/NumberInputRenderer.js +3 -3
  130. package/es-modules/Grid/Pro/CellRendering/Renderers/SelectRenderer.d.ts +40 -42
  131. package/es-modules/Grid/Pro/CellRendering/Renderers/SelectRenderer.js +3 -3
  132. package/es-modules/Grid/Pro/CellRendering/Renderers/SparklineRenderer.d.ts +16 -18
  133. package/es-modules/Grid/Pro/CellRendering/Renderers/SparklineRenderer.js +14 -22
  134. package/es-modules/Grid/Pro/CellRendering/Renderers/TextInputRenderer.d.ts +22 -24
  135. package/es-modules/Grid/Pro/CellRendering/Renderers/TextInputRenderer.js +3 -3
  136. package/es-modules/Grid/Pro/CellRendering/Renderers/TextRenderer.d.ts +10 -12
  137. package/es-modules/Grid/Pro/CellRendering/Renderers/TextRenderer.js +3 -3
  138. package/es-modules/Grid/Pro/CellRendering/Renderers/TimeInputRenderer.d.ts +10 -12
  139. package/es-modules/Grid/Pro/CellRendering/Renderers/TimeInputRenderer.js +3 -3
  140. package/es-modules/Grid/Pro/ColumnTypes/Validator.d.ts +46 -51
  141. package/es-modules/Grid/Pro/ColumnTypes/Validator.js +62 -77
  142. package/es-modules/Grid/Pro/ColumnTypes/ValidatorComposition.d.ts +16 -3
  143. package/es-modules/Grid/Pro/ColumnTypes/ValidatorComposition.js +26 -31
  144. package/es-modules/Grid/Pro/Credits/CreditsPro.d.ts +0 -2
  145. package/es-modules/Grid/Pro/Credits/CreditsProComposition.d.ts +12 -11
  146. package/es-modules/Grid/Pro/Credits/CreditsProComposition.js +29 -31
  147. package/es-modules/Grid/Pro/Export/Exporting.d.ts +3 -3
  148. package/es-modules/Grid/Pro/Export/Exporting.js +35 -29
  149. package/es-modules/Grid/Pro/Export/ExportingComposition.d.ts +12 -11
  150. package/es-modules/Grid/Pro/Export/ExportingComposition.js +24 -26
  151. package/es-modules/Grid/Pro/GridEvents.d.ts +19 -1
  152. package/es-modules/Grid/Pro/GridEvents.js +6 -2
  153. package/es-modules/Grid/Pro/Pagination/PaginationComposition.d.ts +4 -11
  154. package/es-modules/Grid/Pro/Pagination/PaginationComposition.js +44 -45
  155. package/es-modules/Grid/index.d.ts +1 -0
  156. package/es-modules/masters/grid-pro.src.d.ts +62 -37
  157. package/es-modules/masters/grid-pro.src.js +37 -39
  158. package/grid-pro.d.ts +122 -48
  159. package/grid-pro.js +3 -6
  160. package/grid-pro.js.map +1 -1
  161. package/grid-pro.src.d.ts +122 -48
  162. package/grid-pro.src.js +6645 -6270
  163. package/package.json +13 -4
  164. package/es-modules/Grid/Pro/ColumnTypes/ColumnDataType.d.ts +0 -29
@@ -16,7 +16,7 @@
16
16
  'use strict';
17
17
  import Accessibility from './Accessibility/Accessibility.js';
18
18
  import AST from '../../Core/Renderer/HTML/AST.js';
19
- import Defaults from './Defaults.js';
19
+ import { defaultOptions } from './Defaults.js';
20
20
  import GridUtils from './GridUtils.js';
21
21
  import DataTable from '../../Data/DataTable.js';
22
22
  import Table from './Table/Table.js';
@@ -26,7 +26,7 @@ import Globals from './Globals.js';
26
26
  import TimeBase from '../../Shared/TimeBase.js';
27
27
  import Pagination from './Pagination/Pagination.js';
28
28
  const { makeHTMLElement, setHTMLContent } = GridUtils;
29
- const { extend, fireEvent, getStyle, merge, pick, isObject } = U;
29
+ const { defined, diffObjects, extend, fireEvent, getStyle, merge, pick } = U;
30
30
  /* *
31
31
  *
32
32
  * Class
@@ -35,7 +35,7 @@ const { extend, fireEvent, getStyle, merge, pick, isObject } = U;
35
35
  /**
36
36
  * A base class for the Grid.
37
37
  */
38
- class Grid {
38
+ export class Grid {
39
39
  // Implementation
40
40
  static grid(renderTo, options, async) {
41
41
  if (async) {
@@ -90,6 +90,17 @@ class Grid {
90
90
  * that need to be removed when the grid is destroyed.
91
91
  */
92
92
  this.dataTableEventDestructors = [];
93
+ /**
94
+ * Whether the Grid is rendered.
95
+ */
96
+ this.isRendered = false;
97
+ /**
98
+ * The flags that indicate which parts of the Grid are dirty and need to be
99
+ * re-rendered.
100
+ * @internal
101
+ */
102
+ this.dirtyFlags = new Set();
103
+ this.renderTo = renderTo;
93
104
  this.loadUserOptions(options);
94
105
  this.id = this.options?.id || U.uniqueKey();
95
106
  this.querying = new QueryingController(this);
@@ -97,13 +108,7 @@ class Grid {
97
108
  this.time = new TimeBase(extend(this.options?.time, { locale: this.locale }), this.options?.lang);
98
109
  fireEvent(this, 'beforeLoad');
99
110
  Grid.grids.push(this);
100
- this.initContainers(renderTo);
101
- this.initAccessibility();
102
- this.initPagination();
103
- this.loadDataTable();
104
- this.querying.loadOptions();
105
- void this.querying.proceed().then(() => {
106
- this.renderViewport();
111
+ void this.render().then(() => {
107
112
  afterLoadCallback?.(this);
108
113
  fireEvent(this, 'afterLoad');
109
114
  });
@@ -127,22 +132,10 @@ class Grid {
127
132
  * Initializes the pagination.
128
133
  */
129
134
  initPagination() {
130
- let state;
131
- if (this.pagination) {
132
- const { currentPageSize, currentPage } = this.pagination || {};
133
- state = {
134
- currentPageSize,
135
- currentPage
136
- };
137
- }
138
135
  this.pagination?.destroy();
139
136
  delete this.pagination;
140
- const rawOptions = this.options?.pagination;
141
- const options = isObject(rawOptions) ? rawOptions : {
142
- enabled: rawOptions
143
- };
144
- if (options?.enabled) {
145
- this.pagination = new Pagination(this, options, state);
137
+ if (this.options?.pagination?.enabled) {
138
+ this.pagination = new Pagination(this);
146
139
  }
147
140
  }
148
141
  /**
@@ -152,17 +145,13 @@ class Grid {
152
145
  * The render target (html element or id) of the Grid.
153
146
  *
154
147
  */
155
- initContainers(renderTo) {
148
+ initContainer(renderTo) {
156
149
  const container = (typeof renderTo === 'string') ?
157
150
  Globals.win.document.getElementById(renderTo) : renderTo;
158
151
  // Display an error if the renderTo is wrong
159
152
  if (!container) {
160
- // eslint-disable-next-line no-console
161
- console.error(`
162
- Rendering div not found. It is unable to find the HTML element
163
- to render the Grid in.
164
- `);
165
- return;
153
+ throw new Error('Rendering div not found. It is unable to find the HTML ' +
154
+ 'element to render the Grid in.');
166
155
  }
167
156
  this.initialContainerHeight = getStyle(container, 'height', true) || 0;
168
157
  this.container = container;
@@ -182,31 +171,52 @@ class Grid {
182
171
  * When `false` (default), the existing column options will be merged with
183
172
  * the ones that are currently defined in the user options. When `true`,
184
173
  * the columns not defined in the new options will be removed.
174
+ *
175
+ * @returns
176
+ * An object of the changed options.
185
177
  */
186
178
  loadUserOptions(newOptions, oneToOne = false) {
187
179
  // Operate on a copy of the options argument
188
180
  newOptions = merge(newOptions);
181
+ const diff = {};
189
182
  if (newOptions.columns) {
190
183
  if (oneToOne) {
191
- this.setColumnOptionsOneToOne(newOptions.columns);
184
+ diff.columns = this.setColumnOptionsOneToOne(newOptions.columns);
192
185
  }
193
186
  else {
194
- this.setColumnOptions(newOptions.columns);
187
+ diff.columns = this.setColumnOptions(newOptions.columns);
195
188
  }
196
189
  delete newOptions.columns;
197
190
  }
191
+ if (diff.columns && Object.keys(diff.columns).length < 1) {
192
+ // Remove the columns property if it is empty object
193
+ delete diff.columns;
194
+ }
195
+ merge(true, diff, diffObjects(newOptions, this.userOptions));
198
196
  this.userOptions = merge(this.userOptions, newOptions);
199
- this.options = merge(this.options ?? Defaults.defaultOptions, this.userOptions);
200
- // Generate column options map
201
- const columnOptionsArray = this.options?.columns;
202
- if (!columnOptionsArray) {
197
+ this.options = merge(this.options ?? defaultOptions, this.userOptions);
198
+ return diff;
199
+ }
200
+ /**
201
+ * Cleans up and reloads the column options from the `userOptions.columns`.
202
+ * Generates the internal column options map from the options.columns array.
203
+ */
204
+ reloadColumnOptions() {
205
+ const colOptions = this.userOptions.columns;
206
+ if (!colOptions) {
207
+ this.columnOptionsMap = {};
208
+ return;
209
+ }
210
+ if (colOptions.length < 1) {
211
+ delete this.userOptions.columns;
212
+ this.columnOptionsMap = {};
203
213
  return;
204
214
  }
205
215
  const columnOptionsMap = {};
206
- for (let i = 0, iEnd = columnOptionsArray?.length ?? 0; i < iEnd; ++i) {
207
- columnOptionsMap[columnOptionsArray[i].id] = {
216
+ for (let i = 0, iEnd = colOptions.length; i < iEnd; ++i) {
217
+ columnOptionsMap[colOptions[i].id] = {
208
218
  index: i,
209
- options: columnOptionsArray[i]
219
+ options: colOptions[i]
210
220
  };
211
221
  }
212
222
  this.columnOptionsMap = columnOptionsMap;
@@ -220,8 +230,15 @@ class Grid {
220
230
  * @param overwrite
221
231
  * Whether to overwrite the existing column options with the new ones.
222
232
  * Default is `false`.
233
+ *
234
+ * @returns
235
+ * An object of the changed column options in form of a record of
236
+ * `[column.id]: column.options`.
237
+ *
238
+ * @internal
223
239
  */
224
240
  setColumnOptions(newColumnOptions, overwrite = false) {
241
+ const columnDiffOptions = {};
225
242
  if (!this.userOptions.columns) {
226
243
  this.userOptions.columns = this.options?.columns ?? [];
227
244
  }
@@ -232,23 +249,33 @@ class Grid {
232
249
  // If the new column options contain only the id.
233
250
  if (Object.keys(newOptions).length < 2) {
234
251
  if (overwrite && colOptionsIndex !== -1) {
252
+ columnDiffOptions[newOptions.id] = diffObjects(columnOptions[colOptionsIndex], { id: newOptions.id }, true);
235
253
  columnOptions.splice(colOptionsIndex, 1);
236
254
  }
237
255
  continue;
238
256
  }
257
+ let diff;
239
258
  if (colOptionsIndex === -1) {
259
+ diff = merge(newOptions);
240
260
  columnOptions.push(newOptions);
241
261
  }
242
262
  else if (overwrite) {
263
+ const prevOptions = columnOptions[colOptionsIndex];
264
+ diff = merge(diffObjects(prevOptions, newOptions, true), diffObjects(newOptions, prevOptions));
243
265
  columnOptions[colOptionsIndex] = newOptions;
244
266
  }
245
267
  else {
246
- merge(true, columnOptions[colOptionsIndex], newOptions);
268
+ const prevOptions = columnOptions[colOptionsIndex];
269
+ diff = diffObjects(newOptions, prevOptions);
270
+ merge(true, prevOptions, newOptions);
271
+ }
272
+ delete diff.id;
273
+ if (Object.keys(diff).length > 0) {
274
+ columnDiffOptions[newOptions.id] = diff;
247
275
  }
248
276
  }
249
- if (columnOptions.length < 1) {
250
- delete this.userOptions.columns;
251
- }
277
+ this.reloadColumnOptions();
278
+ return columnDiffOptions;
252
279
  }
253
280
  /**
254
281
  * Loads the new column options to the userOptions field in a one-to-one
@@ -257,10 +284,15 @@ class Grid {
257
284
  *
258
285
  * @param newColumnOptions
259
286
  * The new column options that should be loaded.
287
+ *
288
+ * @returns
289
+ * The difference between the previous and the new column options in form
290
+ * of a record of `[column.id]: column.options`.
260
291
  */
261
292
  setColumnOptionsOneToOne(newColumnOptions) {
262
293
  const prevColumnOptions = this.userOptions.columns;
263
294
  const columnOptions = [];
295
+ const columnDiffOptions = {};
264
296
  let prevOptions;
265
297
  for (let i = 0, iEnd = newColumnOptions.length; i < iEnd; ++i) {
266
298
  const newOptions = newColumnOptions[i];
@@ -268,12 +300,19 @@ class Grid {
268
300
  if (indexInPrevOptions !== void 0 && indexInPrevOptions !== -1) {
269
301
  prevOptions = prevColumnOptions?.[indexInPrevOptions];
270
302
  }
303
+ const diffOptions = diffObjects(newOptions, prevOptions ?? {});
304
+ if (Object.keys(diffOptions).length > 0) {
305
+ delete diffOptions.id;
306
+ columnDiffOptions[newOptions.id] = diffOptions;
307
+ }
271
308
  const resultOptions = merge(prevOptions ?? {}, newOptions);
272
309
  if (Object.keys(resultOptions).length > 1) {
273
310
  columnOptions.push(resultOptions);
274
311
  }
275
312
  }
276
313
  this.userOptions.columns = columnOptions;
314
+ this.reloadColumnOptions();
315
+ return columnDiffOptions;
277
316
  }
278
317
  /**
279
318
  * Updates the Grid with new options.
@@ -283,36 +322,221 @@ class Grid {
283
322
  * the update will be proceeded based on the `this.userOptions` property.
284
323
  * The `column` options are merged using the `id` property as a key.
285
324
  *
286
- * @param render
287
- * Whether to re-render the Grid after updating the options.
325
+ * @param redraw
326
+ * Whether to redraw the Grid after updating the options.
288
327
  *
289
328
  * @param oneToOne
290
329
  * When `false` (default), the existing column options will be merged with
291
330
  * the ones that are currently defined in the user options. When `true`,
292
331
  * the columns not defined in the new options will be removed.
293
332
  */
294
- async update(options = {}, render = true, oneToOne = false) {
295
- this.loadUserOptions(options, oneToOne);
296
- if (!this.dataTable || options.dataTable) {
297
- this.userOptions.dataTable = options.dataTable;
298
- (this.options ?? {}).dataTable = options.dataTable;
299
- this.loadDataTable();
300
- this.querying.shouldBeUpdated = true;
301
- }
302
- if (!render) {
333
+ async update(options = {}, redraw = true, oneToOne = false) {
334
+ fireEvent(this, 'beforeUpdate', {
335
+ scope: 'grid',
336
+ options,
337
+ redraw,
338
+ oneToOne
339
+ });
340
+ const { viewport } = this;
341
+ const diff = this.loadUserOptions(options, oneToOne);
342
+ const flags = this.dirtyFlags;
343
+ if (viewport) {
344
+ if (!this.dataTable || 'dataTable' in diff) {
345
+ this.userOptions.dataTable = options.dataTable;
346
+ (this.options ?? {}).dataTable = options.dataTable;
347
+ this.loadDataTable();
348
+ // TODO: Sometimes it can be too much, so we need to check if
349
+ // the columns have changed or just their data. If just their
350
+ // data, we can just mark the grid.table as dirty instead of the
351
+ // whole grid.
352
+ flags.add('grid');
353
+ }
354
+ if ('columns' in diff) {
355
+ const ids = Object.keys(diff.columns ?? {});
356
+ for (const id of ids) {
357
+ // TODO: Move this to the column update method.
358
+ this.loadColumnOptionDiffs(viewport, id, diff.columns?.[id]);
359
+ delete diff.columns?.[id];
360
+ }
361
+ delete diff.columns;
362
+ }
363
+ if ('columnDefaults' in diff) {
364
+ this.loadColumnOptionDiffs(viewport, null, diff.columnDefaults);
365
+ delete diff.columnDefaults;
366
+ }
367
+ if (diff.lang) {
368
+ const langDiff = diff.lang;
369
+ if ('locale' in langDiff) {
370
+ this.locale = langDiff.locale;
371
+ this.time.update({ locale: this.locale });
372
+ }
373
+ delete langDiff.locale;
374
+ // TODO: Add more lang diff checks here.
375
+ if (Object.keys(langDiff).length > 0) {
376
+ flags.add('grid');
377
+ }
378
+ }
379
+ delete diff.lang;
380
+ if ('time' in diff) {
381
+ this.time.update(diff.time);
382
+ delete diff.time;
383
+ }
384
+ if (diff.pagination) {
385
+ const paginationDiff = diff.pagination;
386
+ if ('enabled' in paginationDiff) {
387
+ if (!this.pagination && paginationDiff.enabled) {
388
+ this.pagination = new Pagination(this);
389
+ }
390
+ }
391
+ this.pagination?.update(paginationDiff);
392
+ }
393
+ delete diff.pagination;
394
+ // TODO: Add more options that can be optimized here.
395
+ if (Object.keys(diff).length > 0) {
396
+ flags.add('grid');
397
+ }
398
+ }
399
+ else {
400
+ flags.add('grid');
401
+ }
402
+ if (redraw) {
403
+ await this.redraw();
404
+ }
405
+ fireEvent(this, 'afterUpdate', {
406
+ scope: 'grid',
407
+ options,
408
+ redraw,
409
+ oneToOne
410
+ });
411
+ }
412
+ /**
413
+ * Loads the column option diffs by updating the dirty flags.
414
+ *
415
+ * @param vp
416
+ * The viewport that the column option diffs should be loaded for.
417
+ *
418
+ * @param columnId
419
+ * The ID of the column that should be updated.
420
+ *
421
+ * @param columnDiff
422
+ * The difference between the previous and the new column options in form
423
+ * of a record of `[column.id]: column.options`. If `null`, assume that
424
+ * it refers to the column defaults.
425
+ */
426
+ loadColumnOptionDiffs(vp, columnId, columnDiff = {}) {
427
+ if (Object.keys(columnDiff).length < 1) {
303
428
  return;
304
429
  }
305
- this.initAccessibility();
306
- this.initPagination();
307
- this.querying.loadOptions();
308
- // Update locale.
309
- const locale = options.lang?.locale;
310
- if (locale) {
311
- this.locale = locale;
312
- this.time.update(extend(options.time || {}, { locale: this.locale }));
430
+ const flags = this.dirtyFlags;
431
+ const column = columnId ? this.viewport?.getColumn(columnId) : null;
432
+ if (column !== null && ( // Column null = column defaults
433
+ (!column && columnDiff.enabled !== false) ||
434
+ (column && columnDiff.enabled === false))) {
435
+ flags.add('grid');
436
+ }
437
+ delete columnDiff.enabled;
438
+ if ('cells' in columnDiff) {
439
+ const cellsDiff = columnDiff.cells ?? {};
440
+ if ('format' in cellsDiff ||
441
+ 'formatter' in cellsDiff ||
442
+ 'className' in cellsDiff // TODO: check if this too
443
+ ) {
444
+ // Optimization idea: list of columns to update
445
+ flags.add('rows');
446
+ }
447
+ delete cellsDiff.format;
448
+ delete cellsDiff.formatter;
449
+ delete cellsDiff.className;
450
+ if (Object.keys(cellsDiff).length > 0) {
451
+ flags.add('rows');
452
+ }
453
+ }
454
+ delete columnDiff.cells;
455
+ if ('width' in columnDiff) {
456
+ vp.columnResizing.isDirty = true;
457
+ }
458
+ delete columnDiff.width;
459
+ if ('sorting' in columnDiff) {
460
+ const sortingDiff = columnDiff.sorting ?? {};
461
+ if ('compare' in sortingDiff ||
462
+ 'order' in sortingDiff) {
463
+ flags.add('sorting');
464
+ }
465
+ delete sortingDiff.compare;
466
+ delete sortingDiff.order;
467
+ // Idea: sortable - redraw only header cell
468
+ if (Object.keys(sortingDiff).length > 0) {
469
+ flags.add('grid');
470
+ }
471
+ }
472
+ delete columnDiff.sorting;
473
+ if ('filtering' in columnDiff) {
474
+ const filteringDiff = columnDiff.filtering ?? {};
475
+ if ('condition' in filteringDiff ||
476
+ 'value' in filteringDiff) {
477
+ flags.add('filtering');
478
+ }
479
+ delete filteringDiff.condition;
480
+ delete filteringDiff.value;
481
+ if (Object.keys(filteringDiff).length > 0) {
482
+ flags.add('grid');
483
+ }
484
+ }
485
+ delete columnDiff.filtering;
486
+ if (Object.keys(columnDiff).length > 0) {
487
+ flags.add('grid');
313
488
  }
314
- await this.querying.proceed();
315
- this.renderViewport();
489
+ }
490
+ /**
491
+ * Redraws the Grid in more optimized way than the regular render method.
492
+ * It checks what parts of the Grid are marked as dirty and redraws only
493
+ * them minimizing the number of DOM operations.
494
+ */
495
+ async redraw() {
496
+ fireEvent(this, 'beforeRedraw');
497
+ const flags = this.dirtyFlags;
498
+ if (flags.has('grid')) {
499
+ return await this.render();
500
+ }
501
+ const { viewport: vp, pagination } = this;
502
+ const colResizing = vp?.columnResizing;
503
+ if (flags.has('sorting') ||
504
+ flags.has('filtering') ||
505
+ pagination?.isDirtyQuerying) {
506
+ this.querying.loadOptions();
507
+ }
508
+ if (colResizing?.isDirty) {
509
+ colResizing.loadColumns();
510
+ }
511
+ if (flags.has('rows') ||
512
+ flags.has('sorting') ||
513
+ flags.has('filtering') ||
514
+ pagination?.isDirtyQuerying) {
515
+ await vp?.updateRows();
516
+ }
517
+ else if (flags.has('reflow') ||
518
+ colResizing?.isDirty) {
519
+ vp?.reflow();
520
+ }
521
+ const columns = vp?.columns ?? [];
522
+ if (flags.has('sorting') ||
523
+ flags.has('filtering')) {
524
+ for (const column of columns) {
525
+ column.header?.toolbar?.refreshState();
526
+ }
527
+ }
528
+ if (flags.has('filtering')) {
529
+ for (const column of columns) {
530
+ column.filtering?.refreshState();
531
+ }
532
+ }
533
+ if (pagination?.isDirtyQuerying) {
534
+ pagination.updateControls(true);
535
+ }
536
+ delete pagination?.isDirtyQuerying;
537
+ delete colResizing?.isDirty;
538
+ flags.clear();
539
+ fireEvent(this, 'afterRedraw');
316
540
  }
317
541
  /**
318
542
  * Updates the column of the Grid with new options.
@@ -324,19 +548,54 @@ class Grid {
324
548
  * The options of the columns that should be updated. If null,
325
549
  * column options for this column ID will be removed.
326
550
  *
327
- * @param render
328
- * Whether to re-render the Grid after updating the columns.
551
+ * @param redraw
552
+ * Whether to redraw the Grid after updating the columns.
329
553
  *
330
554
  * @param overwrite
331
555
  * If true, the column options will be updated by replacing the existing
332
556
  * options with the new ones instead of merging them.
333
557
  */
334
- async updateColumn(columnId, options, render = true, overwrite = false) {
335
- this.setColumnOptions([{
558
+ async updateColumn(columnId, options, redraw = true, overwrite = false) {
559
+ fireEvent(this, 'beforeUpdate', {
560
+ scope: 'column',
561
+ options,
562
+ redraw,
563
+ overwrite,
564
+ columnId
565
+ });
566
+ const vp = this.viewport;
567
+ const diffs = this.setColumnOptions([{
336
568
  id: columnId,
337
569
  ...options
338
570
  }], overwrite);
339
- await this.update(void 0, render);
571
+ const diff = diffs?.[columnId];
572
+ if (diff && vp) {
573
+ this.loadColumnOptionDiffs(vp, columnId, diff);
574
+ }
575
+ if (redraw) {
576
+ await this.redraw();
577
+ }
578
+ fireEvent(this, 'afterUpdate', {
579
+ scope: 'column',
580
+ options,
581
+ redraw,
582
+ overwrite,
583
+ columnId
584
+ });
585
+ }
586
+ async render() {
587
+ if (this.isRendered) {
588
+ this.destroy(true);
589
+ }
590
+ this.loadDataTable();
591
+ this.initContainer(this.renderTo);
592
+ this.initAccessibility();
593
+ this.initPagination();
594
+ this.querying.loadOptions();
595
+ await this.querying.proceed();
596
+ this.renderViewport();
597
+ this.isRendered = true;
598
+ this.dirtyFlags.clear();
340
599
  }
341
600
  /**
342
601
  * Hovers the row with the provided index. It removes the hover effect from
@@ -485,7 +744,7 @@ class Grid {
485
744
  renderViewport() {
486
745
  const viewportMeta = this.viewport?.getStateMeta();
487
746
  const pagination = this.pagination;
488
- const paginationPosition = pagination?.options.position;
747
+ const paginationPosition = pagination?.options?.position;
489
748
  this.enabledColumns = this.getEnabledColumnIDs();
490
749
  this.credits?.destroy();
491
750
  this.viewport?.destroy();
@@ -569,6 +828,7 @@ class Grid {
569
828
  * reference, it should be used instead of creating a new one.
570
829
  */
571
830
  loadDataTable() {
831
+ this.querying.shouldBeUpdated = true;
572
832
  // Unregister all events attached to the previous data table.
573
833
  this.dataTableEventDestructors.forEach((fn) => fn());
574
834
  const tableOptions = this.options?.dataTable;
@@ -623,15 +883,26 @@ class Grid {
623
883
  }
624
884
  /**
625
885
  * Destroys the Grid.
886
+ *
887
+ * @param onlyDOM
888
+ * Whether to destroy the Grid instance completely (`false` - default) or
889
+ * just the DOM elements (`true`). If `true`, the Grid can be re-rendered
890
+ * after destruction by calling the `render` method.
626
891
  */
627
- destroy() {
892
+ destroy(onlyDOM = false) {
893
+ this.isRendered = false;
628
894
  const dgIndex = Grid.grids.findIndex((dg) => dg === this);
629
895
  this.dataTableEventDestructors.forEach((fn) => fn());
896
+ this.accessibility?.destroy();
897
+ this.pagination?.destroy();
630
898
  this.viewport?.destroy();
631
899
  if (this.container) {
632
900
  this.container.innerHTML = AST.emptyHTML;
633
901
  this.container.classList.remove(Globals.getClassName('container'));
634
902
  }
903
+ if (onlyDOM) {
904
+ return;
905
+ }
635
906
  // Clear all properties
636
907
  Object.keys(this).forEach((key) => {
637
908
  delete this[key];
@@ -680,17 +951,36 @@ class Grid {
680
951
  * JSON representation of the data
681
952
  */
682
953
  getData(modified = true) {
683
- const dataTable = modified ? this.viewport?.dataTable : this.dataTable;
684
- const columns = dataTable?.columns;
685
- if (!this.enabledColumns || !columns) {
954
+ const dataTable = modified ? this.presentationTable : this.dataTable;
955
+ const tableColumns = dataTable?.columns;
956
+ const outputColumns = {};
957
+ if (!this.enabledColumns || !tableColumns) {
686
958
  return '{}';
687
959
  }
688
- for (const key of Object.keys(columns)) {
689
- if (this.enabledColumns.indexOf(key) === -1) {
690
- delete columns[key];
960
+ const typeParser = (type) => {
961
+ const TypeMap = {
962
+ number: Number,
963
+ datetime: Number,
964
+ string: String,
965
+ 'boolean': Boolean
966
+ };
967
+ return (value) => (defined(value) ? TypeMap[type](value) : null);
968
+ };
969
+ for (const columnId of Object.keys(tableColumns)) {
970
+ const column = this.viewport?.getColumn(columnId);
971
+ if (column) {
972
+ const columnData = tableColumns[columnId];
973
+ const parser = typeParser(column.dataType);
974
+ outputColumns[columnId] = (() => {
975
+ const result = [];
976
+ for (let i = 0, iEnd = columnData.length; i < iEnd; ++i) {
977
+ result.push(parser(columnData[i]));
978
+ }
979
+ return result;
980
+ })();
691
981
  }
692
982
  }
693
- return JSON.stringify(columns, null, 2);
983
+ return JSON.stringify(outputColumns, null, 2);
694
984
  }
695
985
  /**
696
986
  * Returns the current Grid options.