@@ -31,6 +31,10 @@ angular.module('material.components.virtualRepeat', [
31
31
*
32
32
* @param {boolean= } md-orient-horizontal Whether the container should scroll horizontally
33
33
* (defaults to scrolling vertically).
34
+ * @param {boolean= } md-auto-shrink When present, the container will shrink to fit
35
+ * the number of items when that number is less than its original size.
36
+ * @param {number= } md-auto-shrink-min Minimum number of items that md-auto-shrink
37
+ * will shrink to (default: 0).
34
38
*/
35
39
function VirtualRepeatContainerDirective ( ) {
36
40
return {
@@ -89,6 +93,12 @@ function VirtualRepeatContainerController($$rAF, $scope, $element, $attrs) {
89
93
this . horizontal = this . $attrs . hasOwnProperty ( 'mdOrientHorizontal' ) ;
90
94
/** @type {!VirtualRepeatController } The repeater inside of this container */
91
95
this . repeater = null ;
96
+ /** @type {boolean } Whether auto-shrink is enabled */
97
+ this . autoShrink = this . $attrs . hasOwnProperty ( 'mdAutoShrink' ) ;
98
+ /** @type {number } Minimum number of items to auto-shrink to */
99
+ this . autoShrinkMin = parseInt ( this . $attrs . mdAutoShrinkMin , 10 ) || 0 ;
100
+ /** @type {?number } Original container size when shrank */
101
+ this . originalSize = null ;
92
102
93
103
this . scroller = $element [ 0 ] . getElementsByClassName ( 'md-virtual-repeat-scroller' ) [ 0 ] ;
94
104
this . sizer = this . scroller . getElementsByClassName ( 'md-virtual-repeat-sizer' ) [ 0 ] ;
@@ -129,8 +139,21 @@ VirtualRepeatContainerController.prototype.getSize = function() {
129
139
} ;
130
140
131
141
142
+ /**
143
+ * Resizes the container.
144
+ * @private
145
+ * @param {number } The new size to set.
146
+ */
147
+ VirtualRepeatContainerController . prototype . setSize_ = function ( size ) {
148
+ this . size = size ;
149
+ this . $element [ 0 ] . style [ this . isHorizontal ( ) ? 'width' : 'height' ] = size + 'px' ;
150
+ } ;
151
+
152
+
132
153
/** Instructs the container to re-measure its size. */
133
154
VirtualRepeatContainerController . prototype . updateSize = function ( ) {
155
+ if ( this . originalSize ) return ;
156
+
134
157
this . size = this . isHorizontal ( )
135
158
? this . $element [ 0 ] . clientWidth
136
159
: this . $element [ 0 ] . clientHeight ;
@@ -145,44 +168,76 @@ VirtualRepeatContainerController.prototype.getScrollSize = function() {
145
168
146
169
147
170
/**
148
- * Sets the scrollHeight or scrollWidth. Called by the repeater based on
149
- * its item count and item size.
171
+ * Sets the scroller element to the specified size.
172
+ * @private
150
173
* @param {number } size The new size.
151
174
*/
152
- VirtualRepeatContainerController . prototype . setScrollSize = function ( size ) {
153
- if ( this . scrollSize !== size ) {
154
- var dimension = this . isHorizontal ( ) ? 'width' : 'height' ;
155
- var crossDimension = this . isHorizontal ( ) ? 'height' : 'width' ;
156
-
157
- // If the size falls within the browser's maximum explicit size for a single element, we can
158
- // set the size and be done. Otherwise, we have to create children that add up the the desired
159
- // size.
160
- if ( size < MAX_ELEMENT_SIZE ) {
161
- this . sizer . style [ dimension ] = size + 'px' ;
162
- } else {
163
- // Clear any existing dimensions.
164
- this . sizer . innerHTML = '' ;
165
- this . sizer . style [ dimension ] = 'auto' ;
166
- this . sizer . style [ crossDimension ] = 'auto' ;
167
-
168
- // Divide the total size we have to render into N max-size pieces.
169
- var numChildren = Math . floor ( size / MAX_ELEMENT_SIZE ) ;
170
-
171
- // Element template to clone for each max-size piece.
172
- var sizerChild = document . createElement ( 'div' ) ;
173
- sizerChild . style [ dimension ] = MAX_ELEMENT_SIZE + 'px' ;
174
- sizerChild . style [ crossDimension ] = '1px' ;
175
-
176
- for ( var i = 0 ; i < numChildren ; i ++ ) {
177
- this . sizer . appendChild ( sizerChild . cloneNode ( false ) ) ;
175
+ VirtualRepeatContainerController . prototype . sizeScroller_ = function ( size ) {
176
+ var dimension = this . isHorizontal ( ) ? 'width' : 'height' ;
177
+ var crossDimension = this . isHorizontal ( ) ? 'height' : 'width' ;
178
+
179
+ // If the size falls within the browser's maximum explicit size for a single element, we can
180
+ // set the size and be done. Otherwise, we have to create children that add up the the desired
181
+ // size.
182
+ if ( size < MAX_ELEMENT_SIZE ) {
183
+ this . sizer . style [ dimension ] = size + 'px' ;
184
+ } else {
185
+ // Clear any existing dimensions.
186
+ this . sizer . innerHTML = '' ;
187
+ this . sizer . style [ dimension ] = 'auto' ;
188
+ this . sizer . style [ crossDimension ] = 'auto' ;
189
+
190
+ // Divide the total size we have to render into N max-size pieces.
191
+ var numChildren = Math . floor ( size / MAX_ELEMENT_SIZE ) ;
192
+
193
+ // Element template to clone for each max-size piece.
194
+ var sizerChild = document . createElement ( 'div' ) ;
195
+ sizerChild . style [ dimension ] = MAX_ELEMENT_SIZE + 'px' ;
196
+ sizerChild . style [ crossDimension ] = '1px' ;
197
+
198
+ for ( var i = 0 ; i < numChildren ; i ++ ) {
199
+ this . sizer . appendChild ( sizerChild . cloneNode ( false ) ) ;
200
+ }
201
+
202
+ // Re-use the element template for the remainder.
203
+ sizerChild . style [ dimension ] = ( size - ( numChildren * MAX_ELEMENT_SIZE ) ) + 'px' ;
204
+ this . sizer . appendChild ( sizerChild ) ;
205
+ }
206
+ } ;
207
+
208
+
209
+ /**
210
+ * If auto-shrinking is enabled, shrinks or unshrinks as appropriate.
211
+ * @private
212
+ * @param {number } size The new size.
213
+ */
214
+ VirtualRepeatContainerController . prototype . autoShrink_ = function ( size ) {
215
+ var shrinkSize = Math . max ( size , this . autoShrinkMin * this . repeater . getItemSize ( ) ) ;
216
+ if ( this . autoShrink && shrinkSize !== this . size ) {
217
+ if ( shrinkSize < ( this . originalSize || this . size ) ) {
218
+ if ( ! this . originalSize ) {
219
+ this . originalSize = this . size ;
178
220
}
179
221
180
- // Re-use the element template for the remainder.
181
- sizerChild . style [ dimension ] = ( size - ( numChildren * MAX_ELEMENT_SIZE ) ) + 'px' ;
182
- this . sizer . appendChild ( sizerChild ) ;
222
+ this . setSize_ ( shrinkSize ) ;
223
+ } else if ( this . originalSize ) {
224
+ this . setSize_ ( this . originalSize ) ;
225
+ this . originalSize = null ;
183
226
}
184
227
}
228
+ } ;
229
+
230
+
231
+ /**
232
+ * Sets the scrollHeight or scrollWidth. Called by the repeater based on
233
+ * its item count and item size.
234
+ * @param {number } size The new size.
235
+ */
236
+ VirtualRepeatContainerController . prototype . setScrollSize = function ( size ) {
237
+ if ( this . scrollSize === size ) return ;
185
238
239
+ this . sizeScroller_ ( size ) ;
240
+ this . autoShrink_ ( size ) ;
186
241
this . scrollSize = size ;
187
242
} ;
188
243
0 commit comments