jQuery .end() explanation & examples

jQuery's .end() method is one of the most rarely used methods that I know of. In this post I would like share remind you what it does and how we can use it to make our jQuery code more readable.

Firstly, what does it do?

Put simply .end() cancels the last filtering action and returns a set like it was before the filtering was applied. It's best explained with an example. Consider we have this HTML code:

<ul>
  <li>One</li>
  <li>Two</li>
  <li class="special">>Three</li>
</ul>
$('li')  // would have all 3 elements

$('li').filter('.special')  // would have 1 (third) element only

$('li').filter('.special').end()  // would have all 3 elements again

Now, the main question: Why on earth would you need it?! It is actually very useful when you have to apply different methods on several sub-selections in your DOM. The game development fits this case perfectly. I have seen beautiful and easy to understand game code that was made possible by a combination of custom jQuery selectors, extending jQuery and .end() method.

Couple of examples

To give you an idea of what a code of some hypothetical game might look like:

check_mines = function(from, to_coord){  // don't pay attention to this building block
     $("#game-canvas")

          .find("div:ships")
               .moveElements(from, to_coord)
          .end()

          .find("div:mines")
               .killIfClose(to_coord)
          .end()

          .find("div:healthPack")
               .addHealthIfClose(to_coord)
               .markHealthPackUsed(to_coord)
          .end();

};
SomeGame.register(check_mines);  // don't pay attention to this building block

As you can see, .end() helps us group related actions and make the code more readable.

Let's consider more realistic case. Let's say we have an article with images, links etc. (eg. Wikipedia articles). We need to add .content-img class to all images, than add .external-link to all external links, and finally apply a tooltip plugin to all the links that have .tooltip class within the article.

<div class="article">
     <p>Text ... </p>
     ...
</div>
$(".article")

    .find("img")
        .addClass("content-image")
    .end()  // back to .article set

    .find("a:external")
        .addClass("external-link")
    .end() // back to .article set

    .find("a.tooltip")
        .tooltip()
    .end(); // don't really need it here, but nice to have for symmetry

The above case is better written in 3 separate lines of codes of course, but it here to help explain the purpose of the .end().

NOTE:
If you do several filtering, you must call .end() several times as well.

$(".article").find("a").filter(".tooltip").end().end();

Hope you will find useful cases for .end() in your projects.

Bind jQuery events to tab or window close

This post shows you how to bind JavaScript functions that will fire when user navigates away from your page, closes browser or a tab. Browsers have native JavaScript events on window object: unload and beforeunload. beforeunload is a proprietary event introduced by Microsoft and supported by other browsers, but not all.

Please note, these events will be fired when user navigates away from the current page. This includes when user:

  • closes the browser or a tab;
  • clicks on any link (does not matter if it's to other domain or the current domain);
  • types any URL to the browser bar and leaves the page;
  • clicks browser's page reload, back, forward buttons.

NOTE
You must test your code, because the behavior of how browsers handle unload event has changed even in different versions of the browsers.

Catching browser/tab close event with JavaScript

Since unload is a native JavaScript event, we can get away without using jQuery at all.

window.onunload = function(){
    // do some clean up
    clearLocalStorage();
};

If you are using alert(), confirm() or making AJAX requests here, please see what browsers block them belove.

Subscribing to browser/tab close using jQuery

jQuery introduced $.unload() event shorthand in v1.0 and deprecated it in v1.8. $.unload() is a shorthand for .bind('unload', handler).

$(window).unload(function() {
    // Do some code clean up
});

How browsers handle alert(), confirm() and AJAX requests on unload event?

The document unload event was originally designed to let JavaScript to do some clean up. For example, clear or set cookies, but most of the time it is used to fire alert/confirm box or make an AJAX request to the server. This led to bad user experience and browsers started to block these methods in unload event.

Here is what each browser does:

  • Chromer/Safari (WebKit)
    • alert(), confirm() - blocked (confirm() returns false), AJAX request - not sent.
  • Firefox
    • alert(), confirm() - blocked (throws an internal NS_ERROR_NOT_AVAILABLE exception), AJAX requests - sent on page reload, but not on tab close.
  • IE9
    • alert(), confirm() - not blocked, AJAX requests - not sent.
  • Opera
    • alert(), confirm() - blocked, AJAX requests - not sent.

Browsers that have pop-up window blockers will block all window.open() function calls in unload event handler.

No jQuery? Nothing to do here!

Sometimes, including JavaScript library is an overkill. Example: just to get focus on form field. But sometimes, persisting on writing your own javascript library for a task that is solved by an existing framework is double overkill. And this Fridays humor post is just about that... )

