Hello Everyone - I just wanted to quickly pull together some of my thoughts concerning querySelectorAll. I've been asked by a number of people to provide my feedback here. Please forgive me if I've missed some previous discussions on the subject matter.
There's three major points that I wanted to discuss: * DOMElement.querySelectorAll returning incorrect elements This is the most critical issue. As it stands DOM Element-rooted queries are borderline useless to libraries - and users. Their default behavior is unexpected and confusing. Demonstrated with an example, using Dojo: <div><p id="foo"><span></span></p></div> <script src="http://o.aolcdn.com/dojo/1.1.0/dojo/dojo.xd.js"></script> <script> var foo = document.getElementById("foo"); alert( dojo.query('div span', foo).length ); // should return nothing alert( foo.querySelectorAll('div span').length ); // will return the SPAN </script> The demo can be run online here: http://ejohn.org/files/bugs/qsa-root/dojo.html This is due to the fact that element-rooted queries are handled by "finding all the elements that match the given selector -- rooted in the document -- then filtering by the ones that have the specified element as an ancestor." This is completely unacceptable. Not only is it not intuitive (finding elements that don't match the correct expression) but it goes against what every single JavaScript library provides. If there behavior were persisted then there would be serious ramifications for the usefulness of this function in the wild. I asked some of the other library developers what their thoughts were and they agreed with my conclusion. Andrew Dupont (creator of Prototype's selector engine): "My issue with this is that it violates principle of least surprise and bears no resemblance to the APIs in the wild." Alex Russell (creator of Dojo's selector engine): "This is a spec bug." * Combinator-rooted Queries I read about some prior discussion concerning this (especially in relation to DOMElement.querySelectorAll-style queries). This is an important part of most libraries, as it stands. Maciej's proposed solution of using :root to allow for front-leading combinators is perfectly acceptable to me (where :root is made equivalent to the element, not the document element). // jQuery $("#foo").find("> span"); // DOM document.getElementById("foo").querySelectorAll(":root > span") This is something that a library can easily detect and inject. * Error-handling I'm perfectly fine with the proposed try/catch solution however there must be a way of easily determining what the invalid portion of the selector was. Currently the following occurs in Safari: try { document.querySelectorAll("div:foo"); } catch(e) { alert(e); // "Error: SYNTAX_ERR: DOM Exception 12" } If there was an extra property to point to what the inappropriate selector was, that'd be fundamentally important. Probably the best solution (for both implementers and JavaScript library authors) would be to simply provide a character index, working something like the following: var selector = "div:foo"; try { document.querySelectorAll(selector); } catch(e) { alert(selector.slice(e.position)); // ":foo" } The resulting solution in most libraries would then look something like (of course different caching could take place, as well): try { results = document.querySelectorAll(selector); } catch(e) { results = filterQuery( document.querySelectorAll( selector.slice(0, e.position) ), selector.slice(e.position) ); } There will be some form of a performance hit here but I think, if done correctly, it'll be negligible (especially in comparison to the benefits that are being received). I hope these proposed changes work well for the members of this group as they will greatly benefit general web developers - and especially library developers. John Resig jQuery JavaScript Library, Mozilla Corporation