Created
April 26, 2012 14:32
-
-
Save bennadel/2499976 to your computer and use it in GitHub Desktop.
Mouse vs. Keyboard - Determining Click Initiator Using A jQuery Custom Event
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Determine Link Trigger Method With jQuery</title> | |
</head> | |
<body> | |
<h1> | |
Determine Link Trigger Method With jQuery | |
</h1> | |
<p> | |
<a href="#" class="link">Click me please</a>!<br /> | |
<a href="#" class="link">Click me please</a>!<br /> | |
<a href="#" class="link">Click me please</a>!<br /> | |
<a href="#" class="link">Click me please</a>!<br /> | |
</p> | |
<!-- Configure scripts. --> | |
<script type="text/javascript" src="../jquery-1.7.1.js"></script> | |
<script type="text/javascript"> | |
// Set up a special Event Type which will help us to | |
// determine what physical device was used to initiate the | |
// click event on a given element: Mouse or Keywboard. Since | |
// there doesn't appear to be anything inherent to the click | |
// event that denotes device (cross-browser), we'll have to | |
// use some surrounding events to setup the click event | |
// handler data. The default device is considered the Mouse; | |
// the alternate device is the keyboard. | |
(function( $ ){ | |
// When a key is depressed, we want to signal that this | |
// might be a keyboard-initiated click event. As such, | |
// we'll store a boolean to be used in the click event. | |
function handleKeyDown( event ){ | |
// Check to make sure that this key is one that is | |
// capable of triggering a click event (ie. the enter | |
// button, 13). | |
if (event.which === 13){ | |
$.data( this, "clickwithevent:keyboard", true ); | |
} | |
} | |
// When a key is released, we know that the click event | |
// will have already take place (if at all); as such, we | |
// set the boolean flag to false since any subsequent | |
// click event will be triggered by a mouse (or preceeded | |
// by a keydown event). | |
function handleKeyUp( event ){ | |
$.data( this, "clickwithevent:keyboard", false ); | |
} | |
// When the click event is triggered, we need to | |
// determine if the event was initiated by the keyboard | |
// or the mouse. If the boolean flag is true, it means | |
// that the click event was preceeded by the depression | |
// of the Enter key, which indicates that the click event | |
// was initiated by the keyboard. | |
function handleClick( event ){ | |
// Get the flag for keyboard-based click. | |
var isKeyPress = $.data( this, "clickwithevent:keyboard" ); | |
// Let's create a new event that extends the click | |
// event. This way, when we trigger our "clickwith" | |
// event, we get all of the contextual information | |
// associated with the click; but, we don't | |
// accidientally trigger click events. | |
var clickEvent = createEvent( "clickwith", event ) | |
// Tell jQuery to trigger the new event with a second | |
// argument that indicates the initiator of the click | |
// event. | |
$.event.handle.apply( | |
this, | |
[clickEvent, (isKeyPress ? "keyboard" : "mouse")] | |
); | |
} | |
// I create a new jQuery event object using the given | |
// event object as the collection of properties to copy. | |
// This way, we can "extend" an existing Event object | |
// without worrying about copying data we shouldn't. | |
function createEvent( eventType, event ){ | |
// For each event object, we will try to copy all of | |
// the following properties that are available. | |
var properties = [ | |
"altKey", "bubbles", "button", "cancelable", | |
"charCode", "clientX", "clientY", "ctrlKey", | |
"currentTarget", "data", "detail", "eventPhase", | |
"metaKey", "offsetX", "offsetY", "originalTarget", | |
"pageX", "pageY", "prevValue", "relatedTarget", | |
"screenX", "screenY", "shiftKey", "target", | |
"view", "which" | |
]; | |
// Create a new properties object that will be used | |
// to create the new event. | |
var eventProperties = {} | |
// Copy over all properties from the old event. | |
$.each( | |
properties, | |
function( index, property ){ | |
// Make sure this property is available on | |
// the original event. | |
if (property in event){ | |
// Copy it over to the new event property | |
// collection. | |
eventProperties[ property ] = event[ property ]; | |
} | |
} | |
); | |
// Create and return the new event object with the | |
// duplicated properties. | |
return( | |
new $.Event( eventType, eventProperties ) | |
); | |
} | |
// Configure the special event, "clickwith", so that | |
// jQuery knows how to bind and unbind event handlers. | |
$.event.special.clickwith = { | |
// I configure each element that is bound to the | |
// clickwith event. I am only called once per element. | |
setup: function( data, namespaces ){ | |
// Set up the key events that surround the click | |
// events that setup the meta data. | |
$( this ) | |
.data( "clickwithevent:keyboard", false ) | |
.on( "keydown.clickwithevent", handleKeyDown ) | |
.on( "keyup.clickwithevent", handleKeyUp ) | |
.on( "click.clickwithevent", handleClick ) | |
; | |
}, | |
// I remove the configuration from each element that | |
// is bound to the clickwith event. I am only called | |
// oncer per element.s | |
teardown: function( namespaces ){ | |
// Remove all traces of the special event. | |
$( this ) | |
.removeData( "clickwithevent:keyboard" ) | |
.off( "keydown.clickwithevent" ) | |
.off( "keyup.clickwithevent" ) | |
.off( "click.clickwithevent" ) | |
; | |
} | |
}; | |
})( jQuery ); | |
// -------------------------------------------------- // | |
// -------------------------------------------------- // | |
// Make sure this event works on a direct event binding. | |
$( "a.link" ).on( | |
"clickwith", | |
function( event, trigger ){ | |
console.log( "LOCAL[ " + trigger + " ]", event ); | |
} | |
); | |
// Make sure this event works on a delegated event binding. | |
$( document ).on( | |
"clickwith", | |
"a.link", | |
function( event, trigger ){ | |
console.log( "GLOBAL[ " + trigger + " ]", event ); | |
} | |
); | |
// Try manually triggering a click event (which should, in | |
// turn, trigger a clickwith event, using the Mouse as the | |
// default device trigger). | |
$( "a.link:first" ) | |
.trigger( "click" ) | |
; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment