1
+ var DomArray = ( function ( ) {
2
+
3
+ // constructor
4
+
5
+ function DomArray ( collection , parent , renderer ) {
6
+ this . parent = parent ;
7
+ this . renderer = renderer ;
8
+ this . collection = collection ;
9
+ this . nodeMap = typeof Map === 'function' ? new Map ( ) : null ;
10
+
11
+ this . push . apply ( this , collection ) ;
12
+
13
+ // observe changes on collection if it's observable
14
+ if ( typeof collection . on === 'function' ) {
15
+ var methods = 'shift pop unshift push splice reverse sort' . split ( ' ' ) ;
16
+ each ( methods , function ( method ) {
17
+ collection . on ( method , this [ method ] . bind ( this ) ) ;
18
+ } , this ) ;
19
+ }
20
+ } ;
21
+
22
+
23
+ // methods that remove items
24
+
25
+ DomArray . prototype . shift = function ( ) {
26
+ this . parent . removeChild ( this . parent . firstChild ) ;
27
+ } ;
28
+
29
+ DomArray . prototype . pop = function ( ) {
30
+ this . parent . removeChild ( this . parent . lastChild ) ;
31
+ } ;
32
+
33
+
34
+ // methods that add items
35
+
36
+ DomArray . prototype . push = function ( ) {
37
+ if ( ! arguments . length ) return ;
38
+ var node = renderAll ( arguments , this . renderer ) ;
39
+ this . parent . appendChild ( node ) ;
40
+ } ;
41
+
42
+ DomArray . prototype . unshift = function ( ) {
43
+ if ( ! arguments . length ) return ;
44
+ var node = renderAll ( arguments , this . renderer ) ;
45
+ this . parent . insertBefore ( node , this . parent . firstChild ) ;
46
+ } ;
47
+
48
+
49
+ // other methods
50
+
51
+ DomArray . prototype . splice = function ( start , deleteCount ) {
52
+ var childNodes = this . parent . childNodes ;
53
+
54
+ // If `start` is negative, begin that many elements from the end
55
+ start = start < 0 ? childNodes . length + start : start
56
+
57
+ // remove the element at index `start` `deleteCount` times
58
+ deleteCount = typeof deleteCount === 'number' ? deleteCount : childNodes . length - start ;
59
+ var stop = start + deleteCount ;
60
+ for ( var i = start ; i < stop && childNodes [ start ] ; i ++ ) {
61
+ this . parent . removeChild ( childNodes [ start ] ) ;
62
+ }
63
+
64
+ // add new elements at index `start`
65
+ if ( arguments . length > 2 ) {
66
+ var newItems = [ ] . slice . call ( arguments , 2 ) ;
67
+ var node = renderAll ( newItems , this . renderer ) ;
68
+ this . parent . insertBefore ( node , childNodes [ start ] ) ;
69
+ }
70
+ } ;
71
+
72
+ DomArray . prototype . reverse = function ( ) {
73
+ var docFrag = document . createDocumentFragment ( ) ;
74
+
75
+ // append every last child of parent to doc frag
76
+ while ( this . parent . lastChild ) {
77
+ docFrag . appendChild (
78
+ this . parent . removeChild ( this . parent . lastChild )
79
+ ) ;
80
+ }
81
+
82
+ // append doc frag to parent
83
+ this . parent . appendChild ( docFrag ) ;
84
+ } ;
85
+
86
+ DomArray . prototype . sort = function ( ) {
87
+ if ( ! nodeMap ) throw new TypeError ( 'DomArray.prototype.sort() requires Map support.' ) ;
88
+ var docFrag = document . createDocumentFragment ( ) ;
89
+ each ( this . collection , function ( obj ) {
90
+ var node = this . nodeMap . get ( obj ) ;
91
+ parent . removeChild ( node ) ;
92
+ docFrag . appendChild ( node ) ;
93
+ } ) ;
94
+ parent . appendChild ( docFrag ) ;
95
+ } ;
96
+
97
+
98
+ // helper functions
99
+
100
+ function each ( arr , fn , scope ) {
101
+ for ( var i = 0 , l = arr . length ; i < l ; i ++ ) {
102
+ fn . call ( scope , arr [ i ] , i , arr ) ;
103
+ }
104
+ }
105
+
106
+ // renderAll returns a single node containing the rendered nodes
107
+ function renderAll ( collection , renderer ) {
108
+ var nodeMap = this . nodeMap ;
109
+ if ( collection . length > 1 ) {
110
+ var docFrag = document . createDocumentFragment ( ) ;
111
+ each ( collection , function ( item ) {
112
+ // call renderer (should return a DOM node) for each item in collection
113
+ var node = renderer . apply ( null , arguments ) ;
114
+ if ( nodeMap ) nodeMap . set ( item , node ) ;
115
+ docFrag . appendChild ( node ) ;
116
+ } ) ;
117
+ return docFrag ;
118
+ } else {
119
+ return renderer . apply ( null , arguments ) ;
120
+ }
121
+ }
122
+
123
+ return DomArray ;
124
+ } ) ( ) ;
0 commit comments