YUI 3.x Home -

YUI Library Examples: Event: Creating a hover event for DOM subscription

Event: Creating a hover event for DOM subscription

This example will illustrate how to use the synthetic event creation API. We'll create a hover event that accepts two functions at subscription time, the first being the function that executes when the hover begins, and the second when the hover ends.

Subscribing to this new event will look like this:

  1. node.on( "hover", onHover, endHover );
node.on( "hover", onHover, endHover );

Hover over me

on, fire, and detach

The three interesting moments in the lifecycle of an event subscription are

  1. The event is subscribed to
  2. The event is fired
  3. The event is unsubscribed from

Create a new synthetic DOM event with Y.Event.define( name, config ). Define the implementation logic for the on and detach moments in the configuration. Typically the condition triggering the event firing is set up in the on phase.

  1. Y.Event.define( "hover", {
  2. on: function ( node, sub, notifier ) {
  3. // what happens when a subscription is made
  4.  
  5. // if (condition) {
  6. notifier.fire(); // subscribers executed
  7. // }
  8. },
  9.  
  10. detach: function ( node, sub, notifier ) {
  11. // what happens when a subscription is removed
  12. }
  13. } );
Y.Event.define( "hover", {
    on: function ( node, sub, notifier ) {
        // what happens when a subscription is made
 
        // if (condition) {
            notifier.fire(); // subscribers executed
        // }
    },
 
    detach: function ( node, sub, notifier ) {
        // what happens when a subscription is removed
    }
} );

In the case of hovering, the trigger is simply a mouseover, or better yet, a mouseenter event.

  1. Y.Event.define( "hover", {
  2. on: function ( node, sub, notifier ) {
  3. // To make detaching the associated DOM events easy, use a
  4. // detach category, but keep the category unique per subscription
  5. // by creating the category with Y.guid()
  6. sub._evtGuid = Y.guid() + '|';
  7.  
  8. node.on( sub._evtGuid + "mouseenter", function ( e ) {
  9. // Firing the notifier event executes the hover subscribers
  10. notifier.fire();
  11. } );
  12. },
  13.  
  14. detach: function ( node, sub, notifier ) {
  15. // Detach the mouseenter and mouseout subscriptions using the detach
  16. // category - node.detach( 'foo|*' ) detaches everything in category foo
  17. node.detach( sub._evtGuid + '*' );
  18. }
  19. } );
Y.Event.define( "hover", {
    on: function ( node, sub, notifier ) {
        // To make detaching the associated DOM events easy, use a
        // detach category, but keep the category unique per subscription
        // by creating the category with Y.guid()
        sub._evtGuid = Y.guid() + '|';
 
        node.on( sub._evtGuid + "mouseenter", function ( e ) {
            // Firing the notifier event executes the hover subscribers
            notifier.fire();
        } );
    },
 
    detach: function ( node, sub, notifier ) {
        // Detach the mouseenter and mouseout subscriptions using the detach
        // category - node.detach( 'foo|*' ) detaches everything in category foo
        node.detach( sub._evtGuid + '*' );
    }
} );

Extended subscription signature

The target subscription API for the hover event will be

  1. node.on( "hover", onHover, endHover );
node.on( "hover", onHover, endHover );

