Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit bbca34f

Browse files
kseamonThomasBurleson
authored andcommitted
fix(virtualRepeat): Recover from scroll events that occur when hidden Fixes #5448.
fix(virtualRepeat): Recover from scroll events that occur when hidden Fixes #5448. Closes #6389.
1 parent c0f5aea commit bbca34f

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

src/components/virtualRepeat/virtual-repeater.js

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ function VirtualRepeatContainerController(
104104
this.originalSize = null;
105105
/** @type {number} Amount to offset the total scroll size by. */
106106
this.offsetSize = parseInt(this.$attrs.mdOffsetSize, 10) || 0;
107+
/** @type {?string} height or width element style on the container prior to auto-shrinking. */
108+
this.oldElementSize = null;
107109

108110
if (this.$attrs.mdTopIndex) {
109111
/** @type {function(angular.Scope): number} Binds to topIndex on Angular scope */
@@ -184,8 +186,16 @@ VirtualRepeatContainerController.prototype.getSize = function() {
184186
* @param {number} The new size to set.
185187
*/
186188
VirtualRepeatContainerController.prototype.setSize_ = function(size) {
189+
var dimension = this.getDimensionName_();
190+
187191
this.size = size;
188-
this.$element[0].style[this.isHorizontal() ? 'width' : 'height'] = size + 'px';
192+
this.$element[0].style[dimension] = size + 'px';
193+
};
194+
195+
196+
VirtualRepeatContainerController.prototype.unsetSize_ = function() {
197+
this.$element[0].style[this.getDimensionName_()] = this.oldElementSize;
198+
this.oldElementSize = null;
189199
};
190200

191201

@@ -197,6 +207,11 @@ VirtualRepeatContainerController.prototype.updateSize = function() {
197207
? this.$element[0].clientWidth
198208
: this.$element[0].clientHeight;
199209

210+
// Recheck the scroll position after updating the size. This resolves
211+
// problems that can result if the scroll position was measured while the
212+
// element was display: none or detached from the document.
213+
this.handleScroll_();
214+
200215
this.repeater && this.repeater.containerUpdated();
201216
};
202217

@@ -207,13 +222,18 @@ VirtualRepeatContainerController.prototype.getScrollSize = function() {
207222
};
208223

209224

225+
VirtualRepeatContainerController.prototype.getDimensionName_ = function() {
226+
return this.isHorizontal() ? 'width' : 'height';
227+
};
228+
229+
210230
/**
211231
* Sets the scroller element to the specified size.
212232
* @private
213233
* @param {number} size The new size.
214234
*/
215235
VirtualRepeatContainerController.prototype.sizeScroller_ = function(size) {
216-
var dimension = this.isHorizontal() ? 'width' : 'height';
236+
var dimension = this.getDimensionName_();
217237
var crossDimension = this.isHorizontal() ? 'height' : 'width';
218238

219239
// Clear any existing dimensions.
@@ -255,16 +275,21 @@ VirtualRepeatContainerController.prototype.sizeScroller_ = function(size) {
255275
VirtualRepeatContainerController.prototype.autoShrink_ = function(size) {
256276
var shrinkSize = Math.max(size, this.autoShrinkMin * this.repeater.getItemSize());
257277
if (this.autoShrink && shrinkSize !== this.size) {
278+
if (this.oldElementSize === null) {
279+
this.oldElementSize = this.$element[0].style[this.getDimensionName_()];
280+
}
281+
258282
var currentSize = this.originalSize || this.size;
259283
if (!currentSize || shrinkSize < currentSize) {
260284
if (!this.originalSize) {
261285
this.originalSize = this.size;
262286
}
263287

264288
this.setSize_(shrinkSize);
265-
} else if (this.originalSize) {
266-
this.setSize_(this.originalSize);
289+
} else if (this.originalSize !== null) {
290+
this.unsetSize_();
267291
this.originalSize = null;
292+
this.updateSize();
268293
}
269294

270295
this.repeater.containerUpdated();

src/components/virtualRepeat/virtual-repeater.spec.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,17 +580,25 @@ describe('<md-virtual-repeat>', function() {
580580
expect(offsetter.children().length).toBe(43);
581581
});
582582

583-
it('should recheck container size on $md-resize scope event', function() {
583+
it('should recheck container size and scroll position on $md-resize scope ' +
584+
'event', function() {
584585
scope.items = createItems(100);
585586
createRepeater();
586587
// Expect 13 children (10 + 3 extra).
587588
expect(offsetter.children().length).toBe(13);
588589

590+
container.css('height', '300px');
591+
scope.$parent.$broadcast('$md-resize');
592+
593+
// Expect 33 children (30 + 3 extra).
594+
expect(offsetter.children().length).toBe(33);
595+
589596
container.css('height', '400px');
597+
scroller[0].scrollTop = 20;
590598
scope.$parent.$broadcast('$md-resize');
591599

592-
// Expect 43 children (40 + 3 extra).
593-
expect(offsetter.children().length).toBe(43);
600+
// Expect 43 children (40 + 5 extra).
601+
expect(offsetter.children().length).toBe(45);
594602
});
595603

596604
it('should shrink when initial results require shrinking', inject(function() {

0 commit comments

Comments
 (0)