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