シングルクリックイベントとダブルクリックイベントを区別するにはどうすればよいですか?


116

liにidのボタンが1つあります"my_id"。この要素で2つのjQueryイベントをアタッチしました

1。

$("#my_id").click(function() { 
    alert('single click');
});

2。

$("#my_id").dblclick(function() {
    alert('double click');
});

しかし、それはいつも私に single click


シングルクリックは常に発生する必要があります。ダブルクリックが発生するかどうかは、指定されたダブルクリック時間内に実際に発生しないとわかりません。
Pieter Germishuys、2011年

7
これは可能です。私の答えを確認してください。最初のクリックから数ミリ秒待って、指定した時間まで新しいクリックがあるかどうかを確認する必要があります。このようにして、これが単純なクリックかダブルクリックかを知ることができます。
Adrien Schuler

回答:


65

最初のクリックの後に別のクリックがあるかどうかを確認するには、タイムアウトを使用する必要があります。

ここにトリックがあります:

// Author:  Jacek Becela
// Source:  http://gist.github.com/399624
// License: MIT

jQuery.fn.single_double_click = function(single_click_callback, double_click_callback, timeout) {
  return this.each(function(){
    var clicks = 0, self = this;
    jQuery(this).click(function(event){
      clicks++;
      if (clicks == 1) {
        setTimeout(function(){
          if(clicks == 1) {
            single_click_callback.call(self, event);
          } else {
            double_click_callback.call(self, event);
          }
          clicks = 0;
        }, timeout || 300);
      }
    });
  });
}

使用法:

$("button").single_double_click(function () {
  alert("Try double-clicking me!")
}, function () {
  alert("Double click detected, I'm hiding")
  $(this).hide()
})
<button>Click Me!</button>

編集:

以下で説明するように、ネイティブdblclickイベントを使用することをお勧めしますhttp : //www.quirksmode.org/dom/events/click.html

またはjQueryによって提供されるもの:http : //api.jquery.com/dblclick/


14
これは一般的にうまく機能しているように見えるかもしれませんが、クリック間で許容される遅延時間(2つのクリックがダブルクリックとして解釈される)はシステム構成によって異なりませんか?dblclickイベントに依存する方が安全だ
ジョンz

1
ええ、私はあなたが正しいと思います、dblclick今日行くための絶対的な方法です。jQueryもこのイベントを処理します:api.jquery.com/dblclick
Adrien Schuler

14
@AdrienSchuler-リンクするドキュメントから:同じ要素のクリックイベントとdblclickイベントの両方にハンドラーをバインドすることはお勧めできません。質問は両方を持つことです。
アルバロゴンサレス

ときにevent.detail利用可能である、それは、クリックハンドラからダブルクリックを検出するための最良の方法です。この回答を参照してください。
カールG

素敵なソリューションAdrien、1つのオブジェクトでシングルクリックイベントとダブルクリックイベントがあり、1つだけが発生する必要がある場合に必要です。したがって、あなたの解決策は私にとって完璧です。「これ」を制御できるように少し改善しました:playcode.io/492022
LOstBrOkenKeY

79

dblclickイベントの動作はQuirksmodeで説明されています

のイベントの順序は次のdblclickとおりです。

  1. マウスダウン
  2. マウスアップ
  3. クリック
  4. マウスダウン
  5. マウスアップ
  6. クリック
  7. dblclick

このルールの1つの例外は、(もちろん)Internet Explorerで、次のカスタム順序があります。

  1. マウスダウン
  2. マウスアップ
  3. クリック
  4. マウスアップ
  5. dblclick

ご覧のとおり、同じ要素で両方のイベントを一緒にリッスンすると、clickハンドラーが余分に呼び出されます。


dblclick信頼できるかどうかはわかりません... 1回クリックした場合... 1〜2秒待ってからもう一度クリックするとdblclick、2回目のクリックでイベントが発生します。
Michael

このような長いクリックは、ファイル名の変更などに役立ちます。それを区別するために「longClick」のようなパラメータがあればそれは素晴らしいでしょう。
PeterM 2018年

1
ときにevent.detail利用可能である、それは、クリックハンドラからダブルクリックを検出するための最良の方法です。この回答を参照してください。
カールG

38

より多くのアドホック状態とsetTimeoutを利用する代わりにdetaileventオブジェクトからアクセスできるというネイティブプロパティがあることがわかりました!

element.onclick = event => {
   if (event.detail === 1) {
     // it was a single click
   } else if (event.detail === 2) {
     // it was a double click
   }
};

