Skip to content

Instantly share code, notes, and snippets.

@mainyaa
Created July 8, 2012 16:22
Show Gist options
  • Save mainyaa/3071608 to your computer and use it in GitHub Desktop.
Save mainyaa/3071608 to your computer and use it in GitHub Desktop.
Monkey patch for jQuery 1.7 to optimize animation
(function ($) {
// Monkey patch for jQuery 1.7 to optimize animation
// Details:
// jQuery(this).is(":hidden")) access elem.offsetHeight property in each animation step.
// This patch enables lazy access to elem.offsetHeight property only when it is necessary.
// 2012/07/26: this patch is unnecessary on jQuery 1.8. fixed by https://github.com/jquery/jquery/pull/869
var elemdisplay = {},
iframe, iframeDoc,
rfxtypes = /^(?:toggle|show|hide)$/,
rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
timerId,
fxAttrs = [
// height animations
[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
// width animations
[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
// opacity animations
[ "opacity" ]
],
fxNow;
$.fn._animate = $.fn.animate;
$.fn.animate = function( prop, speed, easing, callback ) {
var optall = jQuery.speed( speed, easing, callback );
if ( jQuery.isEmptyObject( prop ) ) {
return this.each( optall.complete, [ false ] );
}
// Do not change referenced properties as per-property easing will be lost
prop = jQuery.extend( {}, prop );
function doAnimation() {
// XXX 'this' does not always have a nodeName when running the
// test suite
if ( optall.queue === false ) {
jQuery._mark( this );
}
var opt = jQuery.extend( {}, optall ),
isElement = this.nodeType === 1,
hidden, name, val, p, e,
parts, start, end, unit,
method;
// will store per property easing and be used to determine when an animation is complete
opt.animatedProperties = {};
for ( p in prop ) {
// property name normalization
name = jQuery.camelCase( p );
if ( p !== name ) {
prop[ name ] = prop[ p ];
delete prop[ p ];
}
val = prop[ name ];
// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
if ( jQuery.isArray( val ) ) {
opt.animatedProperties[ name ] = val[ 1 ];
val = prop[ name ] = val[ 0 ];
} else {
opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
}
if ( val === "hide" && (isElement && jQuery(this).is(":hidden")) || val === "show" && !(isElement && jQuery(this).is(":hidden")) ) {
return opt.complete.call( this );
}
if ( isElement && ( name === "height" || name === "width" ) ) {
// Make sure that nothing sneaks out
// Record all 3 overflow attributes because IE does not
// change the overflow attribute when overflowX and
// overflowY are set to the same value
opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
// Set display property to inline-block for height/width
// animations on inline elements that are having width/height animated
if ( jQuery.css( this, "display" ) === "inline" &&
jQuery.css( this, "float" ) === "none" ) {
// inline-level elements accept inline-block;
// block-level elements need to be inline with layout
if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
this.style.display = "inline-block";
} else {
this.style.zoom = 1;
}
}
}
}
if ( opt.overflow != null ) {
this.style.overflow = "hidden";
}
for ( p in prop ) {
if ( prop[ p ] === "toggle" ) {
hidden = (isElement && jQuery(this).is(":hidden"));
}
}
for ( p in prop ) {
e = new jQuery.fx( this, opt, p );
val = prop[ p ];
if ( rfxtypes.test( val ) ) {
// Tracks whether to show or hide based on private
// data attached to the element
method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
if ( method ) {
jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
e[ method ]();
} else {
e[ val ]();
}
} else {
parts = rfxnum.exec( val );
start = e.cur();
if ( parts ) {
end = parseFloat( parts[2] );
unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
// We need to compute starting value
if ( unit !== "px" ) {
jQuery.style( this, p, (end || 1) + unit);
start = ( (end || 1) / e.cur() ) * start;
jQuery.style( this, p, start + unit);
}
// If a +=/-= token was provided, we're doing a relative animation
if ( parts[1] ) {
end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
}
e.custom( start, end, unit );
} else {
e.custom( start, val, "" );
}
}
}
// For JS strict compliance
return true;
}
return optall.queue === false ?
this.each( doAnimation ) :
this.queue( optall.queue, doAnimation );
};
})(jQuery);
(function(g){var l=/^(?:toggle|show|hide)$/,m=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i;g.fn._animate=g.fn.animate;g.fn.animate=function(d,g,n,o){function k(){var p;i.queue===!1&&jQuery._mark(this);var f=jQuery.extend({},i),e=this.nodeType===1,g,a,b,c,h,j;f.animatedProperties={};for(c in d){a=jQuery.camelCase(c);c!==a&&(d[a]=d[c],delete d[c]);b=d[a];jQuery.isArray(b)?(f.animatedProperties[a]=b[1],p=d[a]=b[0],b=p):f.animatedProperties[a]=f.specialEasing&&f.specialEasing[a]||f.easing||"swing";if(b==="hide"&&
e&&jQuery(this).is(":hidden")||b==="show"&&(!e||!jQuery(this).is(":hidden")))return f.complete.call(this);if(e&&(a==="height"||a==="width"))if(f.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],jQuery.css(this,"display")==="inline"&&jQuery.css(this,"float")==="none")!jQuery.support.inlineBlockNeedsLayout||defaultDisplay(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1}if(f.overflow!=null)this.style.overflow="hidden";for(c in d)d[c]==="toggle"&&
(g=e&&jQuery(this).is(":hidden"));for(c in d)if(e=new jQuery.fx(this,f,c),b=d[c],l.test(b))if(a=jQuery._data(this,"toggle"+c)||(b==="toggle"?g?"show":"hide":0))jQuery._data(this,"toggle"+c,a==="show"?"hide":"show"),e[a]();else e[b]();else a=m.exec(b),h=e.cur(),a?(b=parseFloat(a[2]),j=a[3]||(jQuery.cssNumber[c]?"":"px"),j!=="px"&&(jQuery.style(this,c,(b||1)+j),h*=(b||1)/e.cur(),jQuery.style(this,c,h+j)),a[1]&&(b=(a[1]==="-="?-1:1)*b+h),e.custom(h,b,j)):e.custom(h,b,"");return!0}var i=jQuery.speed(g,
n,o);if(jQuery.isEmptyObject(d))return this.each(i.complete,[!1]);d=jQuery.extend({},d);return i.queue===!1?this.each(k):this.queue(i.queue,k)}})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment