Created
July 12, 2012 14:47
-
-
Save bryanforbes/3098594 to your computer and use it in GitHub Desktop.
_OnDijitClickMixin fix for touch devices
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
// 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