From ef68436ac04da078ffdcacd7e1f785473a303d45 Mon Sep 17 00:00:00 2001 From: Giulio Cesare Solaroli Date: Sun, 02 Oct 2011 23:56:18 +0000 Subject: First version of the newly restructured repository --- (limited to 'frontend/beta/js/YUI-extensions/data/LoadableDataModel.js') diff --git a/frontend/beta/js/YUI-extensions/data/LoadableDataModel.js b/frontend/beta/js/YUI-extensions/data/LoadableDataModel.js new file mode 100644 index 0000000..07def44 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/data/LoadableDataModel.js @@ -0,0 +1,330 @@ +/** + * @class YAHOO.ext.grid.LoadableDataModel + * This class extends DefaultDataModel and adds the core functionality to load data remotely. Generally you will want to use one of it's subclasses.

+ * @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 + * @private + */ + 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 + * @private + */ + this.onLoadException = new YAHOO.util.CustomEvent('loadException'); + /** + * @event load + * Fires when new data has successfully been loaded + * @param {DataModel} this + */ + this.events['load'] = this.onLoad; + /** + * @event beforeload + * Fires before a load takes place + * @param {DataModel} this + */ + this.events['beforeload'] = new YAHOO.util.CustomEvent('beforeload'); + /** + * @event loadexception + * Fires when there's an error loading data + * @param {DataModel} this + * @param {Exception} e The exception object or null + * @param {Object} response The Connect response object + */ + 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 */ + setLoadedPage: function(pageNum, userCallback){ + this.loadedPage = pageNum; + if(typeof userCallback == 'function'){ + userCallback(); + } + }, + + /** Returns true if this model uses paging @return Boolean */ + isPaged: function(){ + return this.pageSize > 0; + }, + + /** Returns the total number of records available, override if needed @return {Number} */ + getTotalRowCount: function(){ + return this.totalCount || this.getRowCount(); + }, + + /** Returns the number of records per page @return Number */ + getPageSize: function(){ + return this.pageSize; + }, + + /** Returns the total number of pages available @return Number */ + getTotalPages: function(){ + if(this.getPageSize() == 0 || this.getTotalRowCount() == 0){ + return 1; + } + return Math.ceil(this.getTotalRowCount()/this.getPageSize()); + }, + + /** Initializes paging for this model. + * @param {String} url + * @param {Number} pageSize + * @param {Object} baseParams (optional) Object containing key/value pairs to add to all requests + */ + initPaging: function(url, pageSize, baseParams){ + this.pageUrl = url; + this.pageSize = pageSize; + this.remoteSort = true; + if(baseParams) this.baseParams = baseParams; + }, + + /** @ignore */ + 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; + }, + + /** + * Loads a page of data. + * @param {Number} pageNum Which page to load. The first page is 1. + * @param {Function} callback (optional) Optional callback when loading is complete + * @param {Boolean} keepExisting (optional) true to keep existing data and append the new data + */ + 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 */ + 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 */ + resetPaging: function(){ + this.loadedPage = 1; + }, + + /* Overridden sort method to use remote sorting if turned on */ + sort: function(sortInfo, columnIndex, direction, suppressEvent){ + if(!this.remoteSort){ + YAHOO.ext.grid.LoadableDataModel.superclass.sort.apply(this, arguments); + }else{ + this.sortInfo = sortInfo; + 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 #loadexception} event. + * @param {Object/String} url The url from which the data can be loaded + * @param {String/Object} params (optional) The parameters to pass as either a url encoded string "param1=1&param2=2" or as an object {param1: 1, param2: 2} + * @param {Function} callback (optional) Callback when load is complete - called with signature (this, true for success, false for failure) + * @param {Number} insertIndex (optional) if present, loaded data is inserted at the specified index instead of overwriting existing data + */ + load: function(url, params, callback, insertIndex){ + this.fireEvent('beforeload', this); + 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'; + this.transId = YAHOO.util.Connect.asyncRequest(method, url, cb, params); + }, + + /**@private*/ + 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 cb == 'function'){ + cb(this, false); + } + } + break; + case YAHOO.ext.grid.LoadableDataModel.TEXT: + this.loadData(response.responseText, cb, keepExisting, insertIndex); + break; + }; + }, + + /**@private*/ + processException: function(response){ + this.fireLoadException(null, response); + if(typeof response.argument.callback == 'function'){ + response.argument.callback(this, false); + } + }, + + fireLoadException: function(e, responseObj){ + this.onLoadException.fireDirect(this, e, responseObj); + }, + + 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. + * @param {Number} columnIndex + * @param {Function} fn + */ + addPreprocessor: function(columnIndex, fn){ + this.preprocessors[columnIndex] = fn; + }, + + /** + * Gets the preprocessor function for the specified column. + * @param {Number} columnIndex + * @return {Function} + */ + getPreprocessor: function(columnIndex){ + return this.preprocessors[columnIndex]; + }, + + /** + * Removes a preprocessor function. + * @param {Number} columnIndex + */ + 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). + * @param {Number} columnIndex + * @param {Function} fn + */ + addPostprocessor: function(columnIndex, fn){ + this.postprocessors[columnIndex] = fn; + }, + + /** + * Gets the postprocessor function for the specified column. + * @param {Number} columnIndex + * @return {Function} + */ + getPostprocessor: function(columnIndex){ + return this.postprocessors[columnIndex]; + }, + + /** + * Removes a postprocessor function. + * @param {Number} columnIndex + */ + 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. + */ + loadData: function(data, callback, keepExisting, insertIndex){ + + } +}); + +YAHOO.ext.grid.LoadableDataModel.XML = 'xml'; +YAHOO.ext.grid.LoadableDataModel.JSON = 'json'; +YAHOO.ext.grid.LoadableDataModel.TEXT = 'text'; + + + + + -- cgit v0.9.0.2