From 96dd06ea50674c77de4a5d953c227bb54d9276af Mon Sep 17 00:00:00 2001 From: John Resig Date: Tue, 8 Sep 2009 01:07:50 +0000 Subject: [PATCH] Removed jQuery.className.(has|remove|add) in favor of .addClass/removeClass/hasClass. Also rewrote the functions for additional performance. --- src/attributes.js | 95 +++++++++++++++++++++++++++++------------------ test/unit/attributes.js | 27 +++++++++----- 2 files changed, 76 insertions(+), 46 deletions(-) diff --git a/src/attributes.js b/src/attributes.js index 93e0433..c4c7500 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -31,8 +31,64 @@ jQuery.fn.extend({ return this; }, + addClass: function( value ) { + if ( value && typeof value === "string" ) { + var classNames = (value || "").split(/\s+/); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + } else { + var className = " " + elem.className + " "; + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + elem.className += " " + classNames[c]; + } + } + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split(/\s+/); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = " " + elem.className + " "; + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = className.substring(1, className.length - 1); + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + hasClass: function( selector ) { - return !!selector && this.is( "." + selector ); + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; }, val: function( value ) { @@ -125,14 +181,6 @@ jQuery.each({ this.removeAttribute( name ); }, - addClass: function( classNames ) { - jQuery.className.add( this, classNames ); - }, - - removeClass: function( classNames ) { - jQuery.className.remove( this, classNames ); - }, - toggleClass: function( classNames, state ) { var type = typeof classNames; if ( type === "string" ) { @@ -141,8 +189,8 @@ jQuery.each({ classNames = classNames.split( /\s+/ ); while ( (className = classNames[ i++ ]) ) { // check each className given, space seperated list - state = isBool ? state : !jQuery.className.has( this, className ); - jQuery.className[ state ? "add" : "remove" ]( this, className ); + state = isBool ? state : !jQuery(this).hasClass( className ); + jQuery(this)[ state ? "addClass" : "removeClass" ]( className ); } } else if ( type === "undefined" || type === "boolean" ) { if ( this.className ) { @@ -160,31 +208,6 @@ jQuery.each({ }); jQuery.extend({ - className: { - // internal only, use addClass("class") - add: function( elem, classNames ) { - jQuery.each((classNames || "").split(/\s+/), function(i, className){ - if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) - elem.className += (elem.className ? " " : "") + className; - }); - }, - - // internal only, use removeClass("class") - remove: function( elem, classNames ) { - if (elem.nodeType == 1) - elem.className = classNames !== undefined ? - jQuery.grep(elem.className.split(/\s+/), function(className){ - return !jQuery.className.has( classNames, className ); - }).join(" ") : - ""; - }, - - // internal only, use hasClass("class") - has: function( elem, className ) { - return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; - } - }, - attr: function( elem, name, value ) { // don't set attributes on text and comment nodes if (!elem || elem.nodeType == 3 || elem.nodeType == 8) diff --git a/test/unit/attributes.js b/test/unit/attributes.js index 7887790..e9880df 100644 --- a/test/unit/attributes.js +++ b/test/unit/attributes.js @@ -272,6 +272,7 @@ test("removeClass(String) - simple", function() { ok( !$divs.is('.test'), "Remove Class" ); reset(); + $divs = jQuery('div'); $divs.addClass("test").addClass("foo").addClass("bar"); $divs.removeClass("test").removeClass("bar").removeClass("foo"); @@ -279,6 +280,7 @@ test("removeClass(String) - simple", function() { ok( !$divs.is('.test,.bar,.foo'), "Remove multiple classes" ); reset(); + $divs = jQuery('div'); // Make sure that a null value doesn't cause problems $divs.eq(0).addClass("test").removeClass(null); @@ -350,19 +352,24 @@ test("removeAttr(String", function() { equals( jQuery('#mark').removeAttr("class")[0].className, "", "remove class" ); }); -test("jQuery.className", function() { +test("addClass, removeClass, hasClass", function() { expect(6); - var x = jQuery("

Hi

")[0]; - var c = jQuery.className; - c.add(x, "hi"); + + var jq = jQuery("

Hi

"), x = jq[0]; + + jq.addClass("hi"); equals( x.className, "hi", "Check single added class" ); - c.add(x, "foo bar"); + + jq.addClass("foo bar"); equals( x.className, "hi foo bar", "Check more added classes" ); - c.remove(x); + + jq.removeClass(); equals( x.className, "", "Remove all classes" ); - c.add(x, "hi foo bar"); - c.remove(x, "foo"); + + jq.addClass("hi foo bar"); + jq.removeClass("foo"); equals( x.className, "hi bar", "Check removal of one class" ); - ok( c.has(x, "hi"), "Check has1" ); - ok( c.has(x, "bar"), "Check has2" ); + + ok( jq.hasClass("hi"), "Check has1" ); + ok( jq.hasClass("bar"), "Check has2" ); }); -- 1.7.10.4