jQuery 1.1a

Posted on by

As previously announced, today we’re bringing you the alpha release of jQuery 1.1. We’d really appreciate it if you could help us test this alpha, so that we can have a stand-up release this weekend – just in time for jQuery’s 1 Year Anniversary! (January 14th)

This is going to be a fantastic release. In fact, this release is so good that we’re going to be taking this entire week to tell you about what’s new and how you can best use it. The Evangelism team has a bunch of stuff lined up to get you introduced and ready to use this great new version of jQuery.

Here’s the quick-and-dirty on jQuery 1.1:

  • Its selectors are 10-20x faster than those in jQuery 1.0.4.
  • The documentation has been completely revamped.
  • The complexity of the API has dropped by 47%.
  • It has a ton of bug fixes.
  • It has a bunch of great new features.
  • … and it’s still the small 19KB that you’ve come to expect.

We’re going to have the full run down during the next couple days, but for right now, it’s shaping up to be a great release.

Download

API Changes

NOTE: We will release a backwards compatibility plugin together with the full release of jQuery 1.1, when it is released this weekend.

It’s important to note that there’s been a lot of API changes. Some in the form of additions, some in the form of reorganization. If you’d like to help us test this alpha release, please keep these changes in mind:

:nth-child() now starts at 1, instead of 0. Our implementation of the CSS 3 selector started its numbering at 0, instead of 1. This is a bug fix, but one that may effect your code.

// 1.0.x: Get the first column from a table
$("td:nth-child(0)")

// 1.1: Get the first column from a table
$("td:nth-child(1)")

The following methods have been renamed/reorganized in this version, here is how you can continue to use them, as you would expect:

Old Way (1.0.x) New Way (1.1)
.ancestors() .parents()
.width() .css(“width”)
.height() .css(“height”)
.top() .css(“top”)
.left() .css(“left”)
.position() .css(“position”)
.float() .css(“float”)
.overflow() .css(“overflow”)
.color() .css(“color”)
.background() .css(“background”)
.id() .attr(“id”)
.title() .attr(“title”)
.name() .attr(“name”)
.href() .attr(“href”)
.src() .attr(“src”)
.rel() .attr(“rel”)
.oneblur(fn) .one(“blur”,fn)
.onefocus(fn) .one(“focus”,fn)
.oneload(fn) .one(“load”,fn)
.oneresize(fn) .one(“resize”,fn)
.onescroll(fn) .one(“scroll”,fn)
.oneunload(fn) .one(“unload”,fn)
.oneclick(fn) .one(“click”,fn)
.onedblclick(fn) .one(“dblclick”,fn)
.onemousedown(fn) .one(“mousedown”,fn)
.onemouseup(fn) .one(“mouseup”,fn)
.onemousemove(fn) .one(“mousemove”,fn)
.onemouseover(fn) .one(“mouseover”,fn)
.onemouseout(fn) .one(“mouseout”,fn)
.onechange(fn) .one(“change”,fn)
.onereset(fn) .one(“reset”,fn)
.oneselect(fn) .one(“select”,fn)
.onesubmit(fn) .one(“submit”,fn)
.onekeydown(fn) .one(“keydown”,fn)
.onekeypress(fn) .one(“keypress”,fn)
.onekeyup(fn) .one(“keyup”,fn)
.oneerror(fn) .one(“error”,fn)
.unblur(fn) .unbind(“blur”,fn)
.unfocus(fn) .unbind(“focus”,fn)
.unload(fn) .unbind(“load”,fn)
.unresize(fn) .unbind(“resize”,fn)
.unscroll(fn) .unbind(“scroll”,fn)
.ununload(fn) .unbind(“unload”,fn)
.unclick(fn) .unbind(“click”,fn)
.undblclick(fn) .unbind(“dblclick”,fn)
.unmousedown(fn) .unbind(“mousedown”,fn)
.unmouseup(fn) .unbind(“mouseup”,fn)
.unmousemove(fn) .unbind(“mousemove”,fn)
.unmouseover(fn) .unbind(“mouseover”,fn)
.unmouseout(fn) .unbind(“mouseout”,fn)
.unchange(fn) .unbind(“change”,fn)
.unreset(fn) .unbind(“reset”,fn)
.unselect(fn) .unbind(“select”,fn)
.unsubmit(fn) .unbind(“submit”,fn)
.unkeydown(fn) .unbind(“keydown”,fn)
.unkeypress(fn) .unbind(“keypress”,fn)
.unkeyup(fn) .unbind(“keyup”,fn)
.unerror(fn) .unbind(“error”,fn)