This differs from the normal subscription signature by introducing a second handler for the end of the hover. In the configuration passed to Y.Event.define, you can include an argument pre-processor function in processArgs. Inside that function, extract any additional info from the subscription arguments, then remove them. What's returned from the function is stored in the subscription object's _extra property.

  1. Y.Event.define( "hover", {
  2. processArgs: function ( args ) {
  3. // Args received here match the Y.on(...) order, so
  4. // [ 'hover', onHover, node, endHover, etc ]
  5. var mouseleave = args[3]; // capture the second function
  6. args.splice(3,1); // then remove it from the arguments
  7.  
  8. // This will be stored in the subscription's '_extra' property
  9. return mouseleave;
  10. },
  11.  
  12. on: function ( node, sub, notifier ) {
  13. var mouseleave = sub._extra;
  14.  
  15. // To make detaching the associated DOM events easy, use a
  16. // detach category, but keep the category unique per subscription
  17. // by creating the category with Y.guid()
  18. sub._evtGuid = Y.guid() + '|';
  19.  
  20. node.on( sub._evtGuid + "mouseenter", function ( e ) {
  21. // Firing the notifier event executes the hover subscribers
  22. notifier.fire();
  23. } );
  24.  
  25. node.on( sub._evtGuid + "mouseleave", mouseleave );
  26. },
  27. ...
Y.Event.define( "hover", {
    processArgs: function ( args ) {
        // Args received here match the Y.on(...) order, so
        // [ 'hover', onHover, node, endHover, etc ]
        var mouseleave = args[3]; // capture the second function
        args.splice(3,1);         // then remove it from the arguments
 
        // This will be stored in the subscription's '_extra' property
        return mouseleave;
    },
 
    on: function ( node, sub, notifier ) {
        var mouseleave = sub._extra;
 
        // To make detaching the associated DOM events easy, use a
        // detach category, but keep the category unique per subscription
        // by creating the category with Y.guid()
        sub._evtGuid = Y.guid() + '|';
 
        node.on( sub._evtGuid + "mouseenter", function ( e ) {
            // Firing the notifier event executes the hover subscribers
            notifier.fire();
        } );
 
        node.on( sub._evtGuid + "mouseleave", mouseleave );
    },
    ...

Use it

Subscribe to the new event or detach the event as you would any other DOM event.

  1. function onHover( e ) {
  2. this.addClass( "hover" );
  3. }
  4. function endHover( e ) {
  5. this.removeClass( "hover" );
  6. }
  7.  
  8. Y.one( "#attach" ).on( "click", function ( e ) {
  9. Y.one( "#demo p" ).on( "hover", onHover, endHover );
  10. } );
  11.  
  12. Y.one( "#detach" ).on( "click", function ( e ) {
  13. Y.one( "#demo p" ).detach( "hover" );
  14. } );
function onHover( e ) {
    this.addClass( "hover" );
}
function endHover( e ) {
    this.removeClass( "hover" );
}
 
Y.one( "#attach" ).on( "click", function ( e ) {
    Y.one( "#demo p" ).on( "hover", onHover, endHover );
} );
 
Y.one( "#detach" ).on( "click", function ( e ) {
    Y.one( "#demo p" ).detach( "hover" );
} );

Full Code Listing

  1. YUI( ).use( "event-synthetic", "event-mouseenter", function ( Y ) {
  2.  
  3. Y.Event.define( "hover", {
  4. processArgs: function ( args ) {
  5. // Args received here match the Y.on(...) order, so
  6. // [ 'hover', onHover, "#demo p", endHover, etc ]
  7. var mouseleave = args[3];
  8. args.splice(3,1);
  9.  
  10. // This will be stored in the subscription's '_extra' property
  11. return mouseleave;
  12. },
  13.  
  14. on: function ( node, sub, notifier ) {
  15. var mouseleave = sub._extra;
  16.  
  17. // To make detaching the associated DOM events easy, use a
  18. // detach category, but keep the category unique per subscription
  19. // by creating the category with Y.guid()
  20. sub._evtGuid = Y.guid() + '|';
  21.  
  22. node.on( sub._evtGuid + "mouseenter", function ( e ) {
  23. // Firing the notifier event executes the hover subscribers
  24. notifier.fire();
  25. } );
  26.  
  27. node.on( sub._evtGuid + "mouseleave", mouseleave );
  28. },
  29.  
  30. detach: function ( node, sub, notifier ) {
  31. // Detach the mouseenter and mouseout subscriptions using the
  32. // detach category
  33. node.detach( sub._evtGuid + '*' );
  34. }
  35. } );
  36.  
  37. function onHover( e ) {
  38. this.addClass( "hover" );
  39. }
  40. function endHover( e ) {
  41. this.removeClass( "hover" );
  42. }
  43.  
  44. Y.one( "#attach" ).on( "click", function ( e ) {
  45. Y.one( "#demo p" ).on( "hover", onHover, endHover );
  46. } );
  47.  
  48. Y.one( "#detach" ).on( "click", function ( e ) {
  49. Y.one( "#demo p" ).detach( "hover" );
  50. } );
  51.  
  52. } );
YUI(  ).use( "event-synthetic", "event-mouseenter", function ( Y ) {
 
    Y.Event.define( "hover", {
        processArgs: function ( args ) {
            // Args received here match the Y.on(...) order, so
            // [ 'hover', onHover, "#demo p", endHover, etc ]
            var mouseleave = args[3];
            args.splice(3,1);
 
            // This will be stored in the subscription's '_extra' property
            return mouseleave;
        },
 
        on: function ( node, sub, notifier ) {
            var mouseleave = sub._extra;
 
            // To make detaching the associated DOM events easy, use a
            // detach category, but keep the category unique per subscription
            // by creating the category with Y.guid()
            sub._evtGuid = Y.guid() + '|';
 
            node.on( sub._evtGuid + "mouseenter", function ( e ) {
                // Firing the notifier event executes the hover subscribers
                notifier.fire();
            } );
 
            node.on( sub._evtGuid + "mouseleave", mouseleave );
        },
 
        detach: function ( node, sub, notifier ) {
            // Detach the mouseenter and mouseout subscriptions using the
            // detach category
            node.detach( sub._evtGuid + '*' );
        }
    } );
 
    function onHover( e ) {
        this.addClass( "hover" );
    }
    function endHover( e ) {
        this.removeClass( "hover" );
    }
 
    Y.one( "#attach" ).on( "click", function ( e ) {
        Y.one( "#demo p" ).on( "hover", onHover, endHover );
    } );
 
    Y.one( "#detach" ).on( "click", function ( e ) {
        Y.one( "#demo p" ).detach( "hover" );
    } );
 
} );

Copyright © 2010 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings