added YUI and YUI-ext

fixed the resizable text area with IE problem
fixed the ad space with IE problem
merged the 7.2.0 and 7.1.4 change logs
This commit is contained in:
JT Smith 2006-11-07 23:15:57 +00:00
parent 6bf329d68d
commit 4f68a0933c
1026 changed files with 331404 additions and 60 deletions

View file

@ -0,0 +1,167 @@
/*
* YUI Extensions
* Copyright(c) 2006, Jack Slocum.
*
* This code is licensed under BSD license.
* http://www.opensource.org/licenses/bsd-license.php
*/
/**
* @class
* This abstract class provides default implementations of the events required by the Grid.
It takes care of the creating the CustomEvents and provides some convenient methods for firing the events. <br><br>
* @constructor
*/
YAHOO.ext.grid.AbstractDataModel = function(){
/** Fires when a cell is updated - fireDirect sig: (this, rowIndex, columnIndex)
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onCellUpdated = new YAHOO.util.CustomEvent('onCellUpdated');
/** Fires when all data needs to be revalidated - fireDirect sig: (thisd)
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onTableDataChanged = new YAHOO.util.CustomEvent('onTableDataChanged');
/** Fires when rows are deleted - fireDirect sig: (this, firstRowIndex, lastRowIndex)
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onRowsDeleted = new YAHOO.util.CustomEvent('onRowsDeleted');
/** Fires when a rows are inserted - fireDirect sig: (this, firstRowIndex, lastRowIndex)
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onRowsInserted = new YAHOO.util.CustomEvent('onRowsInserted');
/** Fires when a rows are updated - fireDirect sig: (this, firstRowIndex, lastRowIndex)
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onRowsUpdated = new YAHOO.util.CustomEvent('onRowsUpdated');
/** Fires when a sort has reordered the rows - fireDirect sig: (this, sortColumnIndex,
* sortDirection = 'ASC' or 'DESC')
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onRowsSorted = new YAHOO.util.CustomEvent('onRowsSorted');
this.events = {
'cellupdated' : this.onCellUpdated,
'datachanged' : this.onTableDataChanged,
'rowsdeleted' : this.onRowsDeleted,
'rowsinserted' : this.onRowsInserted,
'rowsupdated' : this.onRowsUpdated,
'rowssorted' : this.onRowsSorted
};
};
YAHOO.ext.grid.AbstractDataModel.prototype = {
addListener : YAHOO.ext.grid.Grid.prototype.addListener,
removeListener : YAHOO.ext.grid.Grid.prototype.removeListener,
fireEvent : YAHOO.ext.grid.Grid.prototype.fireEvent,
/**
* Notifies listeners that the value of the cell at [row, col] has been updated
*/
fireCellUpdated : function(row, col){
this.onCellUpdated.fireDirect(this, row, col);
},
/**
* Notifies listeners that all data for the grid may have changed - use as a last resort. This
* also wipes out all selections a user might have made.
*/
fireTableDataChanged : function(){
this.onTableDataChanged.fireDirect(this);
},
/**
* Notifies listeners that rows in the range [firstRow, lastRow], inclusive, have been deleted
*/
fireRowsDeleted : function(firstRow, lastRow){
this.onRowsDeleted.fireDirect(this, firstRow, lastRow);
},
/**
* Notifies listeners that rows in the range [firstRow, lastRow], inclusive, have been inserted
*/
fireRowsInserted : function(firstRow, lastRow){
this.onRowsInserted.fireDirect(this, firstRow, lastRow);
},
/**
* Notifies listeners that rows in the range [firstRow, lastRow], inclusive, have been updated
*/
fireRowsUpdated : function(firstRow, lastRow){
this.onRowsUpdated.fireDirect(this, firstRow, lastRow);
},
/**
* Notifies listeners that rows have been sorted and any indexes may be invalid
*/
fireRowsSorted : function(sortColumnIndex, sortDir, noRefresh){
this.onRowsSorted.fireDirect(this, sortColumnIndex, sortDir, noRefresh);
},
/**
* Empty interface method - Classes which extend AbstractDataModel should implement this method.
* See {@link YAHOO.ext.DefaultDataModel} for an example implementation.
*/
sort : function(columnModel, columnIndex, direction, suppressEvent){
},
/**
* Interface method to supply the view with info regarding the Grid's current sort state - if overridden,
* this should return an object like this {column: this.sortColumn, direction: this.sortDir}.
* @return {Object}
*/
getSortState : function(){
return {column: this.sortColumn, direction: this.sortDir};
},
/**
* Empty interface method - Classes which extend AbstractDataModel should implement this method.
* See {@link YAHOO.ext.DefaultDataModel} for an example implementation.
*/
getRowCount : function(){
},
/**
* Empty interface method - Classes which extend AbstractDataModel should implement this method to support virtual row counts.
*/
getTotalRowCount : function(){
return this.getRowCount();
},
/**
* Empty interface method - Classes which extend AbstractDataModel should implement this method.
* See {@link YAHOO.ext.DefaultDataModel} for an example implementation.
*/
getRowId : function(rowIndex){
},
/**
* Empty interface method - Classes which extend AbstractDataModel should implement this method.
* See {@link YAHOO.ext.DefaultDataModel} for an example implementation.
*/
getValueAt : function(rowIndex, colIndex){
},
/**
* Empty interface method - Classes which extend AbstractDataModel should implement this method.
* See {@link YAHOO.ext.DefaultDataModel} for an example implementation.
*/
setValueAt : function(value, rowIndex, colIndex){
},
isPaged : function(){
return false;
}
};

