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.core.Element
18 * An extended {@link Ext.core.Element} object that supports a shadow and shim, constrain to viewport and
19 * automatic maintaining of shadow/shim positions.
20 * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
21 * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the
22 * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false)
23 * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}).
24 * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
25 * @cfg {String} cls CSS class to add to the element
26 * @cfg {Number} zindex Starting z-index (defaults to 11000)
27 * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4)
28 * @cfg {Boolean} useDisplay
29 * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
30 * to use css style <tt>'display:none;'</tt> to hide the Layer.
31 * @cfg {String} visibilityCls The CSS class name to add in order to hide this Layer if this layer
32 * is configured with <code>{@link #hideMode}: 'asclass'</code>
33 * @cfg {String} hideMode
34 * A String which specifies how this Layer will be hidden.
35 * Values may be<div class="mdetail-params"><ul>
36 * <li><code>'display'</code> : The Component will be hidden using the <code>display: none</code> style.</li>
37 * <li><code>'visibility'</code> : The Component will be hidden using the <code>visibility: hidden</code> style.</li>
38 * <li><code>'offsets'</code> : The Component will be hidden by absolutely positioning it out of the visible area of the document. This
39 * is useful when a hidden Component must maintain measurable dimensions. Hiding using <code>display</code> results
40 * in a Component having zero dimensions.</li></ul></div>
42 Ext.define('Ext.Layer', {
45 // shims are shared among layer to keep from having 100 iframes
50 extend: 'Ext.core.Element',
54 * @param {Object} config (optional) An object with config options.
55 * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element.
56 * If the element is not found it creates it.
58 constructor: function(config, existingEl) {
59 config = config || {};
61 dh = Ext.core.DomHelper,
63 pel = cp ? Ext.getDom(cp) : document.body,
67 me.dom = Ext.getDom(existingEl);
70 me.dom = dh.append(pel, config.dh || {
72 cls: Ext.baseCSSPrefix + 'layer'
75 me.addCls(Ext.baseCSSPrefix + 'layer');
76 if (!me.dom.parentNode) {
77 pel.appendChild(me.dom);
82 me.addCls(config.cls);
84 me.constrain = config.constrain !== false;
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.
90 me.setVisibilityMode(Ext.core.Element[hm.toUpperCase()]);
91 if (me.visibilityMode == Ext.core.Element.ASCLASS) {
92 me.visibilityCls = config.visibilityCls;
94 } else if (config.useDisplay) {
95 me.setVisibilityMode(Ext.core.Element.DISPLAY);
97 me.setVisibilityMode(Ext.core.Element.VISIBILITY);
101 me.id = me.dom.id = config.id;
103 me.id = Ext.id(me.dom);
105 me.position('absolute');
107 me.shadowOffset = config.shadowOffset || 4;
108 me.shadow = Ext.create('Ext.Shadow', {
109 offset: me.shadowOffset,
116 me.useShim = config.shim !== false && Ext.useShims;
117 if (config.hidden === true) {
124 getZIndex: function() {
125 return parseInt((this.getShim() || this).getStyle('z-index'), 10);
128 getShim: function() {
136 shim = me.self.shims.shift();
138 shim = me.createShim();
139 shim.enableDisplayMode('block');
142 pn = me.dom.parentNode;
143 if (shim.dom.parentNode != pn) {
144 pn.insertBefore(shim.dom, me.dom);
151 hideShim: function() {
153 this.shim.setDisplayed(false);
154 this.self.shims.push(this.shim);
159 disableShadow: function() {
161 this.shadowDisabled = true;
163 this.lastShadowOffset = this.shadowOffset;
164 this.shadowOffset = 0;
168 enableShadow: function(show) {
170 this.shadowDisabled = false;
171 this.shadowOffset = this.lastShadowOffset;
172 delete this.lastShadowOffset;
181 * <p>Synchronize this Layer's associated elements, the shadow, and possibly the shim.</p>
182 * <p>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)</p>
185 * @param {Boolean} doShow Pass true to ensure that the shadow is shown.
187 sync: function(doShow) {
190 shadowPos, shimStyle, shadowSize;
192 if (!this.updating && this.isVisible() && (shadow || this.useShim)) {
193 var shim = this.getShim(),
194 l = this.getLeft(true),
195 t = this.getTop(true),
197 h = this.getHeight(),
200 if (shadow && !this.shadowDisabled) {
201 if (doShow && !shadow.isVisible()) {
204 shadow.realign(l, t, w, h);
207 // TODO: Determine how the shims zIndex is above the layer zIndex at this point
208 shimIndex = shim.getStyle('z-index');
209 if (shimIndex > me.zindex) {
210 me.shim.setStyle('z-index', me.zindex - 2);
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';
224 shim.setLeftTop(l, t);
228 // TODO: Determine how the shims zIndex is above the layer zIndex at this point
229 shimIndex = shim.getStyle('z-index');
230 if (shimIndex > me.zindex) {
231 me.shim.setStyle('z-index', me.zindex - 2);
235 shim.setLeftTop(l, t);
247 beginUpdate: function() {
248 this.updating = true;
252 endUpdate: function() {
253 this.updating = false;
258 hideUnders: function() {
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(),
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) > vw + s.left) {
283 if ((y + h) > vh + s.top) {
287 // then make sure top/left isn't negative
297 Ext.Layer.superclass.setXY.call(this, [x, y]);
304 getConstrainOffset: function() {
305 return this.shadowOffset;
308 // overridden Element method
309 setVisible: function(visible, animate, duration, callback, easing) {
313 // post operation processing
323 // Hide shadow and shim if hiding
325 this.hideUnders(true);
327 this.callParent([visible, animate, duration, callback, easing]);
335 beforeFx: function() {
337 return this.callParent(arguments);
341 afterFx: function() {
342 this.callParent(arguments);
343 this.sync(this.isVisible());
347 beforeAction: function() {
348 if (!this.updating && this.shadow) {
353 // overridden Element method
354 setLeft: function(left) {
355 this.callParent(arguments);
359 setTop: function(top) {
360 this.callParent(arguments);
364 setLeftTop: function(left, top) {
365 this.callParent(arguments);
369 setXY: function(xy, animate, duration, callback, easing) {
371 // Callback will restore shadow state and call the passed callback
372 callback = this.createCB(callback);
376 this.callParent([xy, animate, duration, callback, easing]);
384 createCB: function(callback) {
386 showShadow = me.shadow && me.shadow.isVisible();
397 // overridden Element method
398 setX: function(x, animate, duration, callback, easing) {
399 this.setXY([x, this.getY()], animate, duration, callback, easing);
403 // overridden Element method
404 setY: function(y, animate, duration, callback, easing) {
405 this.setXY([this.getX(), y], animate, duration, callback, easing);
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);
415 this.callParent([w, h, animate, duration, callback, easing]);
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);
428 this.callParent([w, animate, duration, callback, easing]);
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);
441 this.callParent([h, animate, duration, callback, easing]);
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);
455 Ext.Layer.superclass.setXY.call(this, [x, y]);
456 Ext.Layer.superclass.setSize.call(this, width, height);
459 this.callParent([x, y, width, height, animate, duration, callback, easing]);
465 * <p>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.</p>
467 * <p>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
472 setZIndex: function(zindex) {
473 this.zindex = zindex;
474 if (this.getShim()) {
475 this.shim.setStyle('z-index', zindex++);
478 this.shadow.setZIndex(zindex++);
480 this.setStyle('z-index', zindex);