Tuesday, January 9th, 2007
Custom DOM Attributes vs. Class CSS styles
Pete Forde isn't a huge fan of the practical but not pure use of class="noncssmarker" and has written about Attributes > Classes: Custom DOM Attributes for Fun and Profit.
In this article Pete discusses the high level value of attributes, but then goes a lot further and he patches Prototype to make it just as easy to work with as CSS classes:
-
-
function $P(property) {
-
return document.getElementsByAttribute(property).pluck(property);
-
}
-
-
$P('subtotal') # => ["13488","9534"]
-
$P('subtotal').sum() # => 23022
-
How does this work?
Custom attributes work in all browsers that support XHTML. You do not have to define a custom DTD or sacrifice any children to use them.
We do have to make some changes to the way Prototype works, though. With the addition of a few functions to our application.js, we suddenly have the same flexibility that we had with Element.classNames.
Of course, if you go this route expect XML nazi's to moan about validation.













“Of course, if you go this route expect XML nazi’s to moan about validation.”
Dion, bad bad bad. Never use an apostrophe to make a plural.
Cool article though. :)
XML Nazi’s can moan about validation all they want, this is the defentally the best way to go in my opinion
Wait i think James has a fair point, i think its just nazis. I should have payed attention more in school
You should have *paid* more attention in school.
Nobody ever said that the class attribute was just a “css marker”
What’s stopping the use of custom attributes as long as you define them in a DTD or schema document? Still a valid document as long as it is defined. It’s already done to allow microformats in XHTML, why not custom attributes?
CrackWilding - No i meant, i should have payed attention some money to help me concentrate at school :)
Indeed Cedric. The class attribute is not specifically for CSS. However, from my OOP classes (no pun intended) I learned that every object always “is a” certain type, meaning only one type. C# and Java for instance, do not have multiple inheritance, each object is only one type.
So, here’s my proposition: add an attribute to every xhtml tag called “implements”. Then we can do this to all elements:
bar
Oops, I meant to give this example:
<foo implements=”IDraggable”>bar<foo>
Using CSS classes facilitates degrade-ability and unobtrusive JS implementation. Intelligent choice of class names (a la Microformats) also encourage semantic (and therefore correct) classes, over purely presentational ones. If I know I want my app to do something with all of the phone numbers on the page, using <span class=”phone”> serves any audience, whether they’re taking advantage of my script or using a browser for the visually impaired.
> What’s stopping the use of custom attributes as long as you
> define them in a DTD or schema document?
Nothing. You even don’t need to use XHTML for this. After all, XHTML support is so broken in IE, it is not feasable to use it anyway.
I guess now is an appropriate time to point out that this is how Dojo has been supporting metadata passing since day one.
Maybe we can all wake up from our validation nightmare and get back to doing things that are good for users.
Regards
Alex et al - show me the money! Maybe this example is not a good one but… Do I need a sub-total in the markup? A quick look but no, I don’t. If we are going to use JavaScript anyway then why fragment the logic into JS and HTML? The use of Prototype is spurious. Mixing markup and logic is not a good idea. Show me a better example Ajaxians!
While I generally consider it to be in bad form to comment on my own thread, I respect Dean enough that I did want to offer a response.
I’ll take responsibility for not communicating the reason this article was written clearly enough. You asked why we need to embed metadata in the markup. While that is certainly a valid question on its own, the reality is that Ajax developers currently use metadata all of the time in today’s apps; they’re just doing it with class markers. So this isn’t a “should we” but a “how should we”?
The reason I wrote this is that I believe that using custom attributes accomplishes everything using class markers does, better.
How do I quantify better? In addition to little details like readability, to me the money shot is the ability to use name value pairs. If more, smart people start brainstorming “crazy” things they can do with this functionality, we can expect applications tomorrow that do things today’s applications don’t do. Isn’t that reason enough to spend a few showers wondering what you could do if a TR knew what database row id it was attached to? Maybe this isn’t the earth shaking example you need, but I don’t claim to be the smart people that can think up brilliant applications for arbitrary metadata.
What happens when _why? drops some more acid and starts to teach this in his curriculum at The University of Mininova?
I’m passionate about the sheer unknown possibilities of something that is widely deployed but most developers just haven’t touched yet. You can laugh all you want, but Paul Graham used Lisp to build what became Yahoo Stores just because nobody else was using it.
With Dojo, we’ve considered dropping custom attribute support and moving exclusively to class markers (we currently support both).
But we’re not considering this switch to make the “oh my god, it doesn’t validate” crowd happy, but rather as part of our work on improving Dojo performance. Alex will have more information and performance profiling numbers to share very soon.
From http://www.w3.org/TR/html4/struct/global.html#h-7.5.2
The class attribute has several roles in HTML:
- As a style sheet selector (when an author wishes to assign style information to a set of elements).
- For general purpose processing by user agents.
So it’s perfectly valid to use the class attribute for storing data that are not just hooks for CSS.
one example I can think of, would be to give details on how you’d want an external window opened.
myUrl
This gives you nice clean, onobtrusive and reusable code. Adding custom attributes all over and expecting all sorts of user-agents to be able to handle it, does not.
Grr
<a href=”myURL” class=”external newwidnow*wide”>myURL</a>
Dean Edwards > here’s one use I made of custom-attributes-instead-of-classes.
It’s the only use I ever did of it, and the project is still in a repository waiting to be completed, but…
“Autovalidating” forms.
Usually, when you want to validate forms in javascript, you have two paths: for each form create the whole validation logic (custom for each form), or just send the form via xmlHttpRequest to have it validated server-side.
The first solution is annoying because you have to create custom JS validators, the second one is stupid because most forms don’t require the server to validate their values (send correctness hints to the user).
Solution? Have each form field carry its own validating informations: can it be empty, should its value validate against something (regex?), should an other field be checked, does it allow the selection/checking/usage of other fields, …
I found it far too unwieldy to be done via classes: i’d have to wind up creating a DSL all fit into the class attribute that i’d have to handle and parse, without borking the other (CSS) classes. With DOM attributes, all the parsing was already done, I merely had to check if an attribute was here, and test/extract its value when needed.
Using custom DOM attributes yield:
* A far lower amount of (personal and machine) work to parse and retrieve the informations
* Cleaner code and logic
* The potential, future ability to hook in CSS rules via the use of attr selectors, which currently don’t work on MSIE but should be useable in other browsers, in ways much cleaner than using endless lists of classes.
I found custom DOM attributes to enhance the semantics of my document in ways not possible with regular classes: not only were they more precise, but they were also much cleaner (anyone reading the source code could see the client-side requirements of each field) and much more maintainable (because a field and the rules applying to it were kept close to one another)
I use an attribute ‘validate’ and patched proto to look for it.
It does some automatic validation for forms and field elements.
if(elements[j].getAttribute(’validate’) == ‘foo’)
I looked around at how other people where doing validation and nothing was this clean. I also use an automatic form handler
so you can code buttons like:
actionForm(’tikiform’,'xml.x?m=quotes2/detail/action&action=display’,'RUN’,'ALL’,'contentpane’)
where RUN tells the handler what to do (TEST will show vars) and ALL is a key word for send all data or you could use a comma seperated field list.
If you’re going to have an attribute that specifies a behavior and you also want to apply a particular styling to it (for instance, show all required fields in bold), then you end up with. ..
<input … validate=”required” class=”required” />
That’s pushing the separation of behavior/presentation one step too far. In my opinion, this is more elegant and practical (at least that’s what I use in the wForms library):
<input … class=”validate-required” />
As Masklinn pointed out, with better support for attribute selectors in CSS, we could get rid of the class attribute in the first example, but that’s not well supported enough at this point.
For me, it’s all about the parsing convenience and flexibility (name/value pairs). I think plucking out a classname from a given arbitrarily-long space-seperated list of class names has got to be slower than getting the attribute directly from the DOM, but maybe I’ll be proved wrong.
In another example, I used custom XML attributes to hold some dragging data in an SVG demo, rather than parsing a potentially complex transform string … but this really came down to current SVG implementation deficiencies.
To follow up my cousin’s comment (funny coincidence) - I’m for class names over custom attributes, for a few reasons. While JS string parsing someElement.className via regExp or indexOf() etc. sounds less-than-ideal, it works nicely with a tested algorithm and I suspect may be faster than custom attributes in terms of performance. Provided you aren’t constantly changing class names via JS, your performance should be pretty good overall. Classes are a great way of setting flags for script hooks, without cluttering the document or making it invalid.
I’m so glad to see that after 22 comments here, not a single nazi has appeared. The world is becoming a better place :)
I’m a huge fan of custom attributes, but try not to get carried away — i use classNames as well, depending…
I have one worry, and one problem though:
Worry: will a doctype declaration render custom attributes invisible? I wouldn’t know — i still love ‘quirks-mode’ so i never use a DTD statement.
Problem: impossible to include custom attributes in struts tags, like [html:form], although i’ve been known to add them to the dom element after the page is rendered.
How ’bout using custom namespaces with custom attributes like this:
?
Imho, that’ll fix possible validation problems. The only drawback I can see for now is that this method can’t be used in HTML, xHTML only.
Oh, sorry, sample was cut away… Here it is:
<div xmlns:myns="urn:mysite" myns:value="whatever_i_want">
ARGGGHHH Stop doing stupid stuff. Dojo made this mistake ( prolly their only mistake ).
1) if you are going to extend XHTML you have to define a seperate name space for your special tags. If you don’t, you loose all the display consistancy which you achieved by using XHTML in the first place ( of course if you do, then IE pukes ).
2) I have never yet run into a space where the class attribute could not serve polymorphically as both visual presentation and application descriptor to use Pete Forde example:
simply becomes:
Now you have a class of inputs to which you can assign specific functionality
inputs = dojo.getElementByClassName(’dollar_input’);
do_something(inputs)
A class is a class of things. Like a noun it can have both adjectives and verbs modifying it.
If only getElementByClassName was supported natively! then the debate would be closed :-)
Let’s not go accusing IE of bad puking on XHTML. Namespaced elements / attributes work pretty well in IE from my experience, however, Firefox has a few issues like parentNode not being correct (check it out here and definitely read the comments). The most interesting of which is probably Mark Birbeck’s (note the use of the apostrophe) comment about the “role” attribute in XHTML 2. Just for the record, I like custom attributes AND elements :)
I’ll leave the argument of classes vs. proprietary attributes for another day. What I’d like to say right now is that I find it completely unacceptable to characterise somebody as a nazi. Reducto ad Hitlerum has no place in a discussion about something as trivial as JavaScript.
Any guides out there on extended the XHTML DTD to include custom DTDs?
For me, it’s all about the parsing convenience and flexibility (name/value pairs).
Daelen, programmer of herbal supplements