jQuery (Swipe vs. Touch) pageX and pageY keep returning 0

DA. picture DA. · Aug 18, 2011 · Viewed 32.1k times · Source

I'm playing with touchstart and touchend events on my iPhone. I built a sample page that has div that if you touch it and scroll the page, it should return the y coordinates of the start and end positions.

link: http://jsbin.com/ibemom/2

the jQuery:

var touchStartPos;

$('.theDiv')
  .bind('touchstart', function(e){
    touchStartPos = e.pageY;
  })
  .bind('touchend', function(e){
    alert(touchStartPos + ' | ' + e.pageY)
  })   

When I load that page on my iPhone, however, the alert keeps reporting both values as zero. Anyone see anything wrong with what I have?

UPDATE:

I stumbled across this bit of code in the jQuery Mobile project: https://github.com/jquery/jquery-mobile/issues/734

A comment it from it stuck out:

 // (in iOS event.pageX and event.pageY are always 0 )

It doesn't say why that's the case, but at least I found someone else that sees the same thing. Will dig through the sample code on that page to see if the solution is there.

UPDATE II:

Well, after looking through the sample code in the link above, it looks like this will return an actual value:

e.originalEvent.touches[0].pageY

The catch is, I now realize that's not quite I need. It's returning the Y offset of the area I touched within the object I attached the event to IN RELATION TO THE HTML DOCUMENT...rather than the browser window.

My goal is to figure out where on the screen the touch started, and where it ended...and then compare the values. If they are quite a bit different, then we assue a swipe was performed...rather than a touch.

UPDATE III:

I'm also finding references to these examples:

e.originalEvent.touches[0].pageX

event.targetTouches[0].pageY

Though I can't seem to get those to work either. Both return undefined errors.

UPDATE IV:

It looks like one solution is to track offset() on the document itself. I can apply a touchend event to the document, and then check it's offset.

The problem with this is that my touchend event will first trigger on the element on my page and THEN it'll fire it on the document (bubbling). So I can't actually determine if it was a touch or swipe BEFORE I need to figure out what to do on the objects touchend event.

Still pondering this one...

Answer

andlrc picture andlrc · Aug 24, 2011

Ok the quick answer is you can't detect a touch when the finger leaves the screen (touchend).

My first example proves that: http://jsfiddle.net/Y4fHD/

Now to the workaround. Or call it what you want. Maybe it makes sense not detection on the touchend event because the the touch has ended.

Bind the handler on the touchmove event: http://jsfiddle.net/Y4fHD/1/

var endCoords = {};
$(document.body).bind("touchmove", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
});

And then use the variable endCoords to determinate the last touch

$(document.body).bind("touchend", function(event) {
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY);
});

Ok try to just tap your device! Then the error still will ocure: Why? Because you havn't moved your touch.

If we all ready in the touchstart defines the endCoords variable we are there: http://jsfiddle.net/Y4fHD/2/

var endCoords = {};
$(document.body).bind("touchstart touchmove", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
});

And then use the variable endCoords to determinate the last touch

$(document.body).bind("touchend", function(event) {
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY);
});

Now try to tap your device!

Some final notes will be: Make to variables: startCoords and endCoords then use these in the touchend event: http://jsfiddle.net/Y4fHD/3/

var startCoords = {}, endCoords = {};
$(document.body).bind("touchstart", function(event) {
    startCoords = endCoords = event.originalEvent.targetTouches[0];
});
$(document.body).bind("touchmove", function(event) {
    endCoords = event.originalEvent.targetTouches[0];
});
$(document.body).bind("touchend", function(event) {
    $('p').text("Your touch on the axis: " + Math.abs(startCoords.pageX-endCoords.pageX) + "x, " + Math.abs(startCoords.pageY-endCoords.pageY) + "y");
});

Note:
None of the above examples are tested, hopes it works!
Math.abs gives me the absolute value of a number eg: -5 becomes 5