X-Git-Url: http://git.asbjorn.it/?a=blobdiff_plain;f=src%2Fevent.js;h=e2087cc13cbdf77f7ff59056aeda292793458ced;hb=5cb1163469fb2c9cd80712cd5481b29055821022;hp=380d3d49e38d9d069b6cc2d7a8daae19bddacb64;hpb=bca82254137a161094377b2d8189c2d9d5906a0f;p=jquery.git diff --git a/src/event.js b/src/event.js index 380d3d4..e2087cc 100644 --- a/src/event.js +++ b/src/event.js @@ -405,7 +405,7 @@ jQuery.event = { add: function( proxy, data, namespaces ) { jQuery.extend( proxy, data || {} ); proxy.guid += data.selector + data.live; - jQuery.event.add( this, data.live, liveHandler ); + jQuery.event.add( this, data.live, liveHandler, data ); }, remove: function( namespaces ) { @@ -467,6 +467,7 @@ jQuery.Event.prototype = { if ( !e ) { return; } + // if preventDefault exists run it on the original event if ( e.preventDefault ) { e.preventDefault(); @@ -516,6 +517,14 @@ var withinElement = function( event ) { // handle event if we actually just moused on to a non sub-element jQuery.event.handle.apply( this, arguments ); } + +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); }; // Create mouseenter and mouseleave events @@ -524,22 +533,56 @@ jQuery.each({ mouseout: "mouseleave" }, function( orig, fix ) { jQuery.event.special[ fix ] = { - setup: function(){ - jQuery.event.add( this, orig, withinElement, fix ); + setup: function(data){ + jQuery.event.add( this, orig, data && data.selector ? delegate : withinElement, fix ); }, - teardown: function(){ - jQuery.event.remove( this, orig, withinElement ); + teardown: function(data){ + jQuery.event.remove( this, orig, data && data.selector ? delegate : withinElement ); } }; }); +(function() { + + var event = jQuery.event, + special = event.special, + handle = event.handle; + + special.submit = { + setup: function(data, namespaces) { + if(data.selector) { + event.add(this, 'click.specialSubmit', function(e, eventData) { + if(jQuery(e.target).filter(":submit, :image").closest(data.selector).length) { + e.type = "submit"; + return handle.call( this, e, eventData ); + } + }); + + event.add(this, 'keypress.specialSubmit', function( e, eventData ) { + if(jQuery(e.target).filter(":text, :password").closest(data.selector).length) { + e.type = "submit"; + return handle.call( this, e, eventData ); + } + }); + } else { + return false; + } + }, + + remove: function(namespaces) { + event.remove(this, 'click.specialSubmit'); + event.remove(this, 'keypress.specialSubmit'); + } + }; + +})(); + // Create "bubbling" focus and blur events jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ){ var event = jQuery.event, - special = event.special, handle = event.handle; function ieHandler() { @@ -547,28 +590,35 @@ jQuery.each({ return handle.apply(this, arguments); } - special[orig] = { + event.special[orig] = { setup:function() { if ( this.addEventListener ) this.addEventListener( orig, handle, true ); else - jQuery.event.add( this, fix, ieHandler ); + event.add( this, fix, ieHandler ); }, teardown:function() { if ( this.removeEventListener ) this.removeEventListener( orig, handle, true ); else - jQuery.event.remove( this, fix, ieHandler ); + event.remove( this, fix, ieHandler ); } }; }); jQuery.fn.extend({ + // TODO: make bind(), unbind() and one() DRY! bind: function( type, data, fn, thisObject ) { - if ( jQuery.isFunction( data ) ) { - if ( fn !== undefined ) { - thisObject = fn; + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this.bind(key, data, type[key], fn); } + return this; + } + + if ( jQuery.isFunction( data ) ) { + thisObject = fn; fn = data; data = undefined; } @@ -579,10 +629,16 @@ jQuery.fn.extend({ }, one: function( type, data, fn, thisObject ) { - if ( jQuery.isFunction( data ) ) { - if ( fn !== undefined ) { - thisObject = fn; + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this.one(key, data, type[key], fn); } + return this; + } + + if ( jQuery.isFunction( data ) ) { + thisObject = fn; fn = data; data = undefined; } @@ -597,6 +653,14 @@ jQuery.fn.extend({ }, unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + return this; + } + return this.each(function() { jQuery.event.remove( this, type, fn ); }); @@ -629,13 +693,14 @@ jQuery.fn.extend({ return this.click( jQuery.event.proxy( fn, function( event ) { // Figure out which function to execute - this.lastToggle = ( this.lastToggle || 0 ) % i; + 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(); // and execute the function - return args[ this.lastToggle++ ].apply( this, arguments ) || false; + return args[ lastToggle ].apply( this, arguments ) || false; })); }, @@ -686,15 +751,23 @@ function liveHandler( event ) { jQuery.each( jQuery.data( this, "events" ).live || [], function( i, fn ) { if ( fn.live === event.type ) { - var elem = jQuery( event.target ).closest( fn.selector )[0]; + var elem = jQuery( event.target ).closest( fn.selector, event.currentTarget )[0], + related; if ( elem ) { - elems.push({ elem: elem, fn: fn }); + // Those two events require additional checking + if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) { + related = jQuery( event.relatedTarget ).closest( fn.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, fn: fn }); + } } } }); elems.sort(function( a, b ) { - return jQuery.data( a.elem, "closest" ) - jQuery.data( b.elem, "closest" ); + return a.closer - b.closer; }); jQuery.each(elems, function() { @@ -719,6 +792,10 @@ jQuery.extend({ ready: function() { // Make sure that the DOM is not already loaded if ( !jQuery.isReady ) { + if ( !document.body ) { + return setTimeout( jQuery.ready, 13 ); + } + // Remember that the DOM is ready jQuery.isReady = true; @@ -765,6 +842,7 @@ function bindReady() { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent("onreadystatechange", function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( document.readyState === "complete" ) { document.detachEvent( "onreadystatechange", arguments.callee ); jQuery.ready(); @@ -773,7 +851,8 @@ function bindReady() { // If IE and not an iframe // continually check to see if the document is ready - if ( document.documentElement.doScroll && window === window.top ) (function() { + // NOTE: DO NOT CHANGE TO ===, FAILS IN IE. + if ( document.documentElement.doScroll && window == window.top ) (function() { if ( jQuery.isReady ) { return; } @@ -796,9 +875,9 @@ function bindReady() { jQuery.event.add( window, "load", jQuery.ready ); } -jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," + - "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," + - "change,select,submit,keydown,keypress,keyup,error").split(","), function( i, name ) { +jQuery.each( ("blur focus load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { // Handle event binding jQuery.fn[ name ] = function( fn ) {