3 Quick Steps for a Painless Upgrade to jQuery 1.3

read 20 comments

Since the release of jQuery 1.3 a month and a half ago, I've been keeping my eye on any troubles that people have had with their upgrades. Fortunately, most people have had no problems at all. For those who have, the issues have almost always been in one of three areas. Identifying these areas and adjusting any legacy scripts ahead of time will go a long way toward ensuring a smooth transition to jQuery 1.3.x.

1. Update Attribute Selectors

By far the most common stumbling block to the 1.3 upgrade has been the attribute selector. The XPath syntax for this selector — [@attribute] — has been deprecated since version 1.1.4 in August, 2007. Still, many scripts, including some prominent plugins, continued to use the old syntax, which wasn't a problem until jQuery 1.3, at which point it was no longer supported. The correct syntax (since 1.1.4) follows the CSS standard: [attribute].

The fix is quite simple. Simply search your scripts for [@. Go through the matches one by one, and if the string is being used as an attribute selector (and not, for example, in a regular expression), replace it with [.

Removed XPath Syntax

Continue Reading Below

This will break your code in jQuery 1.3+:

  1. $('a[@href^=http]');
  2. $('[@title=foo]');

Current CSS Syntax

Use this instead:

  1. $('a[href^=http]');
  2. $('[title=foo]');

2. Check Custom Selectors

If you are using custom selectors, either in your own script or within a plugin, you might run across an error if the second argument's object value is a string:

  1. jQuery.extend(jQuery.expr[':'], {
  2.   hasSiblings: "jQuery(a).siblings(m[3]).length>0"
  3. });

This is another easy fix. Simply change that value to an anonymous function and add what was in the string to the return statement:

  1. jQuery.extend(jQuery.expr[':'], {
  2.   hasSiblings: function(a,i,m) {return jQuery(a).siblings(m[3]).length>0;}
  3. });

So, basically, you just change "jQuery(a).siblings(m[3]).length>0" to function(a,i,m) {return jQuery(a).siblings(m[3]).length>0;}.

When someone on the jQuery Google Group was having trouble with George Adamson's excellent More Selectors plugin, all I had to do to make it compatible with jQuery 1.3 was update the attribute selectors and change custom selectors (my updated script is available here temporarily until George has time to update the original).

3. Note Visible and Hidden Elements

This change didn't occur until jQuery 1.3.2, but if you are upgrading to the latest and greatest jQuery version, you'll want to be sure your scripts aren't relying on a quirk in how jQuery was determining the visibility of elements. Prior to 1.3.2, if you had an element with display:block inside a containing element with display: none, the inner element would still be reported as visible.

  1. <div id="outer1" style="display:none">
  2.   <div id="inner1">
  3.       you can't see me!
  4.   </div>
  5. </div>

Before version 1.3.2, $('#inner'1).is(':visible') would return true and $('#inner1:hidden') would match 0 elements. In order to find out if an element were truly hidden, meaning you couldn't see it, you'd have to check all of its ancestors to see if they were hidden as well. Remy Sharp put together a little custom selector to check if elements were *really* visible.

With 1.3.2, $('#inner').is(':visible) returns false and $('#inner:hidden') match 1 element.

Another Visible Wrinkle

There is one more change in how visibility is detected in 1.3.2: elements with visibility: hidden are now considered visible, whereas before they were considered hidden.

  1. <div id="outer2">
  2.   <div id="inner2" style="visibility: hidden">
  3.      you can't see me!
  4.   </div>
  5. </div>

Given the above div structure, jQuery 1.3.2 considers #inner2 visible while prior versions considered it hidden.

Here is a quick demo, with two iFrames showing the differences in determining visibility:

I'm not sure how I feel about the new behavior with visibility:hidden, but I think the change was important for performance reasons.

A Few Others

There are a few other issues that may affect a small minority of users, but the three above represent the lion's share of reported problems that I've seen on the Google Groups. For more information about changes, see the jQuery 1.3 Release Notes

comment feed


  1. Mahdi

    As Usual great job Karl

  2. The first step affects the validation plugin. If you're using it, upgrade to 1.5.1!

  3. SteveS

    'elements with visibility: hidden are now considered visible, whereas before they were considered hidden'

    Really?? Care to explain the thinking behind that one?

    I've been trying to figure out why my :visible selectors are broken in 1.3 for a while now, and ended up abandoning it altogether and using a specific class name.

    • Hi Steve,
      I tracked down John Resig's explanation on the jQuery Dev Google Group:

      Previously bugs would occur with methods like height/width, hide/show, and animate (which only operated on the display property) but the :visible and :hidden properties included the visibility property. It was important that these selectors actually match jQuery's internal definition of "visible".

    • Ken

      visibility:hidden elements are still "on the page" taking up space, even though they are transparent. If it is a link element, for example, and you hover it, an underline will appear, even though the link is visibility:hidden.

      So technically, some of their attributes are still "visible".

  4. Damn, I am pretty sure the ":visible" change broke the zebra striping functionality of the TableSorter plugin....

    Starting to poke through the code now but it's a large uphill climb

    • Chris

      I just tested a table sorter demo with 1.3.2 and zebra stripping is working. I'm using TS 2.0.3

  5. William Rouse

    I was upgrading a page that uses the Thick Box plug-in this weekend and it seems to be broken. The selected image would not come to the screen. Reverting back to an older jQuery fixed the problem.

  6. Great info, Karl. Thanks!

    Sadly, most of my pain will be updating incompatible plugins.

  7. steve

    I'm concerned about the visibility thing. Consider this case:

    <div class="pane">
    <div class="pane-header">
    <div class="closeable">
    <a href="#">[-]</a>
    <div class="pane-content">
    stuff here that can be slid up

    So, this describes a title bar with a close box. The code may not be perfect, cuz it's air code, but you get the idea. Then the jQuery (which also is air code and could be written more concisely):

    $(".pane-header > .closeable").click(function() {
    var pane = this.parents('.pane');
    var content = pane.find('.pane-content');

    if(content.is(':visible')) {
    pane.find('.closeable a').text('[-]');
    else {
    pane.find('.closeable a').text('[+]');

    The question is: When I slideUp the content, will content.is(':visible') then be false, as expected or is there some other result?

  8. Hello,

    please add you site at http://www.sweebs.com among other best sites available on the net!


  9. Adrian

    Thanks for posting this Karl, I have picked up alot from it, but still having a few problems with updating a great plugin by Karel Jan http://sandbox.tinctuur.be/tree/ just wondering if you could point me in the right direction with it?

    • Hi Adrian,
      It looks like that plugin is using jQuery UI as well. If you update jQuery to 1.3.x, you'll need to update to jQuery UI 1.7.x, too.

      If you're still having problems after you've updated everything, let me know. Or, post the question on the jquery-ui Google Group.

  10. Soon to be launched WordPress 2.8 will come bundled with jQuery 1.3.2. Up from 1.2.6.

    While updating my plugin, I hit a few errors. The first resource I turn to for solutions is this page.

    Thanks a lot Karl.

  11. Thanks for summarizing them here ...

9 Pings

  1. 3 Quick Steps for a Painless Upgrade to jQuery 1.3 - Learning jQuery...

    Thank you for submitting this cool story - Trackback from DotNetShoutout...

  2. [...] 3 Quick Steps for a Painless Upgrade to jQuery 1.3 [...]

  3. [...] 3 Quick Steps for a Painless Upgrade to jQuery 1.3 - Karl Swedberg looks at three simple things to do as a part of upgrading your code to use jQuery 1.3 [...]

  4. [...] 3 Quick Steps for a Painless Upgrade to jQuery 1.3 [...]

  5. [...] sito learningjQuery ha pubblicato un articolo dettagliato su come identificare e correggere queste irregolarità nel codice e passare senza [...]

  6. [...] 3 Quick Steps for a Painless Upgrade to jQuery 1.3: Karl Swedberg highlights the most prominent issues that people are experiencing when they upgrade to jQuery 1.3. [...]

  7. [...] 3 Quick Steps for a Painless Upgrade to jQuery 1.3, Learning jQuery Posted in Web RSS 2.0 | Trackback | Comment document.write(""); .eskin001 {width:100%; height:32px; table-layout:fixed;} .eskin001 .eskin_l{width:80px;background:url(http://image.bizshop.daum.net/ui/adclix_b/skin/eskin001_01.gif) no-repeat left top;} .eskin001 .eskin_c{width:100%;padding:2px 0 0 10px;background:url(http://image.bizshop.daum.net/ui/adclix_b/skin/eskin001_02.gif) repeat-x left top;} .eskin001 .eskin_r{width:6px;background:url(http://image.bizshop.daum.net/ui/adclix_b/skin/eskin001_03.gif) no-repeat right top;} .eskin001 a{color:#000;font:normal 13px Dotum,'돋움';} var adc_skin='eskin001'; var adv_random = Math.random() * 10000; var adv_width = '590'; var adv_height = '0'; var adv_key = '20080605092644' + adv_random; var adv_channelid = '137403'; var adv_ad_align_type = '1'; var adv_lo_border = 'cecece'; var adv_lo_background = 'ffffff'; var adv_lo_adtitle = '4f72b3'; var adv_lo_addesc = '666666'; var adv_lo_adurl = '2c81c4'; var adv_adno = '4'; var adv_bg_img = 'skin001'; var adv_ui_type = 'S'; getAdClixAD('20080605092644' + adv_random); [...]

  8. [...] site / blog Learning jQuery publicou um post “faça um upgrade dos seus scripts para jQuery 1.3 em 3 passos”, achei [...]

  9. [...] For more info about what changed with jQuery 1.3, check out this excellent article titled 3 quick steps for a painless upgrade to jQuery 1.3. [...]

Sorry, but comments for this entry are now closed.