Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(750)

Side by Side Diff: chrome/browser/resources/shared/js/cr/ui/table/table_data_model.js

Issue 7038024: Move sorting logic from table to list. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed autofill phones. Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * @fileoverview This is a table data model
7 */
8 cr.define('cr.ui.table', function() {
9 const EventTarget = cr.EventTarget;
10 const Event = cr.Event;
11 const ArrayDataModel = cr.ui.ArrayDataModel;
12
13 /**
14 * A table data model that supports sorting by storing initial indexes of
15 * elements for each position in sorted array.
16 * @param {!Array} items The underlying array.
17 * @constructor
18 * @extends {ArrayDataModel}
19 */
20 function TableDataModel(items) {
21 ArrayDataModel.apply(this, arguments);
22 this.indexes_ = [];
23 for (var i = 0; i < items.length; i++) {
24 this.indexes_.push(i);
25 }
26 }
27
28 TableDataModel.prototype = {
29 __proto__: ArrayDataModel.prototype,
30
31 /**
32 * Returns the item at the given index.
33 * This implementation returns the item at the given index in the source
34 * array before sort.
35 * @param {number} index The index of the element to get.
36 * @return {*} The element at the given index.
37 */
38 getItemByUnsortedIndex_: function(unsortedIndex) {
39 return ArrayDataModel.prototype.item.call(this, unsortedIndex);
40 },
41
42 /**
43 * Returns the item at the given index.
44 * This implementation returns the item at the given index in the sorted
45 * array.
46 * @param {number} index The index of the element to get.
47 * @return {*} The element at the given index.
48 */
49 item: function(index) {
50 if (index >= 0 && index < this.length)
51 return this.getItemByUnsortedIndex_(this.indexes_[index]);
52 return undefined;
53 },
54
55 /**
56 * Returns compare function set for given field.
57 * @param {string} field The field to get compare function for.
58 * @return {Function(*, *): number} Compare function set for given field.
59 */
60 compareFunction: function(field) {
61 return this.compareFunctions_[field];
62 },
63
64 /**
65 * Sets compare function for given field.
66 * @param {string} field The field to set compare function.
67 * @param {Function(*, *): number} Compare function to set for given field.
68 */
69 setCompareFunction: function(field, compareFunction) {
70 this.compareFunctions_[field] = compareFunction;
71 },
72
73 /**
74 * Returns current sort status.
75 * @return {!Object} Current sort status.
76 */
77 get sortStatus() {
78 if (this.sortStatus_) {
79 return this.createSortStatus(
80 this.sortStatus_.field, this.sortStatus_.direction);
81 } else {
82 return this.createSortStatus(null, null);
83 }
84 },
85
86 /**
87 * This removes and adds items to the model.
88 * This dispatches a splice event.
89 * This implementation runs sort after splice and creates permutation for
90 * the whole change.
91 * @param {number} index The index of the item to update.
92 * @param {number} deleteCount The number of items to remove.
93 * @param {...*} The items to add.
94 * @return {!Array} An array with the removed items.
95 */
96 splice: function(index, deleteCount, var_args) {
97 var addCount = arguments.length - 2;
98 var newIndexes = [];
99 var deletePermutation = [];
100 var deleted = 0;
101 for (var i = 0; i < this.indexes_.length; i++) {
102 var oldIndex = this.indexes_[i];
103 if (oldIndex < index) {
104 newIndexes.push(oldIndex);
105 deletePermutation.push(i - deleted);
106 } else if (oldIndex >= index + deleteCount) {
107 newIndexes.push(oldIndex - deleteCount + addCount);
108 deletePermutation.push(i - deleted);
109 } else {
110 deletePermutation.push(-1);
111 deleted++;
112 }
113 }
114 for (var i = 0; i < addCount; i++) {
115 newIndexes.push(index + i);
116 }
117 this.indexes_ = newIndexes;
118
119 var rv = ArrayDataModel.prototype.splice.apply(this, arguments);
120
121 var splicePermutation;
122 if (this.sortStatus.field) {
123 var sortPermutation = this.doSort_(this.sortStatus.field,
124 this.sortStatus.direction);
125 splicePermutation = deletePermutation.map(function(element) {
126 return element != -1 ? sortPermutation[element] : -1;
127 });
128 } else {
129 splicePermutation = deletePermutation;
130 }
131 this.dispatchSortEvent_(splicePermutation);
132
133 return rv;
134 },
135
136 /**
137 * Use this to update a given item in the array. This does not remove and
138 * reinsert a new item.
139 * This dispatches a change event.
140 * This implementation runs sort after updating.
141 * @param {number} index The index of the item to update.
142 */
143 updateIndex: function(index) {
144 ArrayDataModel.prototype.updateIndex.apply(this, arguments);
145
146 if (this.sortStatus.field)
147 this.sort(this.sortStatus.field, this.sortStatus.direction);
148 },
149
150 /**
151 * Creates sort status with given field and direction.
152 * @param {string} field Sort field.
153 * @param {string} direction Sort direction.
154 * @return {!Object} Created sort status.
155 */
156 createSortStatus: function(field, direction) {
157 return {
158 field: field,
159 direction: direction
160 };
161 },
162
163 /**
164 * Called before a sort happens so that you may fetch additional data
165 * required for the sort.
166 *
167 * @param {string} field Sort field.
168 * @param {function()} callback The function to invoke when preparation
169 * is complete.
170 */
171 prepareSort: function(field, callback) {
172 callback();
173 },
174
175 /**
176 * Sorts data model according to given field and direction and dispathes
177 * sorted event.
178 * @param {string} field Sort field.
179 * @param {string} direction Sort direction.
180 */
181 sort: function(field, direction) {
182 var self = this;
183
184 this.prepareSort(field, function() {
185 var sortPermutation = self.doSort_(field, direction);
186 self.dispatchSortEvent_(sortPermutation);
187 });
188 },
189
190 /**
191 * Sorts data model according to given field and direction.
192 * @param {string} field Sort field.
193 * @param {string} direction Sort direction.
194 */
195 doSort_: function(field, direction) {
196 var compareFunction = this.sortFunction_(field, direction);
197 var positions = [];
198 for (var i = 0; i < this.length; i++) {
199 positions[this.indexes_[i]] = i;
200 }
201 this.indexes_.sort(compareFunction);
202 this.sortStatus_ = this.createSortStatus(field, direction);
203 var sortPermutation = [];
204 for (var i = 0; i < this.length; i++) {
205 sortPermutation[positions[this.indexes_[i]]] = i;
206 }
207 return sortPermutation;
208 },
209
210 dispatchSortEvent_: function(sortPermutation) {
211 var e = new Event('sorted');
212 e.sortPermutation = sortPermutation;
213 this.dispatchEvent(e);
214 },
215
216 /**
217 * Creates compare function for the field.
218 * Returns the function set as sortFunction for given field
219 * or default compare function
220 * @param {string} field Sort field.
221 * @param {Function(*, *): number} Compare function.
222 */
223 createCompareFunction_: function(field) {
224 var compareFunction =
225 this.compareFunctions_ ? this.compareFunctions_[field] : null;
226 var defaultValuesCompareFunction = this.defaultValuesCompareFunction;
227 if (compareFunction) {
228 return compareFunction;
229 } else {
230 return function(a, b) {
231 return defaultValuesCompareFunction.call(null, a[field], b[field]);
232 }
233 }
234 return compareFunction;
235 },
236
237 /**
238 * Creates compare function for given field and direction.
239 * @param {string} field Sort field.
240 * @param {string} direction Sort direction.
241 * @param {Function(*, *): number} Compare function.
242 */
243 sortFunction_: function(field, direction) {
244 var compareFunction = this.createCompareFunction_(field);
245 var dirMultiplier = direction == 'desc' ? -1 : 1;
246
247 return function(index1, index2) {
248 var item1 = this.getItemByUnsortedIndex_(index1);
249 var item2 = this.getItemByUnsortedIndex_(index2);
250
251 var compareResult = compareFunction.call(null, item1, item2);
252 if (compareResult != 0)
253 return dirMultiplier * compareResult;
254 return dirMultiplier * this.defaultValuesCompareFunction(index1,
255 index2);
256 }.bind(this);
257 },
258
259 /**
260 * Default compare function.
261 */
262 defaultValuesCompareFunction: function(a, b) {
263 // We could insert i18n comparisons here.
264 if (a < b)
265 return -1;
266 if (a > b)
267 return 1;
268 return 0;
269 }
270 };
271
272 return {
273 TableDataModel: TableDataModel
274 };
275 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698