planet.jquery.com

RSS Feed
$('.blog[tag=jquery]').read();

Just Added: Training at SF jQuery Conference!

Posted May 04, 2012 by Leah Silber

In response to the flood of requests and emails, and our original promise to work on this, we’ve got an announcement: we’ve added a single day Beginner/Intermediate training right before the San Francisco jQuery Conference :)

Tickets are on sale now  (left side, below the fold). The training will be provided by our friends at Bocoup , and hosted by the ever-generous folks at Microsoft . Here’s a snippet of what Trainers Ben Alman and Rebecca Murphey will be covering:

At Bocoup’s intermediate one-day jQuery training, you’ll work with jQuery veterans to build a foundation that will make you a stronger developer and get you prepared for all the great talks that you’ll see over the next two days. You’ll even learn the basics of creating your own jQuery plugin. Topics that will be covered include:

  • The jQuery() function
  • Selecting & Traversing
  • Manipulating the DOM
  • Making stuff happen with Events
  • AJAX
  • Enhancing with Effects
  • Extending jQuery with Plugins
  • jQuery UI
  • jQuery Mobile

To note: the training and conference are both in San Francisco, but take place in different  locations. The training is in the heart of San Fran on Market Street, and the conference is about five to ten minutes from there, on the UCSF Mission Bay campus. Please also note that the conference and training require separate  admission tickets, so make sure you’ve purchased both if you’d like to attend both.

We’re still working on the possibility of adding an Advanced training, but thus far have had mostly requests for beginner materials. So here that is :)

Hope you’ve all bought your tickets to the conference; can’t wait to see you there!

Getting Touchy About Patents

Posted April 10, 2012 by sgonzalez

Touch events have become a hot topic for web developers as more and more companies move into the mobile space. Most of us know that touch events support single and multi-touch tracking. Some of us know the trickiness of working with touch and mouse at the same time. Fewer know that there are multiple touch event models, and even fewer have tried to support multiple models at the same time. I’d like to talk about where we are today, how we got here, and the potential problems we may face in the future.

A Brief History

Back in 2007, Apple introduced the iPhone, and with it came touch events. Neil Roberts sums up the Apple implementation well in a SitePen article : “Though at first the APIs seem a little sketchy, once you’ve learned them you should be able to do amazing things in your application.” Sure enough, we’ve seen plenty of amazing things, without too much complaint of the “sketchy” API. This model was later implemented by Android, Nokia, RIM, Opera, and others. Apple’s implementation is still only available in their private fork of WebKit; it wasn’t until the end of 2009 that touch events first appeared in the main WebKit repo , coming from the Android implementation.

Also in 2009, the W3C started discussing a unified pointer model for DOM Level 3 Events. The idea was that touch (including multi-touch), pen/stylus, and mouse events would be coalesced into a single model, making it easy to support all pointer types at once. However, this was abandoned because the goal at the time was to keep the spec as small as possible in order to become a recommendation faster.

Another two years later (March 2011), Mozilla released Firefox 4, featuring their own flavor of touch events . The Mozilla model is much closer to the mouse event model and the abandoned W3C model in that the event objects are flat; properties such as `event.pageX` exist and there is no touch list. If you want to track multiple touches, you can do so via the event’s `streamId`. Mozilla later deprecated this implementation in favor of an emerging W3C spec based on Apple’s model.

In January 2011, the W3C started drafting a Touch Events spec based on the WebKit implementation . A few months later, it became a Working Draft , and in December it became a Candidate Recommendation . The next month, a Patent Advisory Group (PAG) was formed in order to investigate patents disclosed by Apple . Apple’s absence from the Touch Events Working Group (WG) and their patent disclosure has caused the W3C to stop work on the spec and they do not plan to continue until the PAG has concluded and/or makes a recommendation to the WG. As of this writing, the PAG has not made a decision about the impact of the patents, but the group’s goal is to reach a speedy conclusion.

Meanwhile, Microsoft took a different approach to touch and has implemented their own pointer events in IE10 with the MSPointerEvent object . The MSPointerEvent object is similar to the original Mozilla implementation, in that the event objects are flat and contain a `pointerId` property. However, there are some important differences between MSPointer and all of the other models, which are touch-specific.

Note: The above is just a brief history of touch events on the Web; if you’re interested in the history of touch interfaces, you might want to check out Bill Buxton’s Multi-Touch Systems that I Have Known and Loved .

Pointer Events vs. Touch Events

As mentioned above, generic pointer events such as the original W3C idea or MSPointer, have the benefit of supporting multiple pointer devices. In fact, with a Samsung tablet running Windows 8, mouse, pen, and fingers are all normalized to MSPointer; you can even use the `pointerType` property to determine which type of pointer is being used. In addition to supporting all current pointer devices, MSPointer is designed in such a way that future devices can easily be added, and existing code will automatically support the new device. Even better, MSPointer event objects have the same structure as other events, reducing the learning curve compared to the conglomerate of TouchEvent, TouchList, and Touch.

Another big difference between MSPointer and Touch is that MSPointer has support for hovering (over and out events). While most touch devices have a hardware limitation that doesn’t allow for hovering, Sony recently announced the Xperia sola with “magical floating touch technology.” This brings up an important issue: Touch Events were designed based on a specific device for a specific type of input. Pointer Events represent a completely different approach to input on the Web. While we’ve already covered how this impacts developers, it’s interesting to consider the impact on hardware manufacturers. In order for Apple to succeed with touch interfaces, they had to create a new event model. Innovation for new form factors and new input methods will either be stifled by the existing standards or will require a new set of APIs, following in Apple’s footsteps with the iPhone and Touch Events. Pointer Events provides a clean solution not only for developers, but for hardware manufacturers as well. It’s conceivable that in a few years developers could use Pointer Events as the only event model for pointers, leaving Mouse Events as a thing of the past.

A Splintered Future

Although the W3C is still planning to move forward with the Touch Events spec (pending a recommendation from the PAG), the future is unclear. Even if the PAG determines that Apple’s patents don’t apply and the spec becomes a W3C Recommendation, it’s not clear that Microsoft would implement such a model given the need for a multi-input event system in Windows. If the W3C were to change directions and start a Pointer Events spec, it’s not clear that Apple, or more broadly WebKit, would implement the new event model. It’s entirely possible that even with a W3C Recommendation, we’ll be stuck for years without a consistent event model across browsers and devices.

Regardless of which model the W3C chooses to pursue, jQuery is dedicated to filling in the gaps, just like we do for other events such as submit and change. We think the pointer event model is easier to use and more future-proof, and we hope that it can be standardized, even if Touch Events are standardized as well. However, we are only interested in normalizing to a W3C Recommendation, and will not provide custom pointer events if there is no official W3C specification. We’re working with the W3C and Microsoft to try to find the best way forward for our users and the Open Web.

Call to Action: Microsoft to Submit Pointer Event Proposal

We would like to publicly call upon Microsoft to submit a proposal to the W3C for Pointer Events. The Touch Events Working Group, and by extension various browser vendors, have stated interest in pointer events. The most effective way to proceed would be for Microsoft to officially submit a proposal to the W3C.

Call to Action: Community to Experiment with Both Event Models

We would also encourage the community to experiment with Touch and MSPointer. Play with the APIs, build apps, and provide feedback. If you’re interested in this, but don’t have the necessary hardware, consider pairing up with one or more local developers who do. While there are a lot of developers building on top of Touch, there are very few people building on top of MSPointer, and even fewer publicly comparing them. We encourage you to send your feedback directly to the W3C public-webevents mailing list , but feel free to leave feedback here and we will pass it along.

Call to Action: Submit Prior Art

If you know of any prior art for multi-touch/touch lists, even outside of the Web, please get in touch with the W3C . This includes programming models and APIs, especially those using events. This will help the Patent Advisory Group come to a conclusion sooner. Again, if you’d rather leave comments here, we will pass them along.

Bowling for jQuery – April 2012, Washington, D.C.

Posted March 26, 2012 by Richard D. Worth

The jQuery team is going bowling and we’d love to have you join us! We’ll be spending the evening of Friday, April 13th at King Pinz  in Leesburg, VA, a bit outside of Washington, DC. We’ll have a private room with 6 lanes from 6 to 10 PM. The night will feature unlimited bowling, dinner, desserts, drinks, and billiards. There’s even a cigar bar, if you’re into that!

King Pinz

Very limited space – get your ticket fast.

Bowling

  • Private room with 6 lanes
  • Unlimited bowling (shoe rental included) for 4 hours
  • Cozy couches with cocktail tables
  • King Pinz: Photos
  • Private Room: 360 degree tour

Dinner

  • Appetizers, entrees, and desserts
  • All night

Drinks

  • Open bar
  • All night

Billiards

  • Private billiards table and lounge area

Cigar Bar

Prizes

  • 1 winner gets a copy of Adobe Creative Suite Master Collection 5.5 (a $2,600 value)

    Adobe Creative Suite Master Collection 5.5

    Thanks Adobe.
  • There will be other prizes as well. Cool prizes. Must be present to win.

Who will be there?

  • Dave Methvin
  • Yehuda Katz
  • Leah Silber
  • Rick Waldron
  • Karl Swedberg
  • Adam J. Sontag
  • Scott González
  • Dan Heberden
  • Richard D. Worth
  • Corey Frang
  • Kris Borchers
  • You?

Sponsors

Please join us in thanking our thouroughly awesome sponsors for this event:

 

CustomInk Design T-shirts Online

 

Bocoup - Open Web Technology by and for programmers

 

Adobe

 

Fluidhire - Innovative Technology and New Media Recruiting

 

MoDevUX

 

We know you love jQuery and we love you for showing it.

jQuery 1.7.2 Released

Posted March 21, 2012 by dmethvin

jQuery 1.7.2 is looking good! The release candidate went smoothly so we’ve made only one small change and are releasing it to your eager hands today. You can get the oven-fresh code from the jQuery CDN now, with Google and Microsoft CDNs soon to follow:

Note: If you’re using jQuery Mobile, please use jQuery 1.7.2 only with jQuery Mobile 1.1. For previous versions of jQuery Mobile, stay with jQuery core 1.7.1 or earlier.

You can use the bug tracker to report bugs; be sure to create a test case on jsFiddle so we can figure it out easily. If you’re not sure it’s a bug, ask on our forum or on StackOverflow . Please don’t use the blog comments below to report bugs.

As always, this release wouldn’t have been possible without the hard work of many people. First, the jQuery Core Team: gnarf, jaubourg, mikesherov, rwldrn, and timmywil. The support of the jQuery UI, Mobile, and Infrastructure teams was greatly appreciated as well, especially danheberden’s valiant struggle against Trac.

Community members like adebree, caii, cmc3cn, KYSergey, mathiasbynens, miskith, MrMamen, Orkel, pasky, SineSwiper, tavelli, and vlazar pitched in by reporting, verifying, and fixing bugs. Special jQuery Gold Leaf Cluster thanks to gibson042 and sindresorhus for their work in making 1.7.2 a great release. Don’t let these people have all the fun! If you’d like to contribute to the web’s most popular Javascript library, hop onto #jquery-dev on IRC or the Developing jQuery Core section on our forum and say hello!

Many thanks to Louis-Rémi Babé, who submitted a patch to fix a regression with negative margin animations a mere 30 minutes before the release!

jQuery 1.7.2 Change Log

Here’s the change log of the 1.7.2 release.

Ajax

  • #4624 : Charset in default ajaxSettings.contentType
  • #10978 : jQuery.param() should allow non-native constructed objects as property values
  • #11264 : evalScript() uses defaults set by ajaxSetup()
  • #11426 : jQuery.ajax() always fails when requesting JPG images in IE

Attributes

  • #5571 : Allow chaining when passing undefined to any setter in jQuery
  • #10828 : attr(“coords”) returns undefined in IE7
  • #10870 : Incorrect behaviour of $.removeAttr(“selected”)
  • #11316 : Consider looking through valHooks by element type first, then by nodeName instead of the other way around

Build

  • #10692 : Configure the jshint options to more accurately match the style guide
  • #10693 : generalize the “test something in an iframe” code in unit tests
  • #10901 : have unit tests fail if the tester is running from file:// or doesn’t have PHP
  • #10902 : ability to test a built version of jQuery in unit tests
  • #10931 : Unit tests shouldn’t require internet access

Core

  • #10466 : jQuery.param() mistakes wrapped primitives for deep objects

Css

  • #10639 : outerWidth(true) and css(‘margin’) returning % instead of px in Webkit
  • #10754 : have jQuery.swap return the return of the callback instead of just executing it
  • #10782 : Incorrect calculating width
  • #10796 : Bug in IE7 with $(‘#el’).css.(‘background-position’)
  • #10858 : css.js regular expressions are incomplete
  • #11119 : The curCSS function only need 2 arguments

Data

  • #11309 : hexadecimal-formatted data-* attributes parsed incorrectly

Deferred

  • #11306 : calling .disable() or .lock() on a $.Callbacks object breaks its fired() status

Dimensions

  • #3838 : $(document).height() incorrect in IE6

Effects

  • #8498 : Animate Hooks
  • #10006 : method show is not working as expected in all browsers when called for document fragment
  • #10848 : Animation toggling loses state tracking in certain atomic edge cases
  • #11415 : Silently ignore negative CSS values where they are illegal
  • #11469 : Negative margin in animations (.animate)

Event

  • #8165 : .live(‘click’, handler) fires on disabled buttons with child elements in Chrome
  • #10819 : Eliminate “this.on.call(this, “
  • #10878 : $(“select”).live(“change”, function(){ …broken in IE8 in jQuery 1.7
  • #10961 : Error in XRegExp using jQuery 1.7.1 in IE6-9
  • #10970 : The .on() selector parameter doesn’t work with :not(:first) selector
  • #10984 : Cannot off() custom events ($.event.special)
  • #11021 : Hover hack mangles a namespace named “hover”
  • #11076 : .clone(true) loses delegation filters
  • #11130 : jQuery.fn.on: binding map with null selector ignores data
  • #11145 : $(document).on() not working with name=”disabled”

Manipulation

  • #9427 : Passing undefined to .text() does not trigger setter
  • #10753 : inline the evalScript function in manipulation.js as it’s only used once
  • #10864 : text() method on a document fragment always returns the empty string
  • #11055 : Update HTML5 Shim elements list to support latest html5shiv
  • #11217 : Append problem with webkit
  • #11291 : Cloning XMLDoc’s with HTML5 nodeName’s breaks on IE
  • #11323 : script tags with type=”text/ecmascript” leak into the DOM
  • #11356 : safeFragment memory leak

Misc

  • #10952 : .fired() doesn’t work on Callbacks object when it is flagged with “once”
  • #11257 : Wrong path to source files in test suite if PHP missing

Queue

  • #10967 : .promise() does not attach methods onto target

Support

  • #7986 : Bug in $.support.boxModel if page has DIV-element CSS
  • #11048 : Support Tests affect layout for positioned elements in IE6-9
  • #11337 : Bug in $.support.reliableMarginRight

Traversing

  • #11370 : $(‘<div>’).siblings() throws exception

Announcing the 2012 San Francisco jQuery Conference!

Posted March 20, 2012 by Leah Silber

It’s that time of year again…time to talk about the next jQuery Conference !

Mark your calendars for June 28th and 29th. By popular demand, the next jQuery Conference will be in San Francisco proper (as opposed to Mountain View), at the fantastic UCSF Mission Bay Conference Center . If you haven’t  been to an event there before, some highlights:

  • Pretty much the best conference wifi we’ve ever worked with
  • Pretty much the best conference food  we’ve ever eaten
  • Free flowing coffee, sodas and drinks all day long
  • Great space, with comfy seating, great AV, parking, easy access to public transit, space for partying, and so on and so on and so on

We’re incredibly excited about the new space, and about the way the 2012 SF show is shaping up! We’re going slightly smaller and single track this year too, so things are a bit simplified, a lot more intimate, and there’s less general shuffling about. Registration is open now, and space is extremely  limited Tickets have sold out pretty quickly in the past, and there are about 150 tickets less than last time!

Call for Proposals

We’ve opened a call for speaking proposals , which will remain open until May 13th. We encourage any and all to apply. In fact, we’re borrowing a page from JSConf’s playbook this year and doing an “inverted” call:  you’re encouraged to nominate your dream speaker (or anyone else) for a speaking slot on the subject of your choice. Of course, you’re welcome to nominate yourself!  We love to spice it up with new speakers, new topics, and pretty much whatever you can think of. Submit a proposal now !

Sponsors

Conferences are expensive. So is running an open source project. We couldn’t do any  of it without your help and support… so listen up! If you work for a company that’s hiring, a company that wants some developer publicity, or a company looking to help out and give back to the community, send them our way. Take a look at the conference prospectus  if you (or your bosses) are feeling generous :) Sponsorship benefits and mega karma points are both up for grabs…

Training

We’re still on the lookout for a space for training in SF on Wednesday, June 27th. If your company has a space, or you have an idea for a venue, please shoot us an email , and we’ll be eternally grateful.

That’s it for today, folks. Keep an eye out for upcoming announcements about speakers, sponsors, training days and all varieties of miscellany. We’ll also be updating the conference site with things like venue details and after parties, so keep an eye on that one too. Lastly, as always, if you’ve got questions or comments, reach out or leave a note here.

jQuery 1.7.2 RC1 Released

Posted March 09, 2012 by dmethvin

jQuery 1.7.2 will be arriving soon! To make sure that we’ve fixed the bugs voted “Most Likely to Annoy” without introducing any new bugs, we need your help in testing this release candidate. You can get the code from the jQuery CDN:

It will only take a few minutes to drop in this latest file and test it with your code. If you’ve got a lot of pages, the list of fixed bugs below may be a helpful guide for determining what to test. And of course, if you reported a bug or were affected by one listed below, please re-test to be sure we fixed it for good. We’ve tested it internally against the current builds of jQuery UI and jQuery Mobile. There is one compatibility issue with jQuery Mobile 1.1 RC1 that has already been fixed and will be addressed by their next release.

Looking for an even easier way to test your web site with the latest jQuery? On Windows you can use the excellent Fiddler tool and create an AutoResponder rule to point your HTTP script requests for jQuery to the file location above. Then you are testing your live web site with the latest jQuery on your PC, without having to edit any files at all! If you know of similar tools for other platforms, leave a message in the comments below.

If you are particularly interested in IE6 support, please help us out. We are having sporadic trouble running the unit tests in IE6. It hasn’t been possible for us to determine the cause of these problems, but the problem doesn’t happen consistently and the sheer size of our test suite may just be overwhelming a browser that is more than a decade old. If you observe any reproducible failures in real code, please let us know and try to provide the smallest possible test case.

You can use the bug tracker to report bugs; be sure to create a test case on jsFiddle so we can figure it out easily. If you’re not sure it’s a bug, ask on our forum or on StackOverflow . Please don’t use the blog comments below to report bugs.

jQuery 1.7.2rc1 Change Log

Here’s the current change log of the 1.7.2rc1 release.

Ajax

  • #4624 : Charset in default ajaxSettings.contentType
  • #10978 : jQuery.param() should allow non-native constructed objects as property values
  • #11264 : evalScript() uses defaults set by ajaxSetup()
  • #11426 : jQuery.ajax() always fails when requesting JPG images in IE

Attributes

  • #5571 : Allow chaining when passing undefined to any setter in jQuery
  • #10828 : attr(“coords”) returns undefined in IE7
  • #10870 : Incorrect behaviour of $.removeAttr(“selected”)
  • #11316 : Consider looking through valHooks by element type first, then by nodeName instead of the other way around

Build

  • #10692 : Configure the jshint options to more accurately match the style guide
  • #10693 : generalize the “test something in an iframe” code in unit tests
  • #10901 : have unit tests fail if the tester is running from file:// or doesn’t have PHP
  • #10902 : ability to test a built version of jQuery in unit tests
  • #10931 : Unit tests shouldn’t require internet access

Core

  • #10466 : jQuery.param() mistakes wrapped primitives for deep objects

Css

  • #10639 : outerWidth(true) and css(‘margin’) returning % instead of px in Webkit
  • #10754 : have jQuery.swap return the return of the callback instead of just executing it
  • #10782 : Incorrect calculating width
  • #10796 : Bug in IE7 with $(‘#el’).css.(‘background-position’)
  • #10858 : css.js regular expressions are incomplete
  • #11119 : The curCSS function only need 2 arguments

Data

  • #11309 : hexadecimal-formatted data-* attributes parsed incorrectly

Deferred

  • #11306 : calling .disable() or .lock() on a $.Callbacks object breaks its fired() status

Dimensions

  • #3838 : $(document).height() incorrect in IE6

Effects

  • #8498 : Animate Hooks
  • #10006 : method show is not working as expected in all browsers when called for document fragment
  • #10848 : Animation toggling loses state tracking in certain atomic edge cases
  • #11415 : Silently ignore negative CSS values where they are illegal

Event

  • #8165 : .live(‘click’, handler) fires on disabled buttons with child elements in Chrome
  • #10819 : Eliminate “this.on.call(this, “
  • #10878 : $(“select”).live(“change”, function(){ …broken in IE8 in jQuery 1.7
  • #10961 : Error in XRegExp using jQuery 1.7.1 in IE6-9
  • #10970 : The .on() selector parameter doesn’t work with :not(:first) selector
  • #10984 : Cannot off() custom events ($.event.special)
  • #11021 : Hover hack mangles a namespace named “hover”
  • #11076 : .clone(true) loses delegation filters
  • #11130 : jQuery.fn.on: binding map with null selector ignores data
  • #11145 : $(document).on() not working with name=”disabled”

Manipulation

  • #9427 : Passing undefined to .text() does not trigger setter
  • #10753 : inline the evalScript function in manipulation.js as it’s only used once
  • #10864 : text() method on a document fragment always returns the empty string
  • #11055 : Update HTML5 Shim elements list to support latest html5shiv
  • #11217 : Append problem with webkit
  • #11291 : Cloning XMLDoc’s with HTML5 nodeName’s breaks on IE
  • #11323 : script tags with type=”text/ecmascript” leak into the DOM
  • #11356 : safeFragment memory leak

Misc

  • #10952 : .fired() doesn’t work on Callbacks object when it is flagged with “once”
  • #11257 : Wrong path to source files in test suite if PHP missing

Queue

  • #10967 : .promise() does not attach methods onto target

Support

  • #7986 : Bug in $.support.boxModel if page has DIV-element CSS
  • #11048 : Support Tests affect layout for positioned elements in IE6-9
  • #11337 : Bug in $.support.reliableMarginRight

Traversing

  • #11370 : $(‘<div>’).siblings() throws exception

Announcing the jQuery Foundation

Posted March 06, 2012 by Adam J. Sontag

(BOSTON) — The jQuery Board, in conjunction with Software Freedom Conservancy, is proud to announce the formation of the jQuery Foundation, Inc., an independent organization that will manage jQuery, the Internet’s number one JavaScript library, and its constituent projects.

The jQuery Board previously administered jQuery under the aegis of the Conservancy, a public charity that acts as a non-profit home for free software projects.

The new jQuery Foundation is a non-profit trade association dedicated to supporting development of the jQuery Core, UI, and Mobile projects; providing jQuery documentation and support; and fostering the jQuery community.

Dave Methvin, who recently took over as the head of the jQuery Core development team, will also serve as the Foundation’s President. “jQuery is the most popular JavaScript library, and creating an autonomous organization is the next step in ensuring its future development and benefiting everyone who uses jQuery,” said Methvin. “We’ll be announcing several initiatives shortly, including the next jQuery Conference and other efforts driven by needs within the community and the project.”

“I’m extremely excited to see the jQuery Foundation springing to life. I’m glad that Dave Methvin is leading the foundation and the direction of the core library. He’s a good friend and exceedingly capable of moving jQuery forward,” said John Resig, who created the library in 2005. “Meanwhile, I’ve been spending more time focusing on improving the state of JavaScript and programming education at Khan Academy. I’m psyched to be a part of the jQuery core team and Foundation and can’t wait to see how jQuery grows in the upcoming years.”

“We are proud that the jQuery Board has built jQuery into a vibrant and successful Open Source community under Conservancy’s mentorship,” said Bradley Kuhn, Executive Director of the Software Freedom Conservancy. “Our mission includes helping member projects determine whether to form their own organization, and we’re pleased jQuery is the first Conservancy project to take that step.”

The jQuery Foundation would like to thank Joel G. Kinney of Fort Point Legal , whose generous pro-bono counsel has been invaluable in transitioning to an independent organization. The Foundation is also proud to accept an honorary first donation from the Linux Fund , which has chosen to continue its tradition of supporting the open source community with a contribution to the Foundation’s inaugural operating expense budget.

About jQuery

Created in 2005 by John Resig as a JavaScript library to provide an intuitive approach for working with the DOM and Ajax, jQuery has steadily gained popularity among the development community and is the most widely-adopted JavaScript library in use today.

About the jQuery Foundation

The jQuery Foundation is a non-profit trade association and the home of jQuery, the Internet’s number one JavaScript library.  Founded by a group of leading JavaScript developers and architects, the jQuery Foundation is dedicated to three goals:  supporting development of the jQuery Core, UI, and Mobile projects; providing jQuery documentation and support; and fostering the jQuery community.

jQuery Foundation, Inc. is a Delaware non-profit currently seeking IRS 501(c)(6) status.  Donations to the jQuery Foundation will be used to further the goals of the Foundation.  For more information, visit http://jquery.org .

About Software Freedom Conservancy

Software Freedom Conservancy is a non-profit organization that helps promote, improve, develop and defend Free, Libre and Open Source software projects.  Conservancy is a home to twenty-eight software projects, each supported by a dedicated community of volunteers, developers, and users.  Conservancy’s projects include some of the most widely used software systems in the world across many application areas, including educational software deployed in schools around the globe, embedded software systems deployed in most consumer electronic devices, distributed version control developer tools, integrated library services systems, and widely used graphics and art programs.  A full list of Conservancy’s projects can be found at http://sfconservancy.org/members/current/ .  Conservancy provides to these projects the necessary infrastructure and not-for-profit support services to enable the project’s communities to focus on what they do best: creating innovative software and advancing computing for the public’s benefit.

