Skip to content
This repository was archived by the owner on Mar 13, 2018. It is now read-only.

Commit 786825e

Browse files
committed
added prepareInstancePositionChanged delegate method
[email protected], arv BUG= Review URL: https://codereview.appspot.com/14743044
1 parent 8242f08 commit 786825e

File tree

2 files changed

+128
-8
lines changed

2 files changed

+128
-8
lines changed

src/TemplateBinding.js

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,14 @@
10011001
return instanceNodes;
10021002
},
10031003

1004+
getDelegateFunction: function(delegate, name, template) {
1005+
if (!delegate || typeof delegate[name] !== 'function')
1006+
return null;
1007+
1008+
var fn = delegate[name](template);
1009+
return typeof fn === 'function' ? fn : null;
1010+
},
1011+
10041012
handleSplices: function(splices) {
10051013
if (this.closed)
10061014
return;
@@ -1014,10 +1022,15 @@
10141022
}
10151023

10161024
if (this.instanceModelFn_ === undefined) {
1017-
if (delegate && typeof delegate.prepareInstanceModel === 'function')
1018-
this.instanceModelFn_ = delegate.prepareInstanceModel(template);
1019-
if (typeof this.instanceModelFn_ !== 'function')
1020-
this.instanceModelFn_ = false;
1025+
this.instanceModelFn_ = this.getDelegateFunction(delegate,
1026+
'prepareInstanceModel',
1027+
template);
1028+
}
1029+
1030+
if (this.instancePositionChangedFn_ === undefined) {
1031+
this.instancePositionChangedFn_ =
1032+
this.getDelegateFunction(delegate, 'prepareInstancePositionChanged',
1033+
template);
10211034
}
10221035

10231036
var instanceCache = new Map;
@@ -1061,6 +1074,55 @@
10611074
instanceCache.forEach(function(instanceNodes) {
10621075
this.closeInstanceBindings(instanceNodes.bound);
10631076
}, this);
1077+
1078+
if (this.instancePositionChangedFn_)
1079+
this.reportInstancesMoved(splices);
1080+
},
1081+
1082+
reportInstanceMoved: function(index) {
1083+
var previousTerminator = this.getTerminatorAt(index - 1);
1084+
var terminator = this.getTerminatorAt(index);
1085+
if (previousTerminator === terminator)
1086+
return; // instance has zero nodes.
1087+
1088+
// We must use the first node of the instance, because any subsequent
1089+
// nodes may have been generated by sub-templates.
1090+
// TODO(rafaelw): This is brittle WRT instance mutation -- e.g. if the
1091+
// first node was removed by script.
1092+
var templateInstance = previousTerminator.nextSibling.templateInstance;
1093+
this.instancePositionChangedFn_(templateInstance, index);
1094+
},
1095+
1096+
reportInstancesMoved: function(splices) {
1097+
var index = 0;
1098+
var offset = 0;
1099+
for (var i = 0; i < splices.length; i++) {
1100+
var splice = splices[i];
1101+
if (offset != 0) {
1102+
while (index < splice.index) {
1103+
this.reportInstanceMoved(index);
1104+
index++;
1105+
}
1106+
} else {
1107+
index = splice.index;
1108+
}
1109+
1110+
while (index < splice.index + splice.addedCount) {
1111+
this.reportInstanceMoved(index);
1112+
index++;
1113+
}
1114+
1115+
offset += splice.addedCount - splice.removed.length;
1116+
}
1117+
1118+
if (offset == 0)
1119+
return;
1120+
1121+
var length = this.terminators.length / 2;
1122+
while (index < length) {
1123+
this.reportInstanceMoved(index);
1124+
index++;
1125+
}
10641126
},
10651127

10661128
closeInstanceBindings: function(bound) {

tests/tests.js

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,7 +1859,7 @@ suite('Template Instantiation', function() {
18591859

18601860
var template = div.firstChild;
18611861

1862-
var model = {
1862+
var model = {
18631863
show: true,
18641864
items: [1]
18651865
};
@@ -1890,7 +1890,7 @@ suite('Binding Delegate API', function() {
18901890

18911891
teardown(doTeardown);
18921892

1893-
test('Registration', function() {
1893+
test('prepareBinding', function() {
18941894
var model = { foo: 'bar'};
18951895
var prepareBindData = {
18961896
type: 'prepare',
@@ -1967,7 +1967,7 @@ suite('Binding Delegate API', function() {
19671967
assert.strictEqual(0, testData.length);
19681968
});
19691969

1970-
test('getInstanceModel', function() {
1970+
test('prepareInstanceModel', function() {
19711971
var model = [{ foo: 1 }, { foo: 2 }, { foo: 3 }];
19721972

19731973
var div = createTestHtml(
@@ -2017,7 +2017,7 @@ suite('Binding Delegate API', function() {
20172017
assert.strictEqual(0, testData.length);
20182018
});
20192019

2020-
test('getInstanceModel - reorder instances', function() {
2020+
test('prepareInstanceModel - reorder instances', function() {
20212021
var model = [0, 1, 2];
20222022

20232023
var div = createTestHtml(
@@ -2048,6 +2048,64 @@ suite('Binding Delegate API', function() {
20482048
assert.strictEqual(3, callCount);
20492049
});
20502050

2051+
test('prepareInstancePositionChanged', function() {
2052+
var model = ['a', 'b', 'c'];
2053+
2054+
var div = createTestHtml(
2055+
'<template repeat>' +
2056+
'{{}}</template>');
2057+
var template = div.firstChild;
2058+
2059+
var testData = [
2060+
{
2061+
template: template,
2062+
},
2063+
{
2064+
model: model[0],
2065+
index: 0
2066+
},
2067+
{
2068+
model: model[1],
2069+
index: 1
2070+
},
2071+
{
2072+
model: model[2],
2073+
index: 2
2074+
},
2075+
// After splice
2076+
{
2077+
model: model[2],
2078+
index: 1
2079+
}
2080+
];
2081+
2082+
var delegate = {
2083+
prepareInstancePositionChanged: function(template) {
2084+
var data = testData.shift();
2085+
assert.strictEqual(data.template, template);
2086+
2087+
return function(templateInstance, index) {
2088+
data = testData.shift();
2089+
assert.strictEqual(data.model, templateInstance.model);
2090+
assert.strictEqual(data.index, index);
2091+
}
2092+
}
2093+
};
2094+
2095+
recursivelySetTemplateModel(div, model, delegate);
2096+
Platform.performMicrotaskCheckpoint();
2097+
assert.strictEqual(4, div.childNodes.length);
2098+
assert.strictEqual('TEMPLATE', div.childNodes[0].tagName);
2099+
assert.strictEqual('a', div.childNodes[1].textContent);
2100+
assert.strictEqual('b', div.childNodes[2].textContent);
2101+
assert.strictEqual('c', div.childNodes[3].textContent);
2102+
2103+
model.splice(1, 1);
2104+
Platform.performMicrotaskCheckpoint();
2105+
2106+
assert.strictEqual(0, testData.length);
2107+
});
2108+
20512109
test('Basic', function() {
20522110
var model = { foo: 2, bar: 4 };
20532111

0 commit comments

Comments
 (0)