View file

@ -0,0 +1,311 @@
/*
* YUI Extensions
* Copyright(c) 2006, Jack Slocum.
*
* This code is licensed under BSD license.
* http://www.opensource.org/licenses/bsd-license.php
*/
/**
* @class
* 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.
* <br>Usage:<br>
* <pre><code>
* 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);
* </code></pre>
* @extends YAHOO.ext.grid.AbstractDataModel
* @constructor
*/
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}
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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}
*/
YAHOO.ext.grid.DefaultDataModel.prototype.getRowId = function(rowIndex){
return this.data[rowIndex][0];
};
/**
* Returns the column data for the specified row.
* @return {Array}
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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}
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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}
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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 {<i>Number</i>} endIndex (optional) Defaults to startIndex
*/
YAHOO.ext.grid.DefaultDataModel.prototype.removeRows = function(startIndex, endIndex){
endIndex = endIndex || startIndex;
this.data.splice(startIndex, endIndex-startIndex+1);
this.fireRowsDeleted(startIndex, endIndex);
};
/**
* Remove a row.
* @param {Number} index
*/
YAHOO.ext.grid.DefaultDataModel.prototype.removeRow = function(index){
this.data.splice(index, 1);
this.fireRowsDeleted(index, index);
};
/**
* @private
* Removes all rows.
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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...
* <pre><code>
* // column 1 starts with Jack, column 2 filtered by myFcn, column 3 equals 'Fred'
* dataModel.filter({1: /^Jack.+/i}, 2: myFcn, 3: 'Fred'});
* </code></pre>
* @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.
* @param {Boolean} returnUnmatched True to return rows which <b>don't</b> match the query instead
* of rows that do match
* @return {Array} An array of row indexes that match
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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
*/
YAHOO.ext.grid.DefaultDataModel.prototype.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.
*/
YAHOO.ext.grid.DefaultDataModel.prototype.applySort = function(suppressEvent){
if(this.columnModel && typeof this.sortColumn != 'undefined'){
this.sort(this.columnModel, this.sortColumn, this.sortDir, suppressEvent);
}
};
YAHOO.ext.grid.DefaultDataModel.prototype.setDefaultSort = function(columnModel, columnIndex, direction){
this.columnModel = columnModel;
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 {YAHOO.ext.grid.DefaultColumnModel} columnModel The ColumnModel for this dataset
* @param {Number} columnIndex The column index to sort by
* @param {String} direction The direction of the sort ('DESC' or 'ASC')
*/
YAHOO.ext.grid.DefaultDataModel.prototype.sort = function(columnModel, columnIndex, direction, suppressEvent){
// store these so we can maintain sorting when we load new data
this.columnModel = columnModel;
this.sortColumn = columnIndex;
this.sortDir = direction;
var dsc = direction == 'DESC';
var sortType = columnModel.getSortType(columnIndex);
var fn = function(cells, cells2){
var v1 = sortType(cells[columnIndex], cells);
var v2 = sortType(cells2[columnIndex], cells2);
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);
}
};

