-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
105 lines (92 loc) · 2.65 KB
/
index.js
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
var observe = require('array-observer');
module.exports = function(View) {
View.directive('each', {
bind: function(el){
this.View = View.create(el.innerHTML);
el.innerHTML = '';
this.previous = {};
},
update: function(items, el, view){
var Child = this.View;
var self = this;
var replacing = false;
el.innerHTML = '';
// The new value isn't an array.
if(Array.isArray(items) === false) {
throw new Error(items + ' should be an array');
}
// remove the previous emitter so that we don't
// keep watching the old array for changes
if(this.previous.emitter) {
this.previous.emitter.off();
}
// Destroy any old views
if(this.previous.items) {
this.previous.items.forEach(function(view){
view.destroy();
});
}
function reposition() {
items.forEach(function(view, i){
view.set('$index', i).appendTo(self.node);
});
}
function createViewFromValue(item, i) {
var data = {};
if(typeof item === 'object') data = item;
data.$index = i;
data.$value = item;
var child = new Child({
owner: view,
scope: view,
data: data
});
return child;
}
// Replace all objects in the array with views
items.forEach(function(obj, index){
var view = createViewFromValue(obj, index);
items.splice(index, 1, view);
});
// Watch the array for changes
var emitter = observe(items);
// Items are added to the array
emitter.on('add', function(item, index){
if(replacing) return;
var view = createViewFromValue(item, index);
replacing = true;
items.splice(index, 1, view);
replacing = false;
reposition();
});
// Items are removed from the array
emitter.on('remove', function(view){
if(view instanceof Child) {
view.destroy();
reposition();
}
});
// Re-render everything on a sort
emitter.on('sort', function(){
reposition();
});
// Add all of the views to the DOM immediately
reposition();
// Store it so that we can destroy all of the views
// if the array is changed
this.previous.items = items;
this.previous.emitter = emitter;
},
unbind: function(){
if(this.previous.emitter) {
this.previous.emitter.off();
}
if(this.previous.items) {
this.previous.items.forEach(function(view){
view.destroy();
});
}
this.previous = {};
}
});
}