appcropolois
  •  Templates
  • Builder
    •  Product Tour
    •  Sign up
    •  Dashboard
  •  Learn
  •  Discover
  •  Upgrade
  •  Sign in
  •  My Profile
    • View Orders
    • Edit Profile
    • Sign Out
  •  Cart
    ➜ 
  1. Home
  2. Learn
  3. Implementing doubletap on ...
Share

Implementing doubletap on iPhones and iPads

When the iPhone first arrived, one of the coolest things that Apple did was to have Mobile Safari display a miniature view of an entire web site, allowing users to double tap and zoom into the portions of the site that they wanted to see. This clever solution to navigate large pages in a small screen came with a price.

If your site takes advantage of the double click functionality, when it is displayed on Mobile Safari you loose that capability, your clicks become touch events and the double click (double-tap) now belongs to the browser.

If you want to get the double click functionality back, the first thing you should know is that you can prevent the default browser behavior that takes your double click away. Once you have done that, you can easily re-implement the double click/touch behavior you lost. In your HTML page start with adding a meta tag to indicate the users are not allow to scale the page:

1
2
3
4
5
var isiOS = false;
var agent = navigator.userAgent.toLowerCase();
if(agent.indexOf('iphone') >= 0 || agent.indexOf('ipad') >= 0){
       isiOS = true;
}
var isiOS = false;
var agent = navigator.userAgent.toLowerCase();
if(agent.indexOf('iphone') >= 0 || agent.indexOf('ipad') >= 0){
       isiOS = true;
}

Now you should be able to write code for iOS devices and for regular browsers

1
2
3
4
5
if(isiOS){
       // implement double-tap
}else{
       // implement double click
}
if(isiOS){
       // implement double-tap
}else{
       // implement double click
}

Adding double double tap is bit trickier. We need to measure the time between two consecutive touch events. If a user taps twice within 500 milliseconds (half a second), I can assume that the user meant double tap. Now keep in mind that two click/touch events are also fired. The trick is that we have to wait before we can fire a click/touch event and call our doubletap handler only if users click/tap very quickly.

Let’s go one step at the time. I will use jQuery to bind a touchend event to an element selector:

1
2
3
4
5
6
7
8
9
10
11
$(selector).bind('touchend', function(event){
       var now = new Date().getTime();
       var lastTouch = $(this).data('lastTouch') || now + 1 /** the first time this will make delta a negative number */;
       var delta = now - lastTouch;
       if(delta<500 && delta>0){
               // the second touchend event happened within half a second. Here is where we invoke the double tap code
       }else{
               // A click/touch action could be invoked here but wee need to wait half a second before doing so.
       }
       $(this).data('lastTouch', now);
}
$(selector).bind('touchend', function(event){
       var now = new Date().getTime();
       var lastTouch = $(this).data('lastTouch') || now + 1 /** the first time this will make delta a negative number */;
       var delta = now - lastTouch;
       if(delta<500 && delta>0){
               // the second touchend event happened within half a second. Here is where we invoke the double tap code
       }else{
               // A click/touch action could be invoked here but wee need to wait half a second before doing so.
       }
       $(this).data('lastTouch', now);
}

What I have done so far, is to determine the difference between the last touch and the current touch events. The first time that this code runs, both the current touch time and the last touch time are the same, so the delta is zero. At the end of the function I want to make sure that I update the value of the last touch to be equal to the current touch.

Now that we know where to write the double tap code, let’s figure out how to add some logic to help us know when to invoke the double tap code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var action;
$(selector).bind('touchend', function(event){
       var now = new Date().getTime();
       var lastTouch = $(this).data('lastTouch') || now + 1 /** the first time this will make delta a negative number */;
       var delta = now - lastTouch;
       clearTimeout(action);
       if(delta<500 && delta>0){
               // the second touchend event happened within half a second. Here is where we invoke the double tap code
       }else{
               $(this).data('lastTouch', now);
               action = setTimeout(function(e){
                       // If this runs you can invoke your 'click/touchend' code
                       clearTimeout(action);   // clear the timeout
               }, 500, [event]);
       }
       $(this).data('lastTouch', now);
}
var action;
$(selector).bind('touchend', function(event){
       var now = new Date().getTime();
       var lastTouch = $(this).data('lastTouch') || now + 1 /** the first time this will make delta a negative number */;
       var delta = now - lastTouch;
       clearTimeout(action);
       if(delta<500 && delta>0){
               // the second touchend event happened within half a second. Here is where we invoke the double tap code
       }else{
               $(this).data('lastTouch', now);
               action = setTimeout(function(e){
                       // If this runs you can invoke your 'click/touchend' code
                       clearTimeout(action);   // clear the timeout
               }, 500, [event]);
       }
       $(this).data('lastTouch', now);
}

To determine how long we have to wait before we can tell that the user only tapped once, I added a timeout call declared outside of the touchend event handler. Every time that the touchend event is fired, I clear the action timeout which prevents the click/touch from happening. If the value of delta is less than 500 milliseconds (half a second) we can definitely invoke the doubletap code, but if delta is higher that 500 milliseconds the timeout is defined again and our click/touch code will be invoked in half a second.

 

 

Let’s put everything together and write it as a jQuery extension:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*!
 * jQuery Double Tap Plugin.
 *
 * Copyright (c) 2010 Raul Sanchez (http://www.appcropolis.com)
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
 
(function($){
    // Determine if we on iPhone or iPad
    var isiOS = false;
    var agent = navigator.userAgent.toLowerCase();
    if(agent.indexOf('iphone') >= 0 || agent.indexOf('ipad') >= 0){
           isiOS = true;
    }
 
    $.fn.doubletap = function(onDoubleTapCallback, onTapCallback, delay){
        var eventName, action;
        delay = delay == null? 500 : delay;
        eventName = isiOS == true? 'touchend' : 'click';
 
        $(this).bind(eventName, function(event){
            var now = new Date().getTime();
            var lastTouch = $(this).data('lastTouch') || now + 1 /** the first time this will make delta a negative number */;
            var delta = now - lastTouch;
            clearTimeout(action);
            if(delta<500 && delta>0){
                if(onDoubleTapCallback != null && typeof onDoubleTapCallback == 'function'){
                    onDoubleTapCallback(event);
                }
            }else{
                $(this).data('lastTouch', now);
                action = setTimeout(function(evt){
                    if(onTapCallback != null && typeof onTapCallback == 'function'){
                        onTapCallback(evt);
                    }
                    clearTimeout(action);   // clear the timeout
                }, delay, [event]);
            }
            $(this).data('lastTouch', now);
        });
    };
})(jQuery);
/*!
 * jQuery Double Tap Plugin.
 *
 * Copyright (c) 2010 Raul Sanchez (http://www.appcropolis.com)
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */

(function($){
	// Determine if we on iPhone or iPad
	var isiOS = false;
	var agent = navigator.userAgent.toLowerCase();
	if(agent.indexOf('iphone') >= 0 || agent.indexOf('ipad') >= 0){
		   isiOS = true;
	}

	$.fn.doubletap = function(onDoubleTapCallback, onTapCallback, delay){
		var eventName, action;
		delay = delay == null? 500 : delay;
		eventName = isiOS == true? 'touchend' : 'click';

		$(this).bind(eventName, function(event){
			var now = new Date().getTime();
			var lastTouch = $(this).data('lastTouch') || now + 1 /** the first time this will make delta a negative number */;
			var delta = now - lastTouch;
			clearTimeout(action);
			if(delta<500 && delta>0){
				if(onDoubleTapCallback != null && typeof onDoubleTapCallback == 'function'){
					onDoubleTapCallback(event);
				}
			}else{
				$(this).data('lastTouch', now);
				action = setTimeout(function(evt){
					if(onTapCallback != null && typeof onTapCallback == 'function'){
						onTapCallback(evt);
					}
					clearTimeout(action);   // clear the timeout
				}, delay, [event]);
			}
			$(this).data('lastTouch', now);
		});
	};
})(jQuery);

Usage:

1
2
3
4
5
6
7
8
9
10
11
12
$(selector).doubletap(
    /** doubletap-dblclick callback */
    function(event){
        alert('double-tap');
    },
    /** touch-click callback (touch) */
    function(event){
        alert('single-tap');
    },
    /** doubletap-dblclick delay (default is 500 ms) */
    400
);
$(selector).doubletap(
    /** doubletap-dblclick callback */
    function(event){
        alert('double-tap');
    },
    /** touch-click callback (touch) */
    function(event){
        alert('single-tap');
    },
    /** doubletap-dblclick delay (default is 500 ms) */
    400
);

 

This plugin will work on Desktop Browser as well as Mobile Safari. Click HERE to download the source code and basic examples.

By: Raul Sanchez
Category: How-To
Posted on: Tuesday, January 24, 2012

Sign in to post your comment


Not registered? Create an Account.

Lost your password? Click here to recover.

9 comment


anonymous
anonymous Wednesday 5th, September 2012 - 04:13:55 PM

The major problem of this solution is the event used on iDevice. With touchend, you can't have the position where you doubletaped. However, it seems that the "tap" event featuring in jQuery Mobile works great. Nevertheless, this article is pretty good and i must thank you for helping me :) !

Erwin H
Erwin H Thursday 27th, September 2012 - 03:54:55 PM

You can achieve the same functionality with this 'simple' function:

function simulateDblClickTouchEvent(oo) {
	var $oo = !oo?{}:$(oo);
	if( !$oo[0] ){ return false; }
	$oo[0].__taps = 0;
	$oo.bind('touchend', function(e) {
		var ot = this;
		++ot.__taps;
		$d( 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;
}
Example: simulateDblClickTouchEvent($('#example')); returns true or false when attached or not attached.

Jared Verdi
Jared Verdi Monday 11th, February 2013 - 06:38:49 PM

Nice approach. You may also want to consider taking scroll position into account, to prevent issues when quickly scrolling and you happen to tap on the same object twice: Inserting at line 28: var scrollTop = $(window).scrollTop(); var lastScrollTop = $(this).data('lastScrollTop') || 0; var scrollDelta = scrollTop - lastScrollTop; And in the line 29 conditional: if (delta0 && scrollDelta<25) And finally recording scrollTop after line 42: $(this).data('lastScrollTop', scrollTop);

sanraul
sanraul Tuesday 12th, February 2013 - 08:09:38 PM

Thanks for the suggestion!

David
David Wednesday 29th, May 2013 - 08:05:15 PM

Hi, Is there a working demo I can view? Could I add this to a button so it will do one thing when single clicked, and another when double clicked? Thanks

Brendan
Brendan Sunday 12th, July 2015 - 06:37:33 AM

How do you execute the Java code? What do you do with it

javascript - Doble toque en mobile safari
javascript - Doble toque en mobile safari Tuesday 15th, January 2019 - 07:53:03 PM

[…] Es allí una manera de obligar a un evento de doble punteo (en una sola línea de código) para móviles de safari? O bien, la alternativa es implementar interceptar a dos de un solo toque eventos que ocurrieron en algunos cortos de tiempo determinado (ejemplo: http://appcropolis.com/blog/implementing-doubletap-on-iphones-and-ipads/)? […]

javascript - Double tap sur le navigateur safari mobile
javascript - Double tap sur le navigateur safari mobile Monday 25th, February 2019 - 04:40:53 PM

[…] Est-il un moyen de se lier à une double pression de l'événement (en une seule ligne de code) pour le navigateur safari mobile? Ou, l'alternative est de mettre en œuvre l'interception de deux-appuyez sur les événements qui s'est passé dans une certaine période (exemple: http://appcropolis.com/blog/implementing-doubletap-on-iphones-and-ipads/)? […]

How can I prevent default double-tap behavior (zooming, panning) in Mobile Safari on iOS4? – Config9.com
How can I prevent default double-tap behavior (zooming, panning) in Mobile Safari on iOS4? – Config9.com Sunday 9th, February 2020 - 07:59:23 AM

[…] gets activated and subsequently screws up the page layout. The behavior is quite buggy. Perhaps using Javascript to manage tap events can help to prevent this from happening while we wait for Apple to fix this. […]

Building Apps?

Create, customize, and publish mobile web applications using the Appcropolis Mobile Builder.

Get Started
Browse Categories
  • Books (0)
  • CSS3 (2)
  • Design (0)
  • Frameworks (10)
  • How-To (6)
  • HTML5 (2)
  • jQuery Mobile (7)
  • Miscelaneous (1862)
  • Mobile Builder (1)
  • News (9)
  • Opinion (1)
  • User Experience (0)
  • Web Technology (11)
  • Webclips (4)

Ready-to-use Templates

Check out Appcropolis Mobile Templates

We offer 1,000's of mobile templates that are fully designed, coded, and ready to use. Learn more.

Download Free Templates

Contact Us

Your feedback means the world to us.
Contact us if you have any questions or
any feature requests:

Saint Louis, MO 63101
911 Washington Ave
Email: info@appcropolis.com

Appcropolis

  •   About Us
  •   Blog
  •   Discover
  •   Templates
  •   Contact Us

Get Free Templates

Subscribe to our newsletter to receive
notification about new templates, prodcut updates,
and technical articles.


© 2025 Appcropolis, LLC · All Rights Reserved
Sitemap  ·  Terms Of Service  ·  Privacy