jQuery 1.1.4: Faster, More Tests, Ready for 1.2

Posted on by

We’re pleased to announce the latest release of jQuery: jQuery 1.1.4. Barring any horrible mistakes, this release will be the last of the 1.1.x branch – leading us up to the release of jQuery 1.2 in September.

You can download the release from the jQuery Google Code page:

Download:

Improvements

A number of improvements have gone into this release, in addition to all of the normal bug fixes.

Any Name jQuery

jQuery has taken a big step to become the first major JavaScript library completely capable of renaming itself. Previously, functionality was provided to rename the oft-used ‘$’ shortcut for ‘jQuery’ – but now you can also rename both ‘$’ and ‘jQuery’. This allows for two fantastic results:

  • You can now include multiple versions of jQuery, simultaneously, on the same page.
  • You can now embed jQuery into the namespaces of other objects and libraries, for example:
    // With the Dojo Toolkit
    dojo.jquery = jQuery.noConflict(true);
    dojo.jquery("#elem div").slideDown("slow");
    // or with Yahoo UI
    YAHOO.query = jQuery.noConflict(true);
    YAHOO.query("span.hidden").removeClass("hidden");

Speed Improvements

What would a release be without some speed improvements? We took the opportunity to step beyond any previously-released speed test suites and improve the speed of the three most commonly used portions of jQuery: ID selectors, tag name selectors, and each() loops. It’s absolutely critical that each of these items are made as fast as possible, as they have the possibility of being re-used endlessly, and repeatedly.

Here’s the test suite used to analyze the speed of the three changes.

