-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdynamic-repeat.html
More file actions
123 lines (115 loc) · 4.24 KB
/
Copy pathdynamic-repeat.html
File metadata and controls
123 lines (115 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="temp-latizer.html">
<dom-module id="dynamic-repeat">
<template>
<slot id="slot"></slot>
</template>
<script>
Polymer({
is: 'dynamic-repeat',
properties: {
items: {
type: Array,
},
as: {
type: String,
value: "item"
},
indexAs: {
type: String,
value: "index"
},
attribute: {
type: String,
value: "for"
},
properties: {
type: Array,
value: function() {
return ["prop", "type"];
}
}
},
observers: [
"_generate(items.*)"
],
ready() {
this.templatizerMap = new Map();
this._observer = Polymer.dom(this.$.slot).observeNodes(({addedNodes, removedNodes}) => {
removedNodes
.filter(node => node.nodeName === "TEMPLATE")
.map(node => {
return {
foor: this._getIdentifier(node, this.attribute),
node
};
})
.filter(({foor, node}) => {
return this.templatizerMap.get(foor) === node;
})
.forEach(({node}) => {
this.templatizerMap.delete(foor);
});
addedNodes
.filter(node => node.nodeName === "TEMPLATE")
.forEach(node => {
const foor = this._getIdentifier(node, this.attribute);
this.templatizerMap.set(foor, this._generateTemplatizer(node));
});
if(this.items) {
this._generate();
}
});
},
_getIdentifier(node, attr) {
return node[attr] || node.getAttribute(attr) || "";
},
_generateTemplatizer(template) {
const el = document.createElement("temp-latizer");
el.template = template;
el.as = this.as;
return el;
},
_getTemplatizer(item) {
let templatizer = this.properties.reduce((acc, val) => {
if(!acc) {
acc = this.templatizerMap.get(item[val]);
}
return acc;
}, null);
templatizer = templatizer || this.templatizerMap.get("");
return templatizer;
},
_getInstance(item, index) {
const templatizer = this._getTemplatizer(item);
const inst = templatizer.generate(item);
inst[this.as] = item;
inst[this.indexAs] = index;
return inst;
},
_generate() {
if(!this.items) {
return;
}
(this._instances || [])
.forEach(inst => {
const children = inst._children || inst.children;
for(let i=0; i<children.length; i++) {
Polymer.dom(inst.root).appendChild(children[i]);
}
});
this._instances = this.items
.map(this._getInstance.bind(this))
.filter(inst => !!inst)
.map(inst => {
Polymer.dom(Polymer.dom(this).parentNode).insertBefore(inst.root, this);
return inst;
});
this.dispatchEvent(new CustomEvent('dom-change', {
bubbles: true,
composed: true
}));
},
});
</script>
</dom-module>