Safari iPad: Prevent Double Touch Zoom

I am building a site on Safari for iPad. I need to prevent double tap increase, but I have two problems:

  • double-clicking does not generate any events, so I cannot use "event.preventDefault ();"
  • I need to do this only under certain conditions, so I can not use the tag " <meta name = "viewport" content = "user-scalable = no"> " ... If I did this, users could never increase my page.

How can I fix these problems?

+11
safari ipad zoom
Jun 23 '10 at 17:07
source share
7 answers

Mobile Safari does not support the jdddblclick javascript event. It is interpreted by Safari as "zoom."

Raul Sanchez posted a potential solution: http://appcropolis.com/implementing-doubletap-on-iphones-and-ipads/

+7
Jun 16 '11 at 15:38
source share

Here's the jQuery plugin that I wrote for the same purpose - selectively disabling double-touch scaling on given page elements (in my case, navigation buttons for turning pages). I want to respond to every click (including double-tap) as a normal click event, without iOS "touch magic."

To use it, just run something like $('.prev,.next').nodoubletapzoom(); on the items you need. ( Edit: now also ignores kicks)

 // jQuery no-double-tap-zoom plugin // Triple-licensed: Public Domain, MIT and WTFPL license - share and enjoy! (function($) { var IS_IOS = /iphone|ipad/i.test(navigator.userAgent); $.fn.nodoubletapzoom = function() { if (IS_IOS) $(this).bind('touchstart', function preventZoom(e) { var t2 = e.timeStamp , t1 = $(this).data('lastTouch') || t2 , dt = t2 - t1 , fingers = e.originalEvent.touches.length; $(this).data('lastTouch', t2); if (!dt || dt > 500 || fingers > 1) return; // not double-tap e.preventDefault(); // double tap - prevent the zoom // also synthesize click events we just swallowed up $(this).trigger('click').trigger('click'); }); }; })(jQuery); 
+7
Mar 15 2018-12-15T00:
source share

