I have a function in Javascript which is called by clicking a button and it takes approximately one minute to be finished. How can I disable the button after one click and enable it again after function is finished?
I need this process to prevent spamming.
I tried the following piece of code, but it is not working. It is still possible to click the button several times.
Javascript:
function myFunc()
{
document.getElementById("Btn").disabled = true;
\\do something for one minute
document.getElementById("Btn").disabled = false;
}
html:
<button type="button" id="Btn" onclick="myFunc()">Generate!</button>
Your code is working fine. Maybe your function runs quickly that's why it appears as you can spam.
If you're calling function thru ajax, make sure async is false (default is true)
function myFunc() {
document.getElementById("Btn").disabled = true;
setTimeout(function() {
console.log('hey');
document.getElementById("Btn").disabled = false;
}, 1000);
}
<button type="button" id="Btn" onclick="myFunc()">Generate!</button>
Related
I have two quantity selector buttons.
After the user clicks in any of these buttons (increasing or decreasing quantity), I need to run a function.
But the user can click several times in a row, and I want to execute the function only once.
Like, wait 1 second after each click to run the function. If within this 1 second the user clicks the button again, reset the timer and wait for another second to run the function. When the user doesn´t click again within 1 second, run the function.
What´s the best way to do that in vanilla javascript?
You just need to start a 1 second timer and reset it whenever the button click happens.
let timer
function handleClick() {
clearTimeout(timer)
timer = setTimeout(doSomething, 1000);
}
function doSomething() {
let div = document.getElementById("list")
let p = document.createElement("p")
p.textContent = "1 second passed without a click"
div.append(p)
}
<!DOCTYPE html>
<html>
<body>
<button onclick="handleClick()">Click me</button>
<div id=list></div>
</body>
</html>
I see two solutions:
If each click triggers some request, then disable button until the request is completed
Use throttling for the function invoke. You can use RxJS's throttle or you can write your own throttle method.
https://medium.com/nerd-for-tech/debouncing-throttling-in-javascript-d36ace200cea
You described a classic debounce technique. Here is an implementation:
Taken from https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore#_debounce
Another way is to dig into Lodash source codes and copy it from there
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
timeout = null;
if (!immediate) func.apply(context, args);
}, wait);
if (immediate && !timeout) func.apply(context, args);
};
}
// Avoid costly calculations while the window size is in flux.
jQuery(window).on('resize', debounce(calculateLayout, 150));
Here is a nice article and a playground about it https://css-tricks.com/debouncing-throttling-explained-examples/
You can try this in Vanilla JS :
const btn = document.querySelector('#btn');
const callback = event => {
console.log(event);
clearInterval(interval);
}
let interval;
btn.addEventListener('click', event => {
clearInterval(interval);
interval = setInterval( () => callback(event), 1000);
});
And the HTML :
<html>
<body>
<button id="btn">test</button>
</body>
</html>
That way you can pass the event instance to your callback.
How a user can stop a loop by clicking a button
Here what I need to do in my loop :
HTML :
<input type="button" id="stop" value="Stop" />
<input type="button" id="go" value="Go" />
<div id="div"> </div>
Javascript :
document.getElementById('go').addEventListener('click', function(){
// request to server that return a list of object.
// for each returned objet, I do another request to the server. like that
for(let i=0; i < objets.length; i++){
// request to the server.
// update the div for progress bar like 1%..2%
}
});
document.getElementById('stop').addEventListener('click', function(){
// how to break the loop made by go button
});
If you're running a simple for (..) loop, this cannot be stopped via external influence. Everything is happening on the same thread in Javascript, unless your code "ends" at some point and returns control to the browser for a while no UI interaction can happen. The easiest way to have a "loop" is via a setTimeout or setInterval:
interval = null;
startBTN.onclick = function () {
var i = 0;
interval = setInterval(function () {
console.log(i++); // this is inside your loop
}, 1);
};
stopBTN.onclick = function () {
clearInterval(interval);
};
In this if statement I can call a function to alert a message if the statement are true but the problem I get the message more that one time every time I click on ok button on the message box I get the same message box, again and again, I want to get the message only one time (I want to call the function only one time in the if statement ) are there any way for that ?
My if statement loop
if(brd_side == COLOURS.WHITE) {
firstmassege();
} else {
secondmassege();
}
My functions :
function firstmassege() {
alert('the first massege');
}
function secondmassege() {
alert('the second massege');
}
This Code should simply work. Hope this would be useful. This displays the first message only once and the second message after the button is clicked for the second time as required.
<!DOCTYPE html>
<html>
<body>
<p>Click the button to test the Function</p>
<button onclick="myFunction()">Click </button>
<p id="demo"></p>
<script>
var executed = false;
function myFunction() {
if (!executed){
firstmessage();
executed = true;
} else {
secondmessage();
}
}
function firstmessage() {
alert('the first message');
}
function secondmessage() {
alert('the second message');
}
</script>
</body>
</html>
How about using a flag to store the status. Please see the code below.
$('#btn').click(firstmessage)
var clicked = false;
function firstmessage() {
console.log('other statements...')
if(!clicked){
alert('the first massege');
}
clicked = true;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">click</button>
In your case it will be like below
var flag =false;
if (!flag){
firstmessage();
flag = true;
}
You can use one in jquery:
$('#myButton').one('click', function(){ alert('Hi!');});
I've been making a game to practice programming, and I am having trouble using the Jquery .click() function. I have two buttons in my code, the start button and the attack button. When I click the start button, the .click() function fires the code for the other button as well, which causes my main menu to freeze up and not draw the game screen. I've used separate id's for the buttons, but they both seem to recognize the click on the start button. I can't get it to work in JSFiddle, but all the code is there. Can someone please tell me how to use multiple buttons?
//start button
$('#startButton').click(function() {
stage.state = "battle";
stage.update();
})
//attack button
$('#attack').click(firstTurn());
//attack button code
function firstTurn() {
console.log("firstTurn Fired");
if(p1.speed > opp.speed){
turn = 1;
} else{
turn = 0;
}
battle();
};
function battle(){
var battling = 1;
while(battling == 1) {
if(turn == 0) {
p1.health = p1.health-opp.attack;
$("#textBox").append('<p>'+opp.name+' hit you for '+ opp.attack+' points.</p><br/>');
draw();
sleep(1000);
console.log("attacked");
} else{
opp.health = opp.health-p1.attack;
$('#textBox').append('<p> You hit '+opp.name+' for '+p1.attack+' points.</p><br/>');
draw();
sleep(1000);
}
}
};
https://jsfiddle.net/memersond/m3gvv8y6/
$('#attack').click(firstTurn());
Should be:
$('#attack').click(firstTurn);
You want to pass the function as a reference, not have it executed immediately.
$('#attack').click(firstTurn());
This causes firstTurn() to be called when the listener is initiated, use one of the alternatives:
$('#attack').click(firstTurn );
$('#attack').click(function() {
firstTurn()
});
For some reason html5 validation message is not shown when I'm using an async request.
Here you can see an example.
http://jsfiddle.net/E4mPG/10/
setTimeout(function() {
...
//this is not working
target.setCustomValidity('failed!');
...
}, 1000);
When checkbox is not checked, everything works as expected,
but when it is checked, the message is not visible.
Can someone explain what should be done?
I figured it out, turns out that the HTML5 validation messages will only popup when a form submit is in progress.
Here is the process behind my solution (when timeout is checked):
Submits the form
Sets the forceValidation flag
Sets the timeout function
When the timeout function is called, resubmit the form
If the forceValidation flag is set, show the validation message
Basically perform two submits, the first one triggered by the button, and the second triggered when the timeout function is called.
jsFiddle
var lbl = $("#lbl");
var target = $("#id")[0];
var forceValidation = false;
$("form").submit(function(){
return false;
});
$("button").click(function (){
var useTimeout = $("#chx").is(":checked");
lbl.text("processing...");
lbl.removeClass("failed");
target.setCustomValidity('');
showValidity();
if (forceValidation) {
forceValidation = false;
lbl.text("invalid!");
lbl.addClass("failed");
target.setCustomValidity('failed!');
showValidity();
} else if (useTimeout) {
setTimeout(function () {
forceValidation = true;
$("button").click();
}, 1000);
} else {
lbl.text("invalid without timeout!");
lbl.addClass("failed");
target.setCustomValidity('failed!');
showValidity();
}
});
function showValidity() {
$("#lbl2").text(target.checkValidity());
};
I am running on Chrome version 25.0.1364.172 m.