Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / docs / source / ZIndexManager.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-ZIndexManager-method-constructor'><span id='Ext-ZIndexManager'>/**
19 </span></span> * @class Ext.ZIndexManager
20  * &lt;p&gt;A class that manages a group of {@link Ext.Component#floating} Components and provides z-order management,
21  * and Component activation behavior, including masking below the active (topmost) Component.&lt;/p&gt;
22  * &lt;p&gt;{@link Ext.Component#floating Floating} Components which are rendered directly into the document (Such as {@link Ext.window.Window Window}s which are
23  * {@link Ext.Component#show show}n are managed by a {@link Ext.WindowManager global instance}.&lt;/p&gt;
24  * &lt;p&gt;{@link Ext.Component#floating Floating} Components which are descendants of {@link Ext.Component#floating floating} &lt;i&gt;Containers&lt;/i&gt;
25  * (For example a {Ext.view.BoundList BoundList} within an {@link Ext.window.Window Window}, or a {@link Ext.menu.Menu Menu}),
26  * are managed by a ZIndexManager owned by that floating Container. So ComboBox dropdowns within Windows will have managed z-indices
27  * guaranteed to be correct, relative to the Window.&lt;/p&gt;
28  * @constructor
29  */
30 Ext.define('Ext.ZIndexManager', {
31
32     alternateClassName: 'Ext.WindowGroup',
33
34     statics: {
35         zBase : 9000
36     },
37
38     constructor: function(container) {
39         var me = this;
40
41         me.list = {};
42         me.zIndexStack = [];
43         me.front = null;
44
45         if (container) {
46
47             // This is the ZIndexManager for an Ext.container.Container, base its zseed on the zIndex of the Container's element
48             if (container.isContainer) {
49                 container.on('resize', me._onContainerResize, me);
50                 me.zseed = Ext.Number.from(container.getEl().getStyle('zIndex'), me.getNextZSeed());
51                 // The containing element we will be dealing with (eg masking) is the content target
52                 me.targetEl = container.getTargetEl();
53                 me.container = container;
54             }
55             // This is the ZIndexManager for a DOM element
56             else {
57                 Ext.EventManager.onWindowResize(me._onContainerResize, me);
58                 me.zseed = me.getNextZSeed();
59                 me.targetEl = Ext.get(container);
60             }
61         }
62         // No container passed means we are the global WindowManager. Our target is the doc body.
63         // DOM must be ready to collect that ref.
64         else {
65             Ext.EventManager.onWindowResize(me._onContainerResize, me);
66             me.zseed = me.getNextZSeed();
67             Ext.onDocumentReady(function() {
68                 me.targetEl = Ext.getBody();
69             });
70         }
71     },
72
73     getNextZSeed: function() {
74         return (Ext.ZIndexManager.zBase += 10000);
75     },
76
77     setBase: function(baseZIndex) {
78         this.zseed = baseZIndex;
79         return this.assignZIndices();
80     },
81
82     // private
83     assignZIndices: function() {
84         var a = this.zIndexStack,
85             len = a.length,
86             i = 0,
87             zIndex = this.zseed,
88             comp;
89
90         for (; i &lt; len; i++) {
91             comp = a[i];
92             if (comp &amp;&amp; !comp.hidden) {
93
94                 // Setting the zIndex of a Component returns the topmost zIndex consumed by
95                 // that Component.
96                 // If it's just a plain floating Component such as a BoundList, then the
97                 // return value is the passed value plus 10, ready for the next item.
98                 // If a floating *Container* has its zIndex set, it re-orders its managed
99                 // floating children, starting from that new base, and returns a value 10000 above
100                 // the highest zIndex which it allocates.
101                 zIndex = comp.setZIndex(zIndex);
102             }
103         }
104         this._activateLast();
105         return zIndex;
106     },
107
108     // private
109     _setActiveChild: function(comp) {
110         if (comp != this.front) {
111
112             if (this.front) {
113                 this.front.setActive(false, comp);
114             }
115             this.front = comp;
116             if (comp) {
117                 comp.setActive(true);
118                 if (comp.modal) {
119                     this._showModalMask(comp.el.getStyle('zIndex') - 4);
120                 }
121             }
122         }
123     },
124
125     // private
126     _activateLast: function(justHidden) {
127         var comp,
128             lastActivated = false,
129             i;
130
131         // Go down through the z-index stack.
132         // Activate the next visible one down.
133         // Keep going down to find the next visible modal one to shift the modal mask down under
134         for (i = this.zIndexStack.length-1; i &gt;= 0; --i) {
135             comp = this.zIndexStack[i];
136             if (!comp.hidden) {
137                 if (!lastActivated) {
138                     this._setActiveChild(comp);
139                     lastActivated = true;
140                 }
141
142                 // Move any modal mask down to just under the next modal floater down the stack
143                 if (comp.modal) {
144                     this._showModalMask(comp.el.getStyle('zIndex') - 4);
145                     return;
146                 }
147             }
148         }
149
150         // none to activate, so there must be no modal mask.
151         // And clear the currently active property
152         this._hideModalMask();
153         if (!lastActivated) {
154             this._setActiveChild(null);
155         }
156     },
157
158     _showModalMask: function(zIndex) {
159         if (!this.mask) {
160             this.mask = this.targetEl.createChild({
161                 cls: Ext.baseCSSPrefix + 'mask'
162             });
163             this.mask.setVisibilityMode(Ext.core.Element.DISPLAY);
164             this.mask.on('click', this._onMaskClick, this);
165         }
166         Ext.getBody().addCls(Ext.baseCSSPrefix + 'body-masked');
167         this.mask.setSize(this.targetEl.getViewSize(true));
168         this.mask.setStyle('zIndex', zIndex);
169         this.mask.show();
170     },
171
172     _hideModalMask: function() {
173         if (this.mask) {
174             Ext.getBody().removeCls(Ext.baseCSSPrefix + 'body-masked');
175             this.mask.hide();
176         }
177     },
178
179     _onMaskClick: function() {
180         if (this.front) {
181             this.front.focus();
182         }
183     },
184
185     _onContainerResize: function() {
186         if (this.mask &amp;&amp; this.mask.isVisible()) {
187             this.mask.setSize(this.targetEl.getViewSize(true));
188         }
189     },
190
191 <span id='Ext-ZIndexManager-method-register'>    /**
192 </span>     * &lt;p&gt;Registers a floating {@link Ext.Component} with this ZIndexManager. This should not
193      * need to be called under normal circumstances. Floating Components (such as Windows, BoundLists and Menus) are automatically registered
194      * with a {@link Ext.Component#zIndexManager zIndexManager} at render time.&lt;/p&gt;
195      * &lt;p&gt;Where this may be useful is moving Windows between two ZIndexManagers. For example,
196      * to bring the Ext.MessageBox dialog under the same manager as the Desktop's
197      * ZIndexManager in the desktop sample app:&lt;/p&gt;&lt;code&gt;&lt;pre&gt;
198 MyDesktop.getDesktop().getManager().register(Ext.MessageBox);
199 &lt;/pre&gt;&lt;/code&gt;
200      * @param {Component} comp The Component to register.
201      */
202     register : function(comp) {
203         if (comp.zIndexManager) {
204             comp.zIndexManager.unregister(comp);
205         }
206         comp.zIndexManager = this;
207
208         this.list[comp.id] = comp;
209         this.zIndexStack.push(comp);
210         comp.on('hide', this._activateLast, this);
211     },
212
213 <span id='Ext-ZIndexManager-method-unregister'>    /**
214 </span>     * &lt;p&gt;Unregisters a {@link Ext.Component} from this ZIndexManager. This should not
215      * need to be called. Components are automatically unregistered upon destruction.
216      * See {@link #register}.&lt;/p&gt;
217      * @param {Component} comp The Component to unregister.
218      */
219     unregister : function(comp) {
220         delete comp.zIndexManager;
221         if (this.list &amp;&amp; this.list[comp.id]) {
222             delete this.list[comp.id];
223             comp.un('hide', this._activateLast);
224             Ext.Array.remove(this.zIndexStack, comp);
225
226             // Destruction requires that the topmost visible floater be activated. Same as hiding.
227             this._activateLast(comp);
228         }
229     },
230
231 <span id='Ext-ZIndexManager-method-get'>    /**
232 </span>     * Gets a registered Component by id.
233      * @param {String/Object} id The id of the Component or a {@link Ext.Component} instance
234      * @return {Ext.Component}
235      */
236     get : function(id) {
237         return typeof id == &quot;object&quot; ? id : this.list[id];
238     },
239
240 <span id='Ext-ZIndexManager-method-bringToFront'>   /**
241 </span>     * Brings the specified Component to the front of any other active Components in this ZIndexManager.
242      * @param {String/Object} comp The id of the Component or a {@link Ext.Component} instance
243      * @return {Boolean} True if the dialog was brought to the front, else false
244      * if it was already in front
245      */
246     bringToFront : function(comp) {
247         comp = this.get(comp);
248         if (comp != this.front) {
249             Ext.Array.remove(this.zIndexStack, comp);
250             this.zIndexStack.push(comp);
251             this.assignZIndices();
252             return true;
253         }
254         if (comp.modal) {
255             Ext.getBody().addCls(Ext.baseCSSPrefix + 'body-masked');
256             this.mask.setSize(Ext.core.Element.getViewWidth(true), Ext.core.Element.getViewHeight(true));
257             this.mask.show();
258         }
259         return false;
260     },
261
262 <span id='Ext-ZIndexManager-method-sendToBack'>    /**
263 </span>     * Sends the specified Component to the back of other active Components in this ZIndexManager.
264      * @param {String/Object} comp The id of the Component or a {@link Ext.Component} instance
265      * @return {Ext.Component} The Component
266      */
267     sendToBack : function(comp) {
268         comp = this.get(comp);
269         Ext.Array.remove(this.zIndexStack, comp);
270         this.zIndexStack.unshift(comp);
271         this.assignZIndices();
272         return comp;
273     },
274
275 <span id='Ext-ZIndexManager-method-hideAll'>    /**
276 </span>     * Hides all Components managed by this ZIndexManager.
277      */
278     hideAll : function() {
279         for (var id in this.list) {
280             if (this.list[id].isComponent &amp;&amp; this.list[id].isVisible()) {
281                 this.list[id].hide();
282             }
283         }
284     },
285
286 <span id='Ext-ZIndexManager-method-hide'>    /**
287 </span>     * @private
288      * Temporarily hides all currently visible managed Components. This is for when
289      * dragging a Window which may manage a set of floating descendants in its ZIndexManager;
290      * they should all be hidden just for the duration of the drag.
291      */
292     hide: function() {
293         var i = 0,
294             ln = this.zIndexStack.length,
295             comp;
296
297         this.tempHidden = [];
298         for (; i &lt; ln; i++) {
299             comp = this.zIndexStack[i];
300             if (comp.isVisible()) {
301                 this.tempHidden.push(comp);
302                 comp.hide();
303             }
304         }
305     },
306
307 <span id='Ext-ZIndexManager-method-show'>    /**
308 </span>     * @private
309      * Restores temporarily hidden managed Components to visibility.
310      */
311     show: function() {
312         var i = 0,
313             ln = this.tempHidden.length,
314             comp,
315             x,
316             y;
317
318         for (; i &lt; ln; i++) {
319             comp = this.tempHidden[i];
320             x = comp.x;
321             y = comp.y;
322             comp.show();
323             comp.setPosition(x, y);
324         }
325         delete this.tempHidden;
326     },
327
328 <span id='Ext-ZIndexManager-method-getActive'>    /**
329 </span>     * Gets the currently-active Component in this ZIndexManager.
330      * @return {Ext.Component} The active Component
331      */
332     getActive : function() {
333         return this.front;
334     },
335
336 <span id='Ext-ZIndexManager-method-getBy'>    /**
337 </span>     * Returns zero or more Components in this ZIndexManager using the custom search function passed to this method.
338      * The function should accept a single {@link Ext.Component} reference as its only argument and should
339      * return true if the Component matches the search criteria, otherwise it should return false.
340      * @param {Function} fn The search function
341      * @param {Object} scope (optional) The scope (&lt;code&gt;this&lt;/code&gt; reference) in which the function is executed. Defaults to the Component being tested.
342      * that gets passed to the function if not specified)
343      * @return {Array} An array of zero or more matching windows
344      */
345     getBy : function(fn, scope) {
346         var r = [],
347             i = 0,
348             len = this.zIndexStack.length,
349             comp;
350
351         for (; i &lt; len; i++) {
352             comp = this.zIndexStack[i];
353             if (fn.call(scope||comp, comp) !== false) {
354                 r.push(comp);
355             }
356         }
357         return r;
358     },
359
360 <span id='Ext-ZIndexManager-method-each'>    /**
361 </span>     * Executes the specified function once for every Component in this ZIndexManager, passing each
362      * Component as the only parameter. Returning false from the function will stop the iteration.
363      * @param {Function} fn The function to execute for each item
364      * @param {Object} scope (optional) The scope (&lt;code&gt;this&lt;/code&gt; reference) in which the function is executed. Defaults to the current Component in the iteration.
365      */
366     each : function(fn, scope) {
367         var comp;
368         for (var id in this.list) {
369             comp = this.list[id];
370             if (comp.isComponent &amp;&amp; fn.call(scope || comp, comp) === false) {
371                 return;
372             }
373         }
374     },
375
376 <span id='Ext-ZIndexManager-method-eachBottomUp'>    /**
377 </span>     * Executes the specified function once for every Component in this ZIndexManager, passing each
378      * Component as the only parameter. Returning false from the function will stop the iteration.
379      * The components are passed to the function starting at the bottom and proceeding to the top.
380      * @param {Function} fn The function to execute for each item
381      * @param {Object} scope (optional) The scope (&lt;code&gt;this&lt;/code&gt; reference) in which the function
382      * is executed. Defaults to the current Component in the iteration.
383      */
384     eachBottomUp: function (fn, scope) {
385         var comp,
386             stack = this.zIndexStack,
387             i, n;
388
389         for (i = 0, n = stack.length ; i &lt; n; i++) {
390             comp = stack[i];
391             if (comp.isComponent &amp;&amp; fn.call(scope || comp, comp) === false) {
392                 return;
393             }
394         }
395     },
396
397 <span id='Ext-ZIndexManager-method-eachTopDown'>    /**
398 </span>     * Executes the specified function once for every Component in this ZIndexManager, passing each
399      * Component as the only parameter. Returning false from the function will stop the iteration.
400      * The components are passed to the function starting at the top and proceeding to the bottom.
401      * @param {Function} fn The function to execute for each item
402      * @param {Object} scope (optional) The scope (&lt;code&gt;this&lt;/code&gt; reference) in which the function
403      * is executed. Defaults to the current Component in the iteration.
404      */
405     eachTopDown: function (fn, scope) {
406         var comp,
407             stack = this.zIndexStack,
408             i;
409
410         for (i = stack.length ; i-- &gt; 0; ) {
411             comp = stack[i];
412             if (comp.isComponent &amp;&amp; fn.call(scope || comp, comp) === false) {
413                 return;
414             }
415         }
416     },
417
418     destroy: function() {
419         delete this.zIndexStack;
420         delete this.list;
421         delete this.container;
422         delete this.targetEl;
423     }
424 }, function() {
425 <span id='Ext-WindowManager'>    /**
426 </span>     * @class Ext.WindowManager
427      * @extends Ext.ZIndexManager
428      * &lt;p&gt;The default global floating Component group that is available automatically.&lt;/p&gt;
429      * &lt;p&gt;This manages instances of floating Components which were rendered programatically without
430      * being added to a {@link Ext.container.Container Container}, and for floating Components which were added into non-floating Containers.&lt;/p&gt;
431      * &lt;p&gt;&lt;i&gt;Floating&lt;/i&gt; Containers create their own instance of ZIndexManager, and floating Components added at any depth below
432      * there are managed by that ZIndexManager.&lt;/p&gt;
433      * @singleton
434      */
435     Ext.WindowManager = Ext.WindowMgr = new this();
436 });
437 </pre>
438 </body>
439 </html>