YUI 3.x Home -

Site Search (YDN & YUIBlog):

# 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:

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

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

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

View example in new window.

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.

    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    }} );

    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
        }
    } );

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.

    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 + '*' );    }} );

    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 + '*' );
        }
    } );

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

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

    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.

    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 );    },    ...

    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 );
        },
        ...

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.

    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" );} );

    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" );
    } );

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

    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" );    } ); } );

    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" );
        } );

    } );

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