mirror of
https://github.com/jquery/jquery.git
synced 2025-01-10 18:24:24 +00:00
CSS: Skip falsy values in addClass( array )
, compress code
This change makes jQuery skip falsy values in `addClass( array )`
& `removeClass( array )` instead of stopping iteration when the first falsy
value is detected. This makes code like:
```js
elem.addClass( [ "a", "", "b" ] );
```
add both the `a` & `b` classes.
The code was also optimized for size a bit so it doesn't increase the
minified gzipped size.
Fixes gh-4998
Closes gh-5003
(partially cherry picked from commit a338b407f2
)
This commit is contained in:
parent
95e34b6955
commit
9b34bdb1c3
@ -25,8 +25,7 @@ function classesToArray( value ) {
|
|||||||
|
|
||||||
jQuery.fn.extend( {
|
jQuery.fn.extend( {
|
||||||
addClass: function( value ) {
|
addClass: function( value ) {
|
||||||
var classes, elem, cur, curValue, clazz, j, finalValue,
|
var classNames, cur, curValue, className, i, finalValue;
|
||||||
i = 0;
|
|
||||||
|
|
||||||
if ( isFunction( value ) ) {
|
if ( isFunction( value ) ) {
|
||||||
return this.each( function( j ) {
|
return this.each( function( j ) {
|
||||||
@ -34,36 +33,35 @@ jQuery.fn.extend( {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
classes = classesToArray( value );
|
classNames = classesToArray( value );
|
||||||
|
|
||||||
if ( classes.length ) {
|
if ( classNames.length ) {
|
||||||
while ( ( elem = this[ i++ ] ) ) {
|
return this.each( function() {
|
||||||
curValue = getClass( elem );
|
curValue = getClass( this );
|
||||||
cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
|
cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
|
||||||
|
|
||||||
if ( cur ) {
|
if ( cur ) {
|
||||||
j = 0;
|
for ( i = 0; i < classNames.length; i++ ) {
|
||||||
while ( ( clazz = classes[ j++ ] ) ) {
|
className = classNames[ i ];
|
||||||
if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
|
if ( cur.indexOf( " " + className + " " ) < 0 ) {
|
||||||
cur += clazz + " ";
|
cur += className + " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only assign if different to avoid unneeded rendering.
|
// Only assign if different to avoid unneeded rendering.
|
||||||
finalValue = stripAndCollapse( cur );
|
finalValue = stripAndCollapse( cur );
|
||||||
if ( curValue !== finalValue ) {
|
if ( curValue !== finalValue ) {
|
||||||
elem.setAttribute( "class", finalValue );
|
this.setAttribute( "class", finalValue );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
removeClass: function( value ) {
|
removeClass: function( value ) {
|
||||||
var classes, elem, cur, curValue, clazz, j, finalValue,
|
var classNames, cur, curValue, className, i, finalValue;
|
||||||
i = 0;
|
|
||||||
|
|
||||||
if ( isFunction( value ) ) {
|
if ( isFunction( value ) ) {
|
||||||
return this.each( function( j ) {
|
return this.each( function( j ) {
|
||||||
@ -75,45 +73,42 @@ jQuery.fn.extend( {
|
|||||||
return this.attr( "class", "" );
|
return this.attr( "class", "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
classes = classesToArray( value );
|
classNames = classesToArray( value );
|
||||||
|
|
||||||
if ( classes.length ) {
|
if ( classNames.length ) {
|
||||||
while ( ( elem = this[ i++ ] ) ) {
|
return this.each( function() {
|
||||||
curValue = getClass( elem );
|
curValue = getClass( this );
|
||||||
|
|
||||||
// This expression is here for better compressibility (see addClass)
|
// This expression is here for better compressibility (see addClass)
|
||||||
cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
|
cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
|
||||||
|
|
||||||
if ( cur ) {
|
if ( cur ) {
|
||||||
j = 0;
|
for ( i = 0; i < classNames.length; i++ ) {
|
||||||
while ( ( clazz = classes[ j++ ] ) ) {
|
className = classNames[ i ];
|
||||||
|
|
||||||
// Remove *all* instances
|
// Remove *all* instances
|
||||||
while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
|
while ( cur.indexOf( " " + className + " " ) > -1 ) {
|
||||||
cur = cur.replace( " " + clazz + " ", " " );
|
cur = cur.replace( " " + className + " ", " " );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only assign if different to avoid unneeded rendering.
|
// Only assign if different to avoid unneeded rendering.
|
||||||
finalValue = stripAndCollapse( cur );
|
finalValue = stripAndCollapse( cur );
|
||||||
if ( curValue !== finalValue ) {
|
if ( curValue !== finalValue ) {
|
||||||
elem.setAttribute( "class", finalValue );
|
this.setAttribute( "class", finalValue );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleClass: function( value, stateVal ) {
|
toggleClass: function( value, stateVal ) {
|
||||||
var type = typeof value,
|
var classNames, className, i, self,
|
||||||
|
type = typeof value,
|
||||||
isValidValue = type === "string" || Array.isArray( value );
|
isValidValue = type === "string" || Array.isArray( value );
|
||||||
|
|
||||||
if ( typeof stateVal === "boolean" && isValidValue ) {
|
|
||||||
return stateVal ? this.addClass( value ) : this.removeClass( value );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isFunction( value ) ) {
|
if ( isFunction( value ) ) {
|
||||||
return this.each( function( i ) {
|
return this.each( function( i ) {
|
||||||
jQuery( this ).toggleClass(
|
jQuery( this ).toggleClass(
|
||||||
@ -123,17 +118,20 @@ jQuery.fn.extend( {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.each( function() {
|
if ( typeof stateVal === "boolean" && isValidValue ) {
|
||||||
var className, i, self, classNames;
|
return stateVal ? this.addClass( value ) : this.removeClass( value );
|
||||||
|
}
|
||||||
|
|
||||||
|
classNames = classesToArray( value );
|
||||||
|
|
||||||
|
return this.each( function() {
|
||||||
if ( isValidValue ) {
|
if ( isValidValue ) {
|
||||||
|
|
||||||
// Toggle individual class names
|
// Toggle individual class names
|
||||||
i = 0;
|
|
||||||
self = jQuery( this );
|
self = jQuery( this );
|
||||||
classNames = classesToArray( value );
|
|
||||||
|
|
||||||
while ( ( className = classNames[ i++ ] ) ) {
|
for ( i = 0; i < classNames.length; i++ ) {
|
||||||
|
className = classNames[ i ];
|
||||||
|
|
||||||
// Check each className given, space separated list
|
// Check each className given, space separated list
|
||||||
if ( self.hasClass( className ) ) {
|
if ( self.hasClass( className ) ) {
|
||||||
|
@ -1631,6 +1631,44 @@ QUnit.test( "addClass, removeClass, hasClass on elements with classes with non-H
|
|||||||
testMatches();
|
testMatches();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
( function() {
|
||||||
|
var rnothtmlwhite = /[^\x20\t\r\n\f]+/g;
|
||||||
|
|
||||||
|
function expectClasses( assert, elem, classes ) {
|
||||||
|
var actualClassesSorted = ( elem.attr( "class" ).match( rnothtmlwhite ) || [] )
|
||||||
|
.sort().join( " " );
|
||||||
|
var classesSorted = classes.slice()
|
||||||
|
.sort().join( " " );
|
||||||
|
assert.equal( actualClassesSorted, classesSorted, "Expected classes present" );
|
||||||
|
}
|
||||||
|
|
||||||
|
QUnit.test( "addClass on arrays with falsy elements (gh-4998)", function( assert ) {
|
||||||
|
assert.expect( 3 );
|
||||||
|
|
||||||
|
var elem = jQuery( "<div class='a'></div>" );
|
||||||
|
|
||||||
|
elem.addClass( [ "b", "", "c" ] );
|
||||||
|
expectClasses( assert, elem, [ "a", "b", "c" ] );
|
||||||
|
elem.addClass( [ "", "d" ] );
|
||||||
|
expectClasses( assert, elem, [ "a", "b", "c", "d" ] );
|
||||||
|
elem.addClass( [ "e", "" ] );
|
||||||
|
expectClasses( assert, elem, [ "a", "b", "c", "d", "e" ] );
|
||||||
|
} );
|
||||||
|
|
||||||
|
QUnit.test( "removeClass on arrays with falsy elements (gh-4998)", function( assert ) {
|
||||||
|
assert.expect( 3 );
|
||||||
|
|
||||||
|
var elem = jQuery( "<div class='a b c d e'></div>" );
|
||||||
|
|
||||||
|
elem.removeClass( [ "e", "" ] );
|
||||||
|
expectClasses( assert, elem, [ "a", "b", "c", "d" ] );
|
||||||
|
elem.removeClass( [ "", "d" ] );
|
||||||
|
expectClasses( assert, elem, [ "a", "b", "c" ] );
|
||||||
|
elem.removeClass( [ "b", "", "c" ] );
|
||||||
|
expectClasses( assert, elem, [ "a" ] );
|
||||||
|
} );
|
||||||
|
} )();
|
||||||
|
|
||||||
QUnit.test( "contents().hasClass() returns correct values", function( assert ) {
|
QUnit.test( "contents().hasClass() returns correct values", function( assert ) {
|
||||||
assert.expect( 2 );
|
assert.expect( 2 );
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user