-
Notifications
You must be signed in to change notification settings - Fork 3
/
list.js
56 lines (52 loc) · 1.44 KB
/
list.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
/**
* @param {Element} parent
* @param {Function} factory
* @param {Object} [options]
* @return {Object}
*/
export default function(parent, factory, options) {
return {
parent: parent,
factory: factory,
before: (options && options.before) || null,
after: (options && options.after) || null,
update: updateList,
key: (options && options.key) || ( (v,i) => i ), //TODO simplify
map: Object.create(null),
}
}
/**
* @param {Array} arr
* @return {Node}
*/
function updateList(arr) {
var parent = this.parent,
spot = this.after ? this.after.nextSibling : parent.firstChild,
getK = this.key,
kids = Object.create(null)
if (!arr.length && !this.before && !this.after) parent.textContent = ''
else {
for (var i = 0; i < arr.length; ++i) {
//TODO skip .constructor
var key = getK.constructor === Function ? getK(arr[i], i, arr) : arr[i][getK], //TODO simplify to functions only
kid = this.map[key]
//create or update kid
if (kid) kid.update && kid.update(arr[i], key, arr) //eslint-disable-line
else kid = this.factory(arr[i], i, arr)
kids[key] = kid
//place kid
if (!spot) parent.appendChild(kid)
else if (kid === spot.nextSibling) parent.removeChild(spot)
else if (kid !== spot) parent.insertBefore(kid, spot)
spot = kid.nextSibling
}
//delete remaining
while (spot !== this.before) {
var next = spot.nextSibling
parent.removeChild(spot)
spot = next
}
}
this.map = kids
return this
}