XMLWriter for Javascript

Posted February 17, 2012 by Ariel Flesler

Introduction

This is a Javascript class, based on .NET's XMLTextWriter .

This is not a port, but a reduced and adapted version.



Constructor

The constructor accepts 2 optional arguments: encoding, and version. You call it like this:
var
 xw = new
 XMLWriter( 'UTF-8'
, '1.0'
 );

Methods

Class instances have the following methods:
  • writeStartDocument([ bool standalone ])
    Opens a new document, must be call on start, if standalone is specified, standalone="true/false" will be added to the header.
  • writeEndDocument()
    Closes the active document, it's not really mandatory to call it.
  • writeDocType( string declarations )
    Adds a doctype to the document, can be called at anytime. If specified, a doctype will be included in the generated xml, in this form:

    <!DOCTYPE root-element declarations>
  • writeStartElement( string name [, string ns ] )
    Creates a new node element with this name, and it becomes the active element. A namespace can be specified.
  • writeEndElement()
    Closes the active element and goes up one level.
  • writeAttributeString( string attr, string value )
    Adds an attribute to the active element.
  • writeString( string text )
    Adds a text node to the active element.
  • writeElementString( string name, string txt [, string ns ] )
    Shortcut method, creates an element, adds the text and closes it.
  • writeCDATA( string text )
    Adds a text node wrapped with CDATA, to the active element.
  • writeComment( string text )
    Adds a comment node to the active element.
  • flush(): string
    Generates the XML string and returns it.
  • close()
    Closes the writer and cleans up.
  • getDocument()
    Generates a real XMLDocument from the writer. This method doesn't belong to the original class.

Formatting

You can choose whether the generated XML is formatted or not, and how. You can modify the following options for each instance or from XMLWriter.prototype to affect them all:
  • encoding
    'ISO-8859-1' by default.
  • version
    '1.0' by default.
  • formatting
    'indented'(default) or 'none'.
  • indentChar
    '\t' by default, char to indent.
  • indentation
    # of chars added per level, 1 by default.
  • newLine
    '\n' by default, char to separate lines.
If you choose formatting = 'none', you don't need to modify indentChar, indentation or newLine.



Links

Downloads

Image Similarity Search Wanted

Posted February 13, 2012 by John Resig

I’ve been working on a few projects in my spare time and one service, in particular, would greatly benefit from a high quality image similarity search.

I’ve been trying a number of the Open (and non-Open) Source tools (a great list of which is on Wikipedia here ). Thus far none of the tools that I’ve found are of high-enough quality to warrant further pursuit. They either do simple color comparison, basic wavelet/outline comparison, or some form of hashing – none of which appears to work very well beyond basic images. Some of the best algorithms are either caught up in University research programs (generally unreleased) or are available as corporate search engines.

In an ideal world I’d like something with the quality of TinEye (I’d even be open to using TinEye’s commercial services but they haven’t gotten back to me as of yet – I suspect that they’re mostly interested in dealing with large corporate clients).

In short: Does anyone have a lead on a high quality image similarity search tool (using Content-Based Image Retrieval )? I’m open to Open Source, closed source, or even paid API service – as long as it works well.

Note: I’m looking to use this on a private collection of images, so a service like Google Image Search (or TinEye’s normal commercial API) are not suitable alternatives – they both search images on the open web.

jQuery 1.7.2 Beta 1 Released

Posted February 01, 2012 by dmethvin

Hey there Internets, it’s the jQuery Core team! We haven’t talked in a while, but over the holidays we were busy fixing the bugs you reported. The result of that hard work is jQuery 1.7.2 Beta 1. We decided to get a beta out by Groundhog Day so you wouldn’t be in the shadow of six more weeks of unfixed bugs.

You can get the code from the jQuery CDN:

Oh, we know what you’re thinking: “Cool, a new version of jQuery; I’ll wait until the final release has been out a few weeks and then I’ll give it a try.” Right, and then you’ll find some bug that keeps you from upgrading. Nothing makes us sadder than finishing up a release and only then seeing a report of a serious bug that could have been fixed earlier.

So please, come out of your burrow and try this beta with your code. Did we miss an old bug? Did we create a new bug that makes you feel like Bill Murray waking up to “I Got You Babe?” We want to know. You can use the bug tracker to report bugs; be sure to create a test case on jsFiddle so we can figure it out easily. If you’re not sure it’s a bug, ask on our forum or on StackOverflow .

jQuery 1.7.2b1 Change Log

The current change log of the 1.7.2b1 release.

Ajax

  • #10978 : jQuery.param() should allow non-native constructed objects as property values

Attributes

  • #5571 : Allow chaining when passing undefined to any setter in jQuery

Build

  • #10692 : Configure the jshint options to more accurately match the style guide
  • #10902 : ability to test a built version of jQuery in unit tests
  • #10931 : Unit tests shouldn’t require internet access

Core

  • #10466 : jQuery.param() mistakes wrapped primitives for deep objects

Css

  • #10639 : outerWidth(true) and css(‘margin’) returning % instead of px in Webkit
  • #10754 : have jQuery.swap return the return of the callback instead of just executing it
  • #10782 : Incorrect calculating width
  • #10796 : Bug in IE7 with $(‘#el’).css.(‘background-position’)
  • #10858 : css.js regular expressions are incomplete
  • #11119 : The curCSS function only need 2 arguments

Effects

  • #8498 : Animate Hooks
  • #10006 : method show is not working as expected in all browsers when called for document fragment
  • #10848 : Animation toggling loses state tracking in certain atomic edge cases

Event

  • #8165 : .live(‘click’, handler) fires on disabled buttons with child elements in Chrome
  • #10819 : Eliminate “this.on.call(this, “
  • #10878 : $(“select”).live(“change”, function(){ …broken in IE8 in jQuery 1.7
  • #10961 : Error in XRegExp using jQuery 1.7.1 in IE6-9
  • #10970 : The .on() selector parameter doesn’t work with :not(:first) selector
  • #10984 : Cannot off() custom events ($.event.special)
  • #11021 : Hover hack mangles a namespace named “hover”
  • #11076 : .clone(true) loses delegation filters
  • #11130 : jQuery.fn.on: binding map with null selector ignores data
  • #11145 : $(document).on() not working with name=”disabled”

Manipulation

  • #9427 : Passing undefined to .text() does not trigger setter
  • #10753 : inline the evalScript function in manipulation.js as it’s only used once
  • #10864 : text() method on a document fragment always returns the empty string
  • #11055 : Update HTML5 Shim elements list to support latest html5shiv

Misc

  • #10952 : .fired() doesn’t work on Callbacks object when it is flagged with “once”
  • #11257 : Wrong path to source files in test suite if PHP missing

Support

  • #11048 : Support Tests affect layout for positioned elements in IE6-9

Pagination and Backbone.js

Posted December 30, 2011 by Benjamin Sterling

I recently had to create some pagination for a backbone.js project I’ve been working on.  What I created has been working quite well but was not 100% happy with what I did.  Since I had a week off I figured I’d rewrite it as a mixin and clean up the approach.  Will have to work it back into the project somehow but that is something to worry about later.

Let’s just jump right in there.  Some caveats: I am sure there is probably a better approach to some of the code, so please give some guidance on how it should be improved.  This code assumes that all the data is already loaded into the collection.  The set of data I was working with had a record count of about 28,000 items.  I’ve gone back and both on if having that much data loaded is a good or bad thing.  Of all the articles I’ve read there doesn’t seem to be a consensus.

The folder structure I am using is:

// Folder structure being used
assets/
app/
collections/
tags.js
mixins/
pagination.js
models/
tag.js
views/
pagination.js
tags.js

The JSON structure I am dealing with:

{
"status":true,
"tags":[
{
"id":1,
"name":"A"
},...
]
}

The model, nothing too special going on here:

( function ( models ) {
models . Tag = Backbone . Model . extend ({});
})( App . models );

The collection, again, is a pretty basic set up.  I’ve set to model to map to App.models.Tag, our url to point to tags_all.php and overridden the parse method to return a cleaned up tags array.

The last line _.extend(collections.Tags.prototype, pagination); is where we mixin in our Pagination module(?: not sure what its proper name is actually. Module, Class?).

( function ( collections , pagination , model ) {
collections . Tags = Backbone . Collection . extend ({
model : model ,
url : 'tags_all.php' ,


/**
* @param resp the response returned by the server
* @returns (Array) tags
*/
parse : function ( resp ) {
var tags = resp . tags ;


return tags ;
}
});


_ . extend ( collections . Tags . prototype , pagination );
})( App . collections , App . mixins . Pagination , App . models . Tag );

Next up is the Pagination mixin code, have a read of it and I’ll comment after the code.

( function ( mixins ) {
/**
* @class
* Pagination
*/
mixins . Pagination = {
/** how many items to show per page */
perPage : 20 ,


/** page to start off on */
page : 1 ,


/**
*
*/
nextPage : function () {
var self = this ;


self . page = ++ self . page ;
self . pager ();
},


previousPage : function () {
var self = this ;


self . page = -- self . page || 1 ;
self . pager ();
},


goTo : function ( page ) {
var self = this ;


self . page = parseInt ( page , 10 );
self . pager ();
},


howManyPer : function ( perPage ) {
var self = this ;
self . page = 1 ;
self . perPage = perPage ;
self . pager ();
},


setSort : function ( column , direction ) {
var self = this ;


self . pager ( column , direction );
},


pager : function ( sort , direction ) {
var self = this ,
start = ( self . page - 1 ) * this . perPage ,
stop = start + self . perPage ;


if ( self . orgmodels === undefined ) {
self . orgmodels = self . models ;
}


self . models = self . orgmodels ;


if ( sort ) {
self . models = self . _sort ( self . models , sort );
}


self . reset (
self . models . slice ( start , stop )
);
},


_sort : function ( models , sort ) {
models = models . sort ( function ( a , b ) {
var a = a . get ( sort ),
b = b . get ( sort );


if ( direction === 'desc' ) {
if ( a > b ) {
return - 1 ;
}


if ( a < b ) {
return 1 ;
}
}
else {
if ( a < b ) {
return - 1 ;
}


if ( a > b ) {
return 1 ;
}
}


return 0 ;
});


return models ;
},


info : function () {
var self = this ,
info = {},
totalRecords = ( self . orgmodels ) ? self . orgmodels . length : self . length ,
totalPages = Math . ceil ( totalRecords / self . perPage );


info = {
totalRecords : totalRecords ,
page : self . page ,
perPage : self . perPage ,
totalPages : totalPages ,
lastPage : totalPages ,
lastPagem1 : totalPages - 1 ,
previous : false ,
next : false ,
page_set : [],
startRecord : ( self . page - 1 ) * self . perPage + 1 ,
endRecord : Math . min ( totalRecords , self . page * self . perPage )
};


if ( self . page > 1 ) {
info . prev = self . page - 1 ;
}


if ( self . page < info . totalPages ) {
info . next = self . page + 1 ;
}


info . pageSet = self . setPagination ( info );


self . information = info ;
return info ;
},


setPagination : function ( info ) {
var pages = [];
// How many adjacent pages should be shown on each side?
var ADJACENT = 3 ;
var ADJACENTx2 = ADJACENT * 2 ;
var LASTPAGE = Math . ceil ( info . totalRecords / info . perPage );
var LPM1 = - 1 ;


if ( LASTPAGE > 1 ) {
//not enough pages to bother breaking it up
if ( LASTPAGE < ( 7 + ADJACENTx2 )) {
for ( var i = 1 , l = LASTPAGE ; i <= l ; i ++ ) {
pages . push ( i );
}
}
// enough pages to hide some
else if ( LASTPAGE > ( 5 + ADJACENTx2 )) {


//close to beginning; only hide later pages
if ( info . page < ( 1 + ADJACENTx2 )) {
for ( var i = 1 , l = 4 + ADJACENTx2 ; i < l ; i ++ ) {
pages . push ( i );
}
}


//in middle; hide some front and some back
else if ( LASTPAGE - ADJACENTx2 > info . page && info . page > ADJACENTx2 ) {
for ( var i = info . page - ADJACENT ; i <= info . page + ADJACENT ; i ++ ) {
pages . push ( i );
}
}
//close to end; only hide early pages
else {
for ( var i = LASTPAGE - ( 2 + ADJACENTx2 ); i <= LASTPAGE ; i ++ ) {
pages . push ( i );
}
}
}
}


return pages ;
}
};


})( App . mixins );

Most of the code is pretty self-explanatory, so I won’t dig into every line.  There are some methods you will see in the code, setSort and _sort , that are actually not in use for this discussion but will follow up on them in another post.

The first four methods are the ones that get triggered to start the ball rolling on the pagination.  Each of them call the pager method.

The page method makes a backup copy of the models the first pass through.  Resets models with said backup.  Ignore the sort for this post.  And lastly we pass in the start and stop points into the Array slice method, which we in turn pass to the Backbone.js reset method.  This will trigger a reset event and any view that is watching it will execute.

The last two methods to concern yourself with is the info and setPagination methods.  The info method does some base variable set up that will be used in views that need that info, our pagination view for-instance.  The setPagination method is called by info and at this point I must add two things.  The first is that I more or less borrowed the code from a PHP pagination script and can’t find it again, otherwise I’d give credit.  The second is that the purpose of setPagination is to allow for custom pagination structure and I was not clear I how I should make this more straight forward.  Any suggestions would be great.

So, what does setPagination do?  Basically it returns an array of what pages you want in your pagination — this will become a bit clearer what you see the pagination view below/in action, but let me try to explain.  In the code that is there, if we are on page 8 of our recordset, the pages that show will look something like this: 5 6 7 8 9 10 11.   But you are not limited to that structure.  In the project I will be merging this into, it will have a structure like, assuming I am on page 8 again: 1-5 6 7 8 9 10 11-15.

Hopefully that is clear.

Next two up are the pagination view and template/index page themselves.  The final structure will look something like: First Previous 5 6 7 8 9 10 11 Next Last Show 20 | 50 | 100 141 – 160 of 28091 shown” .  Again, everything should be pretty self-explanatory, each method is named to do what it is supposed to do.

( function ( views ) {
views . Pagination = Backbone . View . extend ({


events : {
'click a.first' : 'gotoFirst' ,
'click a.prev' : 'gotoPrev' ,
'click a.next' : 'gotoNext' ,
'click a.last' : 'gotoLast' ,
'click a.page' : 'gotoPage' ,
'click .howmany a' : 'changeCount'
},


tagName : 'aside' ,
initialize : function () {
_ . bindAll ( this , 'render' );
var self = this ;


self . tmpl = _ . template ( $ ( '#tmpPagination' ). html ());
self . collection . bind ( 'reset' , this . render );
$ ( self . el ). appendTo ( 'body' );
},
render : function () {
            var self ;
            self = this ;


var html = this . tmpl ( self . collection . info ());
$ ( this . el ). html ( html );
},


gotoFirst : function ( e ) {
e . preventDefault ();


var self = this ;


self . collection . goTo ( 1 );
},


gotoPrev : function ( e ) {
e . preventDefault ();


var self = this ;


self . collection . previousPage ();
},


gotoNext : function ( e ) {
e . preventDefault ();


var self = this ;


self . collection . nextPage ();
},


gotoLast : function ( e ) {
e . preventDefault ();


var self = this ;


self . collection . goTo ( self . collection . information . lastPage );
},


gotoPage : function ( e ) {
e . preventDefault ();


var self = this ;
var page = $ ( e . target ). text ();


self . collection . goTo ( page );
},


changeCount : function ( e ) {
e . preventDefault ();


var self = this ;
var per = $ ( e . target ). text ();


self . collection . howManyPer ( per );
}
});
})( App . views );

I am using underscore.js’ template function.  Only real thing to note is the _.each loop.  This is where the “pages”, e.g. “5 6 7 8 9 10 11 “, will get parsed out.

<!DOCTYPE HTML>
<html lang= "en-US" >
<head>
<meta charset= "UTF-8" >
<title></title>
<script src= "jquery-1.7.1.min.js" ></script>
<script src= "underscore.js" ></script>
<script src= "json2.js" ></script>
<script src= "backbone.js" ></script>
<script type= "text/javascript" >
var App = {
collections : {},
models : {},
views : {},
mixins : {},
init : function () {
var collection = new App . collections . Tags ();
App . views . tags = new App . views . Tags ({ collection : collection });
new App . views . Pagination ({ collection : collection });
}
};
</script>
<script src= "assets/app/mixins/pagination.js" ></script>
<script src= "assets/app/models/tag.js" ></script>
<script src= "assets/app/collections/tags.js" ></script>
<script src= "assets/app/views/tags.js" ></script>
<script src= "assets/app/views/pagination.js" ></script>
<script type= "text/javascript" >
$ ( App . init );
</script>
</head>
<body>


<script type= "text/html" id= "tmpPagination" >
< span class = "cell last pages" >
<% if ( page != 1 ) { %>
< a href = "#" class = "first" > First < /a>
< a href = "#" class = "prev" > Previous < /a>
<% } %>
<% _ . each ( pageSet , function ( p ) { %>
<% if ( page == p ) { %>
< span class = "page selected" ><%= p %>< /span>
<% } else { %>
< a href = "#" class = "page" ><%= p %>< /a>
<% } %>
<% }); %>
<% if ( lastPage != page ) { %>
< a href = "#" class = "next" > Next < /a>
< a href = "#" class = "last" > Last < /a>
<% } %>
< /span>


< span class = "cell howmany" >
Show
< a href = "#" class = "selected" > 20 < /a>
|
< a href = "#" class = "" > 50 < /a>
|
< a href = "#" class = "" > 100 < /a>
< /span>


< span class = "cell first records" >
< span class = "current" ><%= startRecord %>< /span>
-
< span class = "perpage" ><%= endRecord %>< /span>
of
< span class = "total" ><%= totalRecords %>< /span>
shown
< /span>
</script>
</body>
</html>

This last bit is the view that helps parses out the tags.

( function ( views ) {
views . Tags = Backbone . View . extend ({
tagName : 'ul' ,
initialize : function () {
_ . bindAll ( this , 'render' , 'addAll' , 'addOne' );
var self = this ;
self . collection . fetch ({
success : function () {
self . collection . pager ();
},
silent : true
});
self . collection . bind ( 'reset' , self . addAll );
$ ( self . el ). appendTo ( 'body' );
},
addAll : function () {
var self = this ;


$ ( self . el ). empty ();
self . collection . each ( self . addOne );
},


addOne : function ( model ) {
var self = this ;


var view = new Tag ({ model : model });
view . render ();
$ ( self . el ). append ( view . el );
}
});


var Tag = Backbone . View . extend ({
tagName : 'li' ,
render : function () {
$ ( this . el ). html ( this . model . get ( 'name' ));
}
});
})( App . views );

Closing

Like anything else, there are a hundred ways to do things and this is just one.  My example goes off the assumption that all the data is available but I am sure it can be re-written to only fetch a certain number of records from the server on an as needed basis.

What would you do differently?  Did you see anything wrong with my implementation?

JavaScript as a First Language

Posted December 21, 2011 by John Resig

At Khan Academy we've been investigating teaching Computer Science to students in some new and interesting ways. The most interesting aspect of which is that we're likely going to be teaching them JavaScript as their first language.

We're in a very unique position as we're primarily aiming to teach students who've been through our previous math and science-centric curriculum . Because of this we can create some rather compelling exercises and projects that never would've been feasible otherwise.

The prospect of teaching the JavaScript language as a first language is actually really exciting. Teaching prototypal inheritance to experienced classical-inheritance-using developers is normally rather frustrating (and results in many libraries springing up attempting to replicate the classical style of inheritance in JavaScript, which is a whole realm of weirdness in-and-of itself). Teaching prototypal inheritance to someone who has never seen any form of inheritance before will decidedly be an easier task. The same goes for learning functional programming. JavaScript is a great language for experiencing functional programming and can be a major focus of our curriculum as a result.

As we've begun to look at the prospect of JavaScript-as-a-first-language a number of obvious warts stick out (as is obvious to anyone who has worked with JavaScript for any duration). To make sure that general warts don't crop up we will be using some form of linting (either JSLint or JSHint or similar) in the code editor to give the users contextual information on what's happening with their code and why they should be writing their code in a certain way.

We want to go beyond basic syntax tweaks though and find ways of using the language that'll result in an easier learning experience. In particular there are two changes which will likely result in a much simpler on-ramp to learning.

Note: These particular recommendations really only make sense if you're teaching JavaScript to someone who has never seen the language before and is really only programming with a set of specific, well-coded, libraries. Obviously more will have to be taught in order bring the students up to the level of "see any random piece of cross-browser JavaScript code and understand what it does."

Type Coercion

Type coercion is just a complete mess, as many many others have pointed out and as what Douglas Crockford typically teaches, as in JavaScript: The Good Parts .

It might make sense to discuss it far later in the education cycle... like after learning about prototypes, functional programming, and closures. Basically after everything that's actually important.

name === "John"

The first change that I'm recommending is that the students will only ever see, and use, === (and !== ). While using '== ' does have the advantage of being syntactically shorter there is so much type coercion baggage attached to it as to make it an exercise in futility to try and teach early on in the learning of programming.

The one exception that might be worthwhile to teach later on is the case in which you wish to see if a variable contains a null or undefined value. This can be done easily with a simple someVar == null check and is likely the one useful case of == . (Another noted exception is the browser bug in IE where === checks against Window objects will always return false, but it's unlikely that we'll cover such specific browser issues in our curriculum.)

Falsy Values

For the same reasons that == can be messy, so can falsy values. Enforcing strict boolean checks would result in less edge cases but would certainly result in longer code. Perhaps education of falsy values can be limited to booleans, null, and undefined with number and string falsy values left for a later exercise.

Function Declarations

Perhaps the most interesting change that we can make is a rather subtle one, but it's eschewing normal function declarations for creating anonymous functions and assigning them to a variable.

// Don't do this:

function getData( ) { }

// Do this instead:

var getData = function ( ) { } ;

There are a number of good habits that are instilled when you use this particular technique.

  • Makes it easier to understand "functions as an object". I've found that when you show new developers a function being assigned to a variable it suddenly becomes much more obvious that a function is actually an object and can be manipulated as such (and that a function can be passed as an argument to another function). Thus students are advanced along the path towards a better understanding of functional programming.
  • It enforces good semicolon habits. Traditional function declaration is the only situation in which semicolons aren't needed (save for conditional statements and loops, naturally) and it makes it much more obvious when they're required all the time.
  • Doesn't have much of the baggage traditionally associated with functions and scope .

Block Scope

This is the remaining area that'll certainly be a challenge for any introductory student to understand and yet I don't see a particularly good solution here. The issue of variables declared within for loops hoisting up is more than enough to make most developers heads spin. I'll have to see if we can't come up with some intuitive ways of explaining how variable declaration works (and combining it with vigilant lint enforcement) rather than having a purely technical solution.

(While (function(){ ... })(); is a solution I'm skeptical that we'll be able to teach that early-enough on as to make it worthwhile.)

JavaScript as a First Language

It should be noted that while we're starting with JavaScript as a first language - largely due to its ubiquity, desirability in the larger workforce, lack of prior installation requirements, and ability to create something that's easy to share with friends - we're not going to be myopic and only focus on JavaScript. There are so many things that can be learned from other languages, not to mention entire skillsets that aren't terribly relevant to in-browser JavaScript, that it behooves us to try and bring as much of them into our curriculum as possible.

I talk a little bit more about our choice to use JavaScript and some of the browsers that we'll want to support in our development in the following video :

By all accounts I want to try and avoid any features that would cause cross-browser weirdness to spring up. As a result we'll be making extensive use of libraries (for drawing to a canvas or manipulating the DOM) and using only JavaScript language features that work consistently in the browsers that we end up supporting.

Using jQuery’s .pushStack() for reusable DOM traversing methods

Posted December 20, 2011 by Karl Swedberg

The .pushStack() method has been in jQuery since before version 1.0, but it hasn't received a whole lot of attention outside of core developers and plugin authors. While its usefulness may not be immediately apparent, it can come in really handy in some situations, so I'd like to take a quick look at what it does, how it works, and how we can use it.

pushStack Basics

