Skip to content

Commit d471842

Browse files
committed
CSS: Don't cache unrecognized CSS property names
This prevents jQuery from caching a prefixed property name if provided directly by the user, e.g. the following code: elem.css( "msTransform", "translate(5px, 2px)" ); should not prevent one from from later setting the transition directly: elem.css( "transform", "translate(5px, 2px)" ); on a browser not understanding the unprefixed version which is the case for Safari 8 & transform. Fixes gh-2015 Closes gh-2298
1 parent 6df669f commit d471842

File tree

2 files changed

+90
-11
lines changed

2 files changed

+90
-11
lines changed

src/css.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ define([
33
"./var/pnum",
44
"./core/access",
55
"./css/var/rmargin",
6+
"./var/document",
67
"./var/rcssNum",
78
"./css/var/rnumnonpx",
89
"./css/var/cssExpand",
@@ -18,8 +19,8 @@ define([
1819
"./core/init",
1920
"./core/ready",
2021
"./selector" // contains
21-
], function( jQuery, pnum, access, rmargin, rcssNum, rnumnonpx, cssExpand, isHidden,
22-
getStyles, swap, curCSS, adjustCSS, addGetHookIf, support, showHide ) {
22+
], function( jQuery, pnum, access, rmargin, document, rcssNum, rnumnonpx, cssExpand,
23+
isHidden, getStyles, swap, curCSS, adjustCSS, addGetHookIf, support, showHide ) {
2324

2425
var
2526
// Swappable if display is none or starts with table
@@ -34,29 +35,27 @@ var
3435
fontWeight: "400"
3536
},
3637

37-
cssPrefixes = [ "Webkit", "Moz", "ms" ];
38+
cssPrefixes = [ "Webkit", "Moz", "ms" ],
39+
emptyStyle = document.createElement( "div" ).style;
3840

3941
// Return a css property mapped to a potentially vendor prefixed property
40-
function vendorPropName( style, name ) {
42+
function vendorPropName( name ) {
4143

4244
// Shortcut for names that are not vendor prefixed
43-
if ( name in style ) {
45+
if ( name in emptyStyle ) {
4446
return name;
4547
}
4648

4749
// Check for vendor prefixed names
4850
var capName = name[0].toUpperCase() + name.slice(1),
49-
origName = name,
5051
i = cssPrefixes.length;
5152

5253
while ( i-- ) {
5354
name = cssPrefixes[ i ] + capName;
54-
if ( name in style ) {
55+
if ( name in emptyStyle ) {
5556
return name;
5657
}
5758
}
58-
59-
return origName;
6059
}
6160

6261
function setPositiveNumber( elem, value, subtract ) {
@@ -203,7 +202,7 @@ jQuery.extend({
203202
style = elem.style;
204203

205204
name = jQuery.cssProps[ origName ] ||
206-
( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
205+
( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
207206

208207
// Gets hook for the prefixed version, then unprefixed version
209208
hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
@@ -261,7 +260,7 @@ jQuery.extend({
261260

262261
// Make sure that we're working with the right name
263262
name = jQuery.cssProps[ origName ] ||
264-
( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
263+
( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
265264

266265
// Try prefixed name followed by the unprefixed name
267266
hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

test/unit/css.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,4 +1116,84 @@ test( "Do not throw on frame elements from css method (#15098)", 1, function() {
11161116
ok( false, "It did throw" );
11171117
}
11181118
});
1119+
1120+
( function() {
1121+
var vendorPrefixes = [ "Webkit", "Moz", "ms" ];
1122+
1123+
function resetCssPropsFor( name ) {
1124+
delete jQuery.cssProps[ name ];
1125+
jQuery.each( vendorPrefixes, function( index, prefix ) {
1126+
delete jQuery.cssProps[ prefix + name[ 0 ].toUpperCase() + name.slice( 1 ) ];
1127+
} );
1128+
}
1129+
1130+
test( "Don't default to a cached previously used wrong prefixed name (gh-2015)", function() {
1131+
// Note: this test needs a property we know is only supported in a prefixed version
1132+
// by at least one of our main supported browsers. This may get out of date so let's
1133+
// use -(webkit|moz)-appearance as well as those two are not on a standards track.
1134+
var appearanceName, transformName, elem, elemStyle,
1135+
transformVal = "translate(5px, 2px)",
1136+
emptyStyle = document.createElement( "div" ).style;
1137+
1138+
if ( "appearance" in emptyStyle ) {
1139+
appearanceName = "appearance";
1140+
} else {
1141+
jQuery.each( vendorPrefixes, function( index, prefix ) {
1142+
var prefixedProp = prefix + "Appearance";
1143+
if ( prefixedProp in emptyStyle ) {
1144+
appearanceName = prefixedProp;
1145+
}
1146+
} );
1147+
}
1148+
1149+
if ( "transform" in emptyStyle ) {
1150+
transformName = "transform";
1151+
} else {
1152+
jQuery.each( vendorPrefixes, function( index, prefix ) {
1153+
var prefixedProp = prefix + "Transform";
1154+
if ( prefixedProp in emptyStyle ) {
1155+
transformName = prefixedProp;
1156+
}
1157+
} );
1158+
}
1159+
1160+
expect( !!appearanceName + !!transformName + 1 );
1161+
1162+
resetCssPropsFor( "appearance" );
1163+
resetCssPropsFor( "transform" );
1164+
1165+
elem = jQuery( "<div/>" )
1166+
.css( {
1167+
msAppearance: "none",
1168+
appearance: "none",
1169+
1170+
// Only the ms prefix is used to make sure we haven't e.g. set
1171+
// webkitTransform ourselves in the test.
1172+
msTransform: transformVal,
1173+
transform: transformVal
1174+
} );
1175+
elemStyle = elem[ 0 ].style;
1176+
1177+
if ( appearanceName ) {
1178+
equal( elemStyle[ appearanceName ], "none", "setting properly-prefixed appearance" );
1179+
}
1180+
if ( transformName ) {
1181+
equal( elemStyle[ transformName ], transformVal, "setting properly-prefixed transform" );
1182+
}
1183+
equal( elemStyle.undefined, undefined, "Nothing writes to node.style.undefined" );
1184+
} );
1185+
1186+
test( "Don't detect fake set properties on a node when caching the prefixed version", function() {
1187+
expect( 1 );
1188+
1189+
var elem = jQuery( "<div/>" ),
1190+
style = elem[ 0 ].style;
1191+
style.MozFakeProperty = "old value";
1192+
elem.css( "fakeProperty", "new value" );
1193+
1194+
equal( style.MozFakeProperty, "old value", "Fake prefixed property is not cached" );
1195+
} );
1196+
1197+
} )();
1198+
11191199
}

0 commit comments

Comments
 (0)