I realize that’s a long list – but you’d be surprised how much of that no one was using. By removing all of those methods we’ve been able to reduce the size of the jQuery API by 47%. We’re going to have more information about the API changes in particular, but for now, this list should help you to sort out any major differences in your code.

If you have any questions, feel free to post them here in the comments and we’ll get them answered right away.

The Path to 1.1

Posted on by

Just a quick update so that everyone knows what’s going on: The jQuery Dev Team is currently working on the upcoming 1.1 release of jQuery. So SVN is going to be changing rather significantly during the next couple weeks. Here’s the current game plan:

  • jQuery 1.1a January 7th – A quick alpha release to help everyone test their code and get it moved over to the upcoming 1.1 release.
  • jQuery 1.1 January 14th – This will be the official release, to coincide with jQuery’s 1 year anniversary.

It’s important to note that jQuery 1.1 will not be backwards compatible with 1.0. The changes will occur in different ways, but so far, this is what is planned to change:

  • Methods like .oneclick() and .unclick() will be going away in favor of .one(“click”) (new) and .unbind(“click”). We found that these methods weren’t used enough to warrant the 70+ API entries that they required.
  • Selectors :nth-child(), :gt(), :lt(), and :eq() will all be starting count at 1 instead of 0, in line with the CSS specification. (This is a bug fix, but causes an incidental API change)
  • Some CSS helper methods are going away, like: .color() and .background(). You should start moving over to using .css(“color”) and .css(“background”) instead.
  • Some attribute helper methods like .title() and .rel() are going away. You should start using .attr(“title”) and .attr(“rel”) instead.

A lot of this is being done to help reduce the magnitude of methods that are included in the jQuery API. Having 70+ less entries will significantly reduce the size of the documentation, along with making it easier to maintain and read.

If you’re interested in the direction that the jQuery code base is heading in, please feel free to subscribe to the jQuery Dev Mailing List where the jQuery Dev Team discusses all of these issues in depth.

Update: I forgot to mention that there will be a compatibility plugin that’ll help you transition over to jQuery 1.1. This way, you can continue to use .oneclick() (and all the other methods) into the foreseeable future (even though it may not be in the jQuery core).

Meet The People Behind jQuery

Posted on by

I would like to take this opportunity to introduce everyone to the people behind jQuery. Not enough has been said about who works for the project and what they do to help out. This fact, combined with a recent re-organization, makes for the perfect time to show you how jQuery works, behind the scenes.

jQuery is an incredible undertaking, with 11 people directly donating their time to furthering jQuery (and countless others contributing plugins, bug fixes, and knowledge). It is important that attention be drawn to the work of all those who help with the project, considering that their work is incalculably valuable.

Expect to see many advancements being made to the jQuery project in the upcoming month (leading up to Jan. 14th – jQuery’s one year “birthday”).

This is a great time to get involved in the jQuery project. Find a team that interests, hop on their mailing list – and get involved. Help is always appreciated. If you don’t have any time to give to the project, financial contributions are always appreciated (and help to maintain the server and level of quality that you expect in the project).

So, without any more hassle, I present to you: The People Behind jQuery.

Development Team

The development team maintains the core aspect of jQuery: The very code itself; pushing the project forward since its inception. It’s been slowly growing, in recent months, keeping up with the demand for features and bug fixes.

The purpose of the development team is just that: To improve the quality of the jQuery code base (by adding in new features) and to fix existing problems (creating a more stable library for everyone to use). Additionally, the team is in charge of documenting all of the jQuery API, building a stable test suite and maintaining the jQuery build system (through which all jQuery code, documentation, and tests are constructed).

