3
3
'../modules/Events' ,
4
4
'./Observer'
5
5
] , function ( blocks , Events , Observer ) {
6
-
6
+
7
7
var Action = {
8
8
NOOP : 0 ,
9
9
ADD : 1 ,
@@ -33,15 +33,14 @@ define([
33
33
newObservable . view . _initialized = false ;
34
34
35
35
newObservable . view . on ( 'get' , newObservable . _getter ) ;
36
-
37
36
newObservable . on ( 'add' , function ( ) {
38
37
if ( newObservable . view . _initialized ) {
39
38
newObservable . view . _connections = { } ;
40
39
newObservable . view . reset ( ) ;
41
40
ExtenderHelper . executeOperations ( newObservable ) ;
42
41
}
43
42
} ) ;
44
-
43
+
45
44
newObservable . on ( 'remove' , function ( ) {
46
45
if ( newObservable . view . _initialized ) {
47
46
newObservable . view . _connections = { } ;
@@ -114,18 +113,27 @@ define([
114
113
} ,
115
114
116
115
executeOperationsChunk : function ( observable , operations ) {
117
- var action = Action . EXISTS ;
116
+ var action = Action . NOOP ;
118
117
119
118
var collection = observable . __value__ ;
120
119
var view = observable . view ;
120
+ // key = index of the __value__ array, value = index of the same value in the view
121
121
var connections = view . _connections ;
122
+ // key = index in the sorted collection, value = index in the (unsorted) connections
123
+ var sortedConnections = { } ;
124
+ var sorted = false ;
122
125
var newConnections = { } ;
123
- var viewIndex = 0 ;
126
+ var collectionIndex ;
127
+ var targetViewIndex = 0 ;
124
128
var update = view . update ;
125
129
var skip = 0 ;
126
130
var take = collection . length ;
127
131
view . update = blocks . noop ;
128
132
133
+ function getConnection ( index ) {
134
+ return sorted ? connections [ sortedConnections [ index ] ] : connections [ index ] ;
135
+ }
136
+
129
137
blocks . each ( operations , function prepareOperations ( operation ) {
130
138
switch ( operation . type ) {
131
139
case ExtenderHelper . operations . SKIP :
@@ -135,15 +143,16 @@ define([
135
143
}
136
144
skip = blocks . unwrap ( skip ) ;
137
145
break ;
146
+
138
147
case ExtenderHelper . operations . TAKE :
139
148
take = operation . take ;
140
149
if ( blocks . isFunction ( take ) ) {
141
150
take = take . call ( observable . __context__ ) ;
142
151
}
143
152
take = blocks . unwrap ( take ) ;
144
153
break ;
154
+
145
155
case ExtenderHelper . operations . SORT :
146
- // @todo resort connections after sorting this
147
156
if ( blocks . isString ( operation . sort ) ) {
148
157
collection = blocks . clone ( collection ) . sort ( function ( valueA , valueB ) {
149
158
valueA = blocks . unwrap ( valueA [ operation . sort ] ) ;
@@ -162,16 +171,29 @@ define([
162
171
collection = blocks . clone ( collection ) . sort ( ) ;
163
172
}
164
173
if ( operations . length == 1 ) {
165
- operations . push ( { type : ExtenderHelper . operations . FILTER , filter : function ( ) { return true ; } } ) ;
174
+ operations . push ( { type : ExtenderHelper . operations . FILTER , filter : noopFilter } ) ;
166
175
}
176
+ sorted = true ;
167
177
break ;
168
178
}
169
179
} ) ;
170
180
181
+ if ( sorted ) {
182
+ // create sortedConnections to match the sorted collection to connections
183
+ blocks . each ( observable . __value__ , function ( original , originalIndex ) {
184
+ blocks . each ( collection , function ( value , newIndex ) {
185
+ if ( value == original ) {
186
+ sortedConnections [ newIndex ] = originalIndex ;
187
+ return false ;
188
+ }
189
+ } ) ;
190
+ } ) ;
191
+ }
192
+
171
193
blocks . each ( collection , function iterateCollection ( value , index ) {
172
- var oldIndex ;
194
+ var currentViewIndex ;
173
195
if ( take <= 0 ) {
174
- while ( view ( ) . length - viewIndex > 0 ) {
196
+ while ( view ( ) . length - targetViewIndex > 0 ) {
175
197
view . removeAt ( view ( ) . length - 1 ) ;
176
198
view . _connections = { } ;
177
199
}
@@ -182,19 +204,17 @@ define([
182
204
var filterCallback = operation . filter ;
183
205
operation . type = operation . type || ( filterCallback && ExtenderHelper . operations . FILTER ) ;
184
206
185
- action = Action . NOOP ;
186
-
187
207
switch ( operation . type ) {
188
208
case ExtenderHelper . operations . FILTER :
189
209
if ( filterCallback . call ( observable . __context__ , value , index , collection ) ) {
190
210
action = Action . EXISTS ;
191
211
192
- if ( connections [ index ] === undefined ) {
212
+ if ( getConnection ( index ) === undefined ) {
193
213
action = Action . ADD ;
194
214
}
195
215
} else {
196
216
action = Action . NOOP ;
197
- if ( connections [ index ] !== undefined ) {
217
+ if ( getConnection ( index ) !== undefined ) {
198
218
action = Action . REMOVE ;
199
219
}
200
220
return false ;
@@ -207,7 +227,7 @@ define([
207
227
if ( skip >= 0 ) {
208
228
action = Action . REMOVE ;
209
229
return false ;
210
- } else if ( skip < 0 && connections [ index ] === undefined ) {
230
+ } else if ( skip < 0 && getConnection ( index ) === undefined ) {
211
231
action = Action . ADD ;
212
232
}
213
233
break ;
@@ -220,48 +240,56 @@ define([
220
240
take -= 1 ;
221
241
action = Action . EXISTS ;
222
242
223
- if ( connections [ index ] === undefined ) {
243
+ if ( getConnection ( index ) === undefined ) {
224
244
action = Action . ADD ;
225
245
}
226
246
}
227
247
break ;
228
248
}
229
249
} ) ;
230
250
231
- oldIndex = connections [ index ] ;
251
+ currentViewIndex = getConnection ( index ) ;
252
+ collectionIndex = sorted ? sortedConnections [ index ] : index ;
253
+
232
254
switch ( action ) {
233
255
case Action . ADD :
234
- newConnections [ index ] = viewIndex ;
235
- view . splice ( viewIndex , 0 , value ) ;
256
+ newConnections [ collectionIndex ] = targetViewIndex ;
257
+ view . splice ( targetViewIndex , 0 , value ) ;
258
+
259
+ // update connections so that the connections reflect the changes on the view-array
236
260
blocks . each ( connections , function ( valueViewIndex , i ) {
237
- if ( valueViewIndex >= viewIndex ) {
261
+ if ( valueViewIndex >= targetViewIndex ) {
238
262
connections [ i ] = ++ valueViewIndex ;
239
263
}
240
264
} ) ;
241
- viewIndex ++ ;
265
+ targetViewIndex ++ ;
242
266
break ;
267
+
243
268
case Action . REMOVE :
244
- view . removeAt ( oldIndex ) ;
269
+ view . removeAt ( currentViewIndex ) ;
270
+
271
+ // update connections so that the connections reflect the changes on the view-array
245
272
blocks . each ( connections , function ( valueViewIndex , i ) {
246
- if ( valueViewIndex > oldIndex ) {
273
+ if ( valueViewIndex > currentViewIndex ) {
247
274
connections [ i ] = -- valueViewIndex ;
248
275
}
249
276
} ) ;
250
277
break ;
278
+
251
279
case Action . EXISTS :
252
- newConnections [ index ] = viewIndex ;
253
- if ( oldIndex != viewIndex ) {
254
- view . move ( oldIndex , viewIndex ) ;
280
+ newConnections [ collectionIndex ] = targetViewIndex ;
281
+ if ( currentViewIndex != targetViewIndex ) {
282
+ view . move ( currentViewIndex , targetViewIndex ) ;
283
+
284
+ // update connections so that the connections reflect the changes on the view-array
255
285
blocks . each ( connections , function ( valueViewIndex , i ) {
256
- if ( valueViewIndex > oldIndex ) {
257
- valueViewIndex -- ;
258
- } else if ( valueViewIndex > viewIndex ) {
259
- valueViewIndex ++ ;
286
+ if ( sorted ? i == sortedConnections [ index ] : i == index ) {
287
+ return ;
260
288
}
261
- connections [ i ] = valueViewIndex ;
289
+ connections [ i ] = ( valueViewIndex > currentViewIndex ? -- valueViewIndex : ++ valueViewIndex ) ;
262
290
} ) ;
263
291
}
264
- viewIndex ++ ;
292
+ targetViewIndex ++ ;
265
293
break ;
266
294
}
267
295
} ) ;
@@ -271,6 +299,7 @@ define([
271
299
view . update ( ) ;
272
300
}
273
301
} ;
302
+ function noopFilter ( ) { return true ; }
274
303
275
304
return ExtenderHelper ;
276
305
} ) ;
0 commit comments