From: Timmy Willison <4timmywil@gmail.com> Date: Tue, 2 Jan 2018 21:45:10 +0000 (-0500) Subject: Attributes: allow array param in add/remove/toggleClass X-Git-Tag: 3.3.0~24 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=80f57f8a13debaab87b99f73631669699da3e1a5;p=jquery.git Attributes: allow array param in add/remove/toggleClass +30 bytes instead of +182 Thanks to @faisaliyk for the first pass on this feature. Fixes gh-3532 Close gh-3917 --- diff --git a/src/attributes/classes.js b/src/attributes/classes.js index 23b4cd6af..1c75821b2 100644 --- a/src/attributes/classes.js +++ b/src/attributes/classes.js @@ -12,6 +12,16 @@ function getClass( elem ) { return elem.getAttribute && elem.getAttribute( "class" ) || ""; } +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + jQuery.fn.extend( { addClass: function( value ) { var classes, elem, cur, curValue, clazz, j, finalValue, @@ -23,9 +33,9 @@ jQuery.fn.extend( { } ); } - if ( typeof value === "string" && value ) { - classes = value.match( rnothtmlwhite ) || []; + classes = classesToArray( value ); + if ( classes.length ) { while ( ( elem = this[ i++ ] ) ) { curValue = getClass( elem ); cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); @@ -64,9 +74,9 @@ jQuery.fn.extend( { return this.attr( "class", "" ); } - if ( typeof value === "string" && value ) { - classes = value.match( rnothtmlwhite ) || []; + classes = classesToArray( value ); + if ( classes.length ) { while ( ( elem = this[ i++ ] ) ) { curValue = getClass( elem ); @@ -96,9 +106,10 @@ jQuery.fn.extend( { }, toggleClass: function( value, stateVal ) { - var type = typeof value; + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); - if ( typeof stateVal === "boolean" && type === "string" ) { + if ( typeof stateVal === "boolean" && isValidValue ) { return stateVal ? this.addClass( value ) : this.removeClass( value ); } @@ -114,12 +125,12 @@ jQuery.fn.extend( { return this.each( function() { var className, i, self, classNames; - if ( type === "string" ) { + if ( isValidValue ) { // Toggle individual class names i = 0; self = jQuery( this ); - classNames = value.match( rnothtmlwhite ) || []; + classNames = classesToArray( value ); while ( ( className = classNames[ i++ ] ) ) { diff --git a/test/unit/attributes.js b/test/unit/attributes.js index 3ab023eaf..b446fe1c3 100644 --- a/test/unit/attributes.js +++ b/test/unit/attributes.js @@ -12,6 +12,10 @@ function functionReturningObj( value ) { }; } +function arrayFromString( value ) { + return value ? value.split( " " ) : []; +} + /* ======== local reference ======= bareObj and functionReturningObj can be used to test passing functions to setters @@ -1261,6 +1265,10 @@ QUnit.test( "addClass(Function)", function( assert ) { testAddClass( functionReturningObj, assert ); } ); +QUnit.test( "addClass(Array)", function( assert ) { + testAddClass( arrayFromString, assert ); +} ); + QUnit.test( "addClass(Function) with incoming value", function( assert ) { assert.expect( 52 ); var pass, i, @@ -1334,6 +1342,10 @@ QUnit.test( "removeClass(Function) - simple", function( assert ) { testRemoveClass( functionReturningObj, assert ); } ); +QUnit.test( "removeClass(Array) - simple", function( assert ) { + testRemoveClass( arrayFromString, assert ); +} ); + QUnit.test( "removeClass(Function) with incoming value", function( assert ) { assert.expect( 52 ); @@ -1432,6 +1444,10 @@ QUnit.test( "toggleClass(Function[, boolean])", function( assert ) { testToggleClass( functionReturningObj, assert ); } ); +QUnit.test( "toggleClass(Array[, boolean])", function( assert ) { + testToggleClass( arrayFromString, assert ); +} ); + QUnit.test( "toggleClass(Function[, boolean]) with incoming value", function( assert ) { assert.expect( 14 ); @@ -1567,6 +1583,40 @@ QUnit.test( "addClass, removeClass, hasClass on many elements", function( assert "Did not find a class when not present" ); } ); +QUnit.test( "addClass, removeClass, hasClass on many elements - Array", function( assert ) { + assert.expect( 16 ); + + var elem = jQuery( "

p0

p1

p2

" ); + + elem.addClass( [ "hi" ] ); + assert.equal( elem[ 0 ].className, "hi", "Check single added class" ); + assert.equal( elem[ 1 ].className, "hi", "Check single added class" ); + assert.equal( elem[ 2 ].className, "hi", "Check single added class" ); + + elem.addClass( [ "foo", "bar" ] ); + assert.equal( elem[ 0 ].className, "hi foo bar", "Check more added classes" ); + assert.equal( elem[ 1 ].className, "hi foo bar", "Check more added classes" ); + assert.equal( elem[ 2 ].className, "hi foo bar", "Check more added classes" ); + + elem.removeClass(); + assert.equal( elem[ 0 ].className, "", "Remove all classes" ); + assert.equal( elem[ 1 ].className, "", "Remove all classes" ); + assert.equal( elem[ 2 ].className, "", "Remove all classes" ); + + elem.addClass( [ "hi", "foo", "bar", "baz" ] ); + elem.removeClass( [ "foo" ] ); + assert.equal( elem[ 0 ].className, "hi bar baz", "Check removal of one class" ); + assert.equal( elem[ 1 ].className, "hi bar baz", "Check removal of one class" ); + assert.equal( elem[ 2 ].className, "hi bar baz", "Check removal of one class" ); + + elem.removeClass( [ "bar baz" ] ); + assert.equal( elem[ 0 ].className, "hi", "Check removal of two classes" ); + assert.equal( elem[ 1 ].className, "hi", "Check removal of two classes" ); + assert.equal( elem[ 2 ].className, "hi", "Check removal of two classes" ); + + assert.ok( elem.hasClass( "hi" ), "Check has1" ); +} ); + QUnit.test( "addClass, removeClass, hasClass on elements with classes with non-HTML whitespace (gh-3072, gh-3003)", function( assert ) { assert.expect( 9 );