Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / ElementLoader.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * A class used to load remote content to an Element. Sample usage:
17  *
18  *     Ext.get('el').load({
19  *         url: 'myPage.php',
20  *         scripts: true,
21  *         params: {
22  *             id: 1
23  *         }
24  *     });
25  *
26  * In general this class will not be instanced directly, rather the {@link Ext.Element#load} method
27  * will be used.
28  */
29 Ext.define('Ext.ElementLoader', {
30
31     /* Begin Definitions */
32
33     mixins: {
34         observable: 'Ext.util.Observable'
35     },
36
37     uses: [
38         'Ext.data.Connection',
39         'Ext.Ajax'
40     ],
41
42     statics: {
43         Renderer: {
44             Html: function(loader, response, active){
45                 loader.getTarget().update(response.responseText, active.scripts === true);
46                 return true;
47             }
48         }
49     },
50
51     /* End Definitions */
52
53     /**
54      * @cfg {String} url
55      * The url to retrieve the content from.
56      */
57     url: null,
58
59     /**
60      * @cfg {Object} params
61      * Any params to be attached to the Ajax request. These parameters will
62      * be overridden by any params in the load options.
63      */
64     params: null,
65
66     /**
67      * @cfg {Object} baseParams Params that will be attached to every request. These parameters
68      * will not be overridden by any params in the load options.
69      */
70     baseParams: null,
71
72     /**
73      * @cfg {Boolean/Object} autoLoad
74      * True to have the loader make a request as soon as it is created.
75      * This argument can also be a set of options that will be passed to {@link #load} is called.
76      */
77     autoLoad: false,
78
79     /**
80      * @cfg {HTMLElement/Ext.Element/String} target
81      * The target element for the loader. It can be the DOM element, the id or an {@link Ext.Element}.
82      */
83     target: null,
84
85     /**
86      * @cfg {Boolean/String} loadMask
87      * True or a string to show when the element is loading.
88      */
89     loadMask: false,
90
91     /**
92      * @cfg {Object} ajaxOptions
93      * Any additional options to be passed to the request, for example timeout or headers.
94      */
95     ajaxOptions: null,
96
97     /**
98      * @cfg {Boolean} scripts
99      * True to parse any inline script tags in the response.
100      */
101     scripts: false,
102
103     /**
104      * @cfg {Function} success
105      * A function to be called when a load request is successful.
106      * Will be called with the following config parameters:
107      *
108      * - this - The ElementLoader instance.
109      * - response - The response object.
110      * - options - Ajax options.
111      */
112
113     /**
114      * @cfg {Function} failure A function to be called when a load request fails.
115      * Will be called with the following config parameters:
116      *
117      * - this - The ElementLoader instance.
118      * - response - The response object.
119      * - options - Ajax options.
120      */
121
122     /**
123      * @cfg {Function} callback A function to be called when a load request finishes.
124      * Will be called with the following config parameters:
125      *
126      * - this - The ElementLoader instance.
127      * - success - True if successful request.
128      * - response - The response object.
129      * - options - Ajax options.
130      */
131
132     /**
133      * @cfg {Object} scope
134      * The scope to execute the {@link #success} and {@link #failure} functions in.
135      */
136
137     /**
138      * @cfg {Function} renderer
139      * A custom function to render the content to the element. The passed parameters are:
140      *
141      * - The loader
142      * - The response
143      * - The active request
144      */
145
146     isLoader: true,
147
148     constructor: function(config) {
149         var me = this,
150             autoLoad;
151
152         config = config || {};
153         Ext.apply(me, config);
154         me.setTarget(me.target);
155         me.addEvents(
156             /**
157              * @event beforeload
158              * Fires before a load request is made to the server.
159              * Returning false from an event listener can prevent the load
160              * from occurring.
161              * @param {Ext.ElementLoader} this
162              * @param {Object} options The options passed to the request
163              */
164             'beforeload',
165
166             /**
167              * @event exception
168              * Fires after an unsuccessful load.
169              * @param {Ext.ElementLoader} this
170              * @param {Object} response The response from the server
171              * @param {Object} options The options passed to the request
172              */
173             'exception',
174
175             /**
176              * @event load
177              * Fires after a successful load.
178              * @param {Ext.ElementLoader} this
179              * @param {Object} response The response from the server
180              * @param {Object} options The options passed to the request
181              */
182             'load'
183         );
184
185         // don't pass config because we have already applied it.
186         me.mixins.observable.constructor.call(me);
187
188         if (me.autoLoad) {
189             autoLoad = me.autoLoad;
190             if (autoLoad === true) {
191                 autoLoad = {};
192             }
193             me.load(autoLoad);
194         }
195     },
196
197     /**
198      * Sets an {@link Ext.Element} as the target of this loader.
199      * Note that if the target is changed, any active requests will be aborted.
200      * @param {String/HTMLElement/Ext.Element} target The element or its ID.
201      */
202     setTarget: function(target){
203         var me = this;
204         target = Ext.get(target);
205         if (me.target && me.target != target) {
206             me.abort();
207         }
208         me.target = target;
209     },
210
211     /**
212      * Returns the target of this loader.
213      * @return {Ext.Component} The target or null if none exists.
214      */
215     getTarget: function(){
216         return this.target || null;
217     },
218
219     /**
220      * Aborts the active load request
221      */
222     abort: function(){
223         var active = this.active;
224         if (active !== undefined) {
225             Ext.Ajax.abort(active.request);
226             if (active.mask) {
227                 this.removeMask();
228             }
229             delete this.active;
230         }
231     },
232
233     /**
234      * Removes the mask on the target
235      * @private
236      */
237     removeMask: function(){
238         this.target.unmask();
239     },
240
241     /**
242      * Adds the mask on the target
243      * @private
244      * @param {Boolean/Object} mask The mask configuration
245      */
246     addMask: function(mask){
247         this.target.mask(mask === true ? null : mask);
248     },
249
250     /**
251      * Loads new data from the server.
252      * @param {Object} options The options for the request. They can be any configuration option that can be specified for
253      * the class, with the exception of the target option. Note that any options passed to the method will override any
254      * class defaults.
255      */
256     load: function(options) {
257         //<debug>
258         if (!this.target) {
259             Ext.Error.raise('A valid target is required when loading content');
260         }
261         //</debug>
262
263         options = Ext.apply({}, options);
264
265         var me = this,
266             target = me.target,
267             mask = Ext.isDefined(options.loadMask) ? options.loadMask : me.loadMask,
268             params = Ext.apply({}, options.params),
269             ajaxOptions = Ext.apply({}, options.ajaxOptions),
270             callback = options.callback || me.callback,
271             scope = options.scope || me.scope || me,
272             request;
273
274         Ext.applyIf(ajaxOptions, me.ajaxOptions);
275         Ext.applyIf(options, ajaxOptions);
276
277         Ext.applyIf(params, me.params);
278         Ext.apply(params, me.baseParams);
279
280         Ext.applyIf(options, {
281             url: me.url
282         });
283
284         //<debug>
285         if (!options.url) {
286             Ext.Error.raise('You must specify the URL from which content should be loaded');
287         }
288         //</debug>
289
290         Ext.apply(options, {
291             scope: me,
292             params: params,
293             callback: me.onComplete
294         });
295
296         if (me.fireEvent('beforeload', me, options) === false) {
297             return;
298         }
299
300         if (mask) {
301             me.addMask(mask);
302         }
303
304         request = Ext.Ajax.request(options);
305         me.active = {
306             request: request,
307             options: options,
308             mask: mask,
309             scope: scope,
310             callback: callback,
311             success: options.success || me.success,
312             failure: options.failure || me.failure,
313             renderer: options.renderer || me.renderer,
314             scripts: Ext.isDefined(options.scripts) ? options.scripts : me.scripts
315         };
316         me.setOptions(me.active, options);
317     },
318
319     /**
320      * Sets any additional options on the active request
321      * @private
322      * @param {Object} active The active request
323      * @param {Object} options The initial options
324      */
325     setOptions: Ext.emptyFn,
326
327     /**
328      * Parses the response after the request completes
329      * @private
330      * @param {Object} options Ajax options
331      * @param {Boolean} success Success status of the request
332      * @param {Object} response The response object
333      */
334     onComplete: function(options, success, response) {
335         var me = this,
336             active = me.active,
337             scope = active.scope,
338             renderer = me.getRenderer(active.renderer);
339
340
341         if (success) {
342             success = renderer.call(me, me, response, active);
343         }
344
345         if (success) {
346             Ext.callback(active.success, scope, [me, response, options]);
347             me.fireEvent('load', me, response, options);
348         } else {
349             Ext.callback(active.failure, scope, [me, response, options]);
350             me.fireEvent('exception', me, response, options);
351         }
352         Ext.callback(active.callback, scope, [me, success, response, options]);
353
354         if (active.mask) {
355             me.removeMask();
356         }
357
358         delete me.active;
359     },
360
361     /**
362      * Gets the renderer to use
363      * @private
364      * @param {String/Function} renderer The renderer to use
365      * @return {Function} A rendering function to use.
366      */
367     getRenderer: function(renderer){
368         if (Ext.isFunction(renderer)) {
369             return renderer;
370         }
371         return this.statics().Renderer.Html;
372     },
373
374     /**
375      * Automatically refreshes the content over a specified period.
376      * @param {Number} interval The interval to refresh in ms.
377      * @param {Object} options (optional) The options to pass to the load method. See {@link #load}
378      */
379     startAutoRefresh: function(interval, options){
380         var me = this;
381         me.stopAutoRefresh();
382         me.autoRefresh = setInterval(function(){
383             me.load(options);
384         }, interval);
385     },
386
387     /**
388      * Clears any auto refresh. See {@link #startAutoRefresh}.
389      */
390     stopAutoRefresh: function(){
391         clearInterval(this.autoRefresh);
392         delete this.autoRefresh;
393     },
394
395     /**
396      * Checks whether the loader is automatically refreshing. See {@link #startAutoRefresh}.
397      * @return {Boolean} True if the loader is automatically refreshing
398      */
399     isAutoRefreshing: function(){
400         return Ext.isDefined(this.autoRefresh);
401     },
402
403     /**
404      * Destroys the loader. Any active requests will be aborted.
405      */
406     destroy: function(){
407         var me = this;
408         me.stopAutoRefresh();
409         delete me.target;
410         me.abort();
411         me.clearListeners();
412     }
413 });
414