Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safari iPad 1: how to disable zoom/centering on double-tap, but keep pinch zoom

I wonder if its possible to prevent double-tap-to-zoom and double-tap-to-center on a specific HTML element in Safari iOS (iPad 1) ?

Because my small HTML5 game forces users to make fast clicks (or taps), which are interpreted as double clicks, and when it happens - the page changes zoom and centers itself.

Detecting double clicks (like in this answer - Safari iPad : prevent zoom on double-tap) smells bad..

Wrong answer #1: <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> - does not suit my purposes, because it will block any zoom.

Wrong answer #2: maybe would .preventDefault() on click event alone be enough for that ? - Does not have any effect.

like image 370
c69 Avatar asked Nov 09 '11 21:11

c69


2 Answers

There's no other way than catching the events you want to prevent, and call preventDefault() on them, as you had already more or less figured out.

Indeed, some particular CSS properties / values may change the global site behavior (fixed width or fixed, for example), but you're not safe from changes to the OS (see fixedhandling change in iOS5), nor do these changes necessarily prevent all behavior (pinch might be off, but not double-tapping).

So, the best way to disable default behavior only for double-tapping is to take advantage of the count of touches iOS provides: if we have only one contact, then we're tapping. Two, this means we're pinching.

The following setup code provides that functionality:

var elm = document.body; // or some selection of the element you want to disable

var catcher = function(evt) {
    if (evt.touches.length < 2)
        evt.preventDefault();
};

elm.addEventListener('touchstart', catcher, true);

Demo on jsFiddle.

Note: the third parameter (true) to addEventListener means that we want to capture events, that is catch them all, even for our descendant children.

like image 105
MattiSG Avatar answered Sep 21 '22 13:09

MattiSG


I am preventing doubletaps like this:

var doubleTouchStartTimestamp = 0;
$(document).bind("touchstart", function (event) {
    var now = +(new Date());
    if (doubleTouchStartTimestamp + 500 > now) {
        event.preventDefault();
    }
    doubleTouchStartTimestamp = now;
});

The elegance lies within the fact, that no timeouts are needed. I only update a timestamp. It only gets compared on the next touchstart. Works for me on iOS 6.

Doubletaps further down the dom are not affected.

The same works without jQuery, as well:

var doubleTouchStartTimestamp = 0;
document.addEventListener("touchstart", function (event) {
    var now = +(new Date());
    if (doubleTouchStartTimestamp + 500 > now) {
        event.preventDefault();
    }
    doubleTouchStartTimestamp = now;
});
like image 28
amenthes Avatar answered Sep 20 '22 13:09

amenthes