We don't do end of line comments, move them above.
[jquery.git] / src / event.js
index 7a10a12..04bf168 100644 (file)
@@ -7,7 +7,8 @@ var rnamespaces = /\.(.*)$/,
        rescape = /[^\w\s.|`]/g,
        fcleanup = function( nm ) {
                return nm.replace(rescape, "\\$&");
-       };
+       },
+       focusCounts = { focusin: 0, focusout: 0 };
 
 /*
  * A number of helper functions used for managing events.
@@ -31,6 +32,9 @@ jQuery.event = {
 
                if ( handler === false ) {
                        handler = returnFalse;
+               } else if ( !handler ) {
+                       // Fixes bug #7229. Fix recommended by jdalton
+                 return;
                }
 
                var handleObjIn, handleObj;
@@ -54,7 +58,10 @@ jQuery.event = {
                        return;
                }
 
-               var events = elemData.events,
+               // Use a key less likely to result in collisions for plain JS objects.
+               // Fixes bug #7150.
+               var eventKey = elem.nodeType ? "events" : "__events__",
+                       events = elemData[ eventKey ],
                        eventHandle = elemData.handle;
                        
                if ( typeof events === "function" ) {
@@ -68,7 +75,7 @@ jQuery.event = {
                        if ( !elem.nodeType ) {
                                // On plain objects, create a fn that acts as the holder
                                // of the values to avoid JSON serialization of event data
-                               elemData.events = elemData = function(){};
+                               elemData[ eventKey ] = elemData = function(){};
                        }
 
                        elemData.events = events = {};
@@ -170,8 +177,9 @@ jQuery.event = {
                }
 
                var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+                       eventKey = elem.nodeType ? "events" : "__events__",
                        elemData = jQuery.data( elem ),
-                       events = elemData && elemData.events;
+                       events = elemData && elemData[ eventKey ];
 
                if ( !elemData || !events ) {
                        return;
@@ -282,7 +290,7 @@ jQuery.event = {
                        delete elemData.handle;
 
                        if ( typeof elemData === "function" ) {
-                               delete elem.events;
+                               jQuery.removeData( elem, eventKey );
 
                        } else if ( jQuery.isEmptyObject( elemData ) ) {
                                jQuery.removeData( elem );
@@ -346,7 +354,7 @@ jQuery.event = {
                // Trigger the event, it is assumed that "handle" is a function
                var handle = elem.nodeType ?
                        jQuery.data( elem, "handle" ) :
-                       elem.events && elem.events.handle;
+                       (jQuery.data( elem, "__events__" ) || {}).handle;
 
                if ( handle ) {
                        handle.apply( elem, data );
@@ -420,7 +428,7 @@ jQuery.event = {
 
                event.namespace = event.namespace || namespace_sort.join(".");
 
-               events = jQuery.data(this, "events");
+               events = jQuery.data(this, this.nodeType ? "events" : "__events__");
 
                if ( typeof events === "function" ) {
                        events = events.events;
@@ -482,7 +490,8 @@ jQuery.event = {
 
                // Fix target property, if necessary
                if ( !event.target ) {
-                       event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+                       // Fixes #1925 where srcElement might not be defined either
+                       event.target = event.srcElement || document;
                }
 
                // check if target is a textnode (safari)
@@ -787,6 +796,8 @@ if ( !jQuery.support.changeBubbles ) {
                filters: {
                        focusout: testChange, 
 
+                       beforedeactivate: testChange,
+
                        click: function( e ) {
                                var elem = e.target, type = elem.type;
 
@@ -851,17 +862,21 @@ if ( document.addEventListener ) {
        jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
                jQuery.event.special[ fix ] = {
                        setup: function() {
-                               this.addEventListener( orig, handler, true );
+                               if ( focusCounts[fix]++ === 0 ) {
+                                       document.addEventListener( orig, handler, true );
+                               }
                        }, 
                        teardown: function() { 
-                               this.removeEventListener( orig, handler, true );
+                               if ( --focusCounts[fix] === 0 ) {
+                                       document.removeEventListener( orig, handler, true );
+                               }
                        }
                };
 
                function handler( e ) { 
                        e = jQuery.event.fix( e );
                        e.type = fix;
-                       return jQuery.event.handle.call( this, e );
+                       return jQuery.event.trigger( e, null, e.target );
                }
        });
 }
@@ -1044,7 +1059,7 @@ jQuery.each(["live", "die"], function( i, name ) {
 function liveHandler( event ) {
        var stop, maxLevel, elems = [], selectors = [],
                related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
-               events = jQuery.data( this, "events" );
+               events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
 
        if ( typeof events === "function" ) {
                events = events.events;
@@ -1054,7 +1069,7 @@ function liveHandler( event ) {
        if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
                return;
        }
-
+       
        if ( event.namespace ) {
                namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
        }
@@ -1118,6 +1133,9 @@ function liveHandler( event ) {
                        if ( ret === false ) {
                                stop = false;
                        }
+                       if ( event.isImmediatePropagationStopped() ) {
+                               break;
+                       }
                }
        }