From 9dc29a2b130e6bbcdbcaf8fdc1433a41e6b7a585 Mon Sep 17 00:00:00 2001 From: Oleg Gaidarenko Date: Mon, 16 Jun 2014 02:59:41 +0400 Subject: [PATCH] Effects: Improve raf logic * Make animation behave as if jQuery.fx.off = true if document is hidden * Use cancelAnimationFrame in jQuery.fx.stop Ref 708764f47b0c8de152bbb444d0f608db558b76ed --- src/effects.js | 42 ++++++++++++++++++------------------------ test/unit/effects.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/src/effects.js b/src/effects.js index af61de705..225b31240 100644 --- a/src/effects.js +++ b/src/effects.js @@ -78,11 +78,6 @@ function raf() { } } -// Will get false negative for old browsers which is okay -function isDocumentHidden() { - return "hidden" in document && document.hidden; -} - // Animations created synchronously will run synchronously function createFxNow() { setTimeout(function() { @@ -446,8 +441,15 @@ jQuery.speed = function( speed, easing, fn ) { easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing }; - opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : - opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; + // Go to the end state if fx are off or if document is hidden + if ( jQuery.fx.off || document.hidden ) { + opt.duration = 0; + + } else { + opt.duration = typeof opt.duration === "number" ? + opt.duration : opt.duration in jQuery.fx.speeds ? + jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; + } // normalize opt.queue - true/undefined/null -> "fx" if ( opt.queue == null || opt.queue === true ) { @@ -472,10 +474,6 @@ jQuery.speed = function( speed, easing, fn ) { jQuery.fn.extend({ fadeTo: function( speed, to, easing, callback ) { - if ( isDocumentHidden() ) { - return this; - } - // show any hidden elements after setting opacity to 0 return this.filter( isHidden ).css( "opacity", 0 ).show() @@ -483,10 +481,6 @@ jQuery.fn.extend({ .end().animate({ opacity: to }, speed, easing, callback ); }, animate: function( prop, speed, easing, callback ) { - if ( isDocumentHidden() ) { - return this; - } - var empty = jQuery.isEmptyObject( prop ), optall = jQuery.speed( speed, easing, callback ), doAnimation = function() { @@ -654,18 +648,18 @@ jQuery.fx.timer = function( timer ) { jQuery.fx.interval = 13; jQuery.fx.start = function() { - if ( !timerId ) { - if ( window.requestAnimationFrame ) { - timerId = true; - window.requestAnimationFrame( raf ); - } else { - timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); - } - } + timerId = window.requestAnimationFrame ? + window.requestAnimationFrame( raf ) : + setInterval( jQuery.fx.tick, jQuery.fx.interval ); }; jQuery.fx.stop = function() { - clearInterval( timerId ); + if ( window.cancelAnimationFrame ) { + window.cancelAnimationFrame( timerId ); + } else { + clearInterval( timerId ); + } + timerId = null; }; diff --git a/test/unit/effects.js b/test/unit/effects.js index 30d58ccd3..8e1f914cf 100644 --- a/test/unit/effects.js +++ b/test/unit/effects.js @@ -2239,4 +2239,32 @@ test( "Respect display value on inline elements (#14824)", 2, function() { clock.tick( 800 ); }); +test( "Animation should go to its end state if document.hidden = true", 1, function() { + var height; + if ( Object.defineProperty ) { + + // Can't rewrite document.hidden property if its host property + try { + Object.defineProperty( document, "hidden", { + get: function() { + return true; + } + }); + } catch ( e ) {} + } else { + document.hidden = true; + } + + if ( document.hidden ) { + height = jQuery( "#qunit-fixture" ).animate({ height: 500 } ).height(); + + equal( height, 500, "Animation should happen immediately if document.hidden = true" ); + jQuery( document ).removeProp( "hidden" ); + + } else { + ok( true, "Can't run the test since we can't reproduce correct environment for it" ); + } +}); + + })(); -- 2.39.5