X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6746dc89c47ed01b165cc1152533605f97eb8e8d..f562e4c6e5fac7bcb445985b99acbea4d706e6f0:/src/LoadMask.js diff --git a/src/LoadMask.js b/src/LoadMask.js index da8dbcc4..cafae053 100644 --- a/src/LoadMask.js +++ b/src/LoadMask.js @@ -14,9 +14,13 @@ If you are unsure which license is appropriate for your use, please contact the */ /** * @class Ext.LoadMask - * A simple utility class for generically masking elements while loading data. If the {@link #store} - * config option is specified, the masking will be automatically synchronized with the store's loading - * process and the mask element will be cached for reuse. + *

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.

+ *

If the {@link #store} config option is specified, the masking will be automatically shown and then hidden synchronized with + * the Store's loading process.

+ *

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.

*

Example usage:

*

 // Basic mask:
@@ -28,13 +32,17 @@ myMask.show();
 
 Ext.define('Ext.LoadMask', {
 
+    extend: 'Ext.Component',
+
+    alias: 'widget.loadmask',
+
     /* Begin Definitions */
 
     mixins: {
-        observable: 'Ext.util.Observable'
+        floating: 'Ext.util.Floating'
     },
 
-    requires: ['Ext.data.StoreManager'],
+    uses: ['Ext.data.StoreManager'],
 
     /* End Definitions */
 
@@ -46,12 +54,12 @@ Ext.define('Ext.LoadMask', {
 
     /**
      * @cfg {String} msg
-     * The text to display in a centered loading message box (defaults to 'Loading...')
+     * The text to display in a centered loading message box.
      */
     msg : 'Loading...',
     /**
-     * @cfg {String} msgCls
-     * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
+     * @cfg {String} [msgCls="x-mask-loading"]
+     * The CSS class to apply to the loading message element.
      */
     msgCls : Ext.baseCSSPrefix + 'mask-loading',
     
@@ -62,72 +70,91 @@ Ext.define('Ext.LoadMask', {
     useMsg: true,
 
     /**
-     * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
+     * 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: '
', + + // 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 {Mixed} el The element, element ID, or DOM node you wish to mask. - * Also, may be a Component who's element you wish to mask. - * @param {Object} config (optional) The config object + * @param {String/HTMLElement/Ext.Element} el The element, element ID, or DOM node you wish to mask. + *

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.

+ * @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); - } else { - me.el = Ext.get(el); } - Ext.apply(me, config); + // 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]); - me.addEvents('beforeshow', 'show', 'hide'); if (me.store) { me.bindStore(me.store, true); } - me.mixins.observable.constructor.call(me, config); + me.renderData = { + msgCls: me.msgCls + }; + me.renderSelectors = { + msgEl: 'div' + }; }, bindComponent: function(comp) { - var me = this, - listeners = { - resize: me.onComponentResize, - scope: me - }; - - if (comp.el) { - me.onComponentRender(comp); - } else { - listeners.render = { - fn: me.onComponentRender, - scope: me, - single: true - }; - } - me.mon(comp, listeners); + this.mon(comp, { + resize: this.onComponentResize, + scope: this + }); }, - /** - * @private - * Called if we were configured with a Component, and that Component was not yet rendered. Collects the element to mask. - */ - onComponentRender: function(comp) { - this.el = comp.getContentTarget(); + afterRender: function() { + this.callParent(arguments); + this.container = this.floatParent.getContentTarget(); }, /** * @private - * Called when this LoadMask's Component is resized. The isMasked method also re-centers any displayed message. + * Called when this LoadMask's Component is resized. The toFront method rebases and resizes the modal mask. */ - onComponentResize: function(comp, w, h) { - this.el.isMasked(); + onComponentResize: function() { + var me = this; + if (me.rendered && me.isVisible()) { + me.toFront(); + me.center(); + } }, /** * Changes the data store bound to this LoadMask. - * @param {Store} store The store to bind to this LoadMask + * @param {Ext.data.Store} store The store to bind to this LoadMask */ bindStore : function(store, initial) { var me = this; @@ -139,7 +166,7 @@ Ext.define('Ext.LoadMask', { load: me.onLoad, exception: me.onLoad }); - if(!store) { + if (!store) { me.store = null; } } @@ -159,76 +186,64 @@ Ext.define('Ext.LoadMask', { } }, - /** - * Disables the mask to prevent it from being displayed - */ - disable : function() { - var me = this; - - me.disabled = true; - if (me.loading) { - me.onLoad(); - } - }, - - /** - * Enables the mask so that it can be displayed - */ - enable : function() { - this.disabled = false; - }, - - /** - * Method to determine whether this LoadMask is currently disabled. - * @return {Boolean} the disabled state of this LoadMask. - */ - isDisabled : function() { - return this.disabled; - }, - - // private - onLoad : function() { - var me = this; - - me.loading = false; - me.el.unmask(); - me.fireEvent('hide', me, me.el, me.store); + onDisable : function() { + this.callParent(arguments); + if (this.loading) { + this.onLoad(); + } }, // private onBeforeLoad : function() { - var me = this; - - if (!me.disabled && !me.loading && me.fireEvent('beforeshow', me, me.el, me.store) !== false) { - if (me.useMsg) { - me.el.mask(me.msg, me.msgCls, false); + 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 { - me.el.mask(); + // 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); + } + }; } - - me.fireEvent('show', me, me.el, me.store); - me.loading = true; } }, - /** - * Show this LoadMask over the configured Element. - */ - show: function() { - this.onBeforeLoad(); + onHide: function(){ + var me = this; + me.callParent(arguments); + me.showOnParentShow = true; }, - /** - * Hide this LoadMask. - */ - hide: function() { - this.onLoad(); + 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 - destroy : function() { - this.hide(); - this.clearListeners(); + onLoad : function() { + this.loading = false; + Ext.Component.prototype.hide.call(this); } }); -