Bug Tracker

Ticket #3662: event-object[6004].diff

File event-object[6004].diff, 10.6 KB (added by flesler, 13 years ago)

This version makes all the tests pass, adds currentTarget attribute to event objects

  • src/event.js

     
    163163                }
    164164        },
    165165
    166         trigger: function(type, data, elem, donative, extra, dohandlers) {
    167                 // Clone the incoming data, if any
    168                 data = jQuery.makeArray(data);
    169 
    170                 if ( type.indexOf("!") >= 0 ) {
    171                         type = type.slice(0, -1);
    172                         var exclusive = true;
    173                 }
    174 
     166        trigger: function( e, data, elem, donative, extra, dohandlers) {
     167                // Event object or event type
     168                var type = e.type || e;
     169               
    175170                // Handle a global trigger
    176171                if ( !elem ) {
    177172                        // Only trigger if we've ever bound an event for it
    178173                        if ( this.global[type] )
    179174                                jQuery.each( jQuery.cache, function(){
    180175                                        if ( this.events && this.events[type] )
    181                                                 jQuery.event.trigger( type, data, this.handle.elem, false );
     176                                                jQuery.event.trigger( e, data, this.handle.elem, false );
    182177                                });
    183178
    184179                // Handle triggering a single element
    185180                } else {
     181
    186182                        // don't do events on text and comment nodes
    187183                        if ( elem.nodeType == 3 || elem.nodeType == 8 )
    188184                                return undefined;
    189185
    190                         var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
    191                                 // Check to see if we need to provide a fake event, or not
    192                                 event = !data[0] || !data[0].preventDefault;
    193 
    194                         // Pass along a fake event
    195                         if ( event ) {
    196                                 data.unshift({
    197                                         type: type,
    198                                         target: elem,
    199                                         preventDefault: function(){},
    200                                         stopPropagation: function(){},
    201                                         stopImmediatePropagation:stopImmediatePropagation,
    202                                         timeStamp: now()
    203                                 });
    204                                 data[0][expando] = true; // no need to fix fake event
     186                        // Clone the incoming data, if any
     187                        data = jQuery.makeArray(data);
     188                       
     189                        if ( type.indexOf("!") >= 0 ) {
     190                                type = type.slice(0, -1);
     191                                var exclusive = true;
    205192                        }
     193                       
     194                        e = typeof e === "object" ?
     195                                // jQuery.Event object
     196                                e[expando] ? e :
     197                                // Object literal
     198                                jQuery.extend( new jQuery.Event(type), e ) :
     199                                // Just the event type (string)
     200                                new jQuery.Event(type);
     201                               
     202                        e.target = e.target || elem;
     203                        e.currentTarget = elem;
     204                        e.exclusive = exclusive;
     205                       
     206                        data.unshift( e );
    206207
    207                         // Enforce the right trigger type
    208                         data[0].type = type;
    209                         if ( exclusive )
    210                                 data[0].exclusive = true;
     208                        var val, ret, fn = jQuery.isFunction( elem[ type ] );
    211209
    212210                        if ( dohandlers !== false ) {
    213211                                // Trigger the event, it is assumed that "handle" is a function
     
    223221                        if ( donative !== false && val !== false ) {
    224222                                var parent = elem.parentNode || elem.ownerDocument;
    225223                                if ( parent )
    226                                         jQuery.event.trigger(type, data, parent, donative);
     224                                        jQuery.event.trigger(e, data, parent, donative);
    227225                        }
    228226
    229227                        // Extra functions don't get the custom event object
    230                         if ( event )
    231                                 data.shift();
     228                        data.shift();
    232229
    233230                        // Handle triggering of extra function
    234231                        if ( extra && jQuery.isFunction( extra ) ) {
     
    300297                return val;
    301298        },
    302299
    303         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 timeStamp toElement type view wheelDelta which".split(" "),
     300        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(" "),
    304301
    305302        fix: function(event) {
    306303                if ( event[expando] )
     
    309306                // store a copy of the original event object
    310307                // and "clone" to set read-only properties
    311308                var originalEvent = event;
    312                 event = { originalEvent: originalEvent };
     309                event = new jQuery.Event( originalEvent );
    313310
    314311                for ( var i = this.props.length, prop; i; ){
    315312                        prop = this.props[ --i ];
    316313                        event[ prop ] = originalEvent[ prop ];
    317314                }
    318315
    319                 // Mark it as fixed
    320                 event[expando] = true;
    321 
    322                 // add preventDefault and stopPropagation since
    323                 // they will not work on the clone
    324                 event.preventDefault = function() {
    325                         // if preventDefault exists run it on the original event
    326                         if (originalEvent.preventDefault)
    327                                 originalEvent.preventDefault();
    328                         // otherwise set the returnValue property of the original event to false (IE)
    329                         originalEvent.returnValue = false;
    330                 };
    331                 event.stopPropagation = function() {
    332                         // if stopPropagation exists run it on the original event
    333                         if (originalEvent.stopPropagation)
    334                                 originalEvent.stopPropagation();
    335                         // otherwise set the cancelBubble property of the original event to true (IE)
    336                         originalEvent.cancelBubble = true;
    337                 };
    338 
    339                 event.stopImmediatePropagation = stopImmediatePropagation;
    340 
    341                 // Fix timeStamp
    342                 event.timeStamp = event.timeStamp || now();
    343 
    344316                // Fix target property, if necessary
    345317                if ( !event.target )
    346318                        event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
     
    413385        }
    414386};
    415387
    416 function stopImmediatePropagation(){
    417         this._sip = 1;
    418         this.stopPropagation();
    419 }
     388jQuery.Event = function( src ){
     389        // Event object
     390        if( src && src.type ){
     391                this.originalEvent = src;
     392                this.type = src.type;
     393               
     394                // Fix timeStamp
     395                this.timeStamp = src.timeStamp || now();
     396        // Event type
     397        }else
     398                this.type = src;
    420399
     400        // Mark it as fixed
     401        this[expando] = true;
     402};
     403
     404jQuery.Event.prototype = {
     405        // add preventDefault and stopPropagation since
     406        // they will not work on the clone
     407        preventDefault: function() {
     408                var e = this.originalEvent;
     409                if( !e )
     410                        return;
     411                // if preventDefault exists run it on the original event
     412                if (e.preventDefault)
     413                        e.preventDefault();
     414                // otherwise set the returnValue property of the original event to false (IE)
     415                e.returnValue = false;
     416        },
     417        stopPropagation: function() {
     418                var e = this.originalEvent;
     419                if( !e )
     420                        return;
     421                // if stopPropagation exists run it on the original event
     422                if (e.stopPropagation)
     423                        e.stopPropagation();
     424                // otherwise set the cancelBubble property of the original event to true (IE)
     425                e.cancelBubble = true;
     426        },
     427        stopImmediatePropagation:function(){
     428                this._sip = true;
     429                this.stopPropagation();
     430        }
     431};
    421432// Checks if an event happened on an element within another element
    422433// Used in jQuery.event.special.mouseenter and mouseleave handlers
    423434var withinElement = function(event) {
  • test/unit/event.js

     
    301301                equals( c, "abc", "check passed data" );
    302302                equals( v, "test", "check current value" );
    303303        };
     304       
     305        var $elem = jQuery("#firstp");
    304306
    305307        // Simulate a "native" click
    306         jQuery("#firstp")[0].click = function(){
     308        $elem[0].click = function(){
    307309                ok( true, "Native call was triggered" );
    308310        };
    309311
    310312        // Triggers handlrs and native
    311313        // Trigger 5
    312         jQuery("#firstp").bind("click", handler).trigger("click", [1, "2", "abc"]);
     314        $elem.bind("click", handler).trigger("click", [1, "2", "abc"]);
    313315
    314316        // Triggers handlers, native, and extra fn
    315317        // Triggers 9
    316         jQuery("#firstp").trigger("click", [1, "2", "abc"], handler4);
     318        $elem.trigger("click", [1, "2", "abc"], handler4);
    317319
    318320        // Simulate a "native" click
    319         jQuery("#firstp")[0].click = function(){
     321        $elem[0].click = function(){
    320322                ok( false, "Native call was triggered" );
    321323        };
    322324
    323         // Triggers handlers, native, and extra fn
    324         // Triggers 7
    325         jQuery("#firstp").trigger("click", [1, "2", "abc"], handler2);
    326 
    327325        // Trigger only the handlers (no native)
    328326        // Triggers 5
    329         equals( jQuery("#firstp").triggerHandler("click", [1, "2", "abc"]), "test", "Verify handler response" );
     327        equals( $elem.triggerHandler("click", [1, "2", "abc"]), "test", "Verify handler response" );
    330328
    331329        // Trigger only the handlers (no native) and extra fn
    332330        // Triggers 8
    333         equals( jQuery("#firstp").triggerHandler("click", [1, "2", "abc"], handler2), false, "Verify handler response" );
     331        equals( $elem.triggerHandler("click", [1, "2", "abc"], handler2), false, "Verify handler response" );
    334332
    335333        // Build fake click event to pass in
    336         var eventObj = jQuery.event.fix({ type: "foo", target: document.body });
     334        var eventObj = new jQuery.Event("click");
    337335
    338336        // Trigger only the handlers (no native), with external event obj
    339337        // Triggers 5
    340         equals( jQuery("#firstp").triggerHandler("click", [eventObj, 1, "2", "abc"]), "test", "Verify handler response" );
     338        equals( $elem.triggerHandler(eventObj, [1, "2", "abc"]), "test", "Verify handler response" );
    341339
    342340        // Trigger only the handlers (no native) and extra fn, with external event obj
    343341        // Triggers 9
    344         eventObj = jQuery.event.fix({ type: "foo", target: document.body });
    345         equals( jQuery("#firstp").triggerHandler("click", [eventObj, 1, "2", "abc"], handler), "test", "Verify handler response" );
     342        eventObj = new jQuery.Event("click");
     343        equals( $elem.triggerHandler(eventObj, [1, "2", "abc"], handler2), false, "Verify handler response" );
    346344       
    347345        var pass = true;
    348346        try {
    349                 jQuery('#form input:first')
    350                         .hide()
    351                         .trigger('focus');
     347                jQuery('#form input:first').hide().trigger('focus');
    352348        } catch(e) {
    353349                pass = false;
    354350        }
     
    356352
    357353        // have the extra handler override the return
    358354        // Triggers 9
    359         equals( jQuery("#firstp").triggerHandler("click", [1, "2", "abc"], handler3), "newVal", "Verify triggerHandler return is overwritten by extra function" );
     355        equals( $elem.triggerHandler("click", [1, "2", "abc"], handler3), "newVal", "Verify triggerHandler return is overwritten by extra function" );
    360356
    361357        // have the extra handler leave the return value alone
    362358        // Triggers 9
    363         equals( jQuery("#firstp").triggerHandler("click", [1, "2", "abc"], handler4), "test", "Verify triggerHandler return is not overwritten by extra function" );
     359        equals( $elem.triggerHandler("click", [1, "2", "abc"], handler4), "test", "Verify triggerHandler return is not overwritten by extra function" );
     360       
     361        $elem.unbind('click').bind('foo',function(e){
     362                equals( e.type, 'foo', 'Verify event type when passed passing an event object' );
     363                equals( e.target.id, 'simon1', 'Verify event.target when passed passing an event object' );
     364                equals( e.currentTarget.id, 'firstp', 'Verify event.target when passed passing an event object' );
     365                equals( e.secret, 'boo!', 'Verify event object\'s custom attribute when passed passing an event object' );
     366        });
     367       
     368        eventObj = new jQuery.Event('foo');
     369        eventObj.secret = 'boo!';
     370       
     371        // Test with event object and bubbling 
     372        jQuery("#simon1").trigger( eventObj );
     373       
     374        // Try passing an object literal
     375        jQuery("#simon1").trigger( {type:'foo', secret:'boo!'} );
     376       
     377        $elem.unbind('foo');
    364378});
    365379
    366380test("toggle(Function, Function, ...)", function() {