Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / LoadMask.js
1 /**
2  * @class Ext.LoadMask
3  * A simple utility class for generically masking elements while loading data.  If the {@link #store}
4  * config option is specified, the masking will be automatically synchronized with the store's loading
5  * process and the mask element will be cached for reuse.
6  * <p>Example usage:</p>
7  * <pre><code>
8 // Basic mask:
9 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
10 myMask.show();
11 </code></pre>
12
13  * @constructor
14  * Create a new LoadMask
15  * @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.
16  * @param {Object} config The config object
17  */
18
19 Ext.define('Ext.LoadMask', {
20
21     /* Begin Definitions */
22
23     mixins: {
24         observable: 'Ext.util.Observable'
25     },
26
27     requires: ['Ext.data.StoreManager'],
28
29     /* End Definitions */
30
31     /**
32      * @cfg {Ext.data.Store} store
33      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
34      * hidden on either load success, or load fail.
35      */
36
37     /**
38      * @cfg {String} msg
39      * The text to display in a centered loading message box (defaults to 'Loading...')
40      */
41     msg : 'Loading...',
42     /**
43      * @cfg {String} msgCls
44      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
45      */
46     msgCls : Ext.baseCSSPrefix + 'mask-loading',
47     
48     /**
49      * @cfg {Boolean} useMsg
50      * Whether or not to use a loading message class or simply mask the bound element.
51      */
52     useMsg: true,
53
54     /**
55      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
56      * @type Boolean
57      */
58     disabled: false,
59
60     constructor : function(el, config) {
61         var me = this;
62
63         if (el.isComponent) {
64             me.bindComponent(el);
65         } else {
66             me.el = Ext.get(el);
67         }
68         Ext.apply(me, config);
69
70         me.addEvents('beforeshow', 'show', 'hide');
71         if (me.store) {
72             me.bindStore(me.store, true);
73         }
74         me.mixins.observable.constructor.call(me, config);
75     },
76
77     bindComponent: function(comp) {
78         var me = this,
79             listeners = {
80                 resize: me.onComponentResize,
81                 scope: me
82             };
83
84         if (comp.el) {
85             me.onComponentRender(comp);
86         } else {
87             listeners.render = {
88                 fn: me.onComponentRender,
89                 scope: me,
90                 single: true
91             };
92         }
93         me.mon(comp, listeners);
94     },
95
96     /**
97      * @private
98      * Called if we were configured with a Component, and that Component was not yet rendered. Collects the element to mask.
99      */
100     onComponentRender: function(comp) {
101         this.el = comp.getContentTarget();
102     },
103
104     /**
105      * @private
106      * Called when this LoadMask's Component is resized. The isMasked method also re-centers any displayed message.
107      */
108     onComponentResize: function(comp, w, h) {
109         this.el.isMasked();
110     },
111
112     /**
113      * Changes the data store bound to this LoadMask.
114      * @param {Store} store The store to bind to this LoadMask
115      */
116     bindStore : function(store, initial) {
117         var me = this;
118
119         if (!initial && me.store) {
120             me.mun(me.store, {
121                 scope: me,
122                 beforeload: me.onBeforeLoad,
123                 load: me.onLoad,
124                 exception: me.onLoad
125             });
126             if(!store) {
127                 me.store = null;
128             }
129         }
130         if (store) {
131             store = Ext.data.StoreManager.lookup(store);
132             me.mon(store, {
133                 scope: me,
134                 beforeload: me.onBeforeLoad,
135                 load: me.onLoad,
136                 exception: me.onLoad
137             });
138
139         }
140         me.store = store;
141         if (store && store.isLoading()) {
142             me.onBeforeLoad();
143         }
144     },
145
146     /**
147      * Disables the mask to prevent it from being displayed
148      */
149     disable : function() {
150         var me = this;
151
152        me.disabled = true;
153        if (me.loading) {
154            me.onLoad();
155        }
156     },
157
158     /**
159      * Enables the mask so that it can be displayed
160      */
161     enable : function() {
162         this.disabled = false;
163     },
164
165     /**
166      * Method to determine whether this LoadMask is currently disabled.
167      * @return {Boolean} the disabled state of this LoadMask.
168      */
169     isDisabled : function() {
170         return this.disabled;
171     },
172
173     // private
174     onLoad : function() {
175         var me = this;
176
177         me.loading = false;
178         me.el.unmask();
179         me.fireEvent('hide', me, me.el, me.store);
180     },
181
182     // private
183     onBeforeLoad : function() {
184         var me = this;
185
186         if (!me.disabled && !me.loading && me.fireEvent('beforeshow', me, me.el, me.store) !== false) {
187             if (me.useMsg) {
188                 me.el.mask(me.msg, me.msgCls, false);
189             } else {
190                 me.el.mask();
191             }
192             
193             me.fireEvent('show', me, me.el, me.store);
194             me.loading = true;
195         }
196     },
197
198     /**
199      * Show this LoadMask over the configured Element.
200      */
201     show: function() {
202         this.onBeforeLoad();
203     },
204
205     /**
206      * Hide this LoadMask.
207      */
208     hide: function() {
209         this.onLoad();
210     },
211
212     // private
213     destroy : function() {
214         this.hide();
215         this.clearListeners();
216     }
217 });