Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / src / ext-core / src / core / Element.fx.js
1 /*!
2  * Ext JS Library 3.2.0
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.Element
9  */
10 /**
11  * Visibility mode constant for use with {@link #setVisibilityMode}. Use visibility to hide element
12  * @static
13  * @type Number
14  */
15 Ext.Element.VISIBILITY = 1;
16 /**
17  * Visibility mode constant for use with {@link #setVisibilityMode}. Use display to hide element
18  * @static
19  * @type Number
20  */
21 Ext.Element.DISPLAY = 2;
22
23 Ext.Element.addMethods(function(){
24     var VISIBILITY = "visibility",
25         DISPLAY = "display",
26         HIDDEN = "hidden",
27         OFFSETS = "offsets",
28         NONE = "none",
29         ORIGINALDISPLAY = 'originalDisplay',
30         VISMODE = 'visibilityMode',
31         ELDISPLAY = Ext.Element.DISPLAY,
32         data = Ext.Element.data,
33         getDisplay = function(dom){
34             var d = data(dom, ORIGINALDISPLAY);
35             if(d === undefined){
36                 data(dom, ORIGINALDISPLAY, d = '');
37             }
38             return d;
39         },
40         getVisMode = function(dom){
41             var m = data(dom, VISMODE);
42             if(m === undefined){
43                 data(dom, VISMODE, m = 1);
44             }
45             return m;
46         };
47
48     return {
49         /**
50          * The element's default display mode  (defaults to "")
51          * @type String
52          */
53         originalDisplay : "",
54         visibilityMode : 1,
55
56         /**
57          * Sets the element's visibility mode. When setVisible() is called it
58          * will use this to determine whether to set the visibility or the display property.
59          * @param {Number} visMode Ext.Element.VISIBILITY or Ext.Element.DISPLAY
60          * @return {Ext.Element} this
61          */
62         setVisibilityMode : function(visMode){
63             data(this.dom, VISMODE, visMode);
64             return this;
65         },
66
67         /**
68          * Perform custom animation on this element.
69          * <div><ul class="mdetail-params">
70          * <li><u>Animation Properties</u></li>
71          *
72          * <p>The Animation Control Object enables gradual transitions for any member of an
73          * element's style object that takes a numeric value including but not limited to
74          * these properties:</p><div><ul class="mdetail-params">
75          * <li><tt>bottom, top, left, right</tt></li>
76          * <li><tt>height, width</tt></li>
77          * <li><tt>margin, padding</tt></li>
78          * <li><tt>borderWidth</tt></li>
79          * <li><tt>opacity</tt></li>
80          * <li><tt>fontSize</tt></li>
81          * <li><tt>lineHeight</tt></li>
82          * </ul></div>
83          *
84          *
85          * <li><u>Animation Property Attributes</u></li>
86          *
87          * <p>Each Animation Property is a config object with optional properties:</p>
88          * <div><ul class="mdetail-params">
89          * <li><tt>by</tt>*  : relative change - start at current value, change by this value</li>
90          * <li><tt>from</tt> : ignore current value, start from this value</li>
91          * <li><tt>to</tt>*  : start at current value, go to this value</li>
92          * <li><tt>unit</tt> : any allowable unit specification</li>
93          * <p>* do not specify both <tt>to</tt> and <tt>by</tt> for an animation property</p>
94          * </ul></div>
95          *
96          * <li><u>Animation Types</u></li>
97          *
98          * <p>The supported animation types:</p><div><ul class="mdetail-params">
99          * <li><tt>'run'</tt> : Default
100          * <pre><code>
101 var el = Ext.get('complexEl');
102 el.animate(
103     // animation control object
104     {
105         borderWidth: {to: 3, from: 0},
106         opacity: {to: .3, from: 1},
107         height: {to: 50, from: el.getHeight()},
108         width: {to: 300, from: el.getWidth()},
109         top  : {by: - 100, unit: 'px'},
110     },
111     0.35,      // animation duration
112     null,      // callback
113     'easeOut', // easing method
114     'run'      // animation type ('run','color','motion','scroll')
115 );
116          * </code></pre>
117          * </li>
118          * <li><tt>'color'</tt>
119          * <p>Animates transition of background, text, or border colors.</p>
120          * <pre><code>
121 el.animate(
122     // animation control object
123     {
124         color: { to: '#06e' },
125         backgroundColor: { to: '#e06' }
126     },
127     0.35,      // animation duration
128     null,      // callback
129     'easeOut', // easing method
130     'color'    // animation type ('run','color','motion','scroll')
131 );
132          * </code></pre>
133          * </li>
134          *
135          * <li><tt>'motion'</tt>
136          * <p>Animates the motion of an element to/from specific points using optional bezier
137          * way points during transit.</p>
138          * <pre><code>
139 el.animate(
140     // animation control object
141     {
142         borderWidth: {to: 3, from: 0},
143         opacity: {to: .3, from: 1},
144         height: {to: 50, from: el.getHeight()},
145         width: {to: 300, from: el.getWidth()},
146         top  : {by: - 100, unit: 'px'},
147         points: {
148             to: [50, 100],  // go to this point
149             control: [      // optional bezier way points
150                 [ 600, 800],
151                 [-100, 200]
152             ]
153         }
154     },
155     3000,      // animation duration (milliseconds!)
156     null,      // callback
157     'easeOut', // easing method
158     'motion'   // animation type ('run','color','motion','scroll')
159 );
160          * </code></pre>
161          * </li>
162          * <li><tt>'scroll'</tt>
163          * <p>Animate horizontal or vertical scrolling of an overflowing page element.</p>
164          * <pre><code>
165 el.animate(
166     // animation control object
167     {
168         scroll: {to: [400, 300]}
169     },
170     0.35,      // animation duration
171     null,      // callback
172     'easeOut', // easing method
173     'scroll'   // animation type ('run','color','motion','scroll')
174 );
175          * </code></pre>
176          * </li>
177          * </ul></div>
178          *
179          * </ul></div>
180          *
181          * @param {Object} args The animation control args
182          * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to <tt>.35</tt>)
183          * @param {Function} onComplete (optional) Function to call when animation completes
184          * @param {String} easing (optional) {@link Ext.Fx#easing} method to use (defaults to <tt>'easeOut'</tt>)
185          * @param {String} animType (optional) <tt>'run'</tt> is the default. Can also be <tt>'color'</tt>,
186          * <tt>'motion'</tt>, or <tt>'scroll'</tt>
187          * @return {Ext.Element} this
188          */
189         animate : function(args, duration, onComplete, easing, animType){
190             this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
191             return this;
192         },
193
194         /*
195          * @private Internal animation call
196          */
197         anim : function(args, opt, animType, defaultDur, defaultEase, cb){
198             animType = animType || 'run';
199             opt = opt || {};
200             var me = this,
201                 anim = Ext.lib.Anim[animType](
202                     me.dom,
203                     args,
204                     (opt.duration || defaultDur) || .35,
205                     (opt.easing || defaultEase) || 'easeOut',
206                     function(){
207                         if(cb) cb.call(me);
208                         if(opt.callback) opt.callback.call(opt.scope || me, me, opt);
209                     },
210                     me
211                 );
212             opt.anim = anim;
213             return anim;
214         },
215
216         // private legacy anim prep
217         preanim : function(a, i){
218             return !a[i] ? false : (Ext.isObject(a[i]) ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
219         },
220
221         /**
222          * Checks whether the element is currently visible using both visibility and display properties.
223          * @return {Boolean} True if the element is currently visible, else false
224          */
225         isVisible : function() {
226             return !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE);
227         },
228
229         /**
230          * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
231          * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
232          * @param {Boolean} visible Whether the element is visible
233          * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
234          * @return {Ext.Element} this
235          */
236          setVisible : function(visible, animate){
237             var me = this, isDisplay, isVisible, isOffsets,
238                 dom = me.dom;
239
240             // hideMode string override
241             if (Ext.isString(animate)){
242                 isDisplay = animate == DISPLAY;
243                 isVisible = animate == VISIBILITY;
244                 isOffsets = animate == OFFSETS;
245                 animate = false;
246             } else {
247                 isDisplay = getVisMode(this.dom) == ELDISPLAY;
248                 isVisible = !isDisplay;
249             }
250
251             if (!animate || !me.anim) {
252                 if (isDisplay){
253                     me.setDisplayed(visible);
254                 } else if (isOffsets){
255                     if (!visible){
256                         me.hideModeStyles = {
257                             position: me.getStyle('position'),
258                             top: me.getStyle('top'),
259                             left: me.getStyle('left')
260                         };
261
262                         me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
263                     } else {
264                         me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
265                     }
266                 }else{
267                     me.fixDisplay();
268                     dom.style.visibility = visible ? "visible" : HIDDEN;
269                 }
270             }else{
271                 // closure for composites
272                 if (visible){
273                     me.setOpacity(.01);
274                     me.setVisible(true);
275                 }
276                 me.anim({opacity: { to: (visible?1:0) }},
277                         me.preanim(arguments, 1),
278                         null,
279                         .35,
280                         'easeIn',
281                         function(){
282                              if(!visible){
283                                  dom.style[isDisplay ? DISPLAY : VISIBILITY] = (isDisplay) ? NONE : HIDDEN;
284                                  Ext.fly(dom).setOpacity(1);
285                              }
286                         });
287             }
288             return me;
289         },
290
291         /**
292          * Toggles the element's visibility or display, depending on visibility mode.
293          * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
294          * @return {Ext.Element} this
295          */
296         toggle : function(animate){
297             var me = this;
298             me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
299             return me;
300         },
301
302         /**
303          * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
304          * @param {Mixed} value Boolean value to display the element using its default display, or a string to set the display directly.
305          * @return {Ext.Element} this
306          */
307         setDisplayed : function(value) {
308             if(typeof value == "boolean"){
309                value = value ? getDisplay(this.dom) : NONE;
310             }
311             this.setStyle(DISPLAY, value);
312             return this;
313         },
314
315         // private
316         fixDisplay : function(){
317             var me = this;
318             if(me.isStyle(DISPLAY, NONE)){
319                 me.setStyle(VISIBILITY, HIDDEN);
320                 me.setStyle(DISPLAY, getDisplay(this.dom)); // first try reverting to default
321                 if(me.isStyle(DISPLAY, NONE)){ // if that fails, default to block
322                     me.setStyle(DISPLAY, "block");
323                 }
324             }
325         },
326
327         /**
328          * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
329          * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
330          * @return {Ext.Element} this
331          */
332         hide : function(animate){
333             // hideMode override
334             if (Ext.isString(animate)){
335                 this.setVisible(false, animate);
336                 return this;
337             }
338             this.setVisible(false, this.preanim(arguments, 0));
339             return this;
340         },
341
342         /**
343         * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
344         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
345          * @return {Ext.Element} this
346          */
347         show : function(animate){
348             // hideMode override
349             if (Ext.isString(animate)){
350                 this.setVisible(true, animate);
351                 return this;
352             }
353             this.setVisible(true, this.preanim(arguments, 0));
354             return this;
355         }
356     };
357 }());