source: trunk/web/addons/job_monarch/lib/extjs/source/core/Fx.js @ 619

Last change on this file since 619 was 619, checked in by ramonb, 15 years ago

lib/:

  • added new AJAX dependancies: ExtJS, pChart, Lightbox2
File size: 34.2 KB
Line 
1/*
2 * Ext JS Library 2.2.1
3 * Copyright(c) 2006-2009, Ext JS, LLC.
4 * licensing@extjs.com
5 *
6 * http://extjs.com/license
7 */
8
9
10//Notifies Element that fx methods are available
11Ext.enableFx = true;
12
13/**
14 * @class Ext.Fx
15 * <p>A class to provide basic animation and visual effects support.  <b>Note:</b> This class is automatically applied
16 * to the {@link Ext.Element} interface when included, so all effects calls should be performed via Element.
17 * Conversely, since the effects are not actually defined in Element, Ext.Fx <b>must</b> be included in order for the
18 * Element effects to work.</p><br/>
19 *
20 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
21 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
22 * method chain.  The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
23 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately.  For this reason,
24 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
25 * expected results and should be done with care.</p><br/>
26 *
27 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
28 * that will serve as either the start or end point of the animation.  Following are all of the supported anchor positions:</p>
29<pre>
30Value  Description
31-----  -----------------------------
32tl     The top left corner
33t      The center of the top edge
34tr     The top right corner
35l      The center of the left edge
36r      The center of the right edge
37bl     The bottom left corner
38b      The center of the bottom edge
39br     The bottom right corner
40</pre>
41 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
42 * below are common options that can be passed to any Fx method.</b>
43 *
44 * @cfg {Function} callback A function called when the effect is finished.  Note that effects are queued internally by the
45 * Fx class, so do not need to use the callback parameter to specify another effect -- effects can simply be chained together
46 * and called in sequence (e.g., el.slideIn().highlight();).  The callback is intended for any additional code that should
47 * run once a particular effect has completed. The Element being operated upon is passed as the first parameter.
48 * @cfg {Object} scope The scope of the effect function
49 * @cfg {String} easing A valid Easing value for the effect
50 * @cfg {String} afterCls A css class to apply after the effect
51 * @cfg {Number} duration The length of time (in seconds) that the effect should last
52 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
53 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
54 * effects that end with the element being visually hidden, ignored otherwise)
55 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
56 * a function which returns such a specification that will be applied to the Element after the effect finishes
57 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
58 * @cfg {Boolean} concurrent Whether to allow subsequently-queued effects to run at the same time as the current effect, or to ensure that they run in sequence
59 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
60 */
61Ext.Fx = {
62        /**
63         * Slides the element into view.  An anchor point can be optionally passed to set the point of
64         * origin for the slide effect.  This function automatically handles wrapping the element with
65         * a fixed-size container if needed.  See the Fx class overview for valid anchor point options.
66         * Usage:
67         *<pre><code>
68// default: slide the element in from the top
69el.slideIn();
70
71// custom: slide the element in from the right with a 2-second duration
72el.slideIn('r', { duration: 2 });
73
74// common config options shown with default values
75el.slideIn('t', {
76    easing: 'easeOut',
77    duration: .5
78});
79</code></pre>
80         * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
81         * @param {Object} options (optional) Object literal with any of the Fx config options
82         * @return {Ext.Element} The Element
83         */
84    slideIn : function(anchor, o){
85        var el = this.getFxEl();
86        o = o || {};
87
88        el.queueFx(o, function(){
89
90            anchor = anchor || "t";
91
92            // fix display to visibility
93            this.fixDisplay();
94
95            // restore values after effect
96            var r = this.getFxRestore();
97            var b = this.getBox();
98            // fixed size for slide
99            this.setSize(b);
100
101            // wrap if needed
102            var wrap = this.fxWrap(r.pos, o, "hidden");
103
104            var st = this.dom.style;
105            st.visibility = "visible";
106            st.position = "absolute";
107
108            // clear out temp styles after slide and unwrap
109            var after = function(){
110                el.fxUnwrap(wrap, r.pos, o);
111                st.width = r.width;
112                st.height = r.height;
113                el.afterFx(o);
114            };
115            // time to calc the positions
116            var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
117
118            switch(anchor.toLowerCase()){
119                case "t":
120                    wrap.setSize(b.width, 0);
121                    st.left = st.bottom = "0";
122                    a = {height: bh};
123                break;
124                case "l":
125                    wrap.setSize(0, b.height);
126                    st.right = st.top = "0";
127                    a = {width: bw};
128                break;
129                case "r":
130                    wrap.setSize(0, b.height);
131                    wrap.setX(b.right);
132                    st.left = st.top = "0";
133                    a = {width: bw, points: pt};
134                break;
135                case "b":
136                    wrap.setSize(b.width, 0);
137                    wrap.setY(b.bottom);
138                    st.left = st.top = "0";
139                    a = {height: bh, points: pt};
140                break;
141                case "tl":
142                    wrap.setSize(0, 0);
143                    st.right = st.bottom = "0";
144                    a = {width: bw, height: bh};
145                break;
146                case "bl":
147                    wrap.setSize(0, 0);
148                    wrap.setY(b.y+b.height);
149                    st.right = st.top = "0";
150                    a = {width: bw, height: bh, points: pt};
151                break;
152                case "br":
153                    wrap.setSize(0, 0);
154                    wrap.setXY([b.right, b.bottom]);
155                    st.left = st.top = "0";
156                    a = {width: bw, height: bh, points: pt};
157                break;
158                case "tr":
159                    wrap.setSize(0, 0);
160                    wrap.setX(b.x+b.width);
161                    st.left = st.bottom = "0";
162                    a = {width: bw, height: bh, points: pt};
163                break;
164            }
165            this.dom.style.visibility = "visible";
166            wrap.show();
167
168            arguments.callee.anim = wrap.fxanim(a,
169                o,
170                'motion',
171                .5,
172                'easeOut', after);
173        });
174        return this;
175    },
176   
177        /**
178         * Slides the element out of view.  An anchor point can be optionally passed to set the end point
179         * for the slide effect.  When the effect is completed, the element will be hidden (visibility =
180         * 'hidden') but block elements will still take up space in the document.  The element must be removed
181         * from the DOM using the 'remove' config option if desired.  This function automatically handles
182         * wrapping the element with a fixed-size container if needed.  See the Fx class overview for valid anchor point options.
183         * Usage:
184         *<pre><code>
185// default: slide the element out to the top
186el.slideOut();
187
188// custom: slide the element out to the right with a 2-second duration
189el.slideOut('r', { duration: 2 });
190
191// common config options shown with default values
192el.slideOut('t', {
193    easing: 'easeOut',
194    duration: .5,
195    remove: false,
196    useDisplay: false
197});
198</code></pre>
199         * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
200         * @param {Object} options (optional) Object literal with any of the Fx config options
201         * @return {Ext.Element} The Element
202         */
203    slideOut : function(anchor, o){
204        var el = this.getFxEl();
205        o = o || {};
206
207        el.queueFx(o, function(){
208
209            anchor = anchor || "t";
210
211            // restore values after effect
212            var r = this.getFxRestore();
213           
214            var b = this.getBox();
215            // fixed size for slide
216            this.setSize(b);
217
218            // wrap if needed
219            var wrap = this.fxWrap(r.pos, o, "visible");
220
221            var st = this.dom.style;
222            st.visibility = "visible";
223            st.position = "absolute";
224
225            wrap.setSize(b);
226
227            var after = function(){
228                if(o.useDisplay){
229                    el.setDisplayed(false);
230                }else{
231                    el.hide();
232                }
233
234                el.fxUnwrap(wrap, r.pos, o);
235
236                st.width = r.width;
237                st.height = r.height;
238
239                el.afterFx(o);
240            };
241
242            var a, zero = {to: 0};
243            switch(anchor.toLowerCase()){
244                case "t":
245                    st.left = st.bottom = "0";
246                    a = {height: zero};
247                break;
248                case "l":
249                    st.right = st.top = "0";
250                    a = {width: zero};
251                break;
252                case "r":
253                    st.left = st.top = "0";
254                    a = {width: zero, points: {to:[b.right, b.y]}};
255                break;
256                case "b":
257                    st.left = st.top = "0";
258                    a = {height: zero, points: {to:[b.x, b.bottom]}};
259                break;
260                case "tl":
261                    st.right = st.bottom = "0";
262                    a = {width: zero, height: zero};
263                break;
264                case "bl":
265                    st.right = st.top = "0";
266                    a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
267                break;
268                case "br":
269                    st.left = st.top = "0";
270                    a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
271                break;
272                case "tr":
273                    st.left = st.bottom = "0";
274                    a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
275                break;
276            }
277
278            arguments.callee.anim = wrap.fxanim(a,
279                o,
280                'motion',
281                .5,
282                "easeOut", after);
283        });
284        return this;
285    },
286
287        /**
288         * Fades the element out while slowly expanding it in all directions.  When the effect is completed, the
289         * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
290         * The element must be removed from the DOM using the 'remove' config option if desired.
291         * Usage:
292         *<pre><code>
293// default
294el.puff();
295
296// common config options shown with default values
297el.puff({
298    easing: 'easeOut',
299    duration: .5,
300    remove: false,
301    useDisplay: false
302});
303</code></pre>
304         * @param {Object} options (optional) Object literal with any of the Fx config options
305         * @return {Ext.Element} The Element
306         */
307    puff : function(o){
308        var el = this.getFxEl();
309        o = o || {};
310
311        el.queueFx(o, function(){
312            this.clearOpacity();
313            this.show();
314
315            // restore values after effect
316            var r = this.getFxRestore();
317            var st = this.dom.style;
318
319            var after = function(){
320                if(o.useDisplay){
321                    el.setDisplayed(false);
322                }else{
323                    el.hide();
324                }
325
326                el.clearOpacity();
327
328                el.setPositioning(r.pos);
329                st.width = r.width;
330                st.height = r.height;
331                st.fontSize = '';
332                el.afterFx(o);
333            };
334
335            var width = this.getWidth();
336            var height = this.getHeight();
337
338            arguments.callee.anim = this.fxanim({
339                    width : {to: this.adjustWidth(width * 2)},
340                    height : {to: this.adjustHeight(height * 2)},
341                    points : {by: [-(width * .5), -(height * .5)]},
342                    opacity : {to: 0},
343                    fontSize: {to:200, unit: "%"}
344                },
345                o,
346                'motion',
347                .5,
348                "easeOut", after);
349        });
350        return this;
351    },
352
353        /**
354         * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
355         * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
356         * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
357         * Usage:
358         *<pre><code>
359// default
360el.switchOff();
361
362// all config options shown with default values
363el.switchOff({
364    easing: 'easeIn',
365    duration: .3,
366    remove: false,
367    useDisplay: false
368});
369</code></pre>
370         * @param {Object} options (optional) Object literal with any of the Fx config options
371         * @return {Ext.Element} The Element
372         */
373    switchOff : function(o){
374        var el = this.getFxEl();
375        o = o || {};
376
377        el.queueFx(o, function(){
378            this.clearOpacity();
379            this.clip();
380
381            // restore values after effect
382            var r = this.getFxRestore();
383            var st = this.dom.style;
384
385            var after = function(){
386                if(o.useDisplay){
387                    el.setDisplayed(false);
388                }else{
389                    el.hide();
390                }
391
392                el.clearOpacity();
393                el.setPositioning(r.pos);
394                st.width = r.width;
395                st.height = r.height;
396
397                el.afterFx(o);
398            };
399
400            this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
401                this.clearOpacity();
402                (function(){
403                    this.fxanim({
404                        height:{to:1},
405                        points:{by:[0, this.getHeight() * .5]}
406                    }, o, 'motion', 0.3, 'easeIn', after);
407                }).defer(100, this);
408            });
409        });
410        return this;
411    },
412
413    /**
414     * Highlights the Element by setting a color (applies to the background-color by default, but can be
415     * changed using the "attr" config option) and then fading back to the original color. If no original
416     * color is available, you should provide the "endColor" config option which will be cleared after the animation.
417     * Usage:
418<pre><code>
419// default: highlight background to yellow
420el.highlight();
421
422// custom: highlight foreground text to blue for 2 seconds
423el.highlight("0000ff", { attr: 'color', duration: 2 });
424
425// common config options shown with default values
426el.highlight("ffff9c", {
427    attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
428    endColor: (current color) or "ffffff",
429    easing: 'easeIn',
430    duration: 1
431});
432</code></pre>
433     * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
434     * @param {Object} options (optional) Object literal with any of the Fx config options
435     * @return {Ext.Element} The Element
436     */ 
437    highlight : function(color, o){
438        var el = this.getFxEl();
439        o = o || {};
440
441        el.queueFx(o, function(){
442            color = color || "ffff9c";
443            var attr = o.attr || "backgroundColor";
444
445            this.clearOpacity();
446            this.show();
447
448            var origColor = this.getColor(attr);
449            var restoreColor = this.dom.style[attr];
450            var endColor = (o.endColor || origColor) || "ffffff";
451
452            var after = function(){
453                el.dom.style[attr] = restoreColor;
454                el.afterFx(o);
455            };
456
457            var a = {};
458            a[attr] = {from: color, to: endColor};
459            arguments.callee.anim = this.fxanim(a,
460                o,
461                'color',
462                1,
463                'easeIn', after);
464        });
465        return this;
466    },
467
468   /**
469    * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
470    * Usage:
471<pre><code>
472// default: a single light blue ripple
473el.frame();
474
475// custom: 3 red ripples lasting 3 seconds total
476el.frame("ff0000", 3, { duration: 3 });
477
478// common config options shown with default values
479el.frame("C3DAF9", 1, {
480    duration: 1 //duration of each individual ripple.
481    // Note: Easing is not configurable and will be ignored if included
482});
483</code></pre>
484    * @param {String} color (optional) The color of the border.  Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
485    * @param {Number} count (optional) The number of ripples to display (defaults to 1)
486    * @param {Object} options (optional) Object literal with any of the Fx config options
487    * @return {Ext.Element} The Element
488    */
489    frame : function(color, count, o){
490        var el = this.getFxEl();
491        o = o || {};
492
493        el.queueFx(o, function(){
494            color = color || "#C3DAF9";
495            if(color.length == 6){
496                color = "#" + color;
497            }
498            count = count || 1;
499            var duration = o.duration || 1;
500            this.show();
501
502            var b = this.getBox();
503            var animFn = function(){
504                var proxy = Ext.getBody().createChild({
505                     style:{
506                        visbility:"hidden",
507                        position:"absolute",
508                        "z-index":"35000", // yee haw
509                        border:"0px solid " + color
510                     }
511                  });
512                var scale = Ext.isBorderBox ? 2 : 1;
513                proxy.animate({
514                    top:{from:b.y, to:b.y - 20},
515                    left:{from:b.x, to:b.x - 20},
516                    borderWidth:{from:0, to:10},
517                    opacity:{from:1, to:0},
518                    height:{from:b.height, to:(b.height + (20*scale))},
519                    width:{from:b.width, to:(b.width + (20*scale))}
520                }, duration, function(){
521                    proxy.remove();
522                    if(--count > 0){
523                         animFn();
524                    }else{
525                        el.afterFx(o);
526                    }
527                });
528            };
529            animFn.call(this);
530        });
531        return this;
532    },
533
534   /**
535    * Creates a pause before any subsequent queued effects begin.  If there are
536    * no effects queued after the pause it will have no effect.
537    * Usage:
538<pre><code>
539el.pause(1);
540</code></pre>
541    * @param {Number} seconds The length of time to pause (in seconds)
542    * @return {Ext.Element} The Element
543    */
544    pause : function(seconds){
545        var el = this.getFxEl();
546        var o = {};
547
548        el.queueFx(o, function(){
549            setTimeout(function(){
550                el.afterFx(o);
551            }, seconds * 1000);
552        });
553        return this;
554    },
555
556   /**
557    * Fade an element in (from transparent to opaque).  The ending opacity can be specified
558    * using the "endOpacity" config option.
559    * Usage:
560<pre><code>
561// default: fade in from opacity 0 to 100%
562el.fadeIn();
563
564// custom: fade in from opacity 0 to 75% over 2 seconds
565el.fadeIn({ endOpacity: .75, duration: 2});
566
567// common config options shown with default values
568el.fadeIn({
569    endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
570    easing: 'easeOut',
571    duration: .5
572});
573</code></pre>
574    * @param {Object} options (optional) Object literal with any of the Fx config options
575    * @return {Ext.Element} The Element
576    */
577    fadeIn : function(o){
578        var el = this.getFxEl();
579        o = o || {};
580        el.queueFx(o, function(){
581            this.setOpacity(0);
582            this.fixDisplay();
583            this.dom.style.visibility = 'visible';
584            var to = o.endOpacity || 1;
585            arguments.callee.anim = this.fxanim({opacity:{to:to}},
586                o, null, .5, "easeOut", function(){
587                if(to == 1){
588                    this.clearOpacity();
589                }
590                el.afterFx(o);
591            });
592        });
593        return this;
594    },
595
596   /**
597    * Fade an element out (from opaque to transparent).  The ending opacity can be specified
598    * using the "endOpacity" config option.  Note that IE may require useDisplay:true in order
599    * to redisplay correctly.
600    * Usage:
601<pre><code>
602// default: fade out from the element's current opacity to 0
603el.fadeOut();
604
605// custom: fade out from the element's current opacity to 25% over 2 seconds
606el.fadeOut({ endOpacity: .25, duration: 2});
607
608// common config options shown with default values
609el.fadeOut({
610    endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
611    easing: 'easeOut',
612    duration: .5,
613    remove: false,
614    useDisplay: false
615});
616</code></pre>
617    * @param {Object} options (optional) Object literal with any of the Fx config options
618    * @return {Ext.Element} The Element
619    */
620    fadeOut : function(o){
621        var el = this.getFxEl();
622        o = o || {};
623        el.queueFx(o, function(){
624            var to = o.endOpacity || 0;
625            arguments.callee.anim = this.fxanim({opacity:{to:to}},
626                o, null, .5, "easeOut", function(){
627                if(to === 0){
628                    if(this.visibilityMode == Ext.Element.DISPLAY || o.useDisplay){
629                         this.dom.style.display = "none";
630                    }else{
631                         this.dom.style.visibility = "hidden";
632                    }
633                    this.clearOpacity();
634                }
635                el.afterFx(o);
636            });
637        });
638        return this;
639    },
640
641   /**
642    * Animates the transition of an element's dimensions from a starting height/width
643    * to an ending height/width.
644    * Usage:
645<pre><code>
646// change height and width to 100x100 pixels
647el.scale(100, 100);
648
649// common config options shown with default values.  The height and width will default to
650// the element's existing values if passed as null.
651el.scale(
652    [element's width],
653    [element's height], {
654            easing: 'easeOut',
655            duration: .35
656        }
657);
658</code></pre>
659    * @param {Number} width  The new width (pass undefined to keep the original width)
660    * @param {Number} height  The new height (pass undefined to keep the original height)
661    * @param {Object} options (optional) Object literal with any of the Fx config options
662    * @return {Ext.Element} The Element
663    */
664    scale : function(w, h, o){
665        this.shift(Ext.apply({}, o, {
666            width: w,
667            height: h
668        }));
669        return this;
670    },
671
672   /**
673    * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
674    * Any of these properties not specified in the config object will not be changed.  This effect
675    * requires that at least one new dimension, position or opacity setting must be passed in on
676    * the config object in order for the function to have any effect.
677    * Usage:
678<pre><code>
679// slide the element horizontally to x position 200 while changing the height and opacity
680el.shift({ x: 200, height: 50, opacity: .8 });
681
682// common config options shown with default values.
683el.shift({
684    width: [element's width],
685    height: [element's height],
686    x: [element's x position],
687    y: [element's y position],
688    opacity: [element's opacity],
689    easing: 'easeOut',
690    duration: .35
691});
692</code></pre>
693    * @param {Object} options  Object literal with any of the Fx config options
694    * @return {Ext.Element} The Element
695    */
696    shift : function(o){
697        var el = this.getFxEl();
698        o = o || {};
699        el.queueFx(o, function(){
700            var a = {}, w = o.width, h = o.height, x = o.x, y = o.y,  op = o.opacity;
701            if(w !== undefined){
702                a.width = {to: this.adjustWidth(w)};
703            }
704            if(h !== undefined){
705                a.height = {to: this.adjustHeight(h)};
706            }
707            if(o.left !== undefined){
708                a.left = {to: o.left};
709            }
710            if(o.top !== undefined){
711                a.top = {to: o.top};
712            }
713            if(o.right !== undefined){
714                a.right = {to: o.right};
715            }
716            if(o.bottom !== undefined){
717                a.bottom = {to: o.bottom};
718            }
719            if(x !== undefined || y !== undefined){
720                a.points = {to: [
721                    x !== undefined ? x : this.getX(),
722                    y !== undefined ? y : this.getY()
723                ]};
724            }
725            if(op !== undefined){
726                a.opacity = {to: op};
727            }
728            if(o.xy !== undefined){
729                a.points = {to: o.xy};
730            }
731            arguments.callee.anim = this.fxanim(a,
732                o, 'motion', .35, "easeOut", function(){
733                el.afterFx(o);
734            });
735        });
736        return this;
737    },
738
739        /**
740         * Slides the element while fading it out of view.  An anchor point can be optionally passed to set the
741         * ending point of the effect.
742         * Usage:
743         *<pre><code>
744// default: slide the element downward while fading out
745el.ghost();
746
747// custom: slide the element out to the right with a 2-second duration
748el.ghost('r', { duration: 2 });
749
750// common config options shown with default values
751el.ghost('b', {
752    easing: 'easeOut',
753    duration: .5,
754    remove: false,
755    useDisplay: false
756});
757</code></pre>
758         * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
759         * @param {Object} options (optional) Object literal with any of the Fx config options
760         * @return {Ext.Element} The Element
761         */
762    ghost : function(anchor, o){
763        var el = this.getFxEl();
764        o = o || {};
765
766        el.queueFx(o, function(){
767            anchor = anchor || "b";
768
769            // restore values after effect
770            var r = this.getFxRestore();
771            var w = this.getWidth(),
772                h = this.getHeight();
773
774            var st = this.dom.style;
775
776            var after = function(){
777                if(o.useDisplay){
778                    el.setDisplayed(false);
779                }else{
780                    el.hide();
781                }
782
783                el.clearOpacity();
784                el.setPositioning(r.pos);
785                st.width = r.width;
786                st.height = r.height;
787
788                el.afterFx(o);
789            };
790
791            var a = {opacity: {to: 0}, points: {}}, pt = a.points;
792            switch(anchor.toLowerCase()){
793                case "t":
794                    pt.by = [0, -h];
795                break;
796                case "l":
797                    pt.by = [-w, 0];
798                break;
799                case "r":
800                    pt.by = [w, 0];
801                break;
802                case "b":
803                    pt.by = [0, h];
804                break;
805                case "tl":
806                    pt.by = [-w, -h];
807                break;
808                case "bl":
809                    pt.by = [-w, h];
810                break;
811                case "br":
812                    pt.by = [w, h];
813                break;
814                case "tr":
815                    pt.by = [w, -h];
816                break;
817            }
818
819            arguments.callee.anim = this.fxanim(a,
820                o,
821                'motion',
822                .5,
823                "easeOut", after);
824        });
825        return this;
826    },
827
828        /**
829         * Ensures that all effects queued after syncFx is called on the element are
830         * run concurrently.  This is the opposite of {@link #sequenceFx}.
831         * @return {Ext.Element} The Element
832         */
833    syncFx : function(){
834        this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
835            block : false,
836            concurrent : true,
837            stopFx : false
838        });
839        return this;
840    },
841
842        /**
843         * Ensures that all effects queued after sequenceFx is called on the element are
844         * run in sequence.  This is the opposite of {@link #syncFx}.
845         * @return {Ext.Element} The Element
846         */
847    sequenceFx : function(){
848        this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
849            block : false,
850            concurrent : false,
851            stopFx : false
852        });
853        return this;
854    },
855
856        /* @private */
857    nextFx : function(){
858        var ef = this.fxQueue[0];
859        if(ef){
860            ef.call(this);
861        }
862    },
863
864        /**
865         * Returns true if the element has any effects actively running or queued, else returns false.
866         * @return {Boolean} True if element has active effects, else false
867         */
868    hasActiveFx : function(){
869        return this.fxQueue && this.fxQueue[0];
870    },
871
872        /**
873         * Stops any running effects and clears the element's internal effects queue if it contains
874         * any additional effects that haven't started yet.
875         * @return {Ext.Element} The Element
876         */
877    stopFx : function(){
878        if(this.hasActiveFx()){
879            var cur = this.fxQueue[0];
880            if(cur && cur.anim && cur.anim.isAnimated()){
881                this.fxQueue = [cur]; // clear out others
882                cur.anim.stop(true);
883            }
884        }
885        return this;
886    },
887
888        /* @private */
889    beforeFx : function(o){
890        if(this.hasActiveFx() && !o.concurrent){
891           if(o.stopFx){
892               this.stopFx();
893               return true;
894           }
895           return false;
896        }
897        return true;
898    },
899
900        /**
901         * Returns true if the element is currently blocking so that no other effect can be queued
902         * until this effect is finished, else returns false if blocking is not set.  This is commonly
903         * used to ensure that an effect initiated by a user action runs to completion prior to the
904         * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
905         * @return {Boolean} True if blocking, else false
906         */
907    hasFxBlock : function(){
908        var q = this.fxQueue;
909        return q && q[0] && q[0].block;
910    },
911
912        /* @private */
913    queueFx : function(o, fn){
914        if(!this.fxQueue){
915            this.fxQueue = [];
916        }
917        if(!this.hasFxBlock()){
918            Ext.applyIf(o, this.fxDefaults);
919            if(!o.concurrent){
920                var run = this.beforeFx(o);
921                fn.block = o.block;
922                this.fxQueue.push(fn);
923                if(run){
924                    this.nextFx();
925                }
926            }else{
927                fn.call(this);
928            }
929        }
930        return this;
931    },
932
933        /* @private */
934    fxWrap : function(pos, o, vis){
935        var wrap;
936        if(!o.wrap || !(wrap = Ext.get(o.wrap))){
937            var wrapXY;
938            if(o.fixPosition){
939                wrapXY = this.getXY();
940            }
941            var div = document.createElement("div");
942            div.style.visibility = vis;
943            wrap = Ext.get(this.dom.parentNode.insertBefore(div, this.dom));
944            wrap.setPositioning(pos);
945            if(wrap.getStyle("position") == "static"){
946                wrap.position("relative");
947            }
948            this.clearPositioning('auto');
949            wrap.clip();
950            wrap.dom.appendChild(this.dom);
951            if(wrapXY){
952                wrap.setXY(wrapXY);
953            }
954        }
955        return wrap;
956    },
957
958        /* @private */
959    fxUnwrap : function(wrap, pos, o){
960        this.clearPositioning();
961        this.setPositioning(pos);
962        if(!o.wrap){
963            wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
964            wrap.remove();
965        }
966    },
967
968        /* @private */
969    getFxRestore : function(){
970        var st = this.dom.style;
971        return {pos: this.getPositioning(), width: st.width, height : st.height};
972    },
973
974        /* @private */
975    afterFx : function(o){
976        if(o.afterStyle){
977            this.applyStyles(o.afterStyle);
978        }
979        if(o.afterCls){
980            this.addClass(o.afterCls);
981        }
982        if(o.remove === true){
983            this.remove();
984        }
985        Ext.callback(o.callback, o.scope, [this]);
986        if(!o.concurrent){
987            this.fxQueue.shift();
988            this.nextFx();
989        }
990    },
991
992        /* @private */
993    getFxEl : function(){ // support for composite element fx
994        return Ext.get(this.dom);
995    },
996
997        /* @private */
998    fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
999        animType = animType || 'run';
1000        opt = opt || {};
1001        var anim = Ext.lib.Anim[animType](
1002            this.dom, args,
1003            (opt.duration || defaultDur) || .35,
1004            (opt.easing || defaultEase) || 'easeOut',
1005            function(){
1006                Ext.callback(cb, this);
1007            },
1008            this
1009        );
1010        opt.anim = anim;
1011        return anim;
1012    }
1013};
1014
1015// backwords compat
1016Ext.Fx.resize = Ext.Fx.scale;
1017
1018//When included, Ext.Fx is automatically applied to Element so that all basic
1019//effects are available directly via the Element API
1020Ext.apply(Ext.Element.prototype, Ext.Fx);
Note: See TracBrowser for help on using the repository browser.