Touch device, Single and Double Tap Events handler jQuery/Javascript?

53,962

Solution 1

If you want to target mobile then you can use touchstart which is the touch equivalent of mousedown. though touch capable desktop browsers can also use this so maybe you still need to do user-agent detection if that doesn't suit you. Last I checked, there wasn't any built in "double tap" event we can hook onto, but we can manually check for a tap or a double tap. The code would look something like

var tapped=false
$("#mini-cart .dropdown-toggle").on("touchstart",function(e){
    if(!tapped){ //if tap is not set, set up single tap
      tapped=setTimeout(function(){
          tapped=null
          //insert things you want to do when single tapped
      },300);   //wait 300ms then run single click code
    } else {    //tapped within 300ms of last tap. double tap
      clearTimeout(tapped); //stop single tap callback
      tapped=null
      //insert things you want to do when double tapped
    }
    e.preventDefault()
});

Demo

This should work on any touch enabled browser.

An alternative, though a bit heavy for just this, is to use Hammer.js. It's a really nice library for handling touch events. And it also aggregates mouse and touch events into one type of event. For example, for tap and double tap it'll essentially be

Hammer(el).on("tap", function() {
    //singletap stuff
});
Hammer(el).on("doubletap", function() {
    //doubletap stuff
});

This also works for mouse events too, which might not be what you want. And it is a bit overkill if it's just for this. But if you plan to do more touch related stuff, I would recommend using this library.

Solution 2

This is the final working code that did the magic for me :) I have just copied and paste all the code in here but one may use it in accordance to own needs.

   if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) {

            $('#dropdown_menu').css({ "right":'20%'});
            var action;
            $('#continue_shopping').show();
            $('#continue_shopping').bind('touchstart click', function(event){
                setTimeout(function(e){
                    $('#mini-cart').removeClass('open');

                    $('#dropdown_menu').hide();
                }, 1200, [event]);

            }); 

            $('#dropdown-toggle').bind('touchstart', function(event){
                var now = new Date().getTime();
                var lastTouch = $(this).data('lastTouch') || now + 1 ;
                var delta = now - lastTouch;
                clearTimeout(action);
                if(delta<500 && delta>0){
                    window.location='<?php echo $this->getUrl('checkout/cart');?>';
                }else{
                    //if(delta == -1){
                    $('#mini-cart').addClass('open');
                    $('#dropdown_menu').show();

                    $(this).data('lastTouch', now);
                    action = setTimeout(function(e){
                        clearTimeout(action);  
                    }, 500, [event]);
                }
                $(this).data('lastTouch', now);
             });

            if (typeof document.body.ontouchstart == "undefined") {
                $('#dropdown-toggle').bind('click', function(event){
                    var now = new Date().getTime();
                    var lastTouch = $(this).data('lastTouch') || now + 1 ;
                    var delta = now - lastTouch;
                    clearTimeout(action);
                    if(delta<600 && delta>0){
                        window.location='<?php echo $this->getUrl('checkout/cart');?>';
                    }else{
                        //if(delta == -1){
                        $('#mini-cart').addClass('open');
                        $('#dropdown_menu').show(); 

                        $(this).data('lastTouch', now);
                        action = setTimeout(function(e){
                            clearTimeout(action);  
                        }, 600, [event]);
                    }
                    $(this).data('lastTouch', now);
                 });
            }
        }

Solution 3

this is my hack. It's a small code block and it should work well on mobiles. It sets a timer when you first tap on something and then it checks if the second tap is in the time range (600ms in this example)

    // DOUBLE TAP
    var timer = 0;
    $(document).on("click" , "#target" , function() {
        if(timer == 0) {
            timer = 1;
            timer = setTimeout(function(){ timer = 0; }, 600);
        }
        else { alert("double tap"); timer = 0; }
    });
Share:
53,962

Related videos on Youtube

atif
Author by

atif

magento, wordpress, custom php/mysql, jquery/Ajax

Updated on July 09, 2022

Comments

  • atif
    atif almost 2 years

    Background:

    My site is in magento open source ecommerce solution, and in the top (header) it has a shopping cart icon. On dekstop, when user hovers mouse over that icon, it shows the content (items) in shopping cart. But on click of that icon, it takes the user to shopping cart page.

    I want:

    I want to have the ability, only for touch devices, that when a user single tap on icon, it should display the content only, but when double tap the icon, it should take them to the cart page.

    HTML CODE:

    <div id="mini-cart" class="dropdown is-not-empty">
    
        <!-- This below div is always visible and on tap of this or either of it's any elements, required behaviour is expected -->
        <div class="dropdown-toggle cover" title="View Bag"> 
            <div class="feature-icon-hover">
    
                <a href="example.com/checkout/cart/" title="Shopping Bag">
                    <span class="first close-to-text icon i-cart-wb force-no-bg-color">&nbsp;</span>
                    <div class="hide-below-960">My Bag</div>
                </a>
    
                <div class="label amount">
                    <a href="example.com/checkout/cart/" title="Shopping Bag">(1)</a>
                </div>
    
                <a class="summary" href="example.com/checkout/cart/" title="Shopping Bag">
                    <span class="subtotal">
                        <span class="price">$28</span>
                    </span>
                </a>
                <span class="caret">&nbsp;</span>
    
            </div> <!-- end: dropdown-toggle > div -->
        </div> <!-- end: dropdown-toggle -->
    
         <!-- This one is invisible by default, and needs to be shown on single tap -->
        <div class="dropdown-menu left-hand" style="display: none;">
              <!-- All THE CONTENT GOES HERE -->
        </div>
    </div>
    

    What I already tried:

    jQuery(function($){
            /* Code to detect the user agent, if mobile device then execute the code*/
            if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) {
    
                // on single touch
                $("#mini-cart .dropdown-toggle").on('click', 'a', function(e){
                    e.preventDefault();
                    $("#mini-cart .dropdown-menu").show();
                });
    
                // on double touch
                $("#mini-cart .feature-icon-hover").find('a').dblclick(function(e){
                    location.href = '/checkout/cart';
                    //alert('dblclick');
                });
            }
        });
    

    This code does prevent from default behaviour on single tap but does not show content div, also does not do anything on double tap. By the way, I am testing it on samsung galaxy, not sure whether it is a correct device for testing, and using JQUERY PLUGIN (not jquery mobile).

    • Chris S.
      Chris S. about 10 years
      In order to prevent the default action, you need to return false; at the end of the click event code. Otherwise, the browser executes your code, then it executes it's default actions.
  • MTM
    MTM about 10 years
    my tablet didn't followed 'touchstart', however, when I used click event, it worked.
  • Peter Valadez
    Peter Valadez over 7 years
    Why do you set tapped=null instead of tapped=false? One less letter? At first I didn't realize that !null == true since null != false...
  • Julian Dormon
    Julian Dormon over 6 years
    You should wrap this with the following condition to prevent pinch-zooming being recognized as a double-tap which seems to be happening to me. If(event.targetTouches.length === 1) { etc }
  • Heribert
    Heribert over 4 years
    This works, but only with the e.preventDefault(). How can I make it work without this line? (on single tap I do want the default behavior).
  • Akash Gorai
    Akash Gorai over 2 years
    Good one! Would work best with few add tweaks.