47

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

4

13 に答える 13

37

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

    $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回目など。発砲しません。私は間違いなくこれをどんな種類のタイマーを使うよりも好みます。

これを読んで、私は自分自身をこの方向に向けさせました


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

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

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

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

于 2015-05-01T18:49:29.203 に答える
18

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

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

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

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


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

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

于 2009-05-19T03:08:56.230 に答える
11

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
  }
});
于 2018-03-24T14:22:49.383 に答える
6

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

于 2009-05-19T01:40:59.713 に答える
4

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

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

于 2012-06-15T20:04:04.433 に答える
3

AFAIK DOMレベル2イベントでは、ダブルクリックの指定はありません。IE7では動作しません(ショックがあります)が、FFとOperaは仕様の管理に問題はなく、すべてのアクションをクリックイベントに添付できますが、ダブルクリックの場合は「詳細」属性まで待つだけですイベントオブジェクトの値は2です。ドキュメントから:「同じ画面位置で複数のクリックが発生した場合、シーケンスは繰り返され、繰り返しごとにdetail属性が増加します。」

于 2009-06-29T10:56:50.750 に答える
3

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

       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
于 2013-02-14T14:20:57.467 に答える
2

別のことを行う必要があるdblclickイベントがあった場合、クリックイベントアクションを防ぐためにプロジェクトにこのソリューションを使用します。

注:このソリューションは、クリックとdblclick専用であり、トリプルクリックなどの他のものではありません。

クリックとダブルクリックの間の適切な時間を確認するには、こちらをご覧ください

英語が下手でごめんなさい。お役に立てば幸いです:)

var button, isDblclick, timeoutTiming;
var clickTimeout, dblclickTimeout;
//-----
button = $('#button');
isDblclick = false;
/*
the proper time between click and dblclick is not standardized,
and is cutsomizable by user apparently (but this is windows standard I guess!)
*/
timeoutTiming = 500;
//-----
button.on('dblclick', function () {

  isDblclick = true;
  clearTimeout(dblclickTimeout);
  dblclickTimeout = setTimeout(function () {
    isDblclick = false;
  }, timeoutTiming);
  //-----
  // here goes your dblclick codes
  console.log('double clicked! not click.');
  
}).on('click', function () {

  clearTimeout(clickTimeout);
  clickTimeout = setTimeout(function () {
    if(!isDblclick) {
      // here goes your click codes
      console.log('a simple click.');
    }
  }, timeoutTiming);
  
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" id="button">
click/dblclick on this to see the result
</button>

于 2020-05-17T23:03:20.213 に答える
0

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

 $('#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();
});
于 2017-11-21T19:02:29.843 に答える
0

これが2回目のクリックを防ぐための私の簡単な解決策です。もちろん、ダブルクリックが検出されたときにタイムアウトを再開することはできますが、実際にはそれは必要ありません。

clickTimeoutId = null;

onClick(e) {
    if (clickTimeoutId !== null) {
        // Double click, do nothing
        return;
    }

    // Single click
    // TODO smth

    clickTimeoutId = setTimeout(() => {
        clearTimeout(clickTimeoutId);
        clickTimeoutId = null;
    }, 300);
}
于 2020-06-11T10:04:14.890 に答える
0

要約すると、同じ要素のsimpleClickイベントとdoubleClickイベントを認識するために、onClickイベントを次のメソッドで処理するだけです。

var EVENT_DOUBLE_CLICK_DELAY = 220; // Adjust max delay btw two clicks (ms)
var eventClickPending = 0;

function onClick(e){
    if ((e.detail == 2 ) && (eventClickPending!= 0)) {
//       console.log('double click action here ' + e.detail);
         clearTimeout(eventClickPending);
         eventClickPending = 0;
         // call your double click method
         fncEventDblclick(e);

    } else if ((e.detail === 1 ) && (eventClickPending== 0)){   
//      console.log('sigle click action here 1');
        eventClickPending= setTimeout(function() {
//          console.log('Executing sigle click');
            eventClickPending = 0
            // call your single click method
            fncEventClick(e);
        }, EVENT_DOUBLE_CLICK_DELAY);

//    } else { // do nothing
//      console.log('more than two clicks action here ' + e.detail);
            
    }
}
于 2020-11-15T13:06:42.423 に答える
0

デバウンスを使用して、シングルクリックハンドラーがダブル/マルチクリックを検出しないようにすることができます

テスト:https ://jsfiddle.net/L3sajybp/

HTML

<div id='toDetect'>
Click or double-click me
</div>
<hr/>

<ol id='info'>
</ol>

JS

function debounce(func, wait, immediate) {
    let timeout;
    return function () {
        const context = this,
            args = arguments;
        const later = function () {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        const callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
}

function debounceSingleClickOnly(func, timeout = 500) {
   function eventHandler (event) {
        const { detail } = event;
      if (detail > 1) {
         console.log('no double click for you '+ func.name);
         console.log('');
         return;
      }
      
      func.apply(this, arguments);
   }
   
   return debounce(eventHandler, timeout); 
}

window.toDetect.addEventListener('click', debounceSingleClickOnly(handleSingleClick));

window.toDetect.addEventListener('dblclick', handleDoubleClick);

function handleS() {
    console.log('S func');
  console.log(this.id);
}

function handleSingleClick(event) { 
   console.log('single click');
   const divText = document.createElement('li');
   divText.appendChild(document.createTextNode('single click'));
   window.info.appendChild(divText)

   console.group();
   console.log('this element was single-clicked: ' + event.target.id);   
   console.log(this.id);  
     console.log('');   
   console.groupEnd();
}

function handleDoubleClick(event) {
   console.log('double click');
   const divText = document.createElement('li');
   divText.appendChild(document.createTextNode('double click'));
   window.info.appendChild(divText);


     console.group();  
   console.log('this element was double-clicked: ' + event.target.id);
   console.log(this.id);  
     console.log('');
   console.groupEnd();
 }

出力:ここに画像の説明を入力してください

于 2021-05-05T08:45:36.603 に答える
-1

  const toggle = () => {
      watchDouble += 1;
      setTimeout(()=>{
        if (watchDouble === 2) {
          console.log('double' + watchDouble)
        } else if (watchDouble === 1) {
          console.log("signle" + watchDouble)
        }
        watchDouble = 0
      },200);

  }
于 2019-05-28T17:27:23.717 に答える