vscroll
Version:
Virtual scroll engine
153 lines • 6.3 kB
JavaScript
import { __extends } from "tslib";
import { BaseProcessFactory, CommonProcess, ProcessStatus } from './misc/index';
import End from './end';
var Adjust = /** @class */ (function (_super) {
__extends(Adjust, _super);
function Adjust() {
return _super !== null && _super.apply(this, arguments) || this;
}
Adjust.run = function (scroller) {
var workflow = scroller.workflow, viewport = scroller.viewport, scroll = scroller.state.scroll;
scroll.positionBeforeAdjust = viewport.scrollPosition;
Adjust.setPaddings(scroller);
scroll.positionAfterAdjust = viewport.scrollPosition;
// scroll position adjustments
var position = Adjust.calculatePosition(scroller);
// additional adjustment if the position can't be reached during the initial cycle
Adjust.setAdditionalForwardPadding(scroller, position);
// set new position using animation frame
Adjust.setPosition(scroller, position, function () {
return workflow.call({
process: Adjust.process,
status: ProcessStatus.done
});
});
};
Adjust.setPaddings = function (scroller) {
var viewport = scroller.viewport, buffer = scroller.buffer, inverse = scroller.settings.inverse, fetch = scroller.state.fetch;
var firstItem = buffer.getFirstVisibleItem();
var lastItem = buffer.getLastVisibleItem();
var first, last;
if (firstItem && lastItem) {
first = firstItem.$index;
last = lastItem.$index;
}
else {
first = !isNaN(fetch.firstVisible.index) ? fetch.firstVisible.index : buffer.startIndex;
last = first - 1;
}
var _a = viewport.paddings, forward = _a.forward, backward = _a.backward;
var index, bwdSize = 0, fwdSize = 0;
// new backward and forward paddings size
for (index = buffer.finiteAbsMinIndex; index < first; index++) {
bwdSize += buffer.getSizeByIndex(index);
}
for (index = last + 1; index <= buffer.finiteAbsMaxIndex; index++) {
fwdSize += buffer.getSizeByIndex(index);
}
// lack of items case
var bufferSize = viewport.getScrollableSize() - forward.size - backward.size;
var scrollSize = bwdSize + bufferSize + fwdSize;
var viewportSizeDiff = viewport.getSize() - scrollSize;
if (viewportSizeDiff > 0) {
if (inverse) {
bwdSize += viewportSizeDiff;
}
else {
fwdSize += viewportSizeDiff;
}
scroller.logger.log(function () {
return inverse ? 'backward' : 'forward' + " padding will be increased by ".concat(viewportSizeDiff, " to fill the viewport");
});
}
backward.size = bwdSize;
forward.size = fwdSize;
scroller.logger.stat('after paddings adjustments');
};
Adjust.calculatePosition = function (scroller) {
var viewport = scroller.viewport, buffer = scroller.buffer, _a = scroller.state, fetch = _a.fetch, render = _a.render, scroll = _a.scroll;
var position = viewport.paddings.backward.size;
// increase the position to meet the expectation of the first visible item
if (!isNaN(fetch.firstVisible.index) && !isNaN(buffer.firstIndex)) {
scroller.logger.log("first index = ".concat(fetch.firstVisible.index, ", delta = ").concat(fetch.firstVisible.delta));
var shouldCheckPreSizeExpectation_1 = fetch.shouldCheckPreSizeExpectation(buffer.lastIndex);
buffer.items.forEach(function (item) {
// 1) shift of the buffered items before the first visible item
if (item.$index < fetch.firstVisible.index) {
position += item.size;
return;
}
// 2) delta of the first visible item
if (item.$index === fetch.firstVisible.index && fetch.firstVisible.delta) {
position -= fetch.firstVisible.delta;
}
// 3) difference between expected and real sizes of fetched items after the first visible
if (shouldCheckPreSizeExpectation_1 && item.preSize && fetch.items.includes(item)) {
position += item.size - item.preSize;
}
});
}
// slow fetch/render case
if (scroll.positionBeforeAsync !== null) {
var diff = render.positionBefore - scroll.positionBeforeAsync;
if (diff !== 0) {
scroller.logger.log("shift position due to fetch-render difference (".concat(diff, ")"));
position += diff;
}
}
// increase the position due to viewport's offset
if (viewport.offset > 0 && (position || fetch.positions.before)) {
position += viewport.offset;
}
return Math.round(position);
};
Adjust.setAdditionalForwardPadding = function (scroller, position) {
var viewport = scroller.viewport, buffer = scroller.buffer, cycle = scroller.state.cycle;
if (!cycle.isInitial || !End.shouldContinueRun(scroller, null)) {
return;
}
var diff = position - viewport.getMaxScrollPosition();
if (diff <= 0) {
return;
}
var last = buffer.getLastVisibleItem();
if (!last) {
return;
}
var size = 0;
var index = last.$index + 1;
while (size <= diff && index <= buffer.absMaxIndex) {
size += buffer.getSizeByIndex(index++);
}
var shift = Math.min(size, diff);
if (shift) {
viewport.paddings.forward.size += shift;
scroller.logger.log("increase fwd padding due to lack of items (".concat(diff, " -> ").concat(shift, ")"));
}
};
Adjust.setPosition = function (scroller, position, done) {
var scroll = scroller.state.scroll, viewport = scroller.viewport, routines = scroller.routines;
if (!scroll.hasPositionChanged(position)) {
return done();
}
scroll.syntheticPosition = position;
scroll.syntheticFulfill = false;
scroll.cancelAnimation = routines.animate(function () {
scroll.cancelAnimation = null;
var inertiaDiff = scroll.positionAfterAdjust - viewport.scrollPosition;
var diffLog = '';
if (inertiaDiff > 0) {
position -= inertiaDiff;
scroll.syntheticPosition = position;
diffLog = " (-".concat(inertiaDiff, ")");
}
scroll.syntheticFulfill = true;
viewport.scrollPosition = position;
scroller.logger.stat('after scroll adjustment' + diffLog);
done();
});
};
return Adjust;
}(BaseProcessFactory(CommonProcess.adjust)));
export default Adjust;
//# sourceMappingURL=adjust.js.map