最新のブラウザ、さらにはIE-9でもサポートされています:)

ソース:https : //developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail


ベストアンサー:)
sk8terboi87ツジャン

3
ダブルクリックの場合event.detail === 1でも、シングルクリック()はトリガーされます。私のフィドルまたはこのスレッドのこのコメントを参照してください。
Fabien Snauwaert、

良い点@FabienSnauwaert。特定の要素にシングルクリックイベントハンドラとダブルクリックイベントハンドラの両方をバインドすることはできないと思います。上記の方法は、タイマーなどに頼らずにダブルクリックを明確に決定するのに役立ちます。
kyw

起動しないようにするには、最初のクリックにタイマーが必要です。stackoverflow.com/questions/5497073/…の

単なるアクセシビリティのメモ:キーボードでクリックイベントが発生した場合(たとえば、ユーザーがタブでボタンにフォーカスしてEnterキーを押した場合)、イベントはdetailプロパティが0で生成されるため、if(evt.detail !== 1) return;偶発的な二重を拒否するようなことをしますクリックすると、マウスを使用していないユーザーがそのボタンにアクセスできなくなります。
グリストウ

25

シンプルな機能。jqueryやその他のフレームワークは必要ありません。関数をパラメーターとして渡す

<div onclick="doubleclick(this, function(){alert('single')}, function(){alert('double')})">click me</div>
    <script>
        function doubleclick(el, onsingle, ondouble) {
            if (el.getAttribute("data-dblclick") == null) {
                el.setAttribute("data-dblclick", 1);
                setTimeout(function () {
                    if (el.getAttribute("data-dblclick") == 1) {
                        onsingle();
                    }
                    el.removeAttribute("data-dblclick");
                }, 300);
            } else {
                el.removeAttribute("data-dblclick");
                ondouble();
            }
        }
    </script>

2
これが最良の答えであると思いますが、Windows IE8で動作するようにタイムアウトを200に減らす必要がありましたが、この値はOSおよびユーザーに依存する場合があります。また、ダブルクリックが登録されている場合にクリックの実行をキャンセルできるように、タイマー参照を保存しました。
xpereta 2013年

このコードの一部をありがとう、それはクロムとファイアフォックスで素晴らしい働きをします(クロムはdblとシングルで動作するためにこのハックを必要としませんが)。
ビクター14年

を使用el.dataset.dblclickすると、これを行うより良い方法になります。
WORMSS 2016

ときにevent.detail利用可能である、それは、クリックハンドラからダブルクリックを検出するための最良の方法です。この回答を参照してください。
カールG

12

動作はブラウザに依存していると思います:

同じ要素のクリックイベントとdblclickイベントの両方にハンドラーをバインドすることはお勧めできません。トリガーされるイベントのシーケンスはブラウザーによって異なり、dblclickの前に2つのクリックイベントを受け取るものもあれば、1つだけ受け取るものもあります。ダブルクリックの感度(ダブルクリックとして検出されるクリック間の最大時間)は、オペレーティングシステムとブラウザーによって異なり、多くの場合、ユーザーが構成できます。

http://api.jquery.com/dblclick/

Firefoxでコードを実行すると、click()ハンドラーのalert()が2回目のクリックを防ぎます。このようなアラートを削除すると、両方のイベントが発生します。


ときにevent.detail利用可能である、それは、クリックハンドラからダブルクリックを検出するための最良の方法です。この回答を参照してください。
カールG

11

よくダブルクリック(2回クリック)するには、最初に1回クリックする必要があります。click()アラートがポップアップするので、ハンドラの火災は、あなたの最初のクリックで、そして、あなたが発射する第二のクリック作るチャンスがありませんdblclick()ハンドラを。

ハンドラーを変更して以外のことを行うalert()と、動作が表示されます。(おそらく要素の背景色を変更します):

$("#my_id").click(function() { 
    $(this).css('backgroundColor', 'red')
});

$("#my_id").dblclick(function() {
    $(this).css('backgroundColor', 'green')
});

7

この答えは時代遅れになっています。@ kywの解決策を確認してください。

@AdrienSchulerが投稿した要旨に触発されたソリューションを作成しました。このソリューションは、シングルクリックとダブルクリックを要素にバインドする場合にのみ使用してください。それ以外の場合は、ネイティブclickおよびdblclickリスナーのます。

これらは違いです:

  • Vanillajs、依存関係なし
  • 待ってはいけない setTimeoutクリックまたはダブルクリックハンドラーの処理を
  • ダブルクリックすると、最初にクリックハンドラーが起動し、次にダブルクリックハンドラーが起動します。

