web-dev-qa-db-fra.com

Comment empêcher un double-clic avec jQuery?

J'ai un bouton en tant que tel:

<input type="submit" id="submit" value="Save" />

Dans jQuery, j'utilise les éléments suivants, mais cela permet tout de même de faire un double clic:

<script type="text/javascript">

$(document).ready(function () {

    $("#submit").one('click', function (event) {  

Une idée sur la façon dont je peux empêcher le double-clic?

51
Nate Pet

jQuery's one () lancera le gestionnaire d'événements attaché une fois pour chaque élément lié, puis supprimera le gestionnaire d'événements. 

Si, pour une raison quelconque, cela ne répond pas aux exigences, vous pouvez également désactiver le bouton après avoir cliqué dessus.

$(document).ready(function () {
     $("#submit").one('click', function (event) {  
           event.preventDefault();
           //do something
           $(this).prop('disabled', true);
     });
});

Il est à noter que l'utilisation de l'ID submit peut entraîner des problèmes, car elle écrase la fonction form.submit avec une référence à cet élément.

63
adeneo

Juste une autre solution:

$('a').on('click', function(e){
    var $link = $(e.target);
    e.preventDefault();
    if(!$link.data('lockedAt') || +new Date() - $link.data('lockedAt') > 300) {
        doSomething();
    }
    $link.data('lockedAt', +new Date());
});

Ici, nous enregistrons le temps du dernier clic en tant qu'attribut de données, puis vérifions si le clic précédent était il y a plus de 0,3 seconde. S'il est faux (il y a moins de 0,3 seconde), il suffit de mettre à jour l'heure du dernier clic. Si la valeur est true, faites quelque chose.

jsbin

21
Kichrum

J'ai constaté que la plupart des solutions ne fonctionnaient pas avec des clics sur des éléments tels que des étiquettes ou des DIV (par exemple, lors de l'utilisation de contrôles Kendo). J'ai donc fait cette solution simple:

function isDoubleClicked(element) {
    //if already clicked return TRUE to indicate this click is not allowed
    if (element.data("isclicked")) return true;

    //mark as clicked for 1 second
    element.data("isclicked", true);
    setTimeout(function () {
        element.removeData("isclicked");
    }, 1000);

    //return FALSE to indicate this click was allowed
    return false;
}

Utilisez-le à l'endroit où vous devez décider de commencer ou non un événement:

$('#button').on("click", function () {
    if (isDoubleClicked($(this))) return;

    ..continue...
});
16
roberth

Ma solution: https://Gist.github.com/pangui/86b5e0610b53ddf28f94 Elle empêche le double clic mais accepte plus de clics après 1 seconde. J'espère que ça aide.

Voici le code:

jQuery.fn.preventDoubleClick = function() {
  $(this).on('click', function(e){
    var $el = $(this);
    if($el.data('clicked')){
      // Previously clicked, stop actions
      e.preventDefault();
      e.stopPropagation();
    }else{
      // Mark to ignore next click
      $el.data('clicked', true);
      // Unmark after 1 second
      window.setTimeout(function(){
        $el.removeData('clicked');
      }, 1000)
    }
  });
  return this;
}; 
12
Pangui

Dans mon cas, jQuery one avait des effets secondaires (dans IE8) et j'ai fini par utiliser les éléments suivants:

$(document).ready(function(){
  $("*").dblclick(function(e){
    e.preventDefault();
  });
});

qui fonctionne très bien et semble plus simple. Je l'ai trouvé ici: http://www.jquerybyexample.net/2013/01/disable-mouse-double-click-using-javascript-or-jquery.html

11
Etienne

il suffit de mettre cette méthode dans vos formulaires, puis il gérera une ou plusieurs fois les clics. une fois la demande envoyée, il ne sera pas possible d'envoyer encore et encore une demande.

<script type="text/javascript">
    $(document).ready(function(){
            $("form").submit(function() {
                $(this).submit(function() {
                    return false;
                });
                return true;
            }); 
    }); 
</script>

cela vous aidera à coup sûr.

3
Bachas

J'ai le même problème. Vous pouvez utiliser setTimeout () pour éviter le double-clic.

//some codes here above after the click then disable it

// vérifie également ici s'il y a un attribut désactivé

// s'il y a un attribut désactivé dans la balise btn, alors // revenir. Convertis ça en js.

$('#btn1').prop("disabled", true);

setTimeout(function(){
    $('#btn1').prop("disabled", false);
}, 300);
2
user3856437

Ce que j’ai découvert est une solution ancienne mais qui fonctionne sur les navigateurs modernes. Fonctionne pour ne pas basculer les classes sur le double clic.

$('*').click(function(event) {
    if(!event.detail || event.detail==1){//activate on first click only to avoid hiding again on double clicks
        // Toggle classes and do functions here
        $(this).slideToggle();
    }
});
1
Tadas Stasiulionis

Ceci est mon tout premier article et je suis très inexpérimenté, alors n'hésitez pas, mais je sens que j'ai une contribution valable qui pourrait être utile à quelqu'un ...

Parfois, vous avez besoin d’une très grande fenêtre temporelle entre les clics répétés (par exemple, un lien mailto où il faut quelques secondes à l’application de messagerie pour s’ouvrir et vous ne voulez pas qu’elle soit réactivée), mais vous ne voulez pas ralentir utilisateur vers le bas ailleurs. Ma solution consiste à utiliser des noms de classe pour les liens en fonction du type d'événement, tout en conservant la fonctionnalité de double-clic ailleurs ...

var controlspeed = 0;

$(document).on('click','a',function (event) {
    eventtype = this.className;
    controlspeed ++;
    if (eventtype == "eg-class01") {
        speedlimit = 3000;
    } else if (eventtype == "eg-class02") { 
        speedlimit = 500; 
    } else { 
        speedlimit = 0; 
    } 
    setTimeout(function() {
        controlspeed = 0;
    },speedlimit);
    if (controlspeed > 1) {
        event.preventDefault();
        return;
    } else {

        (usual onclick code goes here)

    }
});
1
ma5k
/*
Double click behaves as one single click


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

That way we have to check what is the event that is being executed at any sequence. 

   */
       var totalClicks = 1;

 $('#elementId').on('click dblclick', function (e) {

 if (e.type == "dblclick") {
    console.log("e.type1: " + e.type);
    return;
 } else if (e.type == "click") {

    if (totalClicks > 1) {
        console.log("e.type2: " + e.type);
        totalClicks = 1;
        return;
    } else {
        console.log("e.type3: " + e.type);
        ++totalClicks;
    }

    //execute the code you want to execute
}

});
0

Si vous voulez réellement éviter les soumissions multiples de formulaires et pas seulement le double-clic, utiliser jQuery one () sur l'événement de clic d'un bouton peut être problématique s'il existe une validation côté client (telle que des champs de texte marqués comme requis). En effet, click déclenche la validation côté client et si la validation échoue, vous ne pouvez plus utiliser le bouton. Pour éviter cela, one () peut toujours être utilisé directement sur l'événement submit du formulaire. C'est la solution la plus propre que j'ai trouvée pour jQuery:

<script type="text/javascript">
$("#my-signup-form").one("submit", function() {
    // Just disable the button.
    // There will be only one form submission.
    $("#my-signup-btn").prop("disabled", true);
});
</script>
0
regiov

"Peasy facile"

$(function() {
     $('.targetClass').dblclick(false);
});
0
user3852812

J'ai eu un problème similaire, mais la désactivation du bouton n'a pas complètement fait l'affaire. Certaines actions ont eu lieu lorsque l'utilisateur a cliqué sur le bouton et que, parfois, le bouton n'était pas désactivé suffisamment tôt et lorsque l'utilisateur a double-cliqué, 2 événements ont été déclenchés.
J'ai repris l'idée du délai d'attente de Pangui et ai combiné les deux techniques, en désactivant le bouton et en incluant un délai d'attente, juste au cas où. Et j'ai créé un simple plugin jQuery:

var SINGLECLICK_CLICKED = 'singleClickClicked';
$.fn.singleClick = function () {
    var fncHandler; 
    var eventData;
    var fncSingleClick = function (ev) {
        var $this = $(this);
        if (($this.data(SINGLECLICK_CLICKED)) || ($this.prop('disabled'))) {
            ev.preventDefault();
            ev.stopPropagation();
        }
        else {
            $this.data(SINGLECLICK_CLICKED, true);
            window.setTimeout(function () {
                $this.removeData(SINGLECLICK_CLICKED);
            }, 1500);
            if ($.isFunction(fncHandler)) {
                fncHandler.apply(this, arguments);
            }
        }
    }

    switch (arguments.length) {
        case 0:
            return this.click();
        case 1:
            fncHandler = arguments[0];
            this.click(fncSingleClick);
            break;
        case 2: 
            eventData = arguments[0];
            fncHandler = arguments[1];
            this.click(eventData, fncSingleClick);
            break;
    }
    return this;
}

Et puis utilisez-le comme ceci:

$("#button1").singleClick(function () {
   $(this).prop('disabled', true);
   //...
   $(this).prop('disabled', false);
})
0
Andrea

La solution fournie par @Kichrum a presque fonctionné pour moi. J'ai dû ajouter e.stopImmediatePropagation () également pour empêcher l'action par défaut. Voici mon code:

$('a, button').on('click', function (e) {
    var $link = $(e.target);
    if (!$link.data('lockedAt')) {
        $link.data('lockedAt', +new Date());
    } else if (+new Date() - $link.data('lockedAt') > 500) {
        $link.data('lockedAt', +new Date());
    } else {
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
    }
});
0
Peter van Mourik