+var fcleanup = function( nm ) {
+ return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
+ return "\\" + ch;
+ });
+};
+
/*
* A number of helper functions used for managing events.
* Many of the ideas behind this code originated from
// Make sure that the function being executed has a unique ID
if ( !handler.guid ) {
- handler.guid = this.guid++;
+ handler.guid = jQuery.guid++;
}
// if data is passed, bind to handler
var fn = handler;
// Create unique handler function, wrapped around original handler
- handler = this.proxy( fn );
+ handler = jQuery.proxy( fn );
// Store data in unique handler
handler.data = data;
handle = jQuery.data( elem, "handle", eventHandle );
}
+ // If no handle is found then we must be trying to bind to one of the
+ // banned noData elements
+ if ( !handle ) {
+ return;
+ }
+
// Add elem as a property of the handle function
// This is to prevent a memory leak with non-native
// event in IE.
// Handle multiple events separated by a space
// jQuery(...).bind("mouseover mouseout", fn);
types = types.split( /\s+/ );
- var type, i=0;
+
+ var type, i = 0;
+
while ( (type = types[ i++ ]) ) {
// Namespaced event handlers
var namespaces = type.split(".");
type = namespaces.shift();
+
+ if ( i > 1 ) {
+ handler = jQuery.proxy( handler );
+
+ if ( data !== undefined ) {
+ handler.data = data;
+ }
+ }
+
handler.type = namespaces.slice(0).sort().join(".");
// Get the current list of functions bound to this event
var handlers = events[ type ],
special = this.special[ type ] || {};
-
-
// Init the event handler queue
if ( !handlers ) {
handlers = events[ type ] = {};
elem = null;
},
- guid: 1,
global: {},
// Detach an event or set of events from an element
var namespaces = type.split(".");
type = namespaces.shift();
var all = !namespaces.length,
- cleaned = jQuery.map( namespaces.slice(0).sort() , function(nm){ return nm.replace(/[^\w\s\.\|`]/g, function(ch){return "\\"+ch; }); }),
+ cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ),
namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"),
special = this.special[ type ] || {};
if ( !elem ) {
// Don't bubble custom events when global (to avoid too much overhead)
event.stopPropagation();
+
// Only trigger if we've ever bound an event for it
if ( this.global[ type ] ) {
jQuery.each( jQuery.cache, function() {
handle.apply( elem, data );
}
- var nativeFn, nativeHandler;
+ var parent = elem.parentNode || elem.ownerDocument;
+
+ // Trigger an inline bound script
try {
if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
- nativeFn = elem[ type ];
- nativeHandler = elem[ "on" + type ];
+ if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
+ event.result = false;
+ }
}
+
// prevent IE from throwing an error for some elements with some event types, see #3533
} catch (e) {}
- var isClick = jQuery.nodeName(elem, "a") && type === "click";
+ if ( !event.isPropagationStopped() && parent ) {
+ jQuery.event.trigger( event, data, parent, true );
- // Trigger the native events (except for clicks on links)
- if ( !bubbling && nativeFn && !event.isDefaultPrevented() && !isClick ) {
- this.triggered = true;
- try {
- elem[ type ]();
- // prevent IE from throwing an error for some hidden elements
- } catch (e) {}
+ } else if ( !event.isDefaultPrevented() ) {
+ var target = event.target, old,
+ isClick = jQuery.nodeName(target, "a") && type === "click";
- // Handle triggering native .onfoo handlers
- } else if ( nativeHandler && elem[ "on" + type ].apply( elem, data ) === false ) {
- event.result = false;
- }
+ if ( !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
+ try {
+ if ( target[ type ] ) {
+ // Make sure that we don't accidentally re-trigger the onFOO events
+ old = target[ "on" + type ];
- this.triggered = false;
+ if ( old ) {
+ target[ "on" + type ] = null;
+ }
- if ( !event.isPropagationStopped() ) {
- var parent = elem.parentNode || elem.ownerDocument;
- if ( parent ) {
- jQuery.event.trigger( event, data, parent, true );
+ this.triggered = true;
+ target[ type ]();
+ }
+
+ // prevent IE from throwing an error for some elements with some event types, see #3533
+ } catch (e) {}
+
+ if ( old ) {
+ target[ "on" + type ] = old;
+ }
+
+ this.triggered = false;
}
}
},
return event;
},
- proxy: function( fn, proxy, thisObject ) {
- if ( proxy !== undefined && !jQuery.isFunction( proxy ) ) {
- thisObject = proxy;
- proxy = undefined;
- }
- // FIXME: Should proxy be redefined to be applied with thisObject if defined?
- proxy = proxy || function() { return fn.apply( thisObject !== undefined ? thisObject : 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
- return proxy;
- },
+ // Deprecated, use jQuery.guid instead
+ guid: 1E8,
+
+ // Deprecated, use jQuery.proxy instead
+ proxy: jQuery.proxy,
special: {
ready: {
// Make sure the ready event is setup
setup: jQuery.bindReady,
- teardown: function() {}
+ teardown: jQuery.noop
},
live: {
jQuery.extend( proxy, data || {} );
proxy.guid += data.selector + data.live;
+ data.liveProxy = proxy;
+
jQuery.event.add( this, data.live, liveHandler, data );
},
}
};
-jQuery.Event = function( src ){
+jQuery.Event = function( src ) {
// Allow instantiation without the 'new' keyword
if ( !this.preventDefault ) {
return new jQuery.Event( src );
// otherwise set the cancelBubble property of the original event to true (IE)
e.cancelBubble = true;
},
- stopImmediatePropagation: function(){
+ stopImmediatePropagation: function() {
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
},
mouseleave: "mouseout"
}, function( orig, fix ) {
jQuery.event.special[ orig ] = {
- setup: function(data){
+ setup: function( data ) {
jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
},
- teardown: function(data){
+ teardown: function( data ) {
jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
}
};
return trigger( "submit", this, arguments );
}
});
+
+ } else {
+ return false;
}
},
data = jQuery.data( elem, "_change_data" );
val = getVal(elem);
- if ( val === data ) {
- return;
- }
-
// the current data will be also retrieved by beforeactivate
if ( e.type !== "focusout" || elem.type !== "radio" ) {
jQuery.data( elem, "_change_data", val );
}
+
+ if ( data === undefined || val === data ) {
+ return;
+ }
- if ( elem.type !== "select" && (data != null || val) ) {
+ if ( data != null || val ) {
e.type = "change";
- return jQuery.event.trigger( e, arguments[1], this );
+ return jQuery.event.trigger( e, arguments[1], elem );
}
}
},
// Change has to be called before submit
- // Keydown will be called before keypress, wich is used in submit-event delegation
+ // Keydown will be called before keypress, which is used in submit-event delegation
keydown: function( e ) {
var elem = e.target, type = elem.type;
// Create "bubbling" focus and blur events
if ( document.addEventListener ) {
- jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ){
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
jQuery.event.special[ fix ] = {
setup: function() {
this.addEventListener( orig, handler, true );
});
}
-jQuery.each(["bind", "one"], function(i, name) {
- jQuery.fn[ name ] = function( type, data, fn, thisObject ) {
+jQuery.each(["bind", "one"], function( i, name ) {
+ jQuery.fn[ name ] = function( type, data, fn ) {
// Handle object literals
if ( typeof type === "object" ) {
for ( var key in type ) {
}
if ( jQuery.isFunction( data ) ) {
- thisObject = fn;
fn = data;
data = undefined;
}
- fn = thisObject === undefined ? fn : jQuery.event.proxy( fn, thisObject );
- var handler = name === "one" ? jQuery.event.proxy( fn, function( event ) {
+
+ var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
jQuery( this ).unbind( event, handler );
return fn.apply( this, arguments );
}) : fn;
- return type === "unload" ? this.one(type, data, handler, thisObject) : this.each(function() {
- jQuery.event.add( this, type, handler, data );
- });
+
+ return type === "unload" && name !== "one" ?
+ this.one( type, data, fn ) :
+ this.each(function() {
+ jQuery.event.add( this, type, handler, data );
+ });
};
});
var args = arguments, i = 1;
// link all the functions, so any of them can unbind this click handler
- while( i < args.length ) {
- jQuery.event.proxy( fn, args[ i++ ] );
+ while ( i < args.length ) {
+ jQuery.proxy( fn, args[ i++ ] );
}
- return this.click( jQuery.event.proxy( fn, function( event ) {
+ return this.click( jQuery.proxy( fn, function( event ) {
// Figure out which function to execute
- var lastToggle = ( jQuery.data( this, 'lastToggle' + fn.guid ) || 0 ) % i;
- jQuery.data( this, 'lastToggle' + fn.guid, lastToggle + 1 );
+ var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
// Make sure that clicks stop
event.preventDefault();
hover: function( fnOver, fnOut ) {
return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
- },
+ }
+});
+
+jQuery.each(["live", "die"], function( i, name ) {
+ jQuery.fn[ name ] = function( types, data, fn ) {
+ var type, i = 0;
- live: function( type, data, fn, thisObject ) {
if ( jQuery.isFunction( data ) ) {
- if ( fn !== undefined ) {
- thisObject = fn;
- }
fn = data;
data = undefined;
}
- jQuery( this.context ).bind( liveConvert( type, this.selector ), {
- data: data, selector: this.selector, live: type
- }, fn, thisObject );
- return this;
- },
- die: function( type, fn ) {
- jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
+ types = (types || "").split( /\s+/ );
+
+ while ( (type = types[ i++ ]) != null ) {
+ type = type === "focus" ? "focusin" : // focus --> focusin
+ type === "blur" ? "focusout" : // blur --> focusout
+ type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support
+ type;
+
+ if ( name === "live" ) {
+ // bind live handler
+ jQuery( this.context ).bind( liveConvert( type, this.selector ), {
+ data: data, selector: this.selector, live: type
+ }, fn );
+
+ } else {
+ // unbind live handler
+ jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
+ }
+ }
+
return this;
}
});
function liveHandler( event ) {
- var stop = true, elems = [], selectors = [], args = arguments,
- related, match, fn, elem, j, i, data,
+ var stop, elems = [], selectors = [], args = arguments,
+ related, match, fn, elem, j, i, l, data,
live = jQuery.extend({}, jQuery.data( this, "events" ).live);
+ // Make sure we avoid non-left-click bubbling in Firefox (#3861)
+ if ( event.button && event.type === "click" ) {
+ return;
+ }
+
for ( j in live ) {
fn = live[j];
if ( fn.live === event.type ||
}
function liveConvert( type, selector ) {
- return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "&")].join(".");
+ return "live." + (type ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
}
-jQuery.each( ("blur focus load resize scroll unload click dblclick " +
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup error").split(" "), function( i, name ) {
return fn ? this.bind( name, fn ) : this.trigger( name );
};
- if ( jQuery.fnAttr ) {
- jQuery.fnAttr[ name ] = true;
+ if ( jQuery.attrFn ) {
+ jQuery.attrFn[ name ] = true;
}
});