触摸设备,单击和双击事件处理程序jQuery/Javascript?

20

背景:

我的网站使用magento开源电子商务解决方案,在顶部(头部)有一个购物车图标。在桌面上,当用户将鼠标悬停在该图标上时,它会显示购物车中的内容(物品)。但是单击该图标,它会将用户带到购物车页面。

我想要:

我想要只针对触摸设备具有能力,即当用户单击该图标时,它应仅显示内容,但当双击该图标时,它应将其带到购物车页面。

HTML代码:

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

我已经尝试过的内容:

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');
            });
        }
    });

这段代码可以阻止单击事件的默认行为,但是不会显示内容div,并且在双击时也没有任何作用。顺便说一下,我正在三星Galaxy上测试它,不确定这是否是一个正确的测试设备,并且使用的是JQUERY插件(不是jquery mobile)。


为了阻止默认行为,您需要在单击事件代码结尾处返回false;。否则,浏览器将执行您的代码,然后执行其默认操作。 - Chris S.
4个回答

50

如果您想针对移动设备进行操作,可以使用touchstart,它是mousedown的触摸等效事件。尽管支持触摸的桌面浏览器也可以使用此功能,因此,如果这不适合您,则可能仍需要进行用户代理检测。据我所知,没有内置的“双击”事件可供我们挂钩,但我们可以手动检查单击或双击。代码看起来会像这样:

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()
});

演示

这应该可以在任何触摸屏浏览器上使用。

另一个选择,虽然对于仅此而言有点复杂,是使用Hammer.js。 这是一个非常好的用于处理触摸事件的库。 它也将鼠标和触摸事件聚合到一种事件类型中。 例如,对于轻拍和双击,它基本上是

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

这对于鼠标事件也同样适用,这可能不是你想要的。如果仅仅是为此而使用它有些过度了。但如果你计划进行更多触摸相关的事情,我建议使用这个库。


我的平板电脑没有响应“touchstart”事件,但是当我使用点击事件时,它可以正常工作。 - MTM
为什么你将tapped设置为null而不是false?只是少了一个字母吗?起初我没有意识到! null == true,因为null!= false... - Peter Valadez
你应该使用以下条件来包装它,以防止捏合缩放被识别为双击,这似乎是发生在我身上的情况。如果(event.targetTouches.length === 1){等等} - Julian Dormon
这个代码可以运行,但只有在使用e.preventDefault()的情况下。我该如何让它在没有这一行的情况下也能正常工作?(在单击时我确实希望保留默认行为)。 - Heribert

6
这是最终能为我实现魔法的工作代码 :) 我只是将所有代码复制并粘贴到这里,但人们可以根据自己的需求使用它。
   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);
                 });
            }
        }

5

这是我的黑科技。它是一个小的代码块,应该在移动设备上运行良好。当你第一次点击某个东西时,它会设置一个计时器,然后检查第二次点击是否在时间范围内(在这个例子中为600毫秒)。

    // 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; }
    });

不错!加上一些小改动会更好。 - Akash Gorai

0

这也可以使用原生JavaScript实现 =>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <button id="btn">click me</button>
    <script>
      let exit = false;

      document.getElementById('btn').addEventListener('click', async () => {
        let open = true;

        document.getElementById('btn').addEventListener('click', () => {
          if (open) {
            exit = true;
          }
        });

        function timeout(ms) {
          return new Promise(resolve => {
            setTimeout(resolve, ms);
          }).then(() => (open = false));
        }

        await timeout(1500);
        console.log(exit);
      });
    </script>
  </body>
</html>

根据退出变量值(即true或false),您可以定义进一步的操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接