]> source.dussan.org Git - jquery.git/commitdiff
Attributes: add SVG class manipulation
authorTimmy Willison <timmywillisn@gmail.com>
Wed, 6 May 2015 20:30:16 +0000 (13:30 -0700)
committerTimmy Willison <timmywillisn@gmail.com>
Tue, 12 May 2015 14:24:42 +0000 (10:24 -0400)
- Note: support for SVG is limited in jQuery,
  but this is one area where the cost vs benefit ratio
  was acceptable.

Fixes gh-2199
Close gh-2268

src/attributes/classes.js
test/unit/attributes.js

index 95146d25cc47e24fcf6f0fd9fc02bc38bb95162d..f08a1a142db270290c9539f2330b04ab759a4bde 100644 (file)
@@ -6,16 +6,20 @@ define([
 
 var rclass = /[\t\r\n\f]/g;
 
+function getClass( elem ) {
+       return elem.getAttribute && elem.getAttribute( "class" ) || "";
+}
+
 jQuery.fn.extend({
        addClass: function( value ) {
-               var classes, elem, cur, clazz, j, finalValue,
+               var classes, elem, cur, curValue, clazz, j, finalValue,
                        i = 0,
                        len = this.length,
                        proceed = typeof value === "string" && value;
 
                if ( jQuery.isFunction( value ) ) {
                        return this.each(function( j ) {
-                               jQuery( this ).addClass( value.call( this, j, this.className ) );
+                               jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
                        });
                }
 
@@ -25,10 +29,9 @@ jQuery.fn.extend({
 
                        for ( ; i < len; i++ ) {
                                elem = this[ i ];
-                               cur = elem.nodeType === 1 && ( elem.className ?
-                                       ( " " + elem.className + " " ).replace( rclass, " " ) :
-                                       " "
-                               );
+                               curValue = getClass( elem );
+                               cur = elem.nodeType === 1 &&
+                                       ( " " + curValue + " " ).replace( rclass, " " );
 
                                if ( cur ) {
                                        j = 0;
@@ -40,8 +43,8 @@ jQuery.fn.extend({
 
                                        // only assign if different to avoid unneeded rendering.
                                        finalValue = jQuery.trim( cur );
-                                       if ( elem.className !== finalValue ) {
-                                               elem.className = finalValue;
+                                       if ( curValue !== finalValue ) {
+                                               elem.setAttribute( "class", finalValue );
                                        }
                                }
                        }
@@ -51,14 +54,14 @@ jQuery.fn.extend({
        },
 
        removeClass: function( value ) {
-               var classes, elem, cur, clazz, j, finalValue,
+               var classes, elem, cur, curValue, clazz, j, finalValue,
                        i = 0,
                        len = this.length,
                        proceed = arguments.length === 0 || typeof value === "string" && value;
 
                if ( jQuery.isFunction( value ) ) {
                        return this.each(function( j ) {
-                               jQuery( this ).removeClass( value.call( this, j, this.className ) );
+                               jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
                        });
                }
                if ( proceed ) {
@@ -66,11 +69,11 @@ jQuery.fn.extend({
 
                        for ( ; i < len; i++ ) {
                                elem = this[ i ];
+                               curValue = getClass( elem );
+
                                // This expression is here for better compressibility (see addClass)
-                               cur = elem.nodeType === 1 && ( elem.className ?
-                                       ( " " + elem.className + " " ).replace( rclass, " " ) :
-                                       ""
-                               );
+                               cur = elem.nodeType === 1 &&
+                                       ( " " + curValue + " " ).replace( rclass, " " );
 
                                if ( cur ) {
                                        j = 0;
@@ -83,8 +86,8 @@ jQuery.fn.extend({
 
                                        // only assign if different to avoid unneeded rendering.
                                        finalValue = value ? jQuery.trim( cur ) : "";
-                                       if ( elem.className !== finalValue ) {
-                                               elem.className = finalValue;
+                                       if ( curValue !== finalValue ) {
+                                               elem.setAttribute( "class", finalValue );
                                        }
                                }
                        }
@@ -103,21 +106,25 @@ jQuery.fn.extend({
                if ( jQuery.isFunction( value ) ) {
                        return this.each(function( i ) {
                                jQuery( this ).toggleClass(
-                                       value.call(this, i, this.className, stateVal), stateVal
+                                       value.call( this, i, getClass( this ), stateVal ),
+                                       stateVal
                                );
                        });
                }
 
                return this.each(function() {
+                       var className, i, self, classNames;
+
                        if ( type === "string" ) {
-                               // toggle individual class names
-                               var className,
-                                       i = 0,
-                                       self = jQuery( this ),
-                                       classNames = value.match( rnotwhite ) || [];
-
-                               while ( (className = classNames[ i++ ]) ) {
-                                       // check each className given, space separated list
+
+                               // Toggle individual class names
+                               i = 0;
+                               self = jQuery( this );
+                               classNames = value.match( rnotwhite ) || [];
+
+                               while ( ( className = classNames[ i++ ] ) ) {
+
+                                       // Check each className given, space separated list
                                        if ( self.hasClass( className ) ) {
                                                self.removeClass( className );
                                        } else {
@@ -126,19 +133,25 @@ jQuery.fn.extend({
                                }
 
                        // Toggle whole class name
-                       } else if ( type === "undefined" || type === "boolean" ) {
-                               if ( this.className ) {
+                       } else if ( value === undefined || type === "boolean" ) {
+                               className = getClass( this );
+                               if ( className ) {
+
                                        // store className if set
-                                       jQuery._data( this, "__className__", this.className );
+                                       jQuery._data( this, "__className__", className );
                                }
 
                                // If the element has a class name or if we're passed "false",
                                // then remove the whole classname (if there was one, the above saved it).
                                // Otherwise bring back whatever was previously saved (if anything),
                                // falling back to the empty string if nothing was stored.
-                               this.className = this.className || value === false ?
-                                       "" :
-                                       jQuery._data( this, "__className__" ) || "";
+                               if ( this.setAttribute ) {
+                                       this.setAttribute( "class",
+                                               className || value === false ?
+                                               "" :
+                                               jQuery._data( this, "__className__" ) || ""
+                                       );
+                               }
                        }
                });
        },
@@ -149,8 +162,9 @@ jQuery.fn.extend({
                        l = this.length;
                for ( ; i < l; i++ ) {
                        if ( this[i].nodeType === 1 &&
-                               (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
-
+                               ( " " + getClass( this[i] ) + " " ).replace( rclass, " " )
+                                       .indexOf( className ) > -1
+                       ) {
                                return true;
                        }
                }
index 1e9c2fee220f1481a83063087982af8865157013..022d4a8b3bfa7e5d63cfdac6bce33b47a4a667e6 100644 (file)
@@ -1476,3 +1476,31 @@ test( "Insignificant white space returned for $(option).val() (#14858)", functio
        val = jQuery( "<option>  test  </option>" ).val();
        equal( val.length, 4, "insignificant white-space returned for value" );
 });
+
+test( "SVG class manipulation (gh-2199)", function() {
+       expect( 12 );
+
+       function createSVGElement( nodeName ) {
+               return document.createElementNS( "http://www.w3.org/2000/svg", nodeName );
+       }
+
+       jQuery.each([
+               "svg",
+               "rect",
+               "g"
+       ], function() {
+               var elem = jQuery( createSVGElement( this ) );
+
+               elem.addClass( "awesome" );
+               ok( elem.hasClass( "awesome" ), "SVG element (" + this + ") has added class" );
+
+               elem.removeClass( "awesome" );
+               ok( !elem.hasClass( "awesome" ), "SVG element (" + this + ") removes the class" );
+
+               elem.toggleClass( "awesome" );
+               ok( elem.hasClass( "awesome" ), "SVG element (" + this + ") toggles the class on" );
+
+               elem.toggleClass( "awesome" );
+               ok( !elem.hasClass( "awesome" ), "SVG element (" + this + ") toggles the class off" );
+       });
+});