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