cssQuery(): query the DOM with CSS selectors

(Via Planet Web 2.0) cssQuery(), a new JavaScript library from Dean Edwards of the IE7 script fame, sits on top of the Document Object Model (DOM) and lets you obtain references to document elements using CSS selector syntax.

The DOM is a powerful and efficient API for reading, writing and modifying HTML and XML documents. Used with JavaScript, it’s the foundation of DHTML effects. But boy can it require a lot of code sometimes.

Consider this little snippet, from a table sorting script we use here on SitePoint:

function sortables_init() {
    // Find all tables with class sortable and make them sortable
    if (!document.getElementsByTagName) return;
    tbls = document.getElementsByTagName("table");
    for (ti=0;ti<tbls.length;ti++) {
        thisTbl = tbls[ti];
        if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
            ts_makeSortable(thisTbl);
        }
    }
}

This code is perfectly good, but really all it does is call the function ts_makeSortable on every table element with the class sortable applied to it. Here’s how the code would look with cssQuery():

function sortables_init() {
    // Find all tables with class sortable and make them sortable
    tbls = cssQuery("table.sortable");
    for (ti=0;ti<tbls.length;ti++) {
        ts_makeSortable(tbls[ti]);
    }
}

In a typical DHTML script, the code savings this can provide are staggering. Certainly, you’re giving up a little performance as your CSS selectors must be parsed and interpreted in pure JavaScript, but as yet few JavaScript applications are bringing browsers to their knees.

cssQuery() supports all CSS1 and CSS2 selectors, as well as a great many CSS3 selectors. Heck, that’s better than most current Web browsers — and it’s all written in pure JavaScript!

Update: Simon Willison produced a similar library, getElementsBySelector(), back in March 2003. It doesn’t support quite as many CSS selector types, but it probably has more than you’ll ever need in everyday use. Chances are it’s lighter as a result.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Marty

    This is nice and all, but seems to miss the point. Shouldn’t CSS selectors (and by extension, this extension) support XPath selectors?

  • velocd

    Ah, this is awesome.

    I created my own similar function, as I was tired of writing much redundant code whenever needing to grab an array of certain elements (such as your SP example), however mine was far from this versatile.

    The good browser compatibility of cssQuery is note-worthy also:

    * Microsoft Internet Explorer 5+ (Windows)
    * Microsoft Internet Explorer 5.2 (Mac)
    * Firefox/Mozilla 1.6+
    * Opera 7+
    * Netscape 6+
    * Safari 1.2

    Edwards presents us yet another very useful innovative tool.

  • Jimmy Cerra

    cssQuery is actually kinda old (about as old as IE7) but really is awesome! I’ve used it in that past and it is truely an engineering marvel.

  • http://www.dustindiaz.com polvero

    Cool. Although I haven’t found a reason to use anything past my getElementsByClass() function, It’s nice to know that someone has thought of this ahead of time…even dating back to 2003.

  • whol019

    Superb.

    Though I found it not working on the scenario

    cssQuery( ‘#aaa:hover’ )
    cssQuery( ”#aaa:hover span’ )

    I would like to use this lib for setStyle function, because mine have problem with ie….

    Hope this tool could support these kinds of selector.

  • http://www.sitepoint.com/ Kevin Yank

    You’re right, whol019, the library doesn’t support dynamic pseudo-classes like :hover and :active… but cases where you’d want to use JavaScript to get elements that currently have the mouse over them (:hover) would seem to me to be very rare. Why wouldn’t you just use mouseover/mouseout event listeners?

  • whol019

    I am doing a css ImageMap editor
    that need to dynamically assign style sheet attribute to css selector,

    use mouseover/out method should work, but then the published web pages will need to include these related javascript, element position, width, height, color info, etc. This seems to me a bit more complex route to go …

    My only problem now is the editing interface not working for IE….but fine for fx/mz, so I don’t mind too much for that :)

  • http://www.sitepoint.com/ Kevin Yank

    I still don’t get it, whol019. Either you want to apply style properties to elements on mouseover (in which case a simple :hover rule in your site’s style sheet will do the trick), or you want to apply style properties in response to DOM events (in which case cssQuery() will do the trick).

    I can’t see what about your application would require responding to a DOM event by setting permanent style properties on the element that is currently moused over.

  • whol019

    Thanks Kevin, I know the situation is weird…

    I try to create a prototype that can help people, not necessary a web developer, to generate css image map web page like this,

    and these are the few lines that cssQuery not working for my preview mode script….

    setStyle( ‘#imap a#’+tmpTag+”_a”+':hover’, ‘backgroundPosition’, ‘0 0′) ;
    setStyle( ‘#imap a#’+tmpTag+”_a”+':hover span’, ‘left’, ‘-‘+( objArr[i].x-imgDivL) + ‘px’) ;
    setStyle( ‘#imap a#’+tmpTag+”_a”+':hover span’, ‘top’, (parseInt( ySize ) + 16 -objArr[i].y) + ‘px’ ) ;

    Why the app requires these features? I want to make it simple to use, is all.


    just try following the instruction, select a image, mouse select the image areas that you want
    to add hot spots, add info , click preview….

    then you may understand the situation

  • http://www.sitepoint.com/ Kevin Yank

    whol019,

    I see your problem. You misunderstand how cssQuery() is supposed to be used.

    What you’re trying to do is dynamically add CSS rules like this to your document:

    #imap a#tagname_a:hover {
    background-position: 0 0;
    }

    Adding style rules to the document is not what cssQuery() is for. cssQuery() is for using CSS selector syntax to obtain references to DOM elements. Such references are often used to add event listeners to elements, or to modify the document structure on the fly.

    In order to change the styles of a document on-the-fly the way you’re hoping to, you must insert new rules into one of the style sheets you have applied to your document. The W3C DOM2 compliant code to do this looks like this:

    document.styleSheets[0].insertRule(
    "#imap a#tagname_a:hover { background-position: 0 0;}",0);

    Of course, Internet Explorer doesn’t support this portion of the W3C DOM standard, but it has its own API for doing this sort of thing, which you can look up on MSDN.

  • whol019

    Thanks Kevin

    I understand that cssQuery return dom object arrray.

    I like this lib very much and will definitely use it later.

    That’s just my hope. Since this lib is called css_Query, I would like to see it support css rule searching as well. That will make this a great tool for web developers.

    I know one may customize it to suit his own needs, but hopefully this feature would be accepted and done by the mighty author.

  • Pingback: otro blog m