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