$(“#id”) Improvements

Browser jQuery 1.1.3 jQuery 1.1.4 % Improvement
IE 6 651ms 70ms 830%
Firefox 2 1355ms 27ms 4919%
Safari 3 101ms 14ms 620%
Opera 9 270ms 62ms 335%
Average improvement: 1676%

$(“elem”) Improvements

Browser jQuery 1.1.3 jQuery 1.1.4 % Improvement
IE 6 661ms 451ms 47%
Firefox 2 1717ms 143ms 1100%
Safari 3 99ms 83ms 19%
Opera 9 226ms 198ms 14%
Average improvement: 295%

.each() Improvements

Browser jQuery 1.1.3 jQuery 1.1.4 % Improvement
IE 6 200ms 30ms 567%
Firefox 2 468ms 29ms 1514%
Safari 3 17ms 11ms 54%
Opera 9 45ms 25ms 80%
Average improvement: 554%

Test Suite Overhaul

This is very big news – and should be especially so to most developers out there. The jQuery test suite has been completely re-tooled and improved from the ground up for stability. A brand new swath of Animation and Ajax tests have been integrated bringing jQuery’s total test count to over 800 tests!

Additionally, the test suite completely passes with no errors in all the major browsers that we support: Firefox 2, Safari 3, Internet Explorer 6, and Opera 9 (Safari 2 and IE 7 not shown for brevity). Proof:

In the future, we’re working to improve our coverage of the Event, Attribute, and CSS portions of jQuery – undoubtedly bringing us to over 1000 tests very soon.

Additionally, it should be noted that the jQuery test suite is now embedded in the Mozilla test suite – running against every commit of the upcoming Firefox 3 release. You can feel safe knowing that in the newest release of Firefox, everything will just keep working, as you would expect it to.

Bug Fixes

53 tickets have been closed for this release. You can read the full details on the the bug tracker (this includes fixes that went in to jQuery 1.1.3.1).

A bunch of large issues were resolved, including issues related to HTML script evaluation, Safari CSS Computed Style access, and Ajax settings manipulation.

New Functionality

A couple pieces of new functionality have been introduced. The first two of which, .slice() and :has(), are going to be a part of jQuery 1.2, but their existence is obligated by some deprecated functionality (see below). The new changes to extend() and noConflict() were put in order to be able to fix some long standing bugs in jQuery.

.slice()

You may recognize this method name from the .slice() method that exists on JavaScript arrays – you’re in luck because it behaves identically. This is a great method for chopping apart jQuery objects and getting to the elements inside of them. All of the following are valid ways to use the slice() method:

$("div").slice(0,1); // First div
$("div").slice(-1); // Last div
$("div").slice(1,-1); // All divs but the first and last
$("div").slice(1,3); // The second and third div
$("div").slice(7,8); // The eighth div

:has()

This new selector is a replacement for the current way of checking for elements inside of another element (div[p]). You can now use this selector just as you would that particular XPath selector, like so:

// All divs with a paragraph inside
$("div:has(p)")
// All anchors with an image inside
$("a:has(img)") 
// All divs that have an anchor inside that have an image inside
$("div:has(a:has(img))")

Deep, recursive .extend()

This has been a frequently-requested addition to the jQuery .extend() method. This change allows you to deeply merge nested objects (as opposed to having them overwrite each other). This is best demonstrated through an example:

// Normal .extend()
jQuery.extend(
  { name: "John", location: { city: "Boston" } },
  { last: "Resig", location: { state: "MA" } }
);
// Result:
// => { name: "John", last: "Resig", location: { state: "MA" } }
// New Deep .extend()
jQuery.extend( true,
  { name: "John", location: { city: "Boston" } },
  { last: "Resig", location: { state: "MA" } }
);
// Result:
// => { name: "John", last: "Resig",
//      location: { city: "Boston", state: "MA" } }

.noConflict(true)

As described previously, this addition to .noConflict() allows you to completely rename both the ‘jQuery’ namespace and the ‘$’ shortcut, while also rolling back any changes those introductions may have done. You can use this new shortcut like so:

// Give jQuery a custom name:
var jq = jQuery.noConflict(true);
jq("#id div").hide();

// Both Fail - $ and jQuery have been renamed:
$("#id div").hide();
jQuery("#id div").hide();

This trick can also be used to push jQuery into an existing namespace, like so:

// Put jQuery in a namespace:
var obj = {};
obj.jq = jQuery.noConflict(true);
obj.jq("#id div").hide();

Deprecated Functionality

We are deprecating a number of methods in jQuery 1.1.4 in preparation for the API changes in the upcoming jQuery 1.2. Wherever possible, we’ve provided alternate methods for performing actions.

With jQuery 1.2, as with the jQuery 1.1 release, a backwards compatibility plugin will be provided. Thus, if you wish to continue using these particular techniques, you’ll be able to use that plugin and continue doing so.

Additionally, in order to handle the XPath changes another, separate, plugin will be released that will handle XPath selector functionality in jQuery. This plugin will be made available along with the jQuery 1.2 release.

Selectors

$("div//p") XPath Descendant Selector
Please use the CSS $("div p") selector instead. Or, when jQuery 1.2 is released, use the new XPath Plugin.

$("div/p") XPath Child Selector
Please use the CSS $("div > p") selector instead. Or, when jQuery 1.2 is released, use the new XPath Plugin.

$("p/../div") XPath Parent Selector
Please use the $("p").parent("div") selector instead. Or, when jQuery 1.2 is released, use the new XPath Plugin.

$("div[p]") XPath Contains Predicate Selector
Please use the new $("div:has(p)") selector instead. Or, when jQuery 1.2 is released, use the new XPath Plugin.

$("a[@href]") XPath Attribute Selector
Note: While this selector is being deprecated in this release, it will not be removed in jQuery 1.2. Come jQuery 1.2, it’ll be recommended that you use the CSS selector $("a[href]") instead. Or, when jQuery 1.2 is released, use the new XPath Plugin.

DOM Manipulation

$("div").clone(false)
Calling the clone method with an argument is being deprecated (the clone method, as a whole, is being kept). Instead of calling .clone(false) you should now do: .clone().empty() instead.

DOM Traversal

$("div").eq(0)
This method is being deprecated for the use of the new .slice() method (which works identically to an array’s slice method. You can duplicate .eq() like so:

$("div").slice(0,1);

Additionally, .eq(0) can be duplicated in the following ways:

$("div:eq(0)")
$("div:first")

$("div").lt(2)
This method is being deprecated for the use of the new .slice() method (which works identically to an array’s slice method. You can duplicate .lt() like so:

$("div").slice(0,2);

Additionally, .lt(2) can be duplicated in the following way:

$("div:lt(2)")

$("div").gt(2)
This method is being deprecated for the use of the new .slice() method (which works identically to an array’s slice method. You can duplicate .gt() like so:

$("div").slice(3);

Additionally, .gt(2) can be duplicated in the following way:

$("div:gt(2)")

Ajax

$("#elem").loadIfModified("some.php")
This convenience method is being removed in favor of the long form use of $.ajax():

$.ajax({
  url: "some.php",
  ifModified: true,
  success: function(html){
    $("#elem").html(html);
  }
});

$.getIfModified("some.php")
This convenience method is being removed in favor of the long form use of $.ajax():

$.ajax({
  url: "some.php",
  ifModified: true
});

$.ajaxTimeout(3000)
This convenience method is being removed in favor of the long form use of the more-explicit $.ajaxSetup():

$.ajaxSetup({timeout: 3000});

$(...).evalScripts()
This method is no longer necessary in jQuery – all scripts included in HTML strings are automatically evaluated when injected into the document. No substitute method is needed.


As always, please let us know if you encounter any bugs in between jQuery 1.1.3.1 and jQuery 1.1.4. Thanks!

71 thoughts on “jQuery 1.1.4: Faster, More Tests, Ready for 1.2

  1. Sharon Rosner on said:

    There’s a mistake in the deprecations section:

    $.ajaxSettings({timeout: 3000});

    should be:

    $.ajaxSetup({timeout: 3000});

  2. Anders on said:

    Wonderful! Great! Looking forward to the upcoming 1.2 release!

    By the way, the link to the jQuery test suite doesn’t work.

    /Anders

  3. I can not find slide() method in jQuery 1.1.4 . I see the code, download the svn trunk branch, but any slide() method is found.
    ???

    jQuery 1.1.4 works with all my current projects based in 1.1.2 and more fast, perfect!! :-D

  4. Is this a typo: $(“a[href]”) ? The documentation says that css attribute selectors should have @. I tried without it $(input[type=’text’]) and it didn’t work.

  5. @Shanon: Good catch, I’ll fix that in the post.

    @Danny: That’s correct. a[href] is the correct CSS syntax for selecting anchors with an attribute of href. You’ll also note that this change isn’t being made until jQuery 1.2 AND that you’ll still be able to use the @, if you’d like. There’s no need to worry about it now.

    @Everyone: Yes, we also test in Safari 2 and IE 7, they just weren’t mentioned for brevity.

  6. Wade Harrell on said:

    // Put jQuery in a namespace:
    var obj = {};
    obj.jq = jQuery.noConflict(true);
    obj.jq(“#id div”).hide();

    looks very interesting but will this play nicely with plugins? com.jQ would work very nice with the namespaces I use in my apps. I am just concerned that plugins may act up if not assigned beforehand. Guess I will find out soon enough ;)

  7. That’s funny, just tried the tests in Firefox 2.0.0.6, and 10 tests failed.

    selector module: id (2, 5, 7)
    # Died on test #6: TypeError: a[i] has no properties
    # Expected 24 assertions, but 6 were run

    selector module: class (6, 10, 16)
    # Class selector using UTF8 (.台北Táiběi) expected: [ span#utf8class1 ] result: [ ]
    # Class selector using UTF8 (.台北) expected: [ span#utf8class1, span#utf8class2 ] result: [ ]
    # Class selector using UTF8 (.台北Táiběi.台北) expected: [ span#utf8class1 ] result: [ ]
    # Class selector using UTF8 (.台北Táiběi, .台北) expected: [ span#utf8class1, span#utf8class2 ] result: [ ]
    # Descendant class selector using UTF8 (div .台北Táiběi) expected: [ span#utf8class1 ] result: [ ]
    # Child class selector using UTF8 (form > .台北Táiběi) expected: [ span#utf8class1 ] result: [ ]

    selector module: attributes (2, 9, 11)
    # Died on test #10: TypeError: a[i] has no properties
    # Expected 20 assertions, but 10 were run

    It seems like I get these errors in every browser I test it in.

    … That said, I moved one of my projects over to the new version, and things are working flawlessly. So, bravo, but a slightly hesitant bravo.

  8. Fantastic selector speedup, good to see features being condensed and deprecated. Very excited about slice()! I am interested to see some speed tests on that function.

    Unfortunately I get the same results as Aaron when I run the test suite in FF 2.0.0.6.

    I will let y’all know how the upgrade goes!

  9. Well done again for the speed increases.

    There are some truly amazing projects and each getting optimized more and more.

    For example the HAML interpretor has recently increased it’s rendering engine and looking to get faster than erb.

  10. So people who are currently using $(‘div[p]’) should now use $(‘div:has(p)’), but people who are using $(‘div[@p]’) should now use $(‘div[p]’)?!

    If they don’t change the $(‘div[p]’), this will change the functionality to the old @ functionality instead of the has: functionality, right?

    Also, just as an aside, I was using jQuery in a Chickenfoot script, and while 1.1.3.1 works, 1.4 doesn’t (it can’t even find $ or jQuery).

  11. I ran the test suite and had 10 failures.

    Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6

    Tests completed in 53041 milliseconds.
    10 tests of 790 failed.

    Here are the details: (the items with – in front of them failed.)

    62. selector module: id (2, 5, 7)
    1. ID Selector (#body)
    2. ID Selector w/ Element (body#body)
    3. ID Selector w/ Element (ul#first)
    4. ID selector with existing ID descendant (#firstp #simon1)
    5. ID selector with non-existant descendant (#firstp #foobar)
    – 6. Died on test #6: TypeError: a[i] has no properties
    – 7. Expected 24 assertions, but 6 were run

    63. selector module: class (6, 10, 16)
    1. Class Selector (.blog)
    2. Class Selector (.blog.link)
    3. Class Selector w/ Element (a.blog)
    4. Parent Class Selector (p .blog)
    – 5. Class selector using UTF8 (.台北TáibeÌŒi) expected: [ span#utf8class1 ] result: [ ]
    – 6. Class selector using UTF8 (.台北) expected: [ span#utf8class1, span#utf8class2 ] result: [ ]
    – 7. Class selector using UTF8 (.台北TáibeÌŒi.台北) expected: [ span#utf8class1 ] result: [ ]
    – 8. Class selector using UTF8 (.台北TáibeÌŒi, .台北) expected: [ span#utf8class1, span#utf8class2 ] result: [ ]
    – 9. Descendant class selector using UTF8 (div .台北TáibeÌŒi) expected: [ span#utf8class1 ] result: [ ]
    – 10. Child class selector using UTF8 (form > .台北TáibeÌŒi) expected: [ span#utf8class1 ] result: [ ]
    11. Escaped Class (.foo\:bar)
    12. Escaped Class (.test\.foo\[5\]bar)
    13. Descendant scaped Class (div .foo\:bar)
    14. Descendant scaped Class (div .test\.foo\[5\]bar)
    15. Child escaped Class (form > .foo\:bar)
    16. Child escaped Class (form > .test\.foo\[5\]bar)

    66. selector module: attributes (2, 9, 11)
    1. Attribute Exists (a[@title])
    2. Attribute Exists (*[@title])
    3. Attribute Exists ([@title])
    4. Attribute Equals (a[@rel=’bookmark’])
    5. Attribute Equals (a[@rel=”bookmark”])
    6. Attribute Equals (a[@rel=bookmark])
    7. Multiple Attribute Equals (input[@type=’hidden’],input[@type=’radio’])
    8. Multiple Attribute Equals (input[@type=”hidden”],input[@type=’radio’])
    9. Multiple Attribute Equals (input[@type=hidden],input[@type=radio])
    – 10. Died on test #10: TypeError: a[i] has no properties
    – 11. Expected 20 assertions, but 10 were run

  12. AjaxDev0008 on said:

    $(…).evalScripts() Still seems to be required for IE when using something like:
    $.ajax({
    type: “POST”,
    dataType: “html”,
    url: “testAjax.jsp”,
    data: “name=John&location=Boston”,
    success: function(msg){
    $(“div.changeThis”).append(msg);

    }
    });
    Am I missing something?

  13. @Aaron and Charles: I’ve fixed the suite – it wasn’t checked out properly. Go here instead: http://jquery.com/test/

    @Adam: No one should make the switch away from [@foo] -> [foo], because it simply won’t be possible until jQuery 1.2 (because of the obvious API incompatibility). And even so, in 1.2, [@foo] will only be deprecated – it’ll still work (too many plugins and code bases rely on having it still work that way).

    Also, in relation to the Chickfoot item, it might be because we now do window.jQuery now instead of ‘var jQuery’ – hmm, I wonder how we might work around that.

  14. @John:

    Passed with flying colors! I love the attitude around here… “When a problem comes along, you must whip it.”

  15. AjaxDev0008 on said:

    @John Resig: Tested without using evalScripts in IE 6 and 7. Used a simple alert in the file that was called by $.ajax.
    I am afraid the alert was not called when the msg was appended.

    Anyone else test this yet?

    Works in Firefox though.

  16. @AjaxDev0008: We have tests for this in our suite – and it is passing in IE 6. Do you have a demo page that I can see? Maybe I can spot the problem.

  17. @Wade

    I’m not sure how it’s been implemented as I haven’t looked into the code yet, but my guess would be that plugins will play nice as long as they are defined before .noConflict is called. After that they’re probably out of luck.

  18. @John Resig: you are, of course, the man.


    include('http://jqueryjs.googlecode.com/files/jquery-1.1.4.pack.js');
    $ = window.jQuery;
    output($);

    works.

    Is window.jQuery (effectively) mutually exclusive with var jQuery? I mean, are you doing that so we can do the “Any Name jQuery”?

  19. @Adam: Correct, that is part of the “any name” stuff. I’m not sure how ChickenFoot works, in particular – but this may just be a caveat that’ll need to be taken into consideration, in order to use it.

  20. AjaxDev0008 on said:

    @John Resig: I don’t have a demo page available but here is the code that I am using:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
    <title> test </title>

    <script type="text/javascript" src="javascripts/jquery.js"></script>
    <script type="text/javascript">

    function clickMe(){
    $.ajax({
    type: "POST",
    url: "ajaxTest.htm",
    dataType: "html",
    success: function(msg){
    $(‘div#test’).append(msg);
    }
    });
    }

    </script>
    </head>
    <body>
    <div>
    <input type="button" value="Click Me" onclick="clickMe();"/>
    </div>
    <div id="test">Some Text</div>
    </body>
    </html>

    And here is the content of ajaxTest.htm:

    <div>
    Some more text
    <script type="text/javascript">
    alert(‘Hello’);
    </script>
    </div>

  21. Hi,

    I have some problems with $.ajax. My code worked very well with the 1.1.3.1 but does not work anymore with 1.1.4.1.

    Here is the code (all variables are defined previously and work correctly with the previous version in IE7).

    $.ajax({
    url: sUrl,
    data: sParams, // detected parameters
    type: sMethod,
    dataType: ‘html’,
    timeout: 30000,
    error: function(object,message){
    $(sMessageId).html(“Erreur de chargement! “+message+””);
    },
    success: function(html){
    $(sTarget).html(html); // detected target
    $(“#message”).html(“”);
    },
    beforeSend: function(){
    $(sMessageId).html(“”);
    }
    });

    The beforeSend event is triggered but the error, or succes events aren’t. Thit I miss something?

    ;)

    Paul

  22. Glad to see creative updates into jquery, and plugin pages updates very nicely every few days, will be good jump to 1.2, woo!,

    thank much to the very active community! and resource, well organized , good documents and examples.

    cheers to all,
    Nilesh P.

  23. I want to get all the recent speed increases but since 1.1.3 came along my photoviewer is doing weird things because of something that changed in jquery relating to animations, I believe. 1.1.4 has the same problems.

    a) Firefox: I have a row of 6 thumbnails but when the containing viewer is closed now (toggle(‘slow’)), the row breaks after the 5th thumbnail and the last thumbnail drops onto a new second line just before the viewer closes. Somehow it appears to be increasing margins or something when display is toggled so the row no longer fits.

    b) In IE7 it doesn’t do that but instead closes in a slow, odd, step-like manner: click close, pause, then the opacity effect on the background disappears so background goes black, another pause, then closes.

    Ideas on how to overcome these issues?

    Thanks.

  24. @qui est regex: You do realize that we don’t add functionality in minor releases, right? we only add new stuff in major releases? The methods that we added this time we necessary in order to transition people away from the deprecated methods – there’s no such case with regexp selectors.

  25. Ralph Whitbeck on said:

    Holy Snikeys!

    The speed improvements to the ID selector alone is just awe inspiring.

    Great work John and team!

  26. Hey this may be a bit off-topic, but I just watched your entire presentation of Javascript Libraries of about a week ago, John. It’s pretty impressive and I learned a lot from it, about Javascript but also about jQuery. Awesome release by the way.

  27. MikeChristensen on said:

    John,

    I was reading your jQuery 1.2 Roadmap and noticed that you mentioned the possibility of including livequery into jquery if you saw a more widescale adoption of its use. Well, I’m here to testify that it is a main file included on every page of the enterprise-level site we’re building.

    I was starting to get sick of writing initialize $.fn’s and livequery saved the day. After using the selector to bind an event to what is matched, there are many instances in which we Ajax in new content that needs the same event applied after DOM has loaded. Without livequery, we have to reassign events to the Ajaxed content. Of course my only concern is the eventual need for garbage collection on event triggers never used during the page view, but I’m sure some genius will come up with a plan for that.

    If adding livequery to jQuery means I save a couple of bytes of overhead for file inclusion and overall filesize, I say “do it!”

  28. MikeChristensen on said:

    By the way. I can’t thank you enough for jQuery. It has opened the doors for many possibilities and lent me the ability to create feature-rich applications I couldn’t have done with simply reading DOM javascript books.

    Thanks again.

  29. Denis Ignatenko on said:

    @MikeChristensen
    >>Well , I’m here to testify that it is a main file included on every page of the enterprise-level site we’re building.
    If you need some plugins with core lib, so why not to build jQuery and livequery together in a single file? As for me I see no reason for merging.

  30. frankysanders on said:

    I too seem to be having issues with IE 6.0 and evalScripts.

    I had to write a little hack.

    $(“#” + id + “”).html(result);
    if(getBrowser == “msie”){
    $(“#” + id + “”).evalScripts();
    }

    I’ve tested this as follows:
    1) create an ajax chunk

    function test(){
    alert(1);
    }
    test();

    Try to load this via the .ajax method and the alert will not be executed in IE 6. I am not currently able to test this in IE 7 but I suspect similar behavior.

  31. frankysanders on said:

    I’ve moved some code around and all seems to be good now. I am not sure what fixed it but this bug no longer is affecting my application.

  32. AjaxDev0008 on said:

    @frankysanders
    Can you post the changes you made to your code to make the .Ajax bug go away?

  33. Ariel Flesler on said:

    @MikeChristensen:
    The re-binding problem you mention, can be easily avoided using event delegation, jquerylive is a great plugin but you can just bind functions to the containers, that don’t get refreshed with ajax calls and that will work just fine.
    I posted a small plugin for event delegation, it’s called Intercept. It’s pretty simple right now, maybe it helps you out.