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