翻譯自http://brandonaaron.net/blog/2009/03/26/special-eventsjquery
原做者:Brandon Aarongit
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事件的行爲。github
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.app
咱們打算創建一個新事件,該事件當用戶對某個元素點擊三次之後觸發。傳統上咱們應該創建相似jQuery.fn.tripleclick這樣的jQuery插件. 但在這裏咱們不這麼作, 咱們想要利用標準jQuery事件系統的bind語法及其它好處好比event normalization, data, and namespaces.ui
首先咱們要創建這個特殊事件。每一個特殊事件須要定義setup
和teardown
方法。方法setup在事件被bind時調用而
方法teardown則在解除bind時調用
。注意:這兩個方法對每一個元素只會被調用一次,由於jQuery事件系統會管理屢次bind的事件處理器等全部繁瑣的事情。this
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鉤子,參見最後的延伸閱讀部分)spa
咱們的「tripleclick」插件大概骨架以下:.net
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 the teardown
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 of this
, 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 handler
to 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.
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到元素上。換句話說,若是從方法setup和teardown中
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