John Resig (Massachusetts, United States)

John is a programmer and author living in Boston, Massachusetts. He’s in charge of managing the direction of the jQuery library. This involves taking a critical look at existing (and expected) features and making informed decisions about them. He’s also in charge of managing development resources and time spent on the different aspects of the project.

Jörn Zaefferer (Bergneustadt, Germany)

Jörn is a programmer living in Germany. He’s a driving force of the jQuery development process, contributing numerous bug fixes and pushing out many of the 1.0.x releases. He’s also responsible for completely re-building the jQuery test suite and writing a majority of the test cases. He has been the driving force behind the jQuery development process these past few months, helping to bring jQuery closer to an excellent 1.1 release.

Brandon Aaron (Texas, United States)

Brandon is a developer living in Texas, and a new addition to the development team. Having contributed numerous bug fixes for the 1.0.x releases, he’s now taking a critical look at the Animation and CSS/DOM aspects of the jQuery core. He’s looking to provide significant increases in code speed and clarity. This will give us the ability to do things like pause/resume animations.

Paul Bakaus (Mainz, Germany)

Paul is a programmer living in Germany, and a sponsored contributor to jQuery. His work with jQuery has been focused on transforming jQuery into a high-speed library capable of handling difficult large-scale drag-and-drop operations. He was largely responsible for creating the recent dimensions plugin and for suggesting numerous improvements to the CSS methods of jQuery. All of his work is tied back to the Interface Plugin and attempting to create a high-speed drag-and-drop solution.

Stefan Petre (Romania)

Stefan is a developer living in Romania and the creator of the Interface Plugin. His work with the plugin has been led by the desire to create fast, interactive, web-based applications. Interface has been adopted as an officially-sponsored jQuery plugin (along with a few other high-quality plugins). Paul and Stefan are currently working together to improve the overall quality of the Interface plugin (both in speed and quality of code).

Mike Alsup (New York, United States)

Mike is a developer living in New York and is responsible for maintaining the official form plugin for jQuery. He has worked quite extensively to unify and test the Ajax-form-submission process into a single plugin. Additionally, much of his work has trickled back into improving the quality, and consistency, of the core jQuery Ajax code.

Evangelism Team

This is a brand new jQuery team. The focus of this group is to watch the pulse of the jQuery community (both at home and at large) and help in any way that they can. Frequently, this means building new tutorials, explaining difficult problems, or communicating to the other teams what needs to be updated or changed.

This group can be thought of as a sort of developer relations – communicating the desires of the jQuery users back to the dev/web/design teams, while at the same time, going out of their way to bring jQuery to users who haven’t found it yet.

Rey Bango (Florida, United States)

Rey Bango is a consultant living in South Florida, specializing in the development of Rich Internet Applications. He’s been working with jQuery for a while now, and evangelizing its benefits to a large number of people. He’s already helped to convert a number of prominent Cold Fusion developers. He was also responsible for starting and helping to run the jQuery Button Contest.

Karl Swedberg (Michigan, United States)

Karl is a developer living in Michigan who maintains the web site Learning jQuery. He writes numerous tutorials and helps people to better understand how jQuery works. He is a frequent of the jQuery mailing list, helping new users get adjusted to using the library. As a member of the evangelist team he will be continuing his work, finding people who need help understanding the finer points of the library and giving them the resources that they need to get up to speed.

Web Team

The web team is fully responsible for creating the new jQuery web site. This is a team that’s been in the planning for a long time, but is finally starting to come to light. Much of this has been due to the fact that it’s such a daunting project.

In short, many new features are going to be rolled out in the upcoming weeks. The whole process is going to take some time, but the results will be very rewarding. The first features that you can expect are a proper discussion area (hooked in to the existing mailing list) and a proper repository for all the plugins that exist.

All of this will be built using the Drupal CMS. Recently, we helped Drupal convert over to using jQuery as their primary JavaScript library (powering all Drupal-based sites in the upcoming 5.0 release). In working with the Drupal development team, they’ve been most gracious in offering help in any way that they can, with the new site. In addition to this offer of support, the Drupal engine is fantastically powerful, providing nearly every feature that we need to power the new site.

