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 );
Hover over me
on
, fire
, and detach
The three interesting moments in the lifecycle of an event subscription are
- The event is subscribed to
- The event is fired
- 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 } } );
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 + '*' ); } } );
Extended subscription signature
The target subscription API for the hover
event will be
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 ); }, ...
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" ); } );
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" ); } ); } );