jQuery的"特别事件"扩展

特别事件

翻译自http://brandonaaron.net/blog/2009/03/26/special-events

原作者:Brandon Aaron

jQuery自1.2.2版开始引入称为"特别事件"的扩展API。These events are special because they have the ability to do some extra work for specific events and even the option to bypass some of the internal jQuery event system. 有了这些特别事件你可以创建需要一些setup work的自定义事件,甚至你可以完全重载标准jQuery事件的行为。

We use special events in jQuery to create the “mouseenter” and “mouseleave” events. In addition to those two events we used it to make the “ready” event and I use it to normalize the “mousewheel” event in the mouse wheel plugin.

一个例子: “tripleclick”三次点击

我们打算建立一个新事件,该事件当用户对某个元素点击三次以后触发。传统上我们应该建立类似jQuery.fn.tripleclick这样的jQuery插件. 但在这里我们不这么做, 我们想要利用标准jQuery事件系统的bind语法及其它好处比如event normalization, data, and namespaces.

首先我们要建立这个特殊事件。每个特殊事件需要定义setupteardown方法。方法setup在事件被bind时调用而方法teardown则在解除bind时调用。注意:这两个方法对每个元素只会被调用一次,因为jQuery事件系统会管理多次bind的事件处理器等所有繁琐的事情。

In jQuery 1.3 there is a new special event type called “Special All” that operates for all handlers but has a slightly different behavior. However, that is for another article.(这个特性已经被取消,不应该再使用Special All了,可以改用add/remove钩子,参见最后的延伸阅读部分)

我们的“tripleclick”插件大概骨架如下:

jQuery.event.special.tripleclick = {
    setup: function(data, namespaces) {
        var elem = this;
    },

    teardown: function(namespaces) {
        var elem = this;
    }
};

Notice that the setup event gets passed the data and namespaces that were used when binding the event. Also that theteardown event gets passed the namespaces that were used when unbinding the event. Although, they are only marginally useful here since this is the data and namespaces associated with the very first event handler bound to a particular element. But you could use the data to configure the event for all the handlers of that type for an element. The scope, or the value ofthis, for these two methods is the element the event is being bound to.

Behind the scenes we are actually going to utilize the native “click” event to keep track of the number of clicks on an element. We’ll also need a handler that actually does the heavy work of keeping track. I’m going to add a third method called handlerto the tripleclick special event. To make the code a little more simple I’m going to track the number of clicks on an element by using the jQuery data API.

The updated tripleclick special event looks like this.

jQuery.event.special.tripleclick = {
    setup: function(data, namespaces) {
        var elem = this, $elem = jQuery(elem);
        $elem.bind('click', jQuery.event.special.tripleclick.handler);
    },

    teardown: function(namespaces) {
        var elem = this, $elem = jQuery(elem);
        $elem.unbind('click', jQuery.event.special.tripleclick.handler);
    },

    handler: function(event) {
        var elem = this, $elem = jQuery(elem), clicks = $elem.data('clicks') || 0;
        clicks += 1;
        if ( clicks === 3 ) {
            clicks = 0;
            // set event type to "tripleclick"
            event.type = "tripleclick";
            // let jQuery handle the triggering of "tripleclick" event handlers
            jQuery.event.handle.apply(this, arguments)
        }
        $elem.data('clicks', clicks);
    }
};

To quickly break down the handler code. First we get the number of clicks via the data API and increment the number by 1. Then we check to see if it has been clicked 3 times. If so, we then need to reset the number of clicks and trigger the other event handlers as the comment indicates. Finally, we store the new value for the number clicks on the element via the data API.

The handler has to set the event type to “tripleclick” because behind the scenes we actually use a click event. jQuery uses the event type to know which handlers it should call and we want it to call the event handlers for our “tripleclick” event.

The Example

We can now use our special event just like we’d use any other event via the bind method. For example to bind a “tripleclick” event to all divs we’d write the following code.

jQuery('div').bind('tripleclick', function(event) {
    alert('triple clicked');
});

You can see an example of this new special event in action here.

You could enhance this event by requiring all three clicks to be within a certain timeframe. You could achieve this by also storing the event.timeStamp property of the previous click and comparing the distance between it and the latest click.

返回值

前面我说过特别事件能够bypass到内部的jQuery事件系统。The functionality that can be skipped is the actual binding of the event to the element using the addEventListener or attachEvent methods. This functionality is skipped based on the return value. 返回任何非false的值会阻止jQuery将该事件通过DOM实际bind到元素上。换句话说,如果从方法setupteardown中return false的话,jQuery将调用DOM API将事件bind到元素上。在我们的tripleclick插件中,我们不希望在元素上bind这个"tripleclick"事件(并不存在这样的DOM事件),所以我们没有返回任何值(就是说,返回了undefined)

 

延伸阅读

jQuery 1.4为特别事件新增的add和remove钩子: http://brandonaaron.net/blog/2009/06/4/jquery-edge-new-special-event-hooks

Automating with Special Events: http://brandonaaron.net/blog/2009/06/17/automating-with-special-events

Special Events: The changes in jQuery 1.4.2: http://brandonaaron.net/blog/2010/02/25/special-events-the-changes-in-1-4-2

 

你可能感兴趣的:(jquery)