~robcee/ more than just sandwiches

3 August 2012 @ 1pm

Code, devtools, Firebug, Firefox, Mozilla

WebConsole’s $() convenience function: querySelector

tl;dr If you’re used to using $("id") in the WebConsole to lookup nodes with a given id, prepare to get used to doing it with $("#id").

There was a short discussion in the #firebug channel in IRC this week about the usefulness (or lack thereof) of the $() convenience function in the Console (Firebug’s, Firefox’ Web Console, Chrome’s Console, all of ‘em). They currently map to getElementById. Way back in ought-five, when Firebug was still a twinkle in Joe Hewitt’s eye, getElementById probably made more sense than it does today. These days, you don’t see a lot of nodes in a webpage carrying the ID attribute. There are probably some good reasons for this. Having a rich selector API in all browsers is certainly at the top of that list of reasons.

Paul Irish’s initial suggestion was to use querySelectorAll for $(). I felt this would be kind of annoying for users used to getting back a single node. We compromised on using the querySelector function for $() and leaving querySelectorAll on $$(). I think this gives them both a useful purpose and will provide the least breakage for users of $().

It’s a pretty innocuous fix and it’ll be in Firefox Nightly sometime this weekend. Some of the discussions this has spawned have been pretty interesting. It would be nice to have a better iterable interface on NodeLists for example (Array.forEach(list, function...) is way more annoying to type than just list.forEach(function...)). With a proxy object, we could combine the results of $() and return a NodeList in the case where there were non-unique matches and return a single element if there were an exact ID match (without having to prepend the octothorpe to the query).

Leave a comment with your own magical $() wishes or ideas.

You can see the initial discussion in bug 778732. Firebug’s issue 5764 and Webkit’s bug 92648.


Posted by
3 August 2012 @ 2pm

I usually do for each (let [, y] in Iterator(…)) where … is the result of querySelectorAll. I assume the web console has the latest javascript features, so maybe you can apply a similar trick? Like return [y for each ([, y] in Iterator($(…))]? Or maybe the newest let of construct is smart enough to be able to iterate over an HTMLCollection?

(Trying to find something less fancy than resorting to ES6 Proxies.)

Posted by
3 August 2012 @ 5pm

yeah, that would work, but it’s still a lot wordier than just $$(“div”).forEach(…). :)

Posted by
Sean Hogan
3 August 2012 @ 7pm

IDs can have characters that need to be escaped if using querySelector. e.g.


has to be written as


It would be nice to still have a short-cut for document.getElementById. How about $id().

Regarding iteration on node-lists…
I don’t think anyone needs the console’s $$ to blazingly fast, so why not copy the result into an array, something like:

function $$(sel) {
return [].slice.call(document.querySelectorAll(sel),0);

Posted by
tom jones
3 August 2012 @ 7pm

how about a backward-compatible $ function that would function like the old one if you provide a string that “looks like an id”, but without the ‘#’ prefix.

so $(‘something’) would be equivalent to $(‘#something’)

but $(‘div’) would still return all the DIVs and not an element with an id=’div’.

so essentially, special-casing simple css selectors that look like simple tag names (but that are *not* the name of a standard html element) to behave like the old $ function..

Posted by
3 August 2012 @ 10pm

Simpler than for each (let [, y] in Iterator(…)) would be this (which works on NodeLists in Firefox 14):

for (y of …)

Posted by
4 August 2012 @ 2pm

Simpler than for each (let [, y] in Iterator(…)) would be this (which works on NodeLists in Firefox 14):

for (y of …)

we have a winner! *dingding* :)