JavaScript:

function makeDoubleClick(doubleClickCallback, singleClickCallback) {
    var clicks = 0, timeout;
    return function() {
        clicks++;
        if (clicks == 1) {
            singleClickCallback && singleClickCallback.apply(this, arguments);
            timeout = setTimeout(function() { clicks = 0; }, 400);
        } else {
            timeout && clearTimeout(timeout);
            doubleClickCallback && doubleClickCallback.apply(this, arguments);
            clicks = 0;
        }
    };
}

使用法:

var singleClick = function(){ console.log('single click') };
var doubleClick = function(){ console.log('double click') };
element.addEventListener('click', makeDoubleClick(doubleClick, singleClick));

以下はjsfiddleでの使用法です。jQueryボタンは受け入れられた回答の動作です。

jsfiddle


2
上記のコードとフィドルの「バニラ」バージョンは機能しません...これは修正されたバニラバージョンです:jsfiddle.net/jeum/cpbwx5vr/19
jeum

@jeumそれでもすべてのブラウザで私にとってはトリックを実行します。「動作しない」とは何ですか?あなたのバージョンは私が意図したことをしていないようです。
A1rPun 2016年

私のバージョンを修正しました(ダブルクロージャーを削除しました)。新しいバージョンを試してください:jsfiddle.net/jeum/cpbwx5vr/20フィドル(バニラバージョン)の問題は、ダブルクリックでシングルハンドラーがトリガーされることです:シングルを取得します+私にはダブル。
jeum

@jeumそれはエラーを出します。ここに受け入れられ、他の回答からうん私の答えが異なると私はまた、このラインでは、この違いを指定:火クリックし、ダブルクリック(ダブルクリックにまっすぐ行っていない)
A1rPun

1
再びエラーが発生したため、このバージョンは主な質問jsfiddle.net/jeum/cpbwx5vr/21に応答します。さて、あなたのバージョン(私が理解していなかったことは事実です)について、 'jQuery'がフィドルで望むものを達成していないことに気づきましたか?
jeum 2016年

5

A1rPunの回答に基づくもう1つの単純なバニラソリューション(jQueryソリューションについては彼のフィドルを参照してください。どちらもこの1つにあります)。

ユーザーがダブルクリックしたときにシングルクリックハンドラーをトリガーしないように、シングルクリックハンドラーは必ず遅延後にトリガーされます...

var single = function(e){console.log('single')},
    double = function(e){console.log('double')};

var makeDoubleClick = function(e) {

  var clicks = 0,
      timeout;

  return function (e) {

    clicks++;

    if (clicks == 1) {
      timeout = setTimeout(function () {
        single(e);
        clicks = 0;
      }, 250);
    } else {
      clearTimeout(timeout);
      double(e);
      clicks = 0;
    }
  };
}
document.getElementById('btnVanilla').addEventListener('click', makeDoubleClick(), false);

3
シングルクリックを発生させたくない場合、これは確かに最良の代替策です。:)
A1rPun

ときにevent.detail利用可能である、それは、クリックハンドラからダブルクリックを検出するための最良の方法です。この回答を参照してください。
カールG

5

以下は、任意の数のイベントに対するjeumのコードの代替案です。

 var multiClickHandler = function (handlers, delay) {
    var clicks = 0, timeout, delay = delay || 250;
    return function (e) {
      clicks++;
      clearTimeout(timeout);
      timeout = setTimeout(function () {
        if(handlers[clicks]) handlers[clicks](e);
        clicks = 0;
      }, delay);
    };
  }

  cy.on('click', 'node', multiClickHandler({
    1: function(e){console.log('single clicked ', e.cyTarget.id())},
    2: function(e){console.log('double clicked ', e.cyTarget.id())},
    3: function(e){console.log('triple clicked ', e.cyTarget.id())},
    4: function(e){console.log('quadro clicked ', e.cyTarget.id())},
    // ...
  }, 300));

これはcytoscape.jsアプリに必要でした。


いいね!返された関数内で新しい変数を宣言しthis、クリックされた要素であるを割り当てて、ハンドラーに渡すこともできます(それと一緒に、eまたはその代わりに)。
HeyJude 2017

5

同じ要素のシングルクリックとダブルクリックを区別するにはどうすればよいですか?

あなたがそれらを混在させる必要がない場合は、頼ることができるclickdblclick、それぞれがうまく仕事を行います。

それらをミックスしようとすると、問題が発生:イベントが実際にトリガされますうまくなどのイベントをdblclickclick使用すると、シングルクリック、ダブルクリックの「スタンドアローン」シングルクリック、または一部であるかどうかを判断する必要があるので、。

