/** * @class Ext.LoadMask * <p>A modal, floating Component which may be shown above a specified {@link Ext.core.Element Element}, or a specified * {@link Ext.Component Component} while loading data. When shown, the configured owning Element or Component will * be covered with a modality mask, and the LoadMask's {@link #msg} will be displayed centered, accompanied by a spinner image.</p> * <p>If the {@link #store} config option is specified, the masking will be automatically shown and then hidden synchronized with * the Store's loading process.</p> * <p>Because this is a floating Component, its z-index will be managed by the global {@link Ext.WindowManager ZIndexManager} * object, and upon show, it will place itsef at the top of the hierarchy.</p> * <p>Example usage:</p> * <pre><code> // Basic mask: var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."}); myMask.show(); </code></pre> */ Ext.define('Ext.LoadMask', { extend: 'Ext.Component', alias: 'widget.loadmask', /* Begin Definitions */ mixins: { floating: 'Ext.util.Floating' }, uses: ['Ext.data.StoreManager'], /* End Definitions */ /** * @cfg {Ext.data.Store} store * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and * hidden on either load success, or load fail. */ /** * @cfg {String} msg * The text to display in a centered loading message box. */ msg : 'Loading...', /** * @cfg {String} [msgCls="x-mask-loading"] * The CSS class to apply to the loading message element. */ msgCls : Ext.baseCSSPrefix + 'mask-loading', /** * @cfg {Boolean} useMsg * Whether or not to use a loading message class or simply mask the bound element. */ useMsg: true, /** * Read-only. True if the mask is currently disabled so that it will not be displayed * @type Boolean */ disabled: false, baseCls: Ext.baseCSSPrefix + 'mask-msg', renderTpl: '<div style="position:relative" class="{msgCls}"></div>', // Private. The whole point is that there's a mask. modal: true, // Private. Obviously, it's floating. floating: { shadow: 'frame' }, // Private. Masks are not focusable focusOnToFront: false, /** * Creates new LoadMask. * @param {String/HTMLElement/Ext.Element} el The element, element ID, or DOM node you wish to mask. * <p>Also, may be a {@link Ext.Component Component} who's element you wish to mask. If a Component is specified, then * the mask will be automatically sized upon Component resize, the message box will be kept centered, * and the mask only be visible when the Component is.</p> * @param {Object} [config] The config object */ constructor : function(el, config) { var me = this; // If a Component passed, bind to it. if (el.isComponent) { me.ownerCt = el; me.bindComponent(el); } // Create a dumy Component encapsulating the specified Element else { me.ownerCt = new Ext.Component({ el: Ext.get(el), rendered: true, componentLayoutCounter: 1 }); me.container = el; } me.callParent([config]); if (me.store) { me.bindStore(me.store, true); } me.renderData = { msgCls: me.msgCls }; me.renderSelectors = { msgEl: 'div' }; }, bindComponent: function(comp) { this.mon(comp, { resize: this.onComponentResize, scope: this }); }, afterRender: function() { this.callParent(arguments); this.container = this.floatParent.getContentTarget(); }, /** * @private * Called when this LoadMask's Component is resized. The toFront method rebases and resizes the modal mask. */ onComponentResize: function() { var me = this; if (me.rendered && me.isVisible()) { me.toFront(); me.center(); } }, /** * Changes the data store bound to this LoadMask. * @param {Ext.data.Store} store The store to bind to this LoadMask */ bindStore : function(store, initial) { var me = this; if (!initial && me.store) { me.mun(me.store, { scope: me, beforeload: me.onBeforeLoad, load: me.onLoad, exception: me.onLoad }); if (!store) { me.store = null; } } if (store) { store = Ext.data.StoreManager.lookup(store); me.mon(store, { scope: me, beforeload: me.onBeforeLoad, load: me.onLoad, exception: me.onLoad }); } me.store = store; if (store && store.isLoading()) { me.onBeforeLoad(); } }, onDisable : function() { this.callParent(arguments); if (this.loading) { this.onLoad(); } }, // private onBeforeLoad : function() { var me = this, owner = me.ownerCt || me.floatParent, origin; if (!this.disabled) { // If the owning Component has not been layed out, defer so that the ZIndexManager // gets to read its layed out size when sizing the modal mask if (owner.componentLayoutCounter) { Ext.Component.prototype.show.call(me); } else { // The code below is a 'run-once' interceptor. origin = owner.afterComponentLayout; owner.afterComponentLayout = function() { owner.afterComponentLayout = origin; origin.apply(owner, arguments); if(me.loading) { Ext.Component.prototype.show.call(me); } }; } } }, onHide: function(){ var me = this; me.callParent(arguments); me.showOnParentShow = true; }, onShow: function() { var me = this, msgEl = me.msgEl; me.callParent(arguments); me.loading = true; if (me.useMsg) { msgEl.show().update(me.msg); } else { msgEl.parent().hide(); } }, afterShow: function() { this.callParent(arguments); this.center(); }, // private onLoad : function() { this.loading = false; Ext.Component.prototype.hide.call(this); } });