try and get ctrl-enter to add a clear all
[roojs1] / Roo / UpdateManager.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11
12  
13 /**
14  * @class Roo.UpdateManager
15  * @extends Roo.util.Observable
16  * Provides AJAX-style update for Element object.<br><br>
17  * Usage:<br>
18  * <pre><code>
19  * // Get it from a Roo.Element object
20  * var el = Roo.get("foo");
21  * var mgr = el.getUpdateManager();
22  * mgr.update("http://myserver.com/index.php", "param1=1&amp;param2=2");
23  * ...
24  * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
25  * <br>
26  * // or directly (returns the same UpdateManager instance)
27  * var mgr = new Roo.UpdateManager("myElementId");
28  * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
29  * mgr.on("update", myFcnNeedsToKnow);
30  * <br>
31    // short handed call directly from the element object
32    Roo.get("foo").load({
33         url: "bar.php",
34         scripts:true,
35         params: "for=bar",
36         text: "Loading Foo..."
37    });
38  * </code></pre>
39  * @constructor
40  * Create new UpdateManager directly.
41  * @param {String/HTMLElement/Roo.Element} el The element to update
42  * @param {Boolean} forceNew (optional) By default the constructor checks to see if the passed element already has an UpdateManager and if it does it returns the same instance. This will skip that check (useful for extending this class).
43  */
44 Roo.UpdateManager = function(el, forceNew){
45     el = Roo.get(el);
46     if(!forceNew && el.updateManager){
47         return el.updateManager;
48     }
49     /**
50      * The Element object
51      * @type Roo.Element
52      */
53     this.el = el;
54     /**
55      * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
56      * @type String
57      */
58     this.defaultUrl = null;
59
60     this.addEvents({
61         /**
62          * @event beforeupdate
63          * Fired before an update is made, return false from your handler and the update is cancelled.
64          * @param {Roo.Element} el
65          * @param {String/Object/Function} url
66          * @param {String/Object} params
67          */
68         "beforeupdate": true,
69         /**
70          * @event update
71          * Fired after successful update is made.
72          * @param {Roo.Element} el
73          * @param {Object} oResponseObject The response Object
74          */
75         "update": true,
76         /**
77          * @event failure
78          * Fired on update failure.
79          * @param {Roo.Element} el
80          * @param {Object} oResponseObject The response Object
81          */
82         "failure": true
83     });
84     var d = Roo.UpdateManager.defaults;
85     /**
86      * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
87      * @type String
88      */
89     this.sslBlankUrl = d.sslBlankUrl;
90     /**
91      * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
92      * @type Boolean
93      */
94     this.disableCaching = d.disableCaching;
95     /**
96      * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '&lt;div class="loading-indicator"&gt;Loading...&lt;/div&gt;').
97      * @type String
98      */
99     this.indicatorText = d.indicatorText;
100     /**
101      * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
102      * @type String
103      */
104     this.showLoadIndicator = d.showLoadIndicator;
105     /**
106      * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
107      * @type Number
108      */
109     this.timeout = d.timeout;
110
111     /**
112      * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
113      * @type Boolean
114      */
115     this.loadScripts = d.loadScripts;
116
117     /**
118      * Transaction object of current executing transaction
119      */
120     this.transaction = null;
121
122     /**
123      * @private
124      */
125     this.autoRefreshProcId = null;
126     /**
127      * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
128      * @type Function
129      */
130     this.refreshDelegate = this.refresh.createDelegate(this);
131     /**
132      * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
133      * @type Function
134      */
135     this.updateDelegate = this.update.createDelegate(this);
136     /**
137      * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
138      * @type Function
139      */
140     this.formUpdateDelegate = this.formUpdate.createDelegate(this);
141     /**
142      * @private
143      */
144     this.successDelegate = this.processSuccess.createDelegate(this);
145     /**
146      * @private
147      */
148     this.failureDelegate = this.processFailure.createDelegate(this);
149
150     if(!this.renderer){
151      /**
152       * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
153       */
154     this.renderer = new Roo.UpdateManager.BasicRenderer();
155     }
156     
157     Roo.UpdateManager.superclass.constructor.call(this);
158 };
159
160 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
161     /**
162      * Get the Element this UpdateManager is bound to
163      * @return {Roo.Element} The element
164      */
165     getEl : function(){
166         return this.el;
167     },
168     /**
169      * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
170      * @param {Object/String/Function} url The url for this request or a function to call to get the url or a config object containing any of the following options:
171 <pre><code>
172 um.update({<br/>
173     url: "your-url.php",<br/>
174     params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
175     callback: yourFunction,<br/>
176     scope: yourObject, //(optional scope)  <br/>
177     discardUrl: false, <br/>
178     nocache: false,<br/>
179     text: "Loading...",<br/>
180     timeout: 30,<br/>
181     scripts: false<br/>
182 });
183 </code></pre>
184      * The only required property is url. The optional properties nocache, text and scripts
185      * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
186      * @param {String/Object} params (optional) The parameters to pass as either a url encoded string "param1=1&amp;param2=2" or an object {param1: 1, param2: 2}
187      * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
188      * @param {Boolean} discardUrl (optional) By default when you execute an update the defaultUrl is changed to the last used url. If true, it will not store the url.
189      */
190     update : function(url, params, callback, discardUrl){
191         if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
192             var method = this.method,
193                 cfg;
194             if(typeof url == "object"){ // must be config object
195                 cfg = url;
196                 url = cfg.url;
197                 params = params || cfg.params;
198                 callback = callback || cfg.callback;
199                 discardUrl = discardUrl || cfg.discardUrl;
200                 if(callback && cfg.scope){
201                     callback = callback.createDelegate(cfg.scope);
202                 }
203                 if(typeof cfg.method != "undefined"){method = cfg.method;};
204                 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
205                 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
206                 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
207                 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
208             }
209             this.showLoading();
210             if(!discardUrl){
211                 this.defaultUrl = url;
212             }
213             if(typeof url == "function"){
214                 url = url.call(this);
215             }
216
217             method = method || (params ? "POST" : "GET");
218             if(method == "GET"){
219                 url = this.prepareUrl(url);
220             }
221
222             var o = Roo.apply(cfg ||{}, {
223                 url : url,
224                 params: params,
225                 success: this.successDelegate,
226                 failure: this.failureDelegate,
227                 callback: undefined,
228                 timeout: (this.timeout*1000),
229                 argument: {"url": url, "form": null, "callback": callback, "params": params}
230             });
231             Roo.log("updated manager called with timeout of " + o.timeout);
232             this.transaction = Roo.Ajax.request(o);
233         }
234     },
235
236     /**
237      * Performs an async form post, updating this element with the response. If the form has the attribute enctype="multipart/form-data", it assumes it's a file upload.
238      * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
239      * @param {String/HTMLElement} form The form Id or form element
240      * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
241      * @param {Boolean} reset (optional) Whether to try to reset the form after the update
242      * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
243      */
244     formUpdate : function(form, url, reset, callback){
245         if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
246             if(typeof url == "function"){
247                 url = url.call(this);
248             }
249             form = Roo.getDom(form);
250             this.transaction = Roo.Ajax.request({
251                 form: form,
252                 url:url,
253                 success: this.successDelegate,
254                 failure: this.failureDelegate,
255                 timeout: (this.timeout*1000),
256                 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
257             });
258             this.showLoading.defer(1, this);
259         }
260     },
261
262     /**
263      * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
264      * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
265      */
266     refresh : function(callback){
267         if(this.defaultUrl == null){
268             return;
269         }
270         this.update(this.defaultUrl, null, callback, true);
271     },
272
273     /**
274      * Set this element to auto refresh.
275      * @param {Number} interval How often to update (in seconds).
276      * @param {String/Function} url (optional) The url for this request or a function to call to get the url (Defaults to the last used url)
277      * @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}
278      * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
279      * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
280      */
281     startAutoRefresh : function(interval, url, params, callback, refreshNow){
282         if(refreshNow){
283             this.update(url || this.defaultUrl, params, callback, true);
284         }
285         if(this.autoRefreshProcId){
286             clearInterval(this.autoRefreshProcId);
287         }
288         this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
289     },
290
291     /**
292      * Stop auto refresh on this element.
293      */
294      stopAutoRefresh : function(){
295         if(this.autoRefreshProcId){
296             clearInterval(this.autoRefreshProcId);
297             delete this.autoRefreshProcId;
298         }
299     },
300
301     isAutoRefreshing : function(){
302        return this.autoRefreshProcId ? true : false;
303     },
304     /**
305      * Called to update the element to "Loading" state. Override to perform custom action.
306      */
307     showLoading : function(){
308         if(this.showLoadIndicator){
309             this.el.update(this.indicatorText);
310         }
311     },
312
313     /**
314      * Adds unique parameter to query string if disableCaching = true
315      * @private
316      */
317     prepareUrl : function(url){
318         if(this.disableCaching){
319             var append = "_dc=" + (new Date().getTime());
320             if(url.indexOf("?") !== -1){
321                 url += "&" + append;
322             }else{
323                 url += "?" + append;
324             }
325         }
326         return url;
327     },
328
329     /**
330      * @private
331      */
332     processSuccess : function(response){
333         this.transaction = null;
334         if(response.argument.form && response.argument.reset){
335             try{ // put in try/catch since some older FF releases had problems with this
336                 response.argument.form.reset();
337             }catch(e){}
338         }
339         if(this.loadScripts){
340             this.renderer.render(this.el, response, this,
341                 this.updateComplete.createDelegate(this, [response]));
342         }else{
343             this.renderer.render(this.el, response, this);
344             this.updateComplete(response);
345         }
346     },
347
348     updateComplete : function(response){
349         this.fireEvent("update", this.el, response);
350         if(typeof response.argument.callback == "function"){
351             response.argument.callback(this.el, true, response);
352         }
353     },
354
355     /**
356      * @private
357      */
358     processFailure : function(response){
359         this.transaction = null;
360         this.fireEvent("failure", this.el, response);
361         if(typeof response.argument.callback == "function"){
362             response.argument.callback(this.el, false, response);
363         }
364     },
365
366     /**
367      * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
368      * @param {Object} renderer The object implementing the render() method
369      */
370     setRenderer : function(renderer){
371         this.renderer = renderer;
372     },
373
374     getRenderer : function(){
375        return this.renderer;
376     },
377
378     /**
379      * Set the defaultUrl used for updates
380      * @param {String/Function} defaultUrl The url or a function to call to get the url
381      */
382     setDefaultUrl : function(defaultUrl){
383         this.defaultUrl = defaultUrl;
384     },
385
386     /**
387      * Aborts the executing transaction
388      */
389     abort : function(){
390         if(this.transaction){
391             Roo.Ajax.abort(this.transaction);
392         }
393     },
394
395     /**
396      * Returns true if an update is in progress
397      * @return {Boolean}
398      */
399     isUpdating : function(){
400         if(this.transaction){
401             return Roo.Ajax.isLoading(this.transaction);
402         }
403         return false;
404     }
405 });
406
407 /**
408  * @class Roo.UpdateManager.defaults
409  * @static (not really - but it helps the doc tool)
410  * The defaults collection enables customizing the default properties of UpdateManager
411  */
412    Roo.UpdateManager.defaults = {
413        /**
414          * Timeout for requests or form posts in seconds (Defaults 30 seconds).
415          * @type Number
416          */
417          timeout : 30,
418
419          /**
420          * True to process scripts by default (Defaults to false).
421          * @type Boolean
422          */
423         loadScripts : false,
424
425         /**
426         * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
427         * @type String
428         */
429         sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
430         /**
431          * Whether to append unique parameter on get request to disable caching (Defaults to false).
432          * @type Boolean
433          */
434         disableCaching : false,
435         /**
436          * Whether to show indicatorText when loading (Defaults to true).
437          * @type Boolean
438          */
439         showLoadIndicator : true,
440         /**
441          * Text for loading indicator (Defaults to '&lt;div class="loading-indicator"&gt;Loading...&lt;/div&gt;').
442          * @type String
443          */
444         indicatorText : '<div class="loading-indicator">Loading...</div>'
445    };
446
447 /**
448  * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
449  *Usage:
450  * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
451  * @param {String/HTMLElement/Roo.Element} el The element to update
452  * @param {String} url The url
453  * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
454  * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
455  * @static
456  * @deprecated
457  * @member Roo.UpdateManager
458  */
459 Roo.UpdateManager.updateElement = function(el, url, params, options){
460     var um = Roo.get(el, true).getUpdateManager();
461     Roo.apply(um, options);
462     um.update(url, params, options ? options.callback : null);
463 };
464 // alias for backwards compat
465 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
466 /**
467  * @class Roo.UpdateManager.BasicRenderer
468  * Default Content renderer. Updates the elements innerHTML with the responseText.
469  */
470 Roo.UpdateManager.BasicRenderer = function(){};
471
472 Roo.UpdateManager.BasicRenderer.prototype = {
473     /**
474      * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
475      * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
476      * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
477      * @param {Roo.Element} el The element being rendered
478      * @param {Object} response The YUI Connect response object
479      * @param {UpdateManager} updateManager The calling update manager
480      * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
481      */
482      render : function(el, response, updateManager, callback){
483         el.update(response.responseText, updateManager.loadScripts, callback);
484     }
485 };