summaryrefslogtreecommitdiff
path: root/frontend/beta/js/YUI-extensions/data/DefaultDataModel.js
Unidiff
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.js339
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*/
20YAHOO.ext.grid.DefaultDataModel = function(data){
21 YAHOO.ext.grid.DefaultDataModel.superclass.constructor.call(this);
22 /**@private*/
23 this.data = data;
24};
25YAHOO.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 */
337if(YAHOO.ext.grid.DefaultColumnModel){
338 YAHOO.ext.grid.DefaultDataModel.sortTypes = YAHOO.ext.grid.DefaultColumnModel.sortTypes;
339}