| 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 |