さらに、両方clickを使用したりdblclick、1つの同じ要素で使用したりしないでください

同じ要素のクリックイベントとdblclickイベントの両方にハンドラーをバインドすることはお勧めできません。トリガーされるイベントのシーケンスはブラウザーによって異なり、dblclickの前に2つのクリックイベントを受け取るものもあれば、1つだけ受け取るものもあります。ダブルクリックの感度(ダブルクリックとして検出されるクリック間の最大時間)は、オペレーティングシステムとブラウザーによって異なり、多くの場合、ユーザーが構成できます。
ソース:https : //api.jquery.com/dblclick/

さて、朗報です。

イベントのdetailプロパティを使用して、イベントに関連するクリック数を検出できます。これにより、内部をダブルクリックclickすると、検出がかなり簡単になります。

シングルクリックの検出と、ダブルクリックの一部であるかどうかの問題が残っています。そのために、タイマーとを使用することに戻りますsetTimeout

データ属性を使用し(グローバル変数を回避するため)、クリック数を自分でカウントする必要なしに、すべてをまとめて取得します。

HTML:

<div class="clickit" style="font-size: 200%; margin: 2em; padding: 0.25em; background: orange;">Double click me</div>

<div id="log" style="background: #efefef;"></div>

JavaScript:

<script>
var clickTimeoutID;
$( document ).ready(function() {

    $( '.clickit' ).click( function( event ) {

        if ( event.originalEvent.detail === 1 ) {
            $( '#log' ).append( '(Event:) Single click event received.<br>' );

            /** Is this a true single click or it it a single click that's part of a double click?
             * The only way to find out is to wait it for either a specific amount of time or the `dblclick` event.
             **/
            clickTimeoutID = window.setTimeout(
                    function() {
                        $( '#log' ).append( 'USER BEHAVIOR: Single click detected.<br><br>' );
                    },
                    500 // how much time users have to perform the second click in a double click -- see accessibility note below.
                );

        } else if ( event.originalEvent.detail === 2 ) {
            $( '#log' ).append( '(Event:) Double click event received.<br>' );
            $( '#log' ).append( 'USER BEHAVIOR: Double click detected.<br>' );
            window.clearTimeout( clickTimeoutID ); // it's a dblclick, so cancel the single click behavior.
        } // triple, quadruple, etc. clicks are ignored.

    });

});
</script>

デモ:

JSfiddle


