Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / core / src / dom / Element.fx.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.core.Element
17  */
18 /**
19  * Visibility mode constant for use with {@link #setVisibilityMode}. Use visibility to hide element
20  * @static
21  * @type Number
22  */
23 Ext.core.Element.VISIBILITY = 1;
24 /**
25  * Visibility mode constant for use with {@link #setVisibilityMode}. Use display to hide element
26  * @static
27  * @type Number
28  */
29 Ext.core.Element.DISPLAY = 2;
30
31 /**
32  * Visibility mode constant for use with {@link #setVisibilityMode}. Use offsets (x and y positioning offscreen)
33  * to hide element.
34  * @static
35  * @type Number
36  */
37 Ext.core.Element.OFFSETS = 3;
38
39
40 Ext.core.Element.ASCLASS = 4;
41
42 /**
43  * Defaults to 'x-hide-nosize'
44  * @static
45  * @type String
46  */
47 Ext.core.Element.visibilityCls = Ext.baseCSSPrefix + 'hide-nosize';
48
49 Ext.core.Element.addMethods(function(){
50     var El = Ext.core.Element,
51         OPACITY = "opacity",
52         VISIBILITY = "visibility",
53         DISPLAY = "display",
54         HIDDEN = "hidden",
55         OFFSETS = "offsets",
56         ASCLASS = "asclass",
57         NONE = "none",
58         NOSIZE = 'nosize',
59         ORIGINALDISPLAY = 'originalDisplay',
60         VISMODE = 'visibilityMode',
61         ISVISIBLE = 'isVisible',
62         data = El.data,
63         getDisplay = function(dom){
64             var d = data(dom, ORIGINALDISPLAY);
65             if(d === undefined){
66                 data(dom, ORIGINALDISPLAY, d = '');
67             }
68             return d;
69         },
70         getVisMode = function(dom){
71             var m = data(dom, VISMODE);
72             if(m === undefined){
73                 data(dom, VISMODE, m = 1);
74             }
75             return m;
76         };
77
78     return {
79         /**
80          * The element's default display mode  (defaults to "")
81          * @type String
82          */
83         originalDisplay : "",
84         visibilityMode : 1,
85
86         /**
87          * Sets the element's visibility mode. When setVisible() is called it
88          * will use this to determine whether to set the visibility or the display property.
89          * @param {Number} visMode Ext.core.Element.VISIBILITY or Ext.core.Element.DISPLAY
90          * @return {Ext.core.Element} this
91          */
92         setVisibilityMode : function(visMode){
93             data(this.dom, VISMODE, visMode);
94             return this;
95         },
96
97         /**
98          * Checks whether the element is currently visible using both visibility and display properties.
99          * @return {Boolean} True if the element is currently visible, else false
100          */
101         isVisible : function() {
102             var me = this,
103                 dom = me.dom,
104                 visible = data(dom, ISVISIBLE);
105
106             if(typeof visible == 'boolean'){ //return the cached value if registered
107                 return visible;
108             }
109             //Determine the current state based on display states
110             visible = !me.isStyle(VISIBILITY, HIDDEN) &&
111                       !me.isStyle(DISPLAY, NONE) &&
112                       !((getVisMode(dom) == El.ASCLASS) && me.hasCls(me.visibilityCls || El.visibilityCls));
113
114             data(dom, ISVISIBLE, visible);
115             return visible;
116         },
117
118         /**
119          * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
120          * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
121          * @param {Boolean} visible Whether the element is visible
122          * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
123          * @return {Ext.core.Element} this
124          */
125         setVisible : function(visible, animate){
126             var me = this, isDisplay, isVisibility, isOffsets, isNosize,
127                 dom = me.dom,
128                 visMode = getVisMode(dom);
129
130
131             // hideMode string override
132             if (typeof animate == 'string'){
133                 switch (animate) {
134                     case DISPLAY:
135                         visMode = El.DISPLAY;
136                         break;
137                     case VISIBILITY:
138                         visMode = El.VISIBILITY;
139                         break;
140                     case OFFSETS:
141                         visMode = El.OFFSETS;
142                         break;
143                     case NOSIZE:
144                     case ASCLASS:
145                         visMode = El.ASCLASS;
146                         break;
147                 }
148                 me.setVisibilityMode(visMode);
149                 animate = false;
150             }
151
152             if (!animate || !me.anim) {
153                 if(visMode == El.ASCLASS ){
154
155                     me[visible?'removeCls':'addCls'](me.visibilityCls || El.visibilityCls);
156
157                 } else if (visMode == El.DISPLAY){
158
159                     return me.setDisplayed(visible);
160
161                 } else if (visMode == El.OFFSETS){
162
163                     if (!visible){
164                         // Remember position for restoring, if we are not already hidden by offsets.
165                         if (!me.hideModeStyles) {
166                             me.hideModeStyles = {
167                                 position: me.getStyle('position'),
168                                 top: me.getStyle('top'),
169                                 left: me.getStyle('left')
170                             };
171                         }
172                         me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
173                     }
174
175                     // Only "restore" as position if we have actually been hidden using offsets.
176                     // Calling setVisible(true) on a positioned element should not reposition it.
177                     else if (me.hideModeStyles) {
178                         me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
179                         delete me.hideModeStyles;
180                     }
181
182                 }else{
183                     me.fixDisplay();
184                     // Show by clearing visibility style. Explicitly setting to "visible" overrides parent visibility setting.
185                     dom.style.visibility = visible ? '' : HIDDEN;
186                 }
187             }else{
188                 // closure for composites
189                 if(visible){
190                     me.setOpacity(0.01);
191                     me.setVisible(true);
192                 }
193                 if (!Ext.isObject(animate)) {
194                     animate = {
195                         duration: 350,
196                         easing: 'ease-in'
197                     };
198                 }
199                 me.animate(Ext.applyIf({
200                     callback: function() {
201                         visible || me.setVisible(false).setOpacity(1);
202                     },
203                     to: {
204                         opacity: (visible) ? 1 : 0
205                     }
206                 }, animate));
207             }
208             data(dom, ISVISIBLE, visible);  //set logical visibility state
209             return me;
210         },
211
212
213         /**
214          * @private
215          * Determine if the Element has a relevant height and width available based
216          * upon current logical visibility state
217          */
218         hasMetrics  : function(){
219             var dom = this.dom;
220             return this.isVisible() || (getVisMode(dom) == El.OFFSETS) || (getVisMode(dom) == El.VISIBILITY);
221         },
222
223         /**
224          * Toggles the element's visibility or display, depending on visibility mode.
225          * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
226          * @return {Ext.core.Element} this
227          */
228         toggle : function(animate){
229             var me = this;
230             me.setVisible(!me.isVisible(), me.anim(animate));
231             return me;
232         },
233
234         /**
235          * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
236          * @param {Mixed} value Boolean value to display the element using its default display, or a string to set the display directly.
237          * @return {Ext.core.Element} this
238          */
239         setDisplayed : function(value) {
240             if(typeof value == "boolean"){
241                value = value ? getDisplay(this.dom) : NONE;
242             }
243             this.setStyle(DISPLAY, value);
244             return this;
245         },
246
247         // private
248         fixDisplay : function(){
249             var me = this;
250             if (me.isStyle(DISPLAY, NONE)) {
251                 me.setStyle(VISIBILITY, HIDDEN);
252                 me.setStyle(DISPLAY, getDisplay(this.dom)); // first try reverting to default
253                 if (me.isStyle(DISPLAY, NONE)) { // if that fails, default to block
254                     me.setStyle(DISPLAY, "block");
255                 }
256             }
257         },
258
259         /**
260          * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
261          * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
262          * @return {Ext.core.Element} this
263          */
264         hide : function(animate){
265             // hideMode override
266             if (typeof animate == 'string'){
267                 this.setVisible(false, animate);
268                 return this;
269             }
270             this.setVisible(false, this.anim(animate));
271             return this;
272         },
273
274         /**
275         * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
276         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
277          * @return {Ext.core.Element} this
278          */
279         show : function(animate){
280             // hideMode override
281             if (typeof animate == 'string'){
282                 this.setVisible(true, animate);
283                 return this;
284             }
285             this.setVisible(true, this.anim(animate));
286             return this;
287         }
288     };
289 }());