// For whatever reason, IE has trouble passing the window object
// around, causing it to be cloned in the process
- if ( elem.setInterval && elem != window )
+ if ( elem.setInterval && ( elem != window && !elem.frameElement ) )
elem = window;
// Make sure that the function being executed has a unique ID
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;
// Get the current list of functions bound to this event
var handlers = events[type];
-
+
if ( jQuery.event.specialAll[type] )
jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
// Namespaced event handlers
var namespaces = type.split(".");
type = namespaces.shift();
- var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+ var namespace = new RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
if ( events[type] ) {
// remove the given handler for the given type
// 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);
// don't do events on text and comment nodes
if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
return undefined;
-
+
// 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 );
} 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(".");
// Cache this now, all = true means, any handler
all = !namespaces.length && !event.exclusive;
-
- var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+ var namespace = new RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
handlers = ( jQuery.data(this, "events") || {} )[event.type];
}
},
- props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+ props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix: function(event) {
if ( event[expando] )
},
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
teardown: function() {}
}
},
-
+
specialAll: {
live: {
setup: function( selector, namespaces ){
},
teardown: function( namespaces ){
if ( namespaces.length ) {
- var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
-
+ var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+
jQuery.each( (jQuery.data(this, "events").live || {}), function(){
if ( name.test(this.type) )
remove++;
});
-
- if ( remove <= 1 )
+
+ if ( remove < 1 )
jQuery.event.remove( this, namespaces[0], liveHandler );
}
}
// Allow instantiation without the 'new' keyword
if( !this.preventDefault )
return new jQuery.Event(src);
-
+
// Event object
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;
};
while ( parent && parent != this )
try { parent = parent.parentNode; }
catch(e) { parent = this; }
-
+
if( parent != this ){
// set the correct event type
event.type = event.data;
jQuery.event.handle.apply( this, arguments );
}
};
-
-jQuery.each({
- mouseover: 'mouseenter',
+
+jQuery.each({
+ mouseover: 'mouseenter',
mouseout: 'mouseleave'
}, function( orig, fix ){
jQuery.event.special[ fix ] = {
teardown: function(){
jQuery.event.remove( this, orig, withinElement );
}
- };
+ };
});
jQuery.fn.extend({
event.stopPropagation();
jQuery.event.trigger( event, data, this[0] );
return event.result;
- }
+ }
},
toggle: function( fn ) {
return this;
},
-
+
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( this.context ).bind( liveConvert(type, this.selector), this.selector, proxy );
+
return this;
},
-
+
die: function( type, fn ){
- jQuery(document).unbind( liveConvert(type, this.selector), fn );
+ jQuery( this.context ).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;
+ var check = new RegExp("(^|\\.)" + event.type + "(\\.|$)"),
+ stop = true,
+ elems = [];
jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
- if ( !event.isImmediatePropagationStopped() && check.test(fn.type) ) {
+ 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(){
+ event.currentTarget = this.elem;
+ if ( this.fn.call(this.elem, event, this.fn.data) === false )
+ return (stop = false);
+ });
+
return stop;
}
// 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 {
// Prevent memory leaks in IE
// And prevent errors on refresh with events like mouseover in other browsers
// Window isn't included so as not to unbind existing unload events
-jQuery( window ).bind( 'unload', function(){
+// More info:
+// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
+// - https://bugzilla.mozilla.org/show_bug.cgi?id=252542
+jQuery( window ).bind( 'unload', function(){
for ( var id in jQuery.cache )
// Skip the window
if ( id != 1 && jQuery.cache[ id ].handle )
jQuery.event.remove( jQuery.cache[ id ].handle.elem );
-});
+});