At its most basic level, the .pushStack() method accepts an array of DOM elements and "pushes" it onto a "stack" so that later calls to methods like .end() and .andSelf() behave correctly. (Side note: As of jQuery 1.4.2, you can pass in a jQuery object instead of an array, but that isn't documented and jQuery itself always uses an array, so that's what we'll stick to here.)

Internally, jQuery uses .pushStack() to keep track of the previous jQuery collections as you chain traversing methods such as .parents() and .filter() . This lets us traverse through the DOM, do some stuff, "back up" to previous collections within the same chain using .end() , and then do something else. Here is a somewhat contrived example:

JavaScript:

  1. // select some divs
  2. $( 'div.container' )
  3.   // find some spans inside those divs and add a class to them
  4.   .find ( 'span' ) .addClass ( 'baby' )
  5. // pop those spans off the "stack",
  6. // returning to the previous collection (div.container)
  7. .end ( )
  8.   // add a class to the parent of each div.container
  9.   .parent ( ) .addClass ( 'daddy' ) ;


Because .find() returns the result of a .pushStack() call to keep track of the previous collection (as does .parent() ), we can use .end() in the above example to return to the container divs.

Using pushStack for Fun and Profit

So, this is great for jQuery, but what can .pushStack() do for me and my code? Well, it can help me write specialized DOM traversal plugins that act just like jQuery's own traversal methods. In other words, I can stop chaining the same sets of traversal methods together and instead write a reusable function that still works with with .end() and all that. For example, let's say I often have a need to find an element's grandparent. While I could write $('#myElement').parent().parent() every time, it might be nice to just be able to write $('#myElement').grandparent() instead. A naïve way to write a grandparent plugin would look like this (changing the method name to "grandpa" for this example):

JavaScript:

  1. // NOT recommended!
  2. ( function ( $) {
  3.   $.fn .grandpa = function ( ) {
  4.     return this .parents ( ) .parents ( ) ;
  5.   } ;
  6. } ) ( jQuery) ;


The problem here is that two new jQuery object instances are added to the stack. So, let's see what happens when we use it:

JavaScript:

  1. // The DOM looks like this:
  2. // <div class="grandpa">
  3. //  <div class="pa">
  4. //    <div class="child son"></div>
  5. //  </div>
  6. // </div>
  7.  
  8. var elem = $( 'div.son' ) .grandpa ( ) .end ( ) ;
  9. $( 'div.son' ) .text ( elem.attr ( 'class' ) ) ;


Without seeing the plugin, we would expect to see "child son" inserted into <div class="son"> , but "pa" is inserted instead. Each .parent() call in the plugin adds to the stack, so using .end() only pops the second one off.

If we use .pushStack() instead, however, we can achieve the expected behavior:

JavaScript:

  1. ( function ( $) {
  2.   $.fn .grandma = function ( ) {
  3.  
  4.     var els = this .parent ( ) .parent ( ) ;
  5.     return this .pushStack ( els.get ( ) ) ;
  6.   } ;
  7. } ) ( jQuery) ;


Within a plugin function, one that is a method of $.fn , the this keyword refers to the jQuery object; therefore, the els variable refers to a jQuery object, as well. To convert it to an array, we use jQuery's .get() method, and we pass that array to .pushStack() . Let's see if .grandma() works any better than .grandpa() .

JavaScript:

  1. // The DOM looks like this:
  2. // <div class="grandma">
  3. //  <div class="ma">
  4. //    <div class="child daughter"></div>
  5. //  </div>
  6. // </div>
  7.  
  8. var elem = $( 'div.daughter' ) .grandma ( ) .end ( ) ;
  9. $( 'div.daughter' ) .text ( elem.attr ( 'class' ) ) ;


Here, "child daughter" is inserted, which means that .end() works as expected, changing the jQuery collection from the result of .grandma() to the result of $('div.daughter') . So, we've just successfully written a DOM traversal plugin, albeit a very simple one.

The Simplest DOM Traversal Methods

If the plugin only uses one DOM traversal method, then .pushStack() isn't really necessary. The HTML5 data filter plugin written by Elijah Manor illustrates this point nicely:

JavaScript:

  1. ( function ( $) {
  2.   $.fn .filterByData = function ( type, value ) {
  3.     return this .filter ( function ( ) {
  4.       return value != null ?
  5.         $( this ) .data ( type ) === value :
  6.         $( this ) .data ( type ) != null ;
  7.     } ) ;
  8.   } ;
  9. } ) ( jQuery) ;


Only one new jQuery collection is added to the stack, via .filter() , so using .end() simply pops that one off, and our job is done.

Filtering grandparents

For the sake of completeness, it would be nice for this DOM traversal plugin to allow optional "filtering" of the parent and grandparent elements. After all, jQuery's .parent() and .parents() allow filtering. For example, if I were to write $('div.child').parent('.daddy') , the jQuery collection would only contain an element if div.child had a parent element and if that parent had a class of "daddy."

There are plenty of reasonable ways one could include the filters, but for my purposes I'm going to have a .grandparent() method optionally accept two arguments. If only one argument is provided, it will filter the grandparent element only; if two are provided, the first will filter the parent and the second will filter the grandparent. Here is the full plugin plugin:

JavaScript:

  1. ( function ( $) {
  2.   $.fn .grandparent = function ( parentFilter, grandFilter ) {
  3.     if ( ! grandFilter ) {
  4.       grandFilter = parentFilter;
  5.       parentFilter = undefined;
  6.     }
  7.  
  8.     var els = this .parent ( parentFilter ) .parent ( grandFilter ) ;
  9.     return this .pushStack ( els.get ( ) ) ;
  10.   } ;
  11. } ) ( jQuery) ;


Finally, we have a nice .grandparent() plugin that adheres to the contract set by other jQuery DOM traversal methods—one that works with both filters and the .end() method. Here is what it could look like in use.

Plugins Site Update: The Old Is New Again

Posted December 13, 2011 by Adam J. Sontag

We’ve gotten a lot of feedback since last week’s announcement about the plugins site’s unfortunate tumble into oblivion, and I’d like to address a few of the most important concerns that have surfaced since.

“Could you make the old backup available for posterity?”

Yes. We can — and have. Over the weekend, we restored the most recent backup we had, and the original site is now living at archive.plugins.jquery.com ; you should be able to browse through everything that’s there to your heart’s content. We also applied the most recent user information we had, so if you had an account on the old site at any point in the last year, it should still work. However, the site is closed to new user registrations. If you really need a new account, please get in touch with me personally and I can get that straightened out for you. We’ve also set up a redirect, so that if you should encounter any links to plugins.jquery.com in your browsing, you’ll (hopefully) end up at the corresponding page in the archive.

Just get a backup from the Wayback Machine!

While the Internet Archive has cached versions of content that was updated more recently than last October, we just don’t have the people-power to re-create the lost posts manually in the new archive site. If you have an account, you can feel free to add “new” or old plugins, or update existing ones, should you desire to. However, this archive will not be indexed by search engines.

If you hate CMS-es so much, what’s with WordPress?

We’re in the middle of a network-wide redesign, and WordPress offers us a valuable set of tools when it comes to theming, searching, and serving a group of sites. Our new motto, however, is pull requests, not passwords ; we’re implementing theming, documentation, plugins, and more in such a way that contribution will not actually require an account on our CMS at all. As I outlined in the initial post, the plugin submission process will only involve adding a post-receive hook to your repository. In the event of a similar catastrophe, we’re made sure we’ll be able to replay the entire plugin contribution history and get the site back up to speed right away. Our goal is to leverage the WordPress features we find useful without it serving as a barrier to entry or as the canonical warehouse of content. If you are of the mind that WordPress is always a bad idea, no matter what, no matter how, you’re certainly entitled to that opinion, but at this point, it’s not particularly beneficial to the conversation.

Git(Hub) is hard

The new plugins site will serve as an index of plugins, with a simple “download” button right on each plugin’s page. You will not have to just browse around GitHub looking for jQuery plugins. If you don’t know git and only ever want to download jQuery plugins, you don’t have to learn it. However, if you want to submit plugins, you’ll have to be using some sort of source control that you can at least mirror in git. This is by design: it can be really easy to build a jQuery plugin, but that doesn’t mean it’s necessarily fit for public consumption. Requiring the use of source control and package.json are passive mechanisms that will help ensure that plugins which proliferate are authored by developers who have met a reasonable baseline (and aren’t selling batteries). We’re only targeting GitHub support for launch, but we’d like to add support for other services as well . We are actively avoiding the use of GitHub-specific features that would force us to limit the site to GithHub users permanently.

It’s A Conspiracy!

Some have called into question the veracity of my account, and that’s understandable, given the timing and circumstances. But believe me, the last thing I wanted to do after spending a day manually pruning spam from the directory was turn around and cause a gigantic headache for thousands of people, including myself and my colleagues. I hope the re-launching of the last backup at least partially allays these concerns. Additionally, we’re starting off with GitHub simply because it has a very broad user base already, and it has been incredibly positive for us since we shifted to it for development of jQuery Core, UI, and Mobile.

Thanks again for bearing with us during this transition.

Vector math basics to animate a bouncing ball in JavaScript

Posted December 09, 2011 by Jörn

Vector math is pretty much essential when you want to do any kind of physics simulation, be it as simple as a bouncing ball. While my goal originally was to implement a flocking simulation (like birds flying close to each other, but not too close), the lack of math skills led me to build a bouncing ball simulation first.

At the same time, I wanted to see what Khan Academy is all about. Turns out they have lessons on vector math, but there’s very little on vectors specifically. There are two lessons on vector basics, where this second one is a lot more practical . There are also two exercises, one for addition of vectors, one for scaling . Both are pretty easy and you should be done within a minute if you watched the video.

With that knowledge under your belt, let’s look at some practical application, the aforementioned bouncing ball. To start, take a look at the demo and play around with it, there are some instructions at the top.

You can find the source code for that demo on GitHub, here is the main file for the bouncing balls demo . I’m not going to discuss the Point and Vector classes that this uses, though you should take a look . They just implement adding and scaling of vectors, and calculating a vector based on two points. Let’s walk through the code:

var GRAVITY = new Vector(0, 9.81);
var FRICTION = 0.85;
var world = {
	x1: 0,
	y1: 0
};
$(window).resize(function() {
	world.x2 = $(window).width();
	world.y2 = $(window).height();
}).trigger("resize");

This defines two constants, GRAVITY and FRICTION, which we’ll use later to affect simulated objects. GRAVITY is a vector pointing downwards, where the second component represents the 9.81 meters per second, while the first component is zero. FRICTION is used in collisions later, and completely arbitrary.

The world object is also used in collision detection, and represents the dimensions of our 2d world. It starts at 0/0 in the left top corner, and ends in the right bottom corner. We bind a resize handler on window to update this calculation, that way collisions happen within the browser window, no matter how big it currently is.

Next up is the definition of our Ball class:

function Ball() {
	this.position = new Point(200, 200);
	this.output = $("<div>").addClass("dot").appendTo("body");
	this.velocity = new Vector(-5, 0);
}
Ball.prototype = {
	remove: function() {
		this.output.remove();
	},
	move: function() {
		// apply gravity
		this.velocity = this.velocity.add(GRAVITY.scale(0.1));

		// collision detection against world
		if (this.position.y > world.y2) {
			this.velocity.x2 = -this.velocity.x2 * FRICTION;
			this.position.y = world.y2;
		} else if (this.position.y < world.y1) {
			this.velocity.x2 = -this.velocity.x2 * FRICTION;
			this.position.y = world.y1;
		}
		if (this.position.x < world.x1) {
			this.velocity.x1 = -this.velocity.x1 * FRICTION;
			this.position.x = world.x1;
		} else {
			if (this.position.x > world.x2) {
				this.velocity.x1 = -this.velocity.x1 * FRICTION;
				this.position.x = world.x2;
			}
		}

		// update position
		this.position.x += this.velocity.x1;
		this.position.y += this.velocity.x2;

		// render
		this.output.css({
			left: this.position.x,
			top: this.position.y
		});
	}
};

This defines a Ball constructor, which initializes a new Ball at some arbitrary position, with some velocity to the left. It also creates a simple DOM element that we use for output.

The prototype of Ball has two methods. The remove method just removes the DOM element, which we use for cleanup. The move method is much more intersting: It gets called for each ‘tick’ of our animation loop, so we use it to update the current velocity, look for collisions, update the current position and render the result. Step by step:

this.velocity = this.velocity.add(GRAVITY.scale(0.1));

This adds GRAVITY to the balls velocity. While GRAVITY has a real world value, we need to adapt it to our pixel-based dimension. Doing this in every tick causes the ball to accelerate downwards, or when moving upwards, to deccelarate. With this alone our ball would start falling, but never stop. That’s where the next block comes in, the collision detection:

if (this.position.y > world.y2) {
	this.velocity.x2 = -this.velocity.x2 * FRICTION;
	this.position.y = world.y2;
} else if (this.position.y < world.y1) {
	this.velocity.x2 = -this.velocity.x2 * FRICTION;
	this.position.y = world.y1;
}
if (this.position.x < world.x1) {
	this.velocity.x1 = -this.velocity.x1 * FRICTION;
	this.position.x = world.x1;
} else {
	if (this.position.x > world.x2) {
		this.velocity.x1 = -this.velocity.x1 * FRICTION;
		this.position.x = world.x2;
	}
}

Here we compare the current position of our ball to the dimensions of the world . For each direction, there’s a check if the call is beyond the limit, if so, it inverts the velocity for that direction, while applying FRICTION . This causes the ball to bounce back slightly slower then it was before, simulating very primitive friction. To avoid glitches, where the ball goes beyond the world dimensions and doesn’t come back, the position gets updated to move it back inside the defined limits.

Now that we’ve updated the velocity (and fixed the position in case of a collision), we can update the resulting position and output it:

// update position
this.position.x += this.velocity.x1;
this.position.y += this.velocity.x2;

// render
this.output.css({
	left: this.position.x,
	top: this.position.y
});

This adds the velocity components to the position of the ball, then uses inline styles to update the position in the DOM.

Next we’ll look at the setup and animation loop:

var balls = [];
balls.push(new Ball());

// animation loop
setInterval(function() {
	balls.forEach(function(ball) {
		ball.move();
	});
}, 25);

Here we create an array of balls and add one initial Ball. Then start an interval to at 25ms, which should give us about 40 frames per second (fps). To get more smooth 60fps, we’d have to go down to 16.5ms, which would also be even more CPU intensive then this becomes with lots of balls.

Inside the interval, we just loop through all balls and call the move method for each. In a proper game engine, this loop would separate the position updates from the rendering to ensure that, when frames get dropped, the game itself doesn’t slow down.

Up next, we’ve got the code to add new balls, with user controlled initial velocity:

var start;
$(document).mousedown(function(event) {
	start = new Point(event.pageX, event.pageY);
}).mouseup(function(event) {
	var end = new Point(event.pageX, event.pageY);
	var ball = new Ball();
	ball.position = end;
	ball.velocity = start.relative(end).scale(0.2);
	ball.move();
	balls.push(ball);
});

Here we bind mousedown and mouseup events, each time creating a Point object from the pageX and pageY event properties. In the mouseup handler, we then use the end point as the starting position for the new Ball object. Using Point’s relative method, we calculate a vector between those two points, scale it down and use it as the velocity for the new ball. That way, you can just click anywhere to add a new ball, or click, drag and let go to create one with intial velocity based on the drag. To get the ball animated along with the others, its added to the balls array.

With that we’re almost at the end. The last piece just clears all balls when pressing Escape:

$(document).keyup(function(event) {
	if (event.keyCode === 27) {
		balls.forEach(function(ball) {
			ball.remove();
		});
		balls.splice(0, balls.length);
	}
});

And that’s it! Thanks to Vector , we’ve got a pretty sane implementation, and a good starting point for further improvements. And there’s lots of potential:

  • Better friction simulation: Currently balls keep bouncing pretty often, they don’t slow down as much as they should after loosing some height.
  • More collision detection: Detecting collisions with other balls, the mouse or other objects would make the whole thing a lot more interesting.
  • Better collision detection: Currently collision detection just happens against a fixed position, not the actual ball’s dimensions. Taking the (rounded) borders into account would make things quite a bit more complicated, but also more realistic.
  • More moving objects with other shapes: Currently there’s just pixels bouncing around, even though they’re rendering as balls. Adding square objects both animated and static could make things a lot more interesting.
  • 3D: Moving from a 2D to a 3D simulation involves adding another component to both the Vecotor and Point class, and would add that third dimensions to each calculation, making especially the collision detection, already the most complex part, even more complex.

With this, I’ll get back to working on the basics for my flocking simulation.

What Is Happening To The jQuery Plugins Site?

Posted December 08, 2011 by Adam J. Sontag

For about a week, instead of hosting several hundred jQuery plugins and several thousand advertisements for laptop batteries, our plugins repository has been serving up a pretty pathetic message about spam and an allusion to some “new submission process.” This happened very suddenly, and we’re sorry to everyone who’s been inconvenienced. Please allow me a few minutes to explain what happened, where we’re headed, and how it impacts you. If you’re in a rush, here’s the short version .

The Backstory

A White Elephant Though the plugins site you’ve known and loved was a valuable tool when it was first set up, it gradually became something of a white elephant for the project. While powerful distribution tools like GitHub and npm have come to the fore, we’ve been stuck in an aging, CMS-oriented paradigm that frustrated developers and consumers of plugins alike. Many people moved onto alternative sources for finding and vetting plugins. Furthermore, the sites’s original implementors and maintainers had since moved on from active involvement within the jQuery project. While the team faced a steady stream of complaints about usability and a general lack of features, the site itself faced a veritable barrage of (several flavors of) spam. There was your standard, keyword-rich SEO garbage, but there was also something slightly more insidious: the batch posting of under-documented, demo-free plugins with links to paid download sites by third parties trawling for affiliate cash. While this wasn’t explcitly disallowed, it led to a terrible, confusing experience for users and gave the site the distinct sense that all was not on the up and up.

The Best Laid Plans…

Sensitive to all these problems, the team began drawing up requirements for a complete overhaul. We knew we wanted to get out of the business of accepting uploads, serving downloads, and generally legislating the plugin “release” process on our own servers. With our official projects already on GitHub, we knew we wanted to leverage the many wheels they’d already invented for distribution, versioning, and facilitating open, collaborative development. Another requirement was to create a standard schema for authors to clearly delineate dependencies, like which version(s) of jQuery a plugin supports, as well as other plugins and CSS assets it requires to be functional. We also wanted to introduce some quality control, with both passive mechanisms like requiring GitHub and a manifest file for distribution, as well as active ones like user ratings. Finally, we wanted a clean slate; with stricter requirements for submission, there could be no mass import of all the old plugins. We made a lot of progress preparing specifications, but hampered by a lack of resources and a number of other projects, we never were able to get too deep into the implementation phase. After all, the old site “worked!”

…Often Go Awry

Throwing the baby out with the bathwater

As the glut of spam grew worse and multiple reports started showing up on the jQuery Core bug tracker, I wanted to at least take some steps to wipe a bit of the spam and egg off our face. With newly provisioned access to the administrative tools on the site, I teamed up with the Drupal Views Bulk Operations module and set out to identify and delete spammers and their posts. Within a day or two, nearly 90% of the alleged “content” was gone from the site. I continued to monitor the situation over the ensuing days, and deleted spam as it came in. Unfortunately, I likely cast too wide of a net, and threw out several perfectly good babies with the bathwater. Even more unfortunately, I didn’t back up the database before I began this process. At this point, you can probably see where this story is headed. Later in the week, while I was attempting to delete four spam items, I was left completely horrified when the results of the operation reported that the remaining 10% — every single plugin remaining in the database — had been purged. All that remained was a year-old backup. Of course, I realize that this is a dreadful outcome, and I take full responsibility for it. If it helps, I am very receptive to hate mail and tweets reprimanding me for being irresponsible, unprofessional, or just stupid.

At this juncture, we were left with two choices.

  • Keep on kicking the can down the road: Restore from the old backup, losing a lot of data anyway, and have authors go through the painstaking process of re-uploading their plugins, even though the site was slated to be deprecated entirely anyway.
  • Use this glaring mistake as the impetus to hunker down, cleave from the past, and finally implement the site we’ve talked about for so long.

We’ve chosen the latter.

Nuts And Bolts

Over the past few days, we’ve started converting our plans into action, building out an infrastructure that’s backed by GitHub. There are two requirements for listing a plugin on the new site:

Success Kid is helping out as well

  • A valid package.json  file

    We’ve followed the lead of CommonJS and npm and created a schema for specifying dependencies, delivery, and other metadata of jQuery plugins. While the format is largely similar to those other projects, we’ve had to make some minor tweaks to account for some plugin-specific details.
  • At least one versioned release

    This means having tagged your release point(s) with a valid semantic version number (semver ) string.

We’ve pared down the submission and maintenance process to a single, one-time step: adding a post-receive hook to your plugin’s GitHub repository. Assuming your plugin meets the guidelines, a page will be created on the plugins site to present your usage and download information. We’ll keep track of new releases as you push them.

In The Interim

We recognize that the old site was still serving as an regular resource for a lot of people, especially newer jQuery users, who simply valued the existence of a central browsing location, despite its flaws. Though many experienced users had moved on to other sites, or relied on relationships with trusted authors and word of mouth, these can take time to develop. Until we’re able to launch the new system, we’re happy to direct you to several other directories and people who can help pick up the slack:

If, in the process of searching these or any other directories, you are directed back to the current site at plugins.jquery.com, typically a quick search for the author’s name and the plugin name will yield an alternative site where it was hosted. In addition, DailyJS just did a useful roundup of alternatives that goes into more detail.

Next Steps For Plugin Authors

If you’re a plugin developer who wants to make sure your plugins will be ready to go on day one (or even beforehand), you’ll want to make sure your plugins are up on GitHub, and then you’ll want to get started on creating your package.json files and making sure your versions are appropriately tagged. If you aren’t already familiar with Git and GitHub, then this is probably a very good time for you to take the plunge and get started . If you prefer another SCM system, you can look into setting up a mirror to git from svn or hg , or other project hosting sites, like bitbucket or gitorious . If you don’t develop your plugins as open source, or you don’t use any source control at all, we will not be able to accomodate you at this time.

How Can I Help?

Though the site is still a work in progress, you can track progress and even set up your own local development right now at github.com/jquery/plugins.jquery.com/ . We’re still working on getting a public staging environment together.

Though the site is essentially “powered by” GitHub, there are obviously a number of moving parts in play. The site will actually be served from inside of WordPress, which is populated with the contents of the indexed plugins using a node.js tool. There are still many kinks to be ironed out, so if that sounds like a stack you want to jump on, please join us over at the repo . We’ll be using GitHub Issues for all feature requests, bugs, and discussion.

While we’ve put a great deal of thought into putting together our package.json schema, it’s still a living document, and if you have questions or comments on why it is the way that it is, head on over to this issue .

Errata

In an ideal world, this certainly wouldn’t have happened exactly as it did. Sadly, it did. We hope you’ll accept our apologies for the many ways this transition might make your job harder, give you some extra work you weren’t expecting, or just plain leave a bad taste in your mouth. If you are able to forgive us, bear with us, and maybe even lend a hand, we’re confident we’ll be able to deliver the modern, useful plugins site the community deserves.

TL;DR

So that was a lot of words, here’s the takeaway.

  • We’d been planning on replacing the original, spam-ridden plugin site for quite some time
  • In the process of deleting on the spam, all the plugins were deleted and we didn’t have a recent backup
  • Instead of burning cycles keeping the old site on life support, we decided to make a clean break and kick development on the new site into high gear.
  • The new site is powered by GitHub and a package manifest for plugins
  • Plugins from the old site were never going to be automatically imported into the new one.
  • The repo is at github.com/jquery/plugins.jquery.com
  • We are very sorry, but also very excited!

jQuery Conference 2012: UK – Training Workshops Announced

Posted November 29, 2011 by Ralph Whitbeck

We are very happy to announce two training workshops for this years United Kingdom conference . The trainings will be given by Doug Neiner , Ralph Whitbeck and Mike Hostetler of appendTo . The general admission tickets for the conference are now sold out but you can buy conference/training bundles and still attend the conference.

appendTo

appendTo will be giving Introduction to jQuery and jQuery Mobile workshops. The workshops will be held on Thursday, 9 February, 2012 at the Lady Margaret Hall in Oxford, UK.

Introduction to jQuery

jQuery has become the most popular JavaScript library for developers because of it’s easy to learn and write. This course takes students through the basics of jQuery focused front-end development. This material is meant to establish a core foundation for developers. With a solid basis of jQuery and JavaScript understanding a developer will feel confident that they can add richness to their web applications.

jQuery Topics Covered*

  • Introduction
  • Find Something, Do Something
  • The jQuery Function
  • The jQuery Object
  • Events/Ajax/more…

* Topics subject to change

Price for the Introduction to jQuery workshop is £320 + VAT which includes a conference pass, £160 + VAT for just the training.

jQuery Mobile

jQuery mobile has gained undeniable press as a possible great solution to mobile web development. With a progressive enhancement approach jQuery mobile aims to allow a mobile web experience for all, while rewarding those with mobile devices capable of a rich experience.

This training will cover a comprehensive review of the jQuery Mobile Framework, walking through all of its new features and functionalities available to build robust and cross-platform mobile sites. The entire API will covered along with examples of how to use each component to its fullest potential.

The training concludes with a walk through of the construction of a jQuery Mobile application from scratch, all the way through to compiling a native version of the application with PhoneGap.

Topics Covered*

  • The state of the mobile web
  • jQuery Mobile Feature Overview
  • Building a jQuery Mobile application from scratch
  • Go native with jQuery Mobile + PhoneGap

* Topics subject to change

Price for the jQuery Mobile workshop is £420 + VAT which includes a conference pass, £270 + VAT for just the training.

The training workshops will be held on 9 February, 2012 at the Lady Margaret Hall and not at the Saïd Business School where the conference will be held.

Call for jQuery 1.8 Ideas

Posted November 22, 2011 by dmethvin

We’re ready for our next round of community input, this time for version 1.8! This is your chance to suggest things we can fix, add, change, or remove in jQuery to make it better.

You can add a suggestion using this form ; whenever possible provide links to a bug report, a page with a detailed description, or implementations that represent your idea. We’d like to have all your input by December 5 so we can read and discuss them before setting the 1.8 roadmap.

Many thanks for the suggestions left on our earlier blog post about how we can improve jQuery by trimming it down. We’ve gone through those comments and have a few thoughts about how we can address some of them in future versions.

Create a configurable download builder

Several people wondered why we don’t have a way to build a file with just the parts of jQuery you need, since jQuery UI, for example, has that option. It’s not quite the same situation. You know if you are using, say UI Accordion because you call it directly. You often do not know if you or some plugin you include on your page is using $.fn.prepend() or $.fn.animate(). Whether you are using them may even depend on parameters you pass to plugins at runtime.

To keep jQuery development manageable and ensure that CDNs can offer a single file that everyone on the Internet can share and cache effectively, the team wants to stay with a single file as its primary offering. Creating a configurable download may improve file size marginally, but it also complicates documentation, plugin use, and debugging. That is a lot more work for both you and us.

We’re already beginning the efforts to improve modularity by eliminating unwanted dependencies inside jQuery; many of the deprecated features we announce will be directed towards removing those dependencies. By laying that groundwork, others who want to create their own smaller subsets of jQuery or modular versions should have a much easier job.

However, we believe we can do even better than that, and would like to offer automated ways for any user to create an optimally minimized file that includes both application code and just the needed parts of jQuery. In particular, we are working with the Google Closure Compiler team to see if we could use its ADVANCED_OPTIMIZATIONS option. We’ll have more information on our progress as it develops.

Wait until version 2.0 before removing things

We’re sensitive to breaking all the existing jQuery code out there. That is why we are deprecating things as early as possible, so that people have plenty of time to change their code. Just because we deprecate something today, it does not necessarily mean we’ll remove it in the next version. We believe the list of things actually being removed in 1.8 are minor and unlikely to affect most users.

If our experiments with Closure Compiler pan out, we may even be able to leave in many deprecated features but they will be automatically removed if you don’t use them and build a custom application file that includes jQuery. That would be the best of both worlds.

Remove IE 6, 7, and/or 8 support

This topic comes up constantly, so let’s try to put it to bed once and for all. People tend to greatly overestimate the amount of code in jQuery that is specifically related to IE. Most of the problems in IE 6 and IE 7 are also present in IE 8, so there is no real size or complexity benefit to dropping support for the first two as long as that last one still has appreciable desktop market share and must be supported. Nobody (including Microsoft itself) likes these Jurassic Park browsers, but stripping out support for them right now would break web sites for many users.

That said, we know that older-IE support is not required in some scenarios such as mobile browsers. We are looking into ways to put as much of that code as possible into a single clearly marked block so that it can be easily removed by someone who is willing to create their own custom jQuery version. It may also be possible to get Closure Compiler’s help with this issue as well. However, we are not sure that will even provide a significant space savings in gzipped file size, and it won’t offer a performance boost since those code paths aren’t taken in other browsers.

Remove jQuery.browser

We have documented for nearly two years that we intend to move jQuery.browser into a plugin, and several people suggested it in the comments as well. Browser sniffing is not a reliable way to look for features, we recommend something like Modernizr instead. The regular expressions used for browser sniffing are large and don’t compress well; moving it to a plugin will ensure that only the people who use it must pay that size penalty.

What about your ideas?

Please do take this opportunity to give us your input. The team is looking forward to reviewing your suggestions. Oh, and don’t forget to try jQuery 1.7.1 soon!

jQuery 1.7.1 Released

Posted November 22, 2011 by dmethvin

Here in the United States, we’re celebrating Thanksgiving this week. For those of you living elsewhere in the world, it’s a time when we install and test new versions of Javascript libraries while feasting on Mom’s homemade goodies. Kind of like a code sprint, but with better food. We invite everyone worldwide to join us in these traditions.

To kick off the festivities, the jQuery Team is quite thankful to be releasing version 1.7.1! In this go-round we made Pilgrim’s progress on a cornucopia of bugs, listed below. We are serving up our delicious copies on the jQuery CDN, fresh and warm from the oven:

These latest files should also be up on the major CDNs shortly, but please be patient since this is a holiday week for them as well.

Please install and test this latest slice of jQuery with your code. We hope you’ll find it tasty. If we forgot to fry some turkey of a bug, we want to hear about it. Just put together a specific test case for the problems you’ve found (we love jsFiddle.net for that) and create a bug report at bugs.jquery.com .

Also, please welcome new jQuery Core team member Mike Sherov! We’re thankful to have his help for all the great things we have planned for upcoming versions. Mike has a full-time job at SNAP Interactive in New York City, but contributes to the project in his spare time. Please Be Like Mike and pitch in to help the project any way you can. It doesn’t have to be coding. We can always use help in answering questions on the forum or just reproducing and identifying the source of obscure bugs reported on the bug tracker. See our Getting Involved page for information.

We’ll be opening the call for 1.8 suggestions in just a day or two. Take a look at the 1.7.1 release and think about what kind of awesome sauce we can put on top of it for the next big one!

jQuery 1.7.1 Change Log

The change log of the 1.7.1 release.

Ajax

  • #10723 : jqXHR.always() returns a Promise instead of a jqXHR object

Attributes

  • #10724 : $(document).text() always returns an empty string
  • #10773 : removeAttr is fragile for edge cases

Build

  • #10630 : Fix focus-related test failures to resolve Swarm failures

Core

  • #10616 : Type coersion not done for -1 in .eq
  • #10646 : Have jQuery.error throw instanceof Error object
  • #10682 : Creating DOM elements with $(‘ ‘) leaks memory and skips the fragment cache
  • #10687 : jQuery calls the AMD define() global function too early
  • #10690 : isNumeric

Css

  • #10733 : remove uses of jQuery.each in css module in favor of a for loop

Data

  • #10675 : Use internalKey shortcut instead of jQuery.expando

Effects

  • #10669 : .animate() no longer animates percentage(%) width
  • #10750 : A “null” in the data object can cause an error in stop

Event

  • #10676 : wheelDelta not added to mousewheel event anymore
  • #10701 : Problems with submit forms using submit function
  • #10704 : special.handle method should fire under origType name
  • #10705 : off bug event name parser
  • #10712 : Triggering blur with live bind broken
  • #10717 : A triggered load bubbles up to window
  • #10791 : Delegated Events fail on SVG elements
  • #10794 : .triggerHandler should not .preventDefault()
  • #10798 : live(“submit”) and .submit() would cause unobtrusive ajax live to fire twice
  • #10844 : .delegate() on submit doesn’t work when form contains input with name “id”

Manipulation

  • #10177 : index of callback function in .wrap is always 0
  • #10667 : HTML5 Support in .wrapAll() does add a “:” to element
  • #10670 : rnoshimcache probably not constructed correctly
  • #10812 : passing empty object to .before() or .after() throws exception in IE7

Misc

  • #10691 : remove all occurrences of the “equals” and “same” function in the unit tests`

Support

  • #10629 : IE is much too sensitive concerning the fake body. Explore cleaning up support.js to avoid any future crashes.
  • #10807 : Non-ascii apostrophe in comment

Getting Board of jQuery

Posted November 18, 2011 by Adam J. Sontag

TL;DR The body responsible for overseeing jQuery’s finances and administration, which was until today known as the jQuery Team, is now called the jQuery Board. The jQuery Team is for anyone who invests a significant amount of time contributing to jQuery and its related projects.

As jQuery has grown from a cool idea in 2005 to the most widely used piece of JavaScript on the Internet today , so too has the organizational structure required to support its development and its community. Over time, e-mail chains became mailing lists, and out of those lists evolved a casual confederation known as the jQuery Team. To join this team, all you had to do was make a consistent contribution to some aspect of the project and eventually John would add your name to a page in our docs wiki.

By 2009, the team wanted to solidify the long-term future of the project, so we accepted an invitation to join the Software Freedom Conservancy , from whom we’ve since received great amounts of administrative and legal support. Though the SFC offers that “Projects can continue to operate in the same way they did before joining the Conservancy without having to select a board of directors or any other layer of corporate management,” the team chose to implement a governance system whereby the project’s official decisions would be communicated to the Conservancy after a public vote by the members of the “core team,” which initially had 21 members. This conferred a significant amount of formality onto what had been a relatively ad hoc process, and while the system has worked well, it has been accompanied by some confusion.

  • On one hand, there’s the voting membership, responsible primarily for financial and managerial decisions concerning the entire project. On the other, there’s an actual group of people who are working on jQuery Core itself. Both of these groups are sometimes called the jQuery Core Team, which is fairly misleading.
  • As new people come along and become active contributors to some part of the project, it’s not fun to tell them, “Hey, great job, but you’re *not* on the team!”
  • Just because you are really interested in hacking on jQuery Core, UI, or Mobile (or working on docs, or any of the many other ways you can help out the project) doesn’t mean you have the slightest desire to sit in long meetings, discussing how to allocate funds and how to improve beverage service at the next conference.
  • As people’s lives ebb and flow, it’s normal that their capacity to contribute changes. What’s the right correlation between being a genuinely active contributor in the present tense and having a vote in the project’s big-picture management?

In order to attempt to resolve some of this confusion and make clearer the group’s purpose, the jQuery Team is now known as the jQuery Board , and all the governance rules that applied to the Team now apply to the Board. The Board is responsible for

  • approving and appropriating expenditures
  • representing the intentions of the jQuery Project to the SFC
  • overseeing and directing the Subteams and selecting the Subteam Leads responsible for each of the facets of the project
  • voting on its own composition

If you’ve always wanted to be “on the team,” but were unsure of what it meant or what you would do, this is good news! We’re fully embracing the Wikipedia definition of team : a group of people (or animals!) linked in a common purpose. As such, anyone who volunteers, over a sustained period of time, to serve actively on a jQuery Subteam will be invited to join the jQuery Team (at the discretion of the Subteam Lead), so you can feel good putting that on your slide decks, refrigerators, and so forth.

What isn’t changing is the fact that if you are passionate about web development and trying to find a way to make a difference to developers around the world, there is a place for you in the jQuery community. Hop onto the forum and give another developer a hand. Head over to our various bug trackers and help triage the open issues — or dive in and see if you can provide a patch . If you just want to get a lay of the land, join the weekly IRC meetings . Want to work on a particular project? Take a look through the updated team page and get in touch with the right subteam lead! One thing’s for sure:

jQuery wants you!

jQuery 1.7.1 RC1 Released

Posted November 18, 2011 by dmethvin

Just to let you know we’re not asleep at the switch around jQuery Central, we’ve got a new preview release of jQuery. It fixes the problems reported by the community since the original 1.7 release. Please test the code in your applications, making sure that there are no major problems. If you tried jQuery 1.7 and reported a bug, it should be fixed in this release.

You can get the code from the jQuery CDN:

You can help us by dropping that code into your existing application and letting us know that if anything no longer works. Please file a bug and be sure to mention that you’re testing against jQuery 1.7.1 RC1.

We want to encourage everyone from the community to try and get involved in contributing back to jQuery core. We’ve set up a full page of information dedicated towards becoming more involved with the team. The team is here and ready to help you help us!

jQuery 1.7.1 RC1 Change Log

The current change log of the 1.7.1 RC1 release.

Ajax

  • #10723 : jqXHR.always() returns a Promise instead of a jqXHR object

Attributes

  • #10724 : $(document).text() always returns an empty string
  • #10773 : removeAttr is fragile for edge cases

Build

  • #10630 : Fix focus-related test failures to resolve Swarm failures

Core

  • #10616 : Type coersion not done for -1 in .eq
  • #10646 : Have jQuery.error throw instanceof Error object
  • #10682 : Creating DOM elements with $(‘ ‘) leaks memory and skips the fragment cache
  • #10687 : jQuery calls the AMD define() global function too early
  • #10690 : isNumeric

Css

  • #10733 : remove uses of jQuery.each in css module in favor of a for loop

Data

  • #10675 : Use internalKey shortcut instead of jQuery.expando

Effects

  • #10669 : .animate() no longer animates percentage(%) width
  • #10750 : A “null” in the data object can cause an error in stop

Event

  • #10676 : wheelDelta not added to mousewheel event anymore
  • #10701 : Problems with submit forms using submit function
  • #10704 : special.handle method should fire under origType name
  • #10705 : off bug event name parser
  • #10712 : Triggering blur with live bind broken
  • #10717 : A triggered load bubbles up to window
  • #10791 : Delegated Events fail on SVG elements
  • #10794 : .triggerHandler should not .preventDefault()
  • #10798 : live(“submit”) and .submit() would cause unobtrusive ajax live to fire twice

Manipulation

  • #10177 : index of callback function in .wrap is always 0
  • #10667 : HTML5 Support in .wrapAll() does add a “:” to element
  • #10670 : rnoshimcache probably not constructed correctly
  • #10812 : passing empty object to .before() or .after() throws exception in IE7

Misc

  • #10691 : remove all occurrences of the “equals” and “same” function in the unit tests`

Support

  • #10629 : IE is much too sensitive concerning the fake body. Explore cleaning up support.js to avoid any future crashes

Upcoming jQuery Events

Posted November 11, 2011 by Addy Osmani

jQuery Summit 2011

It’s that time of the year again (no, not Christmas!, something almost better!) – the annual (online) jQuery Summit . This year Environment For Humans (E4H) have a terrific line-up including sessions on jQuery plugin authoring best practices, creating interactive experiences with HTML5 and Popcorn.js and best practices for testing your jQuery code amongst others.

With some of the web’s most experienced jQuery and JavaScript professionals on board to share tips, tricks and their own experiences, you’ll be sure to learn something new that could help with your own projects. If you haven’t attended the summit before, you’re in for a real treat.

The summit is a completely online two-track conference run across two days with a track dedicated to designers and another focused completely on developers. As the event is all online, you can access it live whether you’re at home or in the office. For those worried about missing anything, E4H have you covered; all tickets include high-quality recordings that can be played back at your leisure later on.

Discount:

If you’re interested in attending, E4H have provided us with a very special 20% off discount code which can be redeemed on their event site. Just enter in 20JQUERY when purchasing your ticket or use the following link: http://jquerysummit2011.eventbrite.com/?discount=20JQUERY .

Details:

Sessions:

  • jQuery & CSS Selectors – Estelle Weyl
  • jQuery & HTML5 Video – Rick Waldron
  • jQuery UI – Andrew Wirick
  • Plugin Authoring Best Practices – Ben Alman
  • jQuery & Browser Plugins – Sarah Chipps
  • Progressive Enhancement – Nicholas Zakas
  • jQuery & Responsive Web Design – Dave Rupert
  • The State of jQuery – Adam Sontag
  • Large-scale Application Architecture – Addy Osmani
  • jQuery & iframe Programming – Ben Vinegar
  • Structuring Your DOM-based Application – Garann Means
  • Deferreds into jQuery – Dan Heberden
  • jQuery Development Workflow – Anton Kovalyov
  • jQuery & Backbone.js – Matt Kelly
  • jQuery & QUnit – Ben Alman

Tickets: http://jquerysummit.com .

Dates:

Designer track: Tuesday, November 15th

Developer track: Wednesday, November 16th

 

jQuery Training At Bocoup

For those that prefer in-person training, group training is one of the best ways to improve your jQuery skills. Luckily, Boston-based Bocoup has a number of such comprehensive jQuery trainings scheduled for both January and March 2012.

Sessions will be held at The Bocoup Loft in Boston, and 10% of profits will go directly to the jQuery Foundation. If interested, be sure to sign up now since class sizes are limited!.

For more information, checkout http://training.bocoup.com/comprehensive-jquery/

 

Frontend Workshops in HTML5, JavaScript and jQuery

Finally, if you’re interested in learning more general frontend skills, Marc Grabanski is hosting a Frontend Masters Workshop Series for developers looking to earn a mastery in the arts of frontend development.

The training is composed of six workshops that will focus on frontend topics including jQuery, jQuery UI, HTML5 & CSS3, Titanium Mobile and building large JavaScript applications with speakers including jQuery team members Karl Swedberg and Scott Gonzalez.

For tickets and more information, see http://frontendmasters.com .

Building a Slimmer jQuery

Posted November 08, 2011 by dmethvin

jQuery is more than five years old now! Over that time it has evolved along with the browsers, web sites, devices, developers, and users that it serves. It has also, um, grown quite a bit over that time. jQuery has added a lot of useful features, but it’s also accumulated cruft that we’d prefer not to support into perpetuity. It may not be an issue on a desktop PC with a high-speed connection, but we want jQuery to be a good solution for mobile devices as well.

Along with our continuing push for higher performance, our priority for upcoming versions is a smaller gzipped file size. It’s hard to do that when every new feature or bug fix must also preserve all existing features and behavior. So today, we want to start a conversation about slimming down the jQuery API by deprecating some features. Here are our guidelines for deprecation:

  • We don’t believe the feature represents current best practice in the use of jQuery.
  • The feature has proven unpopular, confusing, inefficient, or ineffective in actual use.
  • It is not practical or feasible to enhance the feature or address its limitations.
  • Removing it at some future time could yield notable usability, size, or performance benefits.

Deprecation is just the first step in a process that you can participate in. It is our goal to:

  • Explain the reasons for deprecating a particular feature, as described above.
  • Give at least one major-point-version, and often more, between deprecation and removal.
  • Provide alternatives to deprecated features so that migration is not painful.
  • Listen to community feedback regarding deprecation and removal.

Occasionally, as in the situation with event.layerX/layerY in version 1.7, we will make a breaking change with shorter notice if we judge that it will cause less pain to remove the feature immediately than to leave it in. Those will hopefully be rare exceptions.

Version 1.7 Deprecations

With those things in mind, we consider the following features to be deprecated as of version 1.7. Existing code that uses them continues to work, but the recommended alternatives are a better choice for compatibility with future versions.

.live() and .die() : We continue to get many bug reports and see user confusion regarding the quirks of the .live() method. Common issues are now documented on its updated API page . We strongly advise the use of .on() or .delegate() for new code, since they are better APIs. Given its widespread use it’s unlikely we will remove this API in 1.8, but please do update your code as soon as possible.

Non-standard event properties: As part of our push to improve event handler performance, we are also deprecating the copying of several event properties from the native event object to the jQuery event object and will remove them in 1.8: attrChange, attrName, relatedNode, and srcElement. Instead of accessing these through event.NAME you can access them via event.originalEvent.NAME where needed.

$.ajax() Deferred aliases: In version 1.5 we defined .error()/,success()/.complete() on the jqXHR object as aliases for the Deferred’s .fail()/.done()/.always() methods. Although that seemed like a good idea at the time, it makes jqXHR a non-standard Deferred. That’s not good. Whenever possible, use the deferred/promise method name in preference to the jqXHR one. We still have some work to do here to provide a full migration path, so we are likely to continue supporting the aliases past 1.8.

deferred.isResolved() and deferred.isRejected(): Now that Deferreds and Promises have progress notifications and a convenient .state() method, we are deprecating these older methods and will remove them in 1.8. Getting the state of an N-state object using N-1 Boolean methods is a cruel-code version of “Twenty Questions”. Deferred-based code rarely needs to inspect state, and the string returned now is more convenient for a debugging scenario where it’s often used.

.attr(“value”) on inputs: For backwards compatibility, we’ve been returning the current value here (as in “what is currently in the input box”) versus the real attribute (what the value attribute says in the HTML). That leaves us no way to provide the true attribute value, and is confusing since W3C selectors work on the attribute and not the current value. So we are deprecating this behavior and will remove it in 1.8. Always use the .val() method to get the current live value of an input element. Until we can reclaim the attribute, you can use $("selector")[0].getAttribute("value") except on IE 6/7 where that will still return the current value. (Our 1.8 solution will get the attribute value on all browsers and is another reason why we’re anxious to change this.)

.closest(Array) returning Array: This signature is a bit of a strange bird, it was created for use by the old live events code but it returns an Array rather than a jQuery object. As of 1.8 we plan to remove it. The other signatures of .closest() are here to stay and are not affected.

.data(“events”): jQuery stores its event-related data in a data object named (wait for it) events on each element. This is an internal data structure so in 1.8 this will be removed from the user data name space so it won’t conflict with items of the same name. jQuery’s event data can still be accessed via jQuery._data(element, "events") but be aware that this is an internal data structure that is undocumented and should not be modified.

$.sub() as a plugin: Although $.sub() can be useful for creating interference-free zones for plugins, it is not used by jQuery core and not widely used by other code, so we intend to transition it to a plugin in version 1.8 to save space.

Looking Towards jQuery 1.8

Given our push for a svelte jQuery, the filter for new features in 1.8 will be stringent. Even performance-related proposals need to be balanced against the space they use or save. Features that can be implemented via plugins, special events, attribute hooks, or other jQuery extension mechanisms are likely to stay outside core for now.

That brings up the question of what we could deprecate in 1.8 and eventually remove to simplify and streamline the library. Those things don’t have to totally disappear; they could move into a separate plugin, for example, and only be included when needed. Take a look at how you use jQuery, and talk about it with your colleagues.

Within a few weeks, we’ll be opening the call for your ideas concerning jQuery 1.8 with another blog post — so start thinking about it now!

Edit: No, we’re not removing IE6 support yet, and we can’t. As John Resig mentions at every jQuery Conference, most of the sins of IE6 are also visited upon IE7 and IE8, which together still have more than one-third of desktop browser market share. It doesn’t make sense to remove support for IE6 until we can whack IE7 and IE8 as well.

jQuery 1.7 Released

Posted November 03, 2011 by dmethvin

jQuery 1.7 is ready for download! You can get the code from the jQuery CDN:

This new release should also be available on the Google and Microsoft CDNs within a day or two.

Thanks to your help in testing and reporting bugs during the beta period, we believe we have a solid, stable release. If you do find problems, file a bug and be sure to choose jQuery 1.7 in the version selection. Also be sure to provide a jsFiddle test case so we can quickly analyze the problem.

pre { padding: 4px; }

What’s New in jQuery 1.7

The Version 1.7 tag at the API site is a great way to get up to speed with the new things in this release. Here’s a rundown of the big items in 1.7 and some things not yet mentioned in the API docs.

New Event APIs: .on() and .off()

The new .on() and .off() APIs unify all the ways of attaching events to a document in jQuery — and they’re shorter to type!

$(elements).on( events
 [, selector
] [, data
] , handler
 );
$(elements).off( [ events
 ] [, selector
] [, handler
] );

When a selector is provided, .on() is similar to .delegate() in that it attaches a delegated event handler, filtered by the selector. When the selector is omitted or null the call is like .bind() . There is one ambiguous case: If the data argument is a string, you must provide either a selector string or null so that the data isn’t mistaken as a selector. Pass an object for data and you’ll never have to worry about special cases.

All the existing event binding methods (and their corresponding unbinding methods) are still there in 1.7, but we recommend that you use .on() for any new jQuery project where you know version 1.7 or higher is in use. Here are some examples of mapping between the old and new API calls:

$('a').bind('click', myHandler);
$('a').on('click', myHandler);

$('form').bind('submit', { val: 42 }, fn);
$('form').on('submit', { val: 42 }, fn);

$(window).unbind('scroll.myPlugin');
$(window).off('scroll.myPlugin');

$('.comment').delegate('a.add', 'click', addNew);
$('.comment').on('click', 'a.add', addNew);

$('.dialog').undelegate('a', 'click.myDlg');
$('.dialog').off('click.myDlg', 'a');

$('a').live('click', fn);
$(document).on('click', 'a', fn);

$('a').die('click');
$(document).off('click', 'a');

Improved Performance on Delegated Events

Event delegation has become increasingly important as size and complexity of pages grow. Application frameworks such as Backbone, JavaScriptMVC, and Sproutcore make heavy use of event delegation. With that in mind, jQuery 1.7 event handling was refactored with an eye to making delegated events much faster, especially for the most common cases.

To optimize the code for the most commonly used forms of selectors, we examined a cross-section of code from Google Codesearch. Nearly two-thirds of the selectors used in .live() and .delegate() method calls were in the form tag#id.class where one or more of tag, id, or class were used. By parsing those simple selectors in JavaScript at the time the event was attached, we were able to outperform even the browser’s native-code implementations of matchesSelector during event delivery. For more complex selectors we still use the Sizzle engine, so all existing code should continue to work.

The final result is that delegated events are delivered in about half the time they took in 1.6.4:

Better Support for HTML5 in IE6/7/8

Anyone who has tried to use the new HTML5 tags such as <section> has no doubt run across the problem that IE 6/7/8 not only don’t understand these tags, they actually remove them from the document. With jQuery 1.7 we built in support for using HTML5 tags in older IEs with methods like .html() . This support is on par with what previously required innerShiv . You must still include html5shiv (or Modernizr) in the head of your document in older IEs for HTML5 tag support. For more background, see The Story of the HTML5 Shiv .

Toggling Animations Work Intuitively

In previous versions of jQuery, toggling animations such as .slideToggle() or .fadeToggle() would not work properly when animations were stacked on each other and a previous animation was terminated with .stop() . This has been fixed in 1.7 so that the animation system remembers the elements’ initial values and resets them in the case where a toggled animation is terminated prematurely.

Asynchronous Module Definition (AMD)

jQuery now supports the AMD API . Note that jQuery 1.7 is not a script loader itself; it cooperates with AMD-compliant loaders such as RequireJS or curl.js so it can be loaded dynamically and the ready event can be controlled by the loader. Now an AMD-compliant loader can load an unmodified version of jQuery 1.7 from a CDN such as Google’s or Microsoft’s. Many thanks to James Burke (@jrburke) for submitting the patch and unit tests, then waiting patiently for us to incorporate it.

jQuery.Deferred

The jQuery.Deferred object has been extended with new progress handlers and notification methods that call those handlers. This allows you to asynchronously notify listeners of progress in a request without resolving or rejecting the request. In addition, there is a new state() method that returns the current state of the Deferred; it’s primarily useful for debugging.

Deferreds are now implemented using a new jQuery.Callbacks feature, a generalized way of queueing and triggering a series of handlers. This feature may be of interest to plugin writers, although Deferreds and the event subsystem provide a higher-level interface for this type of functionality.

jQuery.isNumeric()

Inside jQuery we’ve found several situations where we need to know if an argument is numeric, or would be successfully converted to a number if it is some other type. We decided to write and document jQuery.isNumeric() since it’s a useful utility. Pass it an argument of any type and it returns true or false as appropriate.

Removed Features

event.layerX and event.layerY: We have removed these non-standard properties in version 1.7. Although we normally would have gone through a deprecation notice period for these, Chrome version 16 generates a flood of console warning messages on the page. Because of this, we decided to remove them immediately. On platforms that still support these properties, they are available through event.originalEvent.layerX and event.originalEvent.layerY .

jQuery.isNaN(): This undocumented utility function has been removed. It was confusing because it appropriated the name of a built-in JavaScript function but did not have the same semantics. The new jQuery.isNumeric() serves a similar purpose, but has the benefit of being documented and supported. Despite jQuery.isNaN() being undocumented, several projects on Github were using it. We have contacted them and asked that they use jQuery.isNumeric() or some other solution.

jQuery.event.proxy(): This undocumented and deprecated method has been removed. Users should be calling the documented jQuery.proxy method instead.

The jQuery Team, and Your Part

I want to recognize the incredible work of our regular team contributors in getting this release out the door, especially Timmy Willison (timmywil on Github), Corey Frang (gnarf), Rick Waldron (rwldrn), and Julian Aubourg (jaubourg). Karl Swedberg (kswedberg) and Addy Osmani (addyosmani) worked hard on getting the new documentation into shape on the API site. Also, thanks to Mike Sherov (mikesherov), a greenhorn contributor who has already created patches for several tricky bugs. Many thanks to all the others who reported bugs, submitted pull requests, reviewed commits, and in other ways made sure we did the best job we possibly could.

Still, we can always use more help, and that is where you can contribute. The simplest and most important thing you can do is occasionally test our work-in-progress against your code and your expectations. It's always located at http://code.jquery.com/jquery-git.js and a fresh copy is built each time a new commit is made to our master branch at github.com . If you find a bug in a final release, test against jquery-git.js to see if it's already been fixed. It's easy as pie since jsFiddle.net offers an option to test your code with the jquery-git.js file as "jQuery (edge)".

If you'd like to do more, we'd be glad to have you pitch in! We've written a document that can get you started with the process, and one or more of us are generally available in the #jquery-dev channel on IRC if you need more help or information.

jQuery 1.7 Change Log

The current change log of the 1.7 release.

Ajax

  • #9399 : Deprecate jqXHR.success and jqXHR.error

Attributes

  • #5479 : removeAttr: remove multiple attributes
  • #6743 : map enctype to encoding, depending on browser
  • #10176 : Injected script tag is evaluated twice
  • #10278 : checkboxEl.attr('checked') returns stale value after checkboxEl.click()
  • #10429 : IE7 - invalid procedure call or argument when calling removeAttr('contenteditable');
  • #10514 : removeAttr does not remove the class attribute in IE6/7

Core

  • #6485 : Solution for HTML5 in IE
  • #7102 : Register jQuery as a CommonjS async module
  • #9453 : $.inArray does not support fromIndex
  • #10478 : Switch jQuery.isNaN to jQuery.isNumeric

Css

  • #10267 : IE8 and window is(':visible') crashes

Data

  • #7323 : Allow removing multiple data keys at once with $.fn.removeData
  • #8909 : $(element).data() will scan all attributes more than needed.
  • #8921 : jQuery private data should stay private

Deferred

  • #8856 : Request: deferred.isUnresolved()
  • #9033 : try{ } finally{ } error in IE8
  • #9398 : Proposal for Improved Deferreds

Dimensions

  • #9434 : .outerWidth()/.outerHeight()/.innerWidth()/.innerHeight() should work on window and document

Effects

  • #5684 : Effects: exception in animation callback causes endless loop
  • #6150 : .stop sometimes doesn't clear .delay
  • #6641 : Calling stop() within animation finished callback causes other animations to freeze
  • #8685 : Animations should keep track of animation state in order to properly address stacked animations
  • #9280 : Allow multiple effect queues for animate()
  • #9548 : animate does not work with fill-opacity css property for svg elements
  • #10445 : Setting queue to true causes an error
  • #10497 : .stop should allow choosing which queue to stop
  • #10622 : .show() does not properly restore CSS-set "display" value

Event

  • #3368 : event.metaKey should be assigned to event.ctrlKey on Non-Mac only
  • #6170 : jQuery(window).scroll(); causes IE* to scroll to 0,0
  • #6319 : Regression: stopPropagation inside change handlers in IE is incorrectly applied to keydown event
  • #6386 : support data argument for live events via "event.special.live.add"
  • #6593 : IE8: DOM 0 event handler called twice when a separate handler is attached via jQuery
  • #6667 : submit event doesn't delegate in IE* under certain conditions
  • #6903 : special events need a way to determine whether they are being bound with .bind vs .live/.delegate
  • #6942 : JQuery.event.fix causes unnecessary reflows in IE when handling key events
  • #7139 : "hover" event alias should work for .bind as well as .live
  • #7161 : Submit event on a form element not unbound properly in IE
  • #7444 : Submitting form with "Enter" instead of button click on ie8 or ie7 triggers live submit event twice.
  • #8157 : Focusing an already focused text field will prevent the change event from firing in IE
  • #8728 : Event 'mouseenter' not firing when the element being left is removed on leaving
  • #8789 : Meta: Event Property Hooks
  • #8858 : Special events - _default method doesn't have access to the `data` argument of the trigger method
  • #8866 : IE8 input[type=file] delegated change event files only on blur
  • #8982 : bind("unload someOther") => on unload, handler is not executed only once.
  • #9069 : when hover over a child of an element, mouseleave fires when using live or delegate
  • #9279 : delegate() bind does not handle mouseover/mouseout and mouseenter/mouseout correctly for selected elements
  • #9393 : Unify and DRY out event system
  • #9593 : Delegated submit event is not instanceof jQuery.Event in IE
  • #9724 : Infinite loop in trigger function when window.parentNode is a DOM element
  • #9901 : event.handleObj.namespace incorrect when using .delegate
  • #9933 : jQuery.fn.toggle() should store state in private data object
  • #9951 : Wrong order in .trigger() when DOM is modified in a handler
  • #10375 : Do not include `type` in jQuery.event.props
  • #10438 : Rename jQuery.event.propHooks => .fixHooks
  • #10468 : Remove deprecated jQuery.event.guid and jQuery.event.proxy
  • #10489 : Disconnected elements bubble to window on .trigger()
  • #10531 : Consider removing layerX and layerY from $.event.props
  • #10563 : jQuery.Event no longer contains the element that matched the selector in event delegation.
  • #10567 : Delegated events incorrectly match class names
  • #10575 : Breaking changes in live event propagation between 1.6.4 and 1.7rc1
  • #10576 : jQuery1.7rc1 and jQueryMobile1.0rc2 - IE gets error in jqm triggerCustomEvent method

Manipulation

  • #6782 : carefully allow more strings to use innerHTML
  • #7037 : Duplicate mouseover and mouseout events added to cloned element.
  • #10501 : HTML5 element "innerShiv" inconsistent across html()/append()

Misc

  • #10420 : MouseWheel
  • #10553 : Further reduction of minimal license header

Selector

  • #3144 : Inconsistent cross-browser results from .text() method
  • #5637 : Boolean (and Empty) Attribute Selectors Fail
  • #6863 : faster getText
  • #7128 : attribute selector is inconsistent between qSA and Sizzle due to use of DOM properties
  • #8539 : Sizzle cache collision in browsers without querySelectorAll
  • #9261 : Has Attribute not working in filter/children/siblings
  • #9570 : Selector $('form[name=".."]') returns zero elements in IE8 under some conditions
  • #10178 : $(window).is("a") >> Uncaught TypeError: Cannot call method 'toLowerCase' of undefined
  • #10315 : Sizzle ignores seed argument when using positional selectors
  • #10562 : siblings method returns unexpected elements when using Sizzle-invoking pseudo-selectors

Support

  • #5145 : jQuery.support.opacity = false in the Chrome browser
  • #6809 :

jQuery Conference 2012: United Kingdom Announced

Posted November 02, 2011 by Ralph Whitbeck

jQuery Conference 2012: UK

We are very happy to announce jQuery Conference 2012: UK , the first jQuery conference in the UK, on 10th February 2012. The conference will be held at the Saïd Business School in Oxford with a line-up including six jQuery team members and four industry experts:

Tickets

You can read more about the line-up, talks and location on the event site and tickets are on sale now at EventBrite.

Organizers

The event is being organized by Oxford based digital agency White October with the permission of the jQuery project and with the help and support from jQuery team members. Last year, the jQuery events team tried to put together an event outside the USA and we found how very hard it was to secure a venue from so far away. The jQuery Team is very happy to be working with White October in putting the conference together, and we hope to have you join as we make our European debut!

Sponsorship

If your company is interested in sponsoring the event please take a look at the sponsor pack , please feel free to email or phone (+44(0)207 976 4894) John at White October to discuss the different options.

jQuery 1.7 RC2 Released

Posted November 01, 2011 by dmethvin

Today, after a very scary Halloween, the jQuery team is releasing jQuery 1.7 RC2 from our Github crypt, er, repo. Barring a report of really terrifying problems or a mob of townspeople at our door with torches, this code will be exactly the same code that becomes the version 1.7 final. If anyone knows of any reason why this code should not become a final release, we need to hear you scream!

div.downloadlist { position: relative; height: 6em; } div.stone { float: right; width: 9em; margin: 0 0 1em 1em; font: bold 100% Arial, Helvetica, sans-serif; color: #fff; text-shadow: -1px -1px #000; padding: 20px 4px; background: #777; background-image: linear-gradient(bottom, #333 3%, #777 73%); background-image: -o-linear-gradient(bottom, #333 3%, #777 73%); background-image: -moz-linear-gradient(bottom, #333 3%, #777 73%); background-image: -webkit-linear-gradient(bottom, #333 3%, #777 73%); background-image: -ms-linear-gradient(bottom, #333 3%, #777 73%); border-top: 1px solid #888; border-left: 1px solid #888; border-right: 3px solid #000; border-bottom: 3px solid #000; border-top-left-radius: 40px; border-top-right-radius: 40px; text-align: center; } ul.download { list-style-type: none; font-size: 120%; }
HERE LIE THE

BITS FOR RC2;

PLEASE TELL US

IF IT WORKS

FOR YOU

In RC2, we fixed a tricky problem that sometimes caused Internet Explorer 8 to go full-zombie when jQuery was loaded. Appropriately enough, the crash was related to creating a detached <body> element that we were using to perform feature detection. IE8 seems frightened to a crashy death when it sees a detached body. If you still see any problems with IE8 crashes, please let us know.

Thanks to a bug report from @warrenparsons, we also fixed a frightful regression with the .show() method. We really appreciate the efforts from those of you who are testing these pre-release versions. Sure, it’s a lot easier to think, “I’ll try it when it’s finally released,” but then any problems you do find will be preventing you — and possibly hundreds or thousands of others — from upgrading. Now that is really scary, at least to us.

During the next day or so we’ll be conjuring up documentation for many of the 1.7 additions and improvements on api.jquery.com . Please bear with us for a few days while we clean up the pages and make sure that it is filled in and all linked properly. For a quick overview of what’s changed, see the 1.7 category .

jQuery 1.7 RC 2 Change Log

The current change log of the 1.7 RC2 release.

Ajax

  • #9399 : Deprecate jqXHR.success and jqXHR.error

Attributes

  • #5479 : removeAttr: remove multiple attributes
  • #6743 : map enctype to encoding, depending on browser
  • #10176 : Injected script tag is evaluated twice
  • #10278 : checkboxEl.attr(‘checked’) returns stale value after checkboxEl.click()
  • #10429 : IE7 – invalid procedure call or argument when calling removeAttr(‘contenteditable’);
  • #10514 : removeAttr does not remove the class attribute in IE6/7

Core

  • #6485 : Solution for HTML5 in IE
  • #7102 : Register jQuery as a CommonjS async module
  • #9453 : $.inArray does not support fromIndex
  • #10478 : Switch jQuery.isNaN to jQuery.isNumeric

Css

  • #10267 : IE8 and window is(‘:visible’) crashes

Data

  • #7323 : Allow removing multiple data keys at once with $.fn.removeData
  • #8909 : $(element).data() will scan all attributes more than needed.
  • #8921 : jQuery private data should stay private

Deferred

  • #8856 : Request: deferred.isUnresolved()
  • #9033 : try{ } finally{ } error in IE8
  • #9398 : Proposal for Improved Deferreds

Dimensions

  • #9434 : .outerWidth()/.outerHeight()/.innerWidth()/.innerHeight() should work on window and document

Effects

  • #5684 : Effects: exception in animation callback causes endless loop
  • #6150 : .stop sometimes doesn’t clear .delay
  • #6641 : Calling stop() within animation finished callback causes other animations to freeze
  • #8685 : Animations should keep track of animation state in order to properly address stacked animations
  • #9280 : Allow multiple effect queues for animate()
  • #9548 : animate does not work with fill-opacity css property for svg elements
  • #10445 : Setting queue to true causes an error
  • #10497 : .stop should allow choosing which queue to stop
  • #10622 : .show() does not properly restore CSS-set “display” value

Event

  • #3368 : event.metaKey should be assigned to event.ctrlKey on Non-Mac only
  • #6170 : jQuery(window).scroll(); causes IE* to scroll to 0,0
  • #6319 : Regression: stopPropagation inside change handlers in IE is incorrectly applied to keydown event
  • #6386 : support data argument for live events via “event.special.live.add”
  • #6593 : IE8: DOM 0 event handler called twice when a separate handler is attached via jQuery
  • #6667 : submit event doesn’t delegate in IE* under certain conditions
  • #6903 : special events need a way to determine whether they are being bound with .bind vs .live/.delegate
  • #6942 : JQuery.event.fix causes unnecessary reflows in IE when handling key events
  • #7139 : “hover” event alias should work for .bind as well as .live
  • #7161 : Submit event on a form element not unbound properly in IE
  • #7444 : Submitting form with “Enter” instead of button click on ie8 or ie7 triggers live submit event twice.
  • #8157 : Focusing an already focused text field will prevent the change event from firing in IE
  • #8728 : Event ‘mouseenter’ not firing when the element being left is removed on leaving
  • #8789 : Meta: Event Property Hooks
  • #8858 : Special events – _default method doesn’t have access to the `data` argument of the trigger method
  • #8866 : IE8 input[type=file] delegated change event files only on blur
  • #8982 : bind(“unload someOther”) => on unload, handler is not executed only once.
  • #9069 : when hover over a child of an element, mouseleave fires when using live or delegate
  • #9279 : delegate() bind does not handle mouseover/mouseout and mouseenter/mouseout correctly for selected elements
  • #9393 : Unify and DRY out event system
  • #9593 : Delegated submit event is not instanceof jQuery.Event in IE
  • #9724 : Infinite loop in trigger function when window.parentNode is a DOM element
  • #9901 : event.handleObj.namespace incorrect when using .delegate
  • #9933 : jQuery.fn.toggle() should store state in private data object
  • #9951 : Wrong order in .trigger() when DOM is modified in a handler
  • #10375 : Do not include `type` in jQuery.event.props
  • #10438 : Rename jQuery.event.propHooks => .fixHooks
  • #10468 : Remove deprecated jQuery.event.guid and jQuery.event.proxy
  • #10489 : Disconnected elements bubble to window on .trigger()
  • #10531 : Consider removing layerX and layerY from $.event.props
  • #10563 : jQuery.Event no longer contains the element that matched the selector in event delegation.
  • #10567 : Delegated events incorrectly match class names
  • #10575 : Breaking changes in live event propagation between 1.6.4 and 1.7rc1
  • #10576 : jQuery1.7rc1 and jQueryMobile1.0rc2 – IE gets error in jqm triggerCustomEvent method

Manipulation

  • #6782 : carefully allow more strings to use innerHTML
  • #7037 : Duplicate mouseover and mouseout events added to cloned element.
  • #10501 : HTML5 element “innerShiv” inconsistent across html()/append()

Misc

  • #10420 : MouseWheel
  • #10553 : Further reduction of minimal license header

Selector

  • #3144 : Inconsistent cross-browser results from .text() method
  • #5637 : Boolean (and Empty) Attribute Selectors Fail
  • #6863 : faster getText
  • #7128 : attribute selector is inconsistent between qSA and Sizzle due to use of DOM properties
  • #8539 : Sizzle cache collision in browsers without querySelectorAll
  • #9261 : Has Attribute not working in filter/children/siblings
  • #9570 : Selector $(‘form[name=".."]‘) returns zero elements in IE8 under some conditions
  • #10178 : $(window).is(“a”) >> Uncaught TypeError: Cannot call method ‘toLowerCase’ of undefined
  • #10315 : Sizzle ignores seed argument when using positional selectors
  • #10562 : siblings method returns unexpected elements when using Sizzle-invoking pseudo-selectors

Support

  • #5145 : jQuery.support.opacity = false in the Chrome browser
  • #6809 : Add jQuery.support.fixedPosition
  • #10558 : Test Support bug
  • #10613 : IE8 doesn’t like a detached body in its head

Traversing

  • #10449 : Function $(“#id”).closest(“.class”) returns element $(“#id”) itself if it has .class

jQuery 1.7 RC1 Released

Posted October 24, 2011 by dmethvin

The team is getting closer to jQuery 1.7, and today we’re putting out a release candidate. The full list of fixes and features can be found below. We urge everyone to start testing this code in their applications, so we can make sure that there are no major problems before the final release.

Testing couldn’t be simpler, you can get the code from the jQuery CDN:

Please help us by dropping that code into your existing application. If you see something, say something. File a bug and mention that you’re testing against jQuery 1.7 RC1. If there’s a problem we want to fix it.

In the meantime, we’re working on the documentation and release notes to make sure your transition to 1.7 goes smoothly. Stay tuned!

jQuery 1.7 RC 1 Change Log

The current change log of the 1.7 RC 1 release.

Ajax

  • #9399 : Deprecate jqXHR.success and jqXHR.error

Attributes

  • #5479 : removeAttr: remove multiple attributes
  • #6743 : map enctype to encoding, depending on browser
  • #10176 : Injected script tag is evaluated twice
  • #10278 : checkboxEl.attr(‘checked’) returns stale value after checkboxEl.click()
  • #10429 : IE7 – invalid procedure call or argument when calling removeAttr(‘contenteditable’);
  • #10514 : removeAttr does not remove the class attribute in IE6/7

Core

  • #6485 : Solution for HTML5 in IE
  • #7102 : Register jQuery as a CommonjS async module
  • #9453 : $.inArray does not support fromIndex
  • #10478 : Switch jQuery.isNaN to jQuery.isNumeric

Css

  • #10267 : IE8 and window is(‘:visible’) crashes

Data

  • #7323 : Allow removing multiple data keys at once with $.fn.removeData
  • #8909 : $(element).data() will scan all attributes more than needed.
  • #8921 : jQuery private data should stay private

Deferred

  • #8856 : Request: deferred.isUnresolved()
  • #9033 : try{ } finally{ } error in IE8
  • #9398 : Proposal for Improved Deferreds

Dimensions

  • #9434 : .outerWidth()/.outerHeight()/.innerWidth()/.innerHeight() should work on window and document

Effects

  • #5684 : Effects: exception in animation callback causes endless loop
  • #6150 : .stop sometimes doesn’t clear .delay
  • #6641 : Calling stop() within animation finished callback causes other animations to freeze
  • #8685 : Animations should keep track of animation state in order to properly address stacked animations
  • #9280 : Allow multiple effect queues for animate()
  • #9548 : animate does not work with fill-opacity css property for svg elements
  • #10416 : defaultDisplay returns block instead of table-row for a tr in FF
  • #10445 : Setting queue to true causes an error
  • #10497 : .stop should allow choosing which queue to stop

Event

  • #3368 : event.metaKey should be assigned to event.ctrlKey on Non-Mac only
  • #6170 : jQuery(window).scroll(); causes IE* to scroll to 0,0
  • #6319 : Regression: stopPropagation inside change handlers in IE is incorrectly applied to keydown event
  • #6386 : support data argument for live events via “event.special.live.add”
  • #6593 : IE8: DOM 0 event handler called twice when a separate handler is attached via jQuery
  • #6667 : submit event doesn’t delegate in IE* under certain conditions
  • #6903 : special events need a way to determine whether they are being bound with .bind vs .live/.delegate
  • #6942 : JQuery.event.fix causes unnecessary reflows in IE when handling key events
  • #7139 : “hover” event alias should work for .bind as well as .live
  • #7161 : Submit event on a form element not unbound properly in IE
  • #7444 : Submitting form with “Enter” instead of button click on ie8 or ie7 triggers live submit event twice.
  • #8157 : Focusing an already focused text field will prevent the change event from firing in IE
  • #8728 : Event ‘mouseenter’ not firing when the element being left is removed on leaving
  • #8789 : Meta: Event Property Hooks
  • #8858 : Special events – _default method doesn’t have access to the `data` argument of the trigger method
  • #8866 : IE8 input[type=file] delegated change event files only on blur
  • #8982 : bind(“unload someOther”) => on unload, handler is not executed only once.
  • #9069 : when hover over a child of an element, mouseleave fires when using live or delegate
  • #9279 : delegate() bind does not handle mouseover/mouseout and mouseenter/mouseout correctly for selected elements
  • #9393 : Unify and DRY out event system
  • #9593 : Delegated submit event is not instanceof jQuery.Event in IE
  • #9724 : Infinite loop in trigger function when window.parentNode is a DOM element
  • #9901 : event.handleObj.namespace incorrect when using .delegate
  • #9933 : jQuery.fn.toggle() should store state in private data object
  • #9951 : Wrong order in .trigger() when DOM is modified in a handler
  • #10375 : Do not include `type` in jQuery.event.props
  • #10438 : Rename jQuery.event.propHooks => .fixHooks
  • #10468 : Remove deprecated jQuery.event.guid and jQuery.event.proxy
  • #10489 : Disconnected elements bubble to window on .trigger()
  • #10531 : Consider removing layerX and layerY from $.event.props
  • #10563 : jQuery.Event no longer contains the element that matched the selector in event delegation.

Manipulation

  • #6782 : carefully allow more strings to use innerHTML
  • #7037 : Duplicate mouseover and mouseout events added to cloned element.
  • #10501 : HTML5 element “innerShiv” inconsistent across html()/append()

Misc

  • #10553 : Further reduction of minimal license header

Selector

  • #3144 : Inconsistent cross-browser results from .text() method
  • #5637 : Boolean (and Empty) Attribute Selectors Fail
  • #6863 : faster getText
  • #7128 : attribute selector is inconsistent between qSA and Sizzle due to use of DOM properties
  • #8539 : Sizzle cache collision in browsers without querySelectorAll
  • #9261 : Has Attribute not working in filter/children/siblings
  • #9570 : Selector $(‘form[name=".."]‘) returns zero elements in IE8 under some conditions
  • #10178 : $(window).is(“a”) >> Uncaught TypeError: Cannot call method ‘toLowerCase’ of undefined
  • #10315 : Sizzle ignores seed argument when using positional selectors
  • #10562 : siblings method returns unexpected elements when using Sizzle-invoking pseudo-selectors

Support

  • #5145 : jQuery.support.opacity = false in the Chrome browser
  • #6809 : Add jQuery.support.fixedPosition
  • #10558 : Test Support bug

Traversing

  • #10449 : Function $(“#id”).closest(“.class”) returns element $(“#id”) itself if it has .class

Announcing The jQuery Standards Team

Posted October 24, 2011 by Addy Osmani

Today we’re happy to announce the creation of a new jQuery sub-team called the jQuery Standards Team to give web developers a voice in the standards process.

Introduction

We all know that web standards are important. They help ensure the code we write works across different technologies, for people of different abilities and most importantly across all browsers.

That said, how often do we all feel our voices, suggestions and ideas are heard by those groups responsible for defining these standards? The reality is that whilst many of us would like to see change, due to time restrictions and lengthy formal processes we’re unable to participate in standards discussions, get involved with writing specifications and contribute to meetings about the future of features. This makes it difficult for web developers to have a voice.





Yehuda Katz is team lead. Paul Irish joins him.

Another problem is that for those that do get involved with the process, it can often feel like participating on a particular thread in standards mailing lists has a limited impact because the web community is so fragmented. Browser vendors are very active on these lists and there’s a tremendous amount of institutional knowledge assumed in almost all threads. Implementors on those lists have their own venues for discussing areas of shared concerns, but web developers wishing to particpate don’t, with the exception of the accidental meetups at conferences.

The jQuery project would like to help change this – we want you to have a voice in how the future of the web is shaped.

The jQuery Standards Team

The jQuery Standards Team has three primary goals:

  • To represent the web developer community, in particular jQuery users, to standards bodies such as the W3C and TC39 with the intention of improving existing standards and standards in progress to better meet the needs of web developers.
  • To represent the web developer community, and especially jQuery users, to browser vendors with the intent of helping them identify standards that they should prioritize for implementing, and proofs of concept that they can build.
  • To help the jQuery project adopt new standards and browser features as appropriate.

This marks a large change in the way the web developer community is able to submit feedback and influence both standards bodies and specifications. By lowering the barrier of entry to having suggestions and issues about current implementations heard, we hope to encourage more developers with an interest in dealing with standards bodies and browser vendors an opportunity to participate in the process.

The jQuery Standards Team is driven by jQuery team members Yehuda Katz and Paul Irish who some of you may know. Yeuhda and Paul have extenstively worked with standards bodies and browser vendors in a number of capacities over the years, with their individual work on SproutCore and Chrome Developer Relations providing them additional perspectives that will be useful when advocating for the community.

You may be wondering why we feel this team deserves to represent the wider web developer community. Because jQuery is used by such a large percentage of sites on the web (over 50% of the top 10,000 sites), we have a good feel for what problems and challenges are commonly faced and what issues with existing implementations we need to try working around. As jQuery is also so focused on DOM-manipulation, the library offers a good source of information for known implementation issues and their (current) best solutions.

Although the current team is primarily composed of jQuery team members, we want to get as many developers passionate about standards and specifications involved with the team as possible. At the end of the day, the team’s goal is to to help identify web developers interested in the process and give us all a forum for both discussing the process, ideas and shared areas of concern. We believe that working together, we can all help build a better web.

Getting Involved

If you’re interested in getting involved with the jQuery Standards Team, the easiest way is to sign up for the Google Group . Similar to other jQuery sub-teams, there are going to be regular public meetings in #jquery-meeting on freenode (date TBA) to discuss how the team can be as effective as possible in promoting the needs of the web developer community.

You might have already seen Paul’s post What feature would improve the web? — if your feedback was captured there, you’ve already gotten involved. ;)

You can also report (or comment) on standard or specification issues in the issue tracker on the official team Github repo . If you’re posting new issues, try to identify problems with specs or standards that either exist or are currently being proposed. Here’s a great example of one such issue .

We want to collect well-specified and articulated issues with the web ecosystem and advocate for improvements with the standards bodies or vendors. For genuine issues, we’ll tag them accordingly (eg. W3C, TC39, Browser-vendor etc.) and if applicable, file tickets with the appropriate standards groups or browser vendors so you don’t have to.

Conclusions

By creating this new forum we hope to give a voice to the millions of web developers interested in contributing to the process, but without an easy way to do so. Please let us know what your thoughts are about the team as we want to improve it as much as possible. We look forward to hearing your comments, suggestions and ideas about both it and the standards process!

jQuery 1.7 Beta 2 Released

Posted October 14, 2011 by dmethvin

Hot off the momentum of the jQuery Conference in Boston earlier this month, and based on the community’s valuable feedback, we’re releasing a new beta that incorporates further fixes and improves stability. The full list of fixes and features can be found below. We urge everyone to start testing this code in their applications, so we can make sure that there are no major problems before the final release.

You can get the code from the jQuery CDN:

Please help us by dropping that code into your existing application. If you see something, say something. File a bug and mention that you’re testing against jQuery 1.7 Beta 2. If there’s a problem we want to fix it!

jQuery 1.7 Beta 2 Change Log

The current change log of the 1.7 Beta 2 release:

Ajax

  • #9399 : Deprecate jqXHR.success and jqXHR.error

Attributes

  • #5479 : removeAttr: remove multiple attributes
  • #10176 : Injected script tag is evaluated twice
  • #10278 : checkboxEl.attr(‘checked’) returns stale value after checkboxEl.click()
  • #10429 : IE7 – invalid procedure call or argument when calling removeAttr(‘contenteditable’);

Core

  • #6485 : Solution for HTML5 in IE
  • #7102 : Register jQuery as a CommonjS async module
  • #9453 : $.inArray does not support fromIndex
  • #10478 : Switch jQuery.isNaN to jQuery.isNumeric

Css

  • #10267 : IE8 and window is(‘:visible’) crashes

Data

  • #7323 : Allow removing multiple data keys at once with $.fn.removeData
  • #8909 : $(element).data() will scan all attributes more than needed.
  • #8921 : jQuery private data should stay private

Deferred

  • #8856 : Request: deferred.isUnresolved()
  • #9033 : try{ } finally{ } error in IE8
  • #9398 : Proposal for Improved Deferreds

Dimensions

  • #9434 : .outerWidth()/.outerHeight()/.innerWidth()/.innerHeight() should work on window and document

Effects

  • #5684 : Effects: exception in animation callback causes endless loop
  • #6150 : .stop sometimes doesn’t clear .delay
  • #6641 : Calling stop() within animation finished callback causes other animations to freeze
  • #8685 : Animations should keep track of animation state in order to properly address stacked animations
  • #9280 : Allow multiple effect queues for animate()
  • #9548 : animate does not work with fill-opacity css property for svg elements
  • #10416 : defaultDisplay returns block instead of table-row for a tr in FF
  • #10445 : Setting queue to true causes an error

Event

  • #3368 : event.metaKey should be assigned to event.ctrlKey on Non-Mac only
  • #6170 : jQuery(window).scroll(); causes IE* to scroll to 0,0
  • #6319 : Regression: stopPropagation inside change handlers in IE is incorrectly applied to keydown event
  • #6386 : support data argument for live events via “event.special.live.add”
  • #6593 : IE8: DOM 0 event handler called twice when a separate handler is attached via jQuery
  • #6667 : submit event doesn’t delegate in IE* under certain conditions
  • #6903 : special events need a way to determine whether they are being bound with .bind vs .live/.delegate
  • #6942 : JQuery.event.fix causes unnecessary reflows in IE when handling key events
  • #7139 : “hover” event alias should work for .bind as well as .live
  • #7161 : Submit event on a form element not unbound properly in IE
  • #7444 : Submitting form with “Enter” instead of button click on ie8 or ie7 triggers live submit event twice.
  • #8157 : Focusing an already focused text field will prevent the change event from firing in IE
  • #8728 : Event ‘mouseenter’ not firing when the element being left is removed on leaving
  • #8789 : Meta: Event Property Hooks
  • #8858 : Special events – _default method doesn’t have access to the `data` argument of the trigger method
  • #8866 : IE8 input[type=file] delegated change event files only on blur
  • #8982 : bind(“unload someOther”) => on unload, handler is not executed only once.
  • #9069 : when hover over a child of an element, mouseleave fires when using live or delegate
  • #9279 : delegate() bind does not handle mouseover/mouseout and mouseenter/mouseout correctly for selected elements
  • #9393 : Unify and DRY out event system
  • #9593 : Delegated submit event is not instanceof jQuery.Event in IE
  • #9724 : Infinite loop in trigger function when window.parentNode is a DOM element
  • #9901 : event.handleObj.namespace incorrect when using .delegate
  • #9933 : jQuery.fn.toggle() should store state in private data object
  • #9951 : Wrong order in .trigger() when DOM is modified in a handler
  • #10375 : Do not include `type` in jQuery.event.props
  • #10438 : Rename jQuery.event.propHooks => .fixHooks
  • #10468 : Remove deprecated jQuery.event.guid and jQuery.event.proxy
  • #10489 : Disconnected elements bubble to window on .trigger()

Manipulation

  • #6782 : carefully allow more strings to use innerHTML
  • #7037 : Duplicate mouseover and mouseout events added to cloned element.

Selector

  • #3144 : Inconsistent cross-browser results from .text() method
  • #5637 : Boolean (and Empty) Attribute Selectors Fail
  • #6863 : faster getText
  • #7128 : attribute selector is inconsistent between qSA and Sizzle due to use of DOM properties
  • #8539 : Sizzle cache collision in browsers without querySelectorAll
  • #9261 : Has Attribute not working in filter/children/siblings
  • #9570 : Selector $(‘form[name=".."]‘) returns zero elements in IE8 under some conditions
  • #10178 : $(window).is(“a”) >> Uncaught TypeError: Cannot call method ‘toLowerCase’ of undefined
  • #10315 : Sizzle ignores seed argument when using positional selectors

Support

  • #5145 : jQuery.support.opacity = false in the Chrome browser
  • #6809 : Add jQuery.support.fixedPosition

Traversing

  • #10449 : Function $(“#id”).closest(“.class”) returns element $(“#id”) itself if it has .class

Release: Validation Plugin 1.9.0

Posted October 07, 2011 by Jörn

An update for the jQuery validation plugin  is available. Most notable is heavily improved compability with HTML5 controls: You can apply validation rules to input types like number, email or url, it’ll get picked up by the plugin if the type matches a rule, and a required attribute (with the argument) also works with both jQuery 1.6+ (prop) and previous versions (attr).

Another change should make the setup of forms with hidden elements easier, these are now ignored by default (option “ignore” has “:hidden” now as default). In theory, this could break an existing setup. In the unlikely case that it actually does, you can fix it by setting the ignore-option to “[]” (square brackets without the quotes).

A few improvements and bug fixes for validation methods landed:

  • Creditcard now accepts spaces between the other valid characters
  • Email doesn’t accept a dot character at the end anymore.
  • The time method (in additionalMethods.js) is now more thorough.
  • A time12h method got added (also in additionalMethods.js), to validate 12-hour times, while the existing time method does 24-hour times.

There also two new localizations, resulting in a total number of 38 localizations. Existing localizations saw various improvements – thanks to everyone who contributed those! Its the only feature where I’m relying completely on contributions, as I can’t verify the correctness of any of the localizations (other then English and German).

Backwards compatibility is still going strong: The plugin should work with anything from jQuery 1.3.x to 1.6.x.

Download this release.

The full changelog:

  • Added Basque (EU) localization
  • Added Slovenian (SL) localization
  • Fixed issue #127 – Finnish translations has one : instead of ;
  • Fixed Russian localization, minor syntax issue
  • Added in support for HTML5 input types, fixes #97
  • Improved HTML5 support by setting novalidate attribute on the form, and reading the type attribute.
  • Fixed showLabel() removing all classes from error element. Remove only settings.validClass. Fixes #151.
  • Added ‘pattern’ to additional-methods to validate against arbitraty regular expressions.
  • Improved email method to not allow the dot at the end (valid by RFC, but unwanted here). Fixes #143
  • Fixed swedish and norwedian translations, min/max messages got switched. Fixes #181
  • Fixed #184 – resetForm: should unset lastElement
  • Fixed #71 – improve existing time method and add time12h method for 12h am/pm time format
  • Fixed #177 – Fix validation of a single radio or checkbox input
  • Fixed #189 – :hidden elements are now ignored by default
  • Fixed #194 – Required as attribute fails if jQuery>=1.6 – Use .prop instead of .attr
  • Fixed #47, #39, #32 – Allowed credit card numbers to contain spaces as well as dashes (spaces are commonly input by users).
As usual:
  • Please post questions to the official Using jQuery Plugins Forum , tagging your question with (at least) “validate”. Keep your question short and succinct and provide code when possible; a testpage makes it much more likely that you get an useful answer in no time.
  • Please post bug reports and other contributions (enhancements, features, eg. new validation methods) to the GitHub issue tracker

Enjoy!

jQuery 1.7 Beta 1 Released

Posted September 28, 2011 by dmethvin

If you hadn’t heard, jQuery Conference 2011 is taking place in Boston later this week. We’ve put together a little something we like to call jQuery 1.7 Beta 1 that we’ll be talking a lot more about at the conference. It’s got a lovely bunch of new features and significant bug fixes–more than 50 of them at last count.

You can get the beta from the jQuery CDN:

Please help us by dropping this code into your existing application and letting us know if anything no longer works. Please file a bug ticket and be sure to mention that you’re testing against jQuery 1.7 BETA 1.

Also be sure to explore all the new features and see if your favorite pet-peeve bug has been fixed. If you wait until the final release to do your testing it will be too late!

As always, we want to encourage everyone from the community to try and get involved in contributing back to jQuery core. We’ve set up a full page of information dedicated towards becoming more involved with the team. The team is here and ready to help you help us!

Oh, you probably want to know what changed, right? Addy Osmani has made a great start with his recent post , so let’s cover the stuff that isn’t on his list.

New Event APIs: .on() and .off()

Over time, jQuery has evolved three ways to attach events to elements: .bind() , .live() , and .delegate() . Underneath it all, though, the three event APIs call the browser’s event system; that can lead to surprising interactions. For example, $(document).unbind("click") will remove all .live("click", ...) events, since those delegated events are attached to document . (This is also why you should use event namespaces .)

Our current event APIs aren’t going away soon, but to address the inconsistencies we’ve introduced a new and simple pair of event methods that can do the work of all three:

    $(elems).on(events, selector, data, fn);
    $(elems).off(events, selector, fn);

If a selector is provided, it’s a delegated event; otherwise it’s directly bound. All the features of the old APIs are there; for example events can be a space-separated string of event names and/or namespaces, or it can be an object where the keys are events and the values are event handler functions. Here are some examples of how the old methods map into the new ones:

#oldnew { width: 100%; } #oldnew th { text-align: left; } #oldnew td { font-size: 120%; font-family: Courier, sans-serif; }
Old API New API
$(elems).bind(events, fn) $(elems).on(events, fn)
$(elems).bind(events, { mydata: 42 }, fn) $(elems).on(events, { mydata: 42 }, fn)
$(elems).unbind(events, fn) $(elems).off(events, fn)
$(elems).delegate(selector, events, fn) $(elems).on(events, selector, fn)
$(elems).undelegate(selector, events, fn) $(elems).off(events, selector, fn)
$(selector).live(events, fn) $(document).on(events, selector, fn)
$(selector).die(events, fn) $(document).off(events, selector, fn)

Form Change and Submit Events in IE 6/7/8

These old Internet Explorer versions are likely to be haunting us for some time, so we’ve spent a while trying to improve their behavior. Event delivery performance has been greatly improved for them, but the biggest change is that we are using a different approach to fix their non-bubbling and broken form events. As a result we were able to greatly simplify and shorten the special events code. These events should work without any problems–even better than before, since we closed about a half-dozen related bugs–but please keep your eyes open for any unusual behavior.

Animation Improvements

Before version 1.7, if you stopped an animation before it completed it could create a situation where the element being animated would never return to its full size; it would essentially be stuck at the height that it was when the animation was stopped. We’ve fixed that by remembering the original dimensions before the animation starts so that they can be used later. This eliminates a major annoyance in using certain animations, particularly toggling ones.

.removeData() Enhancements

Addy mentioned this one as well, but the .removeData() API now lets you pass either a space-separated string of names or an array of names to be removed. Since spaces were previously allowed in data names, the code first checks for the exact name as you specified it before splitting the string on spaces. That way, no existing code should break as a result of this enhancement.

jQuery 1.7 BETA 1 Change Log

Here is a complete list of changes made for the 1.7 BETA 1 release.

Ajax

  • #9399 : Deprecate jqXHR.success and jqXHR.error

Attributes

  • #5479 : removeAttr: remove multiple attributes
  • #10278 : checkboxEl.attr(‘checked’) returns stale value after checkboxEl.click()

Core

  • #6485 : Solution for HTML5 in IE
  • #7102 : Register jQuery as a CommonjS async module
  • #9453 : $.inArray does not support fromIndex

Css

  • #10267 : IE8 and window is(‘:visible’) crashes

Data

  • #7323 : Allow removing multiple data keys at once with $.fn.removeData
  • #8909 : $(element).data() will scan all attributes more than needed.
  • #8921 : jQuery private data should stay private

Deferred

  • #8856 : Request: deferred.isUnresolved()
  • #9033 : try{ } finally{ } error in IE8
  • #9398 : Proposal for Improved Deferreds

Effects

  • #5684 : Effects: exception in animation callback causes endless loop
  • #6150 : .stop sometimes doesn’t clear .delay
  • #6641 : Calling stop() within animation finished callback causes other animations to freeze
  • #8685 : Animations should keep track of animation state in order to properly address stacked animations
  • #9280 : Allow multiple effect queues for animate()
  • #9548 : animate does not work with fill-opacity css property for svg elements

Event

  • #3368 : event.metaKey should be assigned to event.ctrlKey on Non-Mac only
  • #6170 : jQuery(window).scroll(); causes IE* to scroll to 0,0
  • #6319 : Regression: stopPropagation inside change handlers in IE is incorrectly applied to keydown event
  • #6386 : support data argument for live events via “event.special.live.add”
  • #6593 : IE8: DOM 0 event handler called twice when a separate handler is attached via jQuery
  • #6667 : submit event doesn’t delegate in IE* under certain conditions
  • #6705 : focus() causes focus event to be handled twice in IE8
  • #6903 : special events need a way to determine whether they are being bound with .bind vs .live/.delegate
  • #6942 : JQuery.event.fix causes unnecessary reflows in IE when handling key events
  • #7139 : “hover” event alias should work for .bind as well as .live
  • #7161 : Submit event on a form element not unbound properly in IE
  • #7444 : Submitting form with “Enter” instead of button click on ie8 or ie7 triggers live submit event twice.
  • #8157 : Focusing an already focused text field will prevent the change event from firing in IE
  • #8728 : Event ‘mouseenter’ not firing when the element being left is removed on leaving
  • #8789 : Meta: Event Property Hooks
  • #8858 : Special events – _default method doesn’t have access to the `data` argument of the trigger method
  • #8866 : IE8 input[type=file] delegated change event files only on blur
  • #8982 : bind(“unload someOther”) => on unload, handler is not executed only once.
  • #9069 : when hover over a child of an element, mouseleave fires when using live or delegate
  • #9279 : delegate() bind does not handle mouseover/mouseout and mouseenter/mouseout correctly for selected elements
  • #9393 : Unify and DRY out event system
  • #9593 : Delegated submit event is not instanceof jQuery.Event in IE
  • #9724 : Infinite loop in trigger function when window.parentNode is a DOM element
  • #9901 : event.handleObj.namespace incorrect when using .delegate
  • #9933 : jQuery.fn.toggle() should store state in private data object
  • #9951 : Wrong order in .trigger() when DOM is modified in a handler

Manipulation

  • #6782 : carefully allow more strings to use innerHTML
  • #7037 : Duplicate mouseover and mouseout events added to cloned element.

Selector

  • #5637 : Boolean (and Empty) Attribute Selectors Fail
  • #7128 : attribute selector is inconsistent between qSA and Sizzle due to use of DOM properties
  • #9261 : Has Attribute not working in filter/children/siblings
  • #9570 : Selector $(‘form[name=".."]‘) returns zero elements in IE8 under some conditions
  • #10178 : $(window).is(“a”) >> Uncaught TypeError: Cannot call method ‘toLowerCase’ of undefined
  • #10315 : Sizzle ignores seed argument when using positional selectors

Support

  • #6809 : Add jQuery.support.fixedPosition

Just Added: HTML5 Training at jQuery Conference Boston!

Posted September 20, 2011 by Leah Silber

Update: For the first time ever, we have a conference signage sponsor. Thanks to custom signs shop Signazon for your support.


The Boston conference is sold out (thanks everyone!), as is the Intro to jQuery training session, but the requests keep coming! In response to popular demand, we’ve added a second training scheduled for Friday, September 30th .

The training will focus on HTML5, and be taught by jQuery Core Team Member and Bocoup trainer Richard Worth. The price will be the same $299 (which, if you’ve been paying attention to HTML5 training rates, is a steal!).

Here’s some detail from the training description:

HTML5 is the next major milestone in HTML and it’s not just another incremental enhancement; it represents an enormous advance for modern web applications. A large number of HTML5 features are already supported in browsers, so it’s time to start using them!

In our HTML5 for Programmers Workshop, you will learn how to create HTML5 web pages and web applications using semantic HTML5 markup and cross-browser HTML5 JavaScript APIs. After completing this course, students will:

  • Know how to use semantic HTML5 Markup
  • Know how to use cross-browser HTML5 JavaScript APIs
  • Understand current browser support for the various HTML5 features
  • Understand how to polyfill HTML5 features on older browsers

Our training takes a step-by-step approach, solidifying fundamental concepts and building on them to leave each attendee with a more thorough understanding of HTML5. Using a 50% lecture / 50% lab format, attendees will be able to put the concepts they have just learned to use after each section.

  • HTML5 Overview
  • Using HTML5 Today
  • Markup
  • Forms
  • Canvas
  • Video and Audio
  • Drag and Drop
  • Geolocation
  • Web Storage
  • Web Workers
  • Communication and Web Sockets

This course is designed for software developers interested in designing, creating, and deploying HTML5 web applications. It is valuable to developers that already have experience in developing web applications. To get the most out of the course, you should be familiar with HTML, CSS, and JavaScript.

Prior exposure to any of these concepts will be helpful, but not required: AJAX, XML, jQuery, HTTP, REST.

It’s short notice, but we hope you can make it, so register now ! As always, feel free to email events@jquery.org with any event related questions.

See you all at the show!

jQuery 1.6.4 Released

Posted September 12, 2011 by John Resig

jQuery 1.6.4 Released

This is a minor point release of jQuery. We’re releasing it fix a couple issues that came up during the release of jQuery 1.6.3.

You can get the code from the jQuery CDN:

You can help us by dropping that code into your existing application and letting us know that if anything no longer works. Please file a bug and be sure to mention that you’re testing against jQuery 1.6.4.

We want to encourage everyone from the community to try and get involved in contributing back to jQuery core. We’ve set up a full page of information dedicated towards becoming more involved with the team. The team is here and ready to help you help us!

jQuery 1.6.4 Change Log

The current change log of the 1.6.4 release.

Data

  • #10194 : Data attribute names with single dash-surrounded letters cannot be accessed by the camel-case name

Event

  • #10208 : $(“form”).live(“submit”, fn) not fired from <button type=”submit”> in IE8

Support

  • #10197 : Bug with mime-type application/xhtml+xml in jquery 1.6.3

jQuery 1.6.4 RC1 released

Posted September 09, 2011 by dmethvin

jQuery 1.6.4 will be released soon, and we need your help with this release candidate to find any remaining bugs. We’re putting out a new version to address a few last-minute bugs that crept into the 1.6.3 release. With version 1.7 coming next month, we felt it was important to fix these bugs and finalize the 1.6.x line before making more extensive changes and feature additions.

Feel free to do your testing by including either one of these files (one minified and one uncompressed). If you find any important differences from 1.6.3, please file a bug as soon as possible and be sure to mention that you’re testing against jQuery 1.6.4 RC1. Our preferred venue for test cases is jsFiddle ; you can just use the “jQuery (edge)” selection there.

jQuery 1.6.4 RC1 Change Log

The current change log of the 1.6.4 release:

Data

  • #10194 : Data attribute names with single dash-surrounded letters cannot be accessed by the camel-case name

Event

  • #10208 : $(“form”).live(“submit”, fn) not fired from <button type=”submit”> in IE8

Support

  • #10197 : Bug with mime-type application/xhtml+xml in jquery 1.6.3

Please do file a bug report with a test case as soon as possible if you find problems, as described above. Blog comments or Twitter aren’t helpful bug reports!

Using jQuery’s Data APIs

Posted September 02, 2011 by Dave Methvin

In the beginning (well, beginning with jQuery 1.2.3 in early 2008) there was the jQuery.data() API. It offers a way to associate JavaScript data — strings, numbers, or any object — with a DOM element. As long as you manipulate the DOM element with jQuery, the library ensures that when the DOM element goes away, the associated data goes away as well. This is especially important for older versions of IE that tend to leak memory when JavaScript data is mixed with DOM data.

Most jQuery code sets data values using the higher-level .data() API; for example, $("div").data("imaDiv", true) sets a boolean value on every div in the document. This API, in turn, calls down to jQuery.data() with each element to set the value. For completeness, there are also jQuery.removeData() and .removeData() to remove data elements, and jQuery.hasData() to determine if any data is currently set for an element.

So to recap: At the inception of these APIs, they were only about getting and setting values associated with DOM elements in memory. Most importantly, the data was managed to ensure no memory would leak when the DOM elements were removed. Many internal jQuery features such as event handling and toggle state memory use these data APIs and their benefits.

Enter HTML5

A few years later, HTML5 became popular and associated another concept with the word "data" through its data-* attributes and the associated DOM .dataset property. This isn't quite the same as jQuery's original idea of data: It involves values being associated with HTML elements in markup and not DOM elements in memory. But they are logically close enough that we added the ability to read HTML5 data-* attributes into jQuery's data object starting with version 1.4.

It's not a perfect marriage, though. HTML5 data-* attribute names are more like CSS names; a name like data-shrivel-up is turned into shrivelUp when read in JavaScript-land. No such rules ever applied to jQuery data names in the past, which means we may have to try both shrivel-up and shrivelUp to find a match. We know it's not ideal, but it's a consequence of trying to fit two concepts with differing semantics into a single API.

Rules of the Road for Data APIs

With that history in mind, there are a few important things you should know in order to use the .data() and jQuery.data() APIs effectively. To give you a better sense of what's going on, the items are illustrated with some code. Assume that each code block runs independently of the others and that they all refer the following HTML:

HTML:

  1. <div id = "novel" data-novelist= '{"firstname": "Jose", "lastname": "Saramago"}' > Blindness</div>
  2. <div id = "poem" data-poet= "Edna St. Vincent Millay" > Sonnet 18</div>
  3. <div id = "story" data-story-writer= "Raymond Carver" > A Small, Good Thing</div>


Here are the rules of the road:

  1. Only the .data() API reads HTML5 data-* attributes, and it does so once .

    The in-memory data object for an element is initialized from those data-* attributes the first time you call .data() for the element. Any subsequent changes to the attributes are ignored, since jQuery has already cached the data.

    Rule: If HTML5 data-* attributes change during program execution, use jQuery's .attr() method to get the current values.

    JavaScript:

    1. console .log ( $.data ( document.getElementById ( 'poem' ) , 'poet' ) ) ;
    2. //>> undefined
    3.  
    4. console .log ( $( '#poem' ) .data ( 'poet' ) ) ;
    5. //>> "Edna St. Vincent Millay"
    6.  
    7. // Change the HTML5 data-poet attribute
    8. $( '#poem' ) .attr ( 'data-poet' , 'Edmund Spenser' ) ;
    9.  
    10. console .log ( $( '#poem' ) .data ( 'poet' ) ) ;
    11. //>> "Edna St. Vincent Millay"


  2. The .data() API converts HTML5 data-* values to Javascript types whenever possible.

    That means sequences of digits or exponential-looking values like "11E5" are translated to a Javascript Number type, the string "true" becomes Boolean true , and a valid JSON string becomes a JavaScript object.

    Rule: To get HTML5 data-* attributes as strings without data conversion, use jQuery's .attr() method.

    JavaScript:

    1. console .log ( $( '#novel' ) .data ( 'novelist' ) ) ;
    2. //>> Object> {"firstname": "Jose", "lastname": "Saramago"}
    3.  
    4. console .log ( $( '#novel' ) .attr ( 'data-novelist' ) ) ;
    5. //>> '{"firstname": "Jose", "lastname": "Saramago"}'


  3. The lower-level jQuery.data() API does not read HTML5 data-* attributes.

    However, if the .data() API has been called already on that DOM element, jQuery.data() will "see" the values that it has already read from the data-* attributes. Conversely, if jQuery.data() sets a value with the same name as an HTML5 data-* attribute and .data() later reads them, the HTML5 attribute is ignored .

    Rule: To prevent confusion, do not use similar names for HTML5 data-* attributes and strictly internal data stored using jQuery.data() or .data() on the same elements.

    JavaScript:

    1. // Before reading with .data()
    2. console .log ( $.data ( document.getElementById ( 'poem' ) , 'poet' ) ) ;
    3. //>> undefined
    4.  
    5. console .log ( $( '#poem' ) .data ( 'poet' ) ) ;
    6. //>> "Edna St. Vincent Millay"
    7.  
    8. // After reading with .data()
    9. console .log ( $.data ( document.getElementById ( 'poem' ) , 'poet' ) ) ;
    10. //>> "Edna St. Vincent Millay"


  4. No jQuery data API ever changes HTML5 data-* attributes.

    Most uses of .data() and .removeData() are still for the original purpose of associating data with DOM elements in memory. Updating DOM attributes each time data was changed would slow things down for no good reason. Also, it's not even possible to serialize all data types that might be attached to a DOM element, such as functions, references to other DOM elements, or custom JavaScript objects.

    Rule: To update or remove HTML5 data-* attributes, use jQuery's .attr() or .removeAttr() methods.

    JavaScript:

    1. console .log ( $( '#poem' ) .data ( 'poet' ) ) ;
    2. //>> "Edna St. Vincent Millay"
    3.  
    4. console .log ( $( '#poem' ) .attr ( 'data-poet' ) ) ;
    5. //>> "Edna St. Vincent Millay"
    6.  
    7. // Change the HTML5 data-* attribute
    8. $( '#poem' ) .attr ( 'data-poet' , 'William Shakespeare' ) ;
    9.  
    10. console .log ( $( '#poem' ) .data ( 'poet' ) ) ;
    11. //>> "Edna St. Vincent Millay"
    12.  
    13. console .log ( $( '#poem' ) .attr ( 'data-poet' ) ) ;
    14. //>> "William Shakespeare"
    15.  
    16. // Change .data('poet')
    17. $( '#poem' ) .data ( 'poet' , 'Edmund Spenser' ) ;
    18.  
    19. console .log ( $( '#poem' ) .data ( 'poet' ) ) ;
    20. //>> "Edmund Spenser"
    21.  
    22. console .log ( $( '#poem' ) .attr ( 'data-poet' ) ) ;
    23. //>> "William Shakespeare"


  5. All data-* names are stored in camelCase in the jQuery data object, using W3C rules .

    So, data-caMEL-case becomes the camelCase property in the data object and should be accessed using .data("camelCase") . Because many people will use .data("camel-case") instead, we convert that to camelCase as well, but only if no data item named camel-case is found so it's faster to use the first form. If you get the entire data object using code like data = jQuery.data(elem) , you must use data.camelCase to access the data item.

    Rule: When accessing data taken from data-* attributes, and especially when accessing the data object directly, use the W3C camelCasing conventions.

    JavaScript:

    1. // Not recommended:
    2. console .log ( $( '#story' ) .data ( 'STORY-writer' ) ) ;
    3. //>> "Raymond Carver"
    4.  
    5. // Better:
    6. console .log ( $( '#story' ) .data ( 'storyWriter' ) ) ;
    7. //>> "Raymond Carver"
    8.  
    9. // Broken:
    10. console .log ( $( '#story' ) .attr ( 'dataStoryWriter' ) ) ;
    11. //>> undefined
    12.  
    13. // Better:
    14. console .log ( $( '#story' ) .attr ( 'data-STORY-writer' ) ) ;
    15. //>> "Raymond Carver"


Pick What You Like

Over time, jQuery's .data() API has taken on more responsibilities than it originally had when it was just a way to associate in-memory data with DOM elements and prevent IE leakage. If you need only a simple way to read HTML5 data-* attributes as strings, then the .attr() method may be the best choice, even though the siren-song-name .data() may be telling you otherwise. Whether you use .attr() or .data() , they work consistently across browsers all the way back to IE6 — even if the browser doesn't support HTML5 — so just choose the API with the feature set that works best for your needs.

jQuery 1.6.3 Released

Posted September 01, 2011 by dmethvin

jQuery 1.6.3 is now out! This is the third minor release on top of jQuery 1.6 and lands a number of fixes for bugs, as listed below.

As usual, we provide two copies of jQuery, one minified and one uncompressed (for debugging or reading).

You can help us by dropping that code into your existing application and letting us know if anything no longer works. Please file a bug and be sure to mention that you’re testing against jQuery 1.6.3.

Many thanks to all the people who reported bugs, submitted patches, and otherwise helped with this release! We want to encourage everyone from the community to get involved in contributing back to jQuery core. We’ve set up a full page of information dedicated towards becoming more involved with the team. The team is here and ready to help you help us!

Highlights

Fix an XSS attack vector: User ma.la reported a common pattern that many sites are using to select elements using location.hash that allows someone to inject script into the page. This practice seemed widespread enough that we decided to modify the selector recognition to prevent script injection for the most common case. Any string passed to $() cannot contain HTML tags (and thus no script) if it has a “#” character preceding them. See the ticket linked above for more information and a test case.

No more animation “worm holes” : We had high hopes for the browser’s requestAnimationFrame API when we added support into version 1.6. However, one of the highest-volume complaints we’ve received since then relates to the way requestAnimationFrame acts when a tab is not visible. All the animations initiated when the tab is invisible “stack” and are not executed until the tab is brought back into focus. Then they all animate at warp speed! We’ve removed support for this API (which has no impact on the way you call jQuery’s animation features) and plan to incorporate it into a future version of jQuery.

Better handling of HTML5 data attribute names: The $().data() API serves double-duty, handling data for the internal use of jQuery and plugins in addition to reading initial values of HTML5 data- attributes. We’ve improved the ability to use HTML5 conventions such as converting camel-case to camelCase when needed. Remember, however, that the $().data() API only reads the HTML5 data- attributes initially, and does not keep subsequent data changes in sync with attributes for performance reasons. To update the actual attributes in the HTML markup, use .attr() .

jQuery 1.6.3 Change Log

The change log of the 1.6.3 release:

Ajax

  • #9255 : jQuery.parseXML error handling does not work in webkit browsers
  • #9854 : Pass statusText through instead of “normalizing” it
  • #9887 : jQuery.ajaxSetup may cause unnecessary memory usage
  • #9970 : Typo in ajax.js: status should be jqXHR.status?
  • #10098 : Encode comment-like Accept headers to avoid mobile carrier mangling

Attributes

  • #9630 : foo.contents().hasClass() returns incorrect value
  • #9699 : removeAttr(‘style’) does not consistently remove the style attribute in webkit
  • #9719 : removeAttr(‘disabled’) doesn’t change input’s color on IE6
  • #9979 : .prop(‘tabIndex’) returns inconsistent results for elements that have not yet set tabIndex
  • #9980 : Simplify the attr code by using getAttributeNode for everything in IE6/7

Build

  • #9988 : Minimal License Header in compressed jQuery

Core

  • #9521 : XSS with $(location.hash) and $(#) is needed?
  • #9897 : try-catch isPlainObject detection
  • #10076 : $.inArray crashes IE6 and Chrome if second argument is `null` or `undefined`

CSS

  • #6652 : Remove filter:alpha(opacity=100) after animation
  • #9572 : Support -ms-transform in .css() method
  • #10021 : Can’t add negative numbers using the relative-value syntax with .css() and .animate()

Data

  • #8235 : jQuery.data throws a script error in certain circumstances
  • #9318 : HTML5 data attributes has strange behaviour with if attribute names contain numbers
  • #9413 : $.fn.removeData does not remove data with a dash in a name
  • #9779 : Allow non-null|undefined evaluation of data property values
  • #9794 : jQuery.fn.data() correctly handle access to arbitrary data property values
  • #10016 : Cannot retrieve “false-y” values under key names with dashes using jQuery.data method
  • #10080 : unload from frame’s window breaks in IE8

Dimensions

  • #10123 : .width() can return a float in Firefox 6

Effects

  • #9381 : Animations halt when the browser is out of focus due to requestAnimationFrame
  • #9678 : setInterval cleared by animation

Event

  • #7071 : Accessing the ‘type’ property on VML elements fails on IE during submit special handler

Manipulation

  • #9587 : Cloning a div with an object causes error in IE8

Support

  • #9634 : Visible “t” character in upper left corner during support.js init
  • #9823 : IE 8 crashes when using background-image on BODY in css
  • #9964 : test/support.js module strictEqual typo
  • #10029 : $.support.scriptEval removed, but still included in documentation

Please do file a bug report with a test case as soon as possible if you find problems, as described above. Blog comments or Twitter aren’t helpful bug reports!

jQuery 1.6.3 RC1 Released

Posted August 29, 2011 by dmethvin

jQuery 1.6.3 is almost ready to roll! We need your help with this release candidate to be sure we’ve got everything right.

Feel free to do your testing by including either one of these files (one minified and one uncompressed). Our preferred venue for test cases is jsFiddle ; you can just use the “jQuery (edge)” selection there. If you need to report a bug and cannot use jsFiddle, please use the uncompressed version with your test case.

Please test this release with your most treasured code. If you find any important differences from 1.6.2, please file a bug as soon as possible and be sure to mention that you’re testing against jQuery 1.6.3 RC1.

If you’re making a quantum leap from a much older version of jQuery, it’s possible that the differences you find are due to documented behavior changes introduced in a major-point release. Check your code with the released 1.6.2 version first to be sure the problem only exists in 1.6.3 RC1.

Highlights

Fix an XSS attack vector: User ma.la reported a common pattern that many sites are using to select elements using location.hash that allows someone to inject script into the page. This practice seemed widespread enough that we decided to modify the selector recognition to prevent script injection for the most common case. Any string passed to $() cannot contain HTML tags (and thus no script) if it has a “#” character preceding them. See the ticket linked above for more information and a test case.

No more animation “worm holes” : We had high hopes for the browser’s requestAnimationFrame API when we added support into version 1.6. However, one of the highest-volume complaints we’ve received since then relates to the way requestAnimationFrame acts when a tab is not visible. All the animations initiated when the tab is invisible “stack” and are not executed until the tab is brought back into focus. Then they all animate at warp speed! We’ve removed support for this API (which has no impact on the way you call jQuery’s animation features) and plan to incorporate it into a future version of jQuery.

Better handling of HTML5 data attribute names: The $().data() API serves double-duty, handling data for the internal use of jQuery and plugins in addition to reading initial values of HTML5 data- attributes. We’ve improved the ability to use HTML5 conventions such as converting camel-case to camelCase when needed. Remember, however, that the $().data() API only reads the HTML5 data- attributes initially, and does not keep subsequent data changes in sync with attributes for performance reasons. To update the actual attributes in the HTML markup, use .attr() .

jQuery 1.6.3 Change Log

The current change log of the 1.6.3 release:

Ajax

  • #9255 : jQuery.parseXML error handling does not work in webkit browsers
  • #9854 : Pass statusText through instead of “normalizing” it
  • #9887 : jQuery.ajaxSetup may cause unnecessary memory usage
  • #9970 : Typo in ajax.js: status should be jqXHR.status?
  • #10098 : Encode comment-like Accept headers to avoid mobile carrier mangling

Attributes

  • #9630 : foo.contents().hasClass() returns incorrect value
  • #9699 : removeAttr(‘style’) does not consistently remove the style attribute in webkit
  • #9719 : removeAttr(‘disabled’) doesn’t change input’s color on IE6
  • #9979 : .prop(‘tabIndex’) returns inconsistent results for elements that have not yet set tabIndex
  • #9980 : Simplify the attr code by using getAttributeNode for everything in IE6/7

Build

  • #9988 : Minimal License Header in compressed jQuery

Core

  • #9521 : XSS with $(location.hash) and $(#) is needed?
  • #9897 : try-catch isPlainObject detection
  • #10076 : $.inArray crashes IE6 and Chrome if second argument is `null` or `undefined`

CSS

  • #6652 : Remove filter:alpha(opacity=100) after animation
  • #9572 : Support -ms-transform in .css() method
  • #10021 : Can’t add negative numbers using the relative-value syntax with .css() and .animate()

Data

  • #8235 : jQuery.data throws a script error in certain circumstances
  • #9318 : HTML5 data attributes has strange behaviour with if attribute names contain numbers
  • #9413 : $.fn.removeData does not remove data with a dash in a name
  • #9779 : Allow non-null|undefined evaluation of data property values
  • #9794 : jQuery.fn.data() correctly handle access to arbitrary data property values
  • #10016 : Cannot retrieve “false-y” values under key names with dashes using jQuery.data method
  • #10080 : unload from frame’s window breaks in IE8

Dimensions

  • #10123 : .width() can return a float in Firefox 6

Effects

  • #9381 : Animations halt when the browser is out of focus due to requestAnimationFrame
  • #9678 : setInterval cleared by animation

Event

  • #7071 : Accessing the ‘type’ property on VML elements fails on IE during submit special handler

Manipulation

  • #9587 : Cloning a div with an object causes error in IE8

Support

  • #9634 : Visible “t” character in upper left corner during support.js init
  • #9823 : IE 8 crashes when using background-image on BODY in css
  • #9964 : test/support.js module strictEqual typo
  • #10029 : $.support.scriptEval removed, but still included in documentation

Please do file a bug report with a test case as soon as possible if you find problems, as described above. Blog comments or Twitter aren’t helpful bug reports!

Khan Exercise Rewrite

Posted July 28, 2011 by John Resig

Khan Exercise Framework Deployed

Today we're pushing live a complete rewrite of the Khan Academy Exercise framework (live demo ).

A big push at Khan Academy has been to write more-and-more exercises for students to practice with. Naturally, to increase the number of exercises that we have, we needed to make it easier for team members, and casual committers, to write them.

When I was first looking in to Khan Academy I did a bunch of digging through their code base (which is Open Source ) and noticed that a lot of effort was going in to writing exercises. Interestingly all the exercises were being written in pure JavaScript and were dependent upon the server component in order to run properly. To me this seemed like a massive barrier to entry.

Brand New Framework

When I started just over two months ago I immediately went about rewriting the framework to use semantic HTML and not rely upon any server-side components whatsoever. To provide an example of the change that was made here is one particular exercise, Significant Figures 1, written for the old framework and written for the new framework . You can view the live version of the exercise, as well.

Khan Exercise Code Comparison

Significant Figures 1 went from 191 lines of code down to 58.

Note the dramatic lack of "code" - most logic is encapsulated and reduced to a series of variable declarations (some with minimal logic). Additionally utility functions were made significantly more useful, and generic, shared across exercises (some of this was done in the old framework but a complete rewrite allowed us to find areas of obvious overlap).

The result of the new framework is an interesting mix of semantic markup and logic - wrapped in a form of highly specialized templating. Tons of details regarding the specifics of the framework can be found in the Writing Exercises tutorial .

In short, some of the cool new features of this framework include:

  • A full module system for dynamically loading specific utilities (such as graphing).
  • A brand new templating framework , including templating inheritance, that makes it easy to reduce repeated code in exercises (some examples ).
  • A brand new graphing framework (written by Ben Alpert, named 'Graphie') that's built on top of Raphael. This framework provides a simple API for creating all sorts of graphs and charts, it's used extensively throughout the exercises.
  • An extensible plugin system for creating new answer types (to expand beyond basic multiple choice or fill in the blank).

Of course, that's saying nothing of the actual user interaction as well. Most of the new framework's logic is contained on the client-side and is generated directly off of Khan Academy's REST API .

By moving logic to the client-side we're able to have a much more interactive experience (doing all problem generation on the client-side, doing Ajax-y background submissions, things of that sort).

Testing

A big concern for us, with this rewrite, was to ensure that the quality and integrity of exercises was maintained well into the future. We wanted to make sure that the content of the exercises were correct and that regressions do not occur over time.

In fact we have three levels of testing:

  1. We have unit tests for our modules and utility functions (ensures that stuff like the templating will continue to work correctly).
  2. We have an interactive interface for generating unit tests for any given exercise (details below).
  3. We have a "Report a Problem" interface for sending post-deployment issues directly to our bug tracker.

The second stage is particularly interesting. On a fundamental level it's hard to unit test something as complex as an exercise. While we can ensure that they still work at a functional level we can't verify if the problems make sense, or if graphs look correct, or if it's even possible to pick the right answer.

For these reasons we've introduced a new testing interface in which we use human developers as unit testers. When in test mode an additional panel is displayed asking the user to provide additional details regarding wether the problem is working correctly, or not. We ask them to really dig into the exercises and make sure that they're working correctly, hints are being displayed properly, and other things of that nature.

Khan Exercise Testing

All of this information is collected and distilled into a piece of JavaScript code that is dropped into our test suite , all pushed into QUnit. At the moment we have around 2414 unit test collections with over 10,000 assertions.

Khan Exercise Test Dump

At the moment we're working on ways of having better reporting and integration with our development process, for all those unit tests.

Development Process

I'm rather pleased with how the overall development process worked out. We actively kept both the code open (it's up on Github and it's MIT licensed) and the process open as well. We've had contributions from over twice as many outside contributors than members of the Khan Academy team (although the vast majority of the development was done by members of the team).

We have a detailed Getting Involved guide that explains how exactly anyone can participate in the development of the framework (or in the authoring of new exercises).

Predominantly we've been coordinating through a public HipChat room , using the Github Issue Tracker , and managing all the exercise work through a series of Google Spreadsheets.

We're going to be transitioning now into creating a ton more exercises and we'd love to have even more help from the community. There is a ton of information on how to get involved in the wiki .

Next Steps and Thanks

There are a few things that we're looking to do in the near future: Bring offline support to the exercises (for those with spotty internet connections or those using the upcoming iPad/Android application), client-side translation of content into other languages, and exercise answer checking using Node.js and JSDOM.

I also want to take this opportunity to thank everyone at Khan Academy, and all the community contributors, for helping to make this project happen. I especially want to thank Marcia Lee, Ben Alpert, Jeff Ruberg, Igor Terzic, Omar Rizwan, and Ben Kamens for their help in getting this out the door.

I should also mention that Khan Academy is hiring devs . We're looking for both server/client devs (Python/JavaScript) and also mobile devs (iOS and Android).

Random Khan Exercises

Posted July 19, 2011 by John Resig

We're taking an innovative new approach to providing students with exercises in the new Khan Academy exercise framework (which will be released for beta testing soon). In the old framework a problem would be randomly generated and provided to the user. This would result in a near-infinite number of randomly generated problems.

This ends up being a double-edged sword. While it's great to provide a ton of problem variety to the students it's fundamentally tricky as we want to have a manageable sample size of problems so that we can analyze student behavior and responses. For this reason we want to reduce the pool of possible problems to a more-manageable size (like about 200 or so - we'll experiment with exact figures as time goes by). Most students will only do about 10-20 problems before moving on (since we define a 'streak' as having completed 10 problems in a row correctly) - although we want to provide enough of a pool to allow adventurous users to explore more.

Having a smaller pool size creates another issue though: Potential for student overlap. If there's one thing that we've learned so far it's that students are quite resourceful and identify patterns very quickly. They will realize if they start on the same problem together and if the problems go in the same order.

On top of this we need to make it so that every time the student hits the exercise they are presented with the same exact series of exercises. The first problem will always be the same - and the 50th problem will always be the same for that user. (This will allow us to reproduce the problems at a later date, showing them their problems/answers or analyzing the results.)

Thus we need two pieces of information to determine which problem should be presented to a user: The user's ID and the problem # that they're currently tackling.

We start by placing the user into a simple "bin": We take the CRC32 of the student's ID and mod 200 to start the user at one of the 200 possible exercises. (We picked CRC32 as it's a simple function and we only need a basic level of granularity in the results.) Next we use the CRC32 to figure out how the user should jump through the exercises.

We can't jump through the exercises 1 by 1, since the students will instantly recognize that pattern, so we have to take a random approach - one developed by Khan Academy intern Ben Alpert .

We start with a pool of prime numbers (the first 23 primes, to be exact) and use the user's CRC32 to determine which of those primes will become the "jump distance" for that user.

For example:

var primes = [ 3 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 , 41 , 43 ,

  47 , 53 , 59 , 61 , 67 , 71 , 73 , 79 , 83 , 89 , 97 ] ;

var num = crc32( "jeresig" ) ;

// num = 1411847358

var problemNum = num % 200 ;

// problemNum = 158

var jumpNum = primes[ num % primes.length ] ;

// jumpNum = 71

 

Thus when I visit a particular problem I will start at problem # 158, then go to problem 29, then problem 100, then problem 171, etc. On the other hand, if user "jeresig2" visits the same problem they start at problem 171 then visit problem 182, 193, 4, etc.

(Note that we leave out 2 and 5 to avoid creating a circular loop of exercises - 2 will result in 100 repeating exercises, 5 will result in 40 repeating exercises. Of course we could just make the number of exercises prime to achieve a similar result - we'll see!)

Even though we're not using any built-in random number generator in this process, the distribution of chosen problems appears to be similar to a random distribution (since we've effectively implemented one ourselves):

Khan Problem Probability Distribution

To re-emphasize: We're not trying to stop problem overlap - in fact we want overlap to occur, to give us data to study - but a lack of repeatable patterns has definitely been arrived at here.

We chose a collection of 23 primes because it is sufficiently large - but it also doesn't divide into 200 cleanly (giving users that might have an identical starting position a different jump amount).

Also note that in the final solution we're going to be combining the user's ID with the name of the current problem - so that even if, somehow, two students end up with identical start positions and jump rates on one exercise they will have a different start position and jump rate on other exercises.

If all goes well we'll be opening up the new exercise rewrite for beta testing within the next week or two.

Note: I've been posting interesting dev updates over on Google Plus . Feel free to follow me there if you wish to find out more about what I'm working on with Khan Academy or jQuery.

jQuery 1.6.2 Released

Posted June 30, 2011 by John Resig

jQuery 1.6.2 Released

jQuery 1.6.2 is now out! This is the second minor release on top of jQuery 1.6 and lands a number of fixes for bugs.

As usual, we provide two copies of jQuery, one minified and one uncompressed (for debugging or reading).

You can feel free to include the above URLs directly into your site and you will get the full performance benefits of a quickly-loading jQuery.

You can help us by dropping that code into your existing application and letting us know that if anything no longer works. Please file a bug and be sure to mention that you’re testing against jQuery 1.6.2.

We want to encourage everyone from the community to try and get involved in contributing back to jQuery core. We’ve set up a full page of information dedicated towards becoming more involved with the team. The team is here and ready to help you help us!

jQuery 1.6.2 Change Log

The current change log of the 1.6.2 release.

Attributes

  • #9286 : Using live submit on forms
  • #9298 : $(elem).attr(eventName) not working properly in IE7
  • #9329 : attr(“title”) issue in ie7
  • #9362 : .attr(“value”) does not work for meter elements
  • #9468 : $(‘form’).attr(‘class’) always return undefined in IE 6
  • #9499 : removeClass will only remove the first instance of a class

Core

  • #9301 : Setting data() via an object with hyphenated keys create inaccessible data.
  • #9368 : jQuery.camelCase() defined in css.js, but used more widely
  • #9471 : memory leak noticed when loading jquey.1.6.1.min.js included html pages in the iframe

CSS

  • #7557 : outerWidth()
  • #9237 : .css() doesn’t work with relative values on hyphenated properties

Dimensions

  • #9300 : outerWidth(true) issue

Effects

  • #9220 : Animation Callbacks fire AFTER the next queue function executes.
  • #9678 : setInterval cleared by animation

Event

Manipulation

  • #8950 : (Chrome, Firefox) Second argument (event empty) in jQuery throws error while creating <input>
  • #9370 : Compatibility Issue with jQuery 1.6 and IE6

Support

  • #9239 : Version 1.6.0 breaks the background behavior on body element
  • #9440 : v1.6.1 messes up layout in IE8

Registration Open for jQuery Conference in Boston!

Posted June 28, 2011 by Leah Silber

Hey everyone!

We recently announced the dates for our next jQuery Conference—October 1st and 2nd in Boston, MA —and we’re finally ready to open registration ! Here are some top level bullet points for you:

  • 2 days of jam-packed content from the jQuery Core Team and top community members, covering everything from jQuery basics and advanced techniques, to jQuery UI, jQuery Mobile, and more
  • A new limited-run jQuery tshirt and other jQuery swag
  • A fabulous Boston after party, hosted by our friends over at MediaTemple with free booze, snacks, great company and more
  • Other sweet after-hours events, announcements coming soon

Back by popular demand, we’ve also got a full day of Beginner jQuery Training for the new folks on your team, generously provided by our friends over at Bocoup . We’ll likely be adding additional topical and/or advanced training sessions, so keep an eye here and on Twitter for announcements and updates on that.

New for this year: For the first time ever, we’ve really got an official jQuery Conference Hotel . We’ve had suggested multiple hotels in the past, but this year we’ve secured a fantastic block at the conference venue , arranged for the Core Team and speakers to stay there, and have also thrown in some hotel-guest-only perks, like priority registration and swag distribution. We’ll also be organizing some on-site evening gatherings at the hotel, and hotel guests will receive priority registration for any of those as well.

The room block we secured last year—which didn’t have these extra perks—sold out well before the conference, so make sure you book your room ASAP, and make sure it’s part of our specific room block.

The Call for Papers is still open, so if you haven’t submitted your talk yet, definitely get on that.  Speakers receive access to a fantastic speaker thank you dinner, free accommodations at the conference hotel, and if budget allows it, additional TBD renumeration.

That’s it for now; we’ll have more announcements soon as we roll out the speaking roster, announce more party details and finalize all the other conference-related goodness.

Register Now !



jQuery UI Checkbox/Radio Buttons

Posted June 24, 2011 by Benjamin Sterling

Recently I’ve had the good fortune to getting back into using jQuery and jQuery UI on a new and exciting project after a year and a half of using DOJO and MooTools – both are very good languages in their own right but not my cup of tea.  And one the things I think are really missing with jQuery UI are form controls.  There is progress being made. For instance with the select menu , still some holes from a styling perspective, but solid.  There is also the buttons widget that help with getting buttons – whether you are talking about <A>, <BUTTON> or <INPUT> – to function correctly cross browser.  And although the button widget has some “checkbox/radiobutton” type interactions it does not pass 508 testing on the project I am working on.

So, one of the bigger holes in opinion is with checkboxes and radio buttons and since I’ve had the benefit of working with Dijit and having it pass a very rigorous 508 testing process I figured the best approach is to mimic, in a much less-code kinda way, what Dijit was doing.

So, with out much more blabbering on, below are a few examples of the checkboxes and radio buttons:

First we have the checkboxes:

Then we have the radio buttons:

Some thoughts

So it’s basic and it works and keeps all the basic functionality that comes with standard radio buttons and checkboxes. This is, in my opinion, what any widget that overrides a form control should do.

What probably needs to be taking into account is, what if styles are turned off? What happens if images are disabled? Do we check for these and if styles are off or images are off don’t build? Not sure, maybe that is something to deal with on a per project basis?

Currently if you do something like $( “input[type=radio]:eq(2)” ).prop( ‘checked’, true ); or even $( “input[type=radio]:eq(2)” ).get(0).checked = true; and you are not using the widget the radio button will change accordingly, but not if you are using the widget. The change event is not being triggered. Will need to look into this a bit more.  Thoughts? Not longer an issue, put a setInterval in to check for the change of the checked property and seems to be working correctly.

The checkbox and radio button width are only supporting jQuery 1.6+, it is using the .prop method throughout.  If you need to use it with an earlier release of jQuery you just need to swap those .prop methods out for the .attr method.

As I stated before, this method of doing the radio buttons and checkboxes have been tested fairly well for 508 compliancy so I am pretty confident it should work for you.  However, with everything we do, there is always room for improvement so please let me know via github if you believe you have those improvements.

Lastly, I tried my best to follow the standards that were set on the jQuery UI wiki but please get with me on items I can improve.

The Source

https://github.com/bmsterling/jquery-ui

Please submit any bugs or issues you have on github , I will not respond to those issues within the comments (or at least can’t effectively).

Update

06/25/2011 : Updated the code to allow for onchange to trigger when the checked property has changed.

jQuery Conference 2011: Boston Conference Dates

Posted June 22, 2011 by Ralph Whitbeck

We are very happy to announce the dates and venue for the 2011 Boston jQuery Conference . We will hold our annual Boston Conference on October 1—2, 2011, at the Royal Sonesta Hotel in Cambridge, MA.

Call for Speakers

We are officially opening a call for speakers . If you would like to speak at the conference on topics such as jQuery, JavaScript, HTML5, CSS3, or general front-end development, please submit your talk proposal to us by July 15th . Speakers will be notified, confirmed, and announced within a week after the deadline.

Registration

We will be opening registration soon. You can fill out the form on the events home page and be notified the instant tickets are available.

Hotel

We have worked with the Royal Sonesta Hotel and have a huge block of rooms reserved for the conference. The Royal Sonesta is providing a discounted room rate of $273.53/night (includes tax). If you make your reservation over the phone, please let them know that you are staying for the jQuery Conference to get the discount. You can also reserve your room online . Please use the coded website link on the hotel page of the event site to ensure you get the discounted rate.

More information

If you or your company are interested in sponsoring this event, please contact us to find out more information.

We’re aware that, unfortunately, this year’s Boston conference overlaps JSConf.eu. We considered a number of dates, but had to settle on the 1st and 2nd. We are truly sorry if this presents a conflict for you and hope you can enjoy a weekend of JavaScript on either side of the Atlantic.

jQuery 1.6.2 RC 1 Released

Posted June 14, 2011 by John Resig

This is a preview release of jQuery. We’re releasing it so that everyone can start testing the code in their applications, making sure that there are no major problems.

You can get the code from the jQuery CDN:

You can help us by dropping that code into your existing application and letting us know that if anything no longer works. Please file a bug and be sure to mention that you’re testing against jQuery 1.6.2 RC 1.

We want to encourage everyone from the community to try and get involved in contributing back to jQuery core. We’ve set up a full page of information dedicated towards becoming more involved with the team. The team is here and ready to help you help us!

jQuery 1.6.2 RC 1 Change Log

The current change log of the 1.6.2 RC 1 release.

Attributes

  • #9286 : Using live submit on forms
  • #9298 : $(elem).attr(eventName) not working properly in IE7
  • #9329 : attr(“title”) issue in ie7
  • #9362 : .attr(“value”) does not work for meter elements
  • #9468 : $(‘form’).attr(‘class’) always return undefined in IE 6
  • #9499 : removeClass will only remove the first instance of a class

Core

  • #9301 : Setting data() via an object with hyphenated keys create inaccessible data.
  • #9368 : jQuery.camelCase() defined in css.js, but used more widely
  • #9471 : memory leak noticed when loading jquey.1.6.1.min.js included html pages in the iframe

Css

  • #7557 : outerWidth()
  • #9237 : .css() doesn’t work with relative values on hyphenated properties

Dimensions

  • #9300 : outerWidth(true) issue

Effects

  • #9220 : Animation Callbacks fire AFTER the next queue function executes.

Event

Manipulation

  • #8950 : (Chrome, Firefox) Second argument (event empty) in jQuery throws error while creating <input>
  • #9370 : Compatibility Issue with jQuery 1.6 and IE6

Support

  • #9239 : Version 1.6.0 breaks the background behavior on body element
  • #9440 : v1.6.1 messes up layout in IE8

Simple use of Event Delegation

Posted June 14, 2011 by Remy
Event delegation may be some techie term that you’d rather shy away from, but if you’ve not already used it, this example will show you a simple but powerful use of event delegation. Watch Watch Simple Event Delegation (Alternative flash version) QuickTime version is approximately 22Mb, flash version is streaming. View the demo used in [...]



Using SproutCore 2.0 with jQuery UI

Posted June 11, 2011 by wycats

One of the goals of SproutCore 2.0 is to make it trivial to integrate the tools you’re already using together with SproutCore.

One way that we do that is to make it possible to drop a SproutCore app into a small part of your existing page. Greg Moeck did a great job demonstrating this functionality on the SproutCore Blog a couple of weeks ago, and I’d definitely recommend checking it out if you’re interested in learning more about embedding SproutCore 2.0 in an existing app.

Another complementary approach is to make it easy to integrate SproutCore with existing JavaScript libraries and tools. Because SproutCore 2.0 uses templates as the primary way to build your application, it integrates well with the tools you’re already using. In this post, I’ll show you the hooks you need to integrate SproutCore with anything you want, and then show you how to do a general-purpose integration with jQuery UI.

Quick Refresh: Handlebars Templates

First of all, you can take any piece of HTML and attach it to a SproutCore view. You would typically do this in order to attach event handlers to the view or to define a function that computes how a particular value should be displayed. For instance, let’s say we have some HTML that shows a business card for a person:

<div
 class
="card"
>


  <p
 class
="name"
>

{{salutation}} {{fullName}}</p>



  <p
 class
="address"
>

{{number}} {{street}}</p>



  <p
 class
="region"
>

{{city}}, {{state}} {{zip}}</p>



</div>



We can wrap this chunk of HTML in a SproutCore view, which will define the sources of each of the properties used in {{}}} .

