Подтвердить что ты не робот

Сенсорное устройство, обработчик событий Single и Double Tap jQuery/Javascript?

Фон:

Мой сайт находится в magento с открытым исходным кодом для электронной коммерции, а в верхней части (заголовке) есть значок корзины покупок. В режиме dekstop, когда пользователь наводит курсор мыши на этот значок, он отображает содержимое (элементы) в корзине покупок. Но при нажатии этого значка пользователь переходит на страницу корзины покупок.

Я хочу:

Я хочу иметь возможность только для сенсорных устройств, когда пользователь один раз нажимает на значок, он должен отображать только контент, но при двойном нажатии на значок он должен отображать их на странице корзины.

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 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, также не делает ничего с двойным нажатием. Кстати, я тестирую его на галактике samsung, не уверен, что это правильное устройство для тестирования, и с помощью JQUERY PLUGIN (не jQuery mobile).

4b9b3361

Ответ 1

Если вы хотите настроить таргетинг на мобильный, вы можете использовать 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
});

Это также работает и для событий мыши, что может быть не так, как вы хотите. И это немного переборщит, если это только для этого. Но если вы планируете делать больше касания, я бы рекомендовал использовать эту библиотеку.

Ответ 2

Это окончательный рабочий код, который сделал магию для меня:) Я только что скопировал и вставлял весь код здесь, но можно использовать его в соответствии с собственными потребностями.

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

Ответ 3

Это мой хак. Это небольшой блок кода, и он должен хорошо работать на мобильных телефонах. Он устанавливает таймер, когда вы сначала нажимаете на что-то, а затем проверяет, находится ли второй ответ в диапазоне времени (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; }
    });

Ответ 4

Этого также можно добиться, используя vanilla 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>