diff options
Diffstat (limited to 'src/effects.js')
-rw-r--r-- | src/effects.js | 178 |
1 files changed, 102 insertions, 76 deletions
diff --git a/src/effects.js b/src/effects.js index 4ead51ccd..3268fcda9 100644 --- a/src/effects.js +++ b/src/effects.js @@ -4,18 +4,19 @@ define([ "./var/rcssNum", "./css/var/cssExpand", "./css/var/isHidden", + "./css/var/swap", "./css/adjustCSS", - "./css/defaultDisplay", "./data/var/dataPriv", + "./css/showHide", "./core/init", - "./effects/Tween", "./queue", - "./css", "./deferred", - "./traversing" -], function( jQuery, document, rcssNum, cssExpand, - isHidden, adjustCSS, defaultDisplay, dataPriv ) { + "./traversing", + "./manipulation", + "./css", + "./effects/Tween" +], function( jQuery, document, rcssNum, cssExpand, isHidden, swap, adjustCSS, dataPriv, showHide ) { var fxNow, timerId, @@ -82,14 +83,15 @@ function createTween( value, prop, animation ) { function defaultPrefilter( elem, props, opts ) { /* jshint validthis: true */ - var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay, + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, anim = this, orig = {}, style = elem.style, hidden = elem.nodeType && isHidden( elem ), dataShow = dataPriv.get( elem, "fxshow" ); - // Handle queue: false promises + // Queue-skipping animations hijack the fx hooks if ( !opts.queue ) { hooks = jQuery._queueHooks( elem, "fx" ); if ( hooks.unqueued == null ) { @@ -114,24 +116,69 @@ function defaultPrefilter( elem, props, opts ) { }); } - // Height/width overflow pass - if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { - // Make sure that nothing sneaks out - // Record all 3 overflow attributes because IE9-10 do not - // change the overflow attribute when overflowX and - // overflowY are set to the same value + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + // Support: IE 9 - 11 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - // Set display property to inline-block for height/width - // animations on inline elements that are having width/height animated + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + display = restoreDisplay || swap( elem, { "display": "" }, function() { + return jQuery.css( elem, "display" ); + } ); + } - // Test default display if display is currently "none" - checkDisplay = display === "none" ? - dataPriv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display; - - if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) { - style.display = "inline-block"; + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done(function() { + style.display = restoreDisplay; + }); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } } } @@ -144,73 +191,52 @@ function defaultPrefilter( elem, props, opts ) { }); } - // show/hide pass - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.exec( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { - // If there is dataShow left over from a stopped hide or show - // and we are going to proceed with show, we should pretend to be hidden - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - } else { - continue; + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - // Any non-fx value stops us from restoring the original display value - } else { - display = undefined; - } - } + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } - if ( !jQuery.isEmptyObject( orig ) ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); } - } else { - dataShow = dataPriv.access( elem, "fxshow", {} ); - } - // Store state if its toggle - enables .stop().toggle() to "reverse" - if ( toggle ) { - dataShow.hidden = !hidden; - } - if ( hidden ) { - jQuery( elem ).show(); - } else { + /* jshint -W083 */ anim.done(function() { - jQuery( elem ).hide(); + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } }); } - anim.done(function() { - var prop; - dataPriv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - }); - for ( prop in orig ) { - tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = tween.start; - if ( hidden ) { - tween.end = tween.start; - tween.start = prop === "width" || prop === "height" ? 1 : 0; - } + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = prop === "width" || prop === "height" ? 1 : 0; } } - - // If this is a noop like .hide().hide(), restore an overwritten display value - } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) { - style.display = display; } } |