From 541bb378ddece2eab135a8066a16994e94436dea Mon Sep 17 00:00:00 2001 From: Giulio Cesare Solaroli Date: Mon, 03 Oct 2011 16:04:12 +0000 Subject: Merge pull request #1 from gcsolaroli/master First version of the restructured repository --- (limited to 'frontend/beta/js/YUI-extensions/data/DefaultDataModel.js') 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 @@ + +/** + * @class YAHOO.ext.grid.DefaultDataModel + * This is the default implementation of a DataModel used by the Grid. It works + * with multi-dimensional array based data. Using the event system in the base class + * {@link YAHOO.ext.grid.AbstractDataModel}, all updates to this DataModel are automatically + * reflected in the user interface. + *
Usage:
+ *

+ * var myData = [
+	["MSFT","Microsoft Corporation", "314,571.156", "32,187.000", "55000"],
+	["ORCL", "Oracle Corporation", "62,615.266", "9,519.000", "40650"]
+ * ];
+ * var dataModel = new YAHOO.ext.grid.DefaultDataModel(myData);
+ * 
+ * @extends YAHOO.ext.grid.AbstractDataModel + * @constructor + * @param {Array} data +*/ +YAHOO.ext.grid.DefaultDataModel = function(data){ + YAHOO.ext.grid.DefaultDataModel.superclass.constructor.call(this); + /**@private*/ + this.data = data; +}; +YAHOO.extendX(YAHOO.ext.grid.DefaultDataModel, YAHOO.ext.grid.AbstractDataModel, { + /** + * Returns the number of rows in the dataset + * @return {Number} + */ + getRowCount : function(){ + return this.data.length; + }, + + /** + * Returns the ID of the specified row. By default it return the value of the first column. + * Override to provide more advanced ID handling. + * @return {Number} + */ + getRowId : function(rowIndex){ + return this.data[rowIndex][0]; + }, + + /** + * Returns the column data for the specified row. + * @return {Array} + */ + getRow : function(rowIndex){ + return this.data[rowIndex]; + }, + + /** + * Returns the column data for the specified rows as a + * multi-dimensional array: rows[3][0] would give you the value of row 4, column 0. + * @param {Array} indexes The row indexes to fetch + * @return {Array} + */ + getRows : function(indexes){ + var data = this.data; + var r = []; + for(var i = 0; i < indexes.length; i++){ + r.push(data[indexes[i]]); + } + return r; + }, + + /** + * Returns the value at the specified data position + * @param {Number} rowIndex + * @param {Number} colIndex + * @return {Object} + */ + getValueAt : function(rowIndex, colIndex){ + return this.data[rowIndex][colIndex]; + }, + + /** + * Sets the specified value at the specified data position + * @param {Object} value The new value + * @param {Number} rowIndex + * @param {Number} colIndex + */ + setValueAt: function(value, rowIndex, colIndex){ + this.data[rowIndex][colIndex] = value; + this.fireCellUpdated(rowIndex, colIndex); + }, + + /** + * @private + * Removes the specified range of rows. + * @param {Number} startIndex + * @param {Number} endIndex (optional) Defaults to startIndex + */ + removeRows: function(startIndex, endIndex){ + endIndex = endIndex || startIndex; + this.data.splice(startIndex, endIndex-startIndex+1); + this.fireRowsDeleted(startIndex, endIndex); + }, + + /** + * Remove a row. + * @param {Number} index + */ + removeRow: function(index){ + this.data.splice(index, 1); + this.fireRowsDeleted(index, index); + }, + + /** + * @private + * Removes all rows. + */ + removeAll: function(){ + var count = this.getRowCount(); + if(count > 0){ + this.removeRows(0, count-1); + } + }, + + /** + * Query the DataModel rows by the filters defined in spec, for example... + *

+     * // column 1 starts with Jack, column 2 filtered by myFcn, column 3 equals 'Fred'
+     * dataModel.filter({1: /^Jack.+/i}, 2: myFcn, 3: 'Fred'});
+     * 
+ * @param {Object} spec The spec is generally an object literal consisting of + * column index and filter type. The filter type can be a string/number (exact match), + * a regular expression to test using String.search() or a function to call. If it's a function, + * it will be called with the value for the specified column and an array of the all column + * values for that row: yourFcn(value, columnData). If it returns anything other than true, + * the row is not a match. If you have modified Object.prototype this method may fail. + * @param {Boolean} returnUnmatched True to return rows which don't match the query instead + * of rows that do match + * @return {Array} An array of row indexes that match + */ + query: function(spec, returnUnmatched){ + var d = this.data; + var r = []; + for(var i = 0; i < d.length; i++){ + var row = d[i]; + var isMatch = true; + for(var col in spec){ + //if(typeof spec[col] != 'function'){ + if(!isMatch) continue; + var filter = spec[col]; + switch(typeof filter){ + case 'string': + case 'number': + case 'boolean': + if(row[col] != filter){ + isMatch = false; + } + break; + case 'function': + if(!filter(row[col], row)){ + isMatch = false; + } + break; + case 'object': + if(filter instanceof RegExp){ + if(String(row[col]).search(filter) === -1){ + isMatch = false; + } + } + break; + } + //} + } + if(isMatch && !returnUnmatched){ + r.push(i); + }else if(!isMatch && returnUnmatched){ + r.push(i); + } + } + return r; + }, + + /** + * Filter the DataModel rows by the query defined in spec, see {@link #query} for more details + * on the query spec. + * @param {Object} query The query spec {@link #query} + * @return {Number} The number of rows removed + */ + filter: function(query){ + var matches = this.query(query, true); + var data = this.data; + // go thru the data setting matches to deleted + // while not disturbing row indexes + for(var i = 0; i < matches.length; i++){ + data[matches[i]]._deleted = true; + } + for(var i = 0; i < data.length; i++){ + while(data[i] && data[i]._deleted === true){ + this.removeRow(i); + } + } + return matches.length; + }, + + /** + * Adds a row to the dataset. + * @param {Array} cellValues The array of values for the new row + * @return {Number} The index of the added row + */ + addRow: function(cellValues){ + this.data.push(cellValues); + var newIndex = this.data.length-1; + this.fireRowsInserted(newIndex, newIndex); + this.applySort(); + return newIndex; + }, + + /** + * @private + * Adds a set of rows. + * @param {Array} rowData This should be an array of arrays like the constructor takes + */ + addRows: function(rowData){ + this.data = this.data.concat(rowData); + var firstIndex = this.data.length-rowData.length; + this.fireRowsInserted(firstIndex, firstIndex+rowData.length-1); + this.applySort(); + }, + + /** + * Inserts a row a the specified location in the dataset. + * @param {Number} index The index where the row should be inserted + * @param {Array} cellValues The array of values for the new row + * @return {Number} The index the row was inserted in + */ + insertRow: function(index, cellValues){ + this.data.splice(index, 0, cellValues); + this.fireRowsInserted(index, index); + this.applySort(); + return index; + }, + + /** + * @private + * Inserts a set of rows. + * @param {Number} index The index where the rows should be inserted + * @param {Array} rowData This should be an array of arrays like the constructor takes + */ + insertRows: function(index, rowData){ + /* + if(index == this.data.length){ // try these two first since they are faster + this.data = this.data.concat(rowData); + }else if(index == 0){ + this.data = rowData.concat(this.data); + }else{ + var newData = this.data.slice(0, index); + newData.concat(rowData); + newData.concat(this.data.slice(index)); + this.data = newData; + }*/ + var args = rowData.concat(); + args.splice(0, 0, index, 0); + this.data.splice.apply(this.data, args); + this.fireRowsInserted(index, index+rowData.length-1); + this.applySort(); + }, + + /** + * Applies the last used sort to the current data. + */ + applySort: function(suppressEvent){ + if(typeof this.sortColumn != 'undefined'){ + this.sort(this.sortInfo, this.sortColumn, this.sortDir, suppressEvent); + } + }, + + /** + * Sets the default sort info. Note: this function does not actually apply the sort. + * @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 + * a grid column model. + * @param {Number} columnIndex The column index to sort by + * @param {String} direction The direction of the sort ('DESC' or 'ASC') + */ + setDefaultSort: function(sortInfo, columnIndex, direction){ + this.sortInfo = sortInfo; + this.sortColumn = columnIndex; + this.sortDir = direction; + }, + /** + * Sorts the data by the specified column - Uses the sortType specified for the column in the passed columnModel. + * @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 + * a grid column model. + * @param {Number} columnIndex The column index to sort by + * @param {String} direction The direction of the sort ('DESC' or 'ASC') + */ + sort: function(sortInfo, columnIndex, direction, suppressEvent){ + // store these so we can maintain sorting when we load new data + this.sortInfo = sortInfo; + this.sortColumn = columnIndex; + this.sortDir = direction; + + var dsc = (direction && direction.toUpperCase() == 'DESC'); + var sortType = null; + if(sortInfo != null){ + if(typeof sortInfo == 'function'){ + sortType = sortInfo; + }else if(typeof sortInfo == 'object'){ + sortType = sortInfo.getSortType(columnIndex);; + } + } + var fn = function(cells, cells2){ + var v1 = sortType ? sortType(cells[columnIndex], cells) : cells[columnIndex]; + var v2 = sortType ? sortType(cells2[columnIndex], cells2) : cells2[columnIndex]; + if(v1 < v2) + return dsc ? +1 : -1; + if(v1 > v2) + return dsc ? -1 : +1; + return 0; + }; + this.data.sort(fn); + if(!suppressEvent){ + this.fireRowsSorted(columnIndex, direction); + } + }, + + /** + * Calls passed function with each rows data - if the function returns false it stops. + * @param {Function} fn + * @param {Object} scope (optional) + */ + each: function(fn, scope){ + var d = this.data; + for(var i = 0, len = d.length; i < len; i++){ + if(fn.call(scope || window, d[i], i) === false) break; + } + } +}); + +/** + * Alias to YAHOO.ext.grid.DefaultColumnModel.sortTypes + * @static + */ +if(YAHOO.ext.grid.DefaultColumnModel){ + YAHOO.ext.grid.DefaultDataModel.sortTypes = YAHOO.ext.grid.DefaultColumnModel.sortTypes; +} -- cgit v0.9.0.2