Selectors API
By lachlan.hunt. Thursday, 22. May 2008, 10:49:04
The Selectors API specification, currently being worked on within the WebAPI working group at the W3C, defines DOM APIs designed to make it possible to select elements within the document using Selectors. This simple, yet powerful API has the potential to make working with the DOM faster and easier. If you’re familiar with CSS, you will be familiar with Selectors and these APIs should be easy to learn.
For example, to select all the em and strong elements within the document, you can use this.
document.querySelectorAll("em, strong");
To see how much easier this is compared with traditional APIs, consider this example HTML fragment:
<ul id="fruits"> <li><input type="checkbox" name="fruit" value="apples"> Apples</li> <li><input type="checkbox" name="fruit" value="oranges"> Oranges</li> <li><input type="checkbox" name="fruit" value="bananas"> Bananas</li> <li><input type="checkbox" name="fruit" value="grapes"> Grapes</li> </ul>
After the user has filled out the form containing those check boxes, suppose you want to get the list of all the checked items. Using traditional APIs, this would require obtaining a list of all the input elements and iteratively checking which ones were checked.
var fruits = document.getElementById("fruits");
var checkboxes = fruits.getElementsByTagName("input");
var list = [];
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
list.push(checkboxes[i]);
}
}
Using these new APIs, the operation can be reduced to a single line of code!
var list = document.querySelectorAll("#fruits input:checked");
This returns a node list containing all the input elements that were checked by the user. Your script can then perform any operation you like with them.
We have been working on an implementation of these APIs recently and support has been included within the recently released Acid 3 build.
There are two new methods introduced: querySelector() and querySelectorAll(). The former returns the first matching element within the tree, and the latter returns a collection of all matching elements as a NodeList. The current editor’s draft specification defines that the methods are available on the Document, Element and DocumentFragment nodes. However, our implementation currently only supports it on the Document and Elements nodes.
The querySelector() method is useful for situations where only the first matching element is needed, and is designed to be more efficient than the alternative querySelectorAll() method in such cases.
For example, the following form control and javascript function could be used to validate an email address. For simplicity, this uses the validity APIs from Web Forms 2.0. If support for legacy user agents is required, a more appropriate validity check could be written. The querySelector() method is used to obtain the correct element for outputting the appropriate error message, or clearing it when it is valid.
The JavaScript:
function validateEmail(evt) {
var ctrl = event.target;
var parent = ctrl.parentNode;
var errMsg = parent.querySelector(".error");
// Validate form control value
if (!ctrl.validity.valid) {
errMsg.innerHTML = "Invalid email address."
} else {
errMsg.innerHTML = "";
}
}
The HTML fragment:
<p><input type="email" name="email" onchange="validateEmail();"> <strong class="error"></strong></p>
Our implementation also partially supports the namespace resolver features, allowing you to work with mixed namespace documents and select elements based on their namespace. Consult the specification for more information on the NSResolver object.
You can try out these examples for yourself in the recently released Acid 3 Gogi Build which is available for Windows and Linux.
Great work.
By GreyWyvern, # 22. May 2008, 13:34:09
While it would be nice to have this integrated to browser, i don't see this really catching on in the near future, especially since IE is not so fast at implementing new standards...
By d4n3, # 22. May 2008, 16:36:51
By virtuelvis, # 22. May 2008, 18:30:46
By peroo, # 22. May 2008, 18:33:06
By lachlan.hunt, # 22. May 2008, 20:01:10
I hope JS libraries will implement DOM queries in standard compliant way, so if native support will be available JS library will use it.
At that moment I know only one example of such library: base2.
Prototype, jQuery, YUI, ExtJS, DOMAssistant doen't have any clues about querySelector.
Mootools had unaccepted path for this with such reason for dissaproval:
By FataL, # 22. May 2008, 20:37:39
To clarify things: WebKit implemented it and it's available at least in 3.1
IE8b1 implemented this as well, but without Namespaces, as far as I know.
Mozilla plans to do this for the 1.9.1 release of Gecko which is planned for end of this year.
And now Opera, this is really great. It seems to see the light very soon and will get Web Apps a better performance.
By Zake, # 22. May 2008, 21:04:23
Examples:
Selectors API:
document.querySelectorAll("em, strong");Xpath:
document.selectNodes('//em|//strong');or
document.selectNodes('//*[name() = "em" or name() = "strong"]');
Selectors API:
var errMsg = parent.querySelector(".error");Xpath:
var errMsg = parent.selectSingleNode('//*[contains(concat(" ", @class, " "), " error ")]')This is where selectors outshine xpath. Xpath can only find the elements whom have <input ... checked="checked" /> in the source. However, clicking a checkbox nor changing elem.checked changes/adds the checked property to the element. So that will be most useful. Thanks for the article. Glad the core is getting some love.
By fearphage, # 23. May 2008, 12:45:47
By Fyrd, # 23. May 2008, 13:17:59
The API doesn't mention what level of CSS it should support as a minimum.
The problem becomes obvious when you have a javascript version of Selectors API like the ones you have in jquery, prototype, moo tools and others, and you want to accelerate them with Selectors API if present.
All of these libraries have supported a couple of CSS 3 stuff for a long time, and some of them are really popular because of their use cases in javascript:
*:odd ( get every odd child pr matched tag )
*:even ( get every even child pr matched tag )
*:child(2) ( get child 2 pr matched tag )
*:last-child (get last child of every matched tag )
The first three maps perfectly with :nth-child :
*:nth-child(odd)
*:nth-child(even)
*:nth-child(2)
My point is that the Specification should demand full CSS 2.1 support and some of the most needed child selectors in CSS3 like nth-child and last-child ( maybe also nth-type, but haven't used that much so wouldn't know the value of it ). And IE8 is at the moment the only browser that is holding this back from being the case.
As for xpath, Selector API is from the benchmarks I have seen around, a lot faster. So I don't think it uses xpath internally.
By andré1, # 23. May 2008, 19:13:40
XPath uses the DOM much more completely. It can step back up the tree, and manipulate strings. For example, XPath can say "select the one-but-last paragraph inside a div that has a span inside it that contains a DFN containing the text 'hello' when the text nodes of all child elements are concatenated with spaces ignored". CSS selectors cannot do this, since they cannot select the parent of the element at the end of the selector, and they cannot manipulate strings (even :contains is not good enough for that).
Selectors can select elements based on dynamic pseudo-classes, which XPath cannot, since XPath only sees the resulting DOM.
The benefit of CSS selectors (besides their generally far easier syntax) is that they can use the CSS engine - the same one that works out what style rules apply to what element. Because of the reduced complexity in the selectors engine, not needing to know how to walk back up the tree, CSS selectors can perform faster than XPath in many cases. After all, it manages to apply all of the rules in any stylesheet in realtime to all elements in a document, while XPath is generally suited to one-off requests. It would not make sense to use the XPath engine to do this, when there is already a faster CSS engine sitting there in the layout engine.
The limitation of using CSS selectors is that they are not so flexible.
By tarquinwj, # 27. May 2008, 16:50:38
By D555, # 2. June 2008, 17:13:57
Just thinking that if IE will support querySelectorAll but not getElementsByClassName, then why would anyone even bother using it?
By Fyrd, # 6. June 2008, 13:00:26