Why do I get the error "Too much recursion"? - javascript

I'm working on a small project here and I get this message "too much recursion", when obviously there's not that much.
This is the relevant HTML code
<div id="speed">
<label for="spe">Input speed</label>
<input type="text" id="spe" onkeydown="if (event.keyCode == 13){ javascript:CalcBySpeed(); return false; }" />
<input type="button" name="Sumbit" value="Submit" onclick="javascript:CalcBySpeed()" />
</div>
and a table, generally looking like this:
<tr>
<td id="50">
<p id="117">5</p>
</td>
<td id="51">
<p id="118">20</p>
</td>
<td id="52">
<p id="119">5</p>
</td>
<td id="53">
<p id="120">1,2</p>
</td>
</tr>
And my JavaScript functions are:
function CalcBySpeed() {
var input = "a";
input = parseFloat(document.getElementById("spe").value) * 100;
if (input < 5089) {
getValueBySpeed(input - 3);
} else {
alert("Value undefined!");
}
};
function getValueBySpeed(input) {
if (document.getElementById(input) != null) {
document.getElementById(input).style.backgroundColor = "yellow";
document.getElementById(input + 1).style.backgroundColor = "yellow";
document.getElementById(input + 2).style.backgroundColor = "yellow";
document.getElementById(input + 3).style.backgroundColor = "yellow";
document.getElementById("res1").innerHTML = document.getElementById(input + 3).innerHTML;
document.getElementById("res2").innerHTML = document.getElementById(input + 2).innerHTML;
document.getElementById("res3").innerHTML = document.getElementById(input + 1).innerHTML;
document.getElementById("res4").innerHTML = document.getElementById(input).innerHTML;
} else {
getValueBySpeed(input++);
}
}
So if I decide to input in my input field:
1.2, js highlights this particular row successfully
1.19 js highlights the very same row successfully
0.97 js highlights the same row successfully
However when I input:
1.1 it logs in the console too much recursion
I believe when I input 0.97 there is much more recursion, still the problem is when I input numbers between 1.09 and 1.16.
Outside this range there seems to be no problem.

when obviously there's not that much.
obviously there is ;)
There is probably a mistake in your code:
function getValueBySpeed(input) {
if (document.getElementById(input) != null) {
...
}
else {
getValueBySpeed(input++);
}
}
If document.getElementById(input) != null is false it will likely stay false and the function getValueBySpeed will be called until you get the recursion error.
As a minor note: I don't understand what getValueBySpeed does, the name is weird, the arguments are weird, the implementation is weird.
I would expect perhaps (based on the name):
function getValueBySpeed(speed) {
var value;
value = // get value somehow
return value;
}

The postfix increment returns the original value, so you are calling your function repeatedly with the same value. That said, you don't need recursion, use a loop. Here is a rough attempt, but your code made little sense to me, so I may have gotten it wrong...
function CalcBySpeed()
{
var input = "a";
input = parseFloat(document.getElementById("spe").value)*100;
if (input < 5089) {
getValueBySpeed(input-3);
} else {
alert("Value undefined!");
}
};
function getValueBySpeed(input) {
while (document.getElementById(input) == null)
input++;
document.getElementById(input).style.backgroundColor = "yellow";
document.getElementById(input + 1).style.backgroundColor = "yellow";
document.getElementById(input + 2).style.backgroundColor = "yellow";
document.getElementById(input + 3).style.backgroundColor = "yellow";
document.getElementById("res1").innerHTML = document.getElementById(input + 3).innerHTML;
document.getElementById("res2").innerHTML = document.getElementById(input + 2).innerHTML;
document.getElementById("res3").innerHTML = document.getElementById(input + 1).innerHTML;
document.getElementById("res4").innerHTML = document.getElementById(input).innerHTML;
}

This is a rounding problem. 1.1 * 100 = 110.00000000000001. Then when you're adding 1 for each call the number will never be an integer. An element with the id xxxx.00000000000001 will never be found. 
The root of the problem is that 1.1 cannot be represented accurately with double precision floating point numbers.
The solution is the convert the number to an integer. I.e disregard the decimal value.

Related

Page doesn't load when I set variable to 0 in Javascript

