Saturday, December 1, 2012

Proxying Touch Events to Enable jQuery UI Mouse Interactions

All the jQuery mouse interaction widgets (draggable, droppable, etc) are great until you try them on a touch enabled device like a tablet or phone. Those browsers do not generate mousedown, mousemove, or mouseup events. Instead, they generate toushstart, touchmove, and touchend events. Since jQuery UI is only binding to the mouse events, it will never receive a touch event which results in nothing working. You might be tempted to just bind to the touch events and try to treat them as mouse events. However, because most devices allow multiple touch points, the event does not have a single pageX/pageY variable. Each touch point is represented in an array of touches so any code would have to detect the touch event and look at that array instead of the standard pageX/Y variables.

An alternative approach would be to simply capture the touch events, pull out one of the touches, and then fire the equivalent mouse events. Fortunately, someone already thought of this and created a little hack called Touch Punch to basically proxy touch events and convert them to mouse events. The nice thing about this little library is that it doesn't require to do anything other than including it on your page to use it. Once its added, it just works - all the normal mouse interactions in jQuery UI function on a touch device.

I added it to my sandbox so my demos would be useable on a touch enabled device. As I tested several pages, all the jQuery UI elements worked properly, however, anything I personally bound to mousedown did not work as intended. I created a page on my sandbox specifically to try out the Touch Punch functionality. The goal was to animate something while the mouse was held (mousedown) and animate back to the start when the mouse was released (mouseup). Using Touch Punch, the mousedown event didn't behave the same between my computer and tablet. On the computer, it worked as expected - the animation continued as long as I held the mouse down. On the tablet, it just skipped to the end and then animated back to the beginning as if I on clicked on the element.

I suspect the difference in behavior is due to how the jQuery UI mouse interactions bind to the different events. I spent some time reviewing the UI code and there are several things happening that my simple setup is not doing. Technically, in my code, I don't care where you click - just that you did. So I could bind to the mousedown and touchstart events simultaneously since I don't need the x/y coordinates. However, in other examples in my sandbox, I do need the x/y so I was hoping Touch Punch would be a simple all-in-one solution.

I will probably need to spend a little more time digging to find the solution to my mousedown problem. However, jQuery UI works quite well so if you're looking for something to get your UI interactions working on a tablet, Touch Punch will do the trick.