In addition to the Drupal development team, the following Drupal users have offered to donate their time and effort to help build the new jQuery site.

Mike Hostetler (Colorado, United States)

Mike is a developer living in Colorado. He has significant experience setting up Drupal-based sites. What’s of particular interest is that he already setup a Drupal community and plugin area for another Open Source project: QCodo. He’s already begun work, setting up the base area in which the web team is going to work – and working to integrate the SVN plugin repository directly into the web-based plugin repository (for unified access to all who want it). His work will serve as the base for the rest of the web team’s development efforts.

Tane Piper (Edinburgh, UK)

Tane is a developer living in the UK. He has extensive experience with both PHP and Drupal. Tane recently setup the website getjQuery.org (using Drupal) – at which time I saw the opportunity to bring him in, helping to add many of his desired features to the official jQuery site (like the discussion area and plugin repository, to name a few).

Design Team

The design team is another recent addition to the jQuery development process. The goal of the team is to implement the complete redesign of the jQuery web site, along with all of its upcoming sub-sections (this is working in conjunction with the web team, implementing the design for their work).

There are many individual aspects to this team (such as icon design, branding, graphic design, and XHTML/CSS composition) that will be tied together through the different web projects.

Bradley Sepos (Ohio, United States)

Bradley is an independent designer living in Ohio. He has already started some fine work, creating some excellent mock ups of the new jQuery.com design. He is going to be working on finishing up a solid design for the main jQuery landing page. He will also be in charge of devising a solid branding and design guideline for the rest of the site (and the jQuery project as a whole).

Skye Giordano (Missouri, United States)

Skye is a professor, teaching web design, living in Missouri. He has already been collaborating with Bradley on the design of the new site. In the upcoming weeks he will be focusing on a particular section of the site to completely design from the ground, up. (Such as the discussion area, or the plugin area – this has yet to be decided.)

Helping you understand jQuery

Posted on by

Some recent articles have discussed the need for having “really good” tutorials for JavaScript libraries.

As always, we’re working to make the jQuery documentation better and more useful, so I want to pose the following question: What are some tutorials that would help you better use or learn jQuery? Make sure it’s something simple (like “Building a drop-down menu.”) and not something really complex (like “Building a complete shopping cart system”). Feel free to post your suggestions here in the comments, it’ll help to give us a good idea of what people want and what needs better explaining.

We’ve recently started working on the reorganization of the jQuery documentation wiki. Right now it’s quite messy and all over the place. As you can see from the new wiki’s structure, however, is that we’re going for a much more thorough representation of jQuery itself. Within each of these topics we want to include a number of useful “common case” tutorials that will help you to better understand the functions in the jQuery API.

So please: (Taking into account what you see of the new wiki’s structure) What would help you better learn, and use, jQuery?

jQuery 1.0.4

Posted on by

Another fantastic release of jQuery is ready for your consumption. This release includes a number of bug fixes (as usual) along with some much-needed improvements to jQuery’s Ajax functionality.

As always, if you have any questions or concerns with new release, please feel free to discuss it on the jQuery Mailing List. If you think you’ve spotted a bug, please add it to the bug tracker.

So, without further ado, here’s jQuery 1.0.4:

Download

