From 77344f4c50386690782ab8ddc92898a918f54f5c Mon Sep 17 00:00:00 2001 From: John Resig Date: Fri, 19 Dec 2008 04:34:12 +0000 Subject: [PATCH] Added support for multiple-namespaced events (in bind, trigger, and unbind). --- src/event.js | 17 +++++++++-------- test/unit/event.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/event.js b/src/event.js index 5be849f..7bbca2a 100644 --- a/src/event.js +++ b/src/event.js @@ -53,8 +53,8 @@ jQuery.event = { jQuery.each(types.split(/\s+/), function(index, type) { // Namespaced event handlers var parts = type.split("."); - type = parts[0]; - handler.type = parts[1]; + type = parts.shift(); + handler.type = parts.sort().join("."); // Get the current list of functions bound to this event var handlers = events[type]; @@ -113,8 +113,9 @@ jQuery.event = { // jQuery(...).unbind("mouseover mouseout", fn); jQuery.each(types.split(/\s+/), function(index, type){ // Namespaced event handlers - var parts = type.split("."); - type = parts[0]; + var namespace = type.split("."); + type = namespace.shift(); + namespace = RegExp(namespace.sort().join(".*\\.") + "(\\.|$)"); if ( events[type] ) { // remove the given handler for the given type @@ -125,7 +126,7 @@ jQuery.event = { else for ( handler in events[type] ) // Handle the removal of namespaced events - if ( !parts[1] || events[type][handler].type == parts[1] ) + if ( namespace.test(events[type][handler].type) ) delete events[type][handler]; // remove generic event handler if no more handlers exist @@ -246,8 +247,8 @@ jQuery.event = { // Namespaced event handlers namespace = event.type.split("."); - event.type = namespace[0]; - namespace = namespace[1]; + event.type = namespace.shift(); + namespace = RegExp(namespace.sort().join(".*\\.") + "(\\.|$)"); // Cache this now, all = true means, any handler all = !namespace && !event.exclusive; @@ -257,7 +258,7 @@ jQuery.event = { var handler = handlers[j]; // Filter the functions by class - if ( all || handler.type == namespace ) { + if ( all || namespace.test(handler.type) ) { // Pass in a reference to the handler function itself // So that we can later remove it event.handler = handler; diff --git a/test/unit/event.js b/test/unit/event.js index a0857a3..642ba5e 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -112,6 +112,60 @@ test("bind(), namespaced events, cloned events", function() { ok( jQuery("a.test:first").triggerHandler("click") === false, "Handler is bound to appendTo'd elements" ); }); +test("bind(), multi-namespaced events", function() { + expect(6); + + var order = [ + "click.test.abc", + "click.test.abc", + "click.test", + "click.test.abc", + "click.test", + "custom.test2" + ]; + + function check(name, msg){ + same(name, order.shift(), msg); + } + + jQuery("#firstp").bind("custom.test",function(e){ + check("custom.test", "Custom event triggered"); + }); + + jQuery("#firstp").bind("custom.test2",function(e){ + check("custom.test2", "Custom event triggered"); + }); + + jQuery("#firstp").bind("click.test",function(e){ + check("click.test", "Normal click triggered"); + }); + + jQuery("#firstp").bind("click.test.abc",function(e){ + check("click.test.abc", "Namespaced click triggered"); + }); + + // Trigger both bound fn (1) + jQuery("#firstp").trigger("click.test.abc"); + + // Trigger one bound fn (1) + jQuery("#firstp").trigger("click.abc"); + + // Trigger two bound fn (2) + jQuery("#firstp").trigger("click.test"); + + // Remove only the one fn + jQuery("#firstp").unbind("click.abc"); + + // Trigger the remaining fn (1) + jQuery("#firstp").trigger("click"); + + // Remove the remaining fn + jQuery("#firstp").unbind(".test"); + + // Trigger the remaining fn (1) + jQuery("#firstp").trigger("custom"); +}); + test("trigger() shortcuts", function() { expect(6); jQuery('
  • Change location
  • ').prependTo('#firstUL').find('a').bind('click', function() { -- 1.7.10.4