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