Changes and Features

  • Tons of bug fixes (Full List)
  • Extensions to $.ajax(): $.ajax accepts additional options: beforeSend, async and processData; returns XMLHttpRequest to allow manual aborting of requests, see docs for details.

    Example: Add extra headers to an Ajax request using beforeSend

    $.ajax({
      type: "POST",
      url: "/files/add/",
      beforeSend: function(xhr) {
        xhr.setRequestHeader( "Content-type", "text/plain" );
      },
      data: "This is the contents of my text file."
    });

    Example: Perform a synchronous Ajax request.

    // Get the HTML of a web page and save it 
    // to a variable (the browser will freeze until the 
    // entire request is completed).
    var html = $.ajax({
      type: "GET",
      url: "test.html",
      async: false
    }).responseText;
    
    // Add the HTML into the page
    $("#list").html( html );

    Example: Sending a JavaScript object using processData.

    // The data to send to the server
    var params = {
      name: "John",
      city: "Boston"
    };
    
    // Send the data, but have it be converted into
    // a format the server can understand (w/ processData)
    $.ajax({
      type: "POST",
      url: "/user/add/",
      data: params,
      processData: true
    });

    Example: Aborting an Ajax request after a specific delay in time.

    // Perform a simple Ajax request
    var req = $.ajax({
      type: "GET",
      url: "/user/list/",
      success: function(data) {
        // Do something with the data...
        // Then remove the request.
        req = null;
      }
    });
    
    // Wait for 5 seconds
    setTimeout(function(){
      // If the request is still running, abort it.
      if ( req ) req.abort();
    }, 5000);

  • AJAX module: The public $.ajax API is now used internally (for $.get/$.post etc.); loading scripts works now much more reliably in all browsers (with the exception of Safari, which is a work in progress).
  • New global Ajax handler: ajaxSend – called before an Ajax request is sent.

    Example: Add extra headers to all Ajax requests using the ajaxSend event.

    $(document).ajaxSend(function(xhr){
      xhr.setRequestHeader("X-Web-Request", "MySite.com");
    });

  • Extensions to global Ajax handlers: ajaxSend, ajaxSuccess, ajaxError and ajaxComplete get XMLHttpRequest and settings passed as arguments.

    Example: Prevent any POST requests that are sending too much data.

    $(document).ajaxSend(function(xhr,options){
      if ( options.type == "POST" && options.data.length > 1024 )
        xhr.abort();
    });

    Example: Show a special message for requests submitted using an Ajax POST.

    $("#dataSent").ajaxSend(function(xhr,options){
      if ( options.type == "POST" )
        $(this).show();
    });

  • Extensions to event handling: pageX and pageY are available in all browsers now. (IE does not provide native pageX/Y).

    Example: Have a tooltip follow a user’s mouse around the page.

    $(document).mousemove(function(e){
      $("#mousetip").css({
        top: e.pageY + "px",
        left: e.pageX + "px"
      });
    });

  • Improved docs: $(String) method has now two separate descriptions, one for selecting elements, one for creating html on-the-fly.
  • FX module: Most inline styles added by animations are now removed when the animation is complete, eg. height style when animating height (exception: display styles).

Expandable Sidebar Menu Screencast

Posted on by

This is the first (of hopefully many) screencasts that will provide a quick tutorial to a simple demo of jQuery in action. I plan on doing at least 2-3 more based upon the talks that I’ve given lately – hopefully I can trickle those out over the next week(s) or so. (Oh, and sorry if I sound tired – that’s because I am.) Enjoy!



jQuery Demo – Expandable Sidebar Menu on Vimeo

Or: Watch the original (.mov, 3.85MB) video. (I suspect that this version is much clearer – but not everyone supports Quicktime files)

File Downloads:

jQuery Button Contest Winners

Posted on by

The votes are in! Here are the winners of the jQuery Button Contest:

The Winners

  1. First Place Prize (93 votes): Two Books – Ajax Design Patterns and John Resig’s upcoming Pro JavaScript Techniques
    Ned Collyer, Australia:

    HTML: (Copy this into your web site to use this button)

  2. Second Place Prize (83 votes): One Book – Foundations of Ajax
    Cyril Demars, France:

    HTML: (Copy this into your web site to use this button)

  3. Third Place Prize (75 votes): $10 Cash to a PayPal account of your choosing!
    Altstack, Japan:

    HTML: (Copy this into your web site to use this button)

I’m quite pleased with the results, there’s a good mix of sizes and styles – a little something for everyone. If each of the winners could contact me, we’ll arrange for your prizes right away.

Remember: Even if your favorite entry didn’t win, that doesn’t mean that you can’t use it to promote jQuery.

On another note: The redesign (and reorganization) of the jQuery web site is in full swing. There are a couple professional web designers who are graciously donating their time to make the new site come alive. Expect to see some more updates on this front very soon.

I’d like to, again, thank everyone for participating – this has been a fantastic contest. I’m immensely pleased, and I hope you are too!

