Skip to content

@MathiasPaumgarten /touchmouse.js
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
This snippet maps mouse events and touch events onto one single event. This makes it easier in the code since you have to listen to only one event regardles whether it's desktop or mobile.
(function() {
/* == GLOBAL DECLERATIONS == */
TouchMouseEvent = {
DOWN: "touchmousedown",
UP: "touchmouseup",
MOVE: "touchmousemove"
}
/* == EVENT LISTENERS == */
var onMouseEvent = function(event) {
var type;
switch (event.type) {
case "mousedown": type = TouchMouseEvent.DOWN; break;
case "mouseup": type = TouchMouseEvent.UP; break;
case "mousemove": type = TouchMouseEvent.MOVE; break;
default:
return;
}
var touchMouseEvent = normalizeEvent(type, event, event.pageX, event.pageY);
$(event.target).trigger(touchMouseEvent);
}
var onTouchEvent = function(event) {
var type;
switch (event.type) {
case "touchstart": type = TouchMouseEvent.DOWN; break;
case "touchend": type = TouchMouseEvent.UP; break;
case "touchmove": type = TouchMouseEvent.MOVE; break;
default:
return;
}
var touch = event.originalEvent.touches[0];
var touchMouseEvent;
if (type == TouchMouseEvent.UP)
touchMouseEvent = normalizeEvent(type, event, null, null);
else
touchMouseEvent = normalizeEvent(type, event, touch.pageX, touch.pageY);
$(event.target).trigger(touchMouseEvent);
}
/* == NORMALIZE == */
var normalizeEvent = function(type, original, x, y) {
return $.Event(type, {
pageX: x,
pageY: y,
originalEvent: original
});
}
/* == LISTEN TO ORIGINAL EVENT == */
var jQueryDocument = $(document);
if ("ontouchstart" in window) {
jQueryDocument.on("touchstart", onTouchEvent);
jQueryDocument.on("touchmove", onTouchEvent);
jQueryDocument.on("touchend", onTouchEvent);
} else {
jQueryDocument.on("mousedown", onMouseEvent);
jQueryDocument.on("mouseup", onMouseEvent);
jQueryDocument.on("mousemove", onMouseEvent);
}
})();
@millermedeiros

You can simply do $(document).on('touchstart mousedown', doSomething); or if not using jQuery I have an abstraction for touch events as well, only thing I plan to change is to remove momentum from the ended dispatch (since it's easy to calculate and most times not needed): https://github.com/millermedeiros/MM_js_lib/blob/master/src/events/TouchController.js

@MathiasPaumgarten

nice - thanks for the review. That would make the sure would make the code less verbose. I pretty much only use this snippet when I need X/Y coordinates. I'd say the nicest part is not the "one event for all" - thing but rather the easy access for X and Y. One thing I might add is X/Y on touchend. It's really annoying that webkit does not support it. In my mind, that makes absolutly no sense.

Anyways. I have to rework this code anyways. Just made it a gist for easy access for an article I wrote. I didn't want to make a repo for 70 lines of code. :)

Thanks for feedback.

@alexlaq

Hey!
This is a great piece of code. It works well, but I cannot seem to be able to make it work with the .live() function. I made sure that the TouchMouseEvent was fired, but for some reason the code in the live() function does not execute. I tried :
$('#MyElement').live('TouchMouseEvent', function(){...});
$('#MyElement').live('normalizeEvent', function(){...});
$('#MyElement').live('touchMouseEvent', function(){...});

None of them worked. I know that since jQuery 1.4, the live() function supports custom events, so I don't know why this would not work.
Any help would be appreciated.

@MathiasPaumgarten

@alexlaq Hey, I'm sorry - I haven't seen your comment until now (7 months later ... I know). You problably have figured it out by now but anyways:

You have to listen to one of the TouchMouseEvent like so:

$( "#id" ).live( TouchMouseEvent.DOWN, function( event ) {...} );

or

$( "#id" ).live( "touchmousedown", function( event ) {...} );

I hope that helps.

@juarezpaf

Thanks a lot Mathias for this amazing snippet, it's working very nice with my image crop process, because of this I have mobile devices enabled. :)

@Karu14

Hi, i have an html file with with mouse events in it, i linked your js file to it and tried on cordova.. but no success. can u please help me.. Thank you.

@Framelova

You just save the day, the script works perfectly and avoid to us have to write down a different script when user enter vía touch device.

@jayboyd

Thanks for this, I was going crazy trying to normalize. Touchend events can be handled, (at least in iOS Safari 7+, haven't tested everywhere), like so:

if (type == TouchMouseEvent.UP) {
    var touch = event.originalEvent.changedTouches[0];
    touchMouseEvent = normalizeEvent(type, event, touch.pageX, touch.pageY);
}

One minor caveat of your approach is that it doesn't allow calling event.preventDefault(); you must call event.originalEvent.preventDefault() after normalizing. Just a heads-up.

@warrenca

Thanks for this! This is a life saver! I got a problem in iOS 7.1 Safari browser that when you generate a draggable element via javascript, the browser detect it as a mouse event. So you can't really drag the element.

@aram909

How would I deal with things like targetTouches or the equivalent of that for mouse events?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.