try this modified code. It should work for both Android and iOS devices.

 (function($) { $.fn.nodoubletapzoom = function() { $(this).bind('touchstart', function preventZoom(e){ var t2 = e.timeStamp; var t1 = $(this).data('lastTouch') || t2; var dt = t2 - t1; var fingers = e.originalEvent.touches.length; $(this).data('lastTouch', t2); if (!dt || dt > 500 || fingers > 1){ return; // not double-tap } e.preventDefault(); // double tap - prevent the zoom // also synthesize click events we just swallowed up $(e.target).trigger('click'); }); }; })(jQuery); 

Then apply nodoubletapzoom () to the body tag

 $("body").nodoubletapzoom(); 
+6
Jan 23 '14 at 7:15
source share

I changed @ecmanaut javascript solution to do two things.

  • I use modernizr, so it will put the .touch css class in the html node, so I can detect touch screens instead of using user agent detection. Perhaps there is a modern-less approach, but I don't know that.
  • I separate each "click" so that they happen separately, if you click once, it will click once, if you quickly press the button / trigger, it will count several times.
  • some minor changes to the formatting of the code, I prefer each var to be defined separately, etc., it’s more like me than anything else, I suppose you could just return it, nothing bad will happen.

I believe that these modifications do it better, because you can increase the counter 1,2,3,4 instead of 2,4,6,8

here is the modified code:

 // jQuery no-double-tap-zoom plugin // Triple-licensed: Public Domain, MIT and WTFPL license - share and enjoy! // // chris.thomas@antimatter-studios.com: I modified this to // use modernizr and the html.touch detection and also to stop counting two // clicks at once, but count each click separately. (function($) { $.fn.nodoubletapzoom = function() { if($("html.touch").length == 0) return; $(this).bind('touchstart', function preventZoom(e){ var t2 = e.timeStamp; var t1 = $(this).data('lastTouch') || t2; var dt = t2 - t1; var fingers = e.originalEvent.touches.length; $(this).data('lastTouch', t2); if (!dt || dt > 500 || fingers > 1){ return; // not double-tap } e.preventDefault(); // double tap - prevent the zoom // also synthesize click events we just swallowed up $(this).trigger('click'); }); }; })(jQuery); 

Apply nodoubletapzoom () to the body tag, like this

 $("body").nodoubletapzoom(); 

your html construct should be something like this

 <body> <div class="content">...your content and everything in your page</div> </body> 

Then in your javascript attach the click handlers as follows

 $(".content") .on(".mydomelement","click",function(){...}) .on("button","click",function(){...}) .on("input","keyup blur",function(){...}); // etc etc etc, add ALL your handlers in this way 

you can use any jquery event handler and any dom node. now you don’t have to do anything, you have to attach all your event handlers this way, I haven’t tried it differently, but this method works absolutely solidly, you can literally break the screen 10 times per second and it does not scale and does not register clicks (obviously , not 10 per second, ipad is not so fast, I mean, you can’t activate scaling)

I think this works because you attach the nozoom handler to the body and then bind all the event handlers to the ".content" node, but delegate the specific node, so jquery catches all the handlers in the last step before the event will bubble up to the body tag.

The main advantage of this solution is that you need to assign a nodoubletapzoom () handler to the body, you do it only once, and not once for each element, so it takes much less effort, effort and thinking to get everything done.

this has the added benefit that if you add content using AJAX, they will automatically have ready and pending handlers, I suppose if you want DIDNT this, then this method will not work for you, and you will have to configure it more .

I checked that this code works on ipad, it is actually beautiful, well made for @ecmanaut for the main solution!

** Changed on Saturday May 26th because I found what seems like the perfect solution with absolutely minimal effort.

+5
May 18 '12 at 9:33 a.m.
source share

All the solutions that I have seen (on this page, as well as elsewhere) have a side effect that they prevent from quick repeat clicks. Allows you to use one click for 500 ms or similar. In some cases, this may be good, but not for example. if you have an arrow or arrow buttons that allow you to quickly move from subject to subject.

The simplest solution:

 $('#nozoom').on('touchstart', function(e) { fn_start(e); e.preventDefault(); }); 

This calls fn_start() (the actual callback function) every time you start a touch, but prevents default scaling, etc.

A working comparative example is given here: http://jsbin.com/meluyevisi/1/ . The green box prevents, resolves the red box.

+2
Jun 09 '15 at 23:32
source share

just setting the viewport may not always be sufficient - in some cases, you may also need to call event.preventDefault (); on the touchstart handler.

+1
Mar 30 '12 at 19:12
source share

The accepted "double click" answer is a little "bloated" for me and using a timestamp ..... why? Take a look at this simple implementation without over-inflating.

 function simulateDblClickTouchEvent(oo) { var $oo = !oo?{}:$(oo); if( !$oo[0] ) { return false; } $oo.bind('touchend', function(e) { var ot = this, ev = e.originalEvent; if( ev && typeof ev.touches == 'object' && ev.touches.length > 1 ) { return; } ot.__taps = (!ot.__taps)?1:++ot.__taps; if( !ot.__tabstm ) // don't start it twice { ot.__tabstm = setTimeout( function() { if( ot.__taps >= 2 ) { ot.__taps = 0; $(ot).trigger('dblclick'); } ot.__tabstm = 0; ot.__taps = 0; },800); } }); return true; }; 

Using:

 simulateDblClickTouchEvent($('#example')); or simulateDblClickTouchEvent($('.example')); 
Function

returns true or false when the event is bound or not.

To prevent scaling and scrolling, follow these steps:

 function disableTouchScroll() { try { document.addEventListener('touchmove', function(e) { e.preventDefault(); }, true ); $j('body')[0].addEventListener('touchmove', function(e) { e.preventDefault(); }, true ); } catch(ee) { return false; } return true; } 

Also with CSS it's easy to avoid scaling:

 body * { -webkit-user-select:none; } 
  • = inefficient, but try, it works great.

Hurrah!

0
Sep 27 '12 at 1:40
source share



All Articles