<script
 type
="text/html"
>


{{#view Yehuda.BusinessCard contentBinding="Yehuda.businessContent"}}
  <div
 class
="card"
>


    <p
 class
="name"
>

{{content.salutation}} {{fullName}}</p>



    <p
 class
="address"
>

{{content.streetNumber}} {{content.street}}</p>



    <p
 class
="region"
>

{{content.city}}, {{content.state}} {{content.zip}}</p>



  </div>



{{/view}}
</script>



Wrapping the HTML snippet in a <script> tag tells SproutCore to render it using its template engine. You’d normally get the {{}} properties from a controller or other data source, but let’s define a view with the values baked in for now:

Yehuda.BusinessCard
 =
 SC.View
.extend
(
{

  // fill in the content in the template with contentBinding

  content:
 null
,

 
  fullName:
 function
(
)
 {

    return
 this
.get
(
'firstName'
)
 +
 ' '
 +
 this
.get
(
'lastName'
)
;

  }
.property
(
'content.firstName'
,
 'content.lastName'
)

}
)
;

 
Yehuda.businessContent
 =
 SC.Object
.create
(
{

  firstName:
 "Yehuda"
,

  lastName:
 "Katz"
,

  salutation:
 "Mr."
,

  streetNumber:
 300
,

  street:
 "Brannan"
,

  city:
 "San Francisco"
,

  state:
 "CA"
,

  zip:
 "94107"

}
)
;

If we reload the page, we will see a static business card with my information in it. If we update my content with Yehuda.businessContent.set(key, value) , SproutCore will automatically update the HTML for you. If you update any property, including firstName or lastName , which are used only as dependencies of fullName , SproutCore will automatically handle updating the HTML for you.

didCreateElement

You can also define some code to run every time an element is rendered. You can use this hook to wire up any JavaScript library to the element that SproutCore has created. For instance, let’s say we want to zebra stripe the three lines in our business card once it has been create (note: you probably would not use JS to zebra stripe in real life).

Let’s extend our view:

Yehuda.BusinessCard
 =
 SC.View
.extend
(
{

  // fill in the content in the template with contentBinding

  content:
 null
,

 
  fullName:
 function
(
)
 {

    return
 this
.get
(
'firstName'
)
 +
 ' '
 +
 this
.get
(
'lastName'
)
;

  }
.property
(
'content.firstName'
,
 'content.lastName'
)
,

 
  didCreateElement:
 function
(
)
 {

    this
._super(
)
;

    this
.$(
"p:even"
)
.addClass
(
"even"
)
;

  }

}
)
;

First of all, you will want to call super, to ensure that any hooks in parent classes get called. Second, all SproutCore views have a $ function, which is the normal jQuery function, scoped to the current element. You can also call this.$() to get back a jQuery object wrapping the element itself.

You can use this hook to do anything you want, allowing you to hook in any library you want. You would use this hook a lot like you’d use a jQuery(document).ready hook, but scoped to the view being created.

SproutCore also provides a willDestroyElement hook, which you can use to tear things down that you set up when the element was created. This is relatively rare, and is mostly used when interfacing with another toolkit that requires a teardown, or to tear down custom SproutCore observers.

jQuery UI

We can use these hooks to build some basic integration with jQuery UI. I’ve written a demo that shows how to connect SproutCore bindings to jQuery options at http://sc20-jqui.strobeapp.com/ . You can also check out the annotated source code .

The most important thing to look at is the JQ.Widget mixin, which can be mixed into view classes to attach jQuery UI options and events to SproutCore’s binding and event system.

You can get started with the SproutCore 2.0 developer preview by downloading the starter kit .

Until next time!

jQuery Color v2 Beta 1 Released

Posted May 31, 2011 by Corey Frang

Back in 2007 we released the jQuery Color Plugin, and it has been providing you with color-based animations ever since. We are now preparing a second version of this plugin which adds an API, RGBA, HSLA, and many other features. It is time for a beta! The repository for this plugin can be found at github.com/jquery/jquery-color .  There are also uncompressed and minified versions available on code.jquery.com.

New Feature Overview:

RGBA

We now support RGBA color values. In browsers that don’t support RGBA, the nearest backgroundColor to the element will be used to calculate a “blended” approximation of the color. Although this isn’t “true” alpha, it will at least provide the illusion of alpha when dealing with solid background colors.  This is a screenshot of Opera 10, Chrome 10, Firefox 3.6, and IE 6 all running this demonstration of alpha blending :

Opera 10, Chrome 10, Firefox 3.6, and IE 6  demonstrating alpha blending

HSLA

We also now support using HSLA color values across all browsers, with the execption of alpha, which uses the same techniques described above.

Easy-to-use API

Instead of a simple group of private utility methods, $.Color() now creates a new Color object. The new Color object can be initialized in a few different ways: color names, hexidecimal color codes, css style rgba/hsla, an array of rgba values, or an object with the color properties. There are now helper methods for each color property, like .red() and .hue() that can get or set the particular value. Combined with helper functions like .toRgbString() , .transition() and .is() , $.Color can now handle whatever color needs you might have. Refer to the README on github.com/jquery/jquery-color for an overview of all the new functions available. No longer is jQuery.Color just providing you with animation of simple colors, you can now use its API to do complex color calculations and animations!

Quick Examples:

// Create a red Color object:
var red = $.Color( 'rgba(255,0,0,1)' ); // using a css string

// Create a red Color object, then make orange:
var orange = $.Color( '#FF0000' ).green( 153 );

// Get the color halfway between red and blue:
var between = $.Color([ 255, 0, 0 ]).transition( "blue", 0.5 );

Animating Partial Colors

We have added support for only defining one or two properties of a color object so that you can animate using a partial color like this :

// desaturate the background of this element
elem.animate({
    backgroundColor: $.Color({ saturation: 0 })
}, 1000);

Reporting Problems / Requesting Features:

If you find any problems with the new color plugin, or would like to request a feature, please create a github issue .

Also, we’d love to see and showcase some excellent uses of the new $.Color beta, so please be sure to share it with us in the comments.

Release: Validation Plugin 1.8.1

Posted May 14, 2011 by Jörn

An update for the jQuery validation plugin is available. This brings compability with jQuery 1.6.1, while staying backwards compatible with 1.3.2, 1.4.2, 1.4.4 and 1.5.2 .

The bug was related to the plugin’s usage of the form.elements property, which jQuery 1.6 doesn’t support anymore. Other then that, there is a bug fix for adding and removing the error and valid classes on radio and checkbox elements (thanks to Phil Haack for the contribution), as well as two new localizations: Thai and Vietnamese. That brings the plugin to a total of 37 supported locales.

If you’ve been testing 1.8.0 release with jQuery 1.6 and couldn’t get it to work, despite the note saying that its working, please update to 1.8.1. The form.elements fix was in place before 1.6 final got released, and I only tested against latest code on GitHub, while 1.8.0 was indeed broken.

Download this release.

The full changelog:

  • Added Thai (TH) localization, fixes #85
  • Added Vietnamese (VI) localization, thanks Ngoc
  • Fixed issue #78. Error/Valid styling applies to all radio buttons of same group for required validation.
  • Don’t use form.elements as that isn’t supported in jQuery 1.6 anymore. Its buggy as hell anyway (IE6-8: form.elements === form).
  • Please post questions to the official Using jQuery Plugins Forum , tagging your question with (at least) “validate”. Keep your question short and succinct and provide code when possible; a testpage makes it much more likely that you get an useful answer in no time.
  • Please post bug reports and other contributions (enhancements, features, eg. new validation methods) to the GitHub issue tracker

Enjoy!

jQuery 1.6 and .attr()

Posted May 13, 2011 by John Resig

jQuery 1.6 and 1.6.1 are out the door. Congrats to the team and everyone that was involved with the release!

A relatively controversial change in 1.6 was regarding how attributes and DOM object properties were handled. In 1.6 we wanted to take the major step of completely separating the two, allowing us to create an .attr() method that wasn't quite so mealy-mouthed with regards to how attributes were handled. We did this in 1.6 because we felt that it was a substantial change (we only do major changes in the 1.x major releases of jQuery) and had the possibility of affecting people.

We did a considerable amount of testing on the code and we were quite confident that the amount of problems that people would encounter, while upgrading, would be quite minimal. The biggest pain points, we surmised, would be regarding how boolean attributes were handled (attributes like "disabled" or "selected"). However most of this would be mitigated and would likely have worked fine for users that consistently used .attr() to access and update their attributes.

After making the changes, and publishing 1.6, there were enough complaints that we had changed the API to cause us to reconsider and return .attr() to its sometimes-attribute, sometimes-property, state.

jQuery is in an incredibly tricky position now (and has been for some time). We very rarely add features to the library, for fear of bloat and added API maintenance overhead, and are rarely able to make any sort of API change, for fear of preventing people from upgrading.

Thankfully even though we've reverted some of the changes in 1.6, we've done it in a way that still maintains the performance gains that we achieved with the 1.6 release.

I wanted to try and summarize the .attr() method , to explain how it currently works in 1.6.1, but ended up writing up a sample function instead (note that this is a bit of an over-simplification, please read the code for more details):

function attr( elem, name , value ) {

  // Are we setting a value?

  if ( value !== undefined ) {

    // Make sure the element has the ability to set an attribute

    if ( typeof elem.setAttribute !== "undefined" ) {

      // If the user is setting the value to false

      if ( value === false ) {

        // Completely remove the attribute

        elem.removeAttribute ( name ) ;

     

      // Otherwise set the attribute value

      } else {

        // If the user is setting the value to true,

        // Set it equal to the name of the attribute

        // (handles boolean attributes nicely)

        elem.setAttribute ( name , value === true ? name : value ) ;

      }

   

    // If it doesn't, then we're likely dealing with window or document

    // (or some other object entirely)

    } else {

      elem[ name ] = value;

    }

 

  // Otherwise we're getting an attribute value

  // Check to see if the appropriate method exists

  // Also don't use getAttribute if a boolean property exists

  } else if ( typeof elem.getAttribute !== "undefined" &&

              typeof elem[ name ] !== "boolean" ) {

    return elem.getAttribute ( name ) ;

 

  // If no getAttribute method is present, or if we

  // wish to access the boolean property instead of the

  // attribute, then we fallback to the DOM object property

  } else {

    return elem[ name ] ;

  }

}

Ironically this isn't much shorter than the actual .attr() implementation , I recommend that you check it out.

There's a very good chance that your code, written targeting 1.5.2, will continue to work just fine in 1.6.1 using this particular technique.

However this point now begs the question: Why does .prop() exist?

In short, for two reasons:

  1. There are legitimate use cases for interacting with some DOM properties (such as nodeName , selectedIndex , or defaultValue ) and we want to provide a simple solution for accessing, and mutating, them.
  2. Accessing properties through the .attr() method will be slightly slower than accessing them directly through .prop() (as .attr() calls .prop() internally in order to handle all property-related mutation).

In jQuery 1.5.2, and older, in order to access a DOM property you would have to do something like this:

var elem = $( "#foo" ) [ 0 ] ;

if ( elem ) {

  index = elem.selectedIndex ;

}

In 1.6+ you can just do:

index = $( "#foo" ) .prop ( "selectedIndex" ) ;

Summary: There's a good chance that your code won't be affected at all with the changes that've happened, especially so with the changes in 1.6.1, and jQuery now has a convenience method for handling DOM properties in a simpler, and slightly faster, manner.

Tangentially this reminds me of a common question that I hear: What will be in jQuery 2.0? I have no idea what will be in that release, should it ever arrive, but I do know what won't be in it: A massive API change of any sort. Even when we make, relatively minor, API changes like in the 1.6 release the amount of negative feedback that we get is monumental. If we've learned anything after doing 31 releases of jQuery it's that people like having stability in their API and will cherish that over everything else.

I do want to thank the community though for being so vocal and working to communicate with the team so actively. Without the community's communication and support it's doubtful that the team would be able to continue operating.

I would like to take this opportunity to encourage everyone to get involved with the development of jQuery. We hold active discussions every day in IRC and hold public meetings once a week. We also post weekly status updates if you wish to follow along. Right now we're working on the 1.7 release of the library and are actively encouraging contributions and feedback. If you want to help ensure the quality and stability of the next release of jQuery, the best way to do so is to get involved. Hope to see you around the bug tracker.

jQuery 1.6.1 Released

Posted May 12, 2011 by John Resig

We’re pleased to announce the first update to jQuery 1.6!

You can get the code from the jQuery CDN:

Additionally you can also load the URLs directly from Microsoft and Google’s CDNs:

Microsoft CDN: http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.1.min.js

Google CDN: https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js

You can help us by dropping that code into your existing application and letting us know that if anything no longer works. Please file a bug and be sure to mention that you’re testing against jQuery 1.6.1.

We want to encourage everyone from the community to try and get involved in contributing back to jQuery core. We’ve set up a full page of information dedicated towards becoming more involved with the team. The team is here and ready to help you help us!

Upgrading From 1.5.2 to 1.6.1

With the introduction of the new .prop() method and the changes to the .attr() method, jQuery 1.6 sparked a discussion about the difference between attributes and properties and how they relate to each other. It also came with some backwards compatibility issues that have been fixed in 1.6.1. When updating from 1.5.2 to 1.6.1, you should not have to change any attribute code.

Below is a description of the changes to the Attributes module in jQuery 1.6 and 1.6.1, as well as the preferred usage of the .attr() method and the .prop() method. However, as previously stated, jQuery 1.6.1 will allow you to use .attr() just as it was used before in all situations.

Note that the changes described in the 1.6 release notes regarding the .data() method have been worked around and now work seamlessly between 1.5.2 and 1.6.1.

What’s Changed

The changes to the Attributes module removed the ambiguity between attributes and properties, but caused some confusion in the jQuery community, since all versions of jQuery prior to 1.6 have handled attributes and properties in one method(.attr() ). The old .attr() method had many bugs and was hard to maintain.

jQuery 1.6.1 comes with several bug fixes as well as an update to the Attributes module.

Specifically, boolean attributes such as checked, selected, readonly, and disabled in 1.6.1 will be treated just as they used to be treated in jQuery versions prior to 1.6. This means that code such as

$(“:checkbox”).attr(“checked”, true);
$(“option”).attr(“selected”, true);
$(“input”).attr(“readonly”, true);
$(“input”).attr(“disabled”, true);

or even:

if ( $(“:checkbox”).attr(“checked”) ) { /* Do something */ }

will not need to be changed in 1.6.1 in order to work as previously expected.

To make the changes to .attr() in jQuery 1.6 clear, here are some examples of the use cases of .attr() that worked in previous versions of jQuery that should be switched to use .prop() instead:

.attr() Proper .prop() usage
$(window).attr… $(window).prop…
$(document).attr… $(document).prop…
$(“:checkbox”).attr(“checked”, true); $(“:checkbox”).prop(“checked”, true);
$(“option”).attr(“selected”, true); $(“option”).prop(“selected”, true);

First, using the .attr() method on the window or document did not work in jQuery 1.6 because the window and document cannot have attributes. They contain properties (such as location or readyState) that should be manipulated with .prop() or simply with raw javascript. In jQuery 1.6.1, the .attr() will defer to the .prop() method for both the window and document instead of throwing an error.

Next, checked, selected, and other boolean attributes previously mentioned are receiving special treatment because of the special relationship between these attributes and their corresponding properties. Basically, an attribute is what you see in the html:

<input type=”checkbox” checked=”checked”>

Boolean attributes such as checked only set the default or initial value. In the case of a checkbox, the checked attribute sets whether the checkbox should be checked when the page loads.

Properties are what the browser uses to keep track of the current values. Normally, properties reflect their corresponding attributes (if they exist). This is not the case with boolean attributes. Boolean properties stay up to date when the user clicks a checkbox or selects an option in a select element. The corresponding boolean attributes do not. As was stated above, they are used by the browser only to store the initial value.

$(“:checkbox”).get(0).checked = true;
// Is the same as $(":checkbox:first").prop(“checked”, true);

In jQuery 1.6, setting checked with

$(“:checkbox”).attr(“checked”, true);

would not check the checkbox because it was the property that needed to be set and all you were setting was the initial value.

However, once jQuery 1.6 was released, the jQuery team understood that it was not particularly useful to set something that the browser was only concerned with on page load. Therefore, in the interest of backwards compatibility and the usefulness of the .attr() method, we will continue to be able to get and set these boolean attributes with the .attr() method in jQuery 1.6.1.

The most common boolean attributes are checked, selected, disabled, and readOnly, but here is a full list of boolean attributes/properties that jQuery 1.6.1 supports dynamically getting and setting with .attr() :

autofocus, autoplay, async, checked, controls, defer, disabled,
hidden, loop, multiple, open, readonly, required, scoped, selected


It is still recommended that .prop() be used when setting these boolean attributes/properties, but your code will continue working in jQuery 1.6.1 even if these use cases are not switched to use the .prop() method.

Below is a list of some attributes and properties and which method should normally be used when getting or setting them. This is the preferred usage, but the .attr() method will work in all attribute cases.

Note that some DOM Element properties are also listed below – but will only work with the new .prop() method.



Attribute/Property .attr() .prop()
accesskey
align
async
autofocus
checked
class
contenteditable
defaultValue
draggable
href
id
label
location *
multiple
nodeName
nodeType
readOnly
rel
selected
selectedIndex
src
style
tabindex
tagName
title
type
width **

* For example, with window.location

** If needed over .width()

Neither .attr() nor .prop() should be used for getting/setting value . Use the .val() method instead (although using .attr(“value”, “somevalue”) will continue to work, as it did before 1.6).

Summary of Preferred Usage

The .prop() method should be used for boolean attributes/properties and for properties which do not exist in html (such as window.location). All other attributes (ones you can see in the html) can and should continue to be manipulated with the .attr() method.

jQuery 1.6.1 Change Log

The current change log of the 1.6.1 release.

Attributes

  • #9071 : $(‘<option></option>’).val(‘myValue’) no longer sets value
  • #9079 : .attr(“selected”) returns non-useful value in 1.6
  • #9089 : 1.6 atrr() Inconsistant in IE7,8
  • #9094 : Issue with jQuery 1.6: Can’t uncheck checkboxes
  • #9103 : .attr(‘foo’, true) not setting related DOM property
  • #9123 : Strange behavior of attr method when generate input element.
  • #9129 : jQuery does not support enumerated attributes such as contenteditable
  • #9191 : attr checked bug on radio

Data

  • #9124 : Changes to $.data illogical in certain case
  • #9126 : jquery breaks on use strict

Deferred

  • #9104 : Returning null or undefined in a pipe filter function causes an exception

Effects

  • #9074 : Cannot animate position and opacity at same time
  • #9100 : Order of hide() callbacks has changed

Event

  • #9069 : when hover over a child of an element, mouseleave fires when using live or delegate

Manipulation

  • #9072 : jQuery 1.6 Crashes IE 6
  • #9221 : Javascript within AJAX fails to load in IE – Error 80020101

Queue

  • #9147 : Variable tmp in promise implicitly declared?

Selector

  • #7341 : Slow .add() in IE
  • #9096 : Selector or find bug in jQuery 1.6
  • #9154 : :reset pseudo-selector broken

Support

  • #8763 : Unhandled exception: document.defaultView.getComputedStyle(div, null) is null (FF, hidden iframe)
  • #9109 : support.boxModel now false in IE6 even when not in quirks mode
h2 { font-size: 28px !important; } h3 { font-size: 22px !important; } h4 { font-size: 18px !important; } pre { padding: 5px; border: 1px solid #DDD !important; font-size: 14px !important; } table { font-size: 14px; } td, th { padding: 5px; }