View file

@ -0,0 +1,83 @@
/*
* YUI Extensions
* Copyright(c) 2006, Jack Slocum.
*
* This code is licensed under BSD license.
* http://www.opensource.org/licenses/bsd-license.php
*/
/**
* @class
* This is an implementation of a DataModel used by the Grid. It works
* with JSON data.
* <br>Example schema:
* <pre><code>
* var schema = {
* root: 'Results.Result',
* id: 'ASIN',
* fields: ['Author', 'Title', 'Manufacturer', 'ProductGroup']
* };
* </code></pre>
* @extends YAHOO.ext.grid.LoadableDataModel
* @constructor
*/
YAHOO.ext.grid.JSONDataModel = function(schema){
YAHOO.ext.grid.JSONDataModel.superclass.constructor.call(this, YAHOO.ext.grid.LoadableDataModel.JSON);
/**@private*/
this.schema = schema;
};
YAHOO.extendX(YAHOO.ext.grid.JSONDataModel, YAHOO.ext.grid.LoadableDataModel);
/**
* Overrides loadData in LoadableDataModel to process JSON data
* @param {Object} data The JSON object to load
* @param {Function} callback
*/
YAHOO.ext.grid.JSONDataModel.prototype.loadData = function(data, callback, keepExisting){
var idField = this.schema.id;
var fields = this.schema.fields;
var rowData = [];
try{
var root = eval('data.' + this.schema.root);
for(var i = 0; i < root.length; i++){
var node = root[i];
var colData = [];
colData.node = node;
colData.id = (typeof node[idField] != 'undefined' && node[idField] !== '' ? node[idField] : String(i));
for(var j = 0; j < fields.length; j++) {
var val = node[fields[j]];
if(typeof val == 'undefined'){
val = '';
}
if(this.preprocessors[j]){
val = this.preprocessors[j](val);
}
colData.push(val);
}
rowData.push(colData);
}
if(keepExisting !== true){
this.removeAll();
}
this.addRows(rowData);
if(typeof callback == 'function'){
callback(this, true);
}
this.fireLoadEvent();
}catch(e){
this.fireLoadException(e, null);
if(typeof callback == 'function'){
callback(this, false);
}
}
};
/**
* Overrides getRowId in DefaultDataModel to return the ID value of the specified node.
* @param {Number} rowIndex
* @return {Number}
*/
YAHOO.ext.grid.JSONDataModel.prototype.getRowId = function(rowIndex){
return this.data[rowIndex].id;
};

View file

