Skip to content

Instantly share code, notes, and snippets.

@rainyjune
Created February 14, 2013 07:50
Show Gist options
  • Save rainyjune/4951208 to your computer and use it in GitHub Desktop.
Save rainyjune/4951208 to your computer and use it in GitHub Desktop.
classList(): treat className as a set of CSS classes
/*
* Return the classList property of e, if it has one.
* Otherwise, return an object that simulates the DOMTokenList API for e.
* The returned object has contains(), add(), remove(), toggle() and toString()
* methods for testing and altering the set of classes of the element e.
* If the classList property is natively supported, the returned object is
* array-like and has length and array index properties. The simulated
* DOMTokenList is not array-like, but has a toArray() method that returns
* a true-array snapshot of the element's class names.
*/
function classList(e) {
if (e.classList) return e.classList; // Return e.classList if it exists
else return new CSSClassList(e); // Otherwise try to fake it
}
// CSSClassList is a JavaScript class that simulates DOMTokenList
function CSSClassList(e) { this.e = e; }
// Return true if e.className contains the class c, false otherwise
CSSClassList.prototype.contains = function(c) {
// Check that c is a valid class name
if (c.length === 0 || c.indexOf(" ") != -1)
throw new Error("Invalid class name: '" + c + "'");
// Check common cases first
var classes = this.e.className;
if (!classes) return false; // e has no classes at all
if (classes === c) return true; // e has one class that matches exactly
// Otherwise, use a RegExp to search for c as a word by itself
// \b in a regular expression requires a match at a word boundary.
return classes.search("\\b" + c + "\\b") != -1;
};
// Add c to the e.className if it is not already present
CSSClassList.prototype.add = function(c) {
if (this.contains(c)) return; // Do nothing if already present
var classes = this.e.className;
if (classes && classes[classes.length-1] != " ")
c = " " + c; // Add a space if we need one
this.e.className += c; // Add c to the className
};
// Remove all occurrences of c from e.className
CSSClassList.prototype.remove = function(c) {
// Make sure c is a valid class name
if (c.length === 0 || c.indexOf(" ") != -1)
throw new Error("Invalid class name: '" + c + "'");
// Remove all occurances of c as a word, plus any trailing space
var pattern = new RegExp("\\b" + c + "\\b\\s*", "g");
this.e.className = this.e.className.replace(pattern, "");
};
// Add c to e.className if it is not already present and return true.
// Otherwise, remove all occurrences of c from e.className and return false.
CSSClassList.prototype.toggle = function(c) {
if (this.contains(c)) { // If e.className contains c
this.remove(c); // then remove it.
return false;
}
else { // Otherwise:
this.add(c); // add it.
return true;
}
};
// Return e.className itself
CSSClassList.prototype.toString = function() { return this.e.className; };
// Return of the names in e.className
CSSClassList.prototype.toArray = function() {
return this.e.className.match(/\b\w+\b/g) || [];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment