Diffstat (limited to 'frontend/beta/js/YUI-extensions/data/DefaultDataModel.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/beta/js/YUI-extensions/data/DefaultDataModel.js | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI-extensions/data/DefaultDataModel.js b/frontend/beta/js/YUI-extensions/data/DefaultDataModel.js new file mode 100644 index 0000000..57a022a --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/data/DefaultDataModel.js | |||
@@ -0,0 +1,339 @@ | |||
1 | |||
2 | /** | ||
3 | * @class YAHOO.ext.grid.DefaultDataModel | ||
4 | * This is the default implementation of a DataModel used by the Grid. It works | ||
5 | * with multi-dimensional array based data. Using the event system in the base class | ||
6 | * {@link YAHOO.ext.grid.AbstractDataModel}, all updates to this DataModel are automatically | ||
7 | * reflected in the user interface. | ||
8 | * <br>Usage:<br> | ||
9 | * <pre><code> | ||
10 | * var myData = [ | ||
11 | ["MSFT","Microsoft Corporation", "314,571.156", "32,187.000", "55000"], | ||
12 | ["ORCL", "Oracle Corporation", "62,615.266", "9,519.000", "40650"] | ||
13 | * ]; | ||
14 | * var dataModel = new YAHOO.ext.grid.DefaultDataModel(myData); | ||
15 | * </code></pre> | ||
16 | * @extends YAHOO.ext.grid.AbstractDataModel | ||
17 | * @constructor | ||
18 | * @param {Array} data | ||
19 | */ | ||
20 | YAHOO.ext.grid.DefaultDataModel = function(data){ | ||
21 | YAHOO.ext.grid.DefaultDataModel.superclass.constructor.call(this); | ||
22 | /**@private*/ | ||
23 | this.data = data; | ||
24 | }; | ||
25 | YAHOO.extendX(YAHOO.ext.grid.DefaultDataModel, YAHOO.ext.grid.AbstractDataModel, { | ||
26 | /** | ||
27 | * Returns the number of rows in the dataset | ||
28 | * @return {Number} | ||
29 | */ | ||
30 | getRowCount : function(){ | ||
31 | return this.data.length; | ||
32 | }, | ||
33 | |||
34 | /** | ||
35 | * Returns the ID of the specified row. By default it return the value of the first column. | ||
36 | * Override to provide more advanced ID handling. | ||
37 | * @return {Number} | ||
38 | */ | ||
39 | getRowId : function(rowIndex){ | ||
40 | return this.data[rowIndex][0]; | ||
41 | }, | ||
42 | |||
43 | /** | ||
44 | * Returns the column data for the specified row. | ||
45 | * @return {Array} | ||
46 | */ | ||
47 | getRow : function(rowIndex){ | ||
48 | return this.data[rowIndex]; | ||
49 | }, | ||
50 | |||
51 | /** | ||
52 | * Returns the column data for the specified rows as a | ||
53 | * multi-dimensional array: rows[3][0] would give you the value of row 4, column 0. | ||
54 | * @param {Array} indexes The row indexes to fetch | ||
55 | * @return {Array} | ||
56 | */ | ||
57 | getRows : function(indexes){ | ||
58 | var data = this.data; | ||
59 | var r = []; | ||
60 | for(var i = 0; i < indexes.length; i++){ | ||
61 | r.push(data[indexes[i]]); | ||
62 | } | ||
63 | return r; | ||
64 | }, | ||
65 | |||
66 | /** | ||
67 | * Returns the value at the specified data position | ||
68 | * @param {Number} rowIndex | ||
69 | * @param {Number} colIndex | ||
70 | * @return {Object} | ||
71 | */ | ||
72 | getValueAt : function(rowIndex, colIndex){ | ||
73 | return this.data[rowIndex][colIndex]; | ||
74 | }, | ||
75 | |||
76 | /** | ||
77 | * Sets the specified value at the specified data position | ||
78 | * @param {Object} value The new value | ||
79 | * @param {Number} rowIndex | ||
80 | * @param {Number} colIndex | ||
81 | */ | ||
82 | setValueAt: function(value, rowIndex, colIndex){ | ||
83 | this.data[rowIndex][colIndex] = value; | ||
84 | this.fireCellUpdated(rowIndex, colIndex); | ||
85 | }, | ||
86 | |||
87 | /** | ||
88 | * @private | ||
89 | * Removes the specified range of rows. | ||
90 | * @param {Number} startIndex | ||
91 | * @param {<i>Number</i>} endIndex (optional) Defaults to startIndex | ||
92 | */ | ||
93 | removeRows: function(startIndex, endIndex){ | ||
94 | endIndex = endIndex || startIndex; | ||
95 | this.data.splice(startIndex, endIndex-startIndex+1); | ||
96 | this.fireRowsDeleted(startIndex, endIndex); | ||
97 | }, | ||
98 | |||
99 | /** | ||
100 | * Remove a row. | ||
101 | * @param {Number} index | ||
102 | */ | ||
103 | removeRow: function(index){ | ||
104 | this.data.splice(index, 1); | ||
105 | this.fireRowsDeleted(index, index); | ||
106 | }, | ||
107 | |||
108 | /** | ||
109 | * @private | ||
110 | * Removes all rows. | ||
111 | */ | ||
112 | removeAll: function(){ | ||
113 | var count = this.getRowCount(); | ||
114 | if(count > 0){ | ||
115 | this.removeRows(0, count-1); | ||
116 | } | ||
117 | }, | ||
118 | |||
119 | /** | ||
120 | * Query the DataModel rows by the filters defined in spec, for example... | ||
121 | * <pre><code> | ||
122 | * // column 1 starts with Jack, column 2 filtered by myFcn, column 3 equals 'Fred' | ||
123 | * dataModel.filter({1: /^Jack.+/i}, 2: myFcn, 3: 'Fred'}); | ||
124 | * </code></pre> | ||
125 | * @param {Object} spec The spec is generally an object literal consisting of | ||
126 | * column index and filter type. The filter type can be a string/number (exact match), | ||
127 | * a regular expression to test using String.search() or a function to call. If it's a function, | ||
128 | * it will be called with the value for the specified column and an array of the all column | ||
129 | * values for that row: yourFcn(value, columnData). If it returns anything other than true, | ||
130 | * the row is not a match. If you have modified Object.prototype this method may fail. | ||
131 | * @param {Boolean} returnUnmatched True to return rows which <b>don't</b> match the query instead | ||
132 | * of rows that do match | ||
133 | * @return {Array} An array of row indexes that match | ||
134 | */ | ||
135 | query: function(spec, returnUnmatched){ | ||
136 | var d = this.data; | ||
137 | var r = []; | ||
138 | for(var i = 0; i < d.length; i++){ | ||
139 | var row = d[i]; | ||
140 | var isMatch = true; | ||
141 | for(var col in spec){ | ||
142 | //if(typeof spec[col] != 'function'){ | ||
143 | if(!isMatch) continue; | ||
144 | var filter = spec[col]; | ||
145 | switch(typeof filter){ | ||
146 | case 'string': | ||
147 | case 'number': | ||
148 | case 'boolean': | ||
149 | if(row[col] != filter){ | ||
150 | isMatch = false; | ||
151 | } | ||
152 | break; | ||
153 | case 'function': | ||
154 | if(!filter(row[col], row)){ | ||
155 | isMatch = false; | ||
156 | } | ||
157 | break; | ||
158 | case 'object': | ||
159 | if(filter instanceof RegExp){ | ||
160 | if(String(row[col]).search(filter) === -1){ | ||
161 | isMatch = false; | ||
162 | } | ||
163 | } | ||
164 | break; | ||
165 | } | ||
166 | //} | ||
167 | } | ||
168 | if(isMatch && !returnUnmatched){ | ||
169 | r.push(i); | ||
170 | }else if(!isMatch && returnUnmatched){ | ||
171 | r.push(i); | ||
172 | } | ||
173 | } | ||
174 | return r; | ||
175 | }, | ||
176 | |||
177 | /** | ||
178 | * Filter the DataModel rows by the query defined in spec, see {@link #query} for more details | ||
179 | * on the query spec. | ||
180 | * @param {Object} query The query spec {@link #query} | ||
181 | * @return {Number} The number of rows removed | ||
182 | */ | ||
183 | filter: function(query){ | ||
184 | var matches = this.query(query, true); | ||
185 | var data = this.data; | ||
186 | // go thru the data setting matches to deleted | ||
187 | // while not disturbing row indexes | ||
188 | for(var i = 0; i < matches.length; i++){ | ||
189 | data[matches[i]]._deleted = true; | ||
190 | } | ||
191 | for(var i = 0; i < data.length; i++){ | ||
192 | while(data[i] && data[i]._deleted === true){ | ||
193 | this.removeRow(i); | ||
194 | } | ||
195 | } | ||
196 | return matches.length; | ||
197 | }, | ||
198 | |||
199 | /** | ||
200 | * Adds a row to the dataset. | ||
201 | * @param {Array} cellValues The array of values for the new row | ||
202 | * @return {Number} The index of the added row | ||
203 | */ | ||
204 | addRow: function(cellValues){ | ||
205 | this.data.push(cellValues); | ||
206 | var newIndex = this.data.length-1; | ||
207 | this.fireRowsInserted(newIndex, newIndex); | ||
208 | this.applySort(); | ||
209 | return newIndex; | ||
210 | }, | ||
211 | |||
212 | /** | ||
213 | * @private | ||
214 | * Adds a set of rows. | ||
215 | * @param {Array} rowData This should be an array of arrays like the constructor takes | ||
216 | */ | ||
217 | addRows: function(rowData){ | ||
218 | this.data = this.data.concat(rowData); | ||
219 | var firstIndex = this.data.length-rowData.length; | ||
220 | this.fireRowsInserted(firstIndex, firstIndex+rowData.length-1); | ||
221 | this.applySort(); | ||
222 | }, | ||
223 | |||
224 | /** | ||
225 | * Inserts a row a the specified location in the dataset. | ||
226 | * @param {Number} index The index where the row should be inserted | ||
227 | * @param {Array} cellValues The array of values for the new row | ||
228 | * @return {Number} The index the row was inserted in | ||
229 | */ | ||
230 | insertRow: function(index, cellValues){ | ||
231 | this.data.splice(index, 0, cellValues); | ||
232 | this.fireRowsInserted(index, index); | ||
233 | this.applySort(); | ||
234 | return index; | ||
235 | }, | ||
236 | |||
237 | /** | ||
238 | * @private | ||
239 | * Inserts a set of rows. | ||
240 | * @param {Number} index The index where the rows should be inserted | ||
241 | * @param {Array} rowData This should be an array of arrays like the constructor takes | ||
242 | */ | ||
243 | insertRows: function(index, rowData){ | ||
244 | /* | ||
245 | if(index == this.data.length){ // try these two first since they are faster | ||
246 | this.data = this.data.concat(rowData); | ||
247 | }else if(index == 0){ | ||
248 | this.data = rowData.concat(this.data); | ||
249 | }else{ | ||
250 | var newData = this.data.slice(0, index); | ||
251 | newData.concat(rowData); | ||
252 | newData.concat(this.data.slice(index)); | ||
253 | this.data = newData; | ||
254 | }*/ | ||
255 | var args = rowData.concat(); | ||
256 | args.splice(0, 0, index, 0); | ||
257 | this.data.splice.apply(this.data, args); | ||
258 | this.fireRowsInserted(index, index+rowData.length-1); | ||
259 | this.applySort(); | ||
260 | }, | ||
261 | |||
262 | /** | ||
263 | * Applies the last used sort to the current data. | ||
264 | */ | ||
265 | applySort: function(suppressEvent){ | ||
266 | if(typeof this.sortColumn != 'undefined'){ | ||
267 | this.sort(this.sortInfo, this.sortColumn, this.sortDir, suppressEvent); | ||
268 | } | ||
269 | }, | ||
270 | |||
271 | /** | ||
272 | * Sets the default sort info. Note: this function does not actually apply the sort. | ||
273 | * @param {Function/Object} sortInfo A sort comparison function or null to use the default or A object that has a method getSortType(index) that returns a function like | ||
274 | * a grid column model. | ||
275 | * @param {Number} columnIndex The column index to sort by | ||
276 | * @param {String} direction The direction of the sort ('DESC' or 'ASC') | ||
277 | */ | ||
278 | setDefaultSort: function(sortInfo, columnIndex, direction){ | ||
279 | this.sortInfo = sortInfo; | ||
280 | this.sortColumn = columnIndex; | ||
281 | this.sortDir = direction; | ||
282 | }, | ||
283 | /** | ||
284 | * Sorts the data by the specified column - Uses the sortType specified for the column in the passed columnModel. | ||
285 | * @param {Function/Object} sortInfo A sort comparison function or null to use the default or A object that has a method getSortType(index) that returns a function like | ||
286 | * a grid column model. | ||
287 | * @param {Number} columnIndex The column index to sort by | ||
288 | * @param {String} direction The direction of the sort ('DESC' or 'ASC') | ||
289 | */ | ||
290 | sort: function(sortInfo, columnIndex, direction, suppressEvent){ | ||
291 | // store these so we can maintain sorting when we load new data | ||
292 | this.sortInfo = sortInfo; | ||
293 | this.sortColumn = columnIndex; | ||
294 | this.sortDir = direction; | ||
295 | |||
296 | var dsc = (direction && direction.toUpperCase() == 'DESC'); | ||
297 | var sortType = null; | ||
298 | if(sortInfo != null){ | ||
299 | if(typeof sortInfo == 'function'){ | ||
300 | sortType = sortInfo; | ||
301 | }else if(typeof sortInfo == 'object'){ | ||
302 | sortType = sortInfo.getSortType(columnIndex);; | ||
303 | } | ||
304 | } | ||
305 | var fn = function(cells, cells2){ | ||
306 | var v1 = sortType ? sortType(cells[columnIndex], cells) : cells[columnIndex]; | ||
307 | var v2 = sortType ? sortType(cells2[columnIndex], cells2) : cells2[columnIndex]; | ||
308 | if(v1 < v2) | ||
309 | return dsc ? +1 : -1; | ||
310 | if(v1 > v2) | ||
311 | return dsc ? -1 : +1; | ||
312 | return 0; | ||
313 | }; | ||
314 | this.data.sort(fn); | ||
315 | if(!suppressEvent){ | ||
316 | this.fireRowsSorted(columnIndex, direction); | ||
317 | } | ||
318 | }, | ||
319 | |||
320 | /** | ||
321 | * Calls passed function with each rows data - if the function returns false it stops. | ||
322 | * @param {Function} fn | ||
323 | * @param {Object} scope (optional) | ||
324 | */ | ||
325 | each: function(fn, scope){ | ||
326 | var d = this.data; | ||
327 | for(var i = 0, len = d.length; i < len; i++){ | ||
328 | if(fn.call(scope || window, d[i], i) === false) break; | ||
329 | } | ||
330 | } | ||
331 | }); | ||
332 | |||
333 | /** | ||
334 | * Alias to YAHOO.ext.grid.DefaultColumnModel.sortTypes | ||
335 | * @static | ||
336 | */ | ||
337 | if(YAHOO.ext.grid.DefaultColumnModel){ | ||
338 | YAHOO.ext.grid.DefaultDataModel.sortTypes = YAHOO.ext.grid.DefaultColumnModel.sortTypes; | ||
339 | } | ||