Vote for the jQuery Button

Posted on by

Voting is now closed! Thanks, everyone, for your input! The results can be found here: jQuery Button Contest Winners.


The next round of the jQuery Button Contest is upon us! After some careful deliberation, the judges have narrowed the playing field of 123 jQuery button submissions down to just 30. We were completely overwhelmed with both the quality and quantity of submission and would like to personally thank everyone who participated. There were a ton of excellent entries but ultimately the following 30 buttons were chosen due to their clarity, composition, and originality.

Now it’s your turn to help! In order to narrow the results down to the final three, winning, buttons we need you to vote for which buttons that you like. You’re allowed to vote for as many buttons as you’d like, but only once.

Vote for your favorite buttons:

Your votes are tracked and only counted once – but feel free to vote for as many buttons as you wish.

The polls will be closed Monday 11:59pm (EST, GMT -0500). So get your voting in now – and make your decision count!

jQuery 1.0.3

Posted on by

Another bug-fix release is ready for all to enjoy! It is highly recommended that you upgrade right away. As always, if you spot a bug, please add it to the bug tracker.

As with the last release, jQuery 1.0.3 is featuring only bug fixes – leaving all API additions/changes/deletions until the next full release: jQuery 1.1.

Once again, Jörn Zaefferer did an incredible job really keeping on top of the bugs, fixing the vast majority of them. Much of this release was made possible by him.

Download Now:

This release includes a new package: A complete zip file of everything associated with this release. This includes three versions of jQuery (Regular, Lite, and Packed), the test suite, and all the documentation. Now you don’t have to build it yourself just to have your own copy.

Tickets Closed:

The full set of bugs, or enhancements, that were closed with this release:

Note: Even though about 60 bugs are shown below, many of them were messed with by spammers – so I’m not entirely sure which ones were fixed this release and which ones are just zombie bugs that got re-closed. I’m fairly positive that while there were a lot of bug fixes this release, there weren’t 60 of them.

  1. hover cross browser issue
  2. hoverClass
  3. slideUp/Down buggy in Opera 9.01
  4. jQuery?s toggle(); gets mixed up with moo.fx?s toggle();
  5. FX flash bug in animations
  6. .css() returns incorrect values
  7. Normalize event object
  8. Opacity should go to 1.0
  9. appending thead to table
  10. Problem with ‘e’ being passed to JQuery.css()
  11. [PATCH] IE Opacity issues resolved
  12. bug in show when used inside callback
  13. [jQuery] hover function does not invoke mouseout callback
  14. children() may return nothing
  15. [PATCH] $().hover error in firefox
  16. Context is being modified
  17. .text() includes comments
  18. Animation Queueing is Broken?
  19. IE weirdness on semi-opaque anti-aliased text, a small fix
  20. $([[‘a’, ‘b’]]).length
  21. $().trigger broken since rev. 127
  22. JS ‘warnings’ generated in firefox
  23. Leak for Mozilla/Firefox browsers (using addEventListener)
  24. Safari crash in test suite
  25. remove() & remove(expr) not work
  26. [PATCH] innerWidth and innerHeight fails in IE with no borders
  27. $.load requires a callback
  28. o.getAttribute is not a function (line 634)
  29. Unavailable response header breaks Firefox 1.0
  30. Problems with show and hide
  31. Nested in display:none gives width()/height()=0
  32. this.set is not a function
  33. ifModified arg to $.ajax()
  34. ready does not work over https with msie – fix
  35. Params to $.get() are appended wrong to querystring
  36. ajax summary / todo list
  37. $(‘node1/node2’) gives error when node1 is empty
  38. The float property for IE
  39. Opacity doesn’t work in IE
  40. $.postJSON
  41. cloneNode() issues
  42. “name.replace is not a function” in 1.0.2
  43. it is impossible to implicitly abandon search context (without .end())
  44. load() of html is not shown properly after hide/show
  45. Seperate private and public $.extend
  46. $.load should automatically be JQuerified
  47. ajaxStart and ajaxStop are having issues
  48. .add( jQuery )
  49. Double assignment when setting iframe src attribute
  50. XML not properly parsed by Interface Autocompleter
  51. Some variables are not initialized properly in jQuery.ajax in 1.0.2
  52. $.ajax: Evaluate JS for “html” dataType like load()
  53. $(‘something’).load(‘test.html’).show(“slow”) won’t work
  54. Mod of API Docs for jQuery “val”
  55. jQuery 1.0.2 appears to break the Interface Elements Autocompleter plugin
  56. Hyphens in CSS, IE6
  57. Assert that animate does not alter the hash param
  58. .animate() overflow not reset

