@@ -124,20 +124,9 @@ export class VirtualRepeat extends AbstractRepeater {
124124
125125 detached ( ) : void {
126126 this . scrollContainer . removeEventListener ( 'scroll' , this . scrollListener ) ;
127- this . _first = 0 ;
128- this . _previousFirst = 0 ;
129- this . _viewsLength = 0 ;
130- this . _lastRebind = 0 ;
131- this . _topBufferHeight = 0 ;
132- this . _bottomBufferHeight = 0 ;
133- this . _scrollingDown = false ;
134- this . _scrollingUp = false ;
135- this . _switchedDirection = false ;
127+ this . _resetCalculation ( ) ;
136128 this . _isAttached = false ;
137- this . _ticking = false ;
138- this . _hasCalculatedSizes = false ;
139129 this . templateStrategy . removeBufferElements ( this . element , this . topBuffer , this . bottomBuffer ) ;
140- this . isLastIndex = false ;
141130 this . scrollContainer = null ;
142131 this . scrollContainerHeight = null ;
143132 this . distanceToTop = null ;
@@ -162,49 +151,56 @@ export class VirtualRepeat extends AbstractRepeater {
162151 let previousLastViewIndex = this . _getIndexOfLastView ( ) ;
163152
164153 let items = this . items ;
154+ let shouldCalculateSize = ! ! items ;
165155 this . strategy = this . strategyLocator . getStrategy ( items ) ;
166- if ( items . length > 0 && this . viewCount ( ) === 0 ) {
167- this . strategy . createFirstItem ( this ) ;
168- }
169- // Skip scroll handling if we are decreasing item list
170- // Otherwise if expanding list, call the handle scroll below
171- if ( this . _itemsLength >= items . length ) {
172- //Scroll handle is redundant in this case since the instanceChanged will re-evaluate orderings
173- // Also, when items are reduced, we're not having to move any bindings, just a straight rebind of the items in the list
174- this . _skipNextScrollHandle = true ;
175- reducingItems = true ;
176- }
177- this . _checkFixedHeightContainer ( ) ;
178- this . _calcInitialHeights ( items . length ) ;
156+
157+ if ( shouldCalculateSize ) {
158+ if ( items . length > 0 && this . viewCount ( ) === 0 ) {
159+ this . strategy . createFirstItem ( this ) ;
160+ }
161+ // Skip scroll handling if we are decreasing item list
162+ // Otherwise if expanding list, call the handle scroll below
163+ if ( this . _itemsLength >= items . length ) {
164+ //Scroll handle is redundant in this case since the instanceChanged will re-evaluate orderings
165+ // Also, when items are reduced, we're not having to move any bindings, just a straight rebind of the items in the list
166+ this . _skipNextScrollHandle = true ;
167+ reducingItems = true ;
168+ }
169+ this . _checkFixedHeightContainer ( ) ;
170+ this . _calcInitialHeights ( items . length ) ;
171+ }
179172 if ( ! this . isOneTime && ! this . _observeInnerCollection ( ) ) {
180173 this . _observeCollection ( ) ;
181174 }
182175 this . strategy . instanceChanged ( this , items , this . _first ) ;
183- this . _lastRebind = this . _first ; //Reset rebinding
184-
185- if ( reducingItems && previousLastViewIndex > this . items . length - 1 ) {
186- //Do we need to set scrolltop so that we appear at the bottom of the list to match scrolling as far as we could?
187- //We only want to execute this line if we're reducing such that it brings us to the bottom of the new list
188- //Make sure we handle the special case of tables
189- if ( this . scrollContainer . tagName === 'TBODY' ) {
190- let realScrollContainer = this . scrollContainer . parentNode . parentNode ; //tbody > table > container
191- realScrollContainer . scrollTop = realScrollContainer . scrollTop + ( this . viewCount ( ) * this . itemHeight ) ;
192- } else {
193- this . scrollContainer . scrollTop = this . scrollContainer . scrollTop + ( this . viewCount ( ) * this . itemHeight ) ;
176+
177+ if ( shouldCalculateSize ) {
178+ this . _lastRebind = this . _first ; //Reset rebinding
179+
180+ if ( reducingItems && previousLastViewIndex > this . items . length - 1 ) {
181+ //Do we need to set scrolltop so that we appear at the bottom of the list to match scrolling as far as we could?
182+ //We only want to execute this line if we're reducing such that it brings us to the bottom of the new list
183+ //Make sure we handle the special case of tables
184+ if ( this . scrollContainer . tagName === 'TBODY' ) {
185+ let realScrollContainer = this . scrollContainer . parentNode . parentNode ; //tbody > table > container
186+ realScrollContainer . scrollTop = realScrollContainer . scrollTop + ( this . viewCount ( ) * this . itemHeight ) ;
187+ } else {
188+ this . scrollContainer . scrollTop = this . scrollContainer . scrollTop + ( this . viewCount ( ) * this . itemHeight ) ;
189+ }
194190 }
195- }
196- if ( ! reducingItems ) {
197- // If we're expanding our items, then we need to reset our previous first for the next go around of scroll handling
198- this . _previousFirst = this . _first ;
199- this . _scrollingDown = true ; //Simulating the down scroll event to load up data appropriately
200- this . _scrollingUp = false ;
191+ if ( ! reducingItems ) {
192+ // If we're expanding our items, then we need to reset our previous first for the next go around of scroll handling
193+ this . _previousFirst = this . _first ;
194+ this . _scrollingDown = true ; //Simulating the down scroll event to load up data appropriately
195+ this . _scrollingUp = false ;
201196
202- //Make sure we fix any state (we could have been at the last index before, but this doesn't get set until too late for scrolling)
203- this . isLastIndex = this . _getIndexOfLastView ( ) >= this . items . length - 1 ;
204- }
197+ //Make sure we fix any state (we could have been at the last index before, but this doesn't get set until too late for scrolling)
198+ this . isLastIndex = this . _getIndexOfLastView ( ) >= this . items . length - 1 ;
199+ }
205200
206- //Need to readjust the scroll position to "move" us back to the appropriate position, since moving the views will shift our view port's percieved location
207- this . _handleScroll ( ) ;
201+ //Need to readjust the scroll position to "move" us back to the appropriate position, since moving the views will shift our view port's percieved location
202+ this . _handleScroll ( ) ;
203+ }
208204 }
209205
210206 unbind ( ) : void {
@@ -240,6 +236,24 @@ export class VirtualRepeat extends AbstractRepeater {
240236 }
241237 }
242238
239+ _resetCalculation ( ) : void {
240+ this . _first = 0 ;
241+ this . _previousFirst = 0 ;
242+ this . _viewsLength = 0 ;
243+ this . _lastRebind = 0 ;
244+ this . _topBufferHeight = 0 ;
245+ this . _bottomBufferHeight = 0 ;
246+ this . _scrollingDown = false ;
247+ this . _scrollingUp = false ;
248+ this . _switchedDirection = false ;
249+ this . _ticking = false ;
250+ this . _hasCalculatedSizes = false ;
251+ this . _isAtTop = true ;
252+ this . isLastIndex = false ;
253+ this . elementsInView = 0 ;
254+ this . _adjustBufferHeights ( ) ;
255+ }
256+
243257 _onScroll ( ) : void {
244258 if ( ! this . _ticking && ! this . _handlingMutations ) {
245259 requestAnimationFrame ( ( ) => this . _handleScroll ( ) ) ;
@@ -259,6 +273,9 @@ export class VirtualRepeat extends AbstractRepeater {
259273 this . _skipNextScrollHandle = false ;
260274 return ;
261275 }
276+ if ( ! this . items ) {
277+ return ;
278+ }
262279 let itemHeight = this . itemHeight ;
263280 let scrollTop = this . _fixedHeightContainer ? this . scrollContainer . scrollTop : pageYOffset - this . distanceToTop ;
264281 this . _first = Math . floor ( scrollTop / itemHeight ) ;
@@ -457,7 +474,12 @@ export class VirtualRepeat extends AbstractRepeater {
457474 }
458475
459476 _calcInitialHeights ( itemsLength : number ) : void {
460- if ( this . _viewsLength > 0 && this . _itemsLength === itemsLength || this . _viewsLength > 0 && itemsLength < 0 ) {
477+ const isSameLength = this . _viewsLength > 0 && this . _itemsLength === itemsLength ;
478+ if ( isSameLength ) {
479+ return ;
480+ }
481+ if ( itemsLength < 1 ) {
482+ this . _resetCalculation ( ) ;
461483 return ;
462484 }
463485 this . _hasCalculatedSizes = true ;
0 commit comments