Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created April 26, 2012 14:32
Show Gist options
  • Save bennadel/2499976 to your computer and use it in GitHub Desktop.
Save bennadel/2499976 to your computer and use it in GitHub Desktop.
Mouse vs. Keyboard - Determining Click Initiator Using A jQuery Custom Event
<!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