OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview This is a data model representin | 6 * @fileoverview This is a data model representin |
7 */ | 7 */ |
8 | 8 |
9 // The include directives are put into Javascript-style comments to prevent | 9 // The include directives are put into Javascript-style comments to prevent |
10 // parsing errors in non-flattened mode. The flattener still sees them. | 10 // parsing errors in non-flattened mode. The flattener still sees them. |
(...skipping 23 matching lines...) Expand all Loading... |
34 } | 34 } |
35 } | 35 } |
36 | 36 |
37 ArrayDataModel.prototype = { | 37 ArrayDataModel.prototype = { |
38 __proto__: EventTarget.prototype, | 38 __proto__: EventTarget.prototype, |
39 | 39 |
40 /** | 40 /** |
41 * The length of the data model. | 41 * The length of the data model. |
42 * @type {number} | 42 * @type {number} |
43 */ | 43 */ |
44 get length() { | 44 get length() { return this.array_.length; }, |
45 return this.array_.length; | |
46 }, | |
47 | 45 |
48 /** | 46 /** |
49 * Returns the item at the given index. | 47 * Returns the item at the given index. |
50 * This implementation returns the item at the given index in the sorted | 48 * This implementation returns the item at the given index in the sorted |
51 * array. | 49 * array. |
52 * @param {number} index The index of the element to get. | 50 * @param {number} index The index of the element to get. |
53 * @return {*} The element at the given index. | 51 * @return {*} The element at the given index. |
54 */ | 52 */ |
55 item: function(index) { | 53 item: function(index) { |
56 if (index >= 0 && index < this.length) | 54 if (index >= 0 && index < this.length) |
57 return this.array_[this.indexes_[index]]; | 55 return this.array_[this.indexes_[index]]; |
58 return undefined; | 56 return undefined; |
59 }, | 57 }, |
60 | 58 |
61 /** | 59 /** |
62 * Returns compare function set for given field. | 60 * Returns compare function set for given field. |
63 * @param {string} field The field to get compare function for. | 61 * @param {string} field The field to get compare function for. |
64 * @return {function(*, *): number} Compare function set for given field. | 62 * @return {function(*, *): number} Compare function set for given field. |
65 */ | 63 */ |
66 compareFunction: function(field) { | 64 compareFunction: function(field) { return this.compareFunctions_[field]; }, |
67 return this.compareFunctions_[field]; | |
68 }, | |
69 | 65 |
70 /** | 66 /** |
71 * Sets compare function for given field. | 67 * Sets compare function for given field. |
72 * @param {string} field The field to set compare function. | 68 * @param {string} field The field to set compare function. |
73 * @param {function(*, *): number} compareFunction Compare function to set | 69 * @param {function(*, *): number} compareFunction Compare function to set |
74 * for given field. | 70 * for given field. |
75 */ | 71 */ |
76 setCompareFunction: function(field, compareFunction) { | 72 setCompareFunction: function(field, compareFunction) { |
77 if (!this.compareFunctions_) { | 73 if (!this.compareFunctions_) { |
78 this.compareFunctions_ = {}; | 74 this.compareFunctions_ = {}; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 }, | 114 }, |
119 | 115 |
120 /** | 116 /** |
121 * Returns an array of elements in a selected range. | 117 * Returns an array of elements in a selected range. |
122 * @param {number=} opt_from The starting index of the selected range. | 118 * @param {number=} opt_from The starting index of the selected range. |
123 * @param {number=} opt_to The ending index of selected range. | 119 * @param {number=} opt_to The ending index of selected range. |
124 * @return {Array} An array of elements in the selected range. | 120 * @return {Array} An array of elements in the selected range. |
125 */ | 121 */ |
126 slice: function(opt_from, opt_to) { | 122 slice: function(opt_from, opt_to) { |
127 var arr = this.array_; | 123 var arr = this.array_; |
128 return this.indexes_.slice(opt_from, opt_to).map( | 124 return this.indexes_.slice(opt_from, opt_to).map(function(index) { |
129 function(index) { return arr[index] }); | 125 return arr[index] |
| 126 }); |
130 }, | 127 }, |
131 | 128 |
132 /** | 129 /** |
133 * This removes and adds items to the model. | 130 * This removes and adds items to the model. |
134 * This dispatches a splice event. | 131 * This dispatches a splice event. |
135 * This implementation runs sort after splice and creates permutation for | 132 * This implementation runs sort after splice and creates permutation for |
136 * the whole change. | 133 * the whole change. |
137 * @param {number} index The index of the item to update. | 134 * @param {number} index The index of the item to update. |
138 * @param {number} deleteCount The number of items to remove. | 135 * @param {number} deleteCount The number of items to remove. |
139 * @param {...*} var_args The items to add. | 136 * @param {...*} var_args The items to add. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 | 171 |
175 this.array_ = newArray; | 172 this.array_ = newArray; |
176 | 173 |
177 // TODO(arv): Maybe unify splice and change events? | 174 // TODO(arv): Maybe unify splice and change events? |
178 var spliceEvent = new Event('splice'); | 175 var spliceEvent = new Event('splice'); |
179 spliceEvent.removed = deletedItems; | 176 spliceEvent.removed = deletedItems; |
180 spliceEvent.added = Array.prototype.slice.call(arguments, 2); | 177 spliceEvent.added = Array.prototype.slice.call(arguments, 2); |
181 | 178 |
182 var status = this.sortStatus; | 179 var status = this.sortStatus; |
183 // if sortStatus.field is null, this restores original order. | 180 // if sortStatus.field is null, this restores original order. |
184 var sortPermutation = this.doSort_(this.sortStatus.field, | 181 var sortPermutation = |
185 this.sortStatus.direction); | 182 this.doSort_(this.sortStatus.field, this.sortStatus.direction); |
186 if (sortPermutation) { | 183 if (sortPermutation) { |
187 var splicePermutation = deletePermutation.map(function(element) { | 184 var splicePermutation = deletePermutation.map(function(element) { |
188 return element != -1 ? sortPermutation[element] : -1; | 185 return element != -1 ? sortPermutation[element] : -1; |
189 }); | 186 }); |
190 this.dispatchPermutedEvent_(splicePermutation); | 187 this.dispatchPermutedEvent_(splicePermutation); |
191 spliceEvent.index = sortPermutation[index]; | 188 spliceEvent.index = sortPermutation[index]; |
192 } else { | 189 } else { |
193 this.dispatchPermutedEvent_(deletePermutation); | 190 this.dispatchPermutedEvent_(deletePermutation); |
194 spliceEvent.index = index; | 191 spliceEvent.index = index; |
195 } | 192 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 this.updateIndex(index); | 236 this.updateIndex(index); |
240 }, | 237 }, |
241 | 238 |
242 /** | 239 /** |
243 * Use this to update a given item in the array. This does not remove and | 240 * Use this to update a given item in the array. This does not remove and |
244 * reinsert a new item. | 241 * reinsert a new item. |
245 * This dispatches a change event. | 242 * This dispatches a change event. |
246 * This runs sort after updating. | 243 * This runs sort after updating. |
247 * @param {number} index The index of the item to update. | 244 * @param {number} index The index of the item to update. |
248 */ | 245 */ |
249 updateIndex: function(index) { | 246 updateIndex: function(index) { this.updateIndexes([index]); }, |
250 this.updateIndexes([index]); | |
251 }, | |
252 | 247 |
253 /** | 248 /** |
254 * Notifies of update of the items in the array. This does not remove and | 249 * Notifies of update of the items in the array. This does not remove and |
255 * reinsert new items. | 250 * reinsert new items. |
256 * This dispatches one or more change events. | 251 * This dispatches one or more change events. |
257 * This runs sort after updating. | 252 * This runs sort after updating. |
258 * @param {Array<number>} indexes The index list of items to update. | 253 * @param {Array<number>} indexes The index list of items to update. |
259 */ | 254 */ |
260 updateIndexes: function(indexes) { | 255 updateIndexes: function(indexes) { |
261 indexes.forEach(function(index) { | 256 indexes.forEach(function(index) { |
262 assert(index >= 0 && index < this.length, 'Invalid index'); | 257 assert(index >= 0 && index < this.length, 'Invalid index'); |
263 }, this); | 258 }, this); |
264 | 259 |
265 for (var i = 0; i < indexes.length; i++) { | 260 for (var i = 0; i < indexes.length; i++) { |
266 var e = new Event('change'); | 261 var e = new Event('change'); |
267 e.index = indexes[i]; | 262 e.index = indexes[i]; |
268 this.dispatchEvent(e); | 263 this.dispatchEvent(e); |
269 } | 264 } |
270 | 265 |
271 if (this.sortStatus.field) { | 266 if (this.sortStatus.field) { |
272 var status = this.sortStatus; | 267 var status = this.sortStatus; |
273 var sortPermutation = this.doSort_(this.sortStatus.field, | 268 var sortPermutation = |
274 this.sortStatus.direction); | 269 this.doSort_(this.sortStatus.field, this.sortStatus.direction); |
275 if (sortPermutation) | 270 if (sortPermutation) |
276 this.dispatchPermutedEvent_(sortPermutation); | 271 this.dispatchPermutedEvent_(sortPermutation); |
277 // We should first call prepareSort (data may change), and then sort. | 272 // We should first call prepareSort (data may change), and then sort. |
278 // Still need to finish the sorting above (including events), so | 273 // Still need to finish the sorting above (including events), so |
279 // list will not go to inconsistent state. | 274 // list will not go to inconsistent state. |
280 this.delayedSort_(status.field, status.direction); | 275 this.delayedSort_(status.field, status.direction); |
281 } | 276 } |
282 }, | 277 }, |
283 | 278 |
284 /** | 279 /** |
285 * Creates sort status with given field and direction. | 280 * Creates sort status with given field and direction. |
286 * @param {?string} field Sort field. | 281 * @param {?string} field Sort field. |
287 * @param {?string} direction Sort direction. | 282 * @param {?string} direction Sort direction. |
288 * @return {!Object} Created sort status. | 283 * @return {!Object} Created sort status. |
289 */ | 284 */ |
290 createSortStatus: function(field, direction) { | 285 createSortStatus: function(field, direction) { |
291 return { | 286 return {field: field, direction: direction}; |
292 field: field, | |
293 direction: direction | |
294 }; | |
295 }, | 287 }, |
296 | 288 |
297 /** | 289 /** |
298 * Called before a sort happens so that you may fetch additional data | 290 * Called before a sort happens so that you may fetch additional data |
299 * required for the sort. | 291 * required for the sort. |
300 * | 292 * |
301 * @param {string} field Sort field. | 293 * @param {string} field Sort field. |
302 * @param {function()} callback The function to invoke when preparation | 294 * @param {function()} callback The function to invoke when preparation |
303 * is complete. | 295 * is complete. |
304 */ | 296 */ |
305 prepareSort: function(field, callback) { | 297 prepareSort: function(field, callback) { callback(); }, |
306 callback(); | |
307 }, | |
308 | 298 |
309 /** | 299 /** |
310 * Sorts data model according to given field and direction and dispathes | 300 * Sorts data model according to given field and direction and dispathes |
311 * sorted event with delay. If no need to delay, use sort() instead. | 301 * sorted event with delay. If no need to delay, use sort() instead. |
312 * @param {string} field Sort field. | 302 * @param {string} field Sort field. |
313 * @param {string} direction Sort direction. | 303 * @param {string} direction Sort direction. |
314 * @private | 304 * @private |
315 */ | 305 */ |
316 delayedSort_: function(field, direction) { | 306 delayedSort_: function(field, direction) { |
317 var self = this; | 307 var self = this; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 | 409 |
420 return function(index1, index2) { | 410 return function(index1, index2) { |
421 var item1 = this.array_[index1]; | 411 var item1 = this.array_[index1]; |
422 var item2 = this.array_[index2]; | 412 var item2 = this.array_[index2]; |
423 | 413 |
424 var compareResult = 0; | 414 var compareResult = 0; |
425 if (typeof(compareFunction) === 'function') | 415 if (typeof(compareFunction) === 'function') |
426 compareResult = compareFunction.call(null, item1, item2); | 416 compareResult = compareFunction.call(null, item1, item2); |
427 if (compareResult != 0) | 417 if (compareResult != 0) |
428 return dirMultiplier * compareResult; | 418 return dirMultiplier * compareResult; |
429 return dirMultiplier * this.defaultValuesCompareFunction(index1, | 419 return dirMultiplier * |
430 index2); | 420 this.defaultValuesCompareFunction(index1, index2); |
431 }.bind(this); | 421 }.bind(this); |
432 }, | 422 }, |
433 | 423 |
434 /** | 424 /** |
435 * Default compare function. | 425 * Default compare function. |
436 */ | 426 */ |
437 defaultValuesCompareFunction: function(a, b) { | 427 defaultValuesCompareFunction: function(a, b) { |
438 // We could insert i18n comparisons here. | 428 // We could insert i18n comparisons here. |
439 if (a < b) | 429 if (a < b) |
440 return -1; | 430 return -1; |
441 if (a > b) | 431 if (a > b) |
442 return 1; | 432 return 1; |
443 return 0; | 433 return 0; |
444 } | 434 } |
445 }; | 435 }; |
446 | 436 |
447 return { | 437 return {ArrayDataModel: ArrayDataModel}; |
448 ArrayDataModel: ArrayDataModel | |
449 }; | |
450 }); | 438 }); |
OLD | NEW |