Javascript 如何区分单击事件和双击事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5497073/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:27:40  来源:igfitidea点击:

How to differentiate single click event and double click event?

javascriptjqueryjquery-events

提问by user426795

I have a single button in li with id "my_id". I attached two jQuery events with this element

我在 li 中有一个带有 id 的按钮"my_id"。我用这个元素附加了两个 jQuery 事件

1.

1.

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

2.

2.

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

But every times it gives me the single click

但每次它都给了我 single click

采纳答案by Adrien Schuler

You need to use a timeout to check if there is an another click after the first click.

您需要使用超时来检查第一次点击后是否还有一次点击。

Here is the trick:

这是诀窍

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

Usage:

用法:

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

EDIT:

编辑:

As stated below, prefer using the native dblclickevent: http://www.quirksmode.org/dom/events/click.html

如下所述,更喜欢使用原生dblclick事件:http: //www.quirksmode.org/dom/events/click.html

Or the one provided by jQuery: http://api.jquery.com/dblclick/

或者 jQuery 提供的:http: //api.jquery.com/dblclick/

回答by Ryan

The behavior of the dblclickevent is explained at Quirksmode.

dblclick事件的行为在Quirksmode 中进行了解释。

The order of events for a dblclickis:

a 的事件顺序dblclick是:

  1. mousedown
  2. mouseup
  3. click
  4. mousedown
  5. mouseup
  6. click
  7. dblclick
  1. 鼠标按下
  2. 鼠标向上
  3. 点击
  4. 鼠标按下
  5. 鼠标向上
  6. 点击
  7. 双击

The one exception to this rule is (of course) Internet Explorer with their custom order of:

此规则的一个例外是(当然)Internet Explorer,其自定义顺序为:

  1. mousedown
  2. mouseup
  3. click
  4. mouseup
  5. dblclick
  1. 鼠标按下
  2. 鼠标向上
  3. 点击
  4. 鼠标向上
  5. 双击

As you can see, listening to both events together on the same element will result in extra calls to your clickhandler.

如您所见,在同一元素上同时侦听两个事件将导致对click处理程序的额外调用。

回答by Renzo Ciot

A simple function. No jquery or other framework is required. Pass your functions as parameters

一个简单的功能。不需要 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>

回答by kyw

Instead of utilizing more ad-hoc states and setTimeout, turns out there is a native property called detailthat you can access from the eventobject!

事实证明,不是使用更多的临时状态和 setTimeout,detail您可以从event对象访问一个名为的本机属性!

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

Modern browsers and even IE-9 supports it :)

现代浏览器甚至 IE-9 都支持它 :)

Source: https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail

来源:https: //developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail

回答by álvaro González

I'm afraid that the behaviour is browser dependent:

我担心该行为取决于浏览器:

It is inadvisable to bind handlers to both the click and dblclick events for the same element. The sequence of events triggered varies from browser to browser, with some receiving two click events before the dblclick and others only one. Double-click sensitivity (maximum time between clicks that is detected as a double click) can vary by operating system and browser, and is often user-configurable.

不建议将处理程序绑定到同一元素的 click 和 dblclick 事件。触发事件的顺序因浏览器而异,有些在 dblclick 之前收到两个点击事件,而其他只收到一个。双击灵敏度(被检测为双击的最大单击间隔时间)可能因操作系统和浏览器而异,并且通常是用户可配置的。

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

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

Running your code in Firefox, the alert() in the click()handler prevents you from clicking a second time. If you remove such alert, you get both events.

在 Firefox 中运行您的代码,click()处理程序中的 alert()可防止您再次单击。如果您删除此类警报,则会收到两个事件。

回答by bradley.ayers

Well in order to double click (click twice) you must first click once. The click()handler fires on your first click, and since the alert pops up, you don't have a chance to make the second click to fire the dblclick()handler.

好吧,为了双击(单击两次),您必须先单击一次。该click()处理器大火在你第一次点击,而且由于警报弹出,你没有机会做第二次点击火的dblclick()处理程序。

Change your handlers to do something other than an alert()and you'll see the behaviour. (perhaps change the background color of the element):

更改您的处理程序以执行除 an 之外的其他操作alert(),您将看到行为。(也许改变元素的背景颜色):

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

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

回答by A1rPun

This answer is made obsolete through time, check @kyw's solution.

随着时间的推移,这个答案已经过时了,请查看@kyw 的解决方案。

I created a solution inspired by the gist posted by @AdrienSchuler. Use this solution only when you want to bind a single click AND a double click to an element. Otherwise I recommend using the native clickand dblclicklisteners.

我根据@AdrienSchuler 发布的要点创建了一个解决方案。仅当您想将单击和双击绑定到元素时才使用此解决方案。否则我建议使用 nativeclickdblclicklisteners。

These are the differences:

