Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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).

like image 812
atif Avatar asked Jun 05 '14 10:06

atif


2 Answers

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.

like image 123
mfirdaus Avatar answered Sep 24 '22 05:09

mfirdaus


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);
                 });
            }
        }
like image 38
atif Avatar answered Sep 24 '22 05:09

atif