Ticket #2503 (closed bug: duplicate)
jQuery.fx.update does not account for inline-block elements.
| Reported by: | apramanik | Owned by: | |
|---|---|---|---|
| Priority: | minor | Milestone: | |
| Component: | effects | Version: | 1.2.3 |
| Keywords: | Cc: | ||
| Blocking: | Blocked by: |
Description
I was getting popping in my animations for inline-block (or -moz-inline-box) spans due to them being changed to blocks in jQuery.fx.prototype. I fixed it by making the following changes:
jQuery.fx.prototype = {
// Simple function for setting a style value
update: function(){
if ( this.options.step )
this.options.step.apply( this.elem, [ this.now, this ] );
(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
// Set display property to block for height/width animations
if ( this.prop == "height" || this.prop == "width" )
this.elem.style.display = "block";
},
to
jQuery.fx.prototype = {
// Simple function for setting a style value
update: function(){
if ( this.options.step )
this.options.step.apply( this.elem, [ this.now, this ] );
(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
var comp_display = jQuery( this.elem ).css( 'display' );
// Set display property to block for height/width animations, if it isn't a
// block value already.
if ( ( this.prop == "height" || this.prop == "width" )
&& comp_display != "inline-block"
&& comp_display != "-moz-inline-box"
&& comp_display != "block" )
this.elem.style.display = "block";
},
As mentioned by John Resig, this solution would be slow because it is computing the display property on every frame of animation.
Change History
comment:2 Changed 5 years ago by apramanik
You can't specify what display to transition to on a 'show'. So I made the following changes to allow specification of a display attribute ( e.g. $j( 'a' ).animate( { height: 'show', display : 'inline-block' } ) ). If it isn't specified then it defaults to 'block':
// Simple function for setting a style value
update: function(){
if ( this.options.step )
this.options.step.apply( this.elem, [ this.now, this ] );
(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
// Set display property to block for height/width animations, if it isn't a
// block value already.
if ( ( this.prop == "height" || this.prop == "width" )
&& this.options.display != "inline-block"
&& this.options.display != "-moz-inline-box"
&& this.options.display != "block" )
{
this.elem.style.display = this.options.to_display ? this.options.to_display : "block";
}
},
...
step: function(gotoEnd){
var t = (new Date()).getTime();
if ( gotoEnd || t > this.options.duration + this.startTime ) {
this.now = this.end;
this.pos = this.state = 1;
this.update();
this.options.curAnim[ this.prop ] = true;
var done = true;
for ( var i in this.options.curAnim )
if ( this.options.curAnim[i] !== true )
done = false;
if ( done ) {
if ( this.options.display != null ) {
// Reset the overflow
this.elem.style.overflow = this.options.overflow;
// Reset the display
this.elem.style.display = this.options.display;
if ( jQuery.css(this.elem, "display") == "none" )
this.elem.style.display = this.options.to_display ? this.options.to_display : "block";
}
...
animate: function( prop, speed, easing, callback ) {
var optall = jQuery.speed(speed, easing, callback);
return this[ optall.queue === false ? "each" : "queue" ](function(){
if ( this.nodeType != 1)
return false;
var opt = jQuery.extend({}, optall);
var hidden = jQuery(this).is(":hidden"), self = this;
for ( var p in prop ) {
if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
if ( p == "height" || p == "width" ) {
// Store display property
opt.display = jQuery.css(this, "display");
opt.to_display = prop['display'];
// Make sure that nothing sneaks out
opt.overflow = this.style.overflow;
}
}
That's the best I could think of so far. I'm not fond of the conditionals and would rather just default this.options.to_display to 'block', but I'm not sure where the best place to put that would be.
Please follow the bug reporting guidlines and use jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

Change comp_display to this.options.display. This is computed on effect creation.