这些是差异:

  • Vanillajs, No dependencies
  • Don't wait on the setTimeoutto handle the click or doubleclick handler
  • When double clicking it first fires the click handler, then the doubleclick handler
  • Vanillajs,无依赖
  • 不要等待setTimeout处理单击或双击处理程序
  • 当双击它首先触发点击处理程序,然后双击处理程序

Javascript:

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

Usage:

用法:

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

Below is the usage in a jsfiddle, the jQuery button is the behavior of the accepted answer.

以下是 jsfiddle 中的用法,jQuery 按钮是已接受答案的行为。

jsfiddle

提琴手

回答by jeum

Another simple Vanilla solution based on the A1rPunanswer (see his fiddlefor the jQuery solution, and both are in this one).

另一个基于A1rPun答案的简单 Vanilla 解决方案(请参阅的 jQuery 解决方案的小提琴,两者都在这个中)。

It seems that to NOT trigger a single-click handler when the user double-clicks, the single-click handler is necessarily triggered after a delay...

似乎在用户双击时不触发单击处理程序,必须在延迟后触发单击处理程序......

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

回答by nex

Here's an alternative of jeum's code for an arbitrary number of events:

这是用于任意数量事件的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));

Needed this for a cytoscape.jsapp.

需要这个用于cytoscape.js应用程序。

回答by Fabien Snauwaert

How to differentiate between single clicks and double clicks on one and the same element?

如何区分对同一个元素的单击和双击?

If you don't need to mix them, you can rely on clickand dblclickand each will do the job just fine.

如果你并不需要将它们混合,你可以依靠clickdblclick每个将做的工作就好了。

A problem arises when trying to mix them: a dblclickevent will actually trigger a clickevent as well, so you need to determine whether a single click is a "stand-alone" single click, or part of a double click.

尝试混合它们时会出现一个问题:一个dblclick事件实际上也会触发一个click事件,因此您需要确定单击是“独立”单击还是双击的一部分。

In addition: you shouldn't use both clickand dblclickon one and the same element:

另外:你不应该在同一个元素上同时使用clickanddblclick

It is inadvisable to bind handlers to both the click and dblclick events for the same element. The sequence of events triggered varies from browser to browser, with some receiving two click events before the dblclick and others only one. Double-click sensitivity (maximum time between clicks that is detected as a double click) can vary by operating system and browser, and is often user-configurable.
Source: https://api.jquery.com/dblclick/

不建议将处理程序绑定到同一元素的 click 和 dblclick 事件。触发事件的顺序因浏览器而异,有些在 dblclick 之前收到两个点击事件,而其他只收到一个。双击灵敏度(被检测为双击的最大单击间隔时间)可能因操作系统和浏览器而异,并且通常是用户可配置的。
来源:https: //api.jquery.com/dblclick/

Now on to the good news:

现在是好消息:

You can use the event's detailproperty to detect the number of clicksrelated to the event. This makes double clicks inside of clickfairly easy to detect.

您可以使用事件的detail属性来检测与事件相关的点击次数。这使得双击内部click相当容易检测。

The problem remains of detecting single clicks and whether or not they're part of a double click. For that, we're back to using a timer and setTimeout.

问题仍然是检测单击以及它们是否是双击的一部分。为此,我们又回到使用计时器和setTimeout.

Wrapping it all together, with use of a data attribute (to avoid a global variable) and without the need to count clicks ourselves, we get:

将所有内容包装在一起,使用数据属性(以避免全局变量)并且无需自己计算点击次数,我们得到:

HTML:

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:

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>

Demo:

演示:

JSfiddle

JSfiddle



Notes about accessibility and double click speeds:

关于可访问性和双击速度的说明:

  • As Wikipedia puts it "The maximum delay required for two consecutive clicks to be interpreted as a double-click is not standardized."
  • No way of detecting the system's double-click speed in the browser.
  • Seems the default is 500 ms and the range 100-900mms on Windows (source)
  • Think of people with disabilities who set, in their OS settings, the double click speed to its slowest.
    • If the system double click speed is slower than our default 500 ms above, both the single- and double-click behaviors will be triggered.
    • Either don't use rely on combined single and double click on one and the same item.
    • Or: add a setting in the options to have the ability to increase the value.
  • 正如维基百科所说,“连续两次点击被解释为双击所需的最大延迟没有标准化。”
  • 无法在浏览器中检测系统的双击速度。
  • 似乎默认值为 500 毫秒,Windows 上的范围为 100-900 毫米(来源
  • 想想那些在操作系统设置中将双击速度设置为最慢的残疾人。
    • 如果系统双击速度低于我们上面默认的 500 毫秒,则单击和双击行为都会被触发。
    • 要么不要使用依赖组合单击和双击一个和相同的项目。
    • 或者:在选项中添加一个设置以具有增加值的能力。


It took a while to find a satisfying solution, I hope this helps!

花了一段时间才找到满意的解决方案,我希望这会有所帮助!