Permalink
Browse files

Fix #8498. Add cssHooks[prop].expand for use by animate().

  • Loading branch information...
1 parent 7f6a991 commit 8f5f1b2e6c0f7b8b6d66bfc06c7b169a9443c2b8 @mikesherov mikesherov committed with dmethvin Dec 9, 2011
Showing with 127 additions and 21 deletions.
  1. +43 −17 src/css.js
  2. +17 −4 src/effects.js
  3. +40 −0 test/unit/css.js
  4. +27 −0 test/unit/effects.js
View
@@ -10,8 +10,10 @@ var ralpha = /alpha\([^)]*\)/i,
rmargin = /^margin/,
cssShow = { position: "absolute", visibility: "hidden", display: "block" },
- cssWidth = [ "Left", "Right" ],
- cssHeight = [ "Top", "Bottom" ],
+
+ // order is important!
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+
curCSS,
getComputedStyle,
@@ -169,10 +171,10 @@ jQuery.each(["height", "width"], function( i, name ) {
get: function( elem, computed, extra ) {
if ( computed ) {
if ( elem.offsetWidth !== 0 ) {
- return getWH( elem, name, extra );
+ return getWidthOrHeight( elem, name, extra );
} else {
return jQuery.swap( elem, cssShow, function() {
- return getWH( elem, name, extra );
+ return getWidthOrHeight( elem, name, extra );
});
}
}
@@ -326,24 +328,23 @@ if ( document.documentElement.currentStyle ) {
curCSS = getComputedStyle || currentStyle;
-function getWH( elem, name, extra ) {
+function getWidthOrHeight( elem, name, extra ) {
// Start with offset property
var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
- which = name === "width" ? cssWidth : cssHeight,
- i = 0,
- len = which.length;
+ i = name === "width" ? 1 : 0,
+ len = 4;
if ( val > 0 ) {
if ( extra !== "border" ) {
- for ( ; i < len; i++ ) {
+ for ( ; i < len; i += 2 ) {
if ( !extra ) {
- val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
+ val -= parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
}
if ( extra === "margin" ) {
- val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
+ val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;
} else {
- val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
+ val -= parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
}
}
}
@@ -354,20 +355,20 @@ function getWH( elem, name, extra ) {
// Fall back to computed then uncomputed css if necessary
val = curCSS( elem, name, name );
if ( val < 0 || val == null ) {
- val = elem.style[ name ] || 0;
+ val = elem.style[ name ];
}
// Normalize "", auto, and prepare for extra
val = parseFloat( val ) || 0;
// Add padding, border, margin
if ( extra ) {
- for ( ; i < len; i++ ) {
- val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
+ for ( ; i < len; i += 2 ) {
+ val += parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0;
if ( extra !== "padding" ) {
- val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
+ val += parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
}
if ( extra === "margin" ) {
- val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
+ val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;
}
}
}
@@ -388,4 +389,29 @@ if ( jQuery.expr && jQuery.expr.filters ) {
};
}
+// These hooks are used by animate to expand properties
+jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i,
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ],
+ expanded = {};
+
+ for ( i = 0; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+});
+
})( jQuery );
View
@@ -142,24 +142,37 @@ jQuery.fn.extend({
var opt = jQuery.extend( {}, optall ),
isElement = this.nodeType === 1,
hidden = isElement && jQuery(this).is(":hidden"),
- name, val, p, e,
+ name, val, p, e, hooks, replace,
parts, start, end, unit,
method;
// will store per property easing and be used to determine when an animation is complete
opt.animatedProperties = {};
+ // first pass over propertys to expand / normalize
for ( p in prop ) {
-
- // property name normalization
name = jQuery.camelCase( p );
if ( p !== name ) {
prop[ name ] = prop[ p ];
delete prop[ p ];
}
+
+ if ( ( hooks = jQuery.cssHooks[ name ] ) && "expand" in hooks ) {
+ replace = hooks.expand( prop[ name ] );
+ delete prop[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'p' from above because we have the correct "name"
+ for ( p in replace ) {
+ if ( ! ( p in prop ) ) {
+ prop[ p ] = replace[ p ];
+ }
+ }
+ }
+ }
+ for ( name in prop ) {
val = prop[ name ];
-
// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
if ( jQuery.isArray( val ) ) {
opt.animatedProperties[ name ] = val[ 1 ];
View
@@ -549,4 +549,44 @@ test("outerWidth(true) and css('margin') returning % instead of px in Webkit, se
el = jQuery( "<div/>" ).css({ width: "50%", marginRight: "50%" }).appendTo( container );
equal( el.outerWidth(true), 400, "outerWidth(true) and css('margin') returning % instead of px in Webkit, see #10639" );
+});
+
+test( "cssHooks - expand", function() {
+ expect( 15 );
+ var result,
+ properties = {
+ margin: [ "marginTop", "marginRight", "marginBottom", "marginLeft" ],
+ borderWidth: [ "borderTopWidth", "borderRightWidth", "borderBottomWidth", "borderLeftWidth"],
+ padding: [ "paddingTop", "paddingRight", "paddingBottom", "paddingLeft" ]
+ };
+
+ jQuery.each( properties, function( property, keys ) {
+ var hook = jQuery.cssHooks[ property ],
+ expected = {};
+ jQuery.each( keys, function( _, key ) {
+ expected[ key ] = 10;
+ });
+ result = hook.expand( 10 );
+ deepEqual( result, expected, property + " expands properly with a number" );
+
+ jQuery.each( keys, function( _, key ) {
+ expected[ key ] = "10px";
+ });
+ result = hook.expand( "10px" );
+ deepEqual( result, expected, property + " expands properly with '10px'" );
+
+ expected[ keys[1] ] = expected[ keys[3] ] = "20px";
+ result = hook.expand( "10px 20px" );
+ deepEqual( result, expected, property + " expands properly with '10px 20px'" );
+
+ expected[ keys[2] ] = "30px";
+ result = hook.expand( "10px 20px 30px" );
+ deepEqual( result, expected, property + " expands properly with '10px 20px 30px'" );
+
+ expected[ keys[3] ] = "40px";
+ result = hook.expand( "10px 20px 30px 40px" );
+ deepEqual( result, expected, property + " expands properly with '10px 20px 30px 40px'" );
+
+ });
+
});
View
@@ -1271,3 +1271,30 @@ asyncTest( "callbacks that throw exceptions will be removed (#5684)", function()
start();
}, 1);
});
+
+test("animate will scale margin properties individually", function() {
+ expect( 2 );
+ stop();
+
+ var foo = jQuery( "#foo" ).css({
+ margin: 0,
+ marginLeft: 100
+ });
+
+ ok( foo.css( "marginLeft" ) !== foo.css( "marginRight" ), "Sanity Check" );
+
+ foo.animate({
+ margin: 200
+ }).stop();
+
+ ok( foo.css( "marginLeft") !== foo.css( "marginRight" ), "The margin properties are different");
+
+ // clean up for next test
+ foo.css({
+ marginLeft: '',
+ marginRight: '',
+ marginTop: '',
+ marginBottom: ''
+ });
+ start();
+});

0 comments on commit 8f5f1b2

Please sign in to comment.