Tek tıklama olayıyla çift tıklama olayını nasıl ayırt edebilirim?


116

Kimliğiyle li olarak tek bir düğmem var "my_id". Bu öğeyle iki jQuery etkinliği ekledim

1.

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

2.

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

Ama her seferinde bana veriyor single click


Tek tıklamanın her zaman tetiklenmesi gerekecektir, belirtilen çift tıklama süresi içinde gerçekten gerçekleşmediği sürece bir çift tıklamanın gerçekleşip gerçekleşmeyeceğini bilmek imkansızdır.
Pieter Germishuys

7
Bu mümkün, cevabımı kontrol edin. İlk tıklamadan sonra birkaç ms beklemeniz ve belirtilen saate kadar yeni bir tıklama olup olmadığını kontrol etmeniz gerekir. Bu şekilde, bunun sadece basit bir tıklama mı yoksa çift tıklama mı olduğunu anlayabilirsiniz.
Adrien Schuler

Yanıtlar:


65

İlk tıklamadan sonra başka bir tıklama olup olmadığını kontrol etmek için bir zaman aşımı kullanmanız gerekir.

İşte püf noktası :

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

Kullanımı:

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

DÜZENLE:

Aşağıda belirtildiği gibi, yerel dblclicketkinliği kullanmayı tercih edin : http://www.quirksmode.org/dom/events/click.html

Veya jQuery tarafından sağlanan: http://api.jquery.com/dblclick/


14
Bu genel olarak iyi çalışıyor gibi görünebilir, ancak tıklamalar arasında izin verilen gecikme süresi (bu iki tıklamayla çift tıklama olarak yorumlanır) sistem yapılandırmasına göre farklılık göstermiyor mu? dblclickEtkinliğe güvenmek muhtemelen daha güvenlidir
Jon z

1
Evet, bence haklısın, dblclickkesinlikle bugün gitmenin yolu bu. jQuery bu olayı da yönetir: api.jquery.com/dblclick
Adrien Schuler

14
@AdrienSchuler - Bağladığınız dokümandan: İşleyicileri aynı öğe için hem tıklama hem de dblclick olaylarına bağlamanız tavsiye edilmez. Soru ikisine birden sahip olmakla ilgili .
Álvaro González

Kullanılabilir event.detailolduğunda, tıklama işleyiciden bir çift tıklamayı algılamanın en iyi yolu budur. Bu cevaba bakın .
Carl G

Güzel çözüm Adrien, bir nesnede tek ve çift tıklama olayımızın olduğu ve sadece birinin ateşlenmesi gereken bir durum için buna ihtiyacım var. Bu nedenle çözümünüz benim için mükemmel. "Bunu" kontrol altına almak için biraz geliştirdim: playcode.io/492022
LOstBrOkenKeY

79

dblclickOlayın davranışı Quirksmode'da açıklanmıştır .

A için olayların sırası dblclickşöyledir:

  1. mousedown
  2. mouseup
  3. Tıklayın
  4. mousedown
  5. mouseup
  6. Tıklayın
  7. DblClick

Bu kuralın tek istisnası, (elbette) aşağıdaki özel sıralamasıyla Internet Explorer'dır:

  1. mousedown
  2. mouseup
  3. Tıklayın
  4. mouseup
  5. DblClick

Gördüğünüz gibi, aynı öğe üzerinde her iki olayı birlikte dinlemek, clickişleyicinize fazladan çağrılarla sonuçlanacaktır .


dblclickHatta güvenilir olmadığından emin değilim ... Bir kez tıklarsam ... bir veya iki saniye bekleyin, sonra tekrar dblclicktıklayın, ikinci tıklamada bir etkinlik alıyorum !
Michael

Bu kadar uzun tıklamalar, örneğin dosyaları yeniden adlandırmak için kullanışlıdır. Ayırmak için 'longClick' gibi bir parametre olsaydı iyi olurdu.
PeterM

1
Kullanılabilir event.detailolduğunda, tıklama işleyiciden bir çift tıklamayı algılamanın en iyi yolu budur. Bu cevaba bakın .
Carl G

