Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: Any workarounds for getting Chrome for Android to fire off touchmove and touchend event listeners other than using event.preventDefault()?

When using event listeners with the touchmove and touchend events, I can't get Chrome for Android to acknowledge those events unless I first use event.preventDefault(); earlier in the code. If I'm not wanting to block the default scroll functionality, is there any other workaround I can use to get Chrome for Android to acknowledge these events?

Sample code:

$(document).ready(function () {
// Bind touch event listeners.
var elem = $('html').get(0);
elem.addEventListener('touchstart', function (e) { console.info('"touchstart" detected. Coordinates - ' + getCoord(e)); });
elem.addEventListener('touchmove', function (e) { console.info('"touchmove" detected. Coordinates - ' + getCoord(e)); });
elem.addEventListener('touchend', function (e) { console.info('"touchend" detected. Coordinates - ' + getCoord(e)); });

function getCoord(e) {
var touch = false;
if (e.touches.length > 0) {
touch = e.touches[0];
} else {
touch = e.changedTouches[0];
}
if (touch) {
return 'x: ' + touch.pageX + ', y: ' + touch.pageY;
}
}

Example fiddle here: http://jsfiddle.net/jQ2VS/1/

like image 442
Kyle Weems Avatar asked Dec 05 '13 23:12

Kyle Weems


2 Answers

Google Chrome will fire a touchcancel event about 200 milliseconds after touchstart if it thinks the user is panning/scrolling and you do not call event.preventDefault().

Assuming that you want to intercept horizontal touch events and let vertical touch events cause panning/scrolling, a workaround would be:

  1. On touchstart, store the coordinates in a variable, and set iteration to 0.
  2. For each touchmove event, set iteration to iteration+1.
  3. When iteration is equal to 4 (just a "magic number" I found to be reliable on my set-up), calculate the total touch offset deltas for x- and y- axes. EDIT: on mobile devices you'll only receive one touchmove without event.preventDefault()
  4. If x-axis offset > y-axis offset * 3 then fire event.preventDefault(). (This ensures the the gesture is pretty much horizontal)

The down-side for this is that user can only either swipe left/right or scroll up/down.

like image 97
Henry Avatar answered Nov 15 '22 17:11

Henry


Finally I found the solution (pure js) even in case you might want use it for swipe:

var swipe = function() {

    var touchX, touchY, movX, movY, go;

    function prevent(e){
        e.preventDefault();
    }

    function start(e) {
        go = false;
        document.addEventListener("touchmove", prevent, false);
        touchX = e.touches[0].pageX;
        touchY = e.touches[0].pageY;
    }

    function move(e) {
        movX = e.touches[0].pageX - touchX;
        movY = e.touches[0].pageY - touchY;
        if(!go) {
            (Math.abs(movY) < Math.abs(movX)) ? go = true : stop(e);
        } else {
            /* *************** */
            // cast your spell
            /* *************** */
        }
    }

    function stop(e) {
        document.removeEventListener("touchmove", prevent, false);
    }

    document.addEventListener("touchstart", start, true);
    document.addEventListener("touchmove", move, true);
    document.addEventListener("touchend", stop, true);
    document.addEventListener("touchleave", stop, true);
    document.addEventListener("touchcancel", stop, true);

}

Hope this help.

like image 40
shaithana Avatar answered Nov 15 '22 18:11

shaithana