Home > database >  Prevent multiple requests when clicking link using jQuery
Prevent multiple requests when clicking link using jQuery

Time:10-19

How do I prevent multiple requests when a user double-clicks a link? I want to use jQuery.

I would appreciate an elegant solution.

I'd think this had been asked before, but I cannot find it. Too many people want to prevent the default event and do something else.

I want to allow the default event exactly once then prevent all subsequent events.

Thanks!

Working MWE

Source code for MWE

<?php

sleep(1);

session_name('have-a-cookie');
session_start(['cookie_lifetime' => 3600]);

$_SESSION['counter'] = isset($_SESSION['counter']) ? $_SESSION['counter'] 1 : 0;

?>
<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <link rel="stylesheet" href="bootstrap.min.css" type="text/css" />
        <script src="jquery-3.6.1.min.js"></script>
        <script src="bootstrap.bundle.min.js"></script>
        <script>
// this does not work
// https://stackoverflow.com/questions/41693832/disable-a-link-after-click-using-jquery
$('.btn').on('click', function(e) {
    $(this).prop('disabled',true);
});
        </script>
    </head>
    <body>
        <div  style="max-width: 20em;">
            <div >
                <h2>Count: <?php echo $_SESSION['counter']; ?></h2>
                <p>The goal is to prevent multiple requests.</p>
                <p>Double-clicking the button should make <b>one</b> request and increment the counter by one.</p>
                <p><a  href="mwe.php">Count!</a></p>
                <p ><a href="mwe.php.txt">Source code</a></p>
            </div>
        </div>
    </body>
</html>

CodePudding user response:

Searching for how to disable a link turns up this article, which gives some very good reasons about why not to do it. A link without a, well, link, is meaningless - links are for navigating, and if you don't intend to navigate somewhere, maybe it shouldn't be a link.

The article suggets removing the href, but in your case you are not actually navigating, so that would not help. Your link is styled as a button, and for good reason - making it a button is not only more semantically correct, it would make disabling it a whole lot easier.

If you really want to stick with a link:

  • removing href is useless because you are not actually navigating anyway;

  • .attr('disabled', 'disabled'), or .prop() variants are useless because a link cannot be disabled;

  • .preventDefault() is actually required, because the default action when clicking a link is to navigate, and you don't want to do that, but it won't stop future clicks;

  • The nuclear option - removing the entire click handler so no more clicks are processed by JS - won't work either, because then you lose your .preventDefault(), and a click will act like a plain, vanilla, no-JS click and naviate away to the href target!

One option is to track whether or not the link has been clicked with a variable. Set it to true first time through, and only allow the processing if it is false. Working example:

// Track whether or not the link has been clicked
let clicked = false;

$('.btn').on('click', function(e) {
    // The default action for a link is to navigate - you don't
    // want to do that, so you do need to prevent it
    e.preventDefault();
    
    // Check if we have clicked, and bail out if so
    if (clicked) {
        return;
    }
    
    // Track that we have clicked
    clicked = true;
    
    // Some visual indicator so we can see what is happening
    console.log('click!');    
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<a  href="somewhere.html">Count!</a>

If you want to switch to a button, things are considerably simpler, as well as being semantically correct and elegant:

$('.btn').on('click', function(e) {
    // The default action for a button is to submit - you don't
    // want to do that, so you do need to prevent it
    e.preventDefault();
    
    // Disable button
    $(this).attr('disabled', 'disabled');
    
    // Some visual indicator so we can see what is happening
    console.log('click!');    
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button  href="somewhere.html">Count!</button>

CodePudding user response:

One solution is to convert the button-styled link into a submit button within a form.

Use this script:

(function () {
    var allowSubmit = true;
    $('form').onsubmit = function () {
       if (allowSubmit)
           allowSubmit = false;
       else
           return false;
    }
})();

Credit to Andy E for this component.

Substitute the <button> with a form:

<form action="solution_lucas.php" method="get">
    <input type="submit"  value="Count!" />
</form>

The live working solution is available here (at least temporarily).

Complete source code for the working solution is available here.

I will wait for other better or more elegant solutions! This one puts a question mark at the end of the URL. It is highly flexible though, in case you want send data with the request.

  • Related