vscroll 1.4.0-beta.2 → 1.4.3
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/dist/bundles/vscroll.esm5.js +383 -392
- package/dist/bundles/vscroll.esm5.js.map +1 -1
- package/dist/bundles/vscroll.esm5.min.js +2 -2
- package/dist/bundles/vscroll.esm5.min.js.map +1 -1
- package/dist/bundles/vscroll.esm6.js +337 -342
- package/dist/bundles/vscroll.esm6.js.map +1 -1
- package/dist/bundles/vscroll.esm6.min.js +2 -2
- package/dist/bundles/vscroll.esm6.min.js.map +1 -1
- package/dist/bundles/vscroll.umd.js +386 -395
- package/dist/bundles/vscroll.umd.js.map +1 -1
- package/dist/bundles/vscroll.umd.min.js +2 -2
- package/dist/bundles/vscroll.umd.min.js.map +1 -1
- package/dist/esm2015/classes/buffer/checkCall.js.map +1 -1
- package/dist/esm2015/classes/buffer.js +0 -16
- package/dist/esm2015/classes/buffer.js.map +1 -1
- package/dist/esm2015/classes/domRoutines.js +56 -0
- package/dist/esm2015/classes/domRoutines.js.map +1 -1
- package/dist/esm2015/classes/item.js +4 -0
- package/dist/esm2015/classes/item.js.map +1 -1
- package/dist/esm2015/classes/paddings.js +3 -1
- package/dist/esm2015/classes/paddings.js.map +1 -1
- package/dist/esm2015/classes/state/cycle.js +7 -6
- package/dist/esm2015/classes/state/cycle.js.map +1 -1
- package/dist/esm2015/classes/state/fetch.js +0 -12
- package/dist/esm2015/classes/state/fetch.js.map +1 -1
- package/dist/esm2015/classes/state/render.js +1 -1
- package/dist/esm2015/classes/state/render.js.map +1 -1
- package/dist/esm2015/classes/state/scroll.js +6 -6
- package/dist/esm2015/classes/state/scroll.js.map +1 -1
- package/dist/esm2015/classes/state.js +23 -15
- package/dist/esm2015/classes/state.js.map +1 -1
- package/dist/esm2015/classes/viewport.js +12 -29
- package/dist/esm2015/classes/viewport.js.map +1 -1
- package/dist/esm2015/interfaces/index.js.map +1 -1
- package/dist/esm2015/interfaces/state.js.map +1 -1
- package/dist/esm2015/processes/adapter/append.js +15 -74
- package/dist/esm2015/processes/adapter/append.js.map +1 -1
- package/dist/esm2015/processes/adapter/reload.js +1 -1
- package/dist/esm2015/processes/adapter/reload.js.map +1 -1
- package/dist/esm2015/processes/adjust.js +44 -15
- package/dist/esm2015/processes/adjust.js.map +1 -1
- package/dist/esm2015/processes/end.js +18 -16
- package/dist/esm2015/processes/end.js.map +1 -1
- package/dist/esm2015/processes/fetch.js +3 -3
- package/dist/esm2015/processes/fetch.js.map +1 -1
- package/dist/esm2015/processes/init.js +2 -2
- package/dist/esm2015/processes/init.js.map +1 -1
- package/dist/esm2015/processes/render.js +8 -11
- package/dist/esm2015/processes/render.js.map +1 -1
- package/dist/esm2015/processes/scroll.js +21 -21
- package/dist/esm2015/processes/scroll.js.map +1 -1
- package/dist/esm2015/version.js +1 -1
- package/dist/esm2015/version.js.map +1 -1
- package/dist/esm2015/workflow.js +5 -6
- package/dist/esm2015/workflow.js.map +1 -1
- package/dist/esm5/classes/buffer/checkCall.js.map +1 -1
- package/dist/esm5/classes/buffer/defaultSize.js +1 -1
- package/dist/esm5/classes/buffer/defaultSize.js.map +1 -1
- package/dist/esm5/classes/buffer.js +7 -23
- package/dist/esm5/classes/buffer.js.map +1 -1
- package/dist/esm5/classes/domRoutines.js +56 -0
- package/dist/esm5/classes/domRoutines.js.map +1 -1
- package/dist/esm5/classes/item.js +4 -0
- package/dist/esm5/classes/item.js.map +1 -1
- package/dist/esm5/classes/logger.js +5 -5
- package/dist/esm5/classes/logger.js.map +1 -1
- package/dist/esm5/classes/paddings.js +3 -1
- package/dist/esm5/classes/paddings.js.map +1 -1
- package/dist/esm5/classes/state/cycle.js +7 -6
- package/dist/esm5/classes/state/cycle.js.map +1 -1
- package/dist/esm5/classes/state/fetch.js +0 -12
- package/dist/esm5/classes/state/fetch.js.map +1 -1
- package/dist/esm5/classes/state/render.js +1 -1
- package/dist/esm5/classes/state/render.js.map +1 -1
- package/dist/esm5/classes/state/scroll.js +11 -11
- package/dist/esm5/classes/state/scroll.js.map +1 -1
- package/dist/esm5/classes/state.js +23 -15
- package/dist/esm5/classes/state.js.map +1 -1
- package/dist/esm5/classes/viewport.js +13 -31
- package/dist/esm5/classes/viewport.js.map +1 -1
- package/dist/esm5/inputs/validation.js +2 -2
- package/dist/esm5/inputs/validation.js.map +1 -1
- package/dist/esm5/interfaces/index.js.map +1 -1
- package/dist/esm5/interfaces/state.js.map +1 -1
- package/dist/esm5/processes/adapter/append.js +15 -75
- package/dist/esm5/processes/adapter/append.js.map +1 -1
- package/dist/esm5/processes/adapter/fix.js +1 -1
- package/dist/esm5/processes/adapter/fix.js.map +1 -1
- package/dist/esm5/processes/adapter/insert.js +1 -1
- package/dist/esm5/processes/adapter/insert.js.map +1 -1
- package/dist/esm5/processes/adapter/reload.js +1 -1
- package/dist/esm5/processes/adapter/reload.js.map +1 -1
- package/dist/esm5/processes/adapter/remove.js +1 -1
- package/dist/esm5/processes/adapter/remove.js.map +1 -1
- package/dist/esm5/processes/adjust.js +44 -15
- package/dist/esm5/processes/adjust.js.map +1 -1
- package/dist/esm5/processes/end.js +18 -16
- package/dist/esm5/processes/end.js.map +1 -1
- package/dist/esm5/processes/fetch.js +3 -3
- package/dist/esm5/processes/fetch.js.map +1 -1
- package/dist/esm5/processes/init.js +2 -2
- package/dist/esm5/processes/init.js.map +1 -1
- package/dist/esm5/processes/preFetch.js +1 -1
- package/dist/esm5/processes/preFetch.js.map +1 -1
- package/dist/esm5/processes/render.js +8 -11
- package/dist/esm5/processes/render.js.map +1 -1
- package/dist/esm5/processes/scroll.js +21 -21
- package/dist/esm5/processes/scroll.js.map +1 -1
- package/dist/esm5/version.js +1 -1
- package/dist/esm5/version.js.map +1 -1
- package/dist/esm5/workflow.js +10 -13
- package/dist/esm5/workflow.js.map +1 -1
- package/dist/typings/classes/buffer.d.ts +0 -2
- package/dist/typings/classes/domRoutines.d.ts +12 -0
- package/dist/typings/classes/item.d.ts +1 -0
- package/dist/typings/classes/state/cycle.d.ts +1 -1
- package/dist/typings/classes/state/fetch.d.ts +0 -2
- package/dist/typings/classes/state/render.d.ts +1 -1
- package/dist/typings/classes/state/scroll.d.ts +4 -4
- package/dist/typings/classes/state.d.ts +6 -3
- package/dist/typings/classes/viewport.d.ts +2 -2
- package/dist/typings/interfaces/index.d.ts +2 -2
- package/dist/typings/interfaces/state.d.ts +2 -15
- package/dist/typings/processes/adapter/append.d.ts +1 -4
- package/dist/typings/processes/adjust.d.ts +1 -0
- package/dist/typings/processes/end.d.ts +1 -2
- package/dist/typings/workflow.d.ts +1 -1
- package/package.json +17 -17
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* vscroll (https://github.com/dhilt/vscroll) FESM2015
|
|
3
|
-
* Version: 1.4.
|
|
3
|
+
* Version: 1.4.3 (2021-11-30T02:54:02.729Z)
|
|
4
4
|
* Author: Denis Hilt
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
@@ -328,7 +328,7 @@ const reactiveConfigStorage = new Map();
|
|
|
328
328
|
|
|
329
329
|
var core = {
|
|
330
330
|
name: 'vscroll',
|
|
331
|
-
version: '1.4.
|
|
331
|
+
version: '1.4.3'
|
|
332
332
|
};
|
|
333
333
|
|
|
334
334
|
let instanceCount$1 = 0;
|
|
@@ -1276,10 +1276,10 @@ const BaseAdapterProcessFactory = (process) => { var _a; return _a = class BaseA
|
|
|
1276
1276
|
const initProcesses = [CommonProcess.init, AdapterProcess.reset, AdapterProcess.reload];
|
|
1277
1277
|
class Init extends BaseProcessFactory(CommonProcess.init) {
|
|
1278
1278
|
static run(scroller, process) {
|
|
1279
|
-
const { state
|
|
1279
|
+
const { state, workflow } = scroller;
|
|
1280
1280
|
const isInitial = initProcesses.includes(process);
|
|
1281
1281
|
scroller.logger.logCycle(true);
|
|
1282
|
-
|
|
1282
|
+
state.startWorkflowCycle(isInitial, process);
|
|
1283
1283
|
workflow.call({
|
|
1284
1284
|
process: Init.process,
|
|
1285
1285
|
status: ProcessStatus.next
|
|
@@ -1298,15 +1298,15 @@ class Scroll extends BaseProcessFactory(CommonProcess.scroll) {
|
|
|
1298
1298
|
Scroll.onThrottle(scroller, position, () => Scroll.onScroll(scroller, workflow));
|
|
1299
1299
|
}
|
|
1300
1300
|
static onSynthetic(scroller, position) {
|
|
1301
|
-
const {
|
|
1302
|
-
const synthPos =
|
|
1301
|
+
const { scroll } = scroller.state;
|
|
1302
|
+
const synthPos = scroll.syntheticPosition;
|
|
1303
1303
|
if (synthPos !== null) {
|
|
1304
|
-
if (
|
|
1305
|
-
|
|
1304
|
+
if (scroll.syntheticFulfill) {
|
|
1305
|
+
scroll.syntheticPosition = null;
|
|
1306
1306
|
}
|
|
1307
|
-
if (!
|
|
1307
|
+
if (!scroll.syntheticFulfill || synthPos === position) {
|
|
1308
1308
|
scroller.logger.log(() => [
|
|
1309
|
-
'skipping scroll', position, `[${
|
|
1309
|
+
'skipping scroll', position, `[${scroll.syntheticFulfill ? '' : 'pre-'}synthetic]`
|
|
1310
1310
|
]);
|
|
1311
1311
|
return true;
|
|
1312
1312
|
}
|
|
@@ -1317,13 +1317,13 @@ class Scroll extends BaseProcessFactory(CommonProcess.scroll) {
|
|
|
1317
1317
|
return false;
|
|
1318
1318
|
}
|
|
1319
1319
|
static onThrottle(scroller, position, done) {
|
|
1320
|
-
const { state: {
|
|
1321
|
-
|
|
1322
|
-
const { direction, time } =
|
|
1323
|
-
const timeDiff =
|
|
1320
|
+
const { state: { scroll }, settings: { throttle }, logger } = scroller;
|
|
1321
|
+
scroll.current = Scroll.getScrollEvent(position, scroll.previous);
|
|
1322
|
+
const { direction, time } = scroll.current;
|
|
1323
|
+
const timeDiff = scroll.previous ? time - scroll.previous.time : Infinity;
|
|
1324
1324
|
const delta = throttle - timeDiff;
|
|
1325
1325
|
const shouldDelay = isFinite(delta) && delta > 0;
|
|
1326
|
-
const alreadyDelayed = !!
|
|
1326
|
+
const alreadyDelayed = !!scroll.scrollTimer;
|
|
1327
1327
|
logger.log(() => [
|
|
1328
1328
|
direction === Direction.backward ? '\u2934' : '\u2935',
|
|
1329
1329
|
position,
|
|
@@ -1331,17 +1331,17 @@ class Scroll extends BaseProcessFactory(CommonProcess.scroll) {
|
|
|
1331
1331
|
shouldDelay ? (alreadyDelayed ? 'delayed' : `/ ${delta}ms delay`) : ''
|
|
1332
1332
|
]);
|
|
1333
1333
|
if (!shouldDelay) {
|
|
1334
|
-
if (
|
|
1335
|
-
clearTimeout(
|
|
1336
|
-
|
|
1334
|
+
if (scroll.scrollTimer) {
|
|
1335
|
+
clearTimeout(scroll.scrollTimer);
|
|
1336
|
+
scroll.scrollTimer = null;
|
|
1337
1337
|
}
|
|
1338
1338
|
done();
|
|
1339
1339
|
return;
|
|
1340
1340
|
}
|
|
1341
1341
|
if (!alreadyDelayed) {
|
|
1342
|
-
|
|
1342
|
+
scroll.scrollTimer = setTimeout(() => {
|
|
1343
1343
|
logger.log(() => {
|
|
1344
|
-
const curr = Scroll.getScrollEvent(scroller.viewport.scrollPosition,
|
|
1344
|
+
const curr = Scroll.getScrollEvent(scroller.viewport.scrollPosition, scroll.current);
|
|
1345
1345
|
return [
|
|
1346
1346
|
curr.direction === Direction.backward ? '\u2934' : '\u2935',
|
|
1347
1347
|
curr.position,
|
|
@@ -1350,7 +1350,7 @@ class Scroll extends BaseProcessFactory(CommonProcess.scroll) {
|
|
|
1350
1350
|
position
|
|
1351
1351
|
];
|
|
1352
1352
|
});
|
|
1353
|
-
|
|
1353
|
+
scroll.scrollTimer = null;
|
|
1354
1354
|
done();
|
|
1355
1355
|
}, delta);
|
|
1356
1356
|
}
|
|
@@ -1369,11 +1369,11 @@ class Scroll extends BaseProcessFactory(CommonProcess.scroll) {
|
|
|
1369
1369
|
return { position, direction, time };
|
|
1370
1370
|
}
|
|
1371
1371
|
static onScroll(scroller, workflow) {
|
|
1372
|
-
const { state: {
|
|
1373
|
-
|
|
1374
|
-
|
|
1372
|
+
const { state: { scroll, cycle } } = scroller;
|
|
1373
|
+
scroll.previous = Object.assign({}, scroll.current);
|
|
1374
|
+
scroll.current = null;
|
|
1375
1375
|
if (cycle.busy.get()) {
|
|
1376
|
-
scroller.logger.log(() => ['skipping scroll',
|
|
1376
|
+
scroller.logger.log(() => ['skipping scroll', scroll.previous.position, '[pending]']);
|
|
1377
1377
|
return;
|
|
1378
1378
|
}
|
|
1379
1379
|
workflow.call({
|
|
@@ -1424,7 +1424,7 @@ class Reload extends BaseAdapterProcessFactory(AdapterProcess.reload) {
|
|
|
1424
1424
|
viewport.reset(buffer.startIndex);
|
|
1425
1425
|
const payload = {};
|
|
1426
1426
|
if (state.cycle.busy.get()) {
|
|
1427
|
-
state.
|
|
1427
|
+
state.scroll.stop();
|
|
1428
1428
|
payload.finalize = true;
|
|
1429
1429
|
state.cycle.interrupter = Reload.process;
|
|
1430
1430
|
}
|
|
@@ -1475,6 +1475,10 @@ class Item {
|
|
|
1475
1475
|
this.size = this.routines.getSize(this.element);
|
|
1476
1476
|
}
|
|
1477
1477
|
}
|
|
1478
|
+
makeVisible() {
|
|
1479
|
+
this.routines.makeElementVisible(this.element);
|
|
1480
|
+
this.invisible = false;
|
|
1481
|
+
}
|
|
1478
1482
|
hide() {
|
|
1479
1483
|
if (this.element) {
|
|
1480
1484
|
this.routines.hideElement(this.element);
|
|
@@ -1535,47 +1539,65 @@ class Update extends BaseAdapterProcessFactory(AdapterProcess.update) {
|
|
|
1535
1539
|
}
|
|
1536
1540
|
}
|
|
1537
1541
|
|
|
1538
|
-
class
|
|
1539
|
-
static run(scroller,
|
|
1540
|
-
const { params } =
|
|
1542
|
+
class Insert extends BaseAdapterProcessFactory(AdapterProcess.insert) {
|
|
1543
|
+
static run(scroller, options) {
|
|
1544
|
+
const { params } = Insert.parseInput(scroller, options);
|
|
1541
1545
|
if (!params) {
|
|
1542
1546
|
return;
|
|
1543
1547
|
}
|
|
1544
|
-
const
|
|
1548
|
+
const shouldInsert = Insert.doInsert(scroller, params);
|
|
1545
1549
|
scroller.workflow.call({
|
|
1546
|
-
process:
|
|
1547
|
-
status:
|
|
1550
|
+
process: Insert.process,
|
|
1551
|
+
status: shouldInsert ? ProcessStatus.next : ProcessStatus.done
|
|
1548
1552
|
});
|
|
1549
1553
|
}
|
|
1550
|
-
static
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
result = Append.doVirtual(scroller, items, prepend, fixRight);
|
|
1557
|
-
}
|
|
1558
|
-
else {
|
|
1559
|
-
if (!buffer.size) {
|
|
1560
|
-
result = Append.doEmpty(scroller, items, prepend, fixRight);
|
|
1561
|
-
}
|
|
1562
|
-
else {
|
|
1563
|
-
result = Append.doRegular(scroller, items, prepend, fixRight);
|
|
1554
|
+
static doInsert(scroller, params) {
|
|
1555
|
+
if (!Insert.insertEmpty(scroller, params)) {
|
|
1556
|
+
if (!Insert.insertInBuffer(scroller, params)) {
|
|
1557
|
+
if (!Insert.insertVirtually(scroller, params)) {
|
|
1558
|
+
return false;
|
|
1559
|
+
}
|
|
1564
1560
|
}
|
|
1565
1561
|
}
|
|
1566
|
-
return
|
|
1562
|
+
return true;
|
|
1567
1563
|
}
|
|
1568
|
-
static
|
|
1569
|
-
const { buffer,
|
|
1570
|
-
|
|
1571
|
-
if (!isFinite(buffer[absIndexToken])) {
|
|
1564
|
+
static insertEmpty(scroller, params) {
|
|
1565
|
+
const { buffer, routines, state: { fetch } } = scroller;
|
|
1566
|
+
if (buffer.size) {
|
|
1572
1567
|
return false;
|
|
1573
1568
|
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1569
|
+
const { beforeIndex, afterIndex, items, decrease } = params;
|
|
1570
|
+
if (!buffer.fillEmpty(items, beforeIndex, afterIndex, !!decrease, (index, data) => new Item(index, data, routines))) {
|
|
1571
|
+
return false;
|
|
1576
1572
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1573
|
+
fetch.fill(buffer.items, buffer.startIndex);
|
|
1574
|
+
return true;
|
|
1575
|
+
}
|
|
1576
|
+
static insertInBuffer(scroller, params) {
|
|
1577
|
+
const { before, after, beforeIndex, afterIndex, items, decrease } = params;
|
|
1578
|
+
const indexToInsert = scroller.buffer.getIndexToInsert(before || after, beforeIndex, afterIndex);
|
|
1579
|
+
if (isNaN(indexToInsert)) {
|
|
1580
|
+
return false;
|
|
1581
|
+
}
|
|
1582
|
+
const isBackward = Number.isInteger(beforeIndex) || before;
|
|
1583
|
+
const updateOptions = {
|
|
1584
|
+
predicate: ({ $index, data }) => {
|
|
1585
|
+
if (indexToInsert === $index) {
|
|
1586
|
+
return isBackward ? [...items, data] : [data, ...items];
|
|
1587
|
+
}
|
|
1588
|
+
return true;
|
|
1589
|
+
},
|
|
1590
|
+
fixRight: decrease
|
|
1591
|
+
};
|
|
1592
|
+
return Update.doUpdate(scroller, updateOptions);
|
|
1593
|
+
}
|
|
1594
|
+
static insertVirtually(scroller, params) {
|
|
1595
|
+
const { beforeIndex, afterIndex, items, decrease } = params;
|
|
1596
|
+
const { buffer, state: { fetch }, viewport } = scroller;
|
|
1597
|
+
const direction = Number.isInteger(beforeIndex) ? Direction.backward : Direction.forward;
|
|
1598
|
+
const indexToInsert = (direction === Direction.backward ? beforeIndex : afterIndex);
|
|
1599
|
+
if (!buffer.insertVirtually(items, indexToInsert, direction, !!decrease)) {
|
|
1600
|
+
return false;
|
|
1579
1601
|
}
|
|
1580
1602
|
const { index, diff } = viewport.getEdgeVisibleItem(buffer.items, Direction.backward);
|
|
1581
1603
|
fetch.firstVisible.index = index;
|
|
@@ -1583,46 +1605,41 @@ class Append extends BaseAdapterProcessFactory(AdapterProcess.append) {
|
|
|
1583
1605
|
fetch.simulate = true;
|
|
1584
1606
|
fetch.firstVisible.delta = -buffer.getSizeByIndex(index) + diff;
|
|
1585
1607
|
}
|
|
1586
|
-
logger.log(() => `buffer.${[absIndexToken]} value is set to ${buffer[absIndexToken]}`);
|
|
1587
|
-
logger.stat(`after virtual ${prepend ? 'prepend' : 'append'}`);
|
|
1588
1608
|
return true;
|
|
1589
1609
|
}
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
const
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
class Append extends BaseAdapterProcessFactory(AdapterProcess.append) {
|
|
1613
|
+
static run(scroller, { process, options }) {
|
|
1614
|
+
const { params } = Append.parseInput(scroller, options, false, process);
|
|
1615
|
+
if (!params) {
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
const shouldAppend = Append.doAppend(scroller, process, params);
|
|
1619
|
+
scroller.workflow.call({
|
|
1620
|
+
process: Append.process,
|
|
1621
|
+
status: shouldAppend ? ProcessStatus.next : ProcessStatus.done
|
|
1602
1622
|
});
|
|
1603
|
-
if (bufferLimit !== buffer[absIndexToken]) {
|
|
1604
|
-
buffer[absIndexToken] = bufferLimit;
|
|
1605
|
-
scroller.logger.log(() => `buffer.${absIndexToken} value is set to ${buffer[absIndexToken]}`);
|
|
1606
|
-
}
|
|
1607
|
-
(prepend ? fetch.prepend : fetch.append).call(fetch, newItems);
|
|
1608
|
-
buffer.setItems(newItems);
|
|
1609
|
-
fetch.first.indexBuffer = !isNaN(buffer.firstIndex) ? buffer.firstIndex : index;
|
|
1610
|
-
fetch.last.indexBuffer = !isNaN(buffer.lastIndex) ? buffer.lastIndex : index;
|
|
1611
|
-
fetch.firstVisible.index = startIndex;
|
|
1612
|
-
return true;
|
|
1613
1623
|
}
|
|
1614
|
-
static
|
|
1615
|
-
const
|
|
1616
|
-
const
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1624
|
+
static doAppend(scroller, process, params) {
|
|
1625
|
+
const { bof, eof, increase, decrease } = params;
|
|
1626
|
+
const { buffer } = scroller;
|
|
1627
|
+
const prepend = process === AdapterProcess.prepend;
|
|
1628
|
+
const opposite = prepend ? !increase : decrease;
|
|
1629
|
+
let beforeIndex, afterIndex, items = params.items;
|
|
1630
|
+
if (prepend) {
|
|
1631
|
+
beforeIndex = (bof ? buffer.absMinIndex : buffer.minIndex) + (!buffer.size ? 1 : 0);
|
|
1632
|
+
items = [...items].reverse();
|
|
1633
|
+
}
|
|
1634
|
+
else {
|
|
1635
|
+
afterIndex = (eof ? buffer.absMaxIndex : buffer.maxIndex) - (!buffer.size && !opposite ? 1 : 0);
|
|
1636
|
+
}
|
|
1637
|
+
return Insert.doInsert(scroller, {
|
|
1638
|
+
items,
|
|
1639
|
+
beforeIndex,
|
|
1640
|
+
afterIndex,
|
|
1641
|
+
decrease: opposite
|
|
1642
|
+
});
|
|
1626
1643
|
}
|
|
1627
1644
|
}
|
|
1628
1645
|
|
|
@@ -1769,76 +1786,6 @@ class UserClip extends BaseAdapterProcessFactory(AdapterProcess.clip) {
|
|
|
1769
1786
|
}
|
|
1770
1787
|
}
|
|
1771
1788
|
|
|
1772
|
-
class Insert extends BaseAdapterProcessFactory(AdapterProcess.insert) {
|
|
1773
|
-
static run(scroller, options) {
|
|
1774
|
-
const { params } = Insert.parseInput(scroller, options);
|
|
1775
|
-
if (!params) {
|
|
1776
|
-
return;
|
|
1777
|
-
}
|
|
1778
|
-
const shouldInsert = Insert.doInsert(scroller, params);
|
|
1779
|
-
scroller.workflow.call({
|
|
1780
|
-
process: Insert.process,
|
|
1781
|
-
status: shouldInsert ? ProcessStatus.next : ProcessStatus.done
|
|
1782
|
-
});
|
|
1783
|
-
}
|
|
1784
|
-
static doInsert(scroller, params) {
|
|
1785
|
-
if (!Insert.insertEmpty(scroller, params)) {
|
|
1786
|
-
if (!Insert.insertInBuffer(scroller, params)) {
|
|
1787
|
-
if (!Insert.insertVirtually(scroller, params)) {
|
|
1788
|
-
return false;
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
return true;
|
|
1793
|
-
}
|
|
1794
|
-
static insertEmpty(scroller, params) {
|
|
1795
|
-
const { buffer, routines, state: { fetch } } = scroller;
|
|
1796
|
-
if (buffer.size) {
|
|
1797
|
-
return false;
|
|
1798
|
-
}
|
|
1799
|
-
const { beforeIndex, afterIndex, items, decrease } = params;
|
|
1800
|
-
if (!buffer.fillEmpty(items, beforeIndex, afterIndex, !!decrease, (index, data) => new Item(index, data, routines))) {
|
|
1801
|
-
return false;
|
|
1802
|
-
}
|
|
1803
|
-
fetch.fill(buffer.items, buffer.startIndex);
|
|
1804
|
-
return true;
|
|
1805
|
-
}
|
|
1806
|
-
static insertInBuffer(scroller, params) {
|
|
1807
|
-
const { before, after, beforeIndex, afterIndex, items, decrease } = params;
|
|
1808
|
-
const indexToInsert = scroller.buffer.getIndexToInsert(before || after, beforeIndex, afterIndex);
|
|
1809
|
-
if (isNaN(indexToInsert)) {
|
|
1810
|
-
return false;
|
|
1811
|
-
}
|
|
1812
|
-
const isBackward = Number.isInteger(beforeIndex) || before;
|
|
1813
|
-
const updateOptions = {
|
|
1814
|
-
predicate: ({ $index, data }) => {
|
|
1815
|
-
if (indexToInsert === $index) {
|
|
1816
|
-
return isBackward ? [...items, data] : [data, ...items];
|
|
1817
|
-
}
|
|
1818
|
-
return true;
|
|
1819
|
-
},
|
|
1820
|
-
fixRight: decrease
|
|
1821
|
-
};
|
|
1822
|
-
return Update.doUpdate(scroller, updateOptions);
|
|
1823
|
-
}
|
|
1824
|
-
static insertVirtually(scroller, params) {
|
|
1825
|
-
const { beforeIndex, afterIndex, items, decrease } = params;
|
|
1826
|
-
const { buffer, state: { fetch }, viewport } = scroller;
|
|
1827
|
-
const direction = Number.isInteger(beforeIndex) ? Direction.backward : Direction.forward;
|
|
1828
|
-
const indexToInsert = (direction === Direction.backward ? beforeIndex : afterIndex);
|
|
1829
|
-
if (!buffer.insertVirtually(items, indexToInsert, direction, !!decrease)) {
|
|
1830
|
-
return false;
|
|
1831
|
-
}
|
|
1832
|
-
const { index, diff } = viewport.getEdgeVisibleItem(buffer.items, Direction.backward);
|
|
1833
|
-
fetch.firstVisible.index = index;
|
|
1834
|
-
if (!isNaN(index)) {
|
|
1835
|
-
fetch.simulate = true;
|
|
1836
|
-
fetch.firstVisible.delta = -buffer.getSizeByIndex(index) + diff;
|
|
1837
|
-
}
|
|
1838
|
-
return true;
|
|
1839
|
-
}
|
|
1840
|
-
}
|
|
1841
|
-
|
|
1842
1789
|
class Replace extends BaseAdapterProcessFactory(AdapterProcess.replace) {
|
|
1843
1790
|
static run(scroller, options) {
|
|
1844
1791
|
const { params } = Replace.parseInput(scroller, options);
|
|
@@ -2236,9 +2183,9 @@ class Fetch extends BaseProcessFactory(CommonProcess.fetch) {
|
|
|
2236
2183
|
}
|
|
2237
2184
|
}
|
|
2238
2185
|
else {
|
|
2239
|
-
const { state: {
|
|
2240
|
-
if (
|
|
2241
|
-
|
|
2186
|
+
const { state: { scroll, fetch }, viewport } = scroller;
|
|
2187
|
+
if (scroll.positionBeforeAsync === null) {
|
|
2188
|
+
scroll.positionBeforeAsync = viewport.scrollPosition;
|
|
2242
2189
|
}
|
|
2243
2190
|
fetch.cancel = () => {
|
|
2244
2191
|
box.success = () => null;
|
|
@@ -2358,13 +2305,13 @@ class PostFetch extends BaseProcessFactory(CommonProcess.postFetch) {
|
|
|
2358
2305
|
|
|
2359
2306
|
class Render extends BaseProcessFactory(CommonProcess.render) {
|
|
2360
2307
|
static run(scroller) {
|
|
2361
|
-
const { workflow, state: { cycle, render,
|
|
2308
|
+
const { workflow, state: { cycle, render, scroll }, viewport, routines } = scroller;
|
|
2362
2309
|
scroller.logger.stat('before new items render');
|
|
2363
|
-
if (
|
|
2364
|
-
|
|
2310
|
+
if (scroll.positionBeforeAsync === null) {
|
|
2311
|
+
scroll.positionBeforeAsync = viewport.scrollPosition;
|
|
2365
2312
|
}
|
|
2366
|
-
render.
|
|
2367
|
-
render.
|
|
2313
|
+
render.cancel = routines.render(() => {
|
|
2314
|
+
render.cancel = null;
|
|
2368
2315
|
if (Render.doRender(scroller)) {
|
|
2369
2316
|
workflow.call({
|
|
2370
2317
|
process: Render.process,
|
|
@@ -2379,7 +2326,7 @@ class Render extends BaseProcessFactory(CommonProcess.render) {
|
|
|
2379
2326
|
payload: { error: 'Can\'t associate item with element' }
|
|
2380
2327
|
});
|
|
2381
2328
|
}
|
|
2382
|
-
}
|
|
2329
|
+
});
|
|
2383
2330
|
}
|
|
2384
2331
|
static doRender(scroller) {
|
|
2385
2332
|
const { state: { fetch, render }, viewport, buffer, logger } = scroller;
|
|
@@ -2398,29 +2345,91 @@ class Render extends BaseProcessFactory(CommonProcess.render) {
|
|
|
2398
2345
|
}
|
|
2399
2346
|
static processElement(scroller, item) {
|
|
2400
2347
|
const { viewport, buffer } = scroller;
|
|
2401
|
-
const element = viewport.
|
|
2348
|
+
const element = viewport.findItemElementById(item.nodeId);
|
|
2402
2349
|
if (!element) {
|
|
2403
2350
|
return false;
|
|
2404
2351
|
}
|
|
2405
2352
|
item.element = element;
|
|
2406
|
-
item.
|
|
2407
|
-
item.element.style.top = '';
|
|
2408
|
-
item.element.style.position = '';
|
|
2409
|
-
item.invisible = false;
|
|
2353
|
+
item.makeVisible();
|
|
2410
2354
|
item.setSize(buffer.getSizeByIndex(item.$index));
|
|
2411
2355
|
buffer.cacheItem(item);
|
|
2412
2356
|
return true;
|
|
2413
2357
|
}
|
|
2414
2358
|
}
|
|
2415
2359
|
|
|
2360
|
+
const isInterrupted = ({ call }) => !!call.interrupted;
|
|
2361
|
+
class End extends BaseProcessFactory(CommonProcess.end) {
|
|
2362
|
+
static run(scroller, { error } = {}) {
|
|
2363
|
+
const { workflow, state: { cycle: { interrupter } } } = scroller;
|
|
2364
|
+
if (!error && !interrupter) {
|
|
2365
|
+
// set out params accessible via Adapter
|
|
2366
|
+
End.calculateParams(scroller, workflow);
|
|
2367
|
+
}
|
|
2368
|
+
// explicit interruption for we don't want to go through the inner loop finalizing
|
|
2369
|
+
if (isInterrupted(workflow)) {
|
|
2370
|
+
workflow.call({ process: End.process, status: ProcessStatus.done });
|
|
2371
|
+
return;
|
|
2372
|
+
}
|
|
2373
|
+
const next = End.shouldContinueRun(scroller, error);
|
|
2374
|
+
scroller.state.endInnerLoop();
|
|
2375
|
+
workflow.call({
|
|
2376
|
+
process: End.process,
|
|
2377
|
+
status: next ? ProcessStatus.next : ProcessStatus.done,
|
|
2378
|
+
payload: Object.assign({}, (interrupter ? { process: interrupter } : {}))
|
|
2379
|
+
});
|
|
2380
|
+
}
|
|
2381
|
+
static calculateParams(scroller, workflow) {
|
|
2382
|
+
const { adapter, viewport, buffer: { items } } = scroller;
|
|
2383
|
+
if (adapter.wanted.firstVisible) {
|
|
2384
|
+
const { item } = viewport.getEdgeVisibleItem(items, Direction.backward);
|
|
2385
|
+
if (!item || item.element !== adapter.firstVisible.element) {
|
|
2386
|
+
adapter.firstVisible = item ? item.get() : EMPTY_ITEM;
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
// the workflow can be interrupter on firstVisible change
|
|
2390
|
+
if (adapter.wanted.lastVisible && !isInterrupted(workflow)) {
|
|
2391
|
+
const { item } = viewport.getEdgeVisibleItem(items, Direction.forward);
|
|
2392
|
+
if (!item || item.element !== adapter.lastVisible.element) {
|
|
2393
|
+
adapter.lastVisible = item ? item.get() : EMPTY_ITEM;
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
static shouldContinueRun(scroller, error) {
|
|
2398
|
+
const { cycle, fetch, render } = scroller.state;
|
|
2399
|
+
// Adapter.reload or Adapter.reset
|
|
2400
|
+
if (cycle.interrupter) {
|
|
2401
|
+
return true;
|
|
2402
|
+
}
|
|
2403
|
+
// critical error
|
|
2404
|
+
if (error) {
|
|
2405
|
+
return false;
|
|
2406
|
+
}
|
|
2407
|
+
// Adapter.check
|
|
2408
|
+
if (fetch.simulate && fetch.isCheck && !render.noSize) {
|
|
2409
|
+
return true;
|
|
2410
|
+
}
|
|
2411
|
+
// Adapter.remove or Adapter.update with clip
|
|
2412
|
+
if (fetch.simulate && fetch.doRemove) {
|
|
2413
|
+
return true;
|
|
2414
|
+
}
|
|
2415
|
+
// common inner loop (App start, scroll, Adapter.clip) with full fetch
|
|
2416
|
+
if (!fetch.simulate && ((fetch.hasNewItems && !render.noSize) || fetch.hasAnotherPack)) {
|
|
2417
|
+
return true;
|
|
2418
|
+
}
|
|
2419
|
+
return false;
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2416
2423
|
class Adjust extends BaseProcessFactory(CommonProcess.adjust) {
|
|
2417
2424
|
static run(scroller) {
|
|
2418
|
-
const { workflow, viewport, state: {
|
|
2419
|
-
|
|
2425
|
+
const { workflow, viewport, state: { scroll } } = scroller;
|
|
2426
|
+
scroll.positionBeforeAdjust = viewport.scrollPosition;
|
|
2420
2427
|
Adjust.setPaddings(scroller);
|
|
2421
|
-
|
|
2428
|
+
scroll.positionAfterAdjust = viewport.scrollPosition;
|
|
2422
2429
|
// scroll position adjustments
|
|
2423
2430
|
const position = Adjust.calculatePosition(scroller);
|
|
2431
|
+
// additional adjustment if the position can't be reached during the initial cycle
|
|
2432
|
+
Adjust.setAdditionalForwardPadding(scroller, position);
|
|
2424
2433
|
// set new position using animation frame
|
|
2425
2434
|
Adjust.setPosition(scroller, position, () => workflow.call({
|
|
2426
2435
|
process: Adjust.process,
|
|
@@ -2451,7 +2460,8 @@ class Adjust extends BaseProcessFactory(CommonProcess.adjust) {
|
|
|
2451
2460
|
}
|
|
2452
2461
|
// lack of items case
|
|
2453
2462
|
const bufferSize = viewport.getScrollableSize() - forward.size - backward.size;
|
|
2454
|
-
const
|
|
2463
|
+
const scrollSize = bwdSize + bufferSize + fwdSize;
|
|
2464
|
+
const viewportSizeDiff = viewport.getSize() - scrollSize;
|
|
2455
2465
|
if (viewportSizeDiff > 0) {
|
|
2456
2466
|
if (inverse) {
|
|
2457
2467
|
bwdSize += viewportSizeDiff;
|
|
@@ -2466,7 +2476,7 @@ class Adjust extends BaseProcessFactory(CommonProcess.adjust) {
|
|
|
2466
2476
|
scroller.logger.stat('after paddings adjustments');
|
|
2467
2477
|
}
|
|
2468
2478
|
static calculatePosition(scroller) {
|
|
2469
|
-
const { viewport, buffer, state: { fetch, render,
|
|
2479
|
+
const { viewport, buffer, state: { fetch, render, scroll } } = scroller;
|
|
2470
2480
|
let position = viewport.paddings.backward.size;
|
|
2471
2481
|
// increase the position to meet the expectation of the first visible item
|
|
2472
2482
|
if (!isNaN(fetch.firstVisible.index) && !isNaN(buffer.firstIndex)) {
|
|
@@ -2489,8 +2499,8 @@ class Adjust extends BaseProcessFactory(CommonProcess.adjust) {
|
|
|
2489
2499
|
});
|
|
2490
2500
|
}
|
|
2491
2501
|
// slow fetch/render case
|
|
2492
|
-
if (
|
|
2493
|
-
const diff = render.positionBefore -
|
|
2502
|
+
if (scroll.positionBeforeAsync !== null) {
|
|
2503
|
+
const diff = render.positionBefore - scroll.positionBeforeAsync;
|
|
2494
2504
|
if (diff !== 0) {
|
|
2495
2505
|
scroller.logger.log(`shift position due to fetch-render difference (${diff})`);
|
|
2496
2506
|
position += diff;
|
|
@@ -2502,22 +2512,47 @@ class Adjust extends BaseProcessFactory(CommonProcess.adjust) {
|
|
|
2502
2512
|
}
|
|
2503
2513
|
return Math.round(position);
|
|
2504
2514
|
}
|
|
2515
|
+
static setAdditionalForwardPadding(scroller, position) {
|
|
2516
|
+
const { viewport, buffer, state: { cycle } } = scroller;
|
|
2517
|
+
if (!cycle.isInitial || !End.shouldContinueRun(scroller, null)) {
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2520
|
+
const diff = position - viewport.getMaxScrollPosition();
|
|
2521
|
+
if (diff <= 0) {
|
|
2522
|
+
return;
|
|
2523
|
+
}
|
|
2524
|
+
const last = buffer.getLastVisibleItem();
|
|
2525
|
+
if (!last) {
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
let size = 0;
|
|
2529
|
+
let index = last.$index + 1;
|
|
2530
|
+
while (size <= diff && index <= buffer.absMaxIndex) {
|
|
2531
|
+
size += buffer.getSizeByIndex(index++);
|
|
2532
|
+
}
|
|
2533
|
+
const shift = Math.min(size, diff);
|
|
2534
|
+
if (shift) {
|
|
2535
|
+
viewport.paddings.forward.size += shift;
|
|
2536
|
+
scroller.logger.log(`increase fwd padding due to lack of items (${diff} -> ${shift})`);
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2505
2539
|
static setPosition(scroller, position, done) {
|
|
2506
|
-
const { state: {
|
|
2507
|
-
if (!
|
|
2540
|
+
const { state: { scroll }, viewport, routines } = scroller;
|
|
2541
|
+
if (!scroll.hasPositionChanged(position)) {
|
|
2508
2542
|
return done();
|
|
2509
2543
|
}
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2544
|
+
scroll.syntheticPosition = position;
|
|
2545
|
+
scroll.syntheticFulfill = false;
|
|
2546
|
+
scroll.cancelAnimation = routines.animate(() => {
|
|
2547
|
+
scroll.cancelAnimation = null;
|
|
2548
|
+
const inertiaDiff = scroll.positionAfterAdjust - viewport.scrollPosition;
|
|
2514
2549
|
let diffLog = '';
|
|
2515
2550
|
if (inertiaDiff > 0) {
|
|
2516
2551
|
position -= inertiaDiff;
|
|
2517
|
-
|
|
2552
|
+
scroll.syntheticPosition = position;
|
|
2518
2553
|
diffLog = ` (-${inertiaDiff})`;
|
|
2519
2554
|
}
|
|
2520
|
-
|
|
2555
|
+
scroll.syntheticFulfill = true;
|
|
2521
2556
|
viewport.scrollPosition = position;
|
|
2522
2557
|
scroller.logger.stat('after scroll adjustment' + diffLog);
|
|
2523
2558
|
done();
|
|
@@ -2657,67 +2692,6 @@ class Clip extends BaseProcessFactory(CommonProcess.clip) {
|
|
|
2657
2692
|
}
|
|
2658
2693
|
}
|
|
2659
2694
|
|
|
2660
|
-
const isInterrupted = ({ call }) => !!call.interrupted;
|
|
2661
|
-
class End extends BaseProcessFactory(CommonProcess.end) {
|
|
2662
|
-
static run(scroller, { error } = {}) {
|
|
2663
|
-
const { workflow, state: { cycle: { interrupter } } } = scroller;
|
|
2664
|
-
if (!error && !interrupter) {
|
|
2665
|
-
// set out params accessible via Adapter
|
|
2666
|
-
End.calculateParams(scroller, workflow);
|
|
2667
|
-
}
|
|
2668
|
-
// explicit interruption for we don't want to go through the inner loop finalizing
|
|
2669
|
-
if (isInterrupted(workflow)) {
|
|
2670
|
-
workflow.call({ process: End.process, status: ProcessStatus.done });
|
|
2671
|
-
return;
|
|
2672
|
-
}
|
|
2673
|
-
const next = End.finalizeInnerLoop(scroller, error);
|
|
2674
|
-
workflow.call({
|
|
2675
|
-
process: End.process,
|
|
2676
|
-
status: next ? ProcessStatus.next : ProcessStatus.done,
|
|
2677
|
-
payload: Object.assign({}, (interrupter ? { process: interrupter } : {}))
|
|
2678
|
-
});
|
|
2679
|
-
}
|
|
2680
|
-
static calculateParams(scroller, workflow) {
|
|
2681
|
-
const { adapter, viewport, buffer: { items } } = scroller;
|
|
2682
|
-
if (adapter.wanted.firstVisible) {
|
|
2683
|
-
const { item } = viewport.getEdgeVisibleItem(items, Direction.backward);
|
|
2684
|
-
if (!item || item.element !== adapter.firstVisible.element) {
|
|
2685
|
-
adapter.firstVisible = item ? item.get() : EMPTY_ITEM;
|
|
2686
|
-
}
|
|
2687
|
-
}
|
|
2688
|
-
// the workflow can be interrupter on firstVisible change
|
|
2689
|
-
if (adapter.wanted.lastVisible && !isInterrupted(workflow)) {
|
|
2690
|
-
const { item } = viewport.getEdgeVisibleItem(items, Direction.forward);
|
|
2691
|
-
if (!item || item.element !== adapter.lastVisible.element) {
|
|
2692
|
-
adapter.lastVisible = item ? item.get() : EMPTY_ITEM;
|
|
2693
|
-
}
|
|
2694
|
-
}
|
|
2695
|
-
}
|
|
2696
|
-
static finalizeInnerLoop(scroller, error) {
|
|
2697
|
-
const { state, state: { cycle, clip, fetch } } = scroller;
|
|
2698
|
-
const next = !!cycle.interrupter || (error ? false : End.getNext(scroller));
|
|
2699
|
-
cycle.innerLoop.isInitial = false;
|
|
2700
|
-
fetch.stopSimulate();
|
|
2701
|
-
clip.reset(true);
|
|
2702
|
-
state.endInnerLoop();
|
|
2703
|
-
return next;
|
|
2704
|
-
}
|
|
2705
|
-
static getNext(scroller) {
|
|
2706
|
-
const { state: { fetch, render } } = scroller;
|
|
2707
|
-
if (fetch.simulate && fetch.isCheck && !render.noSize) { // Adapter.check
|
|
2708
|
-
return true;
|
|
2709
|
-
}
|
|
2710
|
-
if (fetch.simulate && fetch.doRemove) { // Adapter.remove or Adapter.update with clip
|
|
2711
|
-
return true;
|
|
2712
|
-
}
|
|
2713
|
-
if ( // common inner loop (App start, Scroll, Adapter.clip) accompanied by fetch
|
|
2714
|
-
!fetch.simulate && ((fetch.hasNewItems && !render.noSize) || fetch.hasAnotherPack)) {
|
|
2715
|
-
return true;
|
|
2716
|
-
}
|
|
2717
|
-
return false;
|
|
2718
|
-
}
|
|
2719
|
-
}
|
|
2720
|
-
|
|
2721
2695
|
class Logger {
|
|
2722
2696
|
constructor(scroller, packageInfo, adapter) {
|
|
2723
2697
|
this.logs = [];
|
|
@@ -2908,12 +2882,50 @@ class Routines {
|
|
|
2908
2882
|
constructor(settings) {
|
|
2909
2883
|
this.horizontal = settings.horizontal;
|
|
2910
2884
|
this.window = settings.windowViewport;
|
|
2885
|
+
this.viewport = settings.viewport;
|
|
2911
2886
|
}
|
|
2912
2887
|
checkElement(element) {
|
|
2913
2888
|
if (!element) {
|
|
2914
2889
|
throw new Error('HTML element is not defined');
|
|
2915
2890
|
}
|
|
2916
2891
|
}
|
|
2892
|
+
getHostElement(element) {
|
|
2893
|
+
if (this.window) {
|
|
2894
|
+
return document.documentElement;
|
|
2895
|
+
}
|
|
2896
|
+
if (this.viewport) {
|
|
2897
|
+
return this.viewport;
|
|
2898
|
+
}
|
|
2899
|
+
this.checkElement(element);
|
|
2900
|
+
const parent = element.parentElement;
|
|
2901
|
+
this.checkElement(parent);
|
|
2902
|
+
return parent;
|
|
2903
|
+
}
|
|
2904
|
+
getScrollEventReceiver(element) {
|
|
2905
|
+
if (this.window) {
|
|
2906
|
+
return window;
|
|
2907
|
+
}
|
|
2908
|
+
return this.getHostElement(element);
|
|
2909
|
+
}
|
|
2910
|
+
setupScrollRestoration() {
|
|
2911
|
+
if ('scrollRestoration' in history) {
|
|
2912
|
+
history.scrollRestoration = 'manual';
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
dismissOverflowAnchor(element) {
|
|
2916
|
+
this.checkElement(element);
|
|
2917
|
+
element.style.overflowAnchor = 'none';
|
|
2918
|
+
}
|
|
2919
|
+
findElementBySelector(element, selector) {
|
|
2920
|
+
this.checkElement(element);
|
|
2921
|
+
return element.querySelector(selector);
|
|
2922
|
+
}
|
|
2923
|
+
findPaddingElement(element, direction) {
|
|
2924
|
+
return this.findElementBySelector(element, `[data-padding-${direction}]`);
|
|
2925
|
+
}
|
|
2926
|
+
findItemElement(element, id) {
|
|
2927
|
+
return this.findElementBySelector(element, `[data-sid="${id}"]`);
|
|
2928
|
+
}
|
|
2917
2929
|
getScrollPosition(element) {
|
|
2918
2930
|
if (this.window) {
|
|
2919
2931
|
return window.pageYOffset;
|
|
@@ -2976,6 +2988,12 @@ class Routines {
|
|
|
2976
2988
|
return element.offsetTop - (relativeElement ? relativeElement.scrollTop : 0) +
|
|
2977
2989
|
(direction === (!opposite ? Direction.forward : Direction.backward) ? this.getSize(element) : 0);
|
|
2978
2990
|
}
|
|
2991
|
+
makeElementVisible(element) {
|
|
2992
|
+
this.checkElement(element);
|
|
2993
|
+
element.style.left = '';
|
|
2994
|
+
element.style.top = '';
|
|
2995
|
+
element.style.position = '';
|
|
2996
|
+
}
|
|
2979
2997
|
hideElement(element) {
|
|
2980
2998
|
this.checkElement(element);
|
|
2981
2999
|
element.style.display = 'none';
|
|
@@ -2988,11 +3006,25 @@ class Routines {
|
|
|
2988
3006
|
this.checkElement(element);
|
|
2989
3007
|
element.scrollIntoView(argument);
|
|
2990
3008
|
}
|
|
3009
|
+
render(cb) {
|
|
3010
|
+
const timeoutId = setTimeout(() => cb());
|
|
3011
|
+
return () => clearTimeout(timeoutId);
|
|
3012
|
+
}
|
|
3013
|
+
animate(cb) {
|
|
3014
|
+
const animationFrameId = requestAnimationFrame(() => cb());
|
|
3015
|
+
return () => cancelAnimationFrame(animationFrameId);
|
|
3016
|
+
}
|
|
3017
|
+
onScroll(element, handler) {
|
|
3018
|
+
element.addEventListener('scroll', handler);
|
|
3019
|
+
return () => element.removeEventListener('scroll', handler);
|
|
3020
|
+
}
|
|
2991
3021
|
}
|
|
2992
3022
|
|
|
2993
3023
|
class Padding {
|
|
2994
3024
|
constructor(element, direction, routines) {
|
|
2995
|
-
|
|
3025
|
+
const found = routines.findPaddingElement(element, direction);
|
|
3026
|
+
routines.checkElement(found);
|
|
3027
|
+
this.element = found;
|
|
2996
3028
|
this.direction = direction;
|
|
2997
3029
|
this.routines = routines;
|
|
2998
3030
|
}
|
|
@@ -3067,28 +3099,21 @@ class Viewport {
|
|
|
3067
3099
|
this.routines = routines;
|
|
3068
3100
|
this.state = state;
|
|
3069
3101
|
this.logger = logger;
|
|
3070
|
-
this.
|
|
3102
|
+
this.hostElement = this.routines.getHostElement(this.element);
|
|
3103
|
+
this.scrollEventReceiver = this.routines.getScrollEventReceiver(this.element);
|
|
3071
3104
|
if (settings.windowViewport) {
|
|
3072
|
-
this.
|
|
3073
|
-
this.scrollEventReceiver = window;
|
|
3074
|
-
}
|
|
3075
|
-
else {
|
|
3076
|
-
this.hostElement = settings.viewport || this.element.parentElement;
|
|
3077
|
-
this.scrollEventReceiver = this.hostElement;
|
|
3078
|
-
}
|
|
3079
|
-
this.paddings = new Paddings(this.element, this.routines, settings);
|
|
3080
|
-
if (settings.windowViewport && 'scrollRestoration' in history) {
|
|
3081
|
-
history.scrollRestoration = 'manual';
|
|
3105
|
+
this.routines.setupScrollRestoration();
|
|
3082
3106
|
}
|
|
3083
3107
|
if (settings.dismissOverflowAnchor) {
|
|
3084
|
-
this.
|
|
3108
|
+
this.routines.dismissOverflowAnchor(this.hostElement);
|
|
3085
3109
|
}
|
|
3110
|
+
this.paddings = new Paddings(this.element, this.routines, settings);
|
|
3086
3111
|
}
|
|
3087
3112
|
reset(startIndex) {
|
|
3088
3113
|
this.setOffset();
|
|
3089
3114
|
this.paddings.reset(this.getSize(), startIndex, this.offset);
|
|
3090
3115
|
this.scrollPosition = this.paddings.backward.size || 0;
|
|
3091
|
-
this.state.
|
|
3116
|
+
this.state.scroll.reset();
|
|
3092
3117
|
}
|
|
3093
3118
|
setPosition(value) {
|
|
3094
3119
|
const oldPosition = this.scrollPosition;
|
|
@@ -3109,28 +3134,15 @@ class Viewport {
|
|
|
3109
3134
|
set scrollPosition(value) {
|
|
3110
3135
|
this.setPosition(value);
|
|
3111
3136
|
}
|
|
3112
|
-
disableScrollForOneLoop() {
|
|
3113
|
-
if (this.disabled) {
|
|
3114
|
-
return;
|
|
3115
|
-
}
|
|
3116
|
-
const { style } = this.hostElement;
|
|
3117
|
-
if (style.overflowY === 'hidden') {
|
|
3118
|
-
return;
|
|
3119
|
-
}
|
|
3120
|
-
this.disabled = true;
|
|
3121
|
-
const overflow = style.overflowY;
|
|
3122
|
-
setTimeout(() => {
|
|
3123
|
-
this.disabled = false;
|
|
3124
|
-
style.overflowY = overflow;
|
|
3125
|
-
});
|
|
3126
|
-
style.overflowY = 'hidden';
|
|
3127
|
-
}
|
|
3128
3137
|
getSize() {
|
|
3129
3138
|
return this.routines.getSize(this.hostElement, true);
|
|
3130
3139
|
}
|
|
3131
3140
|
getScrollableSize() {
|
|
3132
3141
|
return this.routines.getSize(this.element);
|
|
3133
3142
|
}
|
|
3143
|
+
getMaxScrollPosition() {
|
|
3144
|
+
return this.getScrollableSize() - this.getSize();
|
|
3145
|
+
}
|
|
3134
3146
|
getBufferPadding() {
|
|
3135
3147
|
return this.getSize() * this.settings.padding;
|
|
3136
3148
|
}
|
|
@@ -3143,6 +3155,9 @@ class Viewport {
|
|
|
3143
3155
|
this.offset -= this.routines.getOffset(this.hostElement);
|
|
3144
3156
|
}
|
|
3145
3157
|
}
|
|
3158
|
+
findItemElementById(id) {
|
|
3159
|
+
return this.routines.findItemElement(this.element, id);
|
|
3160
|
+
}
|
|
3146
3161
|
getEdgeVisibleItem(items, direction) {
|
|
3147
3162
|
const bwd = direction === Direction.backward;
|
|
3148
3163
|
const opposite = bwd ? Direction.forward : Direction.backward;
|
|
@@ -3744,22 +3759,6 @@ class Buffer {
|
|
|
3744
3759
|
this.startIndex = this.absMinIndex;
|
|
3745
3760
|
}
|
|
3746
3761
|
}
|
|
3747
|
-
appendVirtually(count, fixRight) {
|
|
3748
|
-
if (fixRight) {
|
|
3749
|
-
this.items.forEach(item => item.updateIndex(item.$index - count));
|
|
3750
|
-
this.cache.shiftIndexes(-count);
|
|
3751
|
-
this.items = [...this.items];
|
|
3752
|
-
}
|
|
3753
|
-
this.shiftExtremum(count, fixRight);
|
|
3754
|
-
}
|
|
3755
|
-
prependVirtually(count, fixRight) {
|
|
3756
|
-
if (!fixRight) {
|
|
3757
|
-
this.items.forEach(item => item.updateIndex(item.$index + count));
|
|
3758
|
-
this.cache.shiftIndexes(count);
|
|
3759
|
-
this.items = [...this.items];
|
|
3760
|
-
}
|
|
3761
|
-
this.shiftExtremum(count, fixRight);
|
|
3762
|
-
}
|
|
3763
3762
|
insertVirtually(items, index, direction, fixRight) {
|
|
3764
3763
|
if (!this.checkCall.insertVirtual(items, index, direction)) {
|
|
3765
3764
|
return false;
|
|
@@ -3949,6 +3948,7 @@ class InnerLoopModel {
|
|
|
3949
3948
|
return this.count === 0;
|
|
3950
3949
|
}
|
|
3951
3950
|
done() {
|
|
3951
|
+
this.isInitial = false;
|
|
3952
3952
|
this.count++;
|
|
3953
3953
|
this.total++;
|
|
3954
3954
|
this.busy.set(false);
|
|
@@ -3968,7 +3968,7 @@ class WorkflowCycleModel {
|
|
|
3968
3968
|
this.innerLoop = new InnerLoopModel(loopCount);
|
|
3969
3969
|
this.interrupter = null;
|
|
3970
3970
|
this.busy = new Reactive(false);
|
|
3971
|
-
this.
|
|
3971
|
+
this.end(cycleCount);
|
|
3972
3972
|
}
|
|
3973
3973
|
get loopId() {
|
|
3974
3974
|
return `${this.instanceIndex}-${this.count}-${this.innerLoop.total}`;
|
|
@@ -3976,11 +3976,6 @@ class WorkflowCycleModel {
|
|
|
3976
3976
|
get loopIdNext() {
|
|
3977
3977
|
return `${this.instanceIndex}-${this.count}-${this.innerLoop.total + 1}`;
|
|
3978
3978
|
}
|
|
3979
|
-
done(count) {
|
|
3980
|
-
this.count = count;
|
|
3981
|
-
this.isInitial = false;
|
|
3982
|
-
this.busy.set(false);
|
|
3983
|
-
}
|
|
3984
3979
|
start(isInitial, initiator) {
|
|
3985
3980
|
this.isInitial = isInitial;
|
|
3986
3981
|
this.initiator = initiator;
|
|
@@ -3989,6 +3984,11 @@ class WorkflowCycleModel {
|
|
|
3989
3984
|
this.interrupter = null;
|
|
3990
3985
|
this.busy.set(true);
|
|
3991
3986
|
}
|
|
3987
|
+
end(count) {
|
|
3988
|
+
this.count = count;
|
|
3989
|
+
this.isInitial = false;
|
|
3990
|
+
this.busy.set(false);
|
|
3991
|
+
}
|
|
3992
3992
|
dispose(forever) {
|
|
3993
3993
|
if (forever) {
|
|
3994
3994
|
// otherwise the value will be persisted during re-instantiation
|
|
@@ -4106,18 +4106,6 @@ class FetchModel {
|
|
|
4106
4106
|
this.firstVisible.index = start;
|
|
4107
4107
|
this.firstVisible.delta = 0;
|
|
4108
4108
|
}
|
|
4109
|
-
append(items) {
|
|
4110
|
-
this.startSimulate(items);
|
|
4111
|
-
this.last.index = items[items.length - 1].$index;
|
|
4112
|
-
this.first.index = items[0].$index;
|
|
4113
|
-
this.direction = Direction.forward;
|
|
4114
|
-
}
|
|
4115
|
-
prepend(items) {
|
|
4116
|
-
this.startSimulate(items);
|
|
4117
|
-
this.last.index = items[0].$index;
|
|
4118
|
-
this.first.index = items[items.length - 1].$index;
|
|
4119
|
-
this.direction = Direction.backward;
|
|
4120
|
-
}
|
|
4121
4109
|
check(items) {
|
|
4122
4110
|
this.startSimulate(items);
|
|
4123
4111
|
this.last.index = items[0].$index;
|
|
@@ -4160,11 +4148,11 @@ class RenderModel {
|
|
|
4160
4148
|
this.sizeBefore = 0;
|
|
4161
4149
|
this.sizeAfter = 0;
|
|
4162
4150
|
this.positionBefore = 0;
|
|
4163
|
-
this.
|
|
4151
|
+
this.cancel = null;
|
|
4164
4152
|
}
|
|
4165
4153
|
}
|
|
4166
4154
|
|
|
4167
|
-
class
|
|
4155
|
+
class ScrollModel {
|
|
4168
4156
|
constructor() {
|
|
4169
4157
|
this.reset();
|
|
4170
4158
|
}
|
|
@@ -4176,16 +4164,16 @@ class ScrollState {
|
|
|
4176
4164
|
this.positionBeforeAsync = null;
|
|
4177
4165
|
this.positionBeforeAdjust = null;
|
|
4178
4166
|
this.positionAfterAdjust = null;
|
|
4179
|
-
this.
|
|
4167
|
+
this.stop();
|
|
4180
4168
|
}
|
|
4181
|
-
|
|
4169
|
+
stop() {
|
|
4182
4170
|
if (this.scrollTimer) {
|
|
4183
4171
|
clearTimeout(this.scrollTimer);
|
|
4184
4172
|
this.scrollTimer = null;
|
|
4185
4173
|
}
|
|
4186
|
-
if (this.
|
|
4187
|
-
|
|
4188
|
-
this.
|
|
4174
|
+
if (this.cancelAnimation) {
|
|
4175
|
+
this.cancelAnimation();
|
|
4176
|
+
this.cancelAnimation = null;
|
|
4189
4177
|
}
|
|
4190
4178
|
}
|
|
4191
4179
|
hasPositionChanged(position) {
|
|
@@ -4204,25 +4192,19 @@ class State {
|
|
|
4204
4192
|
this.fetch = new FetchModel(settings.directionPriority);
|
|
4205
4193
|
this.clip = new ClipModel();
|
|
4206
4194
|
this.render = new RenderModel();
|
|
4207
|
-
this.
|
|
4195
|
+
this.scroll = new ScrollModel();
|
|
4208
4196
|
}
|
|
4209
4197
|
get time() {
|
|
4210
4198
|
return Number(new Date()) - this.initTime;
|
|
4211
4199
|
}
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
}
|
|
4218
|
-
if (render.renderTimer) {
|
|
4219
|
-
clearTimeout(render.renderTimer);
|
|
4220
|
-
render.renderTimer = null;
|
|
4221
|
-
}
|
|
4222
|
-
cycle.innerLoop.done();
|
|
4200
|
+
startWorkflowCycle(isInitial, initiator) {
|
|
4201
|
+
this.cycle.start(isInitial, initiator);
|
|
4202
|
+
}
|
|
4203
|
+
endWorkflowCycle(count) {
|
|
4204
|
+
this.cycle.end(count);
|
|
4223
4205
|
}
|
|
4224
4206
|
startInnerLoop() {
|
|
4225
|
-
const { cycle,
|
|
4207
|
+
const { cycle, scroll: scroll, fetch, render, clip } = this;
|
|
4226
4208
|
cycle.innerLoop.start();
|
|
4227
4209
|
scroll.positionBeforeAsync = null;
|
|
4228
4210
|
if (!fetch.simulate) {
|
|
@@ -4235,10 +4217,24 @@ class State {
|
|
|
4235
4217
|
doRender: fetch.simulate && fetch.items.length > 0
|
|
4236
4218
|
} : {}));
|
|
4237
4219
|
}
|
|
4220
|
+
endInnerLoop() {
|
|
4221
|
+
const { fetch, clip, render, cycle } = this;
|
|
4222
|
+
fetch.stopSimulate();
|
|
4223
|
+
clip.reset(true);
|
|
4224
|
+
if (fetch.cancel) {
|
|
4225
|
+
fetch.cancel();
|
|
4226
|
+
fetch.cancel = null;
|
|
4227
|
+
}
|
|
4228
|
+
if (render.cancel) {
|
|
4229
|
+
render.cancel();
|
|
4230
|
+
render.cancel = null;
|
|
4231
|
+
}
|
|
4232
|
+
cycle.innerLoop.done();
|
|
4233
|
+
}
|
|
4238
4234
|
dispose() {
|
|
4235
|
+
this.scroll.stop();
|
|
4239
4236
|
this.cycle.dispose();
|
|
4240
4237
|
this.endInnerLoop();
|
|
4241
|
-
this.scrollState.cleanupTimers();
|
|
4242
4238
|
}
|
|
4243
4239
|
}
|
|
4244
4240
|
|
|
@@ -4924,7 +4920,7 @@ class Workflow {
|
|
|
4924
4920
|
this.cyclesDone = 0;
|
|
4925
4921
|
this.interruptionCount = 0;
|
|
4926
4922
|
this.errors = [];
|
|
4927
|
-
this.
|
|
4923
|
+
this.offScroll = () => null;
|
|
4928
4924
|
this.propagateChanges = run;
|
|
4929
4925
|
this.stateMachineMethods = {
|
|
4930
4926
|
run: this.runProcess(),
|
|
@@ -4952,14 +4948,13 @@ class Workflow {
|
|
|
4952
4948
|
status: ProcessStatus.start
|
|
4953
4949
|
});
|
|
4954
4950
|
// set up scroll event listener
|
|
4955
|
-
const { scrollEventReceiver } = this.scroller
|
|
4951
|
+
const { viewport: { scrollEventReceiver }, routines } = this.scroller;
|
|
4956
4952
|
const onScrollHandler = event => this.callWorkflow({
|
|
4957
4953
|
process: CommonProcess.scroll,
|
|
4958
4954
|
status: ProcessStatus.start,
|
|
4959
4955
|
payload: { event }
|
|
4960
4956
|
});
|
|
4961
|
-
|
|
4962
|
-
this.disposeScrollEventHandler = () => scrollEventReceiver.removeEventListener('scroll', onScrollHandler);
|
|
4957
|
+
this.offScroll = routines.onScroll(scrollEventReceiver, onScrollHandler);
|
|
4963
4958
|
}
|
|
4964
4959
|
changeItems(items) {
|
|
4965
4960
|
this.propagateChanges(items);
|
|
@@ -5045,14 +5040,14 @@ class Workflow {
|
|
|
5045
5040
|
const { state, logger } = this.scroller;
|
|
5046
5041
|
this.cyclesDone++;
|
|
5047
5042
|
logger.logCycle(false);
|
|
5048
|
-
state.
|
|
5043
|
+
state.endWorkflowCycle(this.cyclesDone + 1);
|
|
5049
5044
|
this.finalize();
|
|
5050
5045
|
}
|
|
5051
5046
|
dispose() {
|
|
5052
5047
|
if (this.initTimer) {
|
|
5053
5048
|
clearTimeout(this.initTimer);
|
|
5054
5049
|
}
|
|
5055
|
-
this.
|
|
5050
|
+
this.offScroll();
|
|
5056
5051
|
this.adapterRun$.dispose();
|
|
5057
5052
|
this.scroller.dispose(true);
|
|
5058
5053
|
Object.getOwnPropertyNames(this).forEach(prop => {
|