Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Layer.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="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../resources/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-Layer-cfg-hideMode'><span id='Ext-Layer-cfg-visibilityCls'><span id='Ext-Layer-cfg-useDisplay'><span id='Ext-Layer-cfg-shadowOffset'><span id='Ext-Layer-cfg-zindex'><span id='Ext-Layer-cfg-cls'><span id='Ext-Layer-cfg-constrain'><span id='Ext-Layer-cfg-dh'><span id='Ext-Layer-cfg-shadow'><span id='Ext-Layer-cfg-shim'><span id='Ext-Layer'>/**
19 </span></span></span></span></span></span></span></span></span></span></span> * @class Ext.Layer
20  * @extends Ext.Element
21  * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
22  * automatic maintaining of shadow/shim positions.
23  *
24  * @cfg {Boolean} [shim=true]
25  * False to disable the iframe shim in browsers which need one.
26  *
27  * @cfg {String/Boolean} [shadow=false]
28  * True to automatically create an {@link Ext.Shadow}, or a string indicating the
29  * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow.
30  *
31  * @cfg {Object} [dh={tag: 'div', cls: 'x-layer'}]
32  * DomHelper object config to create element with.
33  *
34  * @cfg {Boolean} [constrain=true]
35  * False to disable constrain to viewport.
36  *
37  * @cfg {String} cls
38  * CSS class to add to the element
39  *
40  * @cfg {Number} [zindex=11000]
41  * Starting z-index.
42  *
43  * @cfg {Number} [shadowOffset=4]
44  * Number of pixels to offset the shadow
45  *
46  * @cfg {Boolean} [useDisplay=false]
47  * Defaults to use css offsets to hide the Layer. Specify &lt;tt&gt;true&lt;/tt&gt;
48  * to use css style &lt;tt&gt;'display:none;'&lt;/tt&gt; to hide the Layer.
49  *
50  * @cfg {String} visibilityCls
51  * The CSS class name to add in order to hide this Layer if this layer
52  * is configured with &lt;code&gt;{@link #hideMode}: 'asclass'&lt;/code&gt;
53  *
54  * @cfg {String} hideMode
55  * A String which specifies how this Layer will be hidden.
56  * Values may be&lt;div class=&quot;mdetail-params&quot;&gt;&lt;ul&gt;
57  * &lt;li&gt;&lt;code&gt;'display'&lt;/code&gt; : The Component will be hidden using the &lt;code&gt;display: none&lt;/code&gt; style.&lt;/li&gt;
58  * &lt;li&gt;&lt;code&gt;'visibility'&lt;/code&gt; : The Component will be hidden using the &lt;code&gt;visibility: hidden&lt;/code&gt; style.&lt;/li&gt;
59  * &lt;li&gt;&lt;code&gt;'offsets'&lt;/code&gt; : The Component will be hidden by absolutely positioning it out of the visible area of the document. This
60  * is useful when a hidden Component must maintain measurable dimensions. Hiding using &lt;code&gt;display&lt;/code&gt; results
61  * in a Component having zero dimensions.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
62  */
63 Ext.define('Ext.Layer', {
64     uses: ['Ext.Shadow'],
65
66     // shims are shared among layer to keep from having 100 iframes
67     statics: {
68         shims: []
69     },
70
71     extend: 'Ext.Element',
72
73 <span id='Ext-Layer-method-constructor'>    /**
74 </span>     * Creates new Layer.
75      * @param {Object} config (optional) An object with config options.
76      * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element.
77      * If the element is not found it creates it.
78      */
79     constructor: function(config, existingEl) {
80         config = config || {};
81         var me = this,
82             dh = Ext.DomHelper,
83             cp = config.parentEl,
84             pel = cp ? Ext.getDom(cp) : document.body,
85         hm = config.hideMode;
86
87         if (existingEl) {
88             me.dom = Ext.getDom(existingEl);
89         }
90         if (!me.dom) {
91             me.dom = dh.append(pel, config.dh || {
92                 tag: 'div',
93                 cls: Ext.baseCSSPrefix + 'layer'
94             });
95         } else {
96             me.addCls(Ext.baseCSSPrefix + 'layer');
97             if (!me.dom.parentNode) {
98                 pel.appendChild(me.dom);
99             }
100         }
101
102         if (config.cls) {
103             me.addCls(config.cls);
104         }
105         me.constrain = config.constrain !== false;
106
107         // Allow Components to pass their hide mode down to the Layer if they are floating.
108         // Otherwise, allow useDisplay to override the default hiding method which is visibility.
109         // TODO: Have ExtJS's Element implement visibilityMode by using classes as in Mobile.
110         if (hm) {
111             me.setVisibilityMode(Ext.Element[hm.toUpperCase()]);
112             if (me.visibilityMode == Ext.Element.ASCLASS) {
113                 me.visibilityCls = config.visibilityCls;
114             }
115         } else if (config.useDisplay) {
116             me.setVisibilityMode(Ext.Element.DISPLAY);
117         } else {
118             me.setVisibilityMode(Ext.Element.VISIBILITY);
119         }
120
121         if (config.id) {
122             me.id = me.dom.id = config.id;
123         } else {
124             me.id = Ext.id(me.dom);
125         }
126         me.position('absolute');
127         if (config.shadow) {
128             me.shadowOffset = config.shadowOffset || 4;
129             me.shadow = Ext.create('Ext.Shadow', {
130                 offset: me.shadowOffset,
131                 mode: config.shadow
132             });
133             me.disableShadow();
134         } else {
135             me.shadowOffset = 0;
136         }
137         me.useShim = config.shim !== false &amp;&amp; Ext.useShims;
138         if (config.hidden === true) {
139             me.hide();
140         } else {
141             me.show();
142         }
143     },
144
145     getZIndex: function() {
146         return parseInt((this.getShim() || this).getStyle('z-index'), 10);
147     },
148
149     getShim: function() {
150         var me = this,
151             shim, pn;
152
153         if (!me.useShim) {
154             return null;
155         }
156         if (!me.shim) {
157             shim = me.self.shims.shift();
158             if (!shim) {
159                 shim = me.createShim();
160                 shim.enableDisplayMode('block');
161                 shim.hide();
162             }
163             pn = me.dom.parentNode;
164             if (shim.dom.parentNode != pn) {
165                 pn.insertBefore(shim.dom, me.dom);
166             }
167             me.shim = shim;
168         }
169         return me.shim;
170     },
171
172     hideShim: function() {
173         var me = this;
174         
175         if (me.shim) {
176             me.shim.setDisplayed(false);
177             me.self.shims.push(me.shim);
178             delete me.shim;
179         }
180     },
181
182     disableShadow: function() {
183         var me = this;
184         
185         if (me.shadow &amp;&amp; !me.shadowDisabled) {
186             me.shadowDisabled = true;
187             me.shadow.hide();
188             me.lastShadowOffset = me.shadowOffset;
189             me.shadowOffset = 0;
190         }
191     },
192
193     enableShadow: function(show) {
194         var me = this;
195         
196         if (me.shadow &amp;&amp; me.shadowDisabled) {
197             me.shadowDisabled = false;
198             me.shadowOffset = me.lastShadowOffset;
199             delete me.lastShadowOffset;
200             if (show) {
201                 me.sync(true);
202             }
203         }
204     },
205
206 <span id='Ext-Layer-method-sync'>    /**
207 </span>     * @private
208      * &lt;p&gt;Synchronize this Layer's associated elements, the shadow, and possibly the shim.&lt;/p&gt;
209      * &lt;p&gt;This code can execute repeatedly in milliseconds,
210      * eg: dragging a Component configured liveDrag: true, or which has no ghost method
211      * so code size was sacrificed for efficiency (e.g. no getBox/setBox, no XY calls)&lt;/p&gt;
212      * @param {Boolean} doShow Pass true to ensure that the shadow is shown.
213      */
214     sync: function(doShow) {
215         var me = this,
216             shadow = me.shadow,
217             shadowPos, shimStyle, shadowSize;
218
219         if (!me.updating &amp;&amp; me.isVisible() &amp;&amp; (shadow || me.useShim)) {
220             var shim = me.getShim(),
221                 l = me.getLeft(true),
222                 t = me.getTop(true),
223                 w = me.dom.offsetWidth,
224                 h = me.dom.offsetHeight,
225                 shimIndex;
226
227             if (shadow &amp;&amp; !me.shadowDisabled) {
228                 if (doShow &amp;&amp; !shadow.isVisible()) {
229                     shadow.show(me);
230                 } else {
231                     shadow.realign(l, t, w, h);
232                 }
233                 if (shim) {
234                     // TODO: Determine how the shims zIndex is above the layer zIndex at this point
235                     shimIndex = shim.getStyle('z-index');
236                     if (shimIndex &gt; me.zindex) {
237                         me.shim.setStyle('z-index', me.zindex - 2);
238                     }
239                     shim.show();
240                     // fit the shim behind the shadow, so it is shimmed too
241                     if (shadow.isVisible()) {
242                         shadowPos = shadow.el.getXY();
243                         shimStyle = shim.dom.style;
244                         shadowSize = shadow.el.getSize();
245                         if (Ext.supports.CSS3BoxShadow) {
246                             shadowSize.height += 6;
247                             shadowSize.width += 4;
248                             shadowPos[0] -= 2;
249                             shadowPos[1] -= 4;
250                         }
251                         shimStyle.left = (shadowPos[0]) + 'px';
252                         shimStyle.top = (shadowPos[1]) + 'px';
253                         shimStyle.width = (shadowSize.width) + 'px';
254                         shimStyle.height = (shadowSize.height) + 'px';
255                     } else {
256                         shim.setSize(w, h);
257                         shim.setLeftTop(l, t);
258                     }
259                 }
260             } else if (shim) {
261                 // TODO: Determine how the shims zIndex is above the layer zIndex at this point
262                 shimIndex = shim.getStyle('z-index');
263                 if (shimIndex &gt; me.zindex) {
264                     me.shim.setStyle('z-index', me.zindex - 2);
265                 }
266                 shim.show();
267                 shim.setSize(w, h);
268                 shim.setLeftTop(l, t);
269             }
270         }
271         return me;
272     },
273
274     remove: function() {
275         this.hideUnders();
276         this.callParent();
277     },
278
279     // private
280     beginUpdate: function() {
281         this.updating = true;
282     },
283
284     // private
285     endUpdate: function() {
286         this.updating = false;
287         this.sync(true);
288     },
289
290     // private
291     hideUnders: function() {
292         if (this.shadow) {
293             this.shadow.hide();
294         }
295         this.hideShim();
296     },
297
298     // private
299     constrainXY: function() {
300         if (this.constrain) {
301             var vw = Ext.Element.getViewWidth(),
302                 vh = Ext.Element.getViewHeight(),
303                 s = Ext.getDoc().getScroll(),
304                 xy = this.getXY(),
305                 x = xy[0],
306                 y = xy[1],
307                 so = this.shadowOffset,
308                 w = this.dom.offsetWidth + so,
309                 h = this.dom.offsetHeight + so,
310                 moved = false; // only move it if it needs it
311             // first validate right/bottom
312             if ((x + w) &gt; vw + s.left) {
313                 x = vw - w - so;
314                 moved = true;
315             }
316             if ((y + h) &gt; vh + s.top) {
317                 y = vh - h - so;
318                 moved = true;
319             }
320             // then make sure top/left isn't negative
321             if (x &lt; s.left) {
322                 x = s.left;
323                 moved = true;
324             }
325             if (y &lt; s.top) {
326                 y = s.top;
327                 moved = true;
328             }
329             if (moved) {
330                 Ext.Layer.superclass.setXY.call(this, [x, y]);
331                 this.sync();
332             }
333         }
334         return this;
335     },
336
337     getConstrainOffset: function() {
338         return this.shadowOffset;
339     },
340
341     // overridden Element method
342     setVisible: function(visible, animate, duration, callback, easing) {
343         var me = this,
344             cb;
345
346         // post operation processing
347         cb = function() {
348             if (visible) {
349                 me.sync(true);
350             }
351             if (callback) {
352                 callback();
353             }
354         };
355
356         // Hide shadow and shim if hiding
357         if (!visible) {
358             me.hideUnders(true);
359         }
360         me.callParent([visible, animate, duration, callback, easing]);
361         if (!animate) {
362             cb();
363         }
364         return me;
365     },
366
367     // private
368     beforeFx: function() {
369         this.beforeAction();
370         return this.callParent(arguments);
371     },
372
373     // private
374     afterFx: function() {
375         this.callParent(arguments);
376         this.sync(this.isVisible());
377     },
378
379     // private
380     beforeAction: function() {
381         if (!this.updating &amp;&amp; this.shadow) {
382             this.shadow.hide();
383         }
384     },
385
386     // overridden Element method
387     setLeft: function(left) {
388         this.callParent(arguments);
389         return this.sync();
390     },
391
392     setTop: function(top) {
393         this.callParent(arguments);
394         return this.sync();
395     },
396
397     setLeftTop: function(left, top) {
398         this.callParent(arguments);
399         return this.sync();
400     },
401
402     setXY: function(xy, animate, duration, callback, easing) {
403         var me = this;
404         
405         // Callback will restore shadow state and call the passed callback
406         callback = me.createCB(callback);
407
408         me.fixDisplay();
409         me.beforeAction();
410         me.callParent([xy, animate, duration, callback, easing]);
411         if (!animate) {
412             callback();
413         }
414         return me;
415     },
416
417     // private
418     createCB: function(callback) {
419         var me = this,
420             showShadow = me.shadow &amp;&amp; me.shadow.isVisible();
421
422         return function() {
423             me.constrainXY();
424             me.sync(showShadow);
425             if (callback) {
426                 callback();
427             }
428         };
429     },
430
431     // overridden Element method
432     setX: function(x, animate, duration, callback, easing) {
433         this.setXY([x, this.getY()], animate, duration, callback, easing);
434         return this;
435     },
436
437     // overridden Element method
438     setY: function(y, animate, duration, callback, easing) {
439         this.setXY([this.getX(), y], animate, duration, callback, easing);
440         return this;
441     },
442
443     // overridden Element method
444     setSize: function(w, h, animate, duration, callback, easing) {
445         var me = this;
446         
447         // Callback will restore shadow state and call the passed callback
448         callback = me.createCB(callback);
449
450         me.beforeAction();
451         me.callParent([w, h, animate, duration, callback, easing]);
452         if (!animate) {
453             callback();
454         }
455         return me;
456     },
457
458     // overridden Element method
459     setWidth: function(w, animate, duration, callback, easing) {
460         var me = this;
461         
462         // Callback will restore shadow state and call the passed callback
463         callback = me.createCB(callback);
464
465         me.beforeAction();
466         me.callParent([w, animate, duration, callback, easing]);
467         if (!animate) {
468             callback();
469         }
470         return me;
471     },
472
473     // overridden Element method
474     setHeight: function(h, animate, duration, callback, easing) {
475         var me = this;
476         
477         // Callback will restore shadow state and call the passed callback
478         callback = me.createCB(callback);
479
480         me.beforeAction();
481         me.callParent([h, animate, duration, callback, easing]);
482         if (!animate) {
483             callback();
484         }
485         return me;
486     },
487
488     // overridden Element method
489     setBounds: function(x, y, width, height, animate, duration, callback, easing) {
490         var me = this;
491         
492         // Callback will restore shadow state and call the passed callback
493         callback = me.createCB(callback);
494
495         me.beforeAction();
496         if (!animate) {
497             Ext.Layer.superclass.setXY.call(me, [x, y]);
498             Ext.Layer.superclass.setSize.call(me, width, height);
499             callback();
500         } else {
501             me.callParent([x, y, width, height, animate, duration, callback, easing]);
502         }
503         return me;
504     },
505
506 <span id='Ext-Layer-method-setZIndex'>    /**
507 </span>     * &lt;p&gt;Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
508      * incremented depending upon the presence of a shim or a shadow in so that it always shows above those two associated elements.&lt;/p&gt;
509      * &lt;p&gt;Any shim, will be assigned the passed z-index. A shadow will be assigned the next highet z-index, and the Layer's
510      * element will receive the highest  z-index.
511      * @param {Number} zindex The new z-index to set
512      * @return {Ext.Layer} The Layer
513      */
514     setZIndex: function(zindex) {
515         var me = this;
516         
517         me.zindex = zindex;
518         if (me.getShim()) {
519             me.shim.setStyle('z-index', zindex++);
520         }
521         if (me.shadow) {
522             me.shadow.setZIndex(zindex++);
523         }
524         return me.setStyle('z-index', zindex);
525     },
526     
527     setOpacity: function(opacity){
528         if (this.shadow) {
529             this.shadow.setOpacity(opacity);
530         }
531         return this.callParent(arguments);
532     }
533 });
534 </pre>
535 </body>
536 </html>