2012. 12. 5. 12:07

Basic jQuery touchmove Event Setup

I was recently tasked with replicating a “mousemove()” event on the iPad using the “touchmove()” event. I ran into a few snags and felt it was worthy enough to document my findings.

Here is the basic setup for using the “touchmove()” event:

$('#someElm').bind('touchmove',function(e){
      e.preventDefault();
      //CODE GOES HERE
});

Nothing really different about the setup behind the “touchmove()” event and any other native jQuery event. The only difference is that when using a “touchmove()”, you must always start your event handler with a event preventDefault();.

Next, its important to point out that if our script is ran as is, you will run into some issues with events being sent to your touch handlers, and none of them having whats called “e.touches” or “e.changedTouches” properties.

“After deep debugging, I eventually discovered that the source of this problem was the fixmethod in jquery’s event code. The fix method tries to copy the event object in order to fix various cross browser issues. Unfortunately, it seems that mobile safari does not allow thee.touches and e.changedTouches properties on event objects to be copied to another object. This is weird and annoying. Luckily you can get around this issue by usinge.originalEvent.” -  http://www.the-xavi.com/articles/trouble-with-touch-events-jquery

So to fix our issue we can simply create a new “touch” variable, then condition both “.originalEvent” and “.changedTouches” to this variable, like so:

$('#someElm').bind('touchmove',function(e){
      e.preventDefault();
      var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
      //CODE GOES HERE
      console.log(touch.pageY+' '+touch.pageX);
});

I included a little console.log() demo showing how you could test your “touchmove()” event coordinates.

The Problem:

There is one slight problem (depending on your functionality needs) when using this “touchmove()”. The event continues to fire even when your “touch” has moved out side the element.

So in other words, it seems that once the event has started, it’s no longer confined to the element its being assigned to.

The Fix:

There is no real solid fix for this issue yet, however you can band-aid the issue with a little math.

Basically, by trimming the elements top and left offset from both of the touchmove’s x and y event coordinates. You can then condition these trimmed values against both the elements width and height (respectively of course).

Completed touchmove() Event with jQuery with Confined Fix:

$('#someElm').bind('touchmove',function(e){
      e.preventDefault();
      var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
      var elm = $(this).offset();
      var x = touch.pageX - elm.left;
      var y = touch.pageY - elm.top;
      if(x < $(this).width() && x > 0){
	      if(y < $(this).height() && y > 0){
                  //CODE GOES HERE
                  console.log(touch.pageY+' '+touch.pageX);
	      }
      }
});

Vole! No matter where the location of the element to the page, or the width and height of the element, the event will only be fired in side of the element.

And that’s your basic setup for a “touchmove()” event using jQuery alone.

Have fun.