Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
/*
* Minimal classList shim for IE 9
* By Devon Govett
* MIT LICENSE
*/
if (!("classList" in document.documentElement) && Object.defineProperty && typeof HTMLElement !== 'undefined') {
Object.defineProperty(HTMLElement.prototype, 'classList', {
get: function() {
var self = this;
function update(fn) {
return function(value) {
var classes = self.className.split(/\s+/),
index = classes.indexOf(value);
fn(classes, index, value);
self.className = classes.join(" ");
}
}
var ret = {
add: update(function(classes, index, value) {
~index || classes.push(value);
}),
remove: update(function(classes, index) {
~index && classes.splice(index, 1);
}),
toggle: update(function(classes, index, value) {
~index ? classes.splice(index, 1) : classes.push(value);
}),
contains: function(value) {
return !!~self.className.split(/\s+/).indexOf(value);
},
item: function(i) {
return self.className.split(/\s+/)[i] || null;
}
};
Object.defineProperty(ret, 'length', {
get: function() {
return self.className.split(/\s+/).length;
}
});
return ret;
}
});
}

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

jdalton commented Nov 21, 2011

@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.

Owner

devongovett commented Nov 21, 2011

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 commented Nov 21, 2011

@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.

Owner

devongovett commented Nov 21, 2011

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 commented Nov 21, 2011

@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 commented Nov 21, 2011

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.

Owner

devongovett commented Nov 21, 2011

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

Owner

devongovett commented Nov 21, 2011

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

jdalton commented Nov 21, 2011

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

Owner

devongovett commented Nov 21, 2011

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

jdalton commented Nov 21, 2011

@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+/.

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

Owner

devongovett commented Nov 21, 2011

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.

Word.

eligrey commented Feb 8, 2012

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