Upgrading to jQuery 1.6: Problems you may face

I rarely (never?) blog. I’m not used to it. But I had to start somewhen. I think now is a good moment, cause upgrading to jQuery 1.6 pissed me off, as it’s not transparent as older upgrades were. I hope you’ll enjoy this post, Cheers!.

Ok, it’s a happy day, you surf the web and discover  jQuery 1.6 has been born. “New version, that’s cool, let’s upgrade!” you may say.  And you upgrade to the latest version as you usually do… but after some time, suddenly, you see your webpage begins to behave strangely (if not, you’re very lucky or it hasn’t happened yet)… what happened? The reason is that jQuery 1.6 has changed dramatically the behavior of some existing methods, breaking changes indeed…

Changes to .attr() method in 1.6. OMG!!

Maybe the most ‘polemic’ change that doesn’t allow to sleep to many developers (at least me), is the change made to the .attr() function. Now, it returns only html attributes and not dom properties. (If you want to get a dom property value as before, there’s a new method called .prop()). I think this change is crazy (good if jquery would have been born with this, but now, it’s crazy).

Consider the following markup:

<input type="checkbox" id="myCheckbox" checked="" value="1" />

Now consider doing

$('#myCheckbox').attr("checked")

You get the following results:

Code jQuery < 1.6 returns: jQuery 1.6 returns:
$('#myCheckbox').attr("checked")
true
""

Oh oh… Let’s go on and see something more ‘applied’:

if($('#myCheckbox').attr("checked")){
   alert("This executes in jQuery<= 1.5");
}else{
   alert("OMG. This executes in jQuery1.6!");
}

Oh my god. This is a HUGE problem in my opinion.  jQuery 1.6 broke our code.

Some of you may be thinking: I’d never leave an empty ‘checked’ attribute, or I’d not use .attr() to see if a checkbox is checked. Yes, but that’s not the point. The point is that this change isn’t fully backwards compatible. And, you may know your code well, but you don’t know how 3rd party plugins will behave.

Yes, the new .prop() method would do what we want, but this is a new function,  so our old code doesn’t use it.  Big problem

Changes to .data() method in 1.6

Now, the .data() function returns data attributes’ names (those prefixed with data-) with camelCase if you use hyphens, and lowercase if you don’t. Why? Because it’s a W3C recommendation. Why is it bad? Because it can break backwards compatibility.

Consider the following markup now:
<input type="text" id="myTextbox" data-firstName="John" data-last-name="Doe" />
And the following code:

$txt= $("#myTextbox");
console.log($txt.data());
console.log('.data("firstName")= ' + $txt.data("firstName"));
console.log('.data("firstname")= ' + $txt.data("firstname"));
console.log('.data("last-name")= ' + $txt.data("last-name"));
console.log('.data("lastName")= ' + $txt.data("lastName"));

These are the results

jQuery < 1.6 returns: jQuery 1.6 returns:
.data()= { last-name="Doe", firstname="John"}
.data("firstName")= John 
.data("firstname")= John
.data("last-name")= Doe
.data("lastName")= undefined
.data()= { lastName="Doe", firstname="John"}
.data("firstName")= undefined 
.data("firstname")= John
.data("last-name")= Doe
.data("lastName")= Doe

Legend

text Equal between jQuery versions
text Different depending on jQuery version

(Note that only the third and fourth lines return the same results in both cases)

So, if you had the following snippets to say “Hi John”, “Bye Doe” in your old-happy jquery 1.5 code:

alert("Hi, " + $txt.data("firstName"));  //Outputs "Hi John" in jQuery < 1.6
alert("Bye, " + $txt.data()['last-name']);  //Outputs "Bye Doe" in jQuery < 1.6

in jQuery 1.6 it would show undefined in both cases. Not good at all.

Possible solutions

Well, those are the problems. Now, there are some solutions. But unfortunately, none of them is easy.

Solution 1: The obvious, and hardest one:

– Change all the code you have, looking for this .attr() and .data(), and change them (when necessary) to be compatible with jQuery 1.6 (doh!, awful solution!).

– In the case of 3rd party plugins, if they are minified apply this changes to unminified versions, and then re-minify them with some minifier (YUI Compressor, packer, uglify or the one you prefer).

Solution 2: Extend jQuery to have both old and new behaviors

– Write a jQuery plugin, let’s say .oldAttr(). This method would have to behave exactly as the old .attr(). This is not so hard if you check jquery 1.5’s source code (I can do it if there are requests). The same should be done for .data, writing an .oldData() plugin.

– Replace all .attr() and .data() calls with the new .oldAttr() and .oldData() plugins.

– For 3rd party plugins, you should replace in unminified versions and then minify again as explained in the previous solution.

– Then, for your new code, use jQuery 1.6, attr(), prop() and data() as the documentation describes.

Solution 3: Wait and Pray (and pressure!) so jQuery folks regret. (I really hope it)

– Wait until the jQuery Team realizes these changes are EVIL (specially the .attr() case), and correct these changes to be backwards-compatible in the next jQuery version (1.6.1). So, we wouldn’t have to make any changes to our code. I hope it!


Well, that’s it. Do you agree? Have any comments? Do you think there are other solutions? Any comment is welcome.

Advertisements

About edgarinvillegas

I'm not talking about me... yet
This entry was posted in jQuery and tagged , , . Bookmark the permalink.

3 Responses to Upgrading to jQuery 1.6: Problems you may face

  1. Lea Hayes says:

    I have found that the following occurs (not sure if this is what you already describe).

    <input id=”test” type=”text” data-first-name=”Bob” />

    $(‘#test’).data(‘first-name’) === ‘Bob’; // true
    $(‘#test’).data(‘firstName’) === ‘Bob’; // true

    So the process of defining both variations causes an overwrite (via jQuery).

    But when defining camel-case variation in HTML jQuery responds with ‘undefined’:

    <input id=”test” type=”text” data-firstName=”Bob” />

    $(‘#test’).data(‘firstName’) === undefined; // true
    $(‘#test’).data(‘first-name’) === undefined; // true

    Yet the following works:

    <input id=”test” type=”text” data-first-Name=”Bob” />

    $(‘#test’).data(‘firstName’) === ‘Bob’; // true
    $(‘#test’).data(‘first-name’) === ‘Bob’; // true

    I wonder if camel-case inconsistency is a bug with jQuery?

    • edgarinvillegas says:

      Hi Lea, yes, that behaviour is exactly what my article tries to explain. Before jQuery 1.6, it mattered if you used lowercase or uppercase letters in your html data attribute names. Starting with jQuery 1.6, data attribute names are first “lowercased” (so case doesn’t matter anymore) and then “camelized” where there are hyphens. It’s because jquery now wants to follow a HTML5 W3C recommendation, which states the following:

      “All attributes on HTML elements in HTML documents get ASCII-lowercased automatically”

      (source: http://www.w3.org/TR/html5/elements.html#embedding-custom-non-visible-data-with-the-data-attributes)

      So, summarizing: Jquery>=1.6 ignores case and camelizes only after hypens.

  2. thanks for the research!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s