Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / core / src / dom / Element.anim.js
1 /**
2  * @class Ext.core.Element
3  */
4 Ext.applyIf(Ext.core.Element.prototype, {
5     // @private override base Ext.util.Animate mixin for animate for backwards compatibility
6     animate: function(config) {
7         var me = this;
8         if (!me.id) {
9             me = Ext.get(me.dom);
10         }
11         if (Ext.fx.Manager.hasFxBlock(me.id)) {
12             return me;
13         }
14         Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(config)));
15         return this;
16     },
17
18     // @private override base Ext.util.Animate mixin for animate for backwards compatibility
19     anim: function(config) {
20         if (!Ext.isObject(config)) {
21             return (config) ? {} : false;
22         }
23
24         var me = this,
25             duration = config.duration || Ext.fx.Anim.prototype.duration,
26             easing = config.easing || 'ease',
27             animConfig;
28
29         if (config.stopAnimation) {
30             me.stopAnimation();
31         }
32
33         Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
34
35         // Clear any 'paused' defaults.
36         Ext.fx.Manager.setFxDefaults(me.id, {
37             delay: 0
38         });
39
40         animConfig = {
41             target: me,
42             remove: config.remove,
43             alternate: config.alternate || false,
44             duration: duration,
45             easing: easing,
46             callback: config.callback,
47             listeners: config.listeners,
48             iterations: config.iterations || 1,
49             scope: config.scope,
50             block: config.block,
51             concurrent: config.concurrent,
52             delay: config.delay || 0,
53             paused: true,
54             keyframes: config.keyframes,
55             from: config.from || {},
56             to: Ext.apply({}, config)
57         };
58         Ext.apply(animConfig.to, config.to);
59
60         // Anim API properties - backward compat
61         delete animConfig.to.to;
62         delete animConfig.to.from;
63         delete animConfig.to.remove;
64         delete animConfig.to.alternate;
65         delete animConfig.to.keyframes;
66         delete animConfig.to.iterations;
67         delete animConfig.to.listeners;
68         delete animConfig.to.target;
69         delete animConfig.to.paused;
70         delete animConfig.to.callback;
71         delete animConfig.to.scope;
72         delete animConfig.to.duration;
73         delete animConfig.to.easing;
74         delete animConfig.to.concurrent;
75         delete animConfig.to.block;
76         delete animConfig.to.stopAnimation;
77         delete animConfig.to.delay;
78         return animConfig;
79     },
80
81     /**
82      * Slides the element into view.  An anchor point can be optionally passed to set the point of
83      * origin for the slide effect.  This function automatically handles wrapping the element with
84      * a fixed-size container if needed.  See the Fx class overview for valid anchor point options.
85      * Usage:
86      *<pre><code>
87 // default: slide the element in from the top
88 el.slideIn();
89
90 // custom: slide the element in from the right with a 2-second duration
91 el.slideIn('r', { duration: 2 });
92
93 // common config options shown with default values
94 el.slideIn('t', {
95     easing: 'easeOut',
96     duration: 500
97 });
98 </code></pre>
99      * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
100      * @param {Object} options (optional) Object literal with any of the Fx config options
101      * @return {Ext.core.Element} The Element
102      */
103     slideIn: function(anchor, obj, slideOut) { 
104         var me = this,
105             elStyle = me.dom.style,
106             beforeAnim, wrapAnim;
107
108         anchor = anchor || "t";
109         obj = obj || {};
110
111         beforeAnim = function() {
112             var animScope = this,
113                 listeners = obj.listeners,
114                 box, position, restoreSize, wrap, anim;
115
116             if (!slideOut) {
117                 me.fixDisplay();
118             }
119
120             box = me.getBox();
121             if ((anchor == 't' || anchor == 'b') && box.height == 0) {
122                 box.height = me.dom.scrollHeight;
123             }
124             else if ((anchor == 'l' || anchor == 'r') && box.width == 0) {
125                 box.width = me.dom.scrollWidth;
126             }
127             
128             position = me.getPositioning();
129             me.setSize(box.width, box.height);
130
131             wrap = me.wrap({
132                 style: {
133                     visibility: slideOut ? 'visible' : 'hidden'
134                 }
135             });
136             wrap.setPositioning(position);
137             if (wrap.isStyle('position', 'static')) {
138                 wrap.position('relative');
139             }
140             me.clearPositioning('auto');
141             wrap.clip();
142
143             // This element is temporarily positioned absolute within its wrapper.
144             // Restore to its default, CSS-inherited visibility setting.
145             // We cannot explicitly poke visibility:visible into its style because that overrides the visibility of the wrap.
146             me.setStyle({
147                 visibility: '',
148                 position: 'absolute'
149             });
150             if (slideOut) {
151                 wrap.setSize(box.width, box.height);
152             }
153
154             switch (anchor) {
155                 case 't':
156                     anim = {
157                         from: {
158                             width: box.width + 'px',
159                             height: '0px'
160                         },
161                         to: {
162                             width: box.width + 'px',
163                             height: box.height + 'px'
164                         }
165                     };
166                     elStyle.bottom = '0px';
167                     break;
168                 case 'l':
169                     anim = {
170                         from: {
171                             width: '0px',
172                             height: box.height + 'px'
173                         },
174                         to: {
175                             width: box.width + 'px',
176                             height: box.height + 'px'
177                         }
178                     };
179                     elStyle.right = '0px';
180                     break;
181                 case 'r':
182                     anim = {
183                         from: {
184                             x: box.x + box.width,
185                             width: '0px',
186                             height: box.height + 'px'
187                         },
188                         to: {
189                             x: box.x,
190                             width: box.width + 'px',
191                             height: box.height + 'px'
192                         }
193                     };
194                     break;
195                 case 'b':
196                     anim = {
197                         from: {
198                             y: box.y + box.height,
199                             width: box.width + 'px',
200                             height: '0px'
201                         },
202                         to: {
203                             y: box.y,
204                             width: box.width + 'px',
205                             height: box.height + 'px'
206                         }
207                     };
208                     break;
209                 case 'tl':
210                     anim = {
211                         from: {
212                             x: box.x,
213                             y: box.y,
214                             width: '0px',
215                             height: '0px'
216                         },
217                         to: {
218                             width: box.width + 'px',
219                             height: box.height + 'px'
220                         }
221                     };
222                     elStyle.bottom = '0px';
223                     elStyle.right = '0px';
224                     break;
225                 case 'bl':
226                     anim = {
227                         from: {
228                             x: box.x + box.width,
229                             width: '0px',
230                             height: '0px'
231                         },
232                         to: {
233                             x: box.x,
234                             width: box.width + 'px',
235                             height: box.height + 'px'
236                         }
237                     };
238                     elStyle.right = '0px';
239                     break;
240                 case 'br':
241                     anim = {
242                         from: {
243                             x: box.x + box.width,
244                             y: box.y + box.height,
245                             width: '0px',
246                             height: '0px'
247                         },
248                         to: {
249                             x: box.x,
250                             y: box.y,
251                             width: box.width + 'px',
252                             height: box.height + 'px'
253                         }
254                     };
255                     break;
256                 case 'tr':
257                     anim = {
258                         from: {
259                             y: box.y + box.height,
260                             width: '0px',
261                             height: '0px'
262                         },
263                         to: {
264                             y: box.y,
265                             width: box.width + 'px',
266                             height: box.height + 'px'
267                         }
268                     };
269                     elStyle.bottom = '0px';
270                     break;
271             }
272
273             wrap.show();
274             wrapAnim = Ext.apply({}, obj);
275             delete wrapAnim.listeners;
276             wrapAnim = Ext.create('Ext.fx.Anim', Ext.applyIf(wrapAnim, {
277                 target: wrap,
278                 duration: 500,
279                 easing: 'ease-out',
280                 from: slideOut ? anim.to : anim.from,
281                 to: slideOut ? anim.from : anim.to
282             }));
283
284             // In the absence of a callback, this listener MUST be added first
285             wrapAnim.on('afteranimate', function() {
286                 if (slideOut) {
287                     me.setPositioning(position);
288                     if (obj.useDisplay) {
289                         me.setDisplayed(false);
290                     } else {
291                         me.hide();   
292                     }
293                 }
294                 else {
295                     me.clearPositioning();
296                     me.setPositioning(position);
297                 }
298                 if (wrap.dom) {
299                     wrap.dom.parentNode.insertBefore(me.dom, wrap.dom); 
300                     wrap.remove();
301                 }
302                 me.setSize(box.width, box.height);
303                 animScope.end();
304             });
305             // Add configured listeners after
306             if (listeners) {
307                 wrapAnim.on(listeners);
308             }
309         };
310
311         me.animate({
312             duration: obj.duration ? obj.duration * 2 : 1000,
313             listeners: {
314                 beforeanimate: {
315                     fn: beforeAnim
316                 },
317                 afteranimate: {
318                     fn: function() {
319                         if (wrapAnim && wrapAnim.running) {
320                             wrapAnim.end();
321                         }
322                     }
323                 }
324             }
325         });
326         return me;
327     },
328
329     
330     /**
331      * Slides the element out of view.  An anchor point can be optionally passed to set the end point
332      * for the slide effect.  When the effect is completed, the element will be hidden (visibility = 
333      * 'hidden') but block elements will still take up space in the document.  The element must be removed
334      * from the DOM using the 'remove' config option if desired.  This function automatically handles 
335      * wrapping the element with a fixed-size container if needed.  See the Fx class overview for valid anchor point options.
336      * Usage:
337      *<pre><code>
338 // default: slide the element out to the top
339 el.slideOut();
340
341 // custom: slide the element out to the right with a 2-second duration
342 el.slideOut('r', { duration: 2 });
343
344 // common config options shown with default values
345 el.slideOut('t', {
346     easing: 'easeOut',
347     duration: 500,
348     remove: false,
349     useDisplay: false
350 });
351 </code></pre>
352      * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
353      * @param {Object} options (optional) Object literal with any of the Fx config options
354      * @return {Ext.core.Element} The Element
355      */
356     slideOut: function(anchor, o) {
357         return this.slideIn(anchor, o, true);
358     },
359
360     /**
361      * Fades the element out while slowly expanding it in all directions.  When the effect is completed, the 
362      * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
363      * Usage:
364      *<pre><code>
365 // default
366 el.puff();
367
368 // common config options shown with default values
369 el.puff({
370     easing: 'easeOut',
371     duration: 500,
372     useDisplay: false
373 });
374 </code></pre>
375      * @param {Object} options (optional) Object literal with any of the Fx config options
376      * @return {Ext.core.Element} The Element
377      */
378
379     puff: function(obj) {
380         var me = this,
381             beforeAnim;
382         obj = Ext.applyIf(obj || {}, {
383             easing: 'ease-out',
384             duration: 500,
385             useDisplay: false
386         });
387
388         beforeAnim = function() {
389             me.clearOpacity();
390             me.show();
391
392             var box = me.getBox(),
393                 fontSize = me.getStyle('fontSize'),
394                 position = me.getPositioning();
395             this.to = {
396                 width: box.width * 2,
397                 height: box.height * 2,
398                 x: box.x - (box.width / 2),
399                 y: box.y - (box.height /2),
400                 opacity: 0,
401                 fontSize: '200%'
402             };
403             this.on('afteranimate',function() {
404                 if (me.dom) {
405                     if (obj.useDisplay) {
406                         me.setDisplayed(false);
407                     } else {
408                         me.hide();
409                     }
410                     me.clearOpacity();  
411                     me.setPositioning(position);
412                     me.setStyle({fontSize: fontSize});
413                 }
414             });
415         };
416
417         me.animate({
418             duration: obj.duration,
419             easing: obj.easing,
420             listeners: {
421                 beforeanimate: {
422                     fn: beforeAnim
423                 }
424             }
425         });
426         return me;
427     },
428
429     /**
430      * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
431      * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still 
432      * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
433      * Usage:
434      *<pre><code>
435 // default
436 el.switchOff();
437
438 // all config options shown with default values
439 el.switchOff({
440     easing: 'easeIn',
441     duration: .3,
442     remove: false,
443     useDisplay: false
444 });
445 </code></pre>
446      * @param {Object} options (optional) Object literal with any of the Fx config options
447      * @return {Ext.core.Element} The Element
448      */
449     switchOff: function(obj) {
450         var me = this,
451             beforeAnim;
452         
453         obj = Ext.applyIf(obj || {}, {
454             easing: 'ease-in',
455             duration: 500,
456             remove: false,
457             useDisplay: false
458         });
459
460         beforeAnim = function() {
461             var animScope = this,
462                 size = me.getSize(),
463                 xy = me.getXY(),
464                 keyframe, position;
465             me.clearOpacity();
466             me.clip();
467             position = me.getPositioning();
468
469             keyframe = Ext.create('Ext.fx.Animator', {
470                 target: me,
471                 duration: obj.duration,
472                 easing: obj.easing,
473                 keyframes: {
474                     33: {
475                         opacity: 0.3
476                     },
477                     66: {
478                         height: 1,
479                         y: xy[1] + size.height / 2
480                     },
481                     100: {
482                         width: 1,
483                         x: xy[0] + size.width / 2
484                     }
485                 }
486             });
487             keyframe.on('afteranimate', function() {
488                 if (obj.useDisplay) {
489                     me.setDisplayed(false);
490                 } else {
491                     me.hide();
492                 }  
493                 me.clearOpacity();
494                 me.setPositioning(position);
495                 me.setSize(size);
496                 animScope.end();
497             });
498         };
499         me.animate({
500             duration: (obj.duration * 2),
501             listeners: {
502                 beforeanimate: {
503                     fn: beforeAnim
504                 }
505             }
506         });
507         return me;
508     },
509
510    /**
511     * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
512     * Usage:
513 <pre><code>
514 // default: a single light blue ripple
515 el.frame();
516
517 // custom: 3 red ripples lasting 3 seconds total
518 el.frame("#ff0000", 3, { duration: 3 });
519
520 // common config options shown with default values
521 el.frame("#C3DAF9", 1, {
522     duration: 1 //duration of each individual ripple.
523     // Note: Easing is not configurable and will be ignored if included
524 });
525 </code></pre>
526     * @param {String} color (optional) The color of the border.  Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
527     * @param {Number} count (optional) The number of ripples to display (defaults to 1)
528     * @param {Object} options (optional) Object literal with any of the Fx config options
529     * @return {Ext.core.Element} The Element
530     */
531     frame : function(color, count, obj){
532         var me = this,
533             beforeAnim;
534
535         color = color || '#C3DAF9';
536         count = count || 1;
537         obj = obj || {};
538
539         beforeAnim = function() {
540             me.show();
541             var animScope = this,
542                 box = me.getBox(),
543                 proxy = Ext.getBody().createChild({
544                     style: {
545                         position : 'absolute',
546                         'pointer-events': 'none',
547                         'z-index': 35000,
548                         border : '0px solid ' + color
549                     }
550                 }),
551                 proxyAnim;
552             proxyAnim = Ext.create('Ext.fx.Anim', {
553                 target: proxy,
554                 duration: obj.duration || 1000,
555                 iterations: count,
556                 from: {
557                     top: box.y,
558                     left: box.x,
559                     borderWidth: 0,
560                     opacity: 1,
561                     height: box.height,
562                     width: box.width
563                 },
564                 to: {
565                     top: box.y - 20,
566                     left: box.x - 20,
567                     borderWidth: 10,
568                     opacity: 0,
569                     height: box.height + 40,
570                     width: box.width + 40
571                 }
572             });
573             proxyAnim.on('afteranimate', function() {
574                 proxy.remove();
575                 animScope.end();
576             });
577         };
578
579         me.animate({
580             duration: (obj.duration * 2) || 2000,
581             listeners: {
582                 beforeanimate: {
583                     fn: beforeAnim
584                 }
585             }
586         });
587         return me;
588     },
589
590     /**
591      * Slides the element while fading it out of view.  An anchor point can be optionally passed to set the 
592      * ending point of the effect.
593      * Usage:
594      *<pre><code>
595 // default: slide the element downward while fading out
596 el.ghost();
597
598 // custom: slide the element out to the right with a 2-second duration
599 el.ghost('r', { duration: 2 });
600
601 // common config options shown with default values
602 el.ghost('b', {
603     easing: 'easeOut',
604     duration: 500
605 });
606 </code></pre>
607      * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
608      * @param {Object} options (optional) Object literal with any of the Fx config options
609      * @return {Ext.core.Element} The Element
610      */
611     ghost: function(anchor, obj) {
612         var me = this,
613             beforeAnim;
614
615         anchor = anchor || "b";
616         beforeAnim = function() {
617             var width = me.getWidth(),
618                 height = me.getHeight(),
619                 xy = me.getXY(),
620                 position = me.getPositioning(),
621                 to = {
622                     opacity: 0
623                 };
624             switch (anchor) {
625                 case 't':
626                     to.y = xy[1] - height;
627                     break;
628                 case 'l':
629                     to.x = xy[0] - width;
630                     break;
631                 case 'r':
632                     to.x = xy[0] + width;
633                     break;
634                 case 'b':
635                     to.y = xy[1] + height;
636                     break;
637                 case 'tl':
638                     to.x = xy[0] - width;
639                     to.y = xy[1] - height;
640                     break;
641                 case 'bl':
642                     to.x = xy[0] - width;
643                     to.y = xy[1] + height;
644                     break;
645                 case 'br':
646                     to.x = xy[0] + width;
647                     to.y = xy[1] + height;
648                     break;
649                 case 'tr':
650                     to.x = xy[0] + width;
651                     to.y = xy[1] - height;
652                     break;
653             }
654             this.to = to;
655             this.on('afteranimate', function () {
656                 if (me.dom) {
657                     me.hide();
658                     me.clearOpacity();
659                     me.setPositioning(position);
660                 }
661             });
662         };
663
664         me.animate(Ext.applyIf(obj || {}, {
665             duration: 500,
666             easing: 'ease-out',
667             listeners: {
668                 beforeanimate: {
669                     fn: beforeAnim
670                 }
671             }
672         }));
673         return me;
674     },
675
676     /**
677      * Highlights the Element by setting a color (applies to the background-color by default, but can be
678      * changed using the "attr" config option) and then fading back to the original color. If no original
679      * color is available, you should provide the "endColor" config option which will be cleared after the animation.
680      * Usage:
681 <pre><code>
682 // default: highlight background to yellow
683 el.highlight();
684
685 // custom: highlight foreground text to blue for 2 seconds
686 el.highlight("0000ff", { attr: 'color', duration: 2 });
687
688 // common config options shown with default values
689 el.highlight("ffff9c", {
690     attr: "backgroundColor", //can be any valid CSS property (attribute) that supports a color value
691     endColor: (current color) or "ffffff",
692     easing: 'easeIn',
693     duration: 1000
694 });
695 </code></pre>
696      * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
697      * @param {Object} options (optional) Object literal with any of the Fx config options
698      * @return {Ext.core.Element} The Element
699      */ 
700     highlight: function(color, o) {
701         var me = this,
702             dom = me.dom,
703             from = {},
704             restore, to, attr, lns, event, fn;
705
706         o = o || {};
707         lns = o.listeners || {};
708         attr = o.attr || 'backgroundColor';
709         from[attr] = color || 'ffff9c';
710         
711         if (!o.to) {
712             to = {};
713             to[attr] = o.endColor || me.getColor(attr, 'ffffff', '');
714         }
715         else {
716             to = o.to;
717         }
718         
719         // Don't apply directly on lns, since we reference it in our own callbacks below
720         o.listeners = Ext.apply(Ext.apply({}, lns), {
721             beforeanimate: function() {
722                 restore = dom.style[attr];
723                 me.clearOpacity();
724                 me.show();
725                 
726                 event = lns.beforeanimate;
727                 if (event) {
728                     fn = event.fn || event;
729                     return fn.apply(event.scope || lns.scope || window, arguments);
730                 }
731             },
732             afteranimate: function() {
733                 if (dom) {
734                     dom.style[attr] = restore;
735                 }
736                 
737                 event = lns.afteranimate;
738                 if (event) {
739                     fn = event.fn || event;
740                     fn.apply(event.scope || lns.scope || window, arguments);
741                 }
742             }
743         });
744
745         me.animate(Ext.apply({}, o, {
746             duration: 1000,
747             easing: 'ease-in',
748             from: from,
749             to: to
750         }));
751         return me;
752     },
753
754    /**
755     * @deprecated 4.0
756     * Creates a pause before any subsequent queued effects begin.  If there are
757     * no effects queued after the pause it will have no effect.
758     * Usage:
759 <pre><code>
760 el.pause(1);
761 </code></pre>
762     * @param {Number} seconds The length of time to pause (in seconds)
763     * @return {Ext.Element} The Element
764     */
765     pause: function(ms) {
766         var me = this;
767         Ext.fx.Manager.setFxDefaults(me.id, {
768             delay: ms
769         });
770         return me;
771     },
772
773    /**
774     * Fade an element in (from transparent to opaque).  The ending opacity can be specified
775     * using the <tt>{@link #endOpacity}</tt> config option.
776     * Usage:
777 <pre><code>
778 // default: fade in from opacity 0 to 100%
779 el.fadeIn();
780
781 // custom: fade in from opacity 0 to 75% over 2 seconds
782 el.fadeIn({ endOpacity: .75, duration: 2});
783
784 // common config options shown with default values
785 el.fadeIn({
786     endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
787     easing: 'easeOut',
788     duration: 500
789 });
790 </code></pre>
791     * @param {Object} options (optional) Object literal with any of the Fx config options
792     * @return {Ext.Element} The Element
793     */
794     fadeIn: function(o) {
795         this.animate(Ext.apply({}, o, {
796             opacity: 1
797         }));
798         return this;
799     },
800
801    /**
802     * Fade an element out (from opaque to transparent).  The ending opacity can be specified
803     * using the <tt>{@link #endOpacity}</tt> config option.  Note that IE may require
804     * <tt>{@link #useDisplay}:true</tt> in order to redisplay correctly.
805     * Usage:
806 <pre><code>
807 // default: fade out from the element's current opacity to 0
808 el.fadeOut();
809
810 // custom: fade out from the element's current opacity to 25% over 2 seconds
811 el.fadeOut({ endOpacity: .25, duration: 2});
812
813 // common config options shown with default values
814 el.fadeOut({
815     endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
816     easing: 'easeOut',
817     duration: 500,
818     remove: false,
819     useDisplay: false
820 });
821 </code></pre>
822     * @param {Object} options (optional) Object literal with any of the Fx config options
823     * @return {Ext.Element} The Element
824     */
825     fadeOut: function(o) {
826         this.animate(Ext.apply({}, o, {
827             opacity: 0
828         }));
829         return this;
830     },
831
832    /**
833     * @deprecated 4.0
834     * Animates the transition of an element's dimensions from a starting height/width
835     * to an ending height/width.  This method is a convenience implementation of {@link shift}.
836     * Usage:
837 <pre><code>
838 // change height and width to 100x100 pixels
839 el.scale(100, 100);
840
841 // common config options shown with default values.  The height and width will default to
842 // the element&#39;s existing values if passed as null.
843 el.scale(
844     [element&#39;s width],
845     [element&#39;s height], {
846         easing: 'easeOut',
847         duration: .35
848     }
849 );
850 </code></pre>
851     * @param {Number} width  The new width (pass undefined to keep the original width)
852     * @param {Number} height  The new height (pass undefined to keep the original height)
853     * @param {Object} options (optional) Object literal with any of the Fx config options
854     * @return {Ext.Element} The Element
855     */
856     scale: function(w, h, o) {
857         this.animate(Ext.apply({}, o, {
858             width: w,
859             height: h
860         }));
861         return this;
862     },
863
864    /**
865     * @deprecated 4.0
866     * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
867     * Any of these properties not specified in the config object will not be changed.  This effect 
868     * requires that at least one new dimension, position or opacity setting must be passed in on
869     * the config object in order for the function to have any effect.
870     * Usage:
871 <pre><code>
872 // slide the element horizontally to x position 200 while changing the height and opacity
873 el.shift({ x: 200, height: 50, opacity: .8 });
874
875 // common config options shown with default values.
876 el.shift({
877     width: [element&#39;s width],
878     height: [element&#39;s height],
879     x: [element&#39;s x position],
880     y: [element&#39;s y position],
881     opacity: [element&#39;s opacity],
882     easing: 'easeOut',
883     duration: .35
884 });
885 </code></pre>
886     * @param {Object} options  Object literal with any of the Fx config options
887     * @return {Ext.Element} The Element
888     */
889     shift: function(config) {
890         this.animate(config);
891         return this;
892     }
893 });