Zebra Table Showdown

Posted on by

As a follow-up to the previous event selector showdown comes a new Zebra Table Showdown.

The Challenge:

Making all tables on a page have striped (“Zebra”) backgrounds (different coloring on every odd row).

The Rules:

  • The odd/even styling should be done by adding a class for the ‘odd’ numbered table rows.
  • This must be able to work on multiple tables. (It’s not as simple as finding all rows then going through every odd one, otherwise an even row could become highlighted in the next table).
  • The code should be done as elegantly as possible, using as much of a libraries’ functionality as possible. Speed is not an issue.

Intended Result:
zebra-fig1.gif

Plain DOM Scripting: (demo)

var tables = document.getElementsByTagName("table");
for ( var t = 0; t < tables.length; t++ ) {
  var rows = tables[t].getElementsByTagName("tr");
  for ( var i = 1; i < rows.length; i += 2 )
    if ( !/(^|\s)odd(\s|$)/.test( rows[i].className ) )
      rows[i].className += " odd";
}

Note: This includes a check to make sure that the 'odd' class doesn't already exist on the table row. This is taken care of by all modern libraries.

Yahoo UI: (demo)

var tables = document.getElementsByTagName("table");
for ( var t = 0; t < tables.length; t++ ) {
  var rows = tables[t].getElementsByTagName("tr");
  for ( var i = 1; i < rows.length; i += 2 )
    YAHOO.util.Dom.addClass( rows[i], "odd" );
}

Note: Although, their own developer site disagrees.

Dojo: (demo)

var each = dojo.lang.forEach;

each(document.getElementsByTagName("table"), function(table){
  each(table.getElementsByTagName("tr"), function(row,i){
    if ( i % 2 == 1 )
      dojo.html.addClass( row, "odd" );
  });
});

Note: A common function was assigned to a variable in order to make the code shorter.

Prototype (1.4.0): (demo)

$A(document.getElementsByTagName("table")).each(function(table){
  $A(table.getElementsByTagName("tr")).each(function(row,i){
    if ( i % 2 == 1 )
      Element.addClassName( row, "odd" );
  });
});

Mochikit: (demo)

var byTag = getElementsByTagAndClassName;

forEach( byTag("table"), function(table) {
  var rows = byTag( "tr", null, table );
  for ( var i = 1; i < rows.length; i += 2 )
    addElementClass( rows[i], "odd" );
});

Note: A common function was assigned to a variable in order to make the code shorter.

Prototype (1.5.0): (demo)

$$("table").each(function(table){
  Selector.findChildElements(table, ["tr"])
    .findAll(function(row,i){ return i % 2 == 1; })
    .invoke("addClassName", "odd");
});

mootools: (demo)

$$("table").each(function(table){
  $ES("tr", table).each(function(row,i){
    if ( i % 2 == 1 )
      row.addClass( "odd" );
  });
});

jQuery: (demo)

$("tr:nth-child(odd)").addClass("odd");

If you feel as if you have a more elegant solution than the ones posted here, please post them below so that the listing can be updated.


New Submissions:

These are new entries that have been submitted by other readers.

AJS: (demo)

AJS.map(AJS.$bytc("table"), function(table) {
 AJS.map(AJS.$bytc("tr", null, table), function(row, i) {
   if ( i % 2 == 1 && !/(^|\s)odd(\s|$)/.test( row.className ) )
     AJS.setClass( row, "odd" );
 });

Prototype 1.5.1: (demo)

$$('tr:nth-child(odd)').invoke('addClassName', 'odd');