Skip to content

Instantly share code, notes, and snippets.

@bryanforbes
Created July 12, 2012 14:47
Show Gist options
  • Save bryanforbes/3098594 to your computer and use it in GitHub Desktop.
Save bryanforbes/3098594 to your computer and use it in GitHub Desktop.
_OnDijitClickMixin fix for touch devices
// Implemented as a monkey-patch for dijit/_OnDijitClickMixin
define([
"dijit/_OnDijitClickMixin",
"dojo/on",
"dojo/_base/window",
"dojo/dom-geometry",
"dijit/registry",
"dojo/domReady!"
], function(_OnDijitClickMixin, on, win, domGeometry, registry){
// The following implements a fast button handler for Dijit widgets.
// Adapted from https://developers.google.com/mobile/articles/fast_buttons.
// Capture handler to prevent clicks we didn't generate
function onClick(event){
if(!event._ghostBuster){
// Stop clicks that we didn't generate
event.stopPropagation();
event.preventDefault();
}
}
// Handler to dojo/on
function a11yclick(node, listener){
var touchend, parentTouchstart, widget,
fireClick = 1;
// Called when touchend handler is called and if this handler is
// removed. Cleans up potential touchend and parent touchstart
// handlers.
function remove(){
touchend && touchend.remove && touchend.remove();
parentTouchstart && parentTouchstart.remove && parentTouchstart.remove();
touchend = parentTouchstart = null;
}
// Hook up touchstart on the passed in node
var touchstart = on(node, "touchstart", function(event){
// Hook up touchstart on parent node to see if touchstart
// has been prevented
parentTouchstart = on(node.parentNode, "touchstart", function(event){
fireClick = !event.defaultPrevented;
});
// Hook up touchend for ghost clicks and bounds checking
touchend = on(node, "touchend", function(event){
remove();
// If touchstart was prevented, don't fire
// click handler
if(!fireClick){
return;
}
if(!widget){
widget = registry.getEnclosingWidget(node);
}
var position = domGeometry.position(widget.domNode);
// Determine if the touchend happened within the bounds
// of the widget. If so, fire click event.
if(!(event.clientX < position.x ||
event.clientX > position.x + position.w ||
event.clientY < position.y ||
event.clientY > position.y + position.h)){
// Fire synthetic click event to trigger
// click handlers immediately.
on.emit(event.target, "click", {
_ghostBuster: 1,
cancelable: true,
bubbles: true
// TODO: should probably add things like clientX/Y
});
}
});
});
// Hook up capture event to prevent native clicks
// from propagating and bubbling
node.addEventListener("click", onClick, true);
// Hook up click on the passed in node. Unlike Google's
// implementation, this will always call the listener with a
// click event, which prevents Dijit from calling preventDefault
// on touchend events.
var click = on(node, "click", function(event){
listener.call(widget, event);
});
// Return an event handler object
return {
remove: function(){
touchstart.remove();
node.removeEventListener("click", onClick, true);
click.remove();
remove();
}
};
}
_OnDijitClickMixin.extend({
connect: function(
/*Object|null*/ obj,
/*String|Function*/ event,
/*String|Function*/ method){
return this.inherited(arguments, [obj, event === "ondijitclick" ? a11yclick : event, method]);
}
});
_OnDijitClickMixin.a11yclick = a11yclick;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment