63

I have a button as such:

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

Within jQuery I am using the following, but it still allows for double-clicks:

<script type="text/javascript">

$(document).ready(function () {

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

Any idea on how I can prevent double-click?

user664833
  • 15,631
  • 18
  • 80
  • 123
Nate Pet
  • 38,422
  • 114
  • 251
  • 393
  • 4
    It's a button, you can click it as many times as you'd like to. Just prevent the default action or disable it after the first click. – adeneo Jul 23 '12 at 22:51
  • 1
    Agree with adeneo. Simplest solution seems to just disable it after it's clicked. – DaiYoukai Jul 23 '12 at 22:53
  • 1
    if disabled! it wont postback! Only single click must be allowed! Do u have any solution so that just one click must occur untill full form processing is done – SHEKHAR SHETE Jan 08 '15 at 09:09

16 Answers16

83

jQuery's one() will fire the attached event handler once for each element bound, and then remove the event handler.

If for some reason that doesn't fulfill the requirements, one could also disable the button entirely after it has been clicked.

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

It should be noted that using the ID submit can cause issues, as it overwrites the form.submit function with a reference to that element.

bancer
  • 7,040
  • 7
  • 35
  • 57
adeneo
  • 293,187
  • 26
  • 361
  • 361
  • 1
    so .one really doees't help in what I am trying to accomplish, correct? We need to use the disabled for it really work. – Nate Pet Jul 23 '12 at 22:58
  • 4
    Nope, one() works just fine, it runs the bound function just once, but since it's a regular button you can click it until you fingers hurt. Only way to stop it, is to disable it like above, or to prevent the default sending of the form so the button does'nt do anything, which you should do anyway otherwise the page will reload, and all the javascript functions will start over, and none of these solutions will work anyhow. – adeneo Jul 23 '12 at 23:01
  • 2
    if you disabled! then the button doesn't postback! Do u have any solution so that just one click must occur untill full form processing is done? – SHEKHAR SHETE Jan 08 '15 at 08:22
  • 2
    On my case it works, since i've page refresh after submit! others should keep in mind that this button will be of no use after single click – Shiv Feb 17 '16 at 15:34
  • Looks like `one()` doesn't work for Windows end users ... – Pathros Sep 07 '20 at 20:54
31

Just one more 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());
});

Here we save the time of last click as data attribute and then check if previous click was more than 0.3 seconds ago. If it is false (less than 0.3 sec ago), just update last click time, if true, do something.

jsbin

Kichrum
  • 521
  • 4
  • 6
24

I found that most solutions didn't work with clicks on elements like Labels or DIV's (eg. when using Kendo controls). So I made this simple solution:

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

Use it on the place where you have to decide to start an event or not:

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

    ..continue...
});
roberth
  • 812
  • 7
  • 15
12

My solution: https://gist.github.com/pangui/86b5e0610b53ddf28f94 It prevents double click but accepts more clicks after 1 second. Hope it helps.

Here is the 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;
}; 
Pangui
  • 121
  • 1
  • 5
11

In my case, jQuery one had some side effects (in IE8) and I ended up using the following :

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

which works very nicely and looks simpler. Found it there: http://www.jquerybyexample.net/2013/01/disable-mouse-double-click-using-javascript-or-jquery.html

Ilia Rostovtsev
  • 12,128
  • 10
  • 47
  • 80
Etienne
  • 1,010
  • 11
  • 21
6

just put this method in your forms then it will handle double-click or more clicks in once. once request send it will not allow sending again and again request.

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

it will help you for sure.

Paul Chu
  • 1,209
  • 3
  • 16
  • 23
Bachas
  • 166
  • 3
  • 11
  • same time you can not submit multiple request. $(this).submit(function() { return false; }); – Bachas Mar 14 '19 at 06:10
5

"Easy Peasy"

$(function() {
     $('.targetClass').dblclick(false);
});
Kabindas
  • 554
  • 6
  • 5
2

I have the similar issue. You can use setTimeout() to avoid the double-click.

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

// also check here if there's an attribute disabled

// if there's an attribute disabled in the btn tag then // return. Convert that into js.

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

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

What I found out was old but working solution on modern browsers. Works for not toggling classes on the double click.

$('*').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();
    }
});
Tadas Stasiulionis
  • 1,238
  • 3
  • 15
  • 18
1
/*
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
}

});
1

The solution provided by @Kichrum almost worked for me. I did have to add e.stopImmediatePropagation() also to prevent the default action. Here is my 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();
    }
});
1

This is my first ever post & I'm very inexperienced so please go easy on me, but I feel I've got a valid contribution that may be helpful to someone...

Sometimes you need a very big time window between repeat clicks (eg a mailto link where it takes a couple of secs for the email app to open and you don't want it re-triggered), yet you don't want to slow the user down elsewhere. My solution is to use class names for the links depending on event type, while retaining double-click functionality elsewhere...

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)

    }
});
ma5k
  • 11
  • 1
1

You can do something like this to disable submit button when loading a new page with the same form:

$("#btnConfirm").bind("click", function (e) {
  $("#btnConfirm ").css("pointer-events", "none");
});

The submit button could look like this:

<input
    type="submit"
    name="ACMS_POST_Form_Confirm"
    value="confirm"
    id="btnConfirm"
/>
Peter Csala
  • 4,906
  • 7
  • 11
  • 29
0

I had a similar issue, but disabling the button didn't fully did the trick. There were some other actions that took place when the button was clicked and, sometimes, button wasn't disabled soon enough and when the user double-clicked, 2 events where fired.
I took Pangui's timeout idea, and combined both techniques, disabling the button and includeding a timeout, just in case. And I created a simple jQuery plugin:

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

And then use it like this:

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

If what you really want is to avoid multiple form submissions, and not just prevent double click, using jQuery one() on a button's click event can be problematic if there's client-side validation (such as text fields marked as required). That's because click triggers client-side validation, and if the validation fails you cannot use the button again. To avoid this, one() can still be used directly on the form's submit event. This is the cleanest jQuery-based solution I found for that:

<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>
regiov
  • 31
  • 2
0

I was able to do this task efficiently by the following way

  1. As soon as the button click handler is called disable the button

  2. Do the necessary operations needed to be done.

  3. Set the disabled property back to false after a couple of seconds using SetTimeout

     $('#btn1).click(function(e){
     $('#btn1').prop("disabled", true);
    
     setTimeout(()=>{
     $('#btn1').prop("disabled", false);
     },2000)
    

This should solve the issue.