It is becoming fashionable to use JavaScript to add behavior to a page without writing it into the (x)HTML. This is a good thing, in my view; it further distinguishes content from interface behavior, makes the code tighter, smaller, more human-readable, and makes it more resilient to the well-meaning machinations of the back-end guys.
Recently, noting the many different forms of (front-end) validation that would be necessary in a web application, I considered getting into using custom attributes to carry relevant metadata. I was considering something like this:
<input type="text" required="true" validation="float" value="" />
which would have all of the aforementioned advantages, and allow all manner of interesting behaviors to be attached at runtime with minimal difficulty. But since no flavor of XHTML or HTML allows the use of custom attributes without inclusion of a custom DTD , which is a big hassle, and since I had recently made validation a portion of some automated test cases, I had to abandon that route. I’ll pursue it elsewhere, naturally. But if you want your pages to validate, or if you care that your web-building friends will clown you mercilessly if your pages do not, this fact can spell trouble.
The obvious alternative is to overload the class attribute. This is already becoming common for styling reasons, since the modern browsers and recent flavors of Interner Explorer all support putting multiple class names in the class attribute, delimited by spaces. Since we can easily get the contents of the class attribute via JavaScript, why not stuff class full of metadata? It is safe and it validates.
Two reasons. One, I like to label my metadata. When you are no longer working at your current job, or on your current project, or when this phase of this project is over, someone else is going to have to look at the code, come to an understanding of it. You should be making it easy for them, or for yourself (because you’ll forget what you meant by
class="topmatter required multi"
). Two, It has also become common to change or destroy classes as part of CSS-enabled JavaScript interface behaviors. When the class name is no longer a single value, this becomes more complicated.
They are trivial, really, but I’ve whipped up some simple functions to help manage this situation. Unfortunately Ineternet Explorer doesn’t let you add methods to the Node prototype, or these would be even simpler, even tighter, even more useful. But here they are (mostly self-documenting):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | function addClass(element, classStr) { if (!element.className) { element.className = classStr; } else { element.className = element.className + " " + classStr; } return this; } function removeClass(element, classStr) { if (!!element.className) { var re = new RegExp(classStr); element.className = element.className.replace(re, ""); } return this; } function containsClass(element, classStr) { var re = new RegExp(classStr); if (!!element.className && element.className.match(re)) { return true; } return false; } |
Granted, these aren’t exactly as squeaky-clean as they could be.
removeClass()
does nothing about any extraneous spaces that might be left in the class name, which shouldn’t matter unless you use these functions to change the add and remove classes on a single element many many times in a page. And
addClass()
doesn’t check to see whether or not the new class is already present, it just tacks it on to the end. I’ll extend these later, but I wanted to make sure they were very tight, very efficient.