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