I have a function that I call when I press a button. My goal is to print "hello" in the console after 5 seconds and, if I press the button during the 5 seconds of waiting, nothing at all.
The problem is that, if I press the button while i'm waiting the 5 seconds, in the console I still get more than one "hello". What am I doing wrong?
Here is the Javascript code:
function foo(){
var block = false;
if(!block){
block = true;
myVar = setTimeout(checkAgain, 5000);
}
function checkAgain(){
console.log("hello");
block = false;
}
}
And the HTML:
<button id="button" onClick="foo();">Click me!</button>
You don't need to manually handle the "block", you can just cancel the call with clearTimeout. This seems to be more natural for me - when you click once you say "call this function in 5 seconds", and when you click it again you say "don't call it".
var timeout = null;
var button = document.querySelector("#btn");
button.onclick = function()
{
if (timeout)
{
clearTimeout(timeout);
timeout = null;
}
else
{
timeout = setTimeout(function() {
timeout = null;
run();
}, 1000); // should be 5000, just for test
}
};
function run()
{
console.log("Hello world");
}
<input type="button" id="btn" value="Click me">
You're not doing anything to block subsequent calls. block is a local variable inside foo, so there's a different one for each call to foo.
Instead, you have to have block outside foo:
var myVar;
var block = false;
function foo(){
if(!block){
block = true;
myVar = setTimeout(checkAgain, 5000);
}
function checkAgain(){
console.log("hello");
block = false;
}
}
document.getElementById("btn").addEventListener("click", foo);
<input type="button" id="btn" value="Click me">
That also means that checkAgain doesn't have to be recreated for every call to foo, since it doesn't need anything local to foo anymore:
var myVar;
var block = false;
function foo(){
if(!block){
block = true;
myVar = setTimeout(checkAgain, 5000);
}
}
function checkAgain(){
console.log("hello");
block = false;
}
document.getElementById("btn").addEventListener("click", foo);
<input type="button" id="btn" value="Click me">
(I assume all of this is in a scoping function or module so these aren't globals.)
That said, the button will remain active, giving the user the impression he/she could click it. Instead, you might consider making it possible for foo to disable and re-enable the button.
that is because you have defined variable 'block' in the scope of the function 'foo' and it is been initiated again every time you call the function. the correct implementation is:
var block = false;
function foo(){
if (!block) {
block = true;
myVar = setTimeout(checkAgain, 5000);
}
function checkAgain() {
console.log("hello");
block = false;
}
}
Related
I have an onclick shuffle function that executes everytime the audio finishes. It works all fine, but I want to make another button that stops its execution.
Please please help with an example
Full Code:
<button onclick="test();stats();auto()">Shuffle</button>
<button id="abort" onclick='exitauto()'>Stop Shuffle</button>
<script>
function exitauto(){
}
</script>
<script>
function stats() {
if(document.getElementById("audio").src == "test.mp3")
{
document.getElementById("p2").innerHTML = "some song";
document.getElementById("playerimg").src="img.png";
};
}
</script>
<script>
function auto(){
var aud = document.getElementById("audio");
aud.onended = function shuf() {
test();
stats();
};
}
</script>
<script>
function test() {
var values = ['test.mp3',
],
valueToUse = values[Math.floor(Math.random() * values.length)];
document.getElementById("audio").pause();
document.getElementById("audio").setAttribute('src', valueToUse);
document.getElementById("audio").load();
document.getElementById("audio").play();
};
</script>
You can add a global variable which can be used to decide whether to call the test() and stats() function in the auto function or not. You can set that variable to true when clicked on start and false when clicked on stop
var init = true;
$('#btn').on('click', delay(function() {
$('#text').append('click');
init = false;
}, 100));
function delay(fn, ms, enabled = true) {
$('#text').append(init);
// if(init) disable delay
let timer = 0;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(fn.bind(this, ...args), ms || 0);
}
}
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<button id='btn'> TRIGGER </button>
<div id="text"></div>
Init is a global variable which is meant to be used inside delay function to disable delay (init true/false) only on event listener initialisation.
The problem is that the delay function is triggered only once and ignores the change (to false) of the init variable.
For example, try clicking the trigger button. The init variable value is printed only for the first time.
You are calling the delay function in a wrong way in the click handler. You have to call it like so:
$('#btn').on('click', function () {
delay(function() {
$('#text').append('click');
init = false;
}, 100);
});
You will have to check for the value of init inside the function, like this:
$('#btn').on('click', delay(function() {
if(init) {
$('#text').append('click');
init = false;
}
}, 100));
At the moment I don't know why append is not working but with a little workaround you can obtain what you want. Concatenate the original text and the actual one and use text() to set it again:
var init = true;
$('#btn').on('click', function() {
$('#text').text(init);
setTimeout(myDelay, 5000);
});
function myDelay() {
let originalText = $('#text').text();
init = false;
console.log("init is false");
console.log("original text displayed: " + originalText);
$('#text').text(originalText + " " + init);
}
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<button id='btn'> TRIGGER </button>
<div id="text"></div>
Overview: There is a Button on my webage, its a single button. When I click this button, it should call function X. If I click this button a second time, it should call function Y. Basically, this is an ON and OFF switch. this button calls a function via onclick="function X". the same onclick needs to call function Y if clicked again. I hope I made that clear.
It cannot be 2 seperate buttons. thats too easy. does anyone have any ideas ? the only flexibily I have in terms of languages is html, javacript and css. any ideas welcome.
You don't need multiple functions. Just use a boolean to toggle between 2 different parts of code.
var toggle = true;
function functionX(){
if(toggle){
// Logic for the first click
} else {
// Logic for the other click
}
toggle = !toggle; // change the toggle for the next time the button's clicked.
}
There are a few ways to do this:
Two Buttons
html
<button id="a" onclick="a()">Test</button>
<button id="b" onclick="b()" style="hidden">Test</button>
css
.hidden {
display: none;
}
js
function a() {
var buttonA = document.getElementById('a');
var buttonB = document.getElementById('b');
buttonA.classList.add('hidden');
buttonB.classList.remove('hidden');
}
function b() {
var buttonA = document.getElementById('a');
var buttonB = document.getElementById('b');
buttonB.classList.add('hidden');
buttonA.classList.remove('hidden');
}
Hold State in a var
html
<button onclick="x()">Test</button>
js
var clicked = 'b'; //initial state
function x() {
switch(clicked) {
case 'a':
clicked = 'a';
a();
break;
case 'b':
clicked = 'b';
b();
break;
default: throw 'unknown state';
}
}
function a() {
//something
}
function b() {
//something
}
Re-assign listener on click (Easier with jquery)
html
<button id="x">Test</button>
js
$(document).ready(function() {
$('#x').click(a());
});
function a() {
//do something then..
$('#x').click(b);
}
function b() {
//do something then..
$('#x').click(a);
}
try this code
var i = 0;
function fun() {
if (i == 0) {
funX();
i = 1;
} else {
funY();
i = 0;
}
}
function funX() {
console.log('x');
}
function funY() {
console.log('y');
}
<button id="test" onclick="fun()">Click</button>
I want to place a command that allows me to change the waiting time after the click, for example
var myVar;
function myFunction() {
myVar = setTimeout(alertFunc, 3000);
}
function alertFunc() {
alert("Hello!");
}
<p>Click the button to wait 3 seconds, then alert "Hello".</p>
<button onclick="myFunction()">Try it</button>
This can easily be achieved with jQuery.
$(".my-button").on("click", function(e){
e.preventDefault();
setTimeout(function(){
alert("hello");
}, 3000);
})
Plunkr Example with enhanced code
JS
// Code goes here
var myVar;
function myFunction() {
// this is to make sure we don't spin up infinite timeouts and have zombie threads
if(myVar === undefined) {
myVar = setTimeout(alertFunc, 3000);
} else {
alert("already running...");
}
}
function alertFunc() {
alert("hello!");
// clears the thread
clearTimeout(myVar);
myVar = undefined;
}
Your Code
Your code seems to be working just fine, alert will work when not in the stack overflow sandbox and the only thing I added was clearing the timeout with clearTimeout this is so it doesn't continually run infinitely.
var myVar;
function myFunction() {
myVar = setTimeout(alertFunc, 3000);
}
function alertFunc() {
console.log("Hello!");
clearTimeout(myVar);
}
<p>Click the button to wait 3 seconds, then alert "Hello".</p>
<button onclick="myFunction()">Try it</button>
<script>
function one() {
blah blah blah
}
function two() {
blah blah blah
}
</script>
<button onclick="one(); two()">Click Me</button>
This will call the two functions at the same time. What I want is to call function one() on the first click and then call function two() on the second click. Calls function three() on 3rd click and so on until 7th click
I would prefer to not use jQuery if possible
You can use an IIFE to accomplish this:
var fn3 = (function() {
var first = true;
return function() {
first ? fn1() : fn2();
first = !first;
}
})();
function fn1() {
console.log(1);
};
function fn2() {
console.log(2);
};
<button onClick="fn3()">click</button>
The solution is not too complex, you can just one() and two() from another function.
var callOne = true;
function one() {
alert('Call one');
}
function two() {
alert('Call two');
}
function call(){
if(callOne) one();
else two();
callOne = !callOne;
}
<button onclick="call();">Click Me</button>
One simple way of doing this is to reassign the onclick value:
<button id="clickme">Click Me</button>
<script>
function one() {
alert('one clicked');
document.getElementById('clickme').onclick = two;
}
function two() {
alert('two clicked');
}
document.getElementById('clickme').onclick = one;
</script>
Using this trick you have the option to disable the button after calling two():
document.getElementById('clickme').onclick = null;
Toggle the click handler back to one():
document.getElementById('clickme').onclick = one;
Or do anything else you want.
I'll do it like bellow
On click of the button have a function which decides which function to call according to number of times.
<button onclick="decideFunction()">Click Me</button>
var times = 0;
var one = function(){
alert('first time');
}
var two = function(){
alert('After first');
}
var decideFunction = function(){
if(times == 0){
one();
times++;
}
else{
two();
}
}
So first time it will execute function one and second time onwards it will execute function two.
The simplest way is defining an extra variable to false(or true, of course). While our variable is false, clicking button calls first function and changes the variable to true. On second click, our onclick function checkes the variable value and calls the function which we defined for true value.
var button = document.getElementById('button');
var x = false;
button.addEventListener('click', function(){
if(!x){
alert('function 1');
x = true;
}else{
alert('function 2');
x = false;
}
})