handsontable 0.0.0-next-18219cd-20241217 → 0.0.0-next-eafbc4a-20241217

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.

Potentially problematic release.


This version of handsontable might be problematic. Click here for more details.

Files changed (57) hide show
  1. package/3rdparty/walkontable/src/index.js +2 -0
  2. package/3rdparty/walkontable/src/index.mjs +2 -1
  3. package/3rdparty/walkontable/src/renderer/_base.js +3 -4
  4. package/3rdparty/walkontable/src/renderer/_base.mjs +2 -2
  5. package/3rdparty/walkontable/src/renderer/cells.js +6 -10
  6. package/3rdparty/walkontable/src/renderer/cells.mjs +5 -8
  7. package/3rdparty/walkontable/src/renderer/colGroup.js +6 -7
  8. package/3rdparty/walkontable/src/renderer/colGroup.mjs +5 -5
  9. package/3rdparty/walkontable/src/renderer/columnHeaders.js +4 -5
  10. package/3rdparty/walkontable/src/renderer/columnHeaders.mjs +3 -3
  11. package/3rdparty/walkontable/src/renderer/index.js +18 -19
  12. package/3rdparty/walkontable/src/renderer/index.mjs +6 -6
  13. package/3rdparty/walkontable/src/renderer/rowHeaders.js +5 -6
  14. package/3rdparty/walkontable/src/renderer/rowHeaders.mjs +4 -4
  15. package/3rdparty/walkontable/src/renderer/rows.js +23 -11
  16. package/3rdparty/walkontable/src/renderer/rows.mjs +23 -10
  17. package/3rdparty/walkontable/src/renderer/table.js +1 -1
  18. package/3rdparty/walkontable/src/renderer/table.mjs +1 -1
  19. package/3rdparty/walkontable/src/utils/nodesPool.js +21 -6
  20. package/3rdparty/walkontable/src/utils/nodesPool.mjs +21 -6
  21. package/3rdparty/walkontable/src/utils/orderView/index.js +4 -5
  22. package/3rdparty/walkontable/src/utils/orderView/index.mjs +2 -2
  23. package/3rdparty/walkontable/src/utils/orderView/sharedView.js +3 -4
  24. package/3rdparty/walkontable/src/utils/orderView/sharedView.mjs +2 -2
  25. package/3rdparty/walkontable/src/utils/orderView/view.js +60 -76
  26. package/3rdparty/walkontable/src/utils/orderView/view.mjs +59 -74
  27. package/3rdparty/walkontable/src/utils/orderView/viewDiffer/index.js +138 -0
  28. package/3rdparty/walkontable/src/utils/orderView/viewDiffer/index.mjs +135 -0
  29. package/3rdparty/walkontable/src/utils/orderView/viewDiffer/viewOrder.js +72 -0
  30. package/3rdparty/walkontable/src/utils/orderView/viewDiffer/viewOrder.mjs +68 -0
  31. package/3rdparty/walkontable/src/utils/orderView/viewSize.js +1 -1
  32. package/3rdparty/walkontable/src/utils/orderView/viewSize.mjs +1 -1
  33. package/3rdparty/walkontable/src/utils/orderView/viewSizeSet.js +4 -5
  34. package/3rdparty/walkontable/src/utils/orderView/viewSizeSet.mjs +3 -3
  35. package/base.js +2 -2
  36. package/base.mjs +2 -2
  37. package/dist/handsontable.css +2 -2
  38. package/dist/handsontable.full.css +2 -2
  39. package/dist/handsontable.full.js +1968 -1730
  40. package/dist/handsontable.full.min.css +2 -2
  41. package/dist/handsontable.full.min.js +8 -8
  42. package/dist/handsontable.js +1970 -1732
  43. package/dist/handsontable.min.css +2 -2
  44. package/dist/handsontable.min.js +15 -15
  45. package/helpers/mixed.js +1 -1
  46. package/helpers/mixed.mjs +1 -1
  47. package/package.json +1 -1
  48. package/plugins/nestedRows/utils/rowMoveController.js +1 -6
  49. package/plugins/nestedRows/utils/rowMoveController.mjs +1 -6
  50. package/styles/handsontable.css +2 -2
  51. package/styles/handsontable.min.css +2 -2
  52. package/styles/ht-theme-horizon.css +2 -2
  53. package/styles/ht-theme-horizon.min.css +2 -2
  54. package/styles/ht-theme-main.css +2 -2
  55. package/styles/ht-theme-main.min.css +2 -2
  56. package/tableView.js +17 -1
  57. package/tableView.mjs +17 -1