var randomNumber = Math.floor(Math.random() * 6);
var attempts = 0
var maximum = 3
while (attempts < maximum){
document.getElementById("submit").onclick = function() {
attempts += 1;
if (document.getElementById("input").value == randomNumber) {
alert("You chose the right number");
} else {
alert("WRONG Number! You have " + attempts + " attempts.");
}
}
}
<input type="text" id="input">
<button id="submit">Submit</button>
while learning how to use a random number generator, I wantd to add a while loop and give 3 attempts to choose from a random number.
When I create a variable to set the number of attempts, if I make the variable equal to 0, my page doesn't load, but if I leave the variable empty without a value, the script doesn't run.
Any ideas of why this may be happening?
var randomNumber = Math.floor(Math.random() * 6);
var x = 0
var maximum = 3
while (x < maximum){
document.getElementById("submit").onclick = function() {
attempts += 1;
if (document.getElementById("input").value == randomNumber) {
alert("You chose the right number");
} else {
alert("WRONG Number! You have " + attempts + " attempts.");
}
}
}
<input type="text" id="input">
<button id="submit">Submit</button>
Your while loop runs synchronously, during pageload. The script never finishes, because the while loop's condition is never negated, so control is never yielded back to the browser to repaint the page, so the user never has a chance to input a number or click on the button.
While you could keep using while by promisifying the onclick and awaiting a Promise, it'd be better to create the handler outside, once, and have it check if the attempts are maxed out.
You also need to use consistent variable names: either use x or attempts, not both:
var randomNumber = Math.floor(Math.random() * 6);
var attempts = 0
var maximum = 3
document.getElementById("submit").onclick = function() {
if (attempts >= maximum) return;
attempts += 1;
if (document.getElementById("input").value == randomNumber) {
alert("You chose the right number");
} else {
alert("WRONG Number! You have " + attempts + " attempts.");
}
}
<input type="text" id="input">
<button id="submit">Submit</button>
You could disable the button after the maximum number of attempts has been reached, like:
var randomNumber = Math.floor(Math.random() * 6);
var attempts = 0;
var maximum = 3;
document.getElementById("submit").onclick = function(e) {
attempts += 1;
if (document.getElementById("input").value == randomNumber) {
alert("You chose the right number");
} else {
alert("WRONG Number! You have " + attempts + " attempts.");
}
if (attempts === maximum) e.target.disabled = true;
};
<input type="text" id="input" />
<button id="submit">Submit</button>

Javascript - need help to understand why the while loop isn't working

I'm probably going to ask a stupid question, but I really need a definitive verdict on this.
I've got 2 while loops.
Code 1:
document.getElementById("guess").onclick = function() {
var myNumber = document.getElementById("myNumber").value;
var gotIt = false;
var numberOfGuesses = 1;
while (gotIt == false) {
var guess = Math.random();
guess = guess * 6;
guess = Math.floor(guess);
if (guess == myNumber) {
gotIt = true;
alert("Got it! It was a " + guess + ". It took me " + numberOfGuesses + " guesses.");
} else {
numberOfGuesses++;
}
}
}
<input type="text" name="" id="myNumber">
<button id="guess">Guess!</button>
Code 2:
document.getElementById("guess").onclick = function() {
var myNumber = document.getElementById("myNumber").value;
var gotIt = false;
var numberOfGuesses = 1;
while (gotIt == false) {
var guess = Math.random();
guess = guess * 6;
guess = Math.floor(guess);
if (guess == myNumber) {
gotIt = true;
alert("Got it! It was a " + guess + ". It took me " + numberOfGuesses + " guesses.");
} else {
numberOfGuesses++;
}
}
}
<select id="myNumber">
<option>0</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
<button id="guess">Guess!</button>
The 2nd piece works fine; the 1st crashes the browser. My idea is the 1st one is taking too many loops to guess, but I can't quite work out why this is happening.
Thanks to anyone willing to explain.
Basically both approaches work just fine. You just have a little logical error in your first implementation.
The reason you have number one hanging is because you don't limit the user to input numbers in the range of 0-5. Therefore any number out of that range will loop forever as it will never result in a number of the 0-5 range, which you have restricted to when multiplying the random by 6.
Bottom line:
Either go with option 2, or validate that the user actually typed a number in the range of 0-5.

Javascript incrementing by more than one

var x1 = document.getElementById("x1");
var x2 = document.getElementById("x2");
function ThisEvent(){// needs a lot of work done to it
if (x1.value==1) {
x2.value--;
} else if (x1.value==2) {
x2.value++;
} else if (x1.value==3) {
x2.value+=5;
}
}
<input type="text" value="0" id="x1" onblur="ThisEvent()"> x1 </br>
<input type="text" value="0" id="x2"> x2
what is happening now is the digit is being added instead of incrementing when 3 is the input if x1. how do you make it increment by more than just one, without it being added it as a digit?
if (x1.value == 3) {
x2.value = parseInt(x2.value) + 5;
}
It's interpreting it as a string. You can parseInt the x2.value in the calculation.
The value of the input is a String, you need to convert it to a Number in order to perfom an addition on it.
You could do it like this:
function ThisEvent() { // needs a lot of work done to it
var valX1 = Number(x1.value);
var valX2 = Number(x2.value);
if (valX1 == 1) {
valX2--;
} else {
if (valX1 == 2) {
valX2++;
} else {
if (valX1 == 3) {
valX2 += 5;
}
}
}
x2.value = valX2;
}
jsFiddle: https://jsfiddle.net/v1utqv7f/

