var fn = handler;
// Create unique handler function, wrapped around original handler
- handler = this.proxy( fn, function() {
- // Pass arguments and context to original handler
- return fn.apply(this, arguments);
- });
+ handler = this.proxy( fn );
// Store data in unique handler
handler.data = data;
// remove all handlers for the given type
else
- for ( handler in events[type] )
+ for ( var handle in events[type] )
// Handle the removal of namespaced events
- if ( namespace.test(events[type][handler].type) )
- delete events[type][handler];
+ if ( namespace.test(events[type][handle].type) )
+ delete events[type][handle];
if ( jQuery.event.specialAll[type] )
jQuery.event.specialAll[type].teardown.call(elem, namespaces);
}
},
- trigger: function( event, data, elem, bubbling /* internal */ ) {
+ // bubbling is internal
+ trigger: function( event, data, elem, bubbling ) {
// Event object or event type
var type = event.type || event;
if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
return undefined;
- // AT_TARGET phase (not bubbling)
- if( !bubbling ){
- // Clean up in case it is reused
- event.result = undefined;
- event.target = elem;
-
- // Clone the incoming data, if any
- data = jQuery.makeArray(data);
- data.unshift( event );
- }
+ // Clean up in case it is reused
+ event.result = undefined;
+ event.target = elem;
+
+ // Clone the incoming data, if any
+ data = jQuery.makeArray(data);
+ data.unshift( event );
}
event.currentTarget = elem;
} catch (e) {}
}
+ this.triggered = false;
+
if ( !event.isPropagationStopped() ) {
var parent = elem.parentNode || elem.ownerDocument;
if ( parent )
jQuery.event.trigger(event, data, parent, true);
}
-
- this.triggered = false;
},
handle: function(event) {
var all, handlers;
event = arguments[0] = jQuery.event.fix( event || window.event );
-
+ event.currentTarget = this;
+
// Namespaced event handlers
var namespaces = event.type.split(".");
event.type = namespaces.shift();
},
proxy: function( fn, proxy ){
+ proxy = proxy || function(){ return fn.apply(this, arguments); };
// Set the guid of unique handler to the same of original handler, so it can be removed
proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
// So proxy can be declared as an argument
remove++;
});
- if ( remove <= 1 )
+ if ( remove < 1 )
jQuery.event.remove( this, namespaces[0], liveHandler );
}
}
if( src && src.type ){
this.originalEvent = src;
this.type = src.type;
- this.timeStamp = src.timeStamp;
// Event type
}else
this.type = src;
- if( !this.timeStamp )
- this.timeStamp = now();
+ // timeStamp is buggy for some events on Firefox(#3843)
+ // So we won't rely on the native value
+ this.timeStamp = now();
// Mark it as fixed
this[expando] = true;
},
live: function( type, fn ){
- jQuery(document).bind( liveConvert(type, this.selector), this.selector, fn );
+ var proxy = jQuery.event.proxy( fn );
+ proxy.guid += this.selector + type;
+
+ jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+
return this;
},
die: function( type, fn ){
- jQuery(document).unbind( liveConvert(type, this.selector), fn );
+ jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
return this;
}
});
function liveHandler( event ){
var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
- stop = true;
+ stop = true,
+ elems = [];
jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
if ( check.test(fn.type) ) {
var elem = jQuery(event.target).closest(fn.data)[0];
- if ( elem && fn.call(elem, event, fn.data) === false )
- stop = false;
+ if ( elem )
+ elems.push({ elem: elem, fn: fn });
}
});
+
+ elems.sort(function(a,b) {
+ return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
+ });
+
+ jQuery.each(elems, function(){
+ if ( this.fn.call(this.elem, event, this.fn.data) === false )
+ return (stop = false);
+ });
+
return stop;
}
function liveConvert(type, selector){
- return ["live", type, selector.replace(/\./g, "_")].join(".");
+ return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
}
jQuery.extend({
// If IE and not an iframe
// continually check to see if the document is ready
- if ( document.documentElement.doScroll && !window.frameElement ) (function(){
+ if ( document.documentElement.doScroll && window == window.top ) (function(){
if ( jQuery.isReady ) return;
try {