]> source.dussan.org Git - jquery-ui.git/commitdiff
Effects: Rewrite
authorMike Sherov <mike.sherov@gmail.com>
Wed, 26 Dec 2012 13:35:42 +0000 (08:35 -0500)
committerMike Sherov <mike.sherov@gmail.com>
Wed, 10 Dec 2014 21:58:38 +0000 (16:58 -0500)
1. Introduces a set of helper methods to easily create and define new effects.
2. Uses clip animations and placeholders instead of wrappers for clip effects.
3. Ensures all animations are detectable as animated

Fixes #10599
Fixes #9477
Fixes #9257
Fixes #9066
Fixes #8867
Fixes #8671
Fixes #8505
Fixes #7885
Fixes #7041

Closes gh-1017

31 files changed:
demos/effect/addClass.html
demos/effect/animate.html
demos/effect/default.html
demos/effect/hide.html
demos/effect/show.html
demos/effect/switchClass.html
demos/effect/toggle.html
tests/unit/effects/effects.html
tests/unit/effects/effects_core.js
tests/unit/effects/effects_scale.js
tests/visual/effects/all.html
tests/visual/effects/clip.html
tests/visual/effects/effects.js
tests/visual/effects/image.png [new file with mode: 0644]
tests/visual/index.html
ui/effect-blind.js
ui/effect-bounce.js
ui/effect-clip.js
ui/effect-drop.js
ui/effect-explode.js
ui/effect-fade.js
ui/effect-fold.js
ui/effect-highlight.js
ui/effect-puff.js
ui/effect-pulsate.js
ui/effect-scale.js
ui/effect-shake.js
ui/effect-size.js
ui/effect-slide.js
ui/effect-transfer.js
ui/effect.js

index f594291fe08152f94c665c9db5ac27ce67f70782..0aab17304e1558f176b773b4fabeb08570633b99 100644 (file)
@@ -10,8 +10,8 @@
        <style>
                .toggler { width: 500px; height: 200px; position: relative; }
                #button { padding: .5em 1em; text-decoration: none; }
