Tuesday, January 9th, 2007

Custom DOM Attributes vs. Class CSS styles

Category: Articles, Prototype

<p>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:

javascript
< view plain text >
  1. function $P(property) {
  2.   return document.getElementsByAttribute(property).pluck(property);
  3. }
  4.  
  5. $P('subtotal') # => ["13488","9534"]
  6. $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.

Related Content:

Posted by Dion Almaer at 10:40 am
29 Comments

++++-
4 rating from 34 votes

29 Comments »

Comments feed TrackBack URI

“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. :)

Comment by James MacFarlane — January 9, 2007

XML Nazi’s can moan about validation all they want, this is the defentally the best way to go in my opinion

Comment by Jason — January 9, 2007

Wait i think James has a fair point, i think its just nazis. I should have payed attention more in school

Comment by Jason — January 9, 2007

Nobody ever said that the class attribute was just a “css marker”

Comment by cedric — January 9, 2007

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?

Comment by Doug — January 9, 2007

CrackWilding – No i meant, i should have payed attention some money to help me concentrate at school :)

Comment by Jason — January 9, 2007

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

Comment by Mike — January 9, 2007

Oops, I meant to give this example:

<foo implements=”IDraggable”>bar<foo>

Comment by Mike — January 9, 2007

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.

Comment by ARWolff — January 9, 2007

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

Comment by Martin — January 9, 2007

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

Comment by Alex Russell — January 9, 2007

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!

Comment by Dean Edwards — January 9, 2007

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.

Comment by Pete Forde — January 9, 2007

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.

Comment by Dylan Schiemann — January 9, 2007

Grr

<a href=”myURL” class=”external newwidnow*wide”>myURL</a>

Comment by Morgan Roderick — January 10, 2007

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)

Comment by Masklinn — January 10, 2007

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.

Comment by mmdonohue — January 10, 2007

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.

Comment by cedric — January 10, 2007

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.

Comment by Jeff Schiller — January 10, 2007

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.

Comment by Scott Schiller — January 10, 2007

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 , although i’ve been known to add them to the dom element after the page is rendered.

Comment by Marty — January 10, 2007

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.

Comment by Nakago — January 10, 2007

Oh, sorry, sample was cut away… Here it is:

<div xmlns:myns="urn:mysite" myns:value="whatever_i_want">

Comment by Nakago — January 10, 2007

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.

Comment by Vance Dubberly — January 10, 2007

If only getElementByClassName was supported natively! then the debate would be closed :-)

Comment by cedric — January 10, 2007

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 :)

Comment by Dave Johnson — January 11, 2007

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.

Comment by Jeremy Keith — January 14, 2007

Any guides out there on extended the XHTML DTD to include custom DTDs?

Comment by SimpleInventor — June 10, 2008

I need to switch the styles between some elements depending on comparing some values associated with those elements with each other. I could perform the processing on the server side, to figure out which element to apply which style to, but I’d rather push that processing out to JavaScript. (So 1000 users pc’s do it, instead of the server doing it for 1000 users.) So what’s the least server-cpu-intensive, least code-bloating way to communicate which elements have what (for example, numeric) values to JavaScript?

For example say I have a list of products. I’m not using the visual screen real estate to display the prices in this particular view, but I want to make the one with the lowest price one color, and the one with the highest price a different color. Is this not a perfect application for a custom attribute? Called, say, “price”? And do I really need to define a whole custom DTD every time I need a data storing attribute like that? Is it really not appropriate to but the data in the DOM, I mean, do I really need to create a whole separate, custom, JavaScript object schema, other than the already existing DOM which I’m going to be using anyway for other things, to store / communicate this kind of data?

Here’s an example of what I’d like to do: Instantiate a javascript array in a script tag, which some javascript scans on load, that says “take the elements with these ids, compare the values they have for this attribute using this named comparison, and apply this style to the ones that meet the criteria implied by the comparison.”

I can see defining a custom DTD if there were any consumer for it other than my own application, but there isn’t. I’m not intending to communicate XML data to some 3rd party, using some communicated standard, I’m just trying to communicate between the server side of my application and the client side.

I suppose someone might argue that validating to a custom DTD forces you to thoroughly document what you are doing, but I’d rather decide for myself when and where doing so is worth while, and in any event, I personally don’t find a custom DTD to have all that much value as coding documentation. I can think of much easier and clearer ways to document the fact that I’m using a particular custom attribute for a particular purpose in specific areas than a custom XML schema DTD. I mean, yeah, ok, maybe it’s nice to be able to rest knowing that there are no attributes in your HTML other than those defined in the DTD, but it’s nicer to get your job done on time and under budget.

(I know, you probably think that in a project of any significant size, enforcing this rule actually reduces the over all time the dev team spends maintaining stuff, but I just don’t agree with that assessment, in fact, imo the opposite is true, and it doesn’t matter what the scale is.)

Comment by Shavais — July 29, 2009

Leave a comment

You must be logged in to post a comment.