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!
<?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 thehref
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.