summaryrefslogtreecommitdiff
path: root/frontend/beta/js/YUI-extensions/data/LoadableDataModel.js
Unidiff
Diffstat (limited to 'frontend/beta/js/YUI-extensions/data/LoadableDataModel.js') (more/less context) (show whitespace changes)
-rw-r--r--frontend/beta/js/YUI-extensions/data/LoadableDataModel.js330
1 files changed, 330 insertions, 0 deletions
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 @@
1/**
2 * @class YAHOO.ext.grid.LoadableDataModel
3 * This class extends DefaultDataModel and adds the core functionality to load data remotely. Generally you will want to use one of it's subclasses.<br><br>
4 * @extends YAHOO.ext.grid.DefaultDataModel
5 * @constructor
6 * @param {String} dataType YAHOO.ext.grid.LoadableDataModel.XML, YAHOO.ext.grid.LoadableDataModel.TEXT or YAHOO.ext.grid.JSON
7*/
8YAHOO.ext.grid.LoadableDataModel = function(dataType){
9 YAHOO.ext.grid.LoadableDataModel.superclass.constructor.call(this, []);
10
11 /** Fires when a successful load is completed - fireDirect sig: (this)
12 * @type YAHOO.util.CustomEvent
13 * @deprecated Use addListener instead of accessing directly
14 * @private
15 */
16 this.onLoad = new YAHOO.util.CustomEvent('load');
17 /** Fires when a load fails - fireDirect sig: (this, errorMsg, responseObj)
18 * @type YAHOO.util.CustomEvent
19 * @deprecated Use addListener instead of accessing directly
20 * @private
21 */
22 this.onLoadException = new YAHOO.util.CustomEvent('loadException');
23 /**
24 * @event load
25 * Fires when new data has successfully been loaded
26 * @param {DataModel} this
27 */
28 this.events['load'] = this.onLoad;
29 /**
30 * @event beforeload
31 * Fires before a load takes place
32 * @param {DataModel} this
33 */
34 this.events['beforeload'] = new YAHOO.util.CustomEvent('beforeload');
35 /**
36 * @event loadexception
37 * Fires when there's an error loading data
38 * @param {DataModel} this
39 * @param {Exception} e The exception object or null
40 * @param {Object} response The Connect response object
41 */
42 this.events['loadexception'] = this.onLoadException;
43
44 /**@private*/
45 this.dataType = dataType;
46 /**@private*/
47 this.preprocessors = [];
48 /**@private*/
49 this.postprocessors = [];
50
51 // paging info
52 /** The active page @type Number*/
53 this.loadedPage = 1;
54 /** True to use remote sorting, initPaging automatically sets this to true @type Boolean */
55 this.remoteSort = false;
56 /** The number of records per page @type Number*/
57 this.pageSize = 0;
58 /** The script/page to call to provide paged/sorted data @type String*/
59 this.pageUrl = null;
60 /** An object of key/value pairs to be passed as parameters
61 * when loading pages/sorting @type Object*/
62 this.baseParams = {};
63 /** Maps named params to url parameters - Override to specify your own param names */
64 this.paramMap = {'page':'page', 'pageSize':'pageSize', 'sortColumn':'sortColumn', 'sortDir':'sortDir'};
65
66};
67YAHOO.extendX(YAHOO.ext.grid.LoadableDataModel, YAHOO.ext.grid.DefaultDataModel, {
68
69 /** @ignore */
70 setLoadedPage: function(pageNum, userCallback){
71 this.loadedPage = pageNum;
72 if(typeof userCallback == 'function'){
73 userCallback();
74 }
75 },
76
77 /** Returns true if this model uses paging @return Boolean */
78 isPaged: function(){
79 return this.pageSize > 0;
80 },
81
82 /** Returns the total number of records available, override if needed @return {Number} */
83 getTotalRowCount: function(){
84 return this.totalCount || this.getRowCount();
85 },
86
87 /** Returns the number of records per page @return Number */
88 getPageSize: function(){
89 return this.pageSize;
90 },
91
92 /** Returns the total number of pages available @return Number */
93 getTotalPages: function(){
94 if(this.getPageSize() == 0 || this.getTotalRowCount() == 0){
95 return 1;
96 }
97 return Math.ceil(this.getTotalRowCount()/this.getPageSize());
98 },
99
100 /** Initializes paging for this model.
101 * @param {String} url
102 * @param {Number} pageSize
103 * @param {Object} baseParams (optional) Object containing key/value pairs to add to all requests
104 */
105 initPaging: function(url, pageSize, baseParams){
106 this.pageUrl = url;
107 this.pageSize = pageSize;
108 this.remoteSort = true;
109 if(baseParams) this.baseParams = baseParams;
110 },
111
112 /** @ignore */
113 createParams: function(pageNum, sortColumn, sortDir){
114 var params = {}, map = this.paramMap;
115 for(var key in this.baseParams){
116 if(typeof this.baseParams[key] != 'function'){
117 params[key] = this.baseParams[key];
118 }
119 }
120 params[map['page']] = pageNum;
121 params[map['pageSize']] = this.getPageSize();
122 params[map['sortColumn']] = (typeof sortColumn == 'undefined' ? '' : sortColumn);
123 params[map['sortDir']] = sortDir || '';
124 return params;
125 },
126
127 /**
128 * Loads a page of data.
129 * @param {Number} pageNum Which page to load. The first page is 1.
130 * @param {Function} callback (optional) Optional callback when loading is complete
131 * @param {Boolean} keepExisting (optional) true to keep existing data and append the new data
132 */
133 loadPage: function(pageNum, callback, keepExisting){
134 var sort = this.getSortState();
135 var params = this.createParams(pageNum, sort.column, sort.direction);
136 this.load(this.pageUrl, params, this.setLoadedPage.createDelegate(this, [pageNum, callback]),
137 keepExisting ? (pageNum-1) * this.pageSize : null);
138 },
139
140 /** @ignore */
141 applySort: function(suppressEvent){
142 if(!this.remoteSort){
143 YAHOO.ext.grid.LoadableDataModel.superclass.applySort.apply(this, arguments);
144 }else if(!suppressEvent){
145 var sort = this.getSortState();
146 if(sort.column){
147 this.fireRowsSorted(sort.column, sort.direction, true);
148 }
149 }
150 },
151
152 /** @ignore */
153 resetPaging: function(){
154 this.loadedPage = 1;
155 },
156
157 /* Overridden sort method to use remote sorting if turned on */
158 sort: function(sortInfo, columnIndex, direction, suppressEvent){
159 if(!this.remoteSort){
160 YAHOO.ext.grid.LoadableDataModel.superclass.sort.apply(this, arguments);
161 }else{
162 this.sortInfo = sortInfo;
163 this.sortColumn = columnIndex;
164 this.sortDir = direction;
165 var params = this.createParams(this.loadedPage, columnIndex, direction);
166 this.load(this.pageUrl, params, this.fireRowsSorted.createDelegate(this, [columnIndex, direction, true]));
167 }
168 },
169
170 /**
171 * Initiates the loading of the data from the specified URL - Failed load attempts will
172 * fire the {@link #loadexception} event.
173 * @param {Object/String} url The url from which the data can be loaded
174 * @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}
175 * @param {<i>Function</i>} callback (optional) Callback when load is complete - called with signature (this, true for success, false for failure)
176 * @param {<i>Number</i>} insertIndex (optional) if present, loaded data is inserted at the specified index instead of overwriting existing data
177 */
178 load: function(url, params, callback, insertIndex){
179 this.fireEvent('beforeload', this);
180 if(params && typeof params != 'string'){ // must be object
181 var buf = [];
182 for(var key in params){
183 if(typeof params[key] != 'function'){
184 buf.push(encodeURIComponent(key), '=', encodeURIComponent(params[key]), '&');
185 }
186 }
187 delete buf[buf.length-1];
188 params = buf.join('');
189 }
190 var cb = {
191 success: this.processResponse,
192 failure: this.processException,
193 scope: this,
194 argument: {callback: callback, insertIndex: insertIndex}
195 };
196 var method = params ? 'POST' : 'GET';
197 this.transId = YAHOO.util.Connect.asyncRequest(method, url, cb, params);
198 },
199
200 /**@private*/
201 processResponse: function(response){
202 var cb = response.argument.callback;
203 var keepExisting = (typeof response.argument.insertIndex == 'number');
204 var insertIndex = response.argument.insertIndex;
205 switch(this.dataType){
206 case YAHOO.ext.grid.LoadableDataModel.XML:
207 this.loadData(response.responseXML, cb, keepExisting, insertIndex);
208 break;
209 case YAHOO.ext.grid.LoadableDataModel.JSON:
210 var rtext = response.responseText;
211 try { // this code is a modified version of Yahoo! UI DataSource JSON parsing
212 // Trim leading spaces
213 while(rtext.substring(0,1) == " ") {
214 rtext = rtext.substring(1, rtext.length);
215 }
216 // Invalid JSON response
217 if(rtext.indexOf("{") < 0) {
218 throw "Invalid JSON response";
219 }
220
221 // Empty (but not invalid) JSON response
222 if(rtext.indexOf("{}") === 0) {
223 this.loadData({}, response.argument.callback);
224 return;
225 }
226
227 // Turn the string into an object literal...
228 // ...eval is necessary here
229 var jsonObjRaw = eval("(" + rtext + ")");
230 if(!jsonObjRaw) {
231 throw "Error evaling JSON response";
232 }
233 this.loadData(jsonObjRaw, cb, keepExisting, insertIndex);
234 } catch(e) {
235 this.fireLoadException(e, response);
236 if(typeof cb == 'function'){
237 cb(this, false);
238 }
239 }
240 break;
241 case YAHOO.ext.grid.LoadableDataModel.TEXT:
242 this.loadData(response.responseText, cb, keepExisting, insertIndex);
243 break;
244 };
245 },
246
247 /**@private*/
248 processException: function(response){
249 this.fireLoadException(null, response);
250 if(typeof response.argument.callback == 'function'){
251 response.argument.callback(this, false);
252 }
253 },
254
255 fireLoadException: function(e, responseObj){
256 this.onLoadException.fireDirect(this, e, responseObj);
257 },
258
259 fireLoadEvent: function(){
260 this.fireEvent('load', this.loadedPage, this.getTotalPages());
261 },
262
263 /**
264 * Adds a preprocessor function to parse data before it is added to the Model - ie. Date.parse to parse dates.
265 * @param {Number} columnIndex
266 * @param {Function} fn
267 */
268 addPreprocessor: function(columnIndex, fn){
269 this.preprocessors[columnIndex] = fn;
270 },
271
272 /**
273 * Gets the preprocessor function for the specified column.
274 * @param {Number} columnIndex
275 * @return {Function}
276 */
277 getPreprocessor: function(columnIndex){
278 return this.preprocessors[columnIndex];
279 },
280
281 /**
282 * Removes a preprocessor function.
283 * @param {Number} columnIndex
284 */
285 removePreprocessor: function(columnIndex){
286 this.preprocessors[columnIndex] = null;
287 },
288
289 /**
290 * Adds a postprocessor function to format data before updating the underlying data source (ie. convert date to string before updating XML document).
291 * @param {Number} columnIndex
292 * @param {Function} fn
293 */
294 addPostprocessor: function(columnIndex, fn){
295 this.postprocessors[columnIndex] = fn;
296 },
297
298 /**
299 * Gets the postprocessor function for the specified column.
300 * @param {Number} columnIndex
301 * @return {Function}
302 */
303 getPostprocessor: function(columnIndex){
304 return this.postprocessors[columnIndex];
305 },
306
307 /**
308 * Removes a postprocessor function.
309 * @param {Number} columnIndex
310 */
311 removePostprocessor: function(columnIndex){
312 this.postprocessors[columnIndex] = null;
313 },
314 /**
315 * Empty interface method - Called to process the data returned by the XHR - Classes which extend LoadableDataModel should implement this method.
316 * See {@link YAHOO.ext.XMLDataModel} for an example implementation.
317 */
318 loadData: function(data, callback, keepExisting, insertIndex){
319
320 }
321});
322
323YAHOO.ext.grid.LoadableDataModel.XML = 'xml';
324YAHOO.ext.grid.LoadableDataModel.JSON = 'json';
325YAHOO.ext.grid.LoadableDataModel.TEXT = 'text';
326
327
328
329
330