Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / core / src / dom / Element.fx-more.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
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.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class Ext.Element
17  */
18 Ext.Element.addMethods(
19     function() {
20         var VISIBILITY      = "visibility",
21             DISPLAY         = "display",
22             HIDDEN          = "hidden",
23             NONE            = "none",
24             XMASKED         = Ext.baseCSSPrefix + "masked",
25             XMASKEDRELATIVE = Ext.baseCSSPrefix + "masked-relative",
26             data            = Ext.Element.data;
27
28         return {
29             /**
30              * Checks whether the element is currently visible using both visibility and display properties.
31              * @param {Boolean} [deep=false] True to walk the dom and see if parent elements are hidden
32              * @return {Boolean} True if the element is currently visible, else false
33              */
34             isVisible : function(deep) {
35                 var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
36                     p   = this.dom.parentNode;
37
38                 if (deep !== true || !vis) {
39                     return vis;
40                 }
41
42                 while (p && !(/^body/i.test(p.tagName))) {
43                     if (!Ext.fly(p, '_isVisible').isVisible()) {
44                         return false;
45                     }
46                     p = p.parentNode;
47                 }
48                 return true;
49             },
50
51             /**
52              * Returns true if display is not "none"
53              * @return {Boolean}
54              */
55             isDisplayed : function() {
56                 return !this.isStyle(DISPLAY, NONE);
57             },
58
59             /**
60              * Convenience method for setVisibilityMode(Element.DISPLAY)
61              * @param {String} display (optional) What to set display to when visible
62              * @return {Ext.Element} this
63              */
64             enableDisplayMode : function(display) {
65                 this.setVisibilityMode(Ext.Element.DISPLAY);
66
67                 if (!Ext.isEmpty(display)) {
68                     data(this.dom, 'originalDisplay', display);
69                 }
70
71                 return this;
72             },
73
74             /**
75              * Puts a mask over this element to disable user interaction. Requires core.css.
76              * This method can only be applied to elements which accept child nodes.
77              * @param {String} msg (optional) A message to display in the mask
78              * @param {String} msgCls (optional) A css class to apply to the msg element
79              * @return {Ext.Element} The mask element
80              */
81             mask : function(msg, msgCls) {
82                 var me  = this,
83                     dom = me.dom,
84                     setExpression = dom.style.setExpression,
85                     dh  = Ext.DomHelper,
86                     EXTELMASKMSG = Ext.baseCSSPrefix + "mask-msg",
87                     el,
88                     mask;
89
90                 if (!(/^body/i.test(dom.tagName) && me.getStyle('position') == 'static')) {
91                     me.addCls(XMASKEDRELATIVE);
92                 }
93                 el = data(dom, 'maskMsg');
94                 if (el) {
95                     el.remove();
96                 }
97                 el = data(dom, 'mask');
98                 if (el) {
99                     el.remove();
100                 }
101
102                 mask = dh.append(dom, {cls : Ext.baseCSSPrefix + "mask"}, true);
103                 data(dom, 'mask', mask);
104
105                 me.addCls(XMASKED);
106                 mask.setDisplayed(true);
107
108                 if (typeof msg == 'string') {
109                     var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
110                     data(dom, 'maskMsg', mm);
111                     mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
112                     mm.dom.firstChild.innerHTML = msg;
113                     mm.setDisplayed(true);
114                     mm.center(me);
115                 }
116                 // NOTE: CSS expressions are resource intensive and to be used only as a last resort
117                 // These expressions are removed as soon as they are no longer necessary - in the unmask method.
118                 // In normal use cases an element will be masked for a limited period of time.
119                 // Fix for https://sencha.jira.com/browse/EXTJSIV-19.
120                 // IE6 strict mode and IE6-9 quirks mode takes off left+right padding when calculating width!
121                 if (!Ext.supports.IncludePaddingInWidthCalculation && setExpression) {
122                     mask.dom.style.setExpression('width', 'this.parentNode.offsetWidth + "px"');
123                 }
124
125                 // Some versions and modes of IE subtract top+bottom padding when calculating height.
126                 // Different versions from those which make the same error for width!
127                 if (!Ext.supports.IncludePaddingInHeightCalculation && setExpression) {
128                     mask.dom.style.setExpression('height', 'this.parentNode.offsetHeight + "px"');
129                 }
130                 // ie will not expand full height automatically
131                 else if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
132                     mask.setSize(undefined, me.getHeight());
133                 }
134                 return mask;
135             },
136
137             /**
138              * Removes a previously applied mask.
139              */
140             unmask : function() {
141                 var me      = this,
142                     dom     = me.dom,
143                     mask    = data(dom, 'mask'),
144                     maskMsg = data(dom, 'maskMsg');
145
146                 if (mask) {
147                     // Remove resource-intensive CSS expressions as soon as they are not required.
148                     if (mask.dom.style.clearExpression) {
149                         mask.dom.style.clearExpression('width');
150                         mask.dom.style.clearExpression('height');
151                     }
152                     if (maskMsg) {
153                         maskMsg.remove();
154                         data(dom, 'maskMsg', undefined);
155                     }
156
157                     mask.remove();
158                     data(dom, 'mask', undefined);
159                     me.removeCls([XMASKED, XMASKEDRELATIVE]);
160                 }
161             },
162             /**
163              * Returns true if this element is masked. Also re-centers any displayed message within the mask.
164              * @return {Boolean}
165              */
166             isMasked : function() {
167                 var me = this,
168                     mask = data(me.dom, 'mask'),
169                     maskMsg = data(me.dom, 'maskMsg');
170
171                 if (mask && mask.isVisible()) {
172                     if (maskMsg) {
173                         maskMsg.center(me);
174                     }
175                     return true;
176                 }
177                 return false;
178             },
179
180             /**
181              * Creates an iframe shim for this element to keep selects and other windowed objects from
182              * showing through.
183              * @return {Ext.Element} The new shim element
184              */
185             createShim : function() {
186                 var el = document.createElement('iframe'),
187                     shim;
188
189                 el.frameBorder = '0';
190                 el.className = Ext.baseCSSPrefix + 'shim';
191                 el.src = Ext.SSL_SECURE_URL;
192                 shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
193                 shim.autoBoxAdjust = false;
194                 return shim;
195             }
196         };
197     }()
198 );