diff --git a/src/lib/template/dom-repeat.html b/src/lib/template/dom-repeat.html
index 78af69c0f0..db74fa9635 100644
--- a/src/lib/template/dom-repeat.html
+++ b/src/lib/template/dom-repeat.html
@@ -190,19 +190,6 @@
*/
delay: Number,
- /**
- * When `limit` is defined, the number of actually rendered template
- * instances will be limited to this count.
- *
- * Note that if `initialCount` is used, the `limit` property will be
- * automatically controlled and should not be set by the user.
- */
- limit: {
- value: Infinity,
- type: Number,
- observer: '_limitChanged'
- },
-
/**
* Defines an initial count of template instances to render after setting
* the `items` array, before the next paint, and puts the `dom-repeat`
@@ -213,28 +200,16 @@
*/
initialCount: {
type: Number,
- value: 0
- },
-
- /**
- * When `initialCount` is used, defines the number of instances to be
- * created at each animation frame after rendering the `initialCount`.
- * When left to the default `'auto'` value, the chunk count will be
- * throttled automatically using a best effort scheme to maintain the
- * value of the `targetFramerate` property.
- */
- chunkCount: {
- type: Number,
- value: 'auto'
+ observer: '_initializeChunking'
},
/**
- * When `initialCount` is used and `chunkCount` is set to `'auto'`, this
- * property defines a frame rate to target by throttling the number of
- * instances rendered each frame to not exceed the budget for the target
- * frame rate. Setting this to a higher number will allow lower latency
- * and higher throughput for things like event handlers, but will result
- * in a longer time for the remaining items to complete rendering.
+ * When `initialCount` is used, this property defines a frame rate to
+ * target by throttling the number of instances rendered each frame to
+ * not exceed the budget for the target frame rate. Setting this to a
+ * higher number will allow lower latency and higher throughput for
+ * things like event handlers, but will result in a longer time for the
+ * remaining items to complete rendering.
*/
targetFramerate: {
type: Number,
@@ -252,32 +227,29 @@
],
observers: [
- '_itemsChanged(items.*)',
- '_initializeChunkCount(initialCount, chunkCount)'
+ '_itemsChanged(items.*)'
],
created: function() {
this._instances = [];
this._pool = [];
- this._boundRenderChunk = this._renderChunk.bind(this);
+ this._limit = Infinity;
+ var self = this;
+ this._boundRenderChunk = function() {
+ self._renderChunk();
+ };
},
detached: function() {
for (var i=0; i=0; i--) {
var inst = this._instances[i];
- if (inst.isPlaceholder && i=this.limit) {
- inst = this._insertRow(i, inst.__key__, true, true);
+ if (inst.isPlaceholder && i=this._limit) {
+ inst = this._downgradeInstance(i, inst.__key__);
}
keyToIdx[inst.__key__] = i;
if (!inst.isPlaceholder) {
@@ -514,16 +482,16 @@
var inst = this._instances[i];
if (inst) {
inst.__key__ = key;
- if (!inst.isPlaceholder && i < this.limit) {
+ if (!inst.isPlaceholder && i < this._limit) {
inst.__setProperty(this.as, c.getItem(key), true);
}
} else {
- this._insertRow(i, key);
+ this._insertPlaceholder(i, key);
}
}
// Remove any extra instances from previous state
for (var j=this._instances.length-1; j>=i; j--) {
- this._detachRow(j);
+ this._removeInstance(j);
}
},
@@ -576,7 +544,7 @@
var idx = removedIdxs[i];
// Removed idx may be undefined if item was previously filtered out
if (idx !== undefined) {
- this._detachRow(idx);
+ this._removeInstance(idx);
}
}
}
@@ -624,7 +592,7 @@
idx = end + 1;
}
// Insert instance at insertion point
- this._insertRow(idx, key);
+ this._insertPlaceholder(idx, key);
return idx;
},
@@ -638,65 +606,48 @@
splices.forEach(function(s) {
// Detach & pool removed instances
for (var i=0; i= this.limit) {
- inst = {
- isPlaceholder: true,
- __key__: key
- };
- } else {
- if (inst = this._pool.pop()) {
- // TODO(kschaaf): If the pool is shared across turns, parentProps
- // need to be re-set to reused instances in addition to item/key
- inst.__setProperty(this.as, this.collection.getItem(key), true);
- inst.__setProperty('__key__', key, true);
- } else {
- inst = this._generateRow(idx, key);
- }
- var beforeRow = this._instances[replace ? idx + 1 : idx];
- var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this;
- var parentNode = Polymer.dom(this).parentNode;
- Polymer.dom(parentNode).insertBefore(inst.root, beforeNode);
- }
- if (replace) {
- if (makePlaceholder) {
- this._detachRow(idx, true);
- }
- this._instances[idx] = inst;
- } else {
- this._instances.splice(idx, 0, inst);
+ _removeInstance: function(idx) {
+ var inst = this._detachInstance(idx);
+ if (inst) {
+ this._pool.push(inst);
}
- return inst;
+ this._instances.splice(idx, 1);
},
- _generateRow: function(idx, key) {
+ _insertPlaceholder: function(idx, key) {
+ this._instances.splice(idx, 0, {
+ isPlaceholder: true,
+ __key__: key
+ });
+ },
+
+ _generateInstance: function(idx, key) {
var model = {
__key__: key
};
@@ -706,6 +657,37 @@
return inst;
},
+ _upgradePlaceholder: function(idx, key) {
+ var inst = this._pool.pop();
+ if (inst) {
+ // TODO(kschaaf): If the pool is shared across turns, parentProps
+ // need to be re-set to reused instances in addition to item/key
+ inst.__setProperty(this.as, this.collection.getItem(key), true);
+ inst.__setProperty('__key__', key, true);
+ } else {
+ inst = this._generateInstance(idx, key);
+ }
+ var beforeRow = this._instances[idx + 1 ];
+ var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this;
+ var parentNode = Polymer.dom(this).parentNode;
+ Polymer.dom(parentNode).insertBefore(inst.root, beforeNode);
+ this._instances[idx] = inst;
+ return inst;
+ },
+
+ _downgradeInstance: function(idx, key) {
+ var inst = this._detachInstance(idx);
+ if (inst) {
+ this._pool.push(inst);
+ }
+ inst = {
+ isPlaceholder: true,
+ __key__: key
+ };
+ this._instances[idx] = inst;
+ return inst;
+ },
+
// Implements extension point from Templatizer mixin
_showHideChildren: function(hidden) {
for (var i=0; i
-
+
{{item.prop}}
@@ -422,7 +422,7 @@
Polymer({
is: 'x-repeat-limit',
properties: {
- items: {
+ preppedItems: {
value: function() {
var ar = [];
for (var i = 0; i < 20; i++) {
diff --git a/test/unit/dom-repeat.html b/test/unit/dom-repeat.html
index 45eff0fe18..3fb04a5f6c 100644
--- a/test/unit/dom-repeat.html
+++ b/test/unit/dom-repeat.html
@@ -3365,6 +3365,9 @@ x-repeat-chunked
};
test('initial limit', function() {
+ limited.items = limited.preppedItems;
+ limited.$.repeater._limit = 2;
+ limited.$.repeater.render();
var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 2);
checkItemOrder(stamped);
@@ -3381,54 +3384,50 @@ x-repeat-chunked
assert.equal(stamped[0].prop, 'changed again');
});
- test('increase limit', function(done) {
- // Increase limit and test async rendering
- limited.$.repeater.limit = 10;
- setTimeout(function() {
- var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 10);
- checkItemOrder(stamped);
- assert.equal(stamped[3].prop, 'changed again');
- assert.equal(stamped[3].textContent, '3-changed');
- limited.set('items.0.prop', 0);
- limited.set('items.3.prop', 3);
- // Increase limit and test sync rendering
- limited.$.repeater.limit = 20;
- Polymer.dom.flush();
- stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 20);
- checkItemOrder(stamped);
- done();
- });
+ test('increase limit', function() {
+ // Increase limit
+ limited.$.repeater._limit = 10;
+ limited.$.repeater.render();
+ var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 10);
+ checkItemOrder(stamped);
+ assert.equal(stamped[3].prop, 'changed again');
+ assert.equal(stamped[3].textContent, '3-changed');
+ limited.set('items.0.prop', 0);
+ limited.set('items.3.prop', 3);
+ // Increase limit
+ limited.$.repeater._limit = 20;
+ limited.$.repeater.render();
+ stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 20);
+ checkItemOrder(stamped);
});
test('increase limit above items.length', function() {
- limited.$.repeater.limit = 30;
- Polymer.dom.flush();
+ limited.$.repeater._limit = 30;
+ limited.$.repeater.render();
stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 20);
- checkItemOrder(stamped);
+ checkItemOrder(stamped);
});
- test('decrease limit', function(done) {
- // Decrease limit and test async rendering
- limited.$.repeater.limit = 15;
- setTimeout(function() {
- var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 15);
- checkItemOrder(stamped);
- // Decrease limit and test sync rendering
- limited.$.repeater.limit = 0;
- Polymer.dom.flush();
- stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 0);
- done();
- });
+ test('decrease limit', function() {
+ // Decrease limit
+ limited.$.repeater._limit = 15;
+ limited.$.repeater.render();
+ var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 15);
+ checkItemOrder(stamped);
+ // Decrease limit
+ limited.$.repeater._limit = 0;
+ limited.$.repeater.render();
+ stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 0);
});
test('negative limit', function() {
- limited.$.repeater.limit = -10;
- Polymer.dom.flush();
+ limited.$.repeater._limit = -10;
+ limited.$.repeater.render();
stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 0);
});
@@ -3444,64 +3443,59 @@ x-repeat-chunked
};
test('initial limit', function() {
- var items = limited.items;
- limited.$.repeater.limit = 2;
+ limited.$.repeater._limit = 2;
limited.$.repeater.sort = function(a, b) {
return b.prop - a.prop;
};
limited.items = null;
- Polymer.dom.flush();
- limited.items = items;
- Polymer.dom.flush();
+ limited.$.repeater.render();
+ limited.items = limited.preppedItems;
+ limited.$.repeater.render();
var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 2);
checkItemOrder(stamped);
});
- test('increase limit', function(done) {
- // Increase limit and test async rendering
- limited.$.repeater.limit = 10;
- setTimeout(function() {
- var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 10);
- checkItemOrder(stamped);
- // Increase limit and test sync rendering
- limited.$.repeater.limit = 20;
- Polymer.dom.flush();
- stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 20);
- checkItemOrder(stamped);
- done();
- });
+ test('increase limit', function() {
+ // Increase limit
+ limited.$.repeater._limit = 10;
+ limited.$.repeater.render();
+ var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 10);
+ checkItemOrder(stamped);
+ // Increase limit
+ limited.$.repeater._limit = 20;
+ limited.$.repeater.render();
+ stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 20);
+ checkItemOrder(stamped);
});
test('increase limit above items.length', function() {
- limited.$.repeater.limit = 30;
- Polymer.dom.flush();
+ limited.$.repeater._limit = 30;
+ limited.$.repeater.render();
stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 20);
- checkItemOrder(stamped);
+ checkItemOrder(stamped);
});
- test('decrease limit', function(done) {
- // Decrease limit and test async rendering
- limited.$.repeater.limit = 15;
- setTimeout(function() {
- var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 15);
- checkItemOrder(stamped);
- // Decrease limit and test sync rendering
- limited.$.repeater.limit = 0;
- Polymer.dom.flush();
- stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 0);
- done();
- });
+ test('decrease limit', function() {
+ // Decrease limit
+ limited.$.repeater._limit = 15;
+ limited.$.repeater.render();
+ var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 15);
+ checkItemOrder(stamped);
+ // Decrease limit
+ limited.$.repeater._limit = 0;
+ limited.$.repeater.render();
+ stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 0);
});
test('negative limit', function() {
- limited.$.repeater.limit = -10;
- Polymer.dom.flush();
+ limited.$.repeater._limit = -10;
+ limited.$.repeater.render();
stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 0);
});
@@ -3518,64 +3512,60 @@ x-repeat-chunked
test('initial limit', function() {
var items = limited.items;
- limited.$.repeater.limit = 2;
+ limited.$.repeater._limit = 2;
limited.$.repeater.sort = null;
limited.$.repeater.filter = function(a) {
return (a.prop % 2) === 0;
};
limited.items = null;
- Polymer.dom.flush();
+ limited.$.repeater.render();
limited.items = items;
- Polymer.dom.flush();
+ limited.$.repeater.render();
var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 2);
checkItemOrder(stamped);
});
- test('increase limit', function(done) {
- // Increase limit and test async rendering
- limited.$.repeater.limit = 5;
- setTimeout(function() {
- var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 5);
- checkItemOrder(stamped);
- // Increase limit and test sync rendering
- limited.$.repeater.limit = 10;
- Polymer.dom.flush();
- stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 10);
- checkItemOrder(stamped);
- done();
- });
+ test('increase limit', function() {
+ // Increase limit
+ limited.$.repeater._limit = 5;
+ limited.$.repeater.render();
+ var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 5);
+ checkItemOrder(stamped);
+ // Increase limit
+ limited.$.repeater._limit = 10;
+ limited.$.repeater.render();
+ stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 10);
+ checkItemOrder(stamped);
});
test('increase limit above items.length', function() {
- limited.$.repeater.limit = 30;
- Polymer.dom.flush();
+ limited.$.repeater._limit = 30;
+ limited.$.repeater.render();
stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 10);
checkItemOrder(stamped);
});
- test('decrease limit', function(done) {
- // Decrease limit and test async rendering
- limited.$.repeater.limit = 5;
- setTimeout(function() {
- var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 5);
- checkItemOrder(stamped);
- // Decrease limit and test sync rendering
- limited.$.repeater.limit = 0;
- Polymer.dom.flush();
- stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 0);
- done();
- });
+ test('decrease limit', function() {
+ // Decrease limit
+ limited.$.repeater._limit = 5;
+ limited.$.repeater.render();
+ var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 5);
+ checkItemOrder(stamped);
+ // Decrease limit
+ limited.$.repeater._limit = 0;
+ limited.$.repeater.render();
+ stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 0);
});
test('negative limit', function() {
- limited.$.repeater.limit = -10;
- Polymer.dom.flush();
+ limited.$.repeater._limit = -10;
+ limited.$.repeater.render();
stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 0);
});
@@ -3592,7 +3582,7 @@ x-repeat-chunked
test('initial limit', function() {
var items = limited.items;
- limited.$.repeater.limit = 2;
+ limited.$.repeater._limit = 2;
limited.$.repeater.sort = function(a, b) {
return b.prop - a.prop;
};
@@ -3600,58 +3590,54 @@ x-repeat-chunked
return (a.prop % 2) === 0;
};
limited.items = null;
- Polymer.dom.flush();
+ limited.$.repeater.render();
limited.items = items;
- Polymer.dom.flush();
+ limited.$.repeater.render();
var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 2);
checkItemOrder(stamped);
});
- test('increase limit', function(done) {
- // Increase limit and test async rendering
- limited.$.repeater.limit = 5;
- setTimeout(function() {
- var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 5);
- checkItemOrder(stamped);
- // Increase limit and test sync rendering
- limited.$.repeater.limit = 10;
- Polymer.dom.flush();
- stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 10);
- checkItemOrder(stamped);
- done();
- });
+ test('increase limit', function() {
+ // Increase limit
+ limited.$.repeater._limit = 5;
+ limited.$.repeater.render();
+ var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 5);
+ checkItemOrder(stamped);
+ // Increase limit
+ limited.$.repeater._limit = 10;
+ limited.$.repeater.render();
+ stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 10);
+ checkItemOrder(stamped);
});
test('increase limit above items.length', function() {
- limited.$.repeater.limit = 30;
- Polymer.dom.flush();
+ limited.$.repeater._limit = 30;
+ limited.$.repeater.render();
stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 10);
checkItemOrder(stamped);
});
- test('decrease limit', function(done) {
- // Decrease limit and test async rendering
- limited.$.repeater.limit = 5;
- setTimeout(function() {
- var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 5);
- checkItemOrder(stamped);
- // Decrease limit and test sync rendering
- limited.$.repeater.limit = 0;
- Polymer.dom.flush();
- stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
- assert.equal(stamped.length, 0);
- done();
- });
+ test('decrease limit', function() {
+ // Decrease limit
+ limited.$.repeater._limit = 5;
+ limited.$.repeater.render();
+ var stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 5);
+ checkItemOrder(stamped);
+ // Decrease limit
+ limited.$.repeater._limit = 0;
+ limited.$.repeater.render();
+ stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
+ assert.equal(stamped.length, 0);
});
test('negative limit', function() {
- limited.$.repeater.limit = -10;
- Polymer.dom.flush();
+ limited.$.repeater._limit = -10;
+ limited.$.repeater.render();
stamped = Polymer.dom(limited.root).querySelectorAll('*:not(template)');
assert.equal(stamped.length, 0);
});