アクセシビリティとダブルクリック速度に関する注意:

  • ウィキペディアは、「ダブルクリックとして解釈される2つの連続したクリックに必要な最大遅延は標準化されていません」と述べています。
  • ブラウザでシステムのダブルクリック速度を検出する方法はありません。
  • デフォルトはWindowsで500ミリ秒、範囲は100〜900 mmのようです(ソース
  • OSの設定でダブルクリックの速度を最も遅くする障害のある人を考えてみてください。
    • システムのダブルクリック速度が上記のデフォルトの500ミリ秒より遅い場合、シングルクリックとダブルクリックの両方の動作がトリガーされます。
    • 同じアイテムをシングルクリックとダブルクリックを組み合わせて使用​​しないでください。
    • または:オプションに設定を追加して、値を増やすことができます。

満足のいく解決策を見つけるのにしばらく時間がかかりました、これが役に立てば幸いです!


4

優れたjQuery Sparkleプラグインを使用してください。プラグインは、最初と最後のクリックを検出するオプションを提供します。別のクリックの後に最初のクリックが続いたかどうかを検出することにより、クリックとdblclickを区別するために使用できます。

http://balupton.com/sandbox/jquery-sparkle/demo/で確認してください。


3

カスタムの「singleclick」イベントを使用して、シングルクリックとダブルクリックを区別できる簡単なjQueryプラグインを作成しました。

https://github.com/omriyariv/jquery-singleclick

$('#someDiv').on('singleclick', function(e) {
    // The event will be fired with a small delay.
    console.log('This is certainly a single-click');
}

3

現代の正解は、受け入れられた答えと@kywの解決策を組み合わせたものです。最初のシングルクリックを防ぐためのタイムアウトとevent.detail、2回目のクリックを防ぐためのチェックが必要です。

const button = document.getElementById('button')
let timer
button.addEventListener('click', event => {
  if (event.detail === 1) {
    timer = setTimeout(() => {
      console.log('click')
    }, 200)
  }
})
button.addEventListener('dblclick', event => {
  clearTimeout(timer)
  console.log('dblclick')
})
<button id="button">Click me</button>


1

私はjquery(および他の90-140k libs)を避けたいと思います、そして言及されたブラウザーが最初にonclickを処理するので、これは私が作成したWebサイトで私がしたことです(この例はクリックされた場所のローカルxyを取得することもカバーします)

clicksNow-0; //global js, owell

function notify2(e, right) {  // called from onclick= and oncontextmenu= (rc)
var x,y,xx,yy;
var ele = document.getElementById('wrap');  
    // offset fixed parent for local win x y
var xxx= ele.offsetLeft;
var yyy= ele.offsetTop;

//NScape
if (document.layers || document.getElementById&&!document.all) {
    xx= e.pageX;
    yy= e.pageY;
} else {
    xx= e.clientX;
    yy= e.clientY;
}
x=xx-xxx;
y=yy-yyy;

clicksNow++;
    // 200 (2/10ths a sec) is about a low as i seem to be able to go
setTimeout( "processClick( " + right + " , " + x + " , " + y + ")", 200);
}

function processClick(right, x, y) {
if (clicksNow==0) return; // already processed as dblclick
if (clicksNow==2) alert('dbl');
clicksNow=0;
    ... handle, etc ...
}

それが役に立てば幸い


2
ゲームのURLは、答えを理解するためにまったく必要ありません。この投稿がスパムの試みと見なされないように、削除します。
アンドリューバーバー

1
唯一のマイナス、200は魔法の定数であり、OSでのユーザーのマウス設定と大幅に異なる可能性があります
ダヌビアンセーラー2013

1

基づいて、エイドリアンシュラー(ありがとうございました!!!)答え、のためDatatables.netと多くの用途のために、ここでの変更は次のとおりです。

関数

/**
 * For handle click and single click in child's objects
 * @param {any} selector Parents selector, like 'tr'
 * @param {any} single_click_callback Callback for single click
 * @param {any} double_click_callback Callback for dblclick
 * @param {any} timeout Timeout, optional, 300 by default
 */
jQuery.fn.single_double_click = function (selector, single_click_callback, double_click_callback, timeout) {
    return this.each(function () {
        let clicks = 0;
        jQuery(this).on('click', selector, function (event) {
            let self = this;
            clicks++;
            if (clicks == 1) {
                setTimeout(function () {
                    if (clicks == 1) {
                        single_click_callback.call(self, event);
                    } else {
                        double_click_callback.call(self, event);
                    }
                    clicks = 0;
                }, timeout || 300);
            }
        });
    });
}

使用する

$("#MyTableId").single_double_click('tr',
            function () {   //  Click
                let row = MyTable.row(this);
                let id = row.id();
                let data = row.data();
                console.log("Click in "+id+" "+data);
            },
            function () {   //  DBLClick
                let row = MyTable.row(this);
                let id = row.id();
                let data = row.data();
                console.log("DBLClick in "+id+" "+data);
            }
        );

0

これは私のために働きました–

var clicked=0;
function chkBtnClcked(evnt) {
    clicked++;
    // wait to see if dblclick
    if (clicked===1) {
        setTimeout(function() {
            clicked=0;
            .
            .
        }, 300); // test for another click within 300ms
    }
    if (clicked===2) {
        stopTimer=setInterval(function() {
            clicked=0;
            .
            .
        }, 30*1000); // refresh every 30 seconds
    }
}

使用法-

<div id="cloneimages" style="position: fixed;" onclick="chkBtnClcked(evnt)"  title="Click for next pic; double-click for slide show"></div>

0

簡単でHTMLにする必要がある場合に備えて、ネイティブHTMLの回答を投稿するだけです。

<p ondblclick="myFunction()" id = 'id'>Double-click me</p>

もちろん、これにはネイティブのJqueryオプションがあります。すなわち... $('#id').attr('ondblclick',function(){...})または、前述のように、$('#id').dblclick(function(){...});


0

私はこれが古いことを知っていますが、以下は、シングルクリックとダブルクリックを判別するための単一のタイマーを備えた基本的なループカウンターのJSのみの例です。うまくいけば、これは誰かを助けます。

var count = 0;
var ele = document.getElementById("my_id");
ele.addEventListener('click', handleSingleDoubleClick, false); 

function handleSingleDoubleClick()
{
  if(!count) setTimeout(TimerFcn, 400); // 400 ms click delay
  count += 1;
}
function TimerFcn() 
{
  if(count > 1) console.log('you double clicked!')
  else console.log('you single clicked')
  count = 0;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.