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