I'm trying to make a recursive function to print 1 to 10 in JavaScript, my current code is:
function rec10(x)
{
if (x < 10)
{
$('#text').val(x+1);
x = x+1;
rec10(x);
}
}
The problem is, everytime I activate this function, the text box only shows "10" directly, i want the code to move from 0 to 1, to 2... until 10. Showing each one of them in the text box.
I tried to use setInterval and setTimeout but I didn't figure it out how to work with that. Thank you very much
instead of:
rec10(x);
call
setTimeout(function() { rec10(x); }, 1000);
With setInterval you can using code below:
function rec10(x) {
var interval = setInterval(function() {
if (x >= 10) clearInterval(interval);
$('#text').val(x++);
}, 1000);
}
JavaScript is single threaded, which means while your code runs, the changes you make to the DOM won't be seen on the browser until your code finish.
You need to give control to the browser for couple of seconds, it can be done with setTimeout:
function rec10(x){
if (x < 10){
$('#text').val(++x);
setTimeout(function(){
rec10(x);
},20);
}
}
Did you resort to setInterval/setTimeout only because you can't make a working recursive function?
If that's the case, how about this recursive function below without using setInterval/setTimeout:
function rec10(x) {
if (x <= 10) {
if (x <= 0) x = 1;
//append?
$('#text').val(x);
rec10(x + 1);
}
}
rec10(1);
But the problem with the code above is it will happen so fast you won't notice the printing of numbers 1 up to 9.
If you want to see the those numbers then I suggest you just append the value to your placeholder $('#text').
But if you really wanna see the numbers being printed and then being replaced by the next number, then you can refer to the answers posted by other users which uses setInterval/setTimeout.
Related
I have a jQuery function that shows modal boxes:
function ShowAnonce(){
...
jQuery(".ShowAnonce").show();
jQuery(".ShowAnonce").animate({opacity: 1},300).delay(1800).animate({opacity: 0},300);
}
And what I want to do is to show this box 10 times with different random intervals. I used a for loop and setTimeout like this:
for(i=0;i<10;i++){
setTimeout(ShowAnonce(),Math.random()*100);
}
but it shows the box 10 times with no delay. What can I do to fix it?
Also, why can't I do the following at the end of ShowAnonce function?
jQuery(".ShowAnonce").hide();
If I do it, it doesn't shows me box because style display:none keeps being assigned.
Math.random() can return value in decimals also like , 0.123. Which the setTimeout() cannot take . Try Math.ceil (Math.random()) this will give you an integer but might give the same value again and again .
I would try (Math.ceil (Math.random()) *10 ).
As an alternative you can use setInterval as below instead of for loop for x number of times:
var x = 0;
var intervalID = setInterval(function () {
ShowAnnounce();
if (++x === 10) {
window.clearInterval(intervalID);
}
}, Math.random()*100);
Another post about each() iteration gave me an answer. So it works for me:
var time = 0;
for(i=0;i<10;i++){
time = time + Math.random() *10000;
setTimeout(ShowAnonce, time);
}
Recently began studying Javascript, trying to read out of Javascript: The Definitive Guide and Eloquent Javascript, while going off on my own to experiment with things in order to really etch them in my memory. I thought a good way to get my head around arithmetic operations and conditional statements, I'd build a series of little games based around each Math operator, and began with addition.
function beginAdditionChallenge() {
var x = Math.ceiling(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 < 3) {
alert("Please try again.");
}
else {
alert("Fail.");
}
}
}
function initChallenge() {
var button = document.getElementById("challengeButton");
button.addEventListener("click", beginAdditionChallenge);
}
window.addEventListener("load", initChallenge);
You can see the whole thing thus far on JSFiddle, here. The idea is that clicking the button generates a random number between 1 and 100, displays it to the user, then prompts them to provide two addends, giving them 3 attempts. If the sum of these addends is equal to the RNG number, it congratulates the user and ends the program. If they do not provide suitable addends, the loop prompts them to try again, until they've hit 3 attempts, at which point the program snarks at them and ends.
I know the event listener is not the failure point here, as when I change beginAdditionChallenge to simply display a test alert, it works, but I don't know what exactly is wrong with the loop I've created.
You did it correctly. However, Math.ceiling isn't a function and should be Math.ceil. In addition, your code (in jsfiddle) should be set to wrap in head. Why? Because right now you call initChallenge when the page loads. However, in your jsfiddle example, the code runs onLoad so the load event never gets called. Essentially, you're adding a load event after the page has loaded.
http://jsfiddle.net/rNn32/
Edit: In addition, you have a for loop that goes up to three. Therefore
else if (a + b !== x && i < 3) {
alert("Please try again.");
}
should be
else if (a + b !== x && i < 2) {
alert("Please try again.");
}
because when i === 2, the user's last chance has ended.
Everything is fine. Just change:-
var x = Math.ceiling(Math.random()*100);
to:-
var x = Math.ceil(Math.random()*100);
I defined a variable 'i' to be equal to 2, and then say: if 'i' is between 0 and 2, let the function 'animate' run. However, if I open up the console in JSFiddle (option-command-I), the console.log() continues decreasing by 1 below 0! Am I using the conditional in the if statement improperly?
var interval = window.setInterval(animate, 500);
var i = 2;
if (0 < i < 2) {
function animate() {
alert('run');
i--;
console.log(i);
}
}
JSFiddle: http://jsfiddle.net/lpsternotes/RuLHn/
There are two problems here.
Firstly, there is this: 0<i<2. This will always evaluate to true.
Why? What you hoped it meant was "i is between 0 and 2" (which could be written as 0<i && i<2). But to a JS compiler, it is just two instances of the < operator. First, 0<i is evaluated, resulting in either true or false; then, that result is compared against <2 - so we have either true<2 or false<2. In order to answer that question, JS must "cast" the true or false to an integer. It treats false as 0, and true as 1; since these are both <2, the final result is always true.
Secondly, there is the position of your if statement, which is checked only once:
if (0 < i < 2) {
function animate() {
If you read through the code, you will see that there is no way of getting back to the line above this if statement, since the only repeating part of the code is the interval repeatedly running the animate function. To run each time the function runs, the if needs to be inside the function, not the other way around.
You need to clear interval once you satisfy the condition and move the if condition (note that 0 < i < 2 needs to be split into 2 conditions joined with && but here you can just do) with modification inside the function.
var interval = window.setInterval(animate, 500);
var i = 2;
function animate() {
if (i > 0) {
console.log('run');
i--;
console.log(i);
}
else{
window.clearInterval(interval);
}
}
Why don't you put if statement inside your animate function?
var i = 2;
function animate () {
if (i> 0 && i<2) {
alert('run');
i--;
console.log(i);
}
}
Edit:
1) you might want to use i>0 && i<2 rather than 0
2) Not sure if you do need to clear the interval after the condition is met. Would be better if you could elaborate a bit more about your requirements.
Alright guys, I'm trying to add numbers on my page every 1/4 second or so. So the change is visible to the user. I'm using setTimeout and all my calculations are occurring correctly but without any delay. Here's the code:
for(var i = 0; i < 10; i++)
{
setTimeout(addNum(i),250);
}
I've also tried capturing the return value:
for(var i = 0; i < 10; i++)
{
var t = setTimeout(addNum(i),250);
}
I've also tried using function syntax as part of the setTimeout params:
for(var i = 0; i < 10; i++)
{
var t = setTimeout(function(){array[j].innerHTML + 1},250);
}
I've also tried putting code in a string & the function call in a string. I can't ever get it to delay. Help Please!
How about:
var i=0;
function adder() {
if(i>=10) {return;}
addNum(i++);
setTimeout(adder,250);
}
adder();
When you did setTimeout(addNum(i),250); you executed the function straight away (function name followed by () will execute it right away and pass the return value to the timeout to be executed 1/4 second later). So in a loop that would just execute all 10 immediately. Which is what you saw.
Capturing the return value var t = setTimeout(...); is helpful, but not in your use case; the value is the timer id number, used for cancelling the timeout.
Not sure what your last attempt is, although presumably it's the function body of your addNum routine, so the same logic applies as above.
Perhaps instead, since you're running the same method multiple times, you should use the setInterval method instead? Here's an example of how you might do that.
Try setTimeout("addNum(" + i + ")", 250); the reason its not working is because its evaluating the parameter and executing it and changing it to something like setTimeout(result of addNum(i), 250);
So I thought that the following code would be really simple but has become a big headache. It should be a loop that will change the opacity of and object so that it fades away.
function doSomething()
{
var i = 10;
for(i = 10; i >=0; i = i - 1)
{
setTimeout("setOpacity('t1',"+ i +")", 100*i);
WRITE 1
}
}
function setOpacity(elem, hmm)
{
WRITE 2
document.getElementById(elem).style.opacity = (10 - hmm)/10;
document.getElementById(elem).style.filter = 'alpha(opacity=' + (10 - hmm)*10 + ')';
}
So the problem is that the for loop is counting down from 10 to 0 and this has been confirmed by a print statement located at WRITE 1. However in the setOpacity method the numbers being received are starting at 0 and counting to 10 and this has been confirmed by a print statement at WRITE 2.
I would like to know why this is happening and how I can fix it. I believe it has something to do with the setTimeout call executing the method call after the end of the loop, but if that is so then why are the values being passed to setOpacity incrementing?
Any help is much appreciated.
The values being passed to setOpacity are increasing because you are passing different timeouts. The result of your loop is essentially the following:
setTimeout("setOpacity('t1', '10')", 1000)
setTimeout("setOpacity('t1', '9')", 900)
setTimeout("setOpacity('t1', '8')", 800)
....
setTimeout("setOpacity('t1', '0')", 0)
The result is that they are called in reverse order based on the timings. So the last call gets executed in 0ms (after the function finishes), resulting in 0 as hmm, followed by 1, 2, 3 ...
To fix this you need to change 100*i to 100 * (10 - i)