PageRenderTime 107ms CodeModel.GetById 73ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 0ms

/hippo/src/main/webapp/ext/src/widgets/Layer.js

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