diff --git a/src/array-virtual-repeat-strategy.ts b/src/array-virtual-repeat-strategy.ts index 837861d..37fad23 100644 --- a/src/array-virtual-repeat-strategy.ts +++ b/src/array-virtual-repeat-strategy.ts @@ -167,7 +167,7 @@ export class ArrayVirtualRepeatStrategy extends ArrayRepeatStrategy implements I ) { let viewIndex = this._getViewIndex(repeat, repeat.viewSlot, collectionIndex); let overrideContext = createFullOverrideContext(repeat, array[collectionIndex], collectionIndex, array.length); - repeat.removeView(viewIndex, true, true); + repeat.removeView(viewIndex, /*return to cache?*/true, /*skip animation?*/true); repeat.insertView(viewIndex, overrideContext.bindingContext, overrideContext); } } @@ -310,11 +310,11 @@ export class ArrayVirtualRepeatStrategy extends ArrayRepeatStrategy implements I repeat._calcInitialHeights(1); } else if (repeat.viewCount() > repeat._viewsLength) { if (hasDistanceToBottomViewPort) { - repeat.removeView(0, true, true); + repeat.removeView(0, /*return to cache?*/true, /*skip animation?*/true); repeat._topBufferHeight = repeat._topBufferHeight + repeat.itemHeight; repeat._updateBufferElements(); } else { - repeat.removeView(repeat.viewCount() - 1, true, true); + repeat.removeView(repeat.viewCount() - 1, /*return to cache?*/true, /*skip animation?*/true); repeat._bottomBufferHeight = repeat._bottomBufferHeight + repeat.itemHeight; } } @@ -328,8 +328,4 @@ export class ArrayVirtualRepeatStrategy extends ArrayRepeatStrategy implements I } repeat._updateBufferElements(); } - - onScroll(newInfo: IScrollerInfo, oldInfo: IScrollerInfo): void { - - } } diff --git a/src/interfaces.ts b/src/interfaces.ts index db8a78c..26d6edf 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -72,11 +72,6 @@ export interface IVirtualRepeatStrategy extends RepeatStrategy { * @param splices Records of array changes. */ instanceMutated(repeat: VirtualRepeat, array: any[], splices: ICollectionObserverSplice[]): void; - - /** - * Handle repeat scroller scroll - */ - onScroll(newInfo: IScrollerInfo, newTop: IScrollerInfo): void; } /** diff --git a/src/null-virtual-repeat-strategy.ts b/src/null-virtual-repeat-strategy.ts index 94b7667..97a021b 100644 --- a/src/null-virtual-repeat-strategy.ts +++ b/src/null-virtual-repeat-strategy.ts @@ -13,6 +13,4 @@ export class NullVirtualRepeatStrategy extends NullRepeatStrategy implements IVi repeat.removeAllViews(/**return to cache?*/true, /**skip animation?*/false); repeat._resetCalculation(); } - - onScroll() {} } diff --git a/src/template-strategy-default.ts b/src/template-strategy-default.ts index 2432fd2..690d888 100644 --- a/src/template-strategy-default.ts +++ b/src/template-strategy-default.ts @@ -42,7 +42,7 @@ export class DefaultTemplateStrategy implements ITemplateStrategy { return lastEl === topBuffer ? null : lastEl; } - getTopBufferDistance(topBuffer: Element): number { - return 0; + getTopBufferDistance(topBuffer: HTMLElement): number { + return topBuffer.offsetTop; } } diff --git a/src/virtual-repeat.ts b/src/virtual-repeat.ts index b1577c5..06caae1 100644 --- a/src/virtual-repeat.ts +++ b/src/virtual-repeat.ts @@ -337,10 +337,12 @@ export class VirtualRepeat extends AbstractRepeater { /**@override */ detached(): void { - if (hasOverflowScroll(this.scrollContainer)) { - this.scrollContainer.removeEventListener('scroll', this.scrollListener); + const scrollCt = this.scrollContainer; + const scrollListener = this.scrollListener; + if (hasOverflowScroll(scrollCt)) { + scrollCt.removeEventListener('scroll', scrollListener); } else { - DOM.removeEventListener('scroll', this.scrollListener, false); + DOM.removeEventListener('scroll', scrollListener, false); } this.isLastIndex = undefined; this._fixedHeightContainer = false; @@ -351,12 +353,12 @@ export class VirtualRepeat extends AbstractRepeater { this.topBufferEl = this.bottomBufferEl = this.scrollContainer = this.scrollListener = null; this.scrollContainerHeight = 0; this.distanceToTop = 0; - this.removeAllViews(true, false); + this.removeAllViews(/*return to cache?*/true, /*skip animation?*/false); this._unsubscribeCollection(); - PLATFORM.global.clearInterval(this._calcDistanceToTopInterval); - if (this._sizeInterval) { - PLATFORM.global.clearInterval(this._sizeInterval); - } + const $clearInterval = PLATFORM.global.clearInterval; + $clearInterval(this._calcDistanceToTopInterval); + $clearInterval(this._sizeInterval); + this._sizeInterval = this._calcDistanceToTopInterval = 0; } /**@override */ @@ -393,7 +395,11 @@ export class VirtualRepeat extends AbstractRepeater { const items = this.items; const shouldCalculateSize = !!items; const strategy = this.strategy = this.strategyLocator.getStrategy(items); - + + if (strategy === null) { + throw new Error('Value is not iterateable for virtual repeat.'); + } + if (shouldCalculateSize) { const currentItemCount = items.length; if (currentItemCount > 0 && this.viewCount() === 0) { @@ -556,8 +562,17 @@ export class VirtualRepeat extends AbstractRepeater { return; } const itemHeight = this.itemHeight; + const topBufferDistance = this.templateStrategy.getTopBufferDistance(this.topBufferEl); + /** + * Real scroll top calculated based on current scroll top of scroller and top buffer {height + distance to top} + * as there could be elements before top buffer and it affects real scroll top of the selected repeat + * + * Calculation are done differently based on the scroller: + * - not document: the scroll top of this repeat is calculated based on current scroller.scrollTop and the distance to top of `top buffer` + * - document: the scroll top is the substraction of `pageYOffset` and distance to top of current buffer element (logic needs revised) + */ const scrollTop = this._fixedHeightContainer - ? this.scrollContainer.scrollTop + ? (this.scrollContainer.scrollTop - topBufferDistance) : (pageYOffset - this.distanceToTop); const scrollerInfo = this.getScrollerInfo(); const elementsInView = this.elementsInView;