Skip to content

@devongovett /gist:1381839
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
/*
* Minimal classList shim
* By Devon Govett
* MIT LICENSE
*/
if (!("classList" in document.documentElement)) {
Object.defineProperty(HTMLElement.prototype, 'classList', {
get: function() {
var self = this;
function update(fn) {
return function(value) {
var classes = self.className.split(/\s+/g),
index = classes.indexOf(value);
fn(classes, index, value);
self.className = classes.join(" ");
}
}
return {
add: update(function(classes, index, value) {
if (!~index) classes.push(value);
}),
remove: update(function(classes, index) {
if (~index) classes.splice(index, 1);
}),
toggle: update(function(classes, index, value) {
if (~index)
classes.splice(index, 1);
else
classes.push(value);
}),
contains: function(value) {
return !!~self.className.split(/\s+/g).indexOf(value);
},
item: function(i) {
return self.className.split(/\s+/g)[i] || null;
}
};
}
});
}
@rwaldron

I wonder if those browsers that are missing classList support would have DOMTokenList support, which would be the base proto of classList...

@jdalton

@devongovett Look to how some of the selector engines like Sizzle or NWMatcher detect class names. They have refined them for speed, at first glance yur class name operations look a little costly. Also extending the DOM leads to nothing but headache and dev tears.

@devongovett
Owner

That's exactly what it is supposed to be though - a polyfill. And I agree it can probably be improved but it was designed to be really small and I wrote it in about 5 minutes. :) If you've got improvements, by all means have at it.

@jdalton

@devongovett Polyfill or not, extending the DOM has been known to cause problems. Would be better if you made a small utility method that leveraged native functionality or forked for a fallback.

@devongovett
Owner

If you don't want to extend the DOM, don't use this shim. What problems do you see? It seems to work for me...

@jdalton

@devongovett I'm trying to save you some heart burn by giving you a heads up. I've spent many years working with libs like Prototype that extend the DOM and a lot of the time things seemed to work fine, for a time, but then fell apart down the road.

@jdalton

I understand support was aimed at IE8/9 but this causes script errors in IE 6/7 and 8.
IE 8 has window.Element but not window.HTMLElement.

@devongovett
Owner

It doesn't have Object.defineProperty either... better?

@devongovett
Owner

@rwldrn wouldn't length be better implemented as a getter? Otherwise if the user updates the className the length won't change.

@jdalton

@devongovett IE8 has Object.defineProperty. In fact, IE8's Object.defineProperty only works on DOM elements ;D

@devongovett
Owner

Yeah I realize that. I was referring to IE 6 and 7. Unfortunately the length getter wouldn't work in IE 8 either.

@jdalton

@devongovett In IE8 HTMLElement will be an undefined var reference and throw an error.

Also another heads up, String#split and IE are iffy when it comes to regexp support (rule of thumb: keep it really simple and test).
Your regexp could be simplified to just /\s+/.

@rwaldron

@devongovett - it sure would, but like I said it's "half-assed" and only meant to work in IE8 right?

@devongovett
Owner

Eh! Screw IE < 9. Too many problems and I wasn't trying to support it in my app anyway. The regex is now simplified, and I added "real" length support via a getter. And to answer your question @rwldrn, it looks like IE does not have DOMTokenList.

@rwaldron

Word.

@eligrey

Super late to this party, but my classList polyfill has true native .length by being an array (i.e. constructor's .prototype = []). You could try something like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.