web-dev-qa-db-ja.com

dblclickイベントが発生したときにクリックイベントが発生しないようにする

DOM要素でclickイベントとdblclickイベントの両方を処理しています。それぞれが異なるコマンドを実行しますが、要素をダブルクリックすると、ダブルクリックイベントが発生するだけでなく、クリックイベントも2回発生することがわかりました。この動作を防ぐための最良のアプローチは何ですか?

29
David

コメントで、あなたは言った、

クリックハンドラーを300ミリ秒(目立って迷惑な遅延)、さらには...

つまり、クリックすると、クリックがダブルクリックの最初のクリックである場合を除いて、DOMはクリックイベントをすぐに生成する必要があるように思えます。

この機能を実装するには、クリックしたときに、DOMがこれが最後のクリックであるか、それがダブルクリックの最初のクリックであるかを予測できる必要があります(ただし、一般にDOMが予測することはできないと思います)ユーザーがもう一度クリックするかどうか)。


クリックとダブルクリックで実行しようとしている2つの異なるアクションは何ですか? IMO、通常のアプリケーションでは、両方のイベントが必要になる場合があります。シングルクリックして要素にフォーカスし、ダブルクリックしてアクティブにします。

イベントを分離する必要がある場合、一部のアプリケーションはダブルクリック以外のものを使用します。たとえば、右クリックやCtrlクリックを使用します。

13
ChrisW

(私がしたように)誰かがこれにつまずいて答えを探している場合、私が思いつくことができる絶対最良の解決策は次のとおりです:

    $node.on('click',function(e){
      if(e.originalEvent.detail > 1){
         return;
        /* if you are returning a value from this
         function then return false or cancel 
         the event some other way */
      }
    });

完了。背中合わせに複数回クリックする場合は、2回目、3回目など。発砲しません。私は間違いなく、あらゆる種類のタイマーを使用するよりもこれを好みます。

this を読んで、私はこの方向を指し示しました。


ちなみに、ページ付けされたリンクを誤ってダブルクリックしたため、最初にこの問題を調査しました。コールバックが発生する前に、イベントが発生して2回終了しました。

上記のコードを思い付く前に、私はを持っていました

 if e.originalEvent.detail === 2 //return

しかし、リンクを3回クリック(トリプルクリック)することができ、2回目のクリックは発生しませんでしたが、3回目のクリックは発生しました

25
dgo

UIEvent.detail 要素がクリックされた回数を検出し、それに基づいてイベントを発生させる場合。

簡単な例:

element.addEventListener("click", function (e) {
  if (e.detail === 1) {
    // do something if the element was clicked once.
  } else if (e.detail === 2) {
    // do something else if the element was clicked twice
  }
});
5
tarek salem

この場合、シングルクリックイベントの実行を少し遅らせるのが最善です。ダブルクリックハンドラーに、シングルクリックイベントがチェックする変数を設定してもらいます。その変数に特定の値がある場合は、boolDoubleClick == true、しないでくださいfire/handleシングルクリック。

5
Jordan S. Jones

これが私がモジュール内で区別するためにしたことです

       node.on('click', function(e) {

            //Prepare for double click, continue to clickHandler doesn't come soon enough
            console.log("cleared timeout in click",_this.clickTimeout);
            clearTimeout(_this.clickTimeout);
            _this.clickTimeout = setTimeout(function(){
                console.log("handling click");
                _this.onClick(e);
            },200);
            console.log(_this.clickTimeout);
        });

        node.on('dblclick', function (e) {

            console.log("cleared timeout in dblclick",_this.clickTimeout);
            clearTimeout(_this.clickTimeout);
            // Rest of the handler function
3
Nithin Haridas

相互作用が両方を必要とする場合に相互に排他的である場合、それらの組み合わせは私にとって合理的な解決策を提供するように見えるので、ここの他のすべての回答に感謝します:

var pendingClick = 0;

function xorClick(e) {
    // kill any pending single clicks
    if (pendingClick) {
        clearTimeout(pendingClick);
        pendingClick = 0;
    }

    switch (e.detail) {
        case 1:
            pendingClick = setTimeout(function() {
                console.log('single click action here');
            }, 500);// should match OS multi-click speed
            break;
        case 2:
            console.log('double click action here');
            break;
        default:
            console.log('higher multi-click actions can be added as needed');
            break;
    }
}

myElem.addEventListener('click', xorClick, false);

更新:このアプローチの一般化されたバージョンとタッチデバイスのクリックポリフィルを、例を挙げてこのGithubリポジトリに追加しました。

https://github.com/mckamey/doubleTap.js

2
mckamey

私はこれが古いことを知っていますが、同じ問題に遭遇したばかりなので、とにかく投稿しようと思いました。これが私がそれを解決した方法です。

 $('#alerts-display, #object-display').on('click', ['.item-data-summary', '.item-marker'], function(e) {
    e.preventDefault();

    var id;

    id = setTimeout(() => {
       // code to run here
       return false;
    }, 150);

    timeoutIDForDoubleClick.Push(id);
});


$('.panel-items-set-marker-view').on('dblclick', ['.summary', '.marker'], function(e) {
    for (let i = 0; i < timeoutIDForDoubleClick.length; i++) {
       clearTimeout(timeoutIDForDoubleClick[i]);
    }

    // code to run on double click

    e.preventDefault();
});
0
stevenlacerda