Problems with Javascript Game

I'm working on what should be an extremely simple "guess my number" game in Javascript, however, I can't get it to work correctly.
The program is supposed to choose a random integer between 1 and 10 and allow the user to try and guess that number as many times as it takes to get it right. If the user guesses a number that's lower than the correct one, the program is supposed to display a "your guess is too low" message, this is the same for when the guess is too high, or correct. The program must display the message on the webpage, not in an alert or any type of pop-up. Also, the program is supposed to keep a running list of the numbers that have been guessed by the user and display them on the page each time the user makes a guess (I want this list to display below my heading "Here are the numbers you've guessed so far:"). And finally, the program is supposed to display a "you already tried using that number" message if the user tries to input a number that they've already used.
Here is my code, along with a JSfiddle I've created and am still playing with.
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>Guess My Number</title>
<script type = "text/javascript">
var tries = [];
game = {
num : 0,
turns : 1,
reset : function() {
this.turns = 1;
this.newNum();
},
newNum : function() {
this.num = parseInt(Math.random(), 10) + 1;
},
guessNumber : function(guess) {
try {
guess = parseInt(guess, 10);
}
catch (e) {
document.getElementById("guess").value = "Enter a guess.";
this.turns++;
return false;
}
if (guess == this.num) {
document.getElementById("result").value = "Correct! It took you " + this.turns + " tries to guess my number.";
tries.push(document.getElementById("guess").value);
display();
document.getElementById("guess").value = " ";
return true;
}
else if(guess > this.num) {
document.getElementById("result").value = "Your guess is too high. Try again.";
tries.push(document.getElementById("guess").value;
display();
document.getElementById("guess").value = " ";
return false;
}
else if(tries.indexOf(guess) != -1 {
document.getElementById("result").value = "You have already guessed that number. Try again.";
document.getElementById("guess").value = " ";
return false;
}
else {
document.getElementById("result").value = "Your guess is too low. Try again.";
tries.push(document.getElementById("guess").value;
display();
document.getElementById("guess").value = " ";
return false;
}
}
function display() {
var number = ";
for(i=0; i<tries.length; i++) {
number += tries[i] + "<br >";
}
document.getElementById("tries").innerHTML = number;
}
function guessNumber() {
var guess = document.getElementById("guess").value;
game.guessNumber(guess);
document.getElementById("guess").value = " ";
}
function resetGame() {
game.reset();
document.getElementById("guess").value = " ";
}
resetGame();
}
</script>
</head>
<body>
<h1>Would You Like To Play A Game?</h1>
<h3>Directions:</h3>
<p>
The game is very simple. I am thinking of a non-decimal number between 1 and 10, it is your job to guess what that number is. If you guess incorrectly on your first attempt, don't worry. You can keep guessing until you guess my number.
</p>
<h3>Thanks for playing and good luck!</h3>
<h3>Created by Beth Tanner</h3>
<p>Your Guess:
<input type = "text" id = "guess" size = "10" />
<br />
<input type = "button" value = "Submit Guess" onclick = "guessNumber()" onclick = "display()" />
<input type = "reset" value = "Reset Game" onclick = "resetGame()" />
</p>
<h3>How'd you do?</h3>
<div id = "result">
<input type = "text" id = "result" size = "20" />
</div>
<h3>Here are the numbers you've guessed so far:</h3>
</body>
</html>
http://jsfiddle.net/v09ttL74/
As you should be able to see from the fiddle, nothing is happening when I click either one of the buttons, so I'm not really sure where the problem is. I am getting a few errors when I select the JShints option on the fiddle, but most are things like "Missing semicolon" in places where there's not supposed to be a semicolon, like an one line where all I have written is
else {
Any suggestions would be greatly appreciated. I feel like this is just a really simple project that I am over-thinking since I'm stressed about it not working.
There's a lot of issues in your code. Just to mention a few...
1- Unclosed parenthesis here
tries.push(document.getElementById("guess").value;
it should be...
tries.push(document.getElementById("guess").value);
2- Expression not terminated with a close parenthesis here
else if(tries.indexOf(guess) != -1 {
it should be...
else if(tries.indexOf(guess) != -1) {
3- Wrong declaration of functions inside a function
function display() {
var number = ";
for(i=0; i<tries.length; i++) {
number += tries[i] + "<br >";
}
document.getElementById("tries").innerHTML = number;
}
function guessNumber() {
var guess = document.getElementById("guess").value;
game.guessNumber(guess);
document.getElementById("guess").value = " ";
}
function resetGame() {
game.reset();
document.getElementById("guess").value = " ";
}
I could be going forever but, really, the errors are a bit obvious
Alright as some of the answers must have already given you an idea of how many mistakes your Script as well as HTML code had.. from missing parenthesis to same ids to missing elements. Well i have corrected them and it's working now:
<h1>Would You Like To Play A Game?</h1>
<h3>Directions:</h3>
<p>
The game is very simple. I am thinking of a non-decimal number between 1 and 10, it is your job to guess what that number is. If you guess incorrectly on your first attempt, don't worry. You can keep guessing until you guess my number.
</p>
<h3>Thanks for playing and good luck!</h3>
<h3>Created by Beth Tanner</h3>
<p>Your Guess:
<input type = "text" id = "guess" size = "10" />
<br />
<input type = "button" value = "Submit Guess" onclick = "guessNumber()" onclick = "display()" />
<input type = "reset" value = "Reset Game" onclick = "resetGame()" />
</p>
<h3>How'd you do?</h3>
<input type = "text" id = "result" size = "20" />
<h3>Here are the numbers you've guessed so far:</h3>
<p id='tries'></p>
Script:
var tries = [];
game = {
num : 0,
turns : 1,
reset : function() {
this.turns = 1;
this.newNum();
},
newNum : function() {
this.num = parseInt(Math.random() * 10) + 1;
},
guessNumber : function(guess) {
try {
guess = parseInt(guess, 10);
}
catch (e) {
document.getElementById("guess").value = "Enter a guess.";
this.turns++;
return false;
}
alert(guess+ ' '+this.num);
if (guess == this.num) {
document.getElementById("result").value = "Correct! It took you " + this.turns + " tries to guess my number.";
tries.push(document.getElementById("guess").value);
display();
document.getElementById("guess").value = " ";
return true;
}
else if(tries.indexOf(guess) != -1) {
document.getElementById("result").value = "You have already guessed that number. Try again.";
document.getElementById("guess").value = " ";
return false;
}
else if(guess > this.num) {
document.getElementById("result").value = "Your guess is too high. Try again.";
tries.push(document.getElementById("guess").value);
display();
document.getElementById("guess").value = " ";
return false;
}
else if(guess < this.num){
document.getElementById("result").value = "Your guess is too low. Try again.";
tries.push(document.getElementById("guess").value);
display();
document.getElementById("guess").value = " ";
return false;
}
}
}
function display() {
var number = "";
for(i=0; i<tries.length; i++) {
number += tries[i] + "<br >";
}
document.getElementById("tries").innerHTML = number;
}
function guessNumber() {
var guess = document.getElementById("guess").value;
game.guessNumber(guess);
document.getElementById("guess").value = " ";
}
function resetGame() {
game.reset();
document.getElementById("guess").value = " ";
}
resetGame();
See the DEMO here

Using DOM for first time to change color of unanswered questions in form onSubmit

Here is my form:
<form id="Test" action="index.php?course=4" method="post" name="Test" onSubmit="IsFormComplete(12)">
Inside the form is a table dynamically generated with id=Qx class=Qx where x is 1 through 12:
<tr id="Q2" class="Q2">
<td width="5%">2) </td>
<td colspan="2">According to the Institute of Medicine study the number of deaths from medical errors per year is between</td>
Here is my javascript function:
function IsFormComplete(iQuestions) {
var questionNum = iQuestions;
itemOkay=true;
for (var i=1;i<questionNum;i++) {
for (var j=0;j<4;j++) {
var thisItem = eval("document.Test.Q" + i + "[" + j + "].checked");
if (!thisItem) {
itemOkay = false;
document.getElementById(eval("Q" + i)).style.color = "red";
}
}
}
alert("item okay = " + itemOkay);
if (itemOkay) {
return true;
} else {
return false;
}
}
Not working PLEASE help. New to DOM and have tried various tags:
document.getElementById(eval("Q" + i)).style.color = "red";
document.Test.getElementById(eval("Q" + i)).style.color = "red";
document.getElementById("Q1").style.color = "red"; //To try literal instead of variable
etc.
You don't need the eval. getElementById uses a string. Try this:
document.getElementById("Q"+i).style.color = "red";

Categories

Resources