@@ -7,32 +7,47 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
7
7
  *
8
8
  * @class {NodesPool}
9
9
  */
10
- export default class NodesPool {
10
+ export class NodesPool {
11
11
  constructor(nodeType) {
12
12
  /**
13
- * Node type to generate (ew 'th', 'td').
13
+ * Node type to generate (e.g. 'TH', 'TD').
14
14
  *
15
15
  * @type {string}
16
16
  */
17
17
  _defineProperty(this, "nodeType", void 0);
18
+ /**
19
+ * The holder for all created DOM nodes (THs, TDs).
20
+ *
21
+ * @type {Map<string, HTMLElement>}
22
+ */
23
+ _defineProperty(this, "pool", new Map());
18
24
  this.nodeType = nodeType.toUpperCase();
19
25
  }
20
26
 
21
27
  /**
22
28
  * Set document owner for this instance.
23
29
  *
24
- * @param {HTMLDocument} rootDocument The document window owner.
30
+ * @param {Document} rootDocument The document window owner.
25
31
  */
26
32
  setRootDocument(rootDocument) {
27
33
  this.rootDocument = rootDocument;
28
34
  }
29
35
 
30
36
  /**
31
- * Obtains an element. The returned elements in the feature can be cached.
37
+ * Obtains an element.
32
38
  *
39
+ * @param {number} rowIndex The row index.
40
+ * @param {number} [columnIndex] The column index.
33
41
  * @returns {HTMLElement}
34
42
  */
35
- obtain() {
36
- return this.rootDocument.createElement(this.nodeType);
43
+ obtain(rowIndex, columnIndex) {
44
+ const hasColumnIndex = typeof columnIndex === 'number';
45
+ const key = hasColumnIndex ? `${rowIndex}x${columnIndex}` : rowIndex.toString();
46
+ if (this.pool.has(key)) {
47
+ return this.pool.get(key);
48
+ }
49
+ const node = this.rootDocument.createElement(this.nodeType);
50
+ this.pool.set(key, node);
51
+ return node;
37
52
  }
38
53
  }
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- var _view = _interopRequireDefault(require("./view"));
5
- exports.OrderView = _view.default;
6
- var _sharedView = _interopRequireDefault(require("./sharedView"));
7
- exports.SharedOrderView = _sharedView.default;
8
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
4
+ var _view = require("./view");
5
+ exports.OrderView = _view.OrderView;
6
+ var _sharedView = require("./sharedView");
7
+ exports.SharedOrderView = _sharedView.SharedOrderView;
@@ -1,3 +1,3 @@
1
- import OrderView from "./view.mjs";
2
- import SharedOrderView from "./sharedView.mjs";
1
+ import { OrderView } from "./view.mjs";
2
+ import { SharedOrderView } from "./sharedView.mjs";
3
3
  export { OrderView, SharedOrderView };
@@ -1,14 +1,13 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- var _view = _interopRequireDefault(require("./view"));
5
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
4
+ var _view = require("./view");
6
5
  /**
7
6
  * Executive model for TR root nodes.
8
7
  *
9
8
  * @class {SharedOrderView}
10
9
  */
11
- class SharedOrderView extends _view.default {
10
+ class SharedOrderView extends _view.OrderView {
12
11
  /**
13
12
  * The method results in merging external order view into the current order. This happens only for order views which
14
13
  * operate on the same root node.
@@ -43,4 +42,4 @@ class SharedOrderView extends _view.default {
43
42
  return this;
44
43
  }
45
44
  }
46
- exports.default = SharedOrderView;
45
+ exports.SharedOrderView = SharedOrderView;
@@ -1,10 +1,10 @@
1
- import OrderView from "./view.mjs";
1
+ import { OrderView } from "./view.mjs";
2
2
  /**
3
3
  * Executive model for TR root nodes.
4
4
  *
5
5
  * @class {SharedOrderView}
6
6
  */
7
- export default class SharedOrderView extends OrderView {
7
+ export class SharedOrderView extends OrderView {
8
8
  /**
9
9
  * The method results in merging external order view into the current order. This happens only for order views which
10
10
  * operate on the same root node.
@@ -3,9 +3,8 @@
3
3
  exports.__esModule = true;
4
4
  require("core-js/modules/es.error.cause.js");
5
5
  require("core-js/modules/es.array.push.js");
6
- var _constants = require("./constants");
7
- var _viewSizeSet = _interopRequireDefault(require("./viewSizeSet"));
8
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
6
+ var _viewSizeSet = require("./viewSizeSet");
7
+ var _viewDiffer = require("./viewDiffer");
9
8
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
10
9
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
11
10
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
@@ -18,7 +17,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
18
17
  * @class {OrderView}
19
18
  */
20
19
  class OrderView {
21
- constructor(rootNode, nodesPool, childNodeType) {
20
+ constructor(rootNode, nodesPool) {
22
21
  /**
23
22
  * The root node to manage with.
24
23
  *
@@ -28,7 +27,7 @@ class OrderView {
28
27
  /**
29
28
  * Factory for newly created DOM elements.
30
29
  *
31
- * @type {Function}
30
+ * @type {function(number): HTMLElement}
32
31
  */
33
32
  _defineProperty(this, "nodesPool", void 0);
34
33
  /**
@@ -36,28 +35,37 @@ class OrderView {
36
35
  *
37
36
  * @type {ViewSizeSet}
38
37
  */
39
- _defineProperty(this, "sizeSet", new _viewSizeSet.default());
38
+ _defineProperty(this, "sizeSet", new _viewSizeSet.ViewSizeSet());
40
39
  /**
41
- * Node type which the order view will manage while rendering the DOM elements.
40
+ * The list of DOM elements which are rendered for this render cycle.
42
41
  *
43
- * @type {string}
42
+ * @type {HTMLElement[]}
44
43
  */
45
- _defineProperty(this, "childNodeType", void 0);
44
+ _defineProperty(this, "collectedNodes", []);
46
45
  /**
47
- * The visual index of currently processed row.
46
+ * The differ which calculates the differences between current and next view. It generates
47
+ * commands that are processed by the OrderView (see `applyCommand` method).
48
48
  *
49
- * @type {number}
49
+ * @type {ViewDiffer}
50
50
  */
51
- _defineProperty(this, "visualIndex", 0);
51
+ _defineProperty(this, "viewDiffer", new _viewDiffer.ViewDiffer(this.sizeSet));
52
52
  /**
53
- * The list of DOM elements which are rendered for this render cycle.
53
+ * The list of render commands to execute. The command is an array with the following
54
+ * structure: [
55
+ * [
56
+ * 'prepend' | 'append' | 'insert_before' | 'replace' | 'remove', // command name
57
+ * 10, // processed node index
58
+ * 9, // previous node index (only for 'insert_before' and 'replace' commands)
59
+ * 8 // node index to remove (only for 'insert_before' command)
60
+ * ],
61
+ * ...
62
+ * ].
54
63
  *
55
- * @type {HTMLElement[]}
64
+ * @type {Array[]}
56
65
  */
57
- _defineProperty(this, "collectedNodes", []);
66
+ _defineProperty(this, "leads", []);
58
67
  this.rootNode = rootNode;
59
68
  this.nodesPool = nodesPool;
60
- this.childNodeType = childNodeType.toUpperCase();
61
69
  }
62
70
 
63
71
  /**
@@ -116,30 +124,38 @@ class OrderView {
116
124
  }
117
125
 
118
126
  /**
119
- * Returns rendered child count for this instance.
127
+ * Applies the commands generated by the differ into the specific DOM operations.
120
128
  *
121
- * @returns {number}
129
+ * @param {Array} command The command to apply.
122
130
  */
123
- getRenderedChildCount() {
131
+ applyCommand(command) {
124
132
  const {
125
- rootNode,
126
- sizeSet
133
+ rootNode
127
134
  } = this;
128
- let childElementCount = 0;
129
- if (this.isSharedViewSet()) {
130
- let element = rootNode.firstElementChild;
131
- while (element) {
132
- if (element.tagName === this.childNodeType) {
133
- childElementCount += 1;
134
- } else if (sizeSet.isPlaceOn(_constants.WORKING_SPACE_TOP)) {
135
- break;
136
- }
137
- element = element.nextElementSibling;
138
- }
139
- } else {
140
- childElementCount = rootNode.childElementCount;
135
+ const [name, nodeIndex, nodePrevIndex, nodeIndexToRemove] = command;
136
+ const node = this.nodesPool(nodeIndex);
137
+ this.collectedNodes.push(node);
138
+ switch (name) {
139
+ case 'prepend':
140
+ rootNode.insertBefore(node, rootNode.firstChild);
141
+ break;
142
+ case 'append':
143
+ rootNode.appendChild(node);
144
+ break;
145
+ case 'insert_before':
146
+ rootNode.insertBefore(node, this.nodesPool(nodePrevIndex));
147
+ // To keep the constant length of child nodes (after inserting a node) remove the last child.
148
+ rootNode.removeChild(this.nodesPool(nodeIndexToRemove));
149
+ break;
150
+ case 'replace':
151
+ rootNode.replaceChild(node, this.nodesPool(nodePrevIndex));
152
+ break;
153
+ case 'remove':
154
+ rootNode.removeChild(node);
155
+ break;
156
+ default:
157
+ break;
141
158
  }
142
- return childElementCount;
143
159
  }
144
160
 
145
161
  /**
@@ -148,30 +164,7 @@ class OrderView {
148
164
  */
149
165
  start() {
150
166
  this.collectedNodes.length = 0;
151
- this.visualIndex = 0;
152
- const {
153
- rootNode,
154
- sizeSet
155
- } = this;
156
- const isShared = this.isSharedViewSet();
157
- const {
158
- nextSize
159
- } = sizeSet.getViewSize();
160
- let childElementCount = this.getRenderedChildCount();
161
- while (childElementCount < nextSize) {
162
- const newNode = this.nodesPool();
163
- if (!isShared || isShared && sizeSet.isPlaceOn(_constants.WORKING_SPACE_BOTTOM)) {
164
- rootNode.appendChild(newNode);
165
- } else {
166
- rootNode.insertBefore(newNode, rootNode.firstChild);
167
- }
168
- childElementCount += 1;
169
- }
170
- const isSharedPlacedOnTop = isShared && sizeSet.isPlaceOn(_constants.WORKING_SPACE_TOP);
171
- while (childElementCount > nextSize) {
172
- rootNode.removeChild(isSharedPlacedOnTop ? rootNode.firstChild : rootNode.lastChild);
173
- childElementCount -= 1;
174
- }
167
+ this.leads = this.viewDiffer.diff();
175
168
  }
176
169
 
177
170
  /**
@@ -179,28 +172,19 @@ class OrderView {
179
172
  * This method has to be called as many times as the size count is met (to cover all previously rendered DOM elements).
180
173
  */
181
174
  render() {
182
- const {
183
- rootNode,
184
- sizeSet
185
- } = this;
186
- let visualIndex = this.visualIndex;
187
- if (this.isSharedViewSet() && sizeSet.isPlaceOn(_constants.WORKING_SPACE_BOTTOM)) {
188
- visualIndex += sizeSet.sharedSize.nextSize;
175
+ if (this.leads.length > 0) {
176
+ this.applyCommand(this.leads.shift());
189
177
  }
190
- let node = rootNode.childNodes[visualIndex];
191
- if (node.tagName !== this.childNodeType) {
192
- const newNode = this.nodesPool();
193
- rootNode.replaceChild(newNode, node);
194
- node = newNode;
195
- }
196
- this.collectedNodes.push(node);
197
- this.visualIndex += 1;
198
178
  }
199
179
 
200
180
  /**
201
181
  * Ends the render process.
202
182
  * This method has to be called only once (at the end) for the render cycle.
203
183
  */
204
- end() {}
184
+ end() {
185
+ while (this.leads.length > 0) {
186
+ this.applyCommand(this.leads.shift());
187
+ }
188
+ }
205
189
  }
206
- exports.default = OrderView;
190
+ exports.OrderView = OrderView;
@@ -3,8 +3,8 @@ import "core-js/modules/es.array.push.js";
3
3
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
4
4
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
5
5
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
6
- import { WORKING_SPACE_TOP, WORKING_SPACE_BOTTOM } from "./constants.mjs";
7
- import ViewSizeSet from "./viewSizeSet.mjs";
6
+ import { ViewSizeSet } from "./viewSizeSet.mjs";
7
+ import { ViewDiffer } from "./viewDiffer/index.mjs";
8
8
  /**
9
9
  * Executive model for each table renderer. It's responsible for injecting DOM nodes in a
10
10
  * specified order and adjusting the number of elements in the root node.
@@ -13,8 +13,8 @@ import ViewSizeSet from "./viewSizeSet.mjs";
13
13
  *
14
14
  * @class {OrderView}
15
15
  */
16
- export default class OrderView {
17
- constructor(rootNode, nodesPool, childNodeType) {
16
+ export class OrderView {
17
+ constructor(rootNode, nodesPool) {
18
18
  /**
19
19
  * The root node to manage with.
20
20
  *
@@ -24,7 +24,7 @@ export default class OrderView {
24
24
  /**
25
25
  * Factory for newly created DOM elements.
26
26
  *
27
- * @type {Function}
27
+ * @type {function(number): HTMLElement}
28
28
  */
29
29
  _defineProperty(this, "nodesPool", void 0);
30
30
  /**
@@ -34,26 +34,35 @@ export default class OrderView {
34
34
  */
35
35
  _defineProperty(this, "sizeSet", new ViewSizeSet());
36
36
  /**
37
- * Node type which the order view will manage while rendering the DOM elements.
37
+ * The list of DOM elements which are rendered for this render cycle.
38
38
  *
39
- * @type {string}
39
+ * @type {HTMLElement[]}
40
40
  */
41
- _defineProperty(this, "childNodeType", void 0);
41
+ _defineProperty(this, "collectedNodes", []);
42
42
  /**
43
- * The visual index of currently processed row.
43
+ * The differ which calculates the differences between current and next view. It generates
44
+ * commands that are processed by the OrderView (see `applyCommand` method).
44
45
  *
45
- * @type {number}
46
+ * @type {ViewDiffer}
46
47
  */
47
- _defineProperty(this, "visualIndex", 0);
48
+ _defineProperty(this, "viewDiffer", new ViewDiffer(this.sizeSet));
48
49
  /**
49
- * The list of DOM elements which are rendered for this render cycle.
50
+ * The list of render commands to execute. The command is an array with the following
51
+ * structure: [
52
+ * [
53
+ * 'prepend' | 'append' | 'insert_before' | 'replace' | 'remove', // command name
54
+ * 10, // processed node index
55
+ * 9, // previous node index (only for 'insert_before' and 'replace' commands)
56
+ * 8 // node index to remove (only for 'insert_before' command)
57
+ * ],
58
+ * ...
59
+ * ].
50
60
  *
51
- * @type {HTMLElement[]}
61
+ * @type {Array[]}
52
62
  */
53
- _defineProperty(this, "collectedNodes", []);
63
+ _defineProperty(this, "leads", []);
54
64
  this.rootNode = rootNode;
55
65
  this.nodesPool = nodesPool;
56
- this.childNodeType = childNodeType.toUpperCase();
57
66
  }
58
67
 
59
68
  /**
@@ -112,30 +121,38 @@ export default class OrderView {
112
121
  }
113
122
 
114
123
  /**
115
- * Returns rendered child count for this instance.
124
+ * Applies the commands generated by the differ into the specific DOM operations.
116
125
  *
117
- * @returns {number}
126
+ * @param {Array} command The command to apply.
118
127
  */
119
- getRenderedChildCount() {
128
+ applyCommand(command) {
120
129
  const {
121
- rootNode,
122
- sizeSet
130
+ rootNode
123
131
  } = this;
124
- let childElementCount = 0;
125
- if (this.isSharedViewSet()) {
126
- let element = rootNode.firstElementChild;
127
- while (element) {
128
- if (element.tagName === this.childNodeType) {
129
- childElementCount += 1;
130
- } else if (sizeSet.isPlaceOn(WORKING_SPACE_TOP)) {
131
- break;
132
- }
133
- element = element.nextElementSibling;
134
- }
135
- } else {
136
- childElementCount = rootNode.childElementCount;
132
+ const [name, nodeIndex, nodePrevIndex, nodeIndexToRemove] = command;
133
+ const node = this.nodesPool(nodeIndex);
134
+ this.collectedNodes.push(node);
135
+ switch (name) {
136
+ case 'prepend':
137
+ rootNode.insertBefore(node, rootNode.firstChild);
138
+ break;
139
+ case 'append':
140
+ rootNode.appendChild(node);
141
+ break;
142
+ case 'insert_before':
143
+ rootNode.insertBefore(node, this.nodesPool(nodePrevIndex));
144
+ // To keep the constant length of child nodes (after inserting a node) remove the last child.
145
+ rootNode.removeChild(this.nodesPool(nodeIndexToRemove));
146
+ break;
147
+ case 'replace':
148
+ rootNode.replaceChild(node, this.nodesPool(nodePrevIndex));
149
+ break;
150
+ case 'remove':
151
+ rootNode.removeChild(node);
152
+ break;
153
+ default:
154
+ break;
137
155
  }
138
- return childElementCount;
139
156
  }
140
157
 
141
158
  /**
@@ -144,30 +161,7 @@ export default class OrderView {
144
161
  */
145
162
  start() {
146
163
  this.collectedNodes.length = 0;
147
- this.visualIndex = 0;
148
- const {
149
- rootNode,
150
- sizeSet
151
- } = this;
152
- const isShared = this.isSharedViewSet();
153
- const {
154
- nextSize
155
- } = sizeSet.getViewSize();
156
- let childElementCount = this.getRenderedChildCount();
157
- while (childElementCount < nextSize) {
158
- const newNode = this.nodesPool();
159
- if (!isShared || isShared && sizeSet.isPlaceOn(WORKING_SPACE_BOTTOM)) {
160
- rootNode.appendChild(newNode);
161
- } else {
162
- rootNode.insertBefore(newNode, rootNode.firstChild);
163
- }
164
- childElementCount += 1;
165
- }
166
- const isSharedPlacedOnTop = isShared && sizeSet.isPlaceOn(WORKING_SPACE_TOP);
167
- while (childElementCount > nextSize) {
168
- rootNode.removeChild(isSharedPlacedOnTop ? rootNode.firstChild : rootNode.lastChild);
169
- childElementCount -= 1;
170
- }
164
+ this.leads = this.viewDiffer.diff();
171
165
  }
172
166
 
173
167
  /**
@@ -175,27 +169,18 @@ export default class OrderView {
175
169
  * This method has to be called as many times as the size count is met (to cover all previously rendered DOM elements).
176
170
  */
177
171
  render() {
178
- const {
179
- rootNode,
180
- sizeSet
181
- } = this;
182
- let visualIndex = this.visualIndex;
183
- if (this.isSharedViewSet() && sizeSet.isPlaceOn(WORKING_SPACE_BOTTOM)) {
184
- visualIndex += sizeSet.sharedSize.nextSize;
172
+ if (this.leads.length > 0) {
173
+ this.applyCommand(this.leads.shift());
185
174
  }
186
- let node = rootNode.childNodes[visualIndex];
187
- if (node.tagName !== this.childNodeType) {
188
- const newNode = this.nodesPool();
189
- rootNode.replaceChild(newNode, node);
190
- node = newNode;
191
- }
192
- this.collectedNodes.push(node);
193
- this.visualIndex += 1;
194
175
  }
195
176
 
196
177
  /**
197
178
  * Ends the render process.
198
179
  * This method has to be called only once (at the end) for the render cycle.
199
180
  */
200
- end() {}
181
+ end() {
182
+ while (this.leads.length > 0) {
183
+ this.applyCommand(this.leads.shift());
184
+ }
185
+ }
201
186
  }
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ require("core-js/modules/es.error.cause.js");
5
+ require("core-js/modules/es.array.push.js");
6
+ var _constants = require("../constants");
7
+ var _viewOrder = require("./viewOrder");
8
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
9
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
10
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* eslint-disable jsdoc/require-description-complete-sentence */
11
+ /**
12
+ * A class which is responsible for generating commands/leads which has to be executed
13
+ * to achieve new DOM nodes order.
14
+ *
15
+ * @class {ViewDiffer}
16
+ */
17
+ class ViewDiffer {
18
+ constructor(sizeSet) {
19
+ _defineProperty(this, "sizeSet", void 0);
20
+ this.sizeSet = sizeSet;
21
+ }
22
+
23
+ /**
24
+ * A method which generates commands/leads which has to be executed to achieve new DOM
25
+ * nodes order based on new offset and view size.
26
+ *
27
+ * For example, if current order looks like this (offset = 0, viewSize = 1):
28
+ * <body> (root node)
29
+ * └ <tr> (row 0)
30
+ * and next order should look like this (offset: 0, viewSize = 5):
31
+ * <body> (root node)
32
+ * ├ <tr> (row 0)
33
+ * ├ <tr> (row 1)
34
+ * ├ <tr> (row 2)
35
+ * ├ <tr> (row 3)
36
+ * └ <tr> (row 4)
37
+ * the generated commands/leads will look like this:
38
+ * <body> (root node)
39
+ * ├ <tr> (none, do nothing, leave as it is)
40
+ * ├ <tr> (append this element at index 1)
41
+ * ├ <tr> (append this element at index 2)
42
+ * ├ <tr> (append this element at index 3)
43
+ * └ <tr> (append this element at index 4)
44
+ *
45
+ * @returns {Array[]} Returns an array with generated commands/leads.
46
+ */
47
+ diff() {
48
+ const {
49
+ sizeSet
50
+ } = this;
51
+ const {
52
+ currentSize: currentViewSize,
53
+ nextSize: nextViewSize
54
+ } = sizeSet.getViewSize();
55
+ let maxSize = Math.max(nextViewSize, currentViewSize);
56
+ if (maxSize === 0) {
57
+ return [];
58
+ }
59
+ const {
60
+ currentOffset,
61
+ nextOffset
62
+ } = sizeSet.getViewSize();
63
+
64
+ // @TODO(perf-tip): Creating an array (createRange) is not necessary it would be enough to generate
65
+ // commands based on numeric values.
66
+ const currentViewOrder = new _viewOrder.ViewOrder(currentOffset, currentViewSize);
67
+ const nextViewOrder = new _viewOrder.ViewOrder(nextOffset, nextViewSize);
68
+ const leads = [];
69
+ for (let i = 0; i < maxSize; i++) {
70
+ const currentIndex = currentViewOrder.get(i);
71
+ const nextIndex = nextViewOrder.get(i);
72
+
73
+ // Current index exceeds the next DOM index so it is necessary to generate a "remove" command
74
+ // to achieve new order.
75
+ if (nextIndex === -1) {
76
+ leads.push(['remove', currentIndex]);
77
+
78
+ // Next index exceeds the current DOM index so it is necessary to generate a "append" command
79
+ // to achieve new order.
80
+ } else if (currentIndex === -1) {
81
+ // Check what command should be generated (depends on if this work as a shared root node
82
+ // and in what position or not)
83
+ if (!sizeSet.isShared() || sizeSet.isShared() && sizeSet.isPlaceOn(_constants.WORKING_SPACE_BOTTOM)) {
84
+ /**
85
+ * If the differ has only one root node to manage with, the "append" command is generated.
86
+ *
87
+ * For example:
88
+ * ┌─────────── <body> (root node)
89
+ * │ <tr>
90
+ * │ <tr>
91
+ * (managed by one <tr>
92
+ * differ - TRs) <tr>
93
+ * │ <tr>
94
+ * └─────────── <tr> <--- Generates "append" command (which later executes `rootNode.appendChild(node)`)
95
+ */
96
+ leads.push(['append', nextIndex]);
97
+ } else {
98
+ /**
99
+ * If the differ is sharing root node, the "prepend" command is generated.
100
+ *
101
+ * For example:
102
+ * ┌─────────── <tr> (root node, shared between two differs)
103
+ * (first differ) <th> <--- Generates "prepend" command (which later executes `rootNode.insertBefore(...)`)
104
+ * ├─────────── <td>
105
+ * │ <td>
106
+ * (second differ <td>
107
+ * - TDs) <td>
108
+ * │ <td>
109
+ * └─────────── <td>
110
+ */
111
+ leads.push(['prepend', nextIndex]);
112
+ }
113
+ } else if (nextIndex > currentIndex) {
114
+ // This emulates DOM behavior when we try to append (or replace) an element which is already
115
+ // mounted. The old index in the array has to be popped out indicating that an element was
116
+ // moved to a different position.
117
+ if (currentViewOrder.has(nextIndex)) {
118
+ currentViewOrder.remove(nextIndex);
119
+
120
+ // Decrease loop size to prevent generating "remove" leads. "remove" leads are necessary only for nodes
121
+ // which are not mounted in current DOM order.
122
+ if (nextViewSize <= currentViewOrder.length) {
123
+ maxSize -= 1;
124
+ }
125
+ }
126
+ leads.push(['replace', nextIndex, currentIndex]);
127
+ } else if (nextIndex < currentIndex) {
128
+ const indexToRemove = currentViewOrder.prepend(nextIndex);
129
+ leads.push(['insert_before', nextIndex, currentIndex, indexToRemove]);
130
+ } else {
131
+ // for the same current and next indexes do nothing.
132
+ leads.push(['none', nextIndex]);
133
+ }
134
+ }
135
+ return leads;
136
+ }
137
+ }
138
+ exports.ViewDiffer = ViewDiffer;