38

Daha fazla ad-hoc durum ve setTimeout kullanmak yerine detail, eventnesneden erişebileceğiniz yerel bir özellik olduğu ortaya çıktı !

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

Modern tarayıcılar ve hatta IE-9 bunu destekliyor :)

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


En iyi cevap :)
sk8terboi87 ツ

3
Çift tıklama durumunda, tek bir tıklama (nerede event.detail === 1) yine de tetiklenecektir. Kemanımı veya bu konu hakkındaki bu yorumu görün .
Fabien Snauwaert

İyi nokta @FabienSnauwaert. Sanırım hem tek hem de çift tıklama olay işleyicisini belirli bir öğeye bağlayamayız; Yukarıdaki yöntem, zamanlayıcı gibi maddelere başvurmadan bir çift tıklamayı kesin olarak belirlemek için kullanışlıdır.
kyw

Ateş etmemek için o ilk tıklamada hala bir zamanlayıcıya ihtiyacınız var. Cevabımı stackoverflow.com/questions/5497073/…

Yalnızca bir erişilebilirlik notu: Bir klavye tarafından bir tıklama olayı tetiklenirse (örneğin, bir kullanıcı bir düğmeye odaklanıp enter tuşuna bastığında), olay detail özelliği ile 0 olarak üretilir, bu nedenle if(evt.detail !== 1) return;yanlışlıkla çiftlemeyi reddetmek gibi bir şey yapmak tıklamalar, faresi olmayan kullanıcıların bu düğmeye erişimini engeller.
gristow

25

Basit bir işlev. Jquery veya başka bir çerçeve gerekmez. İşlevlerinizi parametre olarak aktarın

<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
Bence en iyi cevap bu olmalı, ancak Windows IE8'de çalışması için zaman aşımını 200'e düşürmem gerekiyordu ancak bu değer işletim sistemine ve kullanıcıya bağlı olabilir. Ayrıca, bir çift tıklama kaydedilmişse tıklamanın yürütülmesini iptal edebilmek için zamanlayıcı referansını da kaydetmiştir.
xpereta

Bu kod parçası için teşekkür ederiz, chrome ve firefox üzerinde harika çalışıyor (ancak chrome'un dbl ve single ile çalışması için bu hack'e ihtiyacı yok).
victor

kullanmak el.dataset.dblclickbunu yapmanın daha güzel bir yolu olurdu.
SÖZCÜKLER

Kullanılabilir event.detailolduğunda, tıklama işleyiciden bir çift tıklamayı algılamanın en iyi yolu budur. GörmekBu cevaba.
Carl G

12

Korkarım davranış tarayıcıya bağlıdır:

İşleyicilerin aynı öğe için hem tıklama hem de dblclick olaylarına bağlanması tavsiye edilmez. Tetiklenen olayların sırası tarayıcıdan tarayıcıya değişir, bazıları dblclick'ten önce iki tıklama olayını alırken diğerleri yalnızca bir tıklama alır. Çift tıklama hassasiyeti (çift tıklama olarak algılanan tıklamalar arasındaki maksimum süre) işletim sistemine ve tarayıcıya göre değişebilir ve genellikle kullanıcı tarafından yapılandırılabilir.

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

Kodunuzu Firefox'ta çalıştırdığınızda, click()işleyicideki uyarı () ikinci kez tıklamanızı engeller. Böyle bir uyarıyı kaldırırsanız, her iki etkinliği de alırsınız.


Kullanılabilir event.detailolduğunda, tıklama işleyiciden bir çift tıklamayı algılamanın en iyi yolu budur. Bu cevaba bakın .
Carl G

11

Çift tıklama (iki kez tıklama) için önce bir kez tıklamanız gerekir. click()Uyarı açılır beri işleyici yangınları ilk tıklama, ve eğer yangın ikinci klik yapma şansı yok dblclick()işleyicisi.

İşleyicilerinizi an dışında bir şey yapacak şekilde değiştirin alert()ve davranışı göreceksiniz. (belki öğenin arka plan rengini değiştirin):

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

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

7

Bu cevap zamanla geçersiz hale geldi, @ kyw'nin çözümünü kontrol edin.

@AdrienSchuler tarafından yayınlanan özetten ilham alan bir çözüm yarattım. Bu çözümü yalnızca tek bir tıklama VE bir öğeye çift tıklama bağlamak istediğinizde kullanın. Aksi takdirde yerel clickve dblclickdinleyicileri kullanmanızı öneririm .

Farklılıklar şunlardır:

  • Vanillajs, Bağımlılık yok
  • Beklemeyin setTimeoutTıklama veya çift tıklama işleyicisini işlemeyi
  • Çift tıklandığında önce tıklama işleyiciyi, ardından çift tıklama işleyicisini tetikler

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

Kullanımı:

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

Aşağıda bir jsfiddle'daki kullanım, jQuery düğmesi kabul edilen cevabın davranışıdır.

jsfiddle



@jeum Hala her tarayıcıda benim için hile yapıyor. Ne "çalışmıyor" ve ne bekliyorsunuz? Görünüşe göre senin versiyonun niyet ettiğim şeyi yapmıyor.
A1rPun

İlk Sürümümü değiştirdim (çift kapatma kaldırıldı), lütfen yenisini deneyin: jsfiddle.net/jeum/cpbwx5vr/20 Kemanınızdaki sorun (Vanilya sürümü), çift tıklamanın tek işleyiciyi tetiklemesidir: tekli + benim için iki katı.
jeum

@jeum Bu bir hata veriyor. Evet, cevabım buradaki kabul edilen cevaplardan ve diğer cevaplardan farklı ve bu satırda da bu farkı
belirtiyorum

1
Evet yine hata, bu yüzden bu sürüm ana soruya yanıt veriyor: jsfiddle.net/jeum/cpbwx5vr/21 . Şimdi sürümünüze gelince (anlamadığım doğru), 'jQuery'nin kemanınızda istediğinizi başaramadığını fark ettiniz mi?
jeum

5

A1rPun cevabına dayanan başka bir basit Vanilya çözümü ( jQuery çözümü için onun kemanına bakın ve her ikisi de bu çözümde. ).

Görünüşe göre, kullanıcı çift tıkladığında tek tıklama işleyicisini TETİKLEMEYECEKTİR, tek tıklama işleyicisi mutlaka bir gecikmeden sonra tetiklenir ...

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
Tek tıklamanın ateşlenmesini istemiyorsanız, bu gerçekten en iyi alternatif :)
A1rPun

Kullanılabilir event.detailolduğunda, tıklama işleyiciden bir çift tıklamayı algılamanın en iyi yolu budur. Bu cevaba bakın .
Carl G

5

İşte keyfi sayıda olay için jeum kodunun bir alternatifi:

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

Bir cytoscape.js uygulaması için buna ihtiyaç vardı .


Güzel! Ayrıca, döndürülen işlevin içinde yeni bir değişken thistanımlayabilir ve onu tıklanan öğe olan ile atayabilir ve işleyiciye ( eonun yanında veya yerine) iletebiliriz .
HeyJude

5

Bir ve aynı öğeye yapılan tek tıklamalar ile çift tıklamalar arasında nasıl ayrım yapılır?

Bunları karıştırmanız gerekmiyorsa, güvenebilirsiniz clickvedblclick her gayet iş yapacak.

Bunları karıştırmaya çalışırken bir sorun ortaya çıkıyor: bir dblclickolay aslında bir clickolayı da tetikleyecektir tek bir tıklama çift tıklama bir "tek başına" tek tıklama veya bir parçası olup olmadığını belirlemek gerekir bu yüzden.

Ek olarak: ikisini birden clickve dblclickaynı öğe üzerinde kullanmamalısınız :

İşleyicilerin aynı öğe için hem tıklama hem de dblclick olaylarına bağlanması tavsiye edilmez. Tetiklenen olayların sırası tarayıcıdan tarayıcıya değişir, bazıları dblclick'ten önce iki tıklama olayını alırken diğerleri yalnızca bir tıklama alır. Çift tıklama hassasiyeti (çift tıklama olarak algılanan tıklamalar arasındaki maksimum süre) işletim sistemine ve tarayıcıya göre değişebilir ve genellikle kullanıcı tarafından yapılandırılabilir.
Kaynak: https://api.jquery.com/dblclick/