@ -0,0 +1,346 @@
/*
* YUI Extensions
* Copyright(c) 2006, Jack Slocum.
*
* This code is licensed under BSD license.
* http://www.opensource.org/licenses/bsd-license.php
*/
/**
* @class
* This class extends DefaultDataModel and adds the core functionality to load data remotely. <br><br>
* @extends YAHOO.ext.grid.DefaultDataModel
* @constructor
* @param {String} dataType YAHOO.ext.grid.LoadableDataModel.XML, YAHOO.ext.grid.LoadableDataModel.TEXT or YAHOO.ext.grid.JSON
*/
YAHOO.ext.grid.LoadableDataModel = function(dataType){
YAHOO.ext.grid.LoadableDataModel.superclass.constructor.call(this, []);
/** Fires when a successful load is completed - fireDirect sig: (this)
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onLoad = new YAHOO.util.CustomEvent('load');
/** Fires when a load fails - fireDirect sig: (this, errorMsg, responseObj)
* @type YAHOO.util.CustomEvent
* @deprecated Use addListener instead of accessing directly
*/
this.onLoadException = new YAHOO.util.CustomEvent('loadException');
this.events['load'] = this.onLoad;
this.events['beforeload'] = new YAHOO.util.CustomEvent('beforeload');
this.events['loadexception'] = this.onLoadException;
/**@private*/
this.dataType = dataType;
/**@private*/
this.preprocessors = [];
/**@private*/
this.postprocessors = [];
// paging info
/** The active page @type Number*/
this.loadedPage = 1;
/** True to use remote sorting, initPaging automatically sets this to true @type Boolean */
this.remoteSort = false;
/** The number of records per page @type Number*/
this.pageSize = 0;
/** The script/page to call to provide paged/sorted data @type String*/
this.pageUrl = null;
/** An object of key/value pairs to be passed as parameters
* when loading pages/sorting @type Object*/
this.baseParams = {};
/** Maps named params to url parameters - Override to specify your own param names */
this.paramMap = {'page':'page', 'pageSize':'pageSize', 'sortColumn':'sortColumn', 'sortDir':'sortDir'};
};
YAHOO.extendX(YAHOO.ext.grid.LoadableDataModel, YAHOO.ext.grid.DefaultDataModel);
/** @ignore */
YAHOO.ext.grid.LoadableDataModel.prototype.setLoadedPage = function(pageNum, userCallback){
this.loadedPage = pageNum;
if(typeof userCallback == 'function'){
userCallback();
}
};
/** Returns true if this model uses paging @type Boolean */
YAHOO.ext.grid.LoadableDataModel.prototype.isPaged = function(){
return this.pageSize > 0;
};
/** Returns the total number of records available, override if needed @type Number */
YAHOO.ext.grid.LoadableDataModel.prototype.getTotalRowCount = function(){
return this.totalCount || this.getRowCount();
};
/** Returns the number of records per page @type Number */
YAHOO.ext.grid.LoadableDataModel.prototype.getPageSize = function(){
return this.pageSize;
};
/** Returns the total number of pages available @type Number */
YAHOO.ext.grid.LoadableDataModel.prototype.getTotalPages = function(){
if(this.getPageSize() == 0 || this.getTotalRowCount() == 0){
return 1;
}
return Math.ceil(this.getTotalRowCount()/this.getPageSize());
};
/** Initializes paging for this model. */
YAHOO.ext.grid.LoadableDataModel.prototype.initPaging = function(url, pageSize, baseParams){
this.pageUrl = url;
this.pageSize = pageSize;
this.remoteSort = true;
if(baseParams) this.baseParams = baseParams;
};
/** @ignore */
YAHOO.ext.grid.LoadableDataModel.prototype.createParams = function(pageNum, sortColumn, sortDir){
var params = {}, map = this.paramMap;
for(var key in this.baseParams){
if(typeof this.baseParams[key] != 'function'){
params[key] = this.baseParams[key];
}
}
params[map['page']] = pageNum;
params[map['pageSize']] = this.getPageSize();
params[map['sortColumn']] = (typeof sortColumn == 'undefined' ? '' : sortColumn);
params[map['sortDir']] = sortDir || '';
return params;
};
YAHOO.ext.grid.LoadableDataModel.prototype.loadPage = function(pageNum, callback, keepExisting){
var sort = this.getSortState();
var params = this.createParams(pageNum, sort.column, sort.direction);
this.load(this.pageUrl, params, this.setLoadedPage.createDelegate(this, [pageNum, callback]),
keepExisting ? (pageNum-1) * this.pageSize : null);
};
/** @ignore */
YAHOO.ext.grid.LoadableDataModel.prototype.applySort = function(suppressEvent){
if(!this.remoteSort){
YAHOO.ext.grid.LoadableDataModel.superclass.applySort.apply(this, arguments);
}else if(!suppressEvent){
var sort = this.getSortState();
if(sort.column){
this.fireRowsSorted(sort.column, sort.direction, true);
}
}
};
/** @ignore */
YAHOO.ext.grid.LoadableDataModel.prototype.resetPaging = function(){
this.loadedPage = 1;
};
/** Overridden sort method to use remote sorting if turned on */
YAHOO.ext.grid.LoadableDataModel.prototype.sort = function(columnModel, columnIndex, direction, suppressEvent){
if(!this.remoteSort){
YAHOO.ext.grid.LoadableDataModel.superclass.sort.apply(this, arguments);
}else{
this.columnModel = columnModel;
this.sortColumn = columnIndex;
this.sortDir = direction;
var params = this.createParams(this.loadedPage, columnIndex, direction);
this.load(this.pageUrl, params, this.fireRowsSorted.createDelegate(this, [columnIndex, direction, true]));
}
}
/**
* Initiates the loading of the data from the specified URL - Failed load attempts will
* fire the {@link #onLoadException} event.
* @param {Object/String} url The url from which the data can be loaded
* @param {<i>String/Object</i>} params (optional) The parameters to pass as either a url encoded string "param1=1&amp;param2=2" or as an object {param1: 1, param2: 2}
* @param {<i>Function</i>} callback (optional) Callback when load is complete - called with signature (this, rowCountLoaded)
* @param {<i>Number</i>} insertIndex (optional) if present, loaded data is inserted at the specified index instead of overwriting existing data
*/
YAHOO.ext.grid.LoadableDataModel.prototype.load = function(url, params, callback, insertIndex){
this.fireEvent('beforeload');
if(params && typeof params != 'string'){ // must be object
var buf = [];
for(var key in params){
if(typeof params[key] != 'function'){
buf.push(encodeURIComponent(key), '=', encodeURIComponent(params[key]), '&');
}
}
delete buf[buf.length-1];
params = buf.join('');
}
var cb = {
success: this.processResponse,
failure: this.processException,
scope: this,
argument: {callback: callback, insertIndex: insertIndex}
};
var method = params ? 'POST' : 'GET';
YAHOO.util.Connect.asyncRequest(method, url, cb, params);
};
/**@private*/
YAHOO.ext.grid.LoadableDataModel.prototype.processResponse = function(response){
var cb = response.argument.callback;
var keepExisting = (typeof response.argument.insertIndex == 'number');
var insertIndex = response.argument.insertIndex;
switch(this.dataType){
case YAHOO.ext.grid.LoadableDataModel.XML:
this.loadData(response.responseXML, cb, keepExisting, insertIndex);
break;
case YAHOO.ext.grid.LoadableDataModel.JSON:
var rtext = response.responseText;
try { // this code is a modified version of Yahoo! UI DataSource JSON parsing
// Trim leading spaces
while(rtext.substring(0,1) == " ") {
rtext = rtext.substring(1, rtext.length);
}
// Invalid JSON response
if(rtext.indexOf("{") < 0) {
throw "Invalid JSON response";
}
// Empty (but not invalid) JSON response
if(rtext.indexOf("{}") === 0) {
this.loadData({}, response.argument.callback);
return;
}
// Turn the string into an object literal...
// ...eval is necessary here
var jsonObjRaw = eval("(" + rtext + ")");
if(!jsonObjRaw) {
throw "Error evaling JSON response";
}
this.loadData(jsonObjRaw, cb, keepExisting, insertIndex);
} catch(e) {
this.fireLoadException(e, response);
if(typeof callback == 'function'){
callback(this, false);
}
}
break;
case YAHOO.ext.grid.LoadableDataModel.TEXT:
this.loadData(response.responseText, cb, keepExisting, insertIndex);
break;
};
};
/**@private*/
YAHOO.ext.grid.LoadableDataModel.prototype.processException = function(response){
this.fireLoadException(null, response);
if(typeof response.argument.callback == 'function'){
response.argument.callback(this, false);
}
};
YAHOO.ext.grid.LoadableDataModel.prototype.fireLoadException = function(e, responseObj){
this.onLoadException.fireDirect(this, e, responseObj);
};
YAHOO.ext.grid.LoadableDataModel.prototype.fireLoadEvent = function(){
this.fireEvent('load', this.loadedPage, this.getTotalPages());
};
/**
* Adds a preprocessor function to parse data before it is added to the Model - ie. Date.parse to parse dates.
*/
YAHOO.ext.grid.LoadableDataModel.prototype.addPreprocessor = function(columnIndex, fn){
this.preprocessors[columnIndex] = fn;
};
/**
* Gets the preprocessor function for the specified column.
*/
YAHOO.ext.grid.LoadableDataModel.prototype.getPreprocessor = function(columnIndex){
return this.preprocessors[columnIndex];
};
/**
* Removes a preprocessor function.
*/
YAHOO.ext.grid.LoadableDataModel.prototype.removePreprocessor = function(columnIndex){
this.preprocessors[columnIndex] = null;
};
/**
* Adds a postprocessor function to format data before updating the underlying data source (ie. convert date to string before updating XML document).
*/
YAHOO.ext.grid.LoadableDataModel.prototype.addPostprocessor = function(columnIndex, fn){
this.postprocessors[columnIndex] = fn;
};
/**
* Gets the postprocessor function for the specified column.
*/
YAHOO.ext.grid.LoadableDataModel.prototype.getPostprocessor = function(columnIndex){
return this.postprocessors[columnIndex];
};
/**
* Removes a postprocessor function.
*/
YAHOO.ext.grid.LoadableDataModel.prototype.removePostprocessor = function(columnIndex){
this.postprocessors[columnIndex] = null;
};
/**
* Empty interface method - Called to process the data returned by the XHR - Classes which extend LoadableDataModel should implement this method.
* See {@link YAHOO.ext.XMLDataModel} for an example implementation.
*/
YAHOO.ext.grid.LoadableDataModel.prototype.loadData = function(data, callback, keepExisting, insertIndex){
};
YAHOO.ext.grid.LoadableDataModel.XML = 'xml';
YAHOO.ext.grid.LoadableDataModel.JSON = 'json';
YAHOO.ext.grid.LoadableDataModel.TEXT = 'text';
/*
YAHOO.ext.grid.SparceDataset = function(bufferSize){
this.stack = [];
this.bufferSize = bufferSize || 1000;
this.maxIndex = 0;
this.events = {
'rowsexpired' : new YAHOO.util.CustomEvent('rowsexpired')
};
};
YAHOO.ext.grid.SparceDataset.prototype = {
addListener : YAHOO.ext.grid.Grid.prototype.addListener,
removeListener : YAHOO.ext.grid.Grid.prototype.removeListener,
fireEvent : YAHOO.ext.grid.Grid.prototype.fireEvent,
getRowAt : function(index){
return this[String(index)];
},
splice : function(index, deleteCount){
this.insertRowsAt(index, Array.prototype.slice.call(arguments, 2));
},
concat : function(){
this.insertRowsAt(index, Array.prototype.slice.call(arguments, 2));
},
insertRowsAt: function(index, rowData){
for(var i = 0; i < rowData.length; i++) {
var d = rowData[i];
var dataIndex = index + i;
this[dataIndex] = d;
this.stack.push(dataIndex);
}
this.maxIndex = Math.max(this.maxIndex, index+rowData.length);
this.cleanup();
},
cleanup : function(){
while(stack.length > this.bufferSize){
var dataIndex = stack.shift();
delete this[dataIndex];
this.fireEvent('rowsexpired', dataIndex);
}
}
};*/

