Tuesday, June 28th, 2005

Prototype and DWR: function $()

Category: JavaScript, Prototype

You may have seen $('someId') in some of the JavaScript frameworks out there such as Prototype and DWR.

We have had people wonder what kind of magic that is, and it is just a function. The name of that function just happens to be ‘$’, which is totally valid in JS.

Prototype, being nice and pragmatic, saw that there was a LOT of document.getElementById(element) all over the shop. So they give us the shorthand of $(element). A lot nicer :)

To see one implementation check out the DWR JavaScript docs.

function $()
var elements = new Array();

for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') { if (document.getElementById) { element = document.getElementById(element); } else if (document.all) { element = document.all[element]; } } if (arguments.length == 1) { return element; } elements.push(element); } return elements; }

Posted by Dion Almaer at 11:41 am

3.9 rating from 20 votes


Comments feed

Handy, elegant, and Perlish.

Well done :)


Comment by Geoff Moller — June 28, 2005

You know, this is the exact kind of thing that killed DHTML off the bat. YOU DON’T NEED TO WRAP A NATIVE FUNCTION WITH ANOTHER ONE, JUST TO MAKE IT SHORTER.

It doesn’t get simpler than document.getElementById(…). There is no reason–unless you’re looking to compress your code–to wrap that function with something else.

Now if I’m using that library, I need to remember that “gee, there’s 2 versions of getElementById”. What happens if I use someone else’s code that also has a wrapper for that? Now I have to remember 3 versions.

There is NO REASON to be doing this; this is BAD practice, in any language. This is like wrapping String.toUpper or something because you don’t like the way it was spelled…

Comment by trt — June 28, 2005

$ = 1 character
document.getElementById = 23 characters

I don’t mind the function wrapping. It’s saving me from typing an extra 22 characters on a function that I use A LOT. Plus, it does more than just document.GEById (see, I don’t even feel like re-typing it for sake of this comment =P)

Comment by Ramin — June 29, 2005

The only thing what is not so elegant there I think is that, instead of define the function 2 times with a browser wrapper outside, it is written in the functions itself. This is not very good for the performance of the whole thing.

Better could be

if (document.getElementById)
function $() { … };
function $() { … };

Comment by Sebastian — June 29, 2005


No, but did you notice where the method is more robust? It works with older versions of IE, works with more than one element, etc. I did something similar (but not as cool as $) for our JS library: at its simplest, it returns the object from getElementById if it can, false if it cannot, which makes if/ else tests more obvious in the code. Better yet, it doesn’t blow up on browsers that don’t know gEBI and it can be extended to support other browsers whenever the need arises.

Comment by Tom Clancy — June 29, 2005

Sweet! I was trying to figure that out yesterday. Now I know. Thanks.

Comment by dru — June 29, 2005

“I don’t mind the function wrapping. It’s saving me from typing an extra 22 characters on a function that I use A LOT.”

OK. Let me rephrase then. If you are writing something that will be used by you and only you, then go for it–because at that point you are the only one that has to understand it. BUT if you are writing a library that is out there for public consumption, the game changes a lot; it’s no longer you that is the main audience for it.

“No, but did you notice where the method is more robust?”

Yes, I did, and that would be about the only reason to do something like that. But then you start (in this case) running into questions of browser support and compatibility…

I’m not trying to criticize Prototype directly here; as a consumer of many different DHTML APIs and an author and contributor to at least three, I can say without a doubt that Prototype is pretty nice.

But with the Ajax hype comes a whole new generation of people who are going to repeat the exact same mistakes many of us made in the hey-dey of DHTML, and I would prevent that if I could.

Writing wrapper functions because you are lazy is not an acceptable reason. Writing wrapper functions to create more robust functionality is a different story; at that point it’s not quite a wrapper anyways, but more of an augmentation.

Comment by trt — June 29, 2005

Actually, if you look at the DWR implementation of this, it is coded to handle old browser versions. Thats what the “else if (document.all)” takes care off. It is also quite a bit more robust then doc.getElementById… in that you can ask for multiple things and get an array back of them.

As to your wrappers are not for laziness arguement, I agree…for the most part. However, I think the replacing doc.getElementById might actually improve readability, as your code will become shorter and cleaner with less line wrapping. For lesser used functions, the extra indirection is would not be worth it.

Comment by Rob — June 29, 2005

When we refactored our Sabre framework and came out with Rico, it was some of this elegance in the Prototype framework that drove us to rewrite based on it. We have found it to be much more readable code than the alternative. One note. In time critical areas avoid doing this over and over. Instead stuff in it a var, this avoids repeated function calls which can get expensive in timers and fine grained events.

Comment by Bill Scott — June 30, 2005

The backwards compatibility hacks in Prototype, this one especially, are for naught, as the Prototype library doesn’t support any of those browsers anyway! It simply clutters the code.

Comment by Bob Ippolito — June 30, 2005

Leave a comment

You must be logged in to post a comment.