X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fevent.js;h=f6b3d316d82373d2e0d71be0ee1dd4cb13786d88;hb=31432e048f879b93ffa44c39d6f5989ab2620bd8;hp=efefe578e6a33178e5fd882db6d9e2d52c9322d4;hpb=942f8f7f75a55a36e6b9745030d3b3c983518aa8;p=jquery.git diff --git a/src/event.js b/src/event.js index efefe57..f6b3d31 100644 --- a/src/event.js +++ b/src/event.js @@ -42,8 +42,16 @@ jQuery.event = { } // Init the element's event structure - var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ), - handle = jQuery.data( elem, "handle" ), eventHandle; + var elemData = jQuery.data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events || (elemData.events = {}), + handle = elemData.handle, eventHandle; if ( !handle ) { eventHandle = function() { @@ -54,13 +62,7 @@ jQuery.event = { undefined; }; - 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; + handle = elemData.handle = eventHandle; } // Add elem as a property of the handle function @@ -70,15 +72,11 @@ jQuery.event = { // Handle multiple events separated by a space // jQuery(...).bind("mouseover mouseout", fn); - types = types.split( /\s+/ ); + types = types.split(" "); - var type, i = 0; + var type, i = 0, namespaces; while ( (type = types[ i++ ]) ) { - // Namespaced event handlers - var namespaces = type.split("."); - type = namespaces.shift(); - if ( i > 1 ) { handler = jQuery.proxy( handler ); @@ -87,7 +85,16 @@ jQuery.event = { } } - handler.type = namespaces.slice(0).sort().join("."); + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handler.type = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handler.type = ""; + } // Get the current list of functions bound to this event var handlers = events[ type ], @@ -104,6 +111,7 @@ jQuery.event = { // Bind the global event handler to the element if ( elem.addEventListener ) { elem.addEventListener( type, handle, false ); + } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, handle ); } @@ -140,7 +148,13 @@ jQuery.event = { return; } - var events = jQuery.data( elem, "events" ), ret, type, fn; + var elemData = jQuery.data( elem ); + + if ( !elemData ) { + return; + } + + var events = elemData.events, ret, type, fn; if ( events ) { // Unbind all events for the element @@ -148,6 +162,7 @@ jQuery.event = { for ( type in events ) { this.remove( elem, type + (types || "") ); } + } else { // types is actually an event object here if ( types.type ) { @@ -157,16 +172,27 @@ jQuery.event = { // Handle multiple events separated by a space // jQuery(...).unbind("mouseover mouseout", fn); - types = types.split(/\s+/); - var i = 0; + types = types.split(" "); + + var i = 0, all, namespaces, namespace; + while ( (type = types[ i++ ]) ) { - // Namespaced event handlers - var namespaces = type.split("."); - type = namespaces.shift(); - var all = !namespaces.length, - cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ), - namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"), - special = this.special[ type ] || {}; + all = type.indexOf(".") < 0; + namespaces = null; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)") + + } else { + namespaces = []; + } + + var special = this.special[ type ] || {}; if ( events[ type ] ) { // remove the given handler for the given type @@ -192,14 +218,12 @@ jQuery.event = { for ( ret in events[ type ] ) { break; } + if ( !ret ) { if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, jQuery.data( elem, "handle" ), false ); - } else if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) ); - } + removeEvent( elem, type, elemData.handle ); } + ret = null; delete events[ type ]; } @@ -211,13 +235,19 @@ jQuery.event = { for ( ret in events ) { break; } + if ( !ret ) { - var handle = jQuery.data( elem, "handle" ); + var handle = elemData.handle; if ( handle ) { handle.elem = null; } - jQuery.removeData( elem, "events" ); - jQuery.removeData( elem, "handle" ); + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem ); + } } } }, @@ -299,9 +329,12 @@ jQuery.event = { } else if ( !event.isDefaultPrevented() ) { var target = event.target, old, - isClick = jQuery.nodeName(target, "a") && type === "click"; + isClick = jQuery.nodeName(target, "a") && type === "click", + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { - 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 @@ -492,6 +525,14 @@ jQuery.event = { } }; +var removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + elem.removeEventListener( type, handle, false ); + } : + function( elem, type, handle ) { + elem.detachEvent( "on" + type, handle ); + }; + jQuery.Event = function( src ) { // Allow instantiation without the 'new' keyword if ( !this.preventDefault ) { @@ -796,11 +837,16 @@ jQuery.each(["bind", "one"], function( i, name ) { return fn.apply( this, arguments ); }) : fn; - return type === "unload" && name !== "one" ? - this.one( type, data, fn ) : - this.each(function() { - jQuery.event.add( this, type, handler, data ); - }); + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; }; }); @@ -811,13 +857,29 @@ jQuery.fn.extend({ for ( var key in type ) { this.unbind(key, type[key]); } - return this; + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } } - return this.each(function() { - jQuery.event.remove( this, type, fn ); - }); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } }, + trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); @@ -862,8 +924,10 @@ jQuery.fn.extend({ }); jQuery.each(["live", "die"], function( i, name ) { - jQuery.fn[ name ] = function( types, data, fn ) { - var type, i = 0; + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); if ( jQuery.isFunction( data ) ) { fn = data; @@ -880,13 +944,13 @@ jQuery.each(["live", "die"], function( i, name ) { if ( name === "live" ) { // bind live handler - jQuery( this.context ).bind( liveConvert( type, this.selector ), { - data: data, selector: this.selector, live: type + context.bind( liveConvert( type, selector ), { + data: data, selector: selector, live: type }, fn ); } else { // unbind live handler - jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null ); + context.unbind( liveConvert( type, selector ), fn ? { guid: fn.guid + selector + type } : null ); } } @@ -954,7 +1018,7 @@ function liveHandler( event ) { } function liveConvert( type, selector ) { - return "live." + (type ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); + return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); } jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +