Is Your JavaScript Library Standards Compliant?

One of the things JavaScript libraries like jQuery, Dojo, and YUI can do for you is add support for features in the latest Web standards long before they are built into browsers. But are some libraries going too far?

For the developers of JavaScript libraries, there is a temptation to extend the features of the standard, and build something even better! A good example of this is the CSS selector queries that first made jQuery famous, but which are now available in most JavaScript libraries.

CSS queries provide an extremely convenient way of getting a list of elements from an HTML document that match certain criteria. As an example, you might write a script that opens all hyperlinks with the attribute rel="external" in a new window. Using just the DOM API supported by all major browsers, the JavaScript code to retrieve that list of links is pretty cumbersome:

var anchors = document.getElementsByTagName('a');
for (var i = 0; i < anchors.length; i++)
{
  var href = anchors[i].getAttribute('href');
  var rel = anchors[i].getAttribute('rel');
  if (href != null && href.length > 0 &&
      rel != null && /(^| )external( |$)/.test(rel))
  {
    // anchors[i] is a link with rel="external"
  }
}

This code starts out by getting a list of all a elements in the document, then checks each element in that list to see if it has an href attribute and a rel attribute that contains the word external.

A CSS query lets you express all these tests using the same compact CSS selector syntax we get to use when writing style sheets. Here’s how it looks using jQuery’s CSS query API:

var links = $('a[href][rel~=external]');
for (var i = 0; i < links.length; i++)
{
  // links[i] is a link with rel="external"
}

This feature proved so popular, that it was quickly added to every JavaScript library of note. Here’s the same thing using Dojo’s API:

var links =  dojo.query('a[href][rel~=external]');
for (var i = 0; i < links.length; i++)
{
  // links[i] is a link with rel="external"
}

While the various libraries battled it out to produce the fastest implementation of CSS queries, the browser makers got together at the W3C and nutted out a standard that browsers could implement natively: the Selectors API.

But here’s where things get interesting: some of the libraries, like jQuery, have added support for a whole bunch of extra selectors on top of those provided by the CSS specs, while others, like Dojo, have stuck to supporting standard CSS selectors only.

Obviously, when browsers support the Selectors API (Safari and IE8 beta 1 already do!), their native implementations will run faster than anything a JavaScript library can do. But the Selectors API only lets you use CSS selectors supported by the browser—no more, no less. Libraries that support additional, non-standard selectors will not be able to deliver this performance boost.

Here’s how Dojo’s Alex Russell put it in his announcement of the recently-released Dojo 1.1:

…by keeping our query syntax to just what CSS provides, we’ve avoided getting ourselves into a situation where we’ll always need to be shipping such a query engine down the wire. Sooner or later, dojo.query() will become nothing more than a call into querySelectorAll plus some syntactic sugar on the returned array. Best yet, API won’t change and you can get the speedup on the browsers that support it now, knowing full-well that things will only get faster and smaller in the future. An investment in a toolkit that [pays] attention to the evolution of the web is already paying dividends for Dojo users.

So, which JavaScript library do you use, and have you checked how its APIs compare to the emerging standards for equivalent built-in browser features?

Updated the code samples above to use for loops instead of for…in loops based on the feedback in comments.

Win an Annual Membership to Learnable,