-               #effect { width: 240px;  padding: 1em;  font-size: 1.2em; border: 1px solid #000; background: #eee; color: #333; }
-               .newClass { text-indent: 40px; letter-spacing: .4em; width: 410px; height: 100px; padding: 30px; margin: 10px; font-size: 1.6em; }
+               #effect { width: 240px;  padding: 1em; border: 1px solid #000; background: #eee; color: #333; }
+               .newClass { text-indent: 40px; letter-spacing: .4em; width: 410px; height: 120px; padding: 30px; margin: 10px; font-size: 1.1em; }
        </style>
        <script>
        $(function() {
index 41f969982c8eb40543ebf07eb04be5b2723423a0..7de5351143d82944a3da17f02430ea55d538d227 100644 (file)
@@ -10,7 +10,7 @@
        <style>
                .toggler { width: 500px; height: 200px; position: relative; }
                #button { padding: .5em 1em; text-decoration: none; }
-               #effect { width: 240px; height: 135px; padding: 0.4em; position: relative; background: #fff; }
+               #effect { width: 240px; height: 170px; padding: 0.4em; position: relative; background: #fff; }
                #effect h3 { margin: 0; padding: 0.4em; text-align: center; }
        </style>
        <script>
index aff19783f6273206f17609d670ea5ac8e7e22508..f2a6b768667fb3ac3c6aca6446ba1f86fd4db4b2 100644 (file)
@@ -25,7 +25,7 @@
        <style>
                .toggler { width: 500px; height: 200px; position: relative; }
                #button { padding: .5em 1em; text-decoration: none; }
-               #effect { width: 240px; height: 135px; padding: 0.4em; position: relative; }
+               #effect { width: 240px; height: 170px; padding: 0.4em; position: relative; }
                #effect h3 { margin: 0; padding: 0.4em; text-align: center; }
                .ui-effects-transfer { border: 2px dotted gray; }
        </style>
@@ -40,7 +40,7 @@
                        var options = {};
                        // some effects have required parameters
                        if ( selectedEffect === "scale" ) {
-                               options = { percent: 0 };
+                               options = { percent: 50 };
                        } else if ( selectedEffect === "transfer" ) {
                                options = { to: "#button", className: "ui-effects-transfer" };
                        } else if ( selectedEffect === "size" ) {
index 6c9948aabb690f0a9214b4e68b5b7e409eee93c9..301f93047cf18e5d67fec06d54413b4b2dd5dafc 100644 (file)
@@ -11,6 +11,7 @@
        <script src="../../ui/effect-clip.js"></script>
        <script src="../../ui/effect-drop.js"></script>
        <script src="../../ui/effect-explode.js"></script>
+       <script src="../../ui/effect-fade.js"></script>
        <script src="../../ui/effect-fold.js"></script>
        <script src="../../ui/effect-highlight.js"></script>
        <script src="../../ui/effect-puff.js"></script>
@@ -23,7 +24,7 @@
        <style>
        .toggler { width: 500px; height: 200px; }
        #button { padding: .5em 1em; text-decoration: none; }
-       #effect { width: 240px; height: 135px; padding: 0.4em; position: relative; }
+       #effect { width: 240px; height: 170px; padding: 0.4em; position: relative; }
        #effect h3 { margin: 0; padding: 0.4em; text-align: center; }
        </style>
        <script>
@@ -37,7 +38,7 @@
                        var options = {};
                        // some effects have required parameters
                        if ( selectedEffect === "scale" ) {
-                               options = { percent: 0 };
+                               options = { percent: 50 };
                        } else if ( selectedEffect === "size" ) {
                                options = { to: { width: 200, height: 60 } };
                        }
@@ -77,6 +78,7 @@
        <option value="clip">Clip</option>
        <option value="drop">Drop</option>
        <option value="explode">Explode</option>
+       <option value="fade">Fade</option>
        <option value="fold">Fold</option>
        <option value="highlight">Highlight</option>
        <option value="puff">Puff</option>
index 445db04b934bd29656efc9bb4d67d7f164a70331..5583ff36fdc06480adec0cc96354a45bc9e9a769 100644 (file)
@@ -11,6 +11,7 @@
        <script src="../../ui/effect-clip.js"></script>
        <script src="../../ui/effect-drop.js"></script>
        <script src="../../ui/effect-explode.js"></script>
+       <script src="../../ui/effect-fade.js"></script>
        <script src="../../ui/effect-fold.js"></script>
        <script src="../../ui/effect-highlight.js"></script>
        <script src="../../ui/effect-puff.js"></script>
@@ -23,7 +24,7 @@
        <style>
        .toggler { width: 500px; height: 200px; }
        #button { padding: .5em 1em; text-decoration: none; }
-       #effect { width: 240px; height: 135px; padding: 0.4em; position: relative; }
+       #effect { width: 240px; height: 170px; padding: 0.4em; position: relative; }
        #effect h3 { margin: 0; padding: 0.4em; text-align: center; }
        </style>
        <script>
@@ -37,7 +38,7 @@
                        var options = {};
                        // some effects have required parameters
                        if ( selectedEffect === "scale" ) {
-                               options = { percent: 100 };
+                               options = { percent: 50 };
                        } else if ( selectedEffect === "size" ) {
                                options = { to: { width: 280, height: 185 } };
                        }
@@ -79,6 +80,7 @@
        <option value="clip">Clip</option>
        <option value="drop">Drop</option>
        <option value="explode">Explode</option>
+       <option value="fade">Fade</option>
        <option value="fold">Fold</option>
        <option value="highlight">Highlight</option>
        <option value="puff">Puff</option>
index 34af4715bd794d508c31a679d38947bb46dbc47b..0ac90fe93682843abfe61b1bcbe074abf3a8f9b3 100644 (file)
@@ -11,8 +11,8 @@
        .toggler { width: 500px; height: 200px; position: relative; }
        #button { padding: .5em 1em; text-decoration: none; }
        #effect { position: relative; }
-       .newClass { width: 240px;  padding: 1em; letter-spacing: 0; font-size: 1.2em; margin: 0; }
-       .anotherNewClass { text-indent: 40px; letter-spacing: .4em; width: 410px; height: 100px; padding: 30px; margin: 10px; font-size: 1.6em; }
+       .newClass { width: 240px;  padding: 1em; letter-spacing: 0; margin: 0; }
+       .anotherNewClass { text-indent: 40px; letter-spacing: .2em; width: 410px; height: 100px; padding: 30px; margin: 10px; font-size: 1.1em; }
        </style>
        <script>
        $(function() {
index 1a2cf0a1b3500391ef538ddc0360fa22e9121210..bac5758abccf36d86dd6c6128e46c6aa4f5ae8ac 100644 (file)
@@ -11,6 +11,7 @@
        <script src="../../ui/effect-clip.js"></script>
        <script src="../../ui/effect-drop.js"></script>
        <script src="../../ui/effect-explode.js"></script>
+       <script src="../../ui/effect-fade.js"></script>
        <script src="../../ui/effect-fold.js"></script>
        <script src="../../ui/effect-highlight.js"></script>
        <script src="../../ui/effect-puff.js"></script>
@@ -32,7 +33,7 @@
        #effect {
                position: relative;
                width: 240px;
-               height: 135px;
+               height: 170px;
                padding: 0.4em;
        }
        #effect h3 {
@@ -52,7 +53,7 @@
                        var options = {};
                        // some effects have required parameters
                        if ( selectedEffect === "scale" ) {
-                               options = { percent: 0 };
+                               options = { percent: 50 };
                        } else if ( selectedEffect === "size" ) {
                                options = { to: { width: 200, height: 60 } };
                        }
@@ -85,6 +86,7 @@
        <option value="clip">Clip</option>
        <option value="drop">Drop</option>
        <option value="explode">Explode</option>
+       <option value="fade">Fade</option>
        <option value="fold">Fold</option>
        <option value="highlight">Highlight</option>
        <option value="puff">Puff</option>
index d6cfdb7973be63516aa37bafd0e4a56b68aa8d8f..a092ce04bcf8e80849d55c6267bdedc613a2f5a7 100644 (file)
                width: 100px;
        }
 
+       .relative {
+               position: relative;
+               top: 0px;
+               left: 0px;
+       }
+       .absolute {
+               position: absolute;
+               top: 0px;
+               left: 0px;
+       }
+       .fixed {
+               position: fixed;
+               top: 0px;
+               left: 0px;
+       }
+       .static {
+               position: static;
+       }
+
        </style>
 </head>
 <body>
 
 <div id="qunit"></div>
 <div id="qunit-fixture">
-<div id="elem" class="test">
-</div>
-<div class="hidden test">
-       <div>.</div>
-</div>
-<div class="animateClass test">
-       <h2>Child Element Test</h2>
-</div>
-<div class="relWidth relHeight testAddBorder">
-       <h2>Slide with relative width</h2>
-</div>
-<div class="testScale">
-</div>
-<div class="ticket7106">
-</div>
-
+       <div id="elem" class="test"></div>
+       <div class="hidden test">
+               <div>.</div>
+       </div>
+       <div class="animateClass test">
+               <h2>Child Element Test</h2>
+       </div>
+       <div class="relWidth relHeight testAddBorder">
+               <h2>Slide with relative width</h2>
+       </div>
+       <div class="testScale"></div>
+       <div class="ticket7106"></div>
+       <div class="relative"></div>
+       <div class="absolute"></div>
+       <div class="fixed"></div>
+       <div class="static"></div>
 </div>
 </body>
 </html>
index 05db494e6af7fcfafe3e5a5280485f56202b1b3f..0c4e5574fb9501cb1fcb003fc3e97f1edf8062af 100644 (file)
@@ -1,11 +1,11 @@
 (function($) {
 
 function present( value, array, message ) {
-       QUnit.push( jQuery.inArray( value, array ) !== -1 , value, array, message );
+       QUnit.push( jQuery.inArray( value, array ) !== -1, value, array, message );
 }
 
 function notPresent( value, array, message ) {
-       QUnit.push( jQuery.inArray( value, array ) === -1 , value, array, message );
+       QUnit.push( jQuery.inArray( value, array ) === -1, value, array, message );
 }
 
 // minDuration is used for "short" animate tests where we are only concerned about the final
@@ -75,20 +75,6 @@ test( "removeClass", function() {
        equal( "", element[ 0 ].className );
 });
 
-
-/* TODO: Disabled - Can't figure out why this is failing in IE 6/7
-test( "createWrapper and removeWrapper retain focused elements (#7595)", function() {
-       expect( 2 );
-       var test = $( "div.hidden" ).show(),
-               input = $( "<input type='text'>" ).appendTo( test ).focus();
-
-       $.effects.createWrapper( test );
-       equal( document.activeElement, input[ 0 ], "Active element is still input after createWrapper" );
-       $.effects.removeWrapper( test );
-       equal( document.activeElement, input[ 0 ], "Active element is still input after removeWrapper" );
-});
-*/
-
 module( "effects.core: animateClass" );
 
 asyncTest( "animateClass works with borderStyle", function() {
@@ -213,6 +199,44 @@ asyncTest( "animateClass: css and class changes during animation are not lost (#
                .height( 100 );
 });
 
+test( "createPlaceholder: only created for static or relative elements", function() {
+       expect( 4 );
+
+       ok( $.effects.createPlaceholder( $( ".relative" ) ).length, "placeholder created for relative element" );
+       ok( $.effects.createPlaceholder( $( ".static" ) ).length, "placeholder created for static element" );
+       ok( !$.effects.createPlaceholder( $( ".absolute" ) ), "placeholder not created for absolute element" );
+       ok( !$.effects.createPlaceholder( $( ".fixed" ) ), "placeholder not created for fixed element" );
+});
+
+test( "createPlaceholder: preserves layout affecting properties", function() {
+       expect( 7 );
+
+       var position = 5,
+               element = $( ".relative" ).css({
+                       top: position,
+                       left: position
+               }),
+               before = {
+                       offset: element.offset(),
+                       outerWidth: element.outerWidth( true ),
+                       outerHeight: element.outerHeight( true ),
+                       "float": element.css( "float" ),
+                       position: element.position()
+               },
+               placeholder = $.effects.createPlaceholder( element );
+
+       // Placeholders are only placed to preserve the effect on layout. Considering
+       // top and left do not change layout, they are not preserved, which makes some
+       // of the math simpler in the implementation.
+       deepEqual( before.offset.top - position, placeholder.offset().top, "offset top preserved" );
+       deepEqual( before.offset.left - position, placeholder.offset().left, "offset left preserved" );
+       deepEqual( before.position.top - position, placeholder.position().top, "position top preserved" );
+       deepEqual( before.position.left - position, placeholder.position().left, "position left preserved" );
+
+       deepEqual( before[ "float" ], placeholder.css( "float" ), "float preserved" );
+       deepEqual( before.outerWidth, placeholder.outerWidth( true ), "width preserved" );
+       deepEqual( before.outerHeight, placeholder.outerHeight( true ), "height preserved" );
+});
 
 $.each( $.effects.effect, function( effect ) {
        module( "effects." + effect );
@@ -223,7 +247,7 @@ $.each( $.effects.effect, function( effect ) {
                return;
        }
        asyncTest( "show/hide", function() {
-               expect( 8 );
+               expect( 12 );
                var hidden = $( "div.hidden" ),
                        count = 0,
                        test = 0;
@@ -242,14 +266,40 @@ $.each( $.effects.effect, function( effect ) {
                        };
                }
 
-               hidden.queue( queueTest() ).show( effect, minDuration, queueTest(function() {
-                       equal( hidden.css("display"), "block", "Hidden is shown after .show(\"" +effect+ "\", time)" );
-               })).queue( queueTest() ).hide( effect, minDuration, queueTest(function() {
-                       equal( hidden.css("display"), "none", "Back to hidden after .hide(\"" +effect+ "\", time)" );
-               })).queue( queueTest(function() {
-                       deepEqual( hidden.queue(), ["inprogress"], "Only the inprogress sentinel remains");
-                       start();
-               }));
+               function duringTest( fn ) {
+                       return function( next ) {
+                               setTimeout( fn );
+                               next();
+                       };
+               }
+
+               hidden
+                       .queue( queueTest() )
+                       .queue( duringTest(function() {
+                               ok( hidden.is( ":animated" ),
+                                       "Hidden is seen as animated during .show(\"" + effect + "\", time)" );
+                       }) )
+                       .show( effect, minDuration, queueTest(function() {
+                               equal( hidden.css( "display" ), "block",
+                                       "Hidden is shown after .show(\"" + effect + "\", time)" );
+                               ok( !$( ".ui-effects-placeholder" ).length,
+                                       "No placeholder remains after .show(\"" + effect + "\", time)" );
+                       }) )
+                       .queue( queueTest() )
+                       .queue( duringTest(function() {
+                               ok( hidden.is( ":animated" ),
+                                       "Hidden is seen as animated during .hide(\"" + effect + "\", time)" );
+                       }) )
+                       .hide( effect, minDuration, queueTest(function() {
+                               equal( hidden.css( "display" ), "none",
+                                       "Back to hidden after .hide(\"" + effect + "\", time)" );
+                               ok( !$( ".ui-effects-placeholder" ).length,
+                                       "No placeholder remains after .hide(\"" + effect + "\", time)" );
+                       }) )
+                       .queue( queueTest(function() {
+                               deepEqual( hidden.queue(), [ "inprogress" ], "Only the inprogress sentinel remains" );
+                               start();
+                       }) );
        });
 
        asyncTest( "relative width & height - properties are preserved", function() {
index 6abbcb5382f740f7201a04dfe061678ed985d559..caed39c228c7df50fc2387ecd7f3987040c460f9 100644 (file)
@@ -6,8 +6,8 @@ function run( position, v, h, vo, ho ) {
        asyncTest( desc, function() {
                expect( 2 );
                function complete() {
-                       equal( parseInt( test.css( h ), 10 ), target[ h ], "Horizontal Position Correct " + desc );
-                       equal( parseInt( test.css( v ), 10 ), target[ v ], "Vertical Position Correct " + desc );
+                       closeEnough( parseInt( test.css( h ), 10 ), target[ h ], 1, "Horizontal Position Correct " + desc );
+                       closeEnough( parseInt( test.css( v ), 10 ), target[ v ], 1, "Vertical Position Correct " + desc );
                        start();
                }
                var test = $( ".testScale" ),
index 9fb4cf9c4ce60eb47cc675242b56587d511e42d8..c1bdd9fa32be2bcd5c56c159e1f065775fa59135 100644 (file)
        <script src="../../../ui/effect-fade.js"></script>
        <script src="../../../ui/effect-fold.js"></script>
        <script src="../../../ui/effect-highlight.js"></script>
+       <script src="../../../ui/effect-puff.js"></script>
        <script src="../../../ui/effect-pulsate.js"></script>
        <script src="../../../ui/effect-scale.js"></script>
+       <script src="../../../ui/effect-size.js"></script>
        <script src="../../../ui/effect-shake.js"></script>
        <script src="../../../ui/effect-slide.js"></script>
        <script src="../../../ui/effect-transfer.js"></script>
index 49efa6d8bfc3ba0854910f58f61c56b2afcddd94..f56f5418909d1a6fb8b3a3b56d273357d4de6c83 100644 (file)
@@ -70,6 +70,7 @@
 <p>EXPECTED: Clicking "Toggle" or "Effect Toggle" a second time reverses the animation, first showing all elements at their original dimensions, and restoring them to their original state.</p>
 <p>EXPECTED: Clicking "Effect Default" should always perform a "hide" animation.</p>
 <p>EXPECTED: Clicking any of the buttons in quick succession should queue the relevant animations.</p>
+<p>EXPECTED CANTFIX: In IE8, the clip animation jumps due to a bug that causes .css('clip') to return undefined unless the clip property is an inline style.</p>
 
 <div class="container">
        <button class="toggle">Toggle</button>
@@ -80,7 +81,7 @@
        <p>Jerky corned beef short loin fatback jowl tail. Rump spare ribs shoulder pork belly. Sausage cow ground round bacon. Bresaola kielbasa pastrami brisket ham hock. Andouille kielbasa ham, pork beef tenderloin ground round beef ribs flank turkey pancetta tri-tip.</p>
        <div class="column">
                <p>Shankle filet mignon ribeye chicken, bacon jowl drumstick frankfurter swine short loin capicola leberkas tenderloin pig. Shankle bacon shank pork loin, shoulder ham drumstick biltong. Shankle ham pastrami ball tip turkey leberkas pork loin ground round. Chicken strip steak venison shoulder biltong ham. Bacon pork loin tenderloin kielbasa, prosciutto sausage leberkas jowl ribeye turducken. Flank short loin venison tenderloin spare ribs boudin, tongue pork chop shank sirloin. Ground round ham pork belly, corned beef jowl strip steak short ribs prosciutto pig bresaola spare ribs.</p>
-               <img class="target" style="margin: 10px 20px 30px 40px;" src="../../images/jquery_521x191.png" alt="jQuery Logo">
+               <img class="target margin" src="../../images/jquery_521x191.png" alt="jQuery Logo">
                <p>Pork loin biltong ball tip tail jerky beef ribs prosciutto short loin turducken. Turkey chicken jowl pork loin shank tri-tip swine brisket. Doner prosciutto leberkas venison ground round, short loin capicola hamburger pork bacon. Spare ribs beef pork tenderloin rump shoulder pork belly turducken cow beef ribs pastrami tail flank. Spare ribs tri-tip shank, pork beef ribs ribeye chicken bacon boudin shoulder venison. Sirloin beef ribs boudin, andouille doner tail ball tip biltong prosciutto chicken beef turkey tongue hamburger tri-tip.</p>
        </div>
        <p>Doner salami jowl beef ribs. Pork chop beef short loin pork, kielbasa tail andouille salami sausage meatball short ribs t-bone tri-tip ham. Meatball short ribs prosciutto flank chicken fatback frankfurter brisket turducken. Corned beef hamburger swine short ribs pancetta. Jerky bresaola pork chuck spare ribs pastrami shoulder flank chicken leberkas beef.</p>
index 624e0b128a07448638b90aa3fdfcddffd045794b..f0963a99d5bc6233437b1170bb890b2400e3a75a 100644 (file)
@@ -57,7 +57,7 @@ effect( "#highlight", "highlight", {} );
 
 effect( "#pulsate", "pulsate", { times: 2 } );
 
-effect( "#puff", "puff", { times: 2 } );
+effect( "#puff", "puff", {} );
 effect( "#scale", "scale", {} );
 effect( "#size", "size", {} );
 $( "#sizeToggle" ).click(function() {
diff --git a/tests/visual/effects/image.png b/tests/visual/effects/image.png
new file mode 100644 (file)
index 0000000..4ec9043
Binary files /dev/null and b/tests/visual/effects/image.png differ
index f7d516f2072250ad1c7e40b5b4f6951fa419f1c9..0c9b14da8d2b98138b2941a48659aaa125ab2307 100644 (file)
@@ -48,6 +48,7 @@
                <h2>Effects</h2>
                <ul>
                        <li><a href="effects/all.html">All</a></li>
+                       <li><a href="effects/clip.html">Clip</a></li>
                        <li><a href="effects/scale.html">Scale</a></li>
                        <li><a href="effects/shake.html">Shake</a></li>
                </ul>
index ffdfa37351411d81264d0533faa9dbbb1c61efa3..eb96cca6edc42e03529c1bab8eca1262ac57d723 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.blind = function( o, done ) {
-       // Create element
-       var el = $( this ),
-               rvertical = /up|down|vertical/,
-               rpositivemotion = /up|left|vertical|horizontal/,
-               props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-               mode = $.effects.setMode( el, o.mode || "hide" ),
-               direction = o.direction || "up",
-               vertical = rvertical.test( direction ),
-               ref = vertical ? "height" : "width",
-               ref2 = vertical ? "top" : "left",
-               motion = rpositivemotion.test( direction ),
-               animation = {},
-               show = mode === "show",
-               wrapper, distance, margin;
+return $.effects.define( "blind", "hide", function( options, done ) {
+       var map = {
+                       up: [ "bottom", "top" ],
+                       vertical: [ "bottom", "top" ],
+                       down: [ "top", "bottom" ],
+                       left: [ "right", "left" ],
+                       horizontal: [ "right", "left" ],
+                       right: [ "left", "right" ]
+               },
+               element = $( this ),
+               direction = options.direction || "up",
+               start = element.cssClip(),
+               animate = { clip: $.extend( {}, start ) },
+               placeholder = $.effects.createPlaceholder( element );
 
-       // if already wrapped, the wrapper's properties are my property. #6245
-       if ( el.parent().is( ".ui-effects-wrapper" ) ) {
-               $.effects.save( el.parent(), props );
-       } else {
-               $.effects.save( el, props );
-       }
-       el.show();
-       wrapper = $.effects.createWrapper( el ).css({
-               overflow: "hidden"
-       });
-
-       distance = wrapper[ ref ]();
-       margin = parseFloat( wrapper.css( ref2 ) ) || 0;
+       animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
 
-       animation[ ref ] = show ? distance : 0;
-       if ( !motion ) {
-               el
-                       .css( vertical ? "bottom" : "right", 0 )
-                       .css( vertical ? "top" : "left", "auto" )
-                       .css({ position: "absolute" });
+       if ( options.mode === "show" ) {
+               element.cssClip( animate.clip );
+               if ( placeholder ) {
+                       placeholder.css( $.effects.clipToBox( animate ) );
+               }
 
-               animation[ ref2 ] = show ? margin : distance + margin;
+               animate.clip = start;
        }
 
-       // start at 0 if we are showing
-       if ( show ) {
-               wrapper.css( ref, 0 );
-               if ( !motion ) {
-                       wrapper.css( ref2, margin + distance );
-               }
+       if ( placeholder ) {
+               placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
        }
 
-       // Animate
-       wrapper.animate( animation, {
-               duration: o.duration,
-               easing: o.easing,
+       element.animate( animate, {
                queue: false,
-               complete: function() {
-                       if ( mode === "hide" ) {
-                               el.hide();
-                       }
-                       $.effects.restore( el, props );
-                       $.effects.removeWrapper( el );
-                       done();
-               }
+               duration: options.duration,
+               easing: options.easing,
+               complete: done
        });
-};
+});
 
 }));
index b2fa2c951afab0fdfb13c97baf1d6418c4256df4..d599c40b5d7591f6e9d74c4f686a92b676746fbc 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.bounce = function( o, done ) {
-       var el = $( this ),
-               props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+return $.effects.define( "bounce", function( options, done ) {
+       var upAnim, downAnim, refValue,
+               element = $( this ),
 
                // defaults:
-               mode = $.effects.setMode( el, o.mode || "effect" ),
+               mode = options.mode,
                hide = mode === "hide",
                show = mode === "show",
-               direction = o.direction || "up",
-               distance = o.distance,
-               times = o.times || 5,
+               direction = options.direction || "up",
+               distance = options.distance,
+               times = options.times || 5,
 
                // number of internal animations
                anims = times * 2 + ( show || hide ? 1 : 0 ),
-               speed = o.duration / anims,
-               easing = o.easing,
+               speed = options.duration / anims,
+               easing = options.easing,
 
                // utility:
                ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
                motion = ( direction === "up" || direction === "left" ),
-               i,
-               upAnim,
-               downAnim,
+               i = 0,
 
-               // we will need to re-assemble the queue to stack our animations in place
-               queue = el.queue(),
-               queuelen = queue.length;
+               queuelen = element.queue().length;
 
-       // Avoid touching opacity to prevent clearType and PNG issues in IE
-       if ( show || hide ) {
-               props.push( "opacity" );
-       }
+       $.effects.createPlaceholder( element );
 
-       $.effects.save( el, props );
-       el.show();
-       $.effects.createWrapper( el ); // Create Wrapper
+       refValue = element.css( ref );
 
        // default distance for the BIGGEST bounce is the outer Distance / 3
        if ( !distance ) {
-               distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
+               distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
        }
 
        if ( show ) {
                downAnim = { opacity: 1 };
-               downAnim[ ref ] = 0;
+               downAnim[ ref ] = refValue;
 
                // if we are showing, force opacity 0 and set the initial position
                // then do the "first" animation
-               el.css( "opacity", 0 )
+               element
+                       .css( "opacity", 0 )
                        .css( ref, motion ? -distance * 2 : distance * 2 )
                        .animate( downAnim, speed, easing );
        }
@@ -87,13 +79,14 @@ return $.effects.effect.bounce = function( o, done ) {
        }
 
        downAnim = {};
-       downAnim[ ref ] = 0;
+       downAnim[ ref ] = refValue;
        // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
-       for ( i = 0; i < times; i++ ) {
+       for ( ; i < times; i++ ) {
                upAnim = {};
                upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
 
-               el.animate( upAnim, speed, easing )
+               element
+                       .animate( upAnim, speed, easing )
                        .animate( downAnim, speed, easing );
 
                distance = hide ? distance * 2 : distance / 2;
@@ -104,25 +97,12 @@ return $.effects.effect.bounce = function( o, done ) {
                upAnim = { opacity: 0 };
                upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
 
-               el.animate( upAnim, speed, easing );
+               element.animate( upAnim, speed, easing );
        }
 
-       el.queue(function() {
-               if ( hide ) {
-                       el.hide();
-               }
-               $.effects.restore( el, props );
-               $.effects.removeWrapper( el );
-               done();
-       });
-
-       // inject all the animations we just queued to be first in line (after "inprogress")
-       if ( queuelen > 1) {
-               queue.splice.apply( queue,
-                       [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
-       }
-       el.dequeue();
+       element.queue( done );
 
-};
+       $.effects.unshift( element, queuelen, anims + 1 );
+});
 
 }));
index 6a07ad67d84a5911f0dbe5fe0f5f4a2f1926e10d..1bb3ebce2938fcd866d63f9ae8749e1311ea3437 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.clip = function( o, done ) {
-       // Create element
-       var el = $( this ),
-               props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-               mode = $.effects.setMode( el, o.mode || "hide" ),
-               show = mode === "show",
-               direction = o.direction || "vertical",
-               vert = direction === "vertical",
-               size = vert ? "height" : "width",
-               position = vert ? "top" : "left",
-               animation = {},
-               wrapper, animate, distance;
+return $.effects.define( "clip", "hide", function( options, done ) {
+       var start,
+               animate = {},
+               element = $( this ),
+               direction = options.direction || "vertical",
+               both = direction === "both",
+               horizontal = both || direction === "horizontal",
+               vertical = both || direction === "vertical";
 
-       // Save & Show
-       $.effects.save( el, props );
-       el.show();
+       start = element.cssClip();
+       animate.clip = {
+               top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
+               right: horizontal ? ( start.right - start.left ) / 2 : start.right,
+               bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
+               left: horizontal ? ( start.right - start.left ) / 2 : start.left
+       };
 
-       // Create Wrapper
-       wrapper = $.effects.createWrapper( el ).css({
-               overflow: "hidden"
-       });
-       animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
-       distance = animate[ size ]();
+       $.effects.createPlaceholder( element );
 
-       // Shift
-       if ( show ) {
-               animate.css( size, 0 );
-               animate.css( position, distance / 2 );
+       if ( options.mode === "show" ) {
+               element.cssClip( animate.clip );
+               animate.clip = start;
        }
 
-       // Create Animation Object:
-       animation[ size ] = show ? distance : 0;
-       animation[ position ] = show ? 0 : distance / 2;
-
-       // Animate
-       animate.animate( animation, {
+       element.animate( animate, {
                queue: false,
-               duration: o.duration,
-               easing: o.easing,
-               complete: function() {
-                       if ( !show ) {
-                               el.hide();
-                       }
-                       $.effects.restore( el, props );
-                       $.effects.removeWrapper( el );
-                       done();
-               }
+               duration: options.duration,
+               easing: options.easing,
+               complete: done
        });
 
-};
+});
 
 }));
index 0b3f85557b7c78e87f0b78c6ffca59ea51e4feae..a990c48e7cf4abef6184e90b38388fe54423f41b 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.drop = function( o, done ) {
+return $.effects.define( "drop", "hide", function( options, done ) {
 
-       var el = $( this ),
-               props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
-               mode = $.effects.setMode( el, o.mode || "hide" ),
+       var distance,
+               element = $( this ),
+               mode = options.mode,
                show = mode === "show",
-               direction = o.direction || "left",
+               direction = options.direction || "left",
                ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
-               motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
+               motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
+               oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
                animation = {
-                       opacity: show ? 1 : 0
-               },
-               distance;
+                       opacity: 0
+               };
 
-       // Adjust
-       $.effects.save( el, props );
-       el.show();
-       $.effects.createWrapper( el );
+       $.effects.createPlaceholder( element );
 
-       distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
+       distance = options.distance || element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
+
+       animation[ ref ] = motion + distance;
 
        if ( show ) {
-               el
-                       .css( "opacity", 0 )
-                       .css( ref, motion === "pos" ? -distance : distance );
-       }
+               element.css( animation );
 
-       // Animation
-       animation[ ref ] = ( show ?
-               ( motion === "pos" ? "+=" : "-=" ) :
-               ( motion === "pos" ? "-=" : "+=" ) ) +
-               distance;
+               animation[ ref ] = oppositeMotion + distance;
+               animation.opacity = 1;
+       }
 
        // Animate
-       el.animate( animation, {
+       element.animate( animation, {
                queue: false,
-               duration: o.duration,
-               easing: o.easing,
-               complete: function() {
-                       if ( mode === "hide" ) {
-                               el.hide();
-                       }
-                       $.effects.restore( el, props );
-                       $.effects.removeWrapper( el );
-                       done();
-               }
+               duration: options.duration,
+               easing: options.easing,
+               complete: done
        });
-};
+});
 
 }));
index 547c6787ae4f2e706090f65acae995c3c80342ac..adb05cf5f36a309e2644e91f1b64bbde18936a5a 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.explode = function( o, done ) {
+return $.effects.define( "explode", "hide", function( options, done ) {
 
-       var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
+       var i, j, left, top, mx, my,
+               rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
                cells = rows,
-               el = $( this ),
-               mode = $.effects.setMode( el, o.mode || "hide" ),
+               element = $( this ),
+               mode = options.mode,
                show = mode === "show",
 
                // show and then visibility:hidden the element before calculating offset
-               offset = el.show().css( "visibility", "hidden" ).offset(),
+               offset = element.show().css( "visibility", "hidden" ).offset(),
 
                // width and height of a piece
-               width = Math.ceil( el.outerWidth() / cells ),
-               height = Math.ceil( el.outerHeight() / rows ),
-               pieces = [],
-
-               // loop
-               i, j, left, top, mx, my;
+               width = Math.ceil( element.outerWidth() / cells ),
+               height = Math.ceil( element.outerHeight() / rows ),
+               pieces = [];
 
        // children animate complete:
        function childComplete() {
@@ -66,7 +64,7 @@ return $.effects.effect.explode = function( o, done ) {
 
                        // Create a clone of the now hidden main element that will be absolute positioned
                        // within a wrapper div off the -left and -top equal to size of our pieces
-                       el
+                       element
                                .clone()
                                .appendTo( "body" )
                                .wrap( "<div></div>" )
@@ -93,20 +91,17 @@ return $.effects.effect.explode = function( o, done ) {
                                        left: left + ( show ? 0 : mx * width ),
                                        top: top + ( show ? 0 : my * height ),
                                        opacity: show ? 1 : 0
-                               }, o.duration || 500, o.easing, childComplete );
+                               }, options.duration || 500, options.easing, childComplete );
                }
        }
 
        function animComplete() {
-               el.css({
+               element.css({
                        visibility: "visible"
                });
                $( pieces ).remove();
-               if ( !show ) {
-                       el.hide();
-               }
                done();
        }
-};
+});
 
 }));
index 3bde7d6b9e1f8aa8681063b8ada5769414de5941..ad7c2134b83c3e2932c8baeb0334cb8a3fd10096 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.fade = function( o, done ) {
-       var el = $( this ),
-               mode = $.effects.setMode( el, o.mode || "toggle" );
+return $.effects.define( "fade", "toggle", function( options, done ) {
+       var show = options.mode === "show";
 
-       el.animate({
-               opacity: mode
-       }, {
-               queue: false,
-               duration: o.duration,
-               easing: o.easing,
-               complete: done
-       });
-};
+       $( this )
+               .css( "opacity", show ? 0 : 1 )
+               .animate({
+                       opacity: show ? 1 : 0
+               }, {
+                       queue: false,
+                       duration: options.duration,
+                       easing: options.easing,
+                       complete: done
+               });
+});
 
 }));
index 7776f3cc65ed9b97059b66a7fe67a7a84ee007d1..7961ee79feb4bddd9a773b5be5a91a6a9f2327c7 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.fold = function( o, done ) {
+return $.effects.define( "fold", "hide", function( options, done ) {
 
        // Create element
-       var el = $( this ),
-               props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-               mode = $.effects.setMode( el, o.mode || "hide" ),
+       var element = $( this ),
+               mode = options.mode,
                show = mode === "show",
                hide = mode === "hide",
-               size = o.size || 15,
+               size = options.size || 15,
                percent = /([0-9]+)%/.exec( size ),
-               horizFirst = !!o.horizFirst,
-               widthFirst = show !== horizFirst,
-               ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
-               duration = o.duration / 2,
-               wrapper, distance,
-               animation1 = {},
-               animation2 = {};
-
-       $.effects.save( el, props );
-       el.show();
-
-       // Create Wrapper
-       wrapper = $.effects.createWrapper( el ).css({
-               overflow: "hidden"
-       });
-       distance = widthFirst ?
-               [ wrapper.width(), wrapper.height() ] :
-               [ wrapper.height(), wrapper.width() ];
+               horizFirst = !!options.horizFirst,
+               ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
+               duration = options.duration / 2,
+
+               placeholder = $.effects.createPlaceholder( element ),
+
+               start = element.cssClip(),
+               animation1 = { clip: $.extend( {}, start ) },
+               animation2 = { clip: $.extend( {}, start ) },
+
+               distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
+
+               queuelen = element.queue().length;
 
        if ( percent ) {
                size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
        }
+       animation1.clip[ ref[ 0 ] ] = size;
+       animation2.clip[ ref[ 0 ] ] = size;
+       animation2.clip[ ref[ 1 ] ] = 0;
+
        if ( show ) {
-               wrapper.css( horizFirst ? {
-                       height: 0,
-                       width: size
-               } : {
-                       height: size,
-                       width: 0
-               });
-       }
+               element.cssClip( animation2.clip );
+               if ( placeholder ) {
+                       placeholder.css( $.effects.clipToBox( animation2 ) );
+               }
 
-       // Animation
-       animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
-       animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
+               animation2.clip = start;
+       }
 
        // Animate
-       wrapper
-               .animate( animation1, duration, o.easing )
-               .animate( animation2, duration, o.easing, function() {
-                       if ( hide ) {
-                               el.hide();
+       element
+               .queue(function( next ) {
+                       if ( placeholder ) {
+                               placeholder
+                                       .animate( $.effects.clipToBox( animation1 ), duration, options.easing )
+                                       .animate( $.effects.clipToBox( animation2 ), duration, options.easing );
                        }
-                       $.effects.restore( el, props );
-                       $.effects.removeWrapper( el );
-                       done();
-               });
 
-};
+                       next();
+               })
+               .animate( animation1, duration, options.easing )
+               .animate( animation2, duration, options.easing )
+               .queue( done );
+
+       $.effects.unshift( element, queuelen, 4 );
+});
 
 }));
index e3ad3cbc4e6be55e1c1ba428daf9796109d7951c..fb44aef9124065683a47b0386899c68efa4e9b3d 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.highlight = function( o, done ) {
-       var elem = $( this ),
-               props = [ "backgroundImage", "backgroundColor", "opacity" ],
-               mode = $.effects.setMode( elem, o.mode || "show" ),
+return $.effects.define( "highlight", "show", function( options, done ) {
+       var element = $( this ),
                animation = {
-                       backgroundColor: elem.css( "backgroundColor" )
+                       backgroundColor: element.css( "backgroundColor" )
                };
 
-       if (mode === "hide") {
+       if ( options.mode === "hide" ) {
                animation.opacity = 0;
        }
 
-       $.effects.save( elem, props );
+       $.effects.saveStyle( element );
 
-       elem
-               .show()
+       element
                .css({
                        backgroundImage: "none",
-                       backgroundColor: o.color || "#ffff99"
+                       backgroundColor: options.color || "#ffff99"
                })
                .animate( animation, {
                        queue: false,
-                       duration: o.duration,
-                       easing: o.easing,
-                       complete: function() {
-                               if ( mode === "hide" ) {
-                                       elem.hide();
-                               }
-                               $.effects.restore( elem, props );
-                               done();
-                       }
+                       duration: options.duration,
+                       easing: options.easing,
+                       complete: done
                });
-};
+});
 
 }));
index 8ea6ded225bb87fa8a5e3f7a428b7c353567e5ec..607ca77f5a99f87e8eed1f4e7da30560181e28bd 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.puff = function( o, done ) {
-       var elem = $( this ),
-               mode = $.effects.setMode( elem, o.mode || "hide" ),
-               hide = mode === "hide",
-               percent = parseInt( o.percent, 10 ) || 150,
-               factor = percent / 100,
-               original = {
-                       height: elem.height(),
-                       width: elem.width(),
-                       outerHeight: elem.outerHeight(),
-                       outerWidth: elem.outerWidth()
-               };
-
-       $.extend( o, {
-               effect: "scale",
-               queue: false,
+return $.effects.define( "puff", "hide", function( options, done ) {
+       var newOptions = $.extend( true, {}, options, {
                fade: true,
-               mode: mode,
-               complete: done,
-               percent: hide ? percent : 100,
-               from: hide ?
-                       original :
-                       {
-                               height: original.height * factor,
-                               width: original.width * factor,
-                               outerHeight: original.outerHeight * factor,
-                               outerWidth: original.outerWidth * factor
-                       }
+               percent: parseInt( options.percent, 10 ) || 150
        });
 
-       elem.effect( o );
-};
+       $.effects.effect.scale.call( this, newOptions, done );
+});
 
 }));
index 0e82761a3859f798385b29bb408685bb5cf4a3e1..c28da9ff8eaf7d247ceaf1f514e03921b76527fe 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.pulsate = function( o, done ) {
-       var elem = $( this ),
-               mode = $.effects.setMode( elem, o.mode || "show" ),
+return $.effects.define( "pulsate", "show", function( options, done ) {
+       var element = $( this ),
+               mode = options.mode,
                show = mode === "show",
                hide = mode === "hide",
-               showhide = ( show || mode === "hide" ),
+               showhide = show || hide,
 
-               // showing or hiding leaves of the "last" animation
-               anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
-               duration = o.duration / anims,
+               // Showing or hiding leaves off the "last" animation
+               anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
+               duration = options.duration / anims,
                animateTo = 0,
-               queue = elem.queue(),
-               queuelen = queue.length,
-               i;
+               i = 1,
+               queuelen = element.queue().length;
 
-       if ( show || !elem.is(":visible")) {
-               elem.css( "opacity", 0 ).show();
+       if ( show || !element.is( ":visible" ) ) {
+               element.css( "opacity", 0 ).show();
                animateTo = 1;
        }
 
-       // anims - 1 opacity "toggles"
-       for ( i = 1; i < anims; i++ ) {
-               elem.animate({
-                       opacity: animateTo
-               }, duration, o.easing );
+       // Anims - 1 opacity "toggles"
+       for ( ; i < anims; i++ ) {
+               element.animate( { opacity: animateTo }, duration, options.easing );
                animateTo = 1 - animateTo;
        }
 
-       elem.animate({
-               opacity: animateTo
-       }, duration, o.easing);
+       element.animate( { opacity: animateTo }, duration, options.easing );
 
-       elem.queue(function() {
-               if ( hide ) {
-                       elem.hide();
-               }
-               done();
-       });
+       element.queue( done );
 
-       // We just queued up "anims" animations, we need to put them next in the queue
-       if ( queuelen > 1 ) {
-               queue.splice.apply( queue,
-                       [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
-       }
-       elem.dequeue();
-};
+       $.effects.unshift( element, queuelen, anims + 1 );
+});
 
 }));
index e2e1c0b50d9a3668e263d4e6a01d75e3652d35cd..478ca25baa1a1764a7ac82bb6f43c42fd62bae6f 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.scale = function( o, done ) {
+return $.effects.define( "scale", function( options, done ) {
 
        // Create element
        var el = $( this ),
-               options = $.extend( true, {}, o ),
-               mode = $.effects.setMode( el, o.mode || "effect" ),
-               percent = parseInt( o.percent, 10 ) ||
-                       ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
-               direction = o.direction || "both",
-               origin = o.origin,
-               original = {
-                       height: el.height(),
-                       width: el.width(),
-                       outerHeight: el.outerHeight(),
-                       outerWidth: el.outerWidth()
-               },
-               factor = {
-                       y: direction !== "horizontal" ? (percent / 100) : 1,
-                       x: direction !== "vertical" ? (percent / 100) : 1
-               };
+               mode = options.mode,
+               percent = parseInt( options.percent, 10 ) ||
+                       ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
 
-       // We are going to pass this effect to the size effect:
-       options.effect = "size";
-       options.queue = false;
-       options.complete = done;
-
-       // Set default origin and restore for show/hide
-       if ( mode !== "effect" ) {
-               options.origin = origin || [ "middle", "center" ];
-               options.restore = true;
-       }
-
-       options.from = o.from || ( mode === "show" ? {
-               height: 0,
-               width: 0,
-               outerHeight: 0,
-               outerWidth: 0
-       } : original );
-       options.to = {
-               height: original.height * factor.y,
-               width: original.width * factor.x,
-               outerHeight: original.outerHeight * factor.y,
-               outerWidth: original.outerWidth * factor.x
-       };
+               newOptions = $.extend( true, {
+                       from: $.effects.scaledDimensions( el ),
+                       to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
+                       origin: options.origin || [ "middle", "center" ]
+               }, options );
 
        // Fade option to support puff
        if ( options.fade ) {
-               if ( mode === "show" ) {
-                       options.from.opacity = 0;
-                       options.to.opacity = 1;
-               }
-               if ( mode === "hide" ) {
-                       options.from.opacity = 1;
-                       options.to.opacity = 0;
-               }
+               newOptions.from.opacity = 1;
+               newOptions.to.opacity = 0;
        }
 
-       // Animate
-       el.effect( options );
-
-};
+       $.effects.effect.size.call( this, newOptions, done );
+});
 
 }));
