Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

utilize classList when supported (refs #5087) #1190

Closed
wants to merge 1 commit into from

2 participants

Michał Gołębiowski Rick Waldron
Michał Gołębiowski
Collaborator

No description provided.

Rick Waldron
Collaborator

Thanks for the contribution! As owner of http://bugs.jquery.com/ticket/5087 I can assure you I haven't forgotten! The classList API is still a poor replacement, performance wise, when dealing with multiple classes per call.

Rick Waldron rwaldron closed this
Michał Gołębiowski
Collaborator

Look at my last comment under http://bugs.jquery.com/ticket/5087, I created a few test cases which show we get a large performance boost after applying this patch... What am I missing?

Rick Waldron
Collaborator

That comment wasn't there when I visited the ticket just before closing the PR... I've owned the ticket and babysit the implementation schedule for years and I stand by these decisions:

  1. There is no benefit to adding more code that does the same thing that jQuery already does
  2. Any performance benefits are outweighed by 1
  3. Multiple classes have been a performance issue
  4. jQuery will not use classList until it accepts multiple class args to the add and remove APIs, at which time we'll remove the old way and completely replace it.
Michał Gołębiowski
Collaborator

Well, multiple classes don't seem to be a performance issue anymore, at least it didn't seem so in my test cases on jsFiddle, even with the current limited classList API.

But I understand that as the className path is required even for jQuery 2.0 because of IE9, your first two points have settled it by themselves so I respect your decision.

Amey Sakhadeo ameyms referenced this pull request
Closed

Improve jQuery classes.js #1403

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 2, 2013
  1. Michał Gołębiowski
This page is out of date. Refresh to see the latest.
Showing with 61 additions and 30 deletions.
  1. +59 −30 src/attributes.js
  2. +2 −0  src/support.js
89 src/attributes.js
View
@@ -49,19 +49,24 @@ jQuery.fn.extend({
for ( ; i < len; i++ ) {
elem = this[ i ];
- cur = elem.nodeType === 1 && ( elem.className ?
- ( " " + elem.className + " " ).replace( rclass, " " ) :
- " "
- );
- if ( cur ) {
+ if ( elem.nodeType === 1 ) {
j = 0;
- while ( (clazz = classes[j++]) ) {
- if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
- cur += clazz + " ";
+ if ( jQuery.support.classList ) {
+ while ( (clazz = classes[j++]) ) {
+ elem.classList.add( clazz );
}
+ } else {
+ cur = elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ " ";
+ while ( (clazz = classes[j++]) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+ elem.className = jQuery.trim( cur );
}
- elem.className = jQuery.trim( cur );
}
}
@@ -86,21 +91,29 @@ jQuery.fn.extend({
for ( ; i < len; i++ ) {
elem = this[ i ];
- // This expression is here for better compressibility (see addClass)
- cur = elem.nodeType === 1 && ( elem.className ?
- ( " " + elem.className + " " ).replace( rclass, " " ) :
- ""
- );
- if ( cur ) {
+ if ( elem.nodeType === 1 && elem.className) {
j = 0;
- while ( (clazz = classes[j++]) ) {
- // Remove *all* instances
- while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
- cur = cur.replace( " " + clazz + " ", " " );
+ if ( jQuery.support.classList ) {
+ if ( !value ) {
+ elem.className = "";
+ }
+ while ( (clazz = classes[j++]) ) {
+ elem.classList.remove( clazz );
+ }
+ } else {
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ " ";
+ while ( (clazz = classes[j++]) ) {
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
}
+ elem.className = value ? jQuery.trim( cur ) : "";
}
- elem.className = value ? jQuery.trim( cur ) : "";
}
}
}
@@ -120,17 +133,28 @@ jQuery.fn.extend({
return this.each(function() {
if ( type === "string" ) {
- // toggle individual class names
+ // Toggle individual class names
var className,
i = 0,
self = jQuery( this ),
state = stateVal,
classNames = value.match( core_rnotwhite ) || [];
- while ( (className = classNames[ i++ ]) ) {
- // check each className given, space separated list
- state = isBool ? state : !self.hasClass( className );
- self[ state ? "addClass" : "removeClass" ]( className );
+ // Check each className given, space separated list
+ if ( jQuery.support.classList ) {
+ while ( (className = classNames[ i++ ]) ) {
+ if ( isBool ) {
+ this.classList.toggle( className, state );
+ } else {
+ this.classList.toggle( className );
+ }
+ }
+ // Support: IE9
+ } else {
+ while ( (className = classNames[ i++ ]) ) {
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
}
// Toggle whole class name
@@ -149,13 +173,18 @@ jQuery.fn.extend({
});
},
- hasClass: function( selector ) {
- var className = " " + selector + " ",
- i = 0,
+ hasClass: function( value ) {
+ var i = 0,
l = this.length;
for ( ; i < l; i++ ) {
- if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
- return true;
+ if ( this[i].nodeType === 1 ) {
+ if ( jQuery.support.classList ) {
+ return this[i].classList.contains(value);
+ } else {
+ if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( " " + value + " " ) >= 0 ) {
+ return true;
+ }
+ }
}
}
2  src/support.js
View
@@ -61,6 +61,8 @@ jQuery.support = (function( support ) {
div.cloneNode( true ).style.backgroundClip = "";
support.clearCloneStyle = div.style.backgroundClip === "content-box";
+ support.classList = "classList" in div;
+
// Run tests that need a body at doc ready
jQuery(function() {
var container, marginDiv,
Something went wrong with that request. Please try again.