I have a button that I want to switch between 2 different functions when clicked. like first click would call function A, second click would call function B, Third Click would call function A etc.
for html I have something like this:
<input type="image"onclick="test()">
for javascript I have:
<script>
val = 1;
function test () {
if (val = 1 ) {
function1 ();
}
else {
function2 ();}
}
</script>
<script>
function function1() {
alert("1");
val = 2;}
</script>
<script>
function function2() {
alert("2");
val = 1;}
</script>
it only ever runs function1 Even if I set val = 2 it will run function1. any idea what im doing wrong?
You were using the assignment operator to check the value. Use the equality operator instead:
<script>
val = 1;
function test () {
if (val == 1 ) { // compare values using == (or maybe ===)
function1();
val = 2; // use the assignment operator here
}
else {
function2();
val = 1;
}
}
</script>
Update:
As #nnnnnn pointed out, you might want to update your toggle state inside test() directly.
If you need only toggle button, you can try XOR style function.
<script>
val = 0;
function toggle(){
val = val ^ 1; // XOR 0^1 => 1, 1^1 => 0
if(val == 0){
//do something
}else{
//do something else
}
}
</script>
OR in shorter way
<script>
val = 0;
function toggle(){
val = val ^ 1; // XOR 0^1 => 1, 1^1 => 0
val == 0 ? function1(): function2();
}
</script>
Related
I have a set of independent functions - fn1(), fn2(), fn3(), fn4().
I only need one function running at a time but the functions should toggle, on click of a single button, in a sequence fn1() [click] fn2() [click] fn3() [click] fn4() [click] back to fn1()
How do I approach this problem?
If I've understood what you're trying to do, you want to run a different function on successive clicks on a single element.
To do that you can put each function in an array, then run through each one using the modulo operator to return to the start of the array once the end is reached, something like this:
var functions = [function() {
console.log('first');
}, function() {
console.log('second');
}, function() {
console.log('third');
}, function() {
console.log('fourth');
}];
$('button').click(function() {
var i = ($(this).data('i') + 1) || 0;
functions[i % functions.length]();
$(this).data('i', i);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click me</button>
You can use a closure to keep track of which function you want to execute.
Html:
<button type="button" onclick="foo()"></button>
Js:
var foo = (function() {
var funcIndex = 0;
return function() {
switch(funcIndex) {
case 0: func1(); break;
case 1: func2(); break;
case 2: func3(); break;
case 3: func4(); break;
}
funcIndex = (funcIndex+1) % 4;
}
})();
function fn1(){}
function fn2(){}
function fn3(){}
var i = 1;
function myclick(){
if (i == 1)
fn1();
elseif (i == 2)
fn2();
elseif (i == 3) {
fn3();
i = 1;
}
i++;
}
Everytime you call myclick, it runs one fn and then adds 1 to i. The next time it runs the 2nd fn, followed by the 3rd.
<button onclick="toogle()">Click Me</button>
Then
var index = 0;
var funcArr= [f1,f2,f3,f4];
function toogle(){
funcArr[index]();
index++;
index = index%funcArr.length;
}
function f1(){console.log("f1")};
function f2(){console.log("f2")};
function f3(){console.log("f3")};
function f4(){console.log("f4")};
https://jsfiddle.net/8chvusaq/
arr=[fn1,fn2,fn3,fn4];
var i=0;
$("buttonId").click(function(){
arr[i%4]();
i++;
})
You can try this approach :
function fn1()
{
//do something
$("#myButton").off("click");
$("#myButton").click(fn2);
}
function fn2()
{
//do something
$("#myButton").off("click");
$("#myButton").click(fn3);
}
function fn3()
{
//do something
$("#myButton").off("click");
$("#myButton").click(fn4);
}
function fn4()
{
//do something
$("#myButton").off("click");
$("#myButton").click(fn1);
}
$("#myButton").click(fn1);
<!DOCTYPE html>
<html>
<body>
<button onClick="Display()"></button>
<script>
function Display() {
var a = 0;
if(a = 0){
alert("hello world");
}
}
</script>
</body>
</html>
I run the page and clicked the button and nothing happens. I can't for the life of me figure out why...
Edit: on another note, THIS code executes no matter what, even if I haven't defined var CorrectActivities:
function Display() {
if(CorrectActivities = 3) {
document.getElementById("ActivitiesResult").innerHTML = '<span>style="color:DarkGreen;font-weight:bold;font-size:30px;">3 out of 3 correct!</span>';
} else if (CorrectActivities = 2) {
document.getElementById("ActivitiesResult").innerHTML = '<span style="color:Crimson;font-weight:bold;font-size:30px;">2 out of 3 correct!</span>';
} else if (CorrectActivities = 1) {
document.getElementById("ActivitiesResult").innerHTML = '<span style="color:Crimson;font-weight:bold;font-size:30px;">1 out of 3 correct!</span>';
} else {
document.getElementById("ActivitiesResult").innerHTML = '<span style="color:Crimson;font-weight:bold;font-size:30px;">0 out of 3 correct!</span>';
}
}
Edit2: thanks for the answers. First code is fixed, second is still broken regardless of what I try. Going to look for errors elsewhere in the script...
When you compare values, you should use == (equal) or === (equal and same type). = is only for setting variable value.
<!DOCTYPE html>
<html>
<body>
<button onClick="Display()"></button>
<script>
function Display() {
var a = 0;
if(a == 0){
alert("hello world");
}
}
</script>
</body>
</html>
To your another code, I created a jsfiddle. There you have same problem as in first part, wrong comparison operator. It didn't run if CorrectActivities wasn't declared. I fixed it (like in first part), declared variable and added three buttons to test all cases and it seems to work.
You also have small typo in case 3, you have an extra closing bracket at <span>style
a = 0 is assignment not a valid condition. a == 0, a === 0 or !a will all work for what you want.
Same is the case with CorrectActivities, use CorrectActivities == 3 instead of CorrectActivities = 3.
in javascript = assign a value and return it, == or === compare values
The first part wont execute because:
You click the button
Display get called
if(a = 0) evaluate to if(0) which is to javascript if(false)
so the code inside if won't run. what you want is if(a == 0):
function Display() {
var a = 0;
if (a == 0) {
alert("hello world");
}
}
<button onClick="Display()"></button>
for the second part if(CorrectActivities = 3) will be if(3) which is to javascript if(true) so it will always run. again what you want is using the == operator:
function Display () {
if ((CorrectActivities == 3)) {
document.getElementById('ActivitiesResult').innerHTML = '<span>style="color:DarkGreen;font-weight:bold;font-size:30px;">3 out of 3 correct!</span>'
} else if ((CorrectActivities == 2)) {
document.getElementById('ActivitiesResult').innerHTML = '<span style="color:Crimson;font-weight:bold;font-size:30px;">2 out of 3 correct!</span>'
} else if ((CorrectActivities == 1)) {
document.getElementById('ActivitiesResult').innerHTML = '<span style="color:Crimson;font-weight:bold;font-size:30px;">1 out of 3 correct!</span>'
} else {
document.getElementById('ActivitiesResult').innerHTML = '<span style="color:Crimson;font-weight:bold;font-size:30px;">0 out of 3 correct!</span>'
}
}
This is because instead of comparing,you are assigning it.
So the statement if(a = 0) always comes out to be true.
Use == instead of =.
function Display() {
var a = 0;
if(a = 0){
alert("hello world");
}
}
This will help.
Thanks to the help of you fine Overflowians, I fixed up my silly little RNG Addition game and got it working. Now, at one user's suggestion, I'm trying to change the scope of the addition game's code from global to local before I code up the next game; I want each game to be completely contained within its own scope, as I understand that learning to not thoughtlessly contaminate the global scope is a good idea. However, I'm a bit stuck on how to achieve that.
Here's the code for the currently functional addition game:
function beginAdditionChallenge() {
var x = Math.ceil(Math.random()*100);
alert(x);
for (var i = 0; i < 3; i++) {
var a = Number(prompt("Provide the first addend.", ""));
var b = Number(prompt("Provide the second addend.", ""));
if (a + b === x) {
alert("Well done!");
break;
}
else if (a + b !== x && i < 2) {
alert("Please try again.");
}
else {
alert("Derp.");
}
}
}
function initChallenge() {
var button = document.getElementById("challengeButton");
button.addEventListener("click", beginAdditionChallenge);
}
window.addEventListener("load", initChallenge);
And here's my attempt to wrap it, which only succeeds in breaking the game, such that the button doesn't even respond:
window.addEventListener("load", function() {
function beginAdditionChallenge() {
var x = Math.ceil(Math.random()*100);
alert(x);
for (var i = 0; i < 3; i++) {
var a = Number(prompt("Provide the first addend.", ""));
var b = Number(prompt("Provide the second addend.", ""));
if (a + b === x) {
alert("Well done!");
break;
}
else if (a + b !== x && i < 2) {
alert("Please try again.");
}
else {
alert("Derp.");
}
}
}
function initChallenge() {
var button = document.getElementById("challengeButton");
button.addEventListener("click", beginAdditionChallenge);
}
window.addEventListener("load", initChallenge);
});
Functional code is available on JSFiddle here.
Note that the onLoad option in JSFiddle does the same as your 2nd snippet. You'll want to choose one of the No wrap options when binding to 'load' yourself.
And, the issue stems from attempting to bind to 'load' within a 'load' handler:
window.addEventListener("load", function() {
// ...
window.addEventListener("load", initChallenge);
});
When the event is already firing and handling the outer binding, it's too late to add more handlers to it. They won't be cycled through and the event shouldn't occur again.
You'll either want to call initChallenge within the outer event binding:
window.addEventListener("load", function() {
// ...
initChallenge();
});
Or, you can use an IIFE with the inner binding:
(function () {
// ...
window.addEventListener("load", initChallenge);
})();
The problem is I need to break the function if it is first time running
is there any function available , or I have to do something like the following?
var times = 1
function abc () {
if (times == 1)
break;
else
.....
times++;
}
times = 0;
Thanks.
You can use this pattern:
function abc() {
if (!abc.flag) {
abc.flag = true;
return;
}
// .. rest of the code
}
It's based on the fact that Function is also an object in Javascript.
Basically this is a Memoization pattern. It has disadvantage that the flag property can be overwritten by another code. The advantage is that you don't need to pollute global scope with additional variables.
thg435 proposed much more elegant solution.
It appears to me that you're trying to solve the problem in the wrong place. Can you tell us the whole story?
In the meantime, something like this should do the trick:
function abc() {
abc = function() {
// ...actual work...
}
}
Details depend on how your function is defined (globally, locally, as a method).
var isFirstTime = true;
function abc () {
if (isFirstTime)
{
isFirstTime = false;
return;
}
.....
}
abc(); //returns
abc(); //runs
var firstTime= true
function abc () {
if (firstTime)
{
firstTime = false;
return;
}
else
{
.....
}
}
Try This :
var times = 1;
function abc () {
if (times == 1){}
else{
.....
times == 0;}
}
I'm trying to figure out how I can have a javascript function privately track the number of times it has been called. The objective is to be able to query this value in the console during debugging by doing func.run
My first attempt:
function asdf() {
if (!asdf.run) {
asdf.run = 0;
} else {
asdf.run++;
console.error('run: ' + asdf.run);
}
console.error('asdf.run def: ');
console.error(asdf.run);
}
asdf();
This is a good lesson of why one should ALWAYS aim to use === in nearly all javascript booleans, cause they could secretly be ==
Closures are the way to go here:
var asdf = (function () {
var runs = 0;
var f = function () {
++runs;
// your function here
};
f.runs = function () {
return runs;
};
return f;
}());
Usage:
asdf();
asdf();
asdf.runs(); // 2
asdf();
asdf.runs(); // 3
Or, you could use a mocking framework like (shameless self plug) Myrtle.
Your first try would work fine except you've forgotten that 0 is a "falsy" value in JavaScript, so on the first run and every run thereafter !this.run will evaluate to true and your else block will never be reached. This is pretty easy to work around.
function foo() {
if(typeof(foo.count) == 'undefined') {
foo.count = 0;
} else {
foo.count++;
}
console.log(foo.count);
}
foo(); # => 0
foo(); # => 1
foo(); # => 2
# ...
I haven't actually tried this, but I looked up "static function variables in JavaScript", and I found this resource. I think the main difference between what you wrote and what's in that solution is how the first run of the function is detected. Perhaps your !asdf.run test is not working the way you thought it was, and you should use typeof asdf.run == 'undefined' to test instead.
OK, here is a method that I came up with that does not require the function to be modified at all.
So if you have this.
function someFunction() {
doingThings();
}
you could add a counter like this...
addCounter(this, "someFunction");
where this is the scope you are in, you could use any object that has a method you want to count.
Here's the code for it.
<html>
<head>
<script>
function someFunc() {
console.log("I've been called!");
};
// pass an object, this or window and a function name
function wrapFunction(parent, functionName) {
var count = 0, orig = parent[functionName];
parent[functionName] = function() {
count++;
return orig.call(this, Array.prototype.slice(arguments));
}
parent[functionName].getCount = function() {
return count;
};
}
var someObj = {
someFunc: function() {
console.log("this is someObj.someFunc()");
}
}
wrapFunction(this, "someFunc");
wrapFunction(someObj, "someFunc");
someFunc();
someObj.someFunc();
someObj.someFunc();
someObj.someFunc();
console.log("Global someFunc called " + someFunc.getCount() + " time" + (someFunc.getCount() > 1 ? "s" : "")) ;
console.log("Global someObj.someFunc called " + someObj.someFunc.getCount() + " time" + (someObj.someFunc.getCount() > 1 ? "s" : "")) ;
</script>
</head>
So, !asdf.run is a form of the double equals operator == and I had set asdf.run to 0 so it was false.
Using the triple equals === :
typeof asdf.run === "undefined" for the boolean solves my issue.
So a final usable and useful version:
function sdf() {
if (typeof sdf.run === "undefined") { sdf.run = 0; }
sdf.run++;
}
To query the number of times sdf has been called:
sdf.run;
To actually make this variable private and protect it from change, one would implement a closure.
//using a closure and keeping your functions out of the global scope
var myApp = (function() {
//counter is a private member of this scope
var retObj = {}, counter = 0;
//function fn() has privileged access to counter
retObj.fn = function() {
counter++;
console.log(counter);
};
//set retObj to myApp variable
return retObj;
}());
myApp.fn(); //count = 1
myApp.fn(); //count = 2
myApp.fn(); //count = 3
You don't necessarily need a closure. Just use a static variable.
var foo = function(){
alert( ++foo.count || (foo.count = 1) );
}
// test
function callTwice(f){ f(); f(); }
callTwice(foo) // will alert 1 then 2
or
callTwice( function bar(){
alert( ++bar.count || (bar.count = 1) );
}); // will alert 1 then 2
the second one is a named anonymous function. And note this syntax:
var foo = function bar(){ /* foo === bar in here */ }