Plugins Site Update: The Old Is New Again

Posted on by

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; 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 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.

What Is Happening To The jQuery Plugins Site?

Posted on by

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, 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 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.


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.


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
  • We are very sorry, but also very excited!

jQuery Conference 2012: UK – Training Workshops Announced

Posted on by

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 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 on by

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 on by

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 for that) and create a bug report at

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.


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


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


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


  • #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


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


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


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


  • #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”


  • #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


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


  • #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 on by

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 on by

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.


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


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


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


  • #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


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


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


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


  • #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


  • #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


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


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

Upcoming jQuery Events

Posted on by

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.


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:



  • 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



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


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

Building a Slimmer jQuery

Posted on by

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 on by

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.

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);


$('.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);

$(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.


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.


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 and a fresh copy is built each time a new commit is made to our master branch at 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 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.


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


  • #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
  • #10429: IE7 – invalid procedure call or argument when calling removeAttr(‘contenteditable’);
  • #10514: removeAttr does not remove the class attribute in IE6/7


  • #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


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


  • #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


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


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


  • #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


  • #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 “”
  • #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


  • #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()


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


  • #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


  • #5145: = false in the Chrome browser
  • #6809: