@plcmp/pl-virtual-scroll 1.0.6 → 1.0.7
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.
- package/package.json +1 -1
- package/pl-virtual-scroll.js +32 -28
package/package.json
CHANGED
package/pl-virtual-scroll.js
CHANGED
|
@@ -64,7 +64,7 @@ class PlVirtualScroll extends PlElement {
|
|
|
64
64
|
|
|
65
65
|
this.canvas = this.canvas ?? this.$.vsCanvas;
|
|
66
66
|
this.canvas.parentNode.addEventListener('scroll', e => this.onScroll(e));
|
|
67
|
-
|
|
67
|
+
const tplEl = [...this.childNodes].find(n => n.nodeType === document.COMMENT_NODE && n.textContent.startsWith('tpl:'));
|
|
68
68
|
this.sTpl = tplEl?._tpl;
|
|
69
69
|
this._hctx = tplEl?._hctx;
|
|
70
70
|
}
|
|
@@ -72,27 +72,31 @@ class PlVirtualScroll extends PlElement {
|
|
|
72
72
|
_dataChanged(data, old, /** DataMutation */ mutation) {
|
|
73
73
|
// set microtask, element may be not inserted in dom tree yet,
|
|
74
74
|
// but we need to know viewport height to render
|
|
75
|
-
|
|
75
|
+
const [, index, ...rest] = normalizePath(mutation.path);
|
|
76
76
|
switch (mutation.action) {
|
|
77
77
|
case 'upd':
|
|
78
78
|
if (mutation.path === 'items' && Array.isArray(mutation.value) && Array.isArray(mutation.oldValue)) {
|
|
79
79
|
this.phyPool.forEach((i) => {
|
|
80
|
-
if (i.index !== null
|
|
81
|
-
if (
|
|
80
|
+
if (i.index !== null) {
|
|
81
|
+
if (i.index < this.items.length) {
|
|
82
|
+
if (this.items[i.index] instanceof PlaceHolder) this.items.load?.(this.items[i.index]);
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
i.ctx.replace(this.items[i.index]);
|
|
85
|
+
i.ctx.applyEffects(undefined);
|
|
86
|
+
i.ctx._ti.applyBinds();
|
|
87
|
+
} else {
|
|
88
|
+
i.index = null;
|
|
89
|
+
i.offset = -10000;
|
|
90
|
+
fixOffset(i);
|
|
91
|
+
}
|
|
88
92
|
}
|
|
89
93
|
});
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
if (index !== undefined && +index >= 0) {
|
|
93
|
-
|
|
97
|
+
const el = this.phyPool.find(i => i.index === +index);
|
|
94
98
|
if (el && rest.length > 0) {
|
|
95
|
-
|
|
99
|
+
const path = [this.as, ...rest].join('.');
|
|
96
100
|
el.ctx.applyEffects({ ...mutation, path });
|
|
97
101
|
if (this.items[el.index] instanceof PlaceHolder) this.items.load?.(this.items[el.index]);
|
|
98
102
|
}
|
|
@@ -106,8 +110,8 @@ class PlVirtualScroll extends PlElement {
|
|
|
106
110
|
if (Number(spliceIndex) >= 0) {
|
|
107
111
|
// if mutation is not root try to apply effects to children (need when pushing to array inside array)
|
|
108
112
|
if (rest.length > 0) {
|
|
109
|
-
|
|
110
|
-
this.phyPool[index].ctx.applyEffects({...mutation, path});
|
|
113
|
+
const path = [this.as, ...rest].join('.');
|
|
114
|
+
this.phyPool[index].ctx.applyEffects({ ...mutation, path });
|
|
111
115
|
} else {
|
|
112
116
|
this.phyPool.forEach((i) => {
|
|
113
117
|
if (i.index !== null && i.index >= spliceIndex && i.index < this.items.length) {
|
|
@@ -138,7 +142,7 @@ class PlVirtualScroll extends PlElement {
|
|
|
138
142
|
|
|
139
143
|
render() {
|
|
140
144
|
const canvas = this.canvas;
|
|
141
|
-
|
|
145
|
+
const visibleStart = canvas.parentNode.scrollTop,
|
|
142
146
|
height = canvas.parentNode.offsetHeight,
|
|
143
147
|
visibleEnd = visibleStart + height,
|
|
144
148
|
// render cant complete on too small window, set minimal shadow window
|
|
@@ -163,7 +167,7 @@ class PlVirtualScroll extends PlElement {
|
|
|
163
167
|
|
|
164
168
|
// check items height and offset
|
|
165
169
|
if (this.variableRowHeight) {
|
|
166
|
-
|
|
170
|
+
const firstVisible = used.findIndex(i => i.offset >= visibleStart && i.offset < visibleEnd);
|
|
167
171
|
if (firstVisible >= 0) {
|
|
168
172
|
// fix forward
|
|
169
173
|
for (let i = firstVisible + 1; i < used.length && used[i].offset < shadowEnd; i++) {
|
|
@@ -198,16 +202,16 @@ class PlVirtualScroll extends PlElement {
|
|
|
198
202
|
}
|
|
199
203
|
// filter
|
|
200
204
|
|
|
201
|
-
|
|
205
|
+
const unused = this.phyPool.filter(i => i.index === null);
|
|
202
206
|
|
|
203
207
|
let firstShadow = used.find(i => i.offset + i.h > shadowStart && i.offset < shadowEnd);
|
|
204
208
|
let lastShadow = used.findLast(i => i.offset < shadowEnd && i.offset + i.h > shadowStart);
|
|
205
209
|
|
|
206
210
|
if (!firstShadow && !lastShadow) {
|
|
207
211
|
// jump to nowhere,
|
|
208
|
-
if (this.canvas.parentNode.scrollTop === 0)
|
|
212
|
+
if (this.canvas.parentNode.scrollTop === 0) {
|
|
209
213
|
firstShadow = lastShadow = this.renderItem(0, unused.pop());
|
|
210
|
-
else {
|
|
214
|
+
} else {
|
|
211
215
|
const heightForStart
|
|
212
216
|
= this.phyPool.length > 0
|
|
213
217
|
? this.phyPool.reduce((a, i) => a + i.h, 0) / this.phyPool.length
|
|
@@ -294,7 +298,7 @@ class PlVirtualScroll extends PlElement {
|
|
|
294
298
|
return p_item;
|
|
295
299
|
}
|
|
296
300
|
if (this.items[index] instanceof PlaceHolder) this.items.load?.(this.items[index]);
|
|
297
|
-
|
|
301
|
+
const target = p_item ?? this.createNewItem(this.items[index]);
|
|
298
302
|
|
|
299
303
|
target.index = index;
|
|
300
304
|
if (p_item) {
|
|
@@ -306,7 +310,7 @@ class PlVirtualScroll extends PlElement {
|
|
|
306
310
|
this.phyPool.push(target);
|
|
307
311
|
}
|
|
308
312
|
prev ??= 0;
|
|
309
|
-
target.offset = typeof (prev)
|
|
313
|
+
target.offset = typeof (prev) === 'number' ? prev : (backward ? prev.offset - target.h : prev.offset + prev.h);
|
|
310
314
|
target.ctx._ti._nodes.forEach((n) => {
|
|
311
315
|
if (n.style) {
|
|
312
316
|
n.style.transform = `translateY(${target.offset}px)`;
|
|
@@ -318,12 +322,12 @@ class PlVirtualScroll extends PlElement {
|
|
|
318
322
|
|
|
319
323
|
createNewItem(v) {
|
|
320
324
|
if (!this.sTpl) return;
|
|
321
|
-
|
|
325
|
+
const inst = new TemplateInstance(this.sTpl);
|
|
322
326
|
|
|
323
|
-
|
|
327
|
+
const ctx = new RepeatItem(v, this.as, (ctx, m) => this.onItemChanged(ctx, m));
|
|
324
328
|
ctx._ti = inst;
|
|
325
329
|
inst.attach(this.canvas, undefined, [ctx, ...this._hctx]);
|
|
326
|
-
|
|
330
|
+
const h = !this.variableRowHeight && this.elementHeight ? this.elementHeight : calcNodesRect(inst._nodes).height;
|
|
327
331
|
|
|
328
332
|
if (!this.variableRowHeight && !this.elementHeight) {
|
|
329
333
|
this.elementHeight = h;
|
|
@@ -339,7 +343,7 @@ class PlVirtualScroll extends PlElement {
|
|
|
339
343
|
onItemChanged(ctx, m) {
|
|
340
344
|
// skip replace data call
|
|
341
345
|
if (!m) return;
|
|
342
|
-
|
|
346
|
+
const ind = this.items.findIndex(i => i === ctx[this.as]);
|
|
343
347
|
if (ind < 0) console.warn('repeat item not found');
|
|
344
348
|
if (m.path === this.as) {
|
|
345
349
|
this.set(['items', ind], m.value, m.wmh);
|
|
@@ -377,7 +381,7 @@ function fixOffset(item) {
|
|
|
377
381
|
|
|
378
382
|
function calcNodesRect(nodes) {
|
|
379
383
|
nodes = nodes.filter(n => n.getBoundingClientRect);
|
|
380
|
-
|
|
384
|
+
const rect = nodes[0].getBoundingClientRect();
|
|
381
385
|
let { top, bottom, left, right } = rect;
|
|
382
386
|
({ top, bottom, left, right } = nodes.map(n => n.getBoundingClientRect())
|
|
383
387
|
.filter(i => i)
|
|
@@ -387,9 +391,9 @@ function calcNodesRect(nodes) {
|
|
|
387
391
|
bottom: Math.max(a.bottom, c.bottom),
|
|
388
392
|
left: Math.min(a.left, c.left),
|
|
389
393
|
right: Math.max(a.right, c.right)
|
|
390
|
-
})
|
|
391
|
-
|
|
392
|
-
|
|
394
|
+
}),
|
|
395
|
+
{ top, bottom, left, right }));
|
|
396
|
+
const { x, y, height, width } = { x: left, y: top, width: right - left, height: bottom - top };
|
|
393
397
|
return { x, y, height, width };
|
|
394
398
|
}
|
|
395
399
|
|