3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
17 * @extends Ext.Element
18 * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
19 * automatic maintaining of shadow/shim positions.
21 * @cfg {Boolean} [shim=true]
22 * False to disable the iframe shim in browsers which need one.
24 * @cfg {String/Boolean} [shadow=false]
25 * True to automatically create an {@link Ext.Shadow}, or a string indicating the
26 * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow.
28 * @cfg {Object} [dh={tag: 'div', cls: 'x-layer'}]
29 * DomHelper object config to create element with.
31 * @cfg {Boolean} [constrain=true]
32 * False to disable constrain to viewport.
35 * CSS class to add to the element
37 * @cfg {Number} [zindex=11000]
40 * @cfg {Number} [shadowOffset=4]
41 * Number of pixels to offset the shadow
43 * @cfg {Boolean} [useDisplay=false]
44 * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
45 * to use css style <tt>'display:none;'</tt> to hide the Layer.
47 * @cfg {String} visibilityCls
48 * The CSS class name to add in order to hide this Layer if this layer
49 * is configured with <code>{@link #hideMode}: 'asclass'</code>
51 * @cfg {String} hideMode
52 * A String which specifies how this Layer will be hidden.
53 * Values may be<div class="mdetail-params"><ul>
54 * <li><code>'display'</code> : The Component will be hidden using the <code>display: none</code> style.</li>
55 * <li><code>'visibility'</code> : The Component will be hidden using the <code>visibility: hidden</code> style.</li>
56 * <li><code>'offsets'</code> : The Component will be hidden by absolutely positioning it out of the visible area of the document. This
57 * is useful when a hidden Component must maintain measurable dimensions. Hiding using <code>display</code> results
58 * in a Component having zero dimensions.</li></ul></div>
60 Ext.define('Ext.Layer', {
63 // shims are shared among layer to keep from having 100 iframes
68 extend: 'Ext.Element',
72 * @param {Object} config (optional) An object with config options.
73 * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element.
74 * If the element is not found it creates it.
76 constructor: function(config, existingEl) {
77 config = config || {};
81 pel = cp ? Ext.getDom(cp) : document.body,
85 me.dom = Ext.getDom(existingEl);
88 me.dom = dh.append(pel, config.dh || {
90 cls: Ext.baseCSSPrefix + 'layer'
93 me.addCls(Ext.baseCSSPrefix + 'layer');
94 if (!me.dom.parentNode) {
95 pel.appendChild(me.dom);
100 me.addCls(config.cls);
102 me.constrain = config.constrain !== false;
104 // Allow Components to pass their hide mode down to the Layer if they are floating.
105 // Otherwise, allow useDisplay to override the default hiding method which is visibility.
106 // TODO: Have ExtJS's Element implement visibilityMode by using classes as in Mobile.
108 me.setVisibilityMode(Ext.Element[hm.toUpperCase()]);
109 if (me.visibilityMode == Ext.Element.ASCLASS) {
110 me.visibilityCls = config.visibilityCls;
112 } else if (config.useDisplay) {
113 me.setVisibilityMode(Ext.Element.DISPLAY);
115 me.setVisibilityMode(Ext.Element.VISIBILITY);
119 me.id = me.dom.id = config.id;
121 me.id = Ext.id(me.dom);
123 me.position('absolute');
125 me.shadowOffset = config.shadowOffset || 4;
126 me.shadow = Ext.create('Ext.Shadow', {
127 offset: me.shadowOffset,
134 me.useShim = config.shim !== false && Ext.useShims;
135 if (config.hidden === true) {
142 getZIndex: function() {
143 return parseInt((this.getShim() || this).getStyle('z-index'), 10);
146 getShim: function() {
154 shim = me.self.shims.shift();
156 shim = me.createShim();
157 shim.enableDisplayMode('block');
160 pn = me.dom.parentNode;
161 if (shim.dom.parentNode != pn) {
162 pn.insertBefore(shim.dom, me.dom);
169 hideShim: function() {
173 me.shim.setDisplayed(false);
174 me.self.shims.push(me.shim);
179 disableShadow: function() {
182 if (me.shadow && !me.shadowDisabled) {
183 me.shadowDisabled = true;
185 me.lastShadowOffset = me.shadowOffset;
190 enableShadow: function(show) {
193 if (me.shadow && me.shadowDisabled) {
194 me.shadowDisabled = false;
195 me.shadowOffset = me.lastShadowOffset;
196 delete me.lastShadowOffset;
205 * <p>Synchronize this Layer's associated elements, the shadow, and possibly the shim.</p>
206 * <p>This code can execute repeatedly in milliseconds,
207 * eg: dragging a Component configured liveDrag: true, or which has no ghost method
208 * so code size was sacrificed for efficiency (e.g. no getBox/setBox, no XY calls)</p>
209 * @param {Boolean} doShow Pass true to ensure that the shadow is shown.
211 sync: function(doShow) {
214 shadowPos, shimStyle, shadowSize;
216 if (!me.updating && me.isVisible() && (shadow || me.useShim)) {
217 var shim = me.getShim(),
218 l = me.getLeft(true),
220 w = me.dom.offsetWidth,
221 h = me.dom.offsetHeight,
224 if (shadow && !me.shadowDisabled) {
225 if (doShow && !shadow.isVisible()) {
228 shadow.realign(l, t, w, h);
231 // TODO: Determine how the shims zIndex is above the layer zIndex at this point
232 shimIndex = shim.getStyle('z-index');
233 if (shimIndex > me.zindex) {
234 me.shim.setStyle('z-index', me.zindex - 2);
237 // fit the shim behind the shadow, so it is shimmed too
238 if (shadow.isVisible()) {
239 shadowPos = shadow.el.getXY();
240 shimStyle = shim.dom.style;
241 shadowSize = shadow.el.getSize();
242 if (Ext.supports.CSS3BoxShadow) {
243 shadowSize.height += 6;
244 shadowSize.width += 4;
248 shimStyle.left = (shadowPos[0]) + 'px';
249 shimStyle.top = (shadowPos[1]) + 'px';
250 shimStyle.width = (shadowSize.width) + 'px';
251 shimStyle.height = (shadowSize.height) + 'px';
254 shim.setLeftTop(l, t);
258 // TODO: Determine how the shims zIndex is above the layer zIndex at this point
259 shimIndex = shim.getStyle('z-index');
260 if (shimIndex > me.zindex) {
261 me.shim.setStyle('z-index', me.zindex - 2);
265 shim.setLeftTop(l, t);
277 beginUpdate: function() {
278 this.updating = true;
282 endUpdate: function() {
283 this.updating = false;
288 hideUnders: function() {
296 constrainXY: function() {
297 if (this.constrain) {
298 var vw = Ext.Element.getViewWidth(),
299 vh = Ext.Element.getViewHeight(),
300 s = Ext.getDoc().getScroll(),
304 so = this.shadowOffset,
305 w = this.dom.offsetWidth + so,
306 h = this.dom.offsetHeight + so,
307 moved = false; // only move it if it needs it
308 // first validate right/bottom
309 if ((x + w) > vw + s.left) {
313 if ((y + h) > vh + s.top) {
317 // then make sure top/left isn't negative
327 Ext.Layer.superclass.setXY.call(this, [x, y]);
334 getConstrainOffset: function() {
335 return this.shadowOffset;
338 // overridden Element method
339 setVisible: function(visible, animate, duration, callback, easing) {
343 // post operation processing
353 // Hide shadow and shim if hiding
357 me.callParent([visible, animate, duration, callback, easing]);
365 beforeFx: function() {
367 return this.callParent(arguments);
371 afterFx: function() {
372 this.callParent(arguments);
373 this.sync(this.isVisible());
377 beforeAction: function() {
378 if (!this.updating && this.shadow) {
383 // overridden Element method
384 setLeft: function(left) {
385 this.callParent(arguments);
389 setTop: function(top) {
390 this.callParent(arguments);
394 setLeftTop: function(left, top) {
395 this.callParent(arguments);
399 setXY: function(xy, animate, duration, callback, easing) {
402 // Callback will restore shadow state and call the passed callback
403 callback = me.createCB(callback);
407 me.callParent([xy, animate, duration, callback, easing]);
415 createCB: function(callback) {
417 showShadow = me.shadow && me.shadow.isVisible();
428 // overridden Element method
429 setX: function(x, animate, duration, callback, easing) {
430 this.setXY([x, this.getY()], animate, duration, callback, easing);
434 // overridden Element method
435 setY: function(y, animate, duration, callback, easing) {
436 this.setXY([this.getX(), y], animate, duration, callback, easing);
440 // overridden Element method
441 setSize: function(w, h, animate, duration, callback, easing) {
444 // Callback will restore shadow state and call the passed callback
445 callback = me.createCB(callback);
448 me.callParent([w, h, animate, duration, callback, easing]);
455 // overridden Element method
456 setWidth: function(w, animate, duration, callback, easing) {
459 // Callback will restore shadow state and call the passed callback
460 callback = me.createCB(callback);
463 me.callParent([w, animate, duration, callback, easing]);
470 // overridden Element method
471 setHeight: function(h, animate, duration, callback, easing) {
474 // Callback will restore shadow state and call the passed callback
475 callback = me.createCB(callback);
478 me.callParent([h, animate, duration, callback, easing]);
485 // overridden Element method
486 setBounds: function(x, y, width, height, animate, duration, callback, easing) {
489 // Callback will restore shadow state and call the passed callback
490 callback = me.createCB(callback);
494 Ext.Layer.superclass.setXY.call(me, [x, y]);
495 Ext.Layer.superclass.setSize.call(me, width, height);
498 me.callParent([x, y, width, height, animate, duration, callback, easing]);
504 * <p>Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
505 * incremented depending upon the presence of a shim or a shadow in so that it always shows above those two associated elements.</p>
506 * <p>Any shim, will be assigned the passed z-index. A shadow will be assigned the next highet z-index, and the Layer's
507 * element will receive the highest z-index.
508 * @param {Number} zindex The new z-index to set
509 * @return {Ext.Layer} The Layer
511 setZIndex: function(zindex) {
516 me.shim.setStyle('z-index', zindex++);
519 me.shadow.setZIndex(zindex++);
521 return me.setStyle('z-index', zindex);
524 setOpacity: function(opacity){
526 this.shadow.setOpacity(opacity);
528 return this.callParent(arguments);