8000 Attributes: Only convert true, false & an empty string · jquery/jquery@2adc8e9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2adc8e9

Browse files
committed
Attributes: Only convert true, false & an empty string
The HTML spec defines boolean attributes: https://html.spec.whatwg.org/#boolean-attributes that often correlate with boolean properties. If the attribute is missing, it correlates with the `false` property value, if it's present - the `true` property value. The only valid values are an empty string or the attribute name. jQuery tried to be helpful here and treated boolean attributes in a special way in the `.attr()` API: 1. For the getter, as long as the attribute was present, it was returning the attribute name lowercased, ignoring the value. 2. For the setter, it was removing the attribute when `false` was passed; otherwise, it was ignoring the passed value and set the attribute - interestingly, in jQuery `>=3` not lowercased anymore. The problem is the spec occasionally converts boolean attributes into ones with additional attribute values with special behavior - one such example is the new `"until-found"` value for the `hidden` attribute. Our setter normalization means passing those values is impossible with jQuery. This patch takes a conservative approach, with backwards compatibility in mind, and makes the following changes: 1. It explicitly only applies the logic to the few most popular attribute names. 2. The getter only normalizes the empty string to the lowercased name, returning other attribute values unchanged - it seems unlikely that the empty string value will ever mean anything else than the attribute name repeated. 3. The setter continues to treat `false` as mean attribute removal and `true` as setting the value to the attribute name. All the other inputs are aplied unchanged. With this change, all existing jQuery unit tests were already passing.
1 parent f80e78e commit 2adc8e9

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

src/attributes/attr.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,27 @@ if ( isIE ) {
9797
};
9898
}
9999

100-
// HTML boolean attributes have special behavior:
101-
// we consider the lowercase name to be the only valid value, so
102-
// getting (if the attribute is present) normalizes to that, as does
103-
// setting to any non-`false` value (and setting to `false` removes the attribute).
100+
// HTML boolean attributes have special behavior - the attribute presence
101+
// corresponds to the `true` value and the lack of it - to `false`. The only
102+
// officially valid values are an empty string or the attribute name.
104103
// See https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
104+
//
105+
// Because of that, jQuery used to normalize the value to the name in both
106+
// the getter & setter. However, the spec occasionally adds more values, making
107+
// the attribute non-boolean anymore.
108+
//
109+
// For backwards compatibility, jQuery keeps special logic for select more popular
110+
// attributes that are or were boolean attributes (this list is not meant
111+
// to expand):
112+
// 1. In the getter, an empty string is converted to the lowercase name.
113+
// 2. In the setter, `false` means attribute removal and `true` is converted to name.
114+
// For other getter/setter inputs no special logic is applied.
105115
jQuery.each( (
106-
"checked selected async autofocus autoplay controls defer disabled " +
107-
"hidden ismap loop multiple open readonly required scoped"
116+
"disabled checked readonly selected required hidden open autofocus multiple"
108117
).split( " " ), function( _i, name ) {
109118
jQuery.attrHooks[ name ] = {
110119
get: function( elem ) {
111-
return elem.getAttribute( name ) != null ?
120+
return elem.getAttribute( name ) === "" ?
112121
name.toLowerCase() :
113122
null;
114123
},
@@ -118,10 +127,8 @@ jQuery.each( (
118127

119128
// Remove boolean attributes when set to false
120129
jQuery.removeAttr( elem, name );
121-
} else {
122-
elem.setAttribute( name, name );
130+
return name;
123131
}
124-
return name;
125132
}
126133
};
127134
} );

0 commit comments

Comments
 (0)
0