index 896d6f95e2f5873a60980fbffe2259a8b85ff546..387f213401779eeb11e991fcc877224ade6717a0 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.shake = function( o, done ) {
+return $.effects.define( "shake", function( options, done ) {
 
-       var el = $( this ),
-               props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-               mode = $.effects.setMode( el, o.mode || "effect" ),
-               direction = o.direction || "left",
-               distance = o.distance || 20,
-               times = o.times || 3,
+       var i = 1,
+               element = $( this ),
+               direction = options.direction || "left",
+               distance = options.distance || 20,
+               times = options.times || 3,
                anims = times * 2 + 1,
-               speed = Math.round( o.duration / anims ),
-               ref = (direction === "up" || direction === "down") ? "top" : "left",
-               positiveMotion = (direction === "up" || direction === "left"),
+               speed = Math.round( options.duration / anims ),
+               ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
+               positiveMotion = ( direction === "up" || direction === "left" ),
                animation = {},
                animation1 = {},
                animation2 = {},
-               i,
 
-               // we will need to re-assemble the queue to stack our animations in place
-               queue = el.queue(),
-               queuelen = queue.length;
+               queuelen = element.queue().length;
 
-       $.effects.save( el, props );
-       el.show();
-       $.effects.createWrapper( el );
+       $.effects.createPlaceholder( element );
 
        // Animation
        animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
@@ -59,31 +53,19 @@ return $.effects.effect.shake = function( o, done ) {
        animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
 
        // Animate
-       el.animate( animation, speed, o.easing );
+       element.animate( animation, speed, options.easing );
 
        // Shakes
-       for ( i = 1; i < times; i++ ) {
-               el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
+       for ( ; i < times; i++ ) {
+               element.animate( animation1, speed, options.easing ).animate( animation2, speed, options.easing );
        }
-       el
-               .animate( animation1, speed, o.easing )
-               .animate( animation, speed / 2, o.easing )
-               .queue(function() {
-                       if ( mode === "hide" ) {
-                               el.hide();
-                       }
-                       $.effects.restore( el, props );
-                       $.effects.removeWrapper( el );
-                       done();
-               });
 
-       // inject all the animations we just queued to be first in line (after "inprogress")
-       if ( queuelen > 1) {
-               queue.splice.apply( queue,
-                       [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
-       }
-       el.dequeue();
+       element
+               .animate( animation1, speed, options.easing )
+               .animate( animation, speed / 2, options.easing )
+               .queue( done );
 
-};
+       $.effects.unshift( element, queuelen, anims + 1 );
+});
 
 }));
index 984d741052412df85aedec3e7402579dba5225ed..91a6bf51bde44d0f38609b574814a829f74af033 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.size = function( o, done ) {
+return $.effects.define( "size", function( options, done ) {
 
        // Create element
-       var original, baseline, factor,
-               el = $( this ),
-               props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
-
-               // Always restore
-               props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
+       var baseline, factor, temp,
+               element = $( this ),
 
                // Copy for children
-               props2 = [ "width", "height", "overflow" ],
                cProps = [ "fontSize" ],
                vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
                hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
 
                // Set options
-               mode = $.effects.setMode( el, o.mode || "effect" ),
-               restore = o.restore || mode !== "effect",
-               scale = o.scale || "both",
-               origin = o.origin || [ "middle", "center" ],
-               position = el.css( "position" ),
-               props = restore ? props0 : props1,
-               zero = {
-                       height: 0,
-                       width: 0,
-                       outerHeight: 0,
-                       outerWidth: 0
-               };
+               mode = options.mode,
+               restore = mode !== "effect",
+               scale = options.scale || "both",
+               origin = options.origin || [ "middle", "center" ],
+               position = element.css( "position" ),
+               pos = element.position(),
+               original = $.effects.scaledDimensions( element ),
+               from = options.from || original,
+               to = options.to || $.effects.scaledDimensions( element, 0 );
+
+       $.effects.createPlaceholder( element );
 
        if ( mode === "show" ) {
-               el.show();
-       }
-       original = {
-               height: el.height(),
-               width: el.width(),
-               outerHeight: el.outerHeight(),
-               outerWidth: el.outerWidth()
-       };
-
-       if ( o.mode === "toggle" && mode === "show" ) {
-               el.from = o.to || zero;
-               el.to = o.from || original;
-       } else {
-               el.from = o.from || ( mode === "show" ? zero : original );
-               el.to = o.to || ( mode === "hide" ? zero : original );
+               temp = from;
+               from = to;
+               to = temp;
        }
 
        // Set scaling factor
        factor = {
                from: {
-                       y: el.from.height / original.height,
-                       x: el.from.width / original.width
+                       y: from.height / original.height,
+                       x: from.width / original.width
                },
                to: {
-                       y: el.to.height / original.height,
-                       x: el.to.width / original.width
+                       y: to.height / original.height,
+                       x: to.width / original.width
                }
        };
 
@@ -93,16 +75,14 @@ return $.effects.effect.size = function( o, done ) {
 
                // Vertical props scaling
                if ( factor.from.y !== factor.to.y ) {
-                       props = props.concat( vProps );
-                       el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
-                       el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
+                       from = $.effects.setTransition( element, vProps, factor.from.y, from );
+                       to = $.effects.setTransition( element, vProps, factor.to.y, to );
                }
 
                // Horizontal props scaling
                if ( factor.from.x !== factor.to.x ) {
-                       props = props.concat( hProps );
-                       el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
-                       el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
+                       from = $.effects.setTransition( element, hProps, factor.from.x, from );
+                       to = $.effects.setTransition( element, hProps, factor.to.x, to );
                }
        }
 
@@ -111,128 +91,100 @@ return $.effects.effect.size = function( o, done ) {
 
                // Vertical props scaling
                if ( factor.from.y !== factor.to.y ) {
-                       props = props.concat( cProps ).concat( props2 );
-                       el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
-                       el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
+                       from = $.effects.setTransition( element, cProps, factor.from.y, from );
+                       to = $.effects.setTransition( element, cProps, factor.to.y, to );
                }
        }
 
-       $.effects.save( el, props );
-       el.show();
-       $.effects.createWrapper( el );
-       el.css( "overflow", "hidden" ).css( el.from );
-
-       // Adjust
-       if (origin) { // Calculate baseline shifts
+       // Adjust the position properties based on the provided origin points
+       if ( origin ) {
                baseline = $.effects.getBaseline( origin, original );
-               el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
-               el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
-               el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
-               el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
+               from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
+               from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
+               to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
+               to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
        }
-       el.css( el.from ); // set top & left
+       element.css( from );
 
-       // Animate
-       if ( scale === "content" || scale === "both" ) { // Scale the children
+       // Animate the children if desired
+       if ( scale === "content" || scale === "both" ) {
 
-               // Add margins/font-size
-               vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
+               vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat( cProps );
                hProps = hProps.concat([ "marginLeft", "marginRight" ]);
-               props2 = props0.concat(vProps).concat(hProps);
 
-               el.find( "*[width]" ).each( function() {
+               // Only animate children with width attributes specified
+               // TODO: is this right? should we include anything with css width specified as well
+               element.find( "*[width]" ).each( function() {
                        var child = $( this ),
-                               c_original = {
-                                       height: child.height(),
-                                       width: child.width(),
-                                       outerHeight: child.outerHeight(),
-                                       outerWidth: child.outerWidth()
+                               childOriginal = $.effects.scaledDimensions( child ),
+                               childFrom = {
+                                       height: childOriginal.height * factor.from.y,
+                                       width: childOriginal.width * factor.from.x,
+                                       outerHeight: childOriginal.outerHeight * factor.from.y,
+                                       outerWidth: childOriginal.outerWidth * factor.from.x
+                               },
+                               childTo = {
+                                       height: childOriginal.height * factor.to.y,
+                                       width: childOriginal.width * factor.to.x,
+                                       outerHeight: childOriginal.height * factor.to.y,
+                                       outerWidth: childOriginal.width * factor.to.x
                                };
-                       if (restore) {
-                               $.effects.save(child, props2);
-                       }
-
-                       child.from = {
-                               height: c_original.height * factor.from.y,
-                               width: c_original.width * factor.from.x,
-                               outerHeight: c_original.outerHeight * factor.from.y,
-                               outerWidth: c_original.outerWidth * factor.from.x
-                       };
-                       child.to = {
-                               height: c_original.height * factor.to.y,
-                               width: c_original.width * factor.to.x,
-                               outerHeight: c_original.height * factor.to.y,
-                               outerWidth: c_original.width * factor.to.x
-                       };
 
                        // Vertical props scaling
                        if ( factor.from.y !== factor.to.y ) {
-                               child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
-                               child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
+                               childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
+                               childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
                        }
 
                        // Horizontal props scaling
                        if ( factor.from.x !== factor.to.x ) {
-                               child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
-                               child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
+                               childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
+                               childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
+                       }
+
+                       if ( restore ) {
+                               $.effects.saveStyle( child );
                        }
 
                        // Animate children
-                       child.css( child.from );
-                       child.animate( child.to, o.duration, o.easing, function() {
+                       child.css( childFrom );
+                       child.animate( childTo, options.duration, options.easing, function() {
 
                                // Restore children
                                if ( restore ) {
-                                       $.effects.restore( child, props2 );
+                                       $.effects.restoreStyle( child );
                                }
                        });
                });
        }
 
        // Animate
-       el.animate( el.to, {
+       element.animate( to, {
                queue: false,
-               duration: o.duration,
-               easing: o.easing,
+               duration: options.duration,
+               easing: options.easing,
                complete: function() {
-                       if ( el.to.opacity === 0 ) {
-                               el.css( "opacity", el.from.opacity );
-                       }
-                       if ( mode === "hide" ) {
-                               el.hide();
+
+                       var offset = element.offset();
+
+                       if ( to.opacity === 0 ) {
+                               element.css( "opacity", from.opacity );
                        }
-                       $.effects.restore( el, props );
+
                        if ( !restore ) {
+                               element
+                                       .css( "position", position === "static" ? "relative" : position )
+                                       .offset( offset );
 
-                               // we need to calculate our new positioning based on the scaling
-                               if ( position === "static" ) {
-                                       el.css({
-                                               position: "relative",
-                                               top: el.to.top,
-                                               left: el.to.left
-                                       });
-                               } else {
-                                       $.each([ "top", "left" ], function( idx, pos ) {
-                                               el.css( pos, function( _, str ) {
-                                                       var val = parseInt( str, 10 ),
-                                                               toRef = idx ? el.to.left : el.to.top;
-
-                                                       // if original was "auto", recalculate the new value from wrapper
-                                                       if ( str === "auto" ) {
-                                                               return toRef + "px";
-                                                       }
-
-                                                       return val + toRef + "px";
-                                               });
-                                       });
-                               }
+                               // Need to save style here so that automatic style restoration
+                               // doesn't restore to the original styles from before the animation.
+                               $.effects.saveStyle( element );
                        }
 
-                       $.effects.removeWrapper( el );
                        done();
                }
        });
 
-};
+});
 
 }));
index ec1fec6291f41e24b2619db3b01fb66f0778539b..03086a9285c16d145840770f001964452c0f54bd 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.slide = function( o, done ) {
-
-       // Create element
-       var el = $( this ),
-               props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
-               mode = $.effects.setMode( el, o.mode || "show" ),
-               show = mode === "show",
-               direction = o.direction || "left",
-               ref = (direction === "up" || direction === "down") ? "top" : "left",
-               positiveMotion = (direction === "up" || direction === "left"),
-               distance,
+return $.effects.define( "slide", "show", function( options, done ) {
+       var startClip, startRef,
+               element = $( this ),
+               map = {
+                       up: [ "bottom", "top" ],
+                       down: [ "top", "bottom" ],
+                       left: [ "right", "left" ],
+                       right: [ "left", "right" ]
+               },
+               mode = options.mode,
+               direction = options.direction || "left",
+               ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
+               positiveMotion = ( direction === "up" || direction === "left" ),
+               distance = options.distance || element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
                animation = {};
 
-       // Adjust
-       $.effects.save( el, props );
-       el.show();
-       distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
+       $.effects.createPlaceholder( element );
 
-       $.effects.createWrapper( el ).css({
-               overflow: "hidden"
-       });
+       startClip = element.cssClip();
+       startRef = element.position()[ ref ];
 
-       if ( show ) {
-               el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
-       }
+       // Define hide animation
+       animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
+       animation.clip = element.cssClip();
+       animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
 
-       // Animation
-       animation[ ref ] = ( show ?
-               ( positiveMotion ? "+=" : "-=") :
-               ( positiveMotion ? "-=" : "+=")) +
-               distance;
+       // Reverse the animation if we're showing
+       if ( mode === "show" ) {
+               element.cssClip( animation.clip );
+               element.css( ref, animation[ ref ] );
+               animation.clip = startClip;
+               animation[ ref ] = startRef;
+       }
 
-       // Animate
-       el.animate( animation, {
+       // Actually animate
+       element.animate( animation, {
                queue: false,
-               duration: o.duration,
-               easing: o.easing,
-               complete: function() {
-                       if ( mode === "hide" ) {
-                               el.hide();
-                       }
-                       $.effects.restore( el, props );
-                       $.effects.removeWrapper( el );
-                       done();
-               }
+               duration: options.duration,
+               easing: options.easing,
+               complete: done
        });
-};
+});
 
 }));
index 1008e5b47b55891b88cab247460c5554b33e72d7..78f12881ebe0842088d66624c608d92662993eae 100644 (file)
        }
 }(function( $ ) {
 
-return $.effects.effect.transfer = function( o, done ) {
-       var elem = $( this ),
-               target = $( o.to ),
-               targetFixed = target.css( "position" ) === "fixed",
-               body = $("body"),
-               fixTop = targetFixed ? body.scrollTop() : 0,
-               fixLeft = targetFixed ? body.scrollLeft() : 0,
-               endPosition = target.offset(),
-               animation = {
-                       top: endPosition.top - fixTop,
-                       left: endPosition.left - fixLeft,
-                       height: target.innerHeight(),
-                       width: target.innerWidth()
-               },
-               startPosition = elem.offset(),
-               transfer = $( "<div class='ui-effects-transfer'></div>" )
-                       .appendTo( document.body )
-                       .addClass( o.className )
-                       .css({
-                               top: startPosition.top - fixTop,
-                               left: startPosition.left - fixLeft,
-                               height: elem.innerHeight(),
-                               width: elem.innerWidth(),
-                               position: targetFixed ? "fixed" : "absolute"
-                       })
-                       .animate( animation, o.duration, o.easing, function() {
-                               transfer.remove();
-                               done();
-                       });
-};
+if ( $.uiBackCompat !== false ) {
+       return $.effects.define( "transfer", function( options, done ) {
+               $( this ).transfer( options, done );
+       });
+}
 
 }));
index fbbd7fe28819332f5af58b28b49482cd9427e698..4507ea00658f5912712a832ee76b3e6f06ee0848 100644 (file)
@@ -26,6 +26,8 @@
 }(function( $ ) {
 
 var dataSpace = "ui-effects-",
+       dataSpaceStyle = "ui-effects-style",
+       dataSpaceAnimated = "ui-effects-animated",
 
        // Create a local jQuery because jQuery Color relies on it and the
        // global may not exist with AMD and a custom build (#10199)
@@ -908,155 +910,328 @@ $.fn.extend({
 
 (function() {
 
+if ( $.expr && $.expr.filters && $.expr.filters.animated ) {
+       $.expr.filters.animated = (function( orig ) {
+               return function( elem ) {
+                       return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
+               };
+       })( $.expr.filters.animated );
+}
+
+if ( $.uiBackCompat !== false ) {
+       $.extend( $.effects, {
+               // Saves a set of properties in a data storage
+               save: function( element, set ) {
+                       var i = 0, length = set.length;
+                       for ( ; i < length; i++ ) {
+                               if ( set[ i ] !== null ) {
+                                       element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
+                               }
+                       }
+               },
+
+               // Restores a set of previously saved properties from a data storage
+               restore: function( element, set ) {
+                       var val, i = 0, length = set.length;
+                       for ( ; i < length; i++ ) {
+                               if ( set[ i ] !== null ) {
+                                       val = element.data( dataSpace + set[ i ] );
+                                       // support: jQuery 1.6.2
+                                       // http://bugs.jquery.com/ticket/9917
+                                       // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
+                                       // We can't differentiate between "" and 0 here, so we just assume
+                                       // empty string since it's likely to be a more common value...
+                                       if ( val === undefined ) {
+                                               val = "";
+                                       }
+                                       element.css( set[ i ], val );
+                               }
+                       }
+               },
+
+               setMode: function( el, mode ) {
+                       if ( mode === "toggle" ) {
+                               mode = el.is( ":hidden" ) ? "show" : "hide";
+                       }
+                       return mode;
+               },
+
+               // Wraps the element around a wrapper that copies position properties
+               createWrapper: function( element ) {
+
+                       // if the element is already wrapped, return it
+                       if ( element.parent().is( ".ui-effects-wrapper" ) ) {
+                               return element.parent();
+                       }
+
+                       // wrap the element
+                       var props = {
+                                       width: element.outerWidth( true ),
+                                       height: element.outerHeight( true ),
+                                       "float": element.css( "float" )
+                               },
+                               wrapper = $( "<div></div>" )
+                                       .addClass( "ui-effects-wrapper" )
+                                       .css({
+                                               fontSize: "100%",
+                                               background: "transparent",
+                                               border: "none",
+                                               margin: 0,
+                                               padding: 0
+                                       }),
+                               // Store the size in case width/height are defined in % - Fixes #5245
+                               size = {
+                                       width: element.width(),
+                                       height: element.height()
+                               },
+                               active = document.activeElement;
+
+                       // support: Firefox
+                       // Firefox incorrectly exposes anonymous content
+                       // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
+                       try {
+                               active.id;
+                       } catch ( e ) {
+                               active = document.body;
+                       }
+
+                       element.wrap( wrapper );
+
+                       // Fixes #7595 - Elements lose focus when wrapped.
+                       if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+                               $( active ).focus();
+                       }
+
+                       wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
+
+                       // transfer positioning properties to the wrapper
+                       if ( element.css( "position" ) === "static" ) {
+                               wrapper.css({ position: "relative" });
+                               element.css({ position: "relative" });
+                       } else {
+                               $.extend( props, {
+                                       position: element.css( "position" ),
+                                       zIndex: element.css( "z-index" )
+                               });
+                               $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
+                                       props[ pos ] = element.css( pos );
+                                       if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
+                                               props[ pos ] = "auto";
+                                       }
+                               });
+                               element.css({
+                                       position: "relative",
+                                       top: 0,
+                                       left: 0,
+                                       right: "auto",
+                                       bottom: "auto"
+                               });
+                       }
+                       element.css(size);
+
+                       return wrapper.css( props ).show();
+               },
+
+               removeWrapper: function( element ) {
+                       var active = document.activeElement;
+
+                       if ( element.parent().is( ".ui-effects-wrapper" ) ) {
+                               element.parent().replaceWith( element );
+
+                               // Fixes #7595 - Elements lose focus when wrapped.
+                               if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+                                       $( active ).focus();
+                               }
+                       }
+
+                       return element;
+               }
+       });
+}
+
 $.extend( $.effects, {
        version: "@VERSION",
 
-       // Saves a set of properties in a data storage
-       save: function( element, set ) {
-               for ( var i = 0; i < set.length; i++ ) {
-                       if ( set[ i ] !== null ) {
-                               element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
-                       }
+       define: function( name, mode, effect ) {
+               if ( !effect ) {
+                       effect = mode;
+                       mode = "effect";
                }
+
+               $.effects.effect[ name ] = effect;
+               $.effects.effect[ name ].mode = mode;
+
+               return effect;
        },
 
-       // Restores a set of previously saved properties from a data storage
-       restore: function( element, set ) {
-               var val, i;
-               for ( i = 0; i < set.length; i++ ) {
-                       if ( set[ i ] !== null ) {
-                               val = element.data( dataSpace + set[ i ] );
-                               // support: jQuery 1.6.2
-                               // http://bugs.jquery.com/ticket/9917
-                               // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
-                               // We can't differentiate between "" and 0 here, so we just assume
-                               // empty string since it's likely to be a more common value...
-                               if ( val === undefined ) {
-                                       val = "";
-                               }
-                               element.css( set[ i ], val );
-                       }
+       scaledDimensions: function( element, percent, direction ) {
+               if ( percent === 0 ) {
+                       return {
+                               height: 0,
+                               width: 0,
+                               outerHeight: 0,
+                               outerWidth: 0
+                       };
                }
+
+               var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
+                       y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
+
+               return {
+                       height: element.height() * y,
+                       width: element.width() * x,
+                       outerHeight: element.outerHeight() * y,
+                       outerWidth: element.outerWidth() * x
+               };
+
+       },
+
+       clipToBox: function( animation ) {
+               return {
+                       width: animation.clip.right - animation.clip.left,
+                       height: animation.clip.bottom - animation.clip.top,
+                       left: animation.clip.left,
+                       top: animation.clip.top
+               };
+       },
+
+       // Injects recently queued functions to be first in line (after "inprogress")
+       unshift: function( element, queueLength, count ) {
+               var queue = element.queue();
+
+               if ( queueLength > 1 ) {
+                       queue.splice.apply( queue,
+                               [ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
+               }
+               element.dequeue();
+       },
+
+       saveStyle: function( element ) {
+               element.data( dataSpaceStyle, element[ 0 ].style.cssText );
+       },
+
+       restoreStyle: function( element ) {
+               element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
+               element.removeData( dataSpaceStyle );
        },
 
-       setMode: function( el, mode ) {
-               if (mode === "toggle") {
-                       mode = el.is( ":hidden" ) ? "show" : "hide";
+       mode: function( element, mode ) {
+               var hidden = element.is( ":hidden" );
+
+               if ( mode === "toggle" ) {
+                       mode = hidden ? "show" : "hide";
+               }
+               if ( hidden ? mode === "hide" : mode === "show" ) {
+                       mode = "none";
                }
                return mode;
        },
 
        // Translates a [top,left] array into a baseline value
-       // this should be a little more flexible in the future to handle a string & hash
        getBaseline: function( origin, original ) {
                var y, x;
+
                switch ( origin[ 0 ] ) {
-                       case "top": y = 0; break;
-                       case "middle": y = 0.5; break;
-                       case "bottom": y = 1; break;
-                       default: y = origin[ 0 ] / original.height;
+               case "top":
+                       y = 0;
+                       break;
+               case "middle":
+                       y = 0.5;
+                       break;
+               case "bottom":
+                       y = 1;
+                       break;
+               default:
+                       y = origin[ 0 ] / original.height;
                }
+
                switch ( origin[ 1 ] ) {
-                       case "left": x = 0; break;
-                       case "center": x = 0.5; break;
-                       case "right": x = 1; break;
-                       default: x = origin[ 1 ] / original.width;
+               case "left":
+                       x = 0;
+                       break;
+               case "center":
+                       x = 0.5;
+                       break;
+               case "right":
+                       x = 1;
+                       break;
+               default:
+                       x = origin[ 1 ] / original.width;
                }
+
                return {
                        x: x,
                        y: y
                };
        },
 
-       // Wraps the element around a wrapper that copies position properties
-       createWrapper: function( element ) {
-
-               // if the element is already wrapped, return it
-               if ( element.parent().is( ".ui-effects-wrapper" )) {
-                       return element.parent();
-               }
-
-               // wrap the element
-               var props = {
-                               width: element.outerWidth(true),
-                               height: element.outerHeight(true),
+       // Creates a placeholder element so that the original element can be made absolute
+       createPlaceholder: function( element ) {
+               var placeholder,
+                       cssPosition = element.css( "position" ),
+                       position = element.position();
+
+               // Lock in margins first to account for form elements, which
+               // will change margin if you explicitly set height
+               // see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
+               // Support: Safari
+               element.css({
+                       marginTop: element.css( "marginTop" ),
+                       marginBottom: element.css( "marginBottom" ),
+                       marginLeft: element.css( "marginLeft" ),
+                       marginRight: element.css( "marginRight" )
+               })
+               .outerWidth( element.outerWidth() )
+               .outerHeight( element.outerHeight() );
+
+               if ( /^(static|relative)/.test( cssPosition ) ) {
+                       cssPosition = "absolute";
+
+                       placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css({
+
+                               // Convert inline to inline block to account for inline elements
+                               // that turn to inline block based on content (like img)
+                               display: /^(inline|ruby)/.test( element.css( "display" ) ) ? "inline-block" : "block",
+                               visibility: "hidden",
+
+                               // Margins need to be set to account for margin collapse
+                               marginTop: element.css( "marginTop" ),
+                               marginBottom: element.css( "marginBottom" ),
+                               marginLeft: element.css( "marginLeft" ),
+                               marginRight: element.css( "marginRight" ),
                                "float": element.css( "float" )
-                       },
-                       wrapper = $( "<div></div>" )
-                               .addClass( "ui-effects-wrapper" )
-                               .css({
-                                       fontSize: "100%",
-                                       background: "transparent",
-                                       border: "none",
-                                       margin: 0,
-                                       padding: 0
-                               }),
-                       // Store the size in case width/height are defined in % - Fixes #5245
-                       size = {
-                               width: element.width(),
-                               height: element.height()
-                       },
-                       active = document.activeElement;
-
-               // support: Firefox
-               // Firefox incorrectly exposes anonymous content
-               // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
-               try {
-                       active.id;
-               } catch ( e ) {
-                       active = document.body;
-               }
+                       })
+                       .outerWidth( element.outerWidth() )
+                       .outerHeight( element.outerHeight() )
+                       .addClass( "ui-effects-placeholder" );
 
-               element.wrap( wrapper );
-
-               // Fixes #7595 - Elements lose focus when wrapped.
-               if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
-                       $( active ).focus();
+                       element.data( dataSpace + "placeholder", placeholder );
                }
 
-               wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
-
-               // transfer positioning properties to the wrapper
-               if ( element.css( "position" ) === "static" ) {
-                       wrapper.css({ position: "relative" });
-                       element.css({ position: "relative" });
-               } else {
-                       $.extend( props, {
-                               position: element.css( "position" ),
-                               zIndex: element.css( "z-index" )
-                       });
-                       $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
-                               props[ pos ] = element.css( pos );
-                               if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
-                                       props[ pos ] = "auto";
-                               }
-                       });
-                       element.css({
-                               position: "relative",
-                               top: 0,
-                               left: 0,
-                               right: "auto",
-                               bottom: "auto"
-                       });
-               }
-               element.css(size);
+               element.css({
+                       position: cssPosition,
+                       left: position.left,
+                       top: position.top
+               });
 
-               return wrapper.css( props ).show();
+               return placeholder;
        },
 
-       removeWrapper: function( element ) {
-               var active = document.activeElement;
+       removePlaceholder: function( element ) {
+               var dataKey = dataSpace + "placeholder",
+                               placeholder = element.data( dataKey );
 
-               if ( element.parent().is( ".ui-effects-wrapper" ) ) {
-                       element.parent().replaceWith( element );
-
-                       // Fixes #7595 - Elements lose focus when wrapped.
-                       if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
-                               $( active ).focus();
-                       }
+               if ( placeholder ) {
+                       placeholder.remove();
+                       element.removeData( dataKey );
                }
+       },
 
-               return element;
+       // Removes a placeholder if it exists and restores
+       // properties that were modified during placeholder creation
+       cleanUp: function( element ) {
+               $.effects.restoreStyle( element );
+               $.effects.removePlaceholder( element );
        },
 
        setTransition: function( element, list, factor, value ) {
@@ -1152,48 +1327,109 @@ function standardAnimationOption( option ) {
 $.fn.extend({
        effect: function( /* effect, options, speed, callback */ ) {
                var args = _normalizeArguments.apply( this, arguments ),
-                       mode = args.mode,
+                       effectMethod = $.effects.effect[ args.effect ],
+                       defaultMode = effectMethod.mode,
                        queue = args.queue,
-                       effectMethod = $.effects.effect[ args.effect ];
+                       queueName = queue || "fx",
+                       complete = args.complete,
+                       mode = args.mode,
+                       modes = [],
+                       prefilter = function( next ) {
+                               var el = $( this ),
+                                       normalizedMode = $.effects.mode( el, mode ) || defaultMode;
+
+                               // Sentinel for duck-punching the :animated psuedo-selector
+                               el.data( dataSpaceAnimated, true );
+
+                               // Save effect mode for later use,
+                               // we can't just call $.effects.mode again later,
+                               // as the .show() below destroys the initial state
+                               modes.push( normalizedMode );
+
+                               // See $.uiBackCompat inside of run() for removal of defaultMode in 1.13
+                               if ( defaultMode && ( normalizedMode === "show" ||
+                                               ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
+                                       el.show();
+                               }
+
+                               if ( !defaultMode || normalizedMode !== "none" ) {
+                                       $.effects.saveStyle( el );
+                               }
+
+                               if ( $.isFunction( next ) ) {
+                                       next();
+                               }
+                       };
 
                if ( $.fx.off || !effectMethod ) {
                        // delegate to the original method (e.g., .show()) if possible
                        if ( mode ) {
-                               return this[ mode ]( args.duration, args.complete );
+                               return this[ mode ]( args.duration, complete );
                        } else {
                                return this.each( function() {
-                                       if ( args.complete ) {
-                                               args.complete.call( this );
+                                       if ( complete ) {
+                                               complete.call( this );
                                        }
                                });
                        }
                }
 
                function run( next ) {
-                       var elem = $( this ),
-                               complete = args.complete,
-                               mode = args.mode;
+                       var elem = $( this );
+
+                       function cleanup() {
+                               elem.removeData( dataSpaceAnimated );
+
+                               $.effects.cleanUp( elem );
+
+                               if ( args.mode === "hide" ) {
+                                       elem.hide();
+                               }
+
+                               done();
+                       }
 
                        function done() {
                                if ( $.isFunction( complete ) ) {
-                                       complete.call( elem[0] );
+                                       complete.call( elem[ 0 ] );
                                }
+
                                if ( $.isFunction( next ) ) {
                                        next();
                                }
                        }
 
-                       // If the element already has the correct final state, delegate to
-                       // the core methods so the internal tracking of "olddisplay" works.
-                       if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
-                               elem[ mode ]();
-                               done();
+                       // Override mode option on a per element basis,
+                       // as toggle can be either show or hide depending on element state
+                       args.mode = modes.shift();
+
+                       if ( $.uiBackCompat !== false && !defaultMode ) {
+                               if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
+
+                                       // Call the core method to track "olddisplay" properly
+                                       elem[ mode ]();
+                                       done();
+                               } else {
+                                       effectMethod.call( elem[ 0 ], args, done );
+                               }
                        } else {
-                               effectMethod.call( elem[0], args, done );
+                               if ( args.mode === "none" ) {
+
+                                       // Call the core method to track "olddisplay" properly
+                                       elem[ mode ]();
+                                       done();
+                               } else {
+                                       effectMethod.call( elem[ 0 ], args, cleanup );
+                               }
                        }
                }
 
-               return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
+               // Run prefilter on all elements first to ensure that
+               // any showing or hiding happens before placeholder creation,
+               // which ensures that any layout changes are correctly captured.
+               return queue === false ?
+                       this.each( prefilter ).each( run ) :
+                       this.queue( queueName, prefilter ).queue( queueName, run );
        },
 
        show: (function( orig ) {
@@ -1232,7 +1468,6 @@ $.fn.extend({
                };
        })( $.fn.toggle ),
 
-       // helper functions
        cssUnit: function(key) {
                var style = this.css( key ),
                        val = [];
@@ -1243,9 +1478,77 @@ $.fn.extend({
                        }
                });
                return val;
+       },
+
+       cssClip: function( clipObj ) {
+               return clipObj ?
+                       this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + clipObj.bottom + "px " + clipObj.left + "px)" ) :
+                       parseClip( this.css("clip"), this );
+       },
+
+       transfer: function( options, done ) {
+               var element = $( this ),
+                       target = $( options.to ),
+                       targetFixed = target.css( "position" ) === "fixed",
+                       body = $( "body" ),
+                       fixTop = targetFixed ? body.scrollTop() : 0,
+                       fixLeft = targetFixed ? body.scrollLeft() : 0,
+                       endPosition = target.offset(),
+                       animation = {
+                               top: endPosition.top - fixTop,
+                               left: endPosition.left - fixLeft,
+                               height: target.innerHeight(),
+                               width: target.innerWidth()
+                       },
+                       startPosition = element.offset(),
+                       transfer = $( "<div class='ui-effects-transfer'></div>" )
+                               .appendTo( "body" )
+                               .addClass( options.className )
+                               .css({
+                                       top: startPosition.top - fixTop,
+                                       left: startPosition.left - fixLeft,
+                                       height: element.innerHeight(),
+                                       width: element.innerWidth(),
+                                       position: targetFixed ? "fixed" : "absolute"
+                               })
+                               .animate( animation, options.duration, options.easing, function() {
+                                       transfer.remove();
+                                       done();
+                               });
        }
 });
 
+function parseClip( str, element ) {
+               var outerWidth = element.outerWidth(),
+                       outerHeight = element.outerHeight(),
+                       clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,
+                       values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
+
+               return {
+                       top: parseFloat( values[ 1 ] ) || 0,
+                       right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
+                       bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
+                       left: parseFloat( values[ 4 ] ) || 0
+               };
+}
+
+$.fx.step.clip = function( fx ) {
+       if ( !fx.clipInit ) {
+               fx.start = $( fx.elem ).cssClip();
+               if ( typeof fx.end === "string" ) {
+                       fx.end = parseClip( fx.end, fx.elem );
+               }
+               fx.clipInit = true;
+       }
+
+       $( fx.elem ).cssClip({
+               top: fx.pos * (fx.end.top - fx.start.top) + fx.start.top,
+               right: fx.pos * (fx.end.right - fx.start.right) + fx.start.right,
+               bottom: fx.pos * (fx.end.bottom - fx.start.bottom) + fx.start.bottom,
+               left: fx.pos * (fx.end.left - fx.start.left) + fx.start.left
+       });
+};
+
 })();
 
 /******************************************************************************/