SitePoint's Learning Platform

  • Jon

    How on Earth is this going “too far”? Surely the whole point of script libraries is to extend the capabilities of the browser beyond what it natively supports, not just to wrap what is already there? So should I not use Mootools animations because they’re not an implementation of a standard? Should I not write that javascript chess game until the W3C publishes a <chess> tag? I’m all for web standards, but to suggest that third party JS libraries must limit themselves merely to delivering standardised functionality is madness.

  • Garrick

    I use mootools but have not checked if it’s standards compliant.

  • Sorccu

    .. you do realise that none of your examples actually work, right?

  • Stuart

    Safari and IE8 already support these selectors – I’m curious though, do both of them already support them in an identical way that doesn’t require any changes at all in syntax, hacks or workarounds to get one script working in both browsers? Something that’s going to let me not to go mad by keeping every different type of browser open while I write the code and testing every line I write as I go in each separate browser?

    Because that’s what jQ does for me… if what you’re saying is that IE8 and Safari are now totally and harmonically compatible between each other as regards javascript interpretation, then I guess soon I won’t need to use it any more.

  • Harald

    Wow, the worst post about JavaScript I saw in a long time. I use MooTools, I love JavaScript code, but what you wrote here is blasphemy. Its not only bad code but bad advices. Read better books about DOM Scripting.

  • Anonymous

    The omission of mootools and prototype from the list of popular frameworks is… well, unfortunate. On the matter of standards compliance, I disagree. JavaScript exists to make browsers do what they couldn’t with HTML and CSS alone. It’s purpose is to broaden the browser’s capability. Sure, just like everything else, it can be abused. But the functionality isn’t by itself counter-productive to the aim of standards compliance.

  • Anonymous

    I use jQuery, and I’m glad that I do, I have no problems with any of the other JS Libraries out there, its just that personally I prefer jQuery.

    Should these libraries limit themselves to standards compliance? No. Should they embrace and extend standards? Certainly.

    I agree with Jon, how is this going too far? If you take a look back at the history of the internet its chock-full of people pushing the edge, going beyond the standards.

    JavaScript originally was only a Netscape thing, now its grown to something that all major browsers, and quite a few non-major browsers, support.

    10 yrs ago, Flash was virtually unheard of, look at it now.

    I say, let them add extra selectors, let them help to make our jobs easier. Each browser has its own set of extras, IE supports ‘‘, Mozilla ignores it, Mozilla has a few extra CSS goodies as well ‘-moz-box-sizing’ for instance, while IE ignores it.

    “Obviously, when browsers support the Selectors API (Safari and IE8 beta 1 already do!), their native implementations will run faster than anything a JavaScript library can do.”
    Will they support it fully? They still haven’t caught up with CSS2 and CSS3 is in the works. Will they run those selectors faster? Maybe, but they are becoming so bloated that I’m surprised if they run anything faster.

    Fully supporting standards is one thing, limiting yourself to them is another thing altogether.

  • http://www.solidhex.com solidhex

    @Sorccu

    Did you include the libraries he’s referring to and wrap the code into a function to run on page load?

    The only thing I would say is be careful when using for..in loops as they don’t work as you expect on arrays. I am sure Kevin knows this, but non-experts may not :)

  • Joan Molina

    Well, if a browser still does not support a CSS feature surely Javascript libraries should provide a way to support it. But once the browser supports it, a Javascript library should be rewritten so as to adapt the new feature into its code. Therefore, we, developers, need not worry about these things. Keep the code as it is.

    It’s a similar situation as forgetting about browser sniffing when coding. That annoying question is hardcoded into the Javascript library. No problem.

  • kangax

    Huh?

    1) I don’t understand the promotion of using for/in for array enumeration.
    2) Redeclaring variables in each iteration is quite redundant.
    3) href != null is redundant as well.
    4) “[href]” selector matches empty attributes, so there’s no need to test for length > 0
    4) rel != null && /(^| )external( |$)/.test(rel) could be replaced with /external/.test(rel) as “test” works just fine with any falsy values.

    I don’t mean to sound offensive, but giving such examples to novice javascripters doesn’t sound like a good idea.


    for (var anchors = document.getElementsByTagName('a'), i=0, l=anchors.length; i<l; i++) {
    if (typeof anchors[i].getAttribute('href') == 'string' && /external/.test(anchors[i].getAttribute('rel'))) {
    ...
    }
    }

    Cheers,
    kangax

  • http://www.igeek.info asp_funda

    Kevin, aren’t all Javascript libaries today used majorly for functionalities that browsers by default don’t provide? Isn’t depending on browsers the reason which kept Rich User Interfaces and interactive applications in Javascript away from users for 7-8 years before they were actually put in mass use? IE introduced it 10 years back & the other browsers didn’t implement it for the next 7-8 years, else imagine what the scene would’ve been of the web had these RUI’s came out 10 years ago!

    So I don’t understand what exactly Dojo’s Alex Russell mean to say! Did he mean that making a check in the javascript function to see if the browser by default supports selector query or not is impossible or too hard? Did he mean that its impossible to check if browser supports the functionality natively or not & then use browser’s call(if it supports) else use the library’s own engine! If he means that then I think that’s enough said & I will not consider Dojo at all if these kind of developers make that framework!

    I think what he skipped over is that the reason why people like prototype & jQuery etc. is that these are quite lightweight & by default come as no-frills libraries! The developer working on them can then add on top of them whatever frills (s)he wants but Dojo is one beast that’s quite slow & comes with all the bells & whistles by default that not everyone might want!!

  • Sorccu

    solidhex:

    I was just pointing out how things are. for .. in does not work the way it’s been used in the post. Clearly the author didn’t even bother testing anything. I find it most unfortunate that SitePoint’s once top-quality blogs have become like this.

  • http://www.sitepoint.com/ mattymcg

    Harald wrote:

    Wow, the worst post about JavaScript I saw in a long time. I use MooTools, I love JavaScript code, but what you wrote here is blasphemy. Its not only bad code but bad advices. Read better books about DOM Scripting.

    I have to laugh at this comment. Harald you do actually realise that Kevin WROTE one of the books on that list? :-D

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

    kangax,

    1) I don’t understand the promotion of using for/in for array enumeration.

    You’re absolutely right, and I’ve amended the code to use for loops instead.

    2) Redeclaring variables in each iteration is quite redundant.

    This causes no overhead, and keeps the code tidy.

    3) href != null is redundant as well.

    Not so. In Internet Explorer, an <a name="…"> tag’s href property is undefined, while all other browsers return an empty string. A typeof check is therefore inadequate.

    4) “[href]” selector matches empty attributes, so there’s no need to test for length > 0

    I don’t know what you mean here. The test for href.length > 0 doesn’t appear in the same example as the [href] selector.

    4) rel != null && /(^| )external( |$)/.test(rel) could be replaced with /external/.test(rel) as “test” works just fine with any falsy values.

    The rel attribute is a space-separated list of values. Thus the need for the more complicated regular expression.

  • anon

    @asp_funda: your info. about dojo is far outdated. While your comments may have been true for Dojo 0.4, more recent versions of Dojo are extremely competitive in size and performance with Prototype and jQuery, and outperform most toolkits it the selectors SlickSpeed tests. It seems a bit odd to complain about incorrect info. with incorrect info. The Dojo of today is fast… if you don’t believe me, check it out.

    What Alex was saying is that by only supporting valid selectors, it’s a lot easier to flip the switch from custom to native selector engines, without having to fork based on each selector, which helps keep code lean and concise. But complaining about Alex’s explanation for why Dojo chooses to do this, because of the way the author created this story is a bit unfair to Alex. He was simply explaining why Dojo took this route (to make it easier to support the coming native engines).

  • rimmer33

    First jQuery example is kinda lame :) Nobody in jQuery world would do so. We do $('our selector').each(function(){here goes our stuff for each element}) or even more simple if it is all about to delegate an event on each element.

    And about selectors: if JavaScript was emerged to browsers only for sake of doing what ony those particular browsers can do, there wouldn’t be so much hype about that. JavaScript extends browser capabilities, nothing less. Why should we care if IE supports CSS3 selectors API, if we use a selected cross-browser JS library. It was written to extend the possibilities, not to wrap them in yet another layer. So, I use what I use, take benefit of it’s powers and don’t care if it is standard in any part. It just works. It’s a job of library author to follow standards in his code, not mine, I follow standards only in my part. Separation that is. Good practice, I think.

  • http://www.solidhex.com solidhex

    @rimmer33

    In jQuery you don’t even need the each, could just do
    $('a[rel~=external]').click(function(e){
    open(this.href);
    e.preventDefault();
    });

    :)

  • raymond

    Hi,

    IMO the libraries take make the best of both worlds. For extended css selectors javascript will be used for standard css selectors the new api can be used.

    So either way it’s a win-win.

  • Anonymous

    if JS library authors want to support standards and then some, I have no problem with that. If this leaves them with some headaches about compatibility in the future, so be it, I thank them for taking on the hard work required to give us features that pathetic browser vendors will not until dead slow W3C jokers finish dragging their knuckles.

    There is one problem with the web at the moment and one problem only: the dysfunctional behaviour between browser vendors and standards writers (and the fact that most of the time they are one in the same).

    We need to get the EU to thump Microsoft a lot harder. Compatibility through turning on a true standards mode by default is great, but what about getting up to speed with standards support? Where is border-radius? Where is support?

  • pd

    if JS library authors want to support standards and then some, I have no problem with that. If this leaves them with some headaches about compatibility in the future, so be it, I thank them for taking on the hard work required to give us features that pathetic browser vendors will not until dead slow W3C jokers finish dragging their knuckles.

    There is one problem with the web at the moment and one problem only: the dysfunctional behaviour between browser vendors and standards writers (and the fact that most of the time they are one in the same).

    We need to get the EU to thump Microsoft a lot harder. Compatibility through turning on a true standards mode by default is great, but what about getting up to speed with standards support? Where is border-radius? Where is support?

  • 鱼排

    Can you tell how to highlight the code?

    You can find me here.