NOTE: I am not against developers creating new stuff and challenging existing norms, on the very contrary. That's how "next great things" are built. I just don't get when we reject to harness the benefits of collective effort...

8+ methods that will not work in jQuery 1.9

There have been many method additions and deprecations in the last jQuery releases, but never so many changes that remove previous deprecations and make backward incompatible changes in a single release. Final release of jQuery 1.9 will be announced today. This article will help you get an overview of what’s changing and how to get prepared. So lets review these changes.

1) $.browser is no longer available

$.browser added in v1.0, deprecated since v1.3 and now it's gone. If possible use browser feature detection ($.support) instead of browser sniffing ($.browser). The documentation says that it may be moved to a plugin, but it's not yet (well, not considering jQuery Migrate of course). If you haven't used $.support before, we will cover it in our next post.

For those who really need just the browser sniffing feature back, you can copy-paste the highlighted code from jQuery 1.8.3's core here.

2) .andSelf() is renamed to .addBack()

.andSelf() added in v1.2, deprecated in v1.8. It's used for adding previous selection set to the current set in the chain.

For example: $('.first-set').children().andSelf() - would return a set with all children of the .first-set, plus .first-set's themselves. It took no arguments and now it has been replaced by .addBack() method that does the exact same thing, but accepts optional selector argument to filter out the set. So with the example above you could say: $('.first-set').children().addBack('div') - return all children of .first-set, plus .first-set's that are <div>s.

3) Removed deprecated .sub()

.sub() added in v1.5, deprecated in v1.7. Lets you create a copy of jQuery object, so that methods' default behaviours could be overwritten.

For example you could overwrite jQuery's .data() methods so that it would try to fetch required data from your server if it's not found on the element.

(function() {
  var copy = jQuery.sub();

  copy.data = function(element, key, value) {
    // Make sure user is trying to get, not set data
    if(!!value) return jQuery.data.apply(this, arguments);

    // Get data using default jQuery.data() method
    var data = jQuery.data.apply(this, arguments);

    if(!data) {
      // if no data, get it from the server
      data = $.ajax({ AJAX_INFO });
    }

    // Once we have the data, cache it using
    // original $.data() and return to the callee
    return jQuery.data.apply(this, arguments, data);
  };

  copy(document).ready(function($) {
    alert($(".test-elem").data();
  });

})();

If you want to study how it was accomplished, here is the related code from 1.8.3 code base.

4) Can't toggle through click events, only visibility

.toggle() added in v1.0, deprecated in v1.8. There were 2 .toggle() methods: one that animates show/hide, the other toggles click events. The one that toggles through click handlers is removed. So .toggle(function(){}, function(){}) will not work. Here is the related code in jQuery Migrate plugin.

5) No more $('img').error()

.error() added in v1.0, deprecated in v1.8. Not to be confused with $.error() method, that throws new Error(msg);

6) .attr() for working with attributes only

.attr('value', newValue) used to set property instead of attribute. To set current value use .prop('value', newValue) and .val(newValue) for form elements.

Learn the difference between property and attribute.

7) Removed "hover" pseudo-event

"hover" – there is no more event called hover. Instead use "mouseenter mouseleave". Please note, that only pseudo-event name is no longer available. You can still use .hover() method.

8) Global AJAX events triggered on document

ajaxStart, ajaxSend, ajaxSuccess, ajaxError, ajaxComplete, ajaxStop now must be bound to 'document'.

9) Internal undocumented changes

There are also some other internal methods that were either changed or removed (like .data('events') and $.clean()), but since they are not documented I guess you are not using them.

How to deal with all the changes?

As you can see jQuery 1.9 throws away many deprecated methods, but the team understands that there is a lot of code in production that relies on these features. So jQuery team provided us with jQuery Migrate plugin that makes code written prior to 1.9 work with it.

If you use unminified version of the plugin, it will log warning messages in console if your code uses any of the deprecated methods. The minified file is for production and it does not throw any warnings.

Learn QUnit in just 2 hours

This is not a catchy post title or usual marketing trick. 2 hours is actually how long it would take to learn QUnit for an average developer (provided you are familiar with JavaScript and web dev basics of course). Well, that's how long it took me to learn. I read the docs (very short and concise), read QUnit tests of some popular jQuery plugins, wrote some tests of my own, and all these got me to the point where I could answer QUnit related questions on StackOverflow.

First, I was planning to cover all the basics of QUnit in this article, but then I thought, getting the message out would yield more positive results. The message that learning everything (and I mean everything) about QUnit testing takes no more than couple of hours. I believe this would make a better impact on jQuery/JavaScript community as a whole. This article will outline the basics and guide you through the optimal learning process (with links to resources).

Let's get started

