/** * @class Ext.ElementLoader * A class used to load remote content to an Element. Sample usage: * <pre><code> Ext.get('el').load({ url: 'myPage.php', scripts: true, params: { id: 1 } }); * </code></pre> * <p> * In general this class will not be instanced directly, rather the {@link Ext.core.Element#load} method * will be used. * </p> */ Ext.define('Ext.ElementLoader', { /* Begin Definitions */ mixins: { observable: 'Ext.util.Observable' }, uses: [ 'Ext.data.Connection', 'Ext.Ajax' ], statics: { Renderer: { Html: function(loader, response, active){ loader.getTarget().update(response.responseText, active.scripts === true); return true; } } }, /* End Definitions */ /** * @cfg {String} url The url to retrieve the content from. Defaults to <tt>null</tt>. */ url: null, /** * @cfg {Object} params Any params to be attached to the Ajax request. These parameters will * be overridden by any params in the load options. Defaults to <tt>null</tt>. */ params: null, /** * @cfg {Object} baseParams Params that will be attached to every request. These parameters * will not be overridden by any params in the load options. Defaults to <tt>null</tt>. */ baseParams: null, /** * @cfg {Boolean/Object} autoLoad True to have the loader make a request as soon as it is created. Defaults to <tt>false</tt>. * This argument can also be a set of options that will be passed to {@link #load} is called. */ autoLoad: false, /** * @cfg {Mixed} target The target element for the loader. It can be the DOM element, the id or an Ext.Element. */ target: null, /** * @cfg {Mixed} loadMask True or a string to show when the element is loading. */ loadMask: false, /** * @cfg {Object} ajaxOptions Any additional options to be passed to the request, for example timeout or headers. Defaults to <tt>null</tt>. */ ajaxOptions: null, /** * @cfg {Boolean} scripts True to parse any inline script tags in the response. */ scripts: false, /** * @cfg {Function} success A function to be called when a load request is successful. */ /** * @cfg {Function} failure A function to be called when a load request fails. */ /** * @cfg {Object} scope The scope to execute the {@link #success} and {@link #failure} functions in. */ /** * @cfg {Function} renderer A custom function to render the content to the element. The passed parameters * are * <ul> * <li>The loader</li> * <li>The response</li> * <li>The active request</li> * </ul> */ isLoader: true, constructor: function(config) { var me = this, autoLoad; config = config || {}; Ext.apply(me, config); me.setTarget(me.target); me.addEvents( /** * @event beforeload * Fires before a load request is made to the server. * Returning false from an event listener can prevent the load * from occurring. * @param {Ext.ElementLoader} this * @param {Object} options The options passed to the request */ 'beforeload', /** * @event exception * Fires after an unsuccessful load. * @param {Ext.ElementLoader} this * @param {Object} response The response from the server * @param {Object} options The options passed to the request */ 'exception', /** * @event exception * Fires after a successful load. * @param {Ext.ElementLoader} this * @param {Object} response The response from the server * @param {Object} options The options passed to the request */ 'load' ); // don't pass config because we have already applied it. me.mixins.observable.constructor.call(me); if (me.autoLoad) { autoLoad = me.autoLoad; if (autoLoad === true) { autoLoad = {}; } me.load(autoLoad); } }, /** * Set an {Ext.Element} as the target of this loader. Note that if the target is changed, * any active requests will be aborted. * @param {Mixed} target The element */ setTarget: function(target){ var me = this; target = Ext.get(target); if (me.target && me.target != target) { me.abort(); } me.target = target; }, /** * Get the target of this loader. * @return {Ext.Component} target The target, null if none exists. */ getTarget: function(){ return this.target || null; }, /** * Aborts the active load request */ abort: function(){ var active = this.active; if (active !== undefined) { Ext.Ajax.abort(active.request); if (active.mask) { this.removeMask(); } delete this.active; } }, /** * Remove the mask on the target * @private */ removeMask: function(){ this.target.unmask(); }, /** * Add the mask on the target * @private * @param {Mixed} mask The mask configuration */ addMask: function(mask){ this.target.mask(mask === true ? null : mask); }, /** * Load new data from the server. * @param {Object} options The options for the request. They can be any configuration option that can be specified for * the class, with the exception of the target option. Note that any options passed to the method will override any * class defaults. */ load: function(options) { //<debug> if (!this.target) { Ext.Error.raise('A valid target is required when loading content'); } //</debug> options = Ext.apply({}, options); var me = this, target = me.target, mask = Ext.isDefined(options.loadMask) ? options.loadMask : me.loadMask, params = Ext.apply({}, options.params), ajaxOptions = Ext.apply({}, options.ajaxOptions), callback = options.callback || me.callback, scope = options.scope || me.scope || me, request; Ext.applyIf(ajaxOptions, me.ajaxOptions); Ext.applyIf(options, ajaxOptions); Ext.applyIf(params, me.params); Ext.apply(params, me.baseParams); Ext.applyIf(options, { url: me.url }); //<debug> if (!options.url) { Ext.Error.raise('You must specify the URL from which content should be loaded'); } //</debug> Ext.apply(options, { scope: me, params: params, callback: me.onComplete }); if (me.fireEvent('beforeload', me, options) === false) { return; } if (mask) { me.addMask(mask); } request = Ext.Ajax.request(options); me.active = { request: request, options: options, mask: mask, scope: scope, callback: callback, success: options.success || me.success, failure: options.failure || me.failure, renderer: options.renderer || me.renderer, scripts: Ext.isDefined(options.scripts) ? options.scripts : me.scripts }; me.setOptions(me.active, options); }, /** * Set any additional options on the active request * @private * @param {Object} active The active request * @param {Object} options The initial options */ setOptions: Ext.emptyFn, /** * Parse the response after the request completes * @private * @param {Object} options Ajax options * @param {Boolean} success Success status of the request * @param {Object} response The response object */ onComplete: function(options, success, response) { var me = this, active = me.active, scope = active.scope, renderer = me.getRenderer(active.renderer); if (success) { success = renderer.call(me, me, response, active); } if (success) { Ext.callback(active.success, scope, [me, response, options]); me.fireEvent('load', me, response, options); } else { Ext.callback(active.failure, scope, [me, response, options]); me.fireEvent('exception', me, response, options); } Ext.callback(active.callback, scope, [me, success, response, options]); if (active.mask) { me.removeMask(); } delete me.active; }, /** * Gets the renderer to use * @private * @param {String/Function} renderer The renderer to use * @return {Function} A rendering function to use. */ getRenderer: function(renderer){ if (Ext.isFunction(renderer)) { return renderer; } return this.statics().Renderer.Html; }, /** * Automatically refreshes the content over a specified period. * @param {Number} interval The interval to refresh in ms. * @param {Object} options (optional) The options to pass to the load method. See {@link #load} */ startAutoRefresh: function(interval, options){ var me = this; me.stopAutoRefresh(); me.autoRefresh = setInterval(function(){ me.load(options); }, interval); }, /** * Clears any auto refresh. See {@link #startAutoRefresh}. */ stopAutoRefresh: function(){ clearInterval(this.autoRefresh); delete this.autoRefresh; }, /** * Checks whether the loader is automatically refreshing. See {@link #startAutoRefresh}. * @return {Boolean} True if the loader is automatically refreshing */ isAutoRefreshing: function(){ return Ext.isDefined(this.autoRefresh); }, /** * Destroys the loader. Any active requests will be aborted. */ destroy: function(){ var me = this; me.stopAutoRefresh(); delete me.target; me.abort(); me.clearListeners(); } });