Added support for multiple-namespaced events (in bind, trigger, and unbind).
authorJohn Resig <jeresig@gmail.com>
Fri, 19 Dec 2008 04:34:12 +0000 (04:34 +0000)
committerJohn Resig <jeresig@gmail.com>
Fri, 19 Dec 2008 04:34:12 +0000 (04:34 +0000)
src/event.js
test/unit/event.js

index 5be849f..7bbca2a 100644 (file)
@@ -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;
index a0857a3..642ba5e 100644 (file)
@@ -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('<li><a href="#">Change location</a></li>').prependTo('#firstUL').find('a').bind('click', function() {