View file

@ -0,0 +1,239 @@
/*
* YUI Extensions
* Copyright(c) 2006, Jack Slocum.
*
* This code is licensed under BSD license.
* http://www.opensource.org/licenses/bsd-license.php
*/
/**
* @class
* This is an implementation of a DataModel used by the Grid. It works
* with XML data.
* <br>Example schema from Amazon search:
* <pre><code>
* var schema = {
* tagName: 'Item',
* id: 'ASIN',
* fields: ['Author', 'Title', 'Manufacturer', 'ProductGroup']
* };
* </code></pre>
* @extends YAHOO.ext.grid.LoadableDataModel
* @constructor
* @param {Object} schema The schema to use
* @param {XMLDocument} xml An XML document to load immediately
*/
YAHOO.ext.grid.XMLDataModel = function(schema, xml){
YAHOO.ext.grid.XMLDataModel.superclass.constructor.call(this, YAHOO.ext.grid.LoadableDataModel.XML);
/**@private*/
this.schema = schema;
this.xml = xml;
if(xml){
this.loadData(xml);
}
};
YAHOO.extendX(YAHOO.ext.grid.XMLDataModel, YAHOO.ext.grid.LoadableDataModel);
YAHOO.ext.grid.XMLDataModel.prototype.getDocument = function(){
return this.xml;
};
/**
* Overrides loadData in LoadableDataModel to process XML
* @param {XMLDocument} doc The document to load
* @param {<i>Function</i>} callback (optional) callback to call when loading is complete
* @param {<i>Boolean</i>} keepExisting (optional) true to keep existing data
* @param {<i>Number</i>} insertIndex (optional) if present, loaded data is inserted at the specified index instead of overwriting existing data
*/
YAHOO.ext.grid.XMLDataModel.prototype.loadData = function(doc, callback, keepExisting, insertIndex){
this.xml = doc;
var idField = this.schema.id;
var fields = this.schema.fields;
if(this.schema.totalTag){
this.totalCount = null;
var totalNode = doc.getElementsByTagName(this.schema.totalTag);
if(totalNode && totalNode.item(0) && totalNode.item(0).firstChild) {
var v = parseInt(totalNode.item(0).firstChild.nodeValue, 10);
if(!isNaN(v)){
this.totalCount = v;
}
}
}
var rowData = [];
var nodes = doc.getElementsByTagName(this.schema.tagName);
if(nodes && nodes.length > 0) {
for(var i = 0; i < nodes.length; i++) {
var node = nodes.item(i);
var colData = [];
colData.node = node;
colData.id = this.getNamedValue(node, idField, String(i));
for(var j = 0; j < fields.length; j++) {
var val = this.getNamedValue(node, fields[j], "");
if(this.preprocessors[j]){
val = this.preprocessors[j](val);
}
colData.push(val);
}
rowData.push(colData);
}
}
if(keepExisting !== true){
YAHOO.ext.grid.XMLDataModel.superclass.removeAll.call(this);
}
if(typeof insertIndex != 'number'){
insertIndex = this.getRowCount();
}
YAHOO.ext.grid.XMLDataModel.superclass.insertRows.call(this, insertIndex, rowData);
if(typeof callback == 'function'){
callback(this, true);
}
this.fireLoadEvent();
};
/**
* Adds a row to this DataModel and syncs the XML document
* @param {String} id The id of the row, if null the next row index is used
* @param {Array} cellValues The cell values for this row
* @return {Number} The index of the new row
*/
YAHOO.ext.grid.XMLDataModel.prototype.addRow = function(id, cellValues){
var newIndex = this.getRowCount();
var node = this.createNode(this.xml, id, cellValues);
cellValues.id = id || newIndex;
cellValues.node = node;
YAHOO.ext.grid.XMLDataModel.superclass.addRow.call(this, cellValues);
return newIndex;
};
/**
* Inserts a row into this DataModel and syncs the XML document
* @param {Number} index The index to insert the row
* @param {String} id The id of the row, if null the next row index is used
* @param {Array} cellValues The cell values for this row
* @return {Number} The index of the new row
*/
YAHOO.ext.grid.XMLDataModel.prototype.insertRow = function(index, id, cellValues){
var node = this.createNode(this.xml, id, cellValues);
cellValues.id = id || this.getRowCount();
cellValues.node = node;
YAHOO.ext.grid.XMLDataModel.superclass.insertRow.call(this, index, cellValues);
return index;
};
/**
* Removes the row from DataModel and syncs the XML document
* @param {Number} index The index of the row to remove
*/
YAHOO.ext.grid.XMLDataModel.prototype.removeRow = function(index){
var node = this.data[index].node;
node.parentNode.removeChild(node);
YAHOO.ext.grid.XMLDataModel.superclass.removeRow.call(this, index, index);
};
YAHOO.ext.grid.XMLDataModel.prototype.getNode = function(rowIndex){
return this.data[rowIndex].node;
};
/**
* Override this method to define your own node creation routine for when new rows are added.
* By default this method clones the first node and sets the column values in the newly cloned node.
* @param {XMLDocument} xmlDoc The xml document being used by this model
* @param {Array} colData The column data for the new node
* @return {XMLNode} The created node
*/
YAHOO.ext.grid.XMLDataModel.prototype.createNode = function(xmlDoc, id, colData){
var template = this.data[0].node;
var newNode = template.cloneNode(true);
var fields = this.schema.fields;
for(var i = 0; i < fields.length; i++){
var nodeValue = colData[i];
if(this.postprocessors[i]){
nodeValue = this.postprocessors[i](nodeValue);
}
this.setNamedValue(newNode, fields[i], nodeValue);
}
if(id){
this.setNamedValue(newNode, this.schema.idField, id);
}
template.parentNode.appendChild(newNode);
return newNode;
};
/**
* Convenience function looks for value in attributes, then in children tags - also
* normalizes namespace matches (ie matches ns:tag, FireFox matches tag and not ns:tag).
*/
YAHOO.ext.grid.XMLDataModel.prototype.getNamedValue = function(node, name, defaultValue){
if(!node || !name){
return defaultValue;
}
var nodeValue = defaultValue;
var attrNode = node.attributes.getNamedItem(name);
if(attrNode) {
nodeValue = attrNode.value;
} else {
var childNode = node.getElementsByTagName(name);
if(childNode && childNode.item(0) && childNode.item(0).firstChild) {
nodeValue = childNode.item(0).firstChild.nodeValue;
}else{
// try to strip namespace for FireFox
var index = name.indexOf(':');
if(index > 0){
return this.getNamedValue(node, name.substr(index+1), defaultValue);
}
}
}
return nodeValue;
};
/**
* Convenience function set a value in the underlying xml node.
*/
YAHOO.ext.grid.XMLDataModel.prototype.setNamedValue = function(node, name, value){
if(!node || !name){
return;
}
var attrNode = node.attributes.getNamedItem(name);
if(attrNode) {
attrNode.value = value;
return;
}
var childNode = node.getElementsByTagName(name);
if(childNode && childNode.item(0) && childNode.item(0).firstChild) {
childNode.item(0).firstChild.nodeValue = value;
}else{
// try to strip namespace for FireFox
var index = name.indexOf(':');
if(index > 0){
this.setNamedValue(node, name.substr(index+1), value);
}
}
};
/**
* Overrides DefaultDataModel.setValueAt to update the underlying XML Document
* @param {Object} value The new value
* @param {Number} rowIndex
* @param {Number} colIndex
*/
YAHOO.ext.grid.XMLDataModel.prototype.setValueAt = function(value, rowIndex, colIndex){
var node = this.data[rowIndex].node;
if(node){
var nodeValue = value;
if(this.postprocessors[colIndex]){
nodeValue = this.postprocessors[colIndex](value);
}
this.setNamedValue(node, this.schema.fields[colIndex], nodeValue);
}
YAHOO.ext.grid.XMLDataModel.superclass.setValueAt.call(this, value, rowIndex, colIndex);
};
/**
* Overrides getRowId in DefaultDataModel to return the ID value of the specified node.
* @param {Number} rowIndex
* @return {Number}
*/
YAHOO.ext.grid.XMLDataModel.prototype.getRowId = function(rowIndex){
return this.data[rowIndex].id;
};