Learning QUnit at first might be overwhelming. But once you learn that its' API has only 14 methods (and some of them are just negation of others, e.g. equal() & notEqual()), the learning process gets more manageable and easy. Here is an overview of those 14 methods mentioned above:

  • 8 assertions (equal(), notEqual(), deepEqual(), notDeepEqual(), strictEqual(), notStrictEqual(), ok(), throws())
  • 3 assertion organisation methods, also known as test suites in other unit testing frameworks (module(), test(), asyncTest())
  • 3 helper methods to test async methods, such as AJAX, setTimeout(), callbacks, etc. (expect(), stop(), start())

This out of the way, we are ready to learn QUnit.

Here are 4 steps that will (1) introduce you to unit testing and QUnit, (2) cover all API methods, (3) show and discuss some common testing scenarios and (4) see how others are using it:

  1. Read an Introduction to unit testing. The article introduces the idea of unit testing and sets the stage to and introduces QUnit. - 20 min
  2. Go through those 14 methods we talked about above (assert, async assert, test). The API explanations are very short and to the point. - 30 min
  3. See some examples of testing javascript and jQuery code using QUnit in the cookbook. - 40 min
  4. Read and examine some tests on GitHub: - 30 min

Hopefully, you will spend the next 2 hours learning QUnit and your next jQuery plugin/JavaScript code will be covered by tests. Please, help to spread the word and share the link.

PS. In upcoming posts we will cover other testing frameworks such as Mocha and Jasmine (has syntax that resembles Ruby's rspec), object stubbing and mocking with Sinon.JS, and some alternatives to assertions with Chai. Also, to make coding more pleasant we'll cover CoffeeScript as well. So stay tuned: Like us on Facebook, follow on Twitter or subscribe to RSS.

Tough jQuery developer

This week's "Friday jQuery humor" post is a bit late. Anyway, let's see how tough are you?

Tough jQuery developer

All about jQuery plugin manifest file

As it was described in our previous post “How to prepare your plugin for the new jQuery plugins site” you will need to add a manifest file if you want your plugin to appear on the new jQuery plugins site. In this post we will cover everything you need to know about the manifest file, how to format it and where to put it.

What is a jQuery plugin manifest file?

It is a JSON file (not JavaScript literal) that carries all necessary information about your plugin. Information like: plugin name, description, version, author, homepage, licenses, plugin dependencies, etc. The upcoming plugins.jquery.com site will use this data to populate its’ database and create an individual pages for each plugin.

Manifest file naming conventions

The manifest file’s name must be yourpluginname.jquery.json. For example, jTwitter plugins manifest file name would be named: jtwitter.jquery.json. Please be advised, at first the file name was planned to be package.json (following common.js conventions). However, after some discussions it was changed to *.jquery.json.

There is also a concept of suites. Suites are a way to namespace many plugins in a single repository (e.g. jQuery UI would name their fils: ui.tabs.jquery.json). Suites are created manually by jQuery team.

MEME: jQuery version

I thought I’d spice thing up a bit with some humour related to jQuery and JavaScript from my experience. With the new work and responsibilities, this kind of “surprise” happened to me more than once :)

If you like it, please share. Depending on the interest, this might become more periodic thing.

How to prepare your jQuery plugin for the new plugins.jquery.com site

It’s been over a year since the unfortunate event that whipped out the plugins.jquery.com site’s database. But sometimes unfortunate events lead to better things and that’s the case with the Plugins site. Instead of trying to reinvent the wheel and create a website equally useful for plugin users and plugin developers (while fighting spam, maintaining the servers, etc.), the team decided to embrace the power of existing tools. Now plugin developers will maintain their code on GitHub taking full advantage of all its’ features, while jQuery Foundation concentrates on building a better user experience for “plugin users”.

This means that plugin development and maintenance lifecycles are moving over to more confortable and more suitable for this kind of work GitHub platform.

There seems to be a lot of confusion among “plugin users”, that they’ll need to deal with GitHub and such. “NO” – plugin users will see all necessary information about the plugin on a user friendly plugins.jquery.com website.

“It’s alive” - new theme design, interesting posts & more…

Happy New Year everyone! I would like to give you a heads up with the news that the blog will become “live” again with more regular and interesting posts around jQuery and JavaScript. For the last couple of years I have been involved in a very fast growing start-up with a vibrant developers team. I have learned a lot during this period, so I decided to also cover topics about maintaining frequently changing codebase, programming best practices for better code maintenance and also tools & tips to stay sane.

To get things moving I spent couple of days redesigning the blog theme using Twitter Bootstrap and dressing it up to Blogger template (if there is a demand, I can polish the template’s code and release it to the public). I hope you like the new look. If there are any bugs, please leave a message on Facebook or Twitter.

Happy New Year and happy coding…