Şimdi iyi haberlere geçelim:

Olayladetail ilgili tıklama sayısını tespit etmek için olayın özelliğini kullanabilirsiniz . Bu, içinde çift tıklama yaparclick tespit oldukça kolay .

Sorun, tek tıklamaları tespit etme ve bunların bir çift tıklamanın parçası olup olmadıklarıdır. Bunun için bir zamanlayıcı kullanmaya geri döndük vesetTimeout .

Bir veri özelliği kullanarak (global bir değişkenden kaçınmak için) ve tıklamaları saymaya gerek kalmadan hepsini bir araya getirerek şunları elde ederiz:

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>

Demo:

JSfiddle


Erişilebilirlik ve çift tıklama hızlarıyla ilgili notlar:

  • Wikipedia'nın dediği gibi "Art arda iki tıklamanın çift tıklama olarak yorumlanması için gereken maksimum gecikme standartlaştırılmamıştır."
  • Tarayıcıda sistemin çift tıklama hızını tespit etmenin bir yolu yok.
  • Varsayılan değerin 500 ms ve Windows'ta 100-900 mm aralığı olduğu görülüyor ( kaynak )
  • İşletim sistemi ayarlarında çift tıklama hızını en yavaşına ayarlayan engelli insanları düşünün.
    • Sistem çift tıklama hızı yukarıdaki varsayılan 500 ms'den daha yavaşsa, hem tek hem de çift tıklama davranışları tetiklenecektir.
    • Bir ve aynı öğeye birleşik tek ve çift tıklamaya güvenmeyin.
    • Veya: değeri artırma yeteneğine sahip olmak için seçeneklere bir ayar ekleyin.

Tatmin edici bir çözüm bulmak biraz zaman aldı, umarım bu yardımcı olur!



3

Tek tıklamayı çift tıklamadan ayırmak için özel bir 'tek tıklama' olayı kullanmanıza izin veren basit bir jQuery eklentisi yazdım:

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

Modern doğru cevap, kabul edilen cevap ile @kyw'nin çözümü arasında bir karışımdır. İlk tek tıklamayı önlemek için bir zaman aşımına event.detailve ikinci tıklamayı önlemek için denetlemeye ihtiyacınız vardır.

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'den (ve diğer 90-140 bin kitaplıklardan) kaçınmayı seviyorum ve belirtilen tarayıcılar önce onclick'i ele alıyor, işte oluşturduğum bir web sitesinde yaptığım şey budur (bu örnek aynı zamanda yerel xy tıklanan bir konumu almayı da kapsar)

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

umarım yardımcı olur


2
Cevabınızı anlamak için oyununuzun URL'si gerekli değildir. Bu gönderinin spam girişimi olarak görülmemesi için onu kaldırıyorum.
Andrew Barber

1
tek eksi, 200 sihirli sabittir ve kullanıcının işletim sistemindeki fare ayarlarından büyük ölçüde değişebilir
Danubian Sailor

1

Dayanarak Adrien Schuler (çok teşekkürler !!!) cevabı için Datatables.net ve birçok kullanımlar için, burada bir değişiklik geçerli:

fonksiyon

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

kullanım

$("#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

bu benim için çalıştı

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

Kullanımı-

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

0

Sadece ihtiyacın kolay ve HTML olması durumunda yerel HTML yanıtını yayınlamak.

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

Bu elbette yerel Jquery seçeneklerine sahiptir. yani ... $('#id').attr('ondblclick',function(){...})veya daha önce belirtildiği gibi,$('#id').dblclick(function(){...});


0

Bunun eski olduğunu biliyorum, ancak aşağıda tek ve çift tıklamayı belirlemek için tek bir zamanlayıcıya sahip temel bir döngü sayacının yalnızca JS örneği verilmiştir. Umarım bu birine yardımcı olur.

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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.