skip to content

jQuery Edge: New Special Event Hooks

5 min read

These Special Event hooks were changed in 1.4.2. Check out this blog post to see the details about the change.

In jQuery 1.3.3 1.4 there are two new special event hooks: add and remove. These two hooks, unlike setup and teardown, are called for each event being bound. The add hook receives the handler, data, and namespaces as arguments. The remove hook receives the data and namespaces as arguments. The add and remove hooks enable the creation of more complex, even customizable, events.

If you haven’t done so, I recommend reading the Special Events blog post which explains what special events are and how to use them. For the following example I assume you already understand the concept of special events in jQuery.

As an example I’m going to build a new special event called “multiclick”. This event tracks clicks on an element and fires at a given threshold or number of clicks. The required number of clicks will be customizable per a handler.

First, here is how you’d use the multiclick event.

$('div')
    .bind("multiclick", { threshold: 5 }, function( event ) {
        alert( "Clicked 5 times" );
    })
    .bind("multiclick", { threshold: 3 }, function( event ) {
        alert( "Clicked 3 times" );
    });

Now lets build it. The skeleton of the multiclick special event looks like this.

jQuery.event.special.multiclick = {
    add: function( handler, data, namespaces ) {
        // called for each bound handler
    },

    setup: function( data, namespaces ) {
        // called once per an element
    },

    remove: function( namespaces ) {
        // called for each bound handler
    },

    teardown: function( namespaces ) {
        // called once per an element
    },

    handler: function( event ) {

    }
};

Behind the scenes we’ll need to use a normal click event. We’ll use the setup hook to bind the initial click event to track the actual clicks. The handler method will be used to properly trigger the multiclick events. Once all the multiclick events are removed, the teardown hook will be triggered. We’ll need to unbind the the click event we used to track the clicks in the setup hook. Here is the updated multiclick event.

jQuery.event.special.multiclick = {
    add: function( handler, data, namespaces ) {
        // called for each bound handler
    },

    setup: function( data, namespaces ) {
        jQuery( this ).bind( "click", jQuery.event.special.multiclick.handler );
    },

    remove: function( namespaces ) {
        // called for each bound handler
    },

    teardown: function( namespaces ) {
        jQuery( this ).unbind( "click", jQuery.event.special.multiclick.handler );
    },

    handler: function( event ) {
        // set correct event type
        event.type = "multiclick";
        // trigger multiclick handlers
        jQuery.event.handle.apply( this, arguments );
    }
};

Next we need to make sure the bound function to a multiclick event isn’t fired until it reaches the number of clicks specified. We’ll utilize the add hook for this. The add hook has the ability to return a function which will take the place of the provided handler. This is a powerful feature and allows us to do all sorts of fun things with special events. In the case of the multiclick event we are going to return a new function that calls the given handler after the specified number of clicks. Here is the add hook.

jQuery.event.special.multiclick = {
    add: function( handler, data, namespaces ) {
        // get the required number of clicks from data
        var threshold = data && data.threshold || 1,
            // number of clicks
            clicks = 0;

        // return a new function that will become the handler
        return function( event ) {
            // increase number of clicks
            clicks += 1;
            if ( clicks === threshold ) {
                // required number of clicks reached, reset
                clicks = 0;
                // call the actual supplied handler
                handler.apply( this, arguments );
            }
        }
    },

    ...
};

The add hook makes use of closures to keep track of the required number of clicks (threshold), the actual number of clicks, and the handler to be called once the required number of clicks is reached. The jQuery event system keeps everything in tact so that when you call unbind with the same named function that you supplied to bind, it still unbinds it as expected.

It ends up that we don’t actually need to use the remove hook for this special event, so we’ll just remove it. Thats it. The multiclick special event is done.

jQuery.event.special.multiclick = {
    add: function( handler, data, namespaces ) {
        // get the required number of clicks from data
        var threshold = data && data.threshold || 1,
            // number of clicks
            clicks = 0;

        // return a new function that will become the handler
        return function( event ) {
            // increase number of clicks
            clicks += 1;
            if ( clicks === threshold ) {
                // required number of clicks reached, reset
                clicks = 0;
                // call the actual supplied handler
                handler.apply( this, arguments );
            }
        }
    },

    setup: function( data, namespaces ) {
        jQuery( this ).bind( "click", jQuery.event.special.multiclick.handler );
    },

    teardown: function( namespaces ) {
        jQuery( this ).unbind( "click", jQuery.event.special.multiclick.handler );
    },

    handler: function( event ) {
        // set correct event type
        event.type = "multiclick";
        // trigger multiclick handlers
        jQuery.event.handle.apply( this, arguments );
    }
};

Thanks

Thanks to Mike Helgeson who helped evolve the special events API to include these two hooks. He also has a handful of special events that he has created: drag, drop, hover, and wheel.

If you knew about the specialAll event hook, it has been removed in favor of using these two extra hooks.