背景:
私のサイトはmagentoオープンソースeコマースソリューションにあり、上部(ヘッダー)にはショッピングカートアイコンがあります。 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'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"> </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"> </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を表示せず、ダブルタップでも何もしません。ちなみに、私はサムスンギャラクシーでテストしていますが、それがテスト用の正しいデバイスであるかどうかはわかりませんが、JQUERY PLUGIN(jquery mobileではありません)を使用しています。
モバイルをターゲットにしたい場合は、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 を使用します。タッチイベントを処理するための本当に素晴らしいライブラリです。また、マウスイベントとタッチイベントを1種類のイベントに集約します。たとえば、タップとダブルタップの場合、基本的には
Hammer(el).on("tap", function() {
//singletap stuff
});
Hammer(el).on("doubletap", function() {
//doubletap stuff
});
これは、マウスイベントでも機能しますが、これは望んでいない場合があります。そして、これだけのためなら少しやり過ぎです。しかし、タッチ関連のものをもっと行う予定がある場合は、このライブラリを使用することをお勧めします。
これは私のために魔法をかけた最終的な作業コードです:)ここにすべてのコードをコピーして貼り付けましたが、自分のニーズに応じてそれを使用することができます。
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);
});
}
}
これが私のハックです。これは小さなコードブロックであり、モバイルでうまく機能するはずです。最初に何かをタップするとタイマーが設定され、2番目のタップが時間範囲(この例では600ms)にあるかどうかがチェックされます
// 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; }
});
これは、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>
Exit変数の値(つまり、trueまたはfalse)に応じて、さらにアクションを定義できます。