Issue with an infinite loop? - javascript

I'm having some issues with an accidental infinite loop. I've just been starting with javascript, and so I've been trying to make a simple game as practice. I keep getting an infinite loop, and I can't tell why. I'm fairly sure it's not a syntax error, since the console isn't telling me about any. Here's the code where the problems are happening:
HTML:
<input id="lemonadePrice" class="buytextbox" placeholder="Lemonade price">
<input class="submit" onclick="begin();" type="submit" value="Begin!">
JavaScript:
while (isNaN(lemonadePrice)) {
document.getElementById("introduction").innerHTML="Uh-oh! Your lemonade price is not a
number!Please remove any words or symbols like '$'.";
lemonadePrice = document.getElementById("lemonadePrice");
}
Here's a link to the full code: jsfiddle

This might be because of your while() loop. What might be happening is that the while loop goes on infinitely while this isNAN(lemonadePrice) returns true, and this is what happens in your case, given that you say it runs infinitely.
You can try using an if(). Since .getElementById of "lemonadePrice" will not be returning a number, the isNAN() would be evaluating to true all the time. isNAN() simply means "is not a number". If you think for a second, you know where the bug is.
I think you are looking to get the value of "lemonadePrice", so instead of just getting the element, you should also consider pulling in the value that lies inside it. I do not see this in your code but it would simply be this DOM: var value = document.getElementById(id).value;

I think you want an if instead of while
The definition while taken from wikipedia
In most computer programming languages, a while loop is a control flow
statement that allows code to be executed repeatedly based on a given
boolean condition. The while loop can be thought of as a repeating if
statement.
It means while loop will repeat under condition that inside the brackets. In this case, what you need is a conditional statement (if())
If will be executed only once. While will be executed repeatedly until the condition is false. In your case, the condition will be always true. That is why you ended up in infinite loop.
See code below
if (isNaN(lemonadePrice)) {
document.getElementById("introduction").innerHTML="Uh-oh! Your lemonade price is not a
number!Please remove any words or symbols like '$'.";
lemonadePrice = document.getElementById("lemonadePrice");
}

If we assume begin() is basically this:
function begin(){
var lemonadePrice = document.getElementById("lemonadePrice");
while (isNaN(lemonadePrice)) {
document.getElementById("introduction").innerHTML="Uh-oh! Your lemonade price is not a number!Please remove any words or symbols like '$'.";
lemonadePrice = document.getElementById("lemonadePrice");
}
}
then your loop will never have a chance to exit, since lemonadePrice is always set to the "value" of the lemonadePrice DOM element; that means lemonadePrice will always be NaN, so the loop is infinite. Like others have already mentioned, you need to use an if() statment instead of a loop, and remove the last line. You also want to look at the value of the element:
function begin(){
var lemonadePrice = document.getElementById("lemonadePrice").value;
if(isNaN(lemonadePrice)) {
document.getElementById("introduction").innerHTML="Uh-oh! Your lemonade price is not a number!Please remove any words or symbols like '$'.";
}
}

You better use onsubmit and prevent form submit if not valid.
Its also better to use regular expression to check if its valid float number.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form action="yourfile.php" method="post" onsubmit="validate();">
<input id="lemonadePrice" class="buytextbox" placeholder="Lemonade price" /> <span id="lemonade_error"></span>
<br>
<input class="submit" type="submit" value="Begin!" />
</form>
<script type='text/javascript'>//<![CDATA[
function validate() {
var lemonade_price = document.getElementById("lemonadePrice").value;
if (lemonade_price.match(/\d+\.*\d*/i)){
document.getElementById("lemonade_error").innerHTML = "Not valid.";
if (event.preventDefault){
event.preventDefault();
} else {
event.returnValue = false; // for IE as dont support preventDefault;
}
return false;
}
return true;
}
//]]>
</script>
</body>
</html>
Code here : http://jsfiddle.net/Pxuey/5/

Related

Regex.test(value) returns true when logged but false within an if statement

I'm noticing something weird with my code. I have a regex to check UK postcodes, it uses capture groups and works fine unless within an if statement. The code to test is within a validator class which is passed an HTML node list with all fields from a form.
For example, when I use it within the pattern tag on the HTML input field it acts as you would expect. As it does when I console.log(regex.test(field.value)). However, when I put it into an if statement it seems to fail every time.
The regex is as follows:
/\b([a-zA-Z]{1,2}[0-9]{1,2}[a-zA-Z]?){1}( |-)?([0-9]{1,2}[a-zA-Z]{1,2}){1}\b/
The input field is as follows:
<input required pattern="\b([a-zA-Z]{1,2}[0-9]{1,2}[a-zA-Z]?){1}( |-)?([0-9]{1,2}[a-zA-Z]{1,2}){1}\b" inputmode="text" class="form-field" type="text" name="postcode" id="contactPostcode" placeholder="Postcode eg NW2 8BZ" />
The code to test it is as follows:
validate(fields)
// ... omitted ... //
let errors = [];
const postcodeRegex = /\b([a-zA-Z]{1,2}[0-9]{1,2}[a-zA-Z]?){1}( |-)?([0-9]{1,2}[a-zA-Z]{1,2}){1}\b/;
postcodeRegex.lastIndex = 0;
for (let field of fields) {
if(field.name === 'postcode') {
console.log(postcodeRegex.test(field.value))
if(!postcodeRegex.test(field.value)) {
errors.push({
field: field.getAttribute('name'),
error: 'Illegal character detected'
});
continue;
}
}
}
The console.log check returns true however the if statement check returns false every time and I don't understand why the two identical checks would output different results, does anyone have any advice? I am guessing something is going over my head here.
Thanks
Edit for clarification: The console log's true but the if statement is still being executed
As per documentation
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
As with exec() (or in combination with it), test() called multiple times on the same global regular expression instance will advance past the previous
So this is why the second time you get false.
Try this:
var res = postcodeRegex.test(field.value);
console.log(res)
if(!res) {

if statements in for loop both executing instead of just one

First If statement works just fine, then it goes into the for loop as expected BUT THEN OUT OF NOWHERE, it decides to execute both if statements (which they are contradictory of each other "==" and "!=")..I don't understand :(
if($scope.firstinitial==$scope.firstinput&&$scope.secondinitial==$scope.secondinput){
$scope.initialmatches="MATCHES THE INITIALS";
for (var i=0; i<$scope.discountcodes.length; i++) {
console.log($scope.discountcodes[i]);
if($rootScope.discountcodeinput.attempt.toLowerCase()!=$scope.discountcodes[i]){
$scope.changeBack();//DOES ONLY IF INPUT DOES NOT MATCH DATA
}
if($rootScope.discountcodeinput.attempt.toLowerCase()==$scope.discountcodes[i]){
console.log($scope.discountcodes[i]);//DOES ONLY IF INPUT MATCHES DATA
$scope.changeBackAgain();
}
}
}
UPDATE:
After bug testing, only the last discount code when matched works correctly...which boggles my mind even further. So when the user types in the discount code which matches the last discount code in the array, then only the first if statement triggers and not the second one. Any ideas?
I think whatever is happening inside $scope.changeBack(); is making the second condition true
If $scope.changeBack(); does something to modify discountcodes[i] or $rootScope.discountcodeinput.attempt it is possible for the second if statement to execute. What you probably mean to do is:
for (var i=0; i<$scope.discountcodes.length; i++) {
if($rootScope.discountcodeinput.attempt.toLowerCase()!=$scope.discountcodes[i]){
$scope.changeBack();//DOES ONLY IF INPUT DOES NOT MATCH DATA
}
else {
$scope.changeBackAgain();
}
}
Apparently using the == operator can have very unexpected results due to the type-coercion internally, so using === is always the recommended
also add an else statement in there if you don't need both of them executing.
Other than that I would say that something is changing, I would step through it in the debug window and see what the current results are for each variable or print them to the console.
if($scope.firstinitial==$scope.firstinput&&$scope.secondinitial==$scope.secondinput){
$scope.initialmatches="MATCHES THE INITIALS";
for (var i=0; i<$scope.discountcodes.length; i++) {
console.log($scope.discountcodes[i]);
if($rootScope.discountcodeinput.attempt.toLowerCase()!==$scope.discountcodes[i]){
$scope.changeBack();//DOES ONLY IF INPUT DOES NOT MATCH DATA
}
else if($rootScope.discountcodeinput.attempt.toLowerCase()===$scope.discountcodes[i]){
console.log($scope.discountcodes[i]);//DOES ONLY IF INPUT MATCHES DATA
$scope.changeBackAgain();
}
}
}
Trying using the else if statement to run one code then the other
<script>
if($scope.firstinitial==$scope.firstinput&&$scope.secondinitial==$scope.secondinput){
$scope.initialmatches="MATCHES THE INITIALS";
for (var i=0; i<$scope.discountcodes.length; i++) {
console.log($scope.discountcodes[i]);
if($rootScope.discountcodeinput.attempt.toLowerCase()==$scope.discountcodes[i]){
console.log($scope.discountcodes[i]);//DOES ONLY IF INPUT MATCHES DATA
$scope.changeBackAgain();
} else if($rootScope.discountcodeinput.attempt.toLowerCase()!=$scope.discountcodes[i]){
$scope.changeBack();
}
}
}
</script>
Obviously ($rootScope.discountcodeinput.attempt.toLowerCase()!=$scope.discountcodes[i] and ($rootScope.discountcodeinput.attempt.toLowerCase()==$scope.discountcodes[i] can not be true at the same time. So I guess you are doing some magic inside $scope.changeBack() that changes the value of either $rootScope.discountcodeinput.attempt or $scope.discountcodes[i], so when the second if gets checked, the value has already changed and the condition passes.
I would suggest breaking out of the iteration as soon as you know you are done, by adding a continue statement. Something like this:
for (var i = 0; i < $scope.discountcodes.length; i++) {
console.log($scope.discountcodes[i]);
if ($rootScope.discountcodeinput.attempt.toLowerCase() != $scope.discountcodes[i]) {
$scope.changeBack(); //DOES ONLY IF INPUT DOES NOT MATCH DATA
continue; // done
}
// no need to check again
console.log($scope.discountcodes[i]); //DOES ONLY IF INPUT MATCHES DATA
$scope.changeBackAgain();
}
I figured it out...
Essentially the for loop was going through and checking both if statements with each object, if the first object matched it would trigger the first if statement and not the second. BUT then the for loop would continue and look at the next object in the array and only trigger the second if statement...then it would loop through with the third object in the array and again only trigger the second if statement...so on and so on.
The workaround I came up with was just embedding both into another if statement that checked for a var value of yes
if($scope.value=="no")
then I placed the not equal if statement (!=) first and the equal if statement (==) second. Finally, I added in the (==) if statement:
$scope.value="yes";
thus avoiding going through the parent if statement on every loop of the for loop.
Thanks everyone for the help...this was killing me!

How to select and set multiple textboxes text in jquery

Please I have my Jquery code that I want to do few things since. I have a form with a bunch of textboxes. I want to validate each textbox to allow numbers only. To also display error where not number.
var validateForm = function(frm){
var isValid = true;
resetError();
$(":text").each(function(variable){
console.log("The variable is" , variable);
if(!isNormalInteger(variable.val))
{
$("#error"+variable.id).text("Please enter an integer value");
isValid = false;
}
});
if(!isValid)
return false;
};
The above fails. When I print the variable on my console I was getting numbers 0 - 9. My textboxes where empty yet, it returns numbers. I tried variable.val() still fails and return numbers. I modified my select to
$("input[type=text]", frm).each();
Where my form is my form selected by id. It also failed. Below is the example of my html label and textbox. I have about ten of them
<div class="grid-grid-8">
<input class=" text" id="id" name="name" type="text">
<br>
<p class="hint">Once this limit is reached, you may no longer deposit.</p>
<p class="errorfield" id="errorMAXCASHBAL"></p>
Please how do I select them properly? Moreover, my reset function above also returns incrementing integers for value. The p property is of class errorField and I want to set the text property. Please how do I achieve this? Previously I tried the class name only $(.errorField). It also failed. Any help would be appreciated.
var resetError = function(){
//reset error to empty
$("p errorfield").each(function(value){
console.log("the val", value);
//value.text() = '';
});
};
//filter non integer/numbers
function isNormalInteger(str) {
return /^\+?\d+$/.test(str);
}
The main problem is your selectors in javascript. And as laszlokiss88 stated wrong usage of .each() function.
Here is a working example of your code: jsFiddle in this example all .each() functions use $(this) selector inside instead of index and value
You are using .each wrong because the first parameter is the index and the second is the element. Check the documentation.
Moreover, the correct selector for the resetError is: p.errorfield
So, you should modify your code to look something like this:
var resetError = function(){
$("p.errorfield").each(function (idx, element) {
$(element).text("");
});
};
With this, I believe you can fix the upper function as well. ;)

Javascript Confirm with action?

wording this question was hard, but here i go. ok, i am using code from this site:
http://www.switchonthecode.com/tutorials/javascript-tutorial-getting-user-input-with-prompt-and-confirm
<script type="text/javascript">
function confirmInput()
{
var ans = confirm("Install a virus and delete all your files?");
alert(ans ? document.getElementById('level').value = "0";
: "If no, do nothing");
}
</script>
<input type="button" onclick="confirmInput()" value="Show me the Question!" />
I have even tried to replace the Text for the answer with the actions, but i get nothing.
How do i add a action to the answer, so when it is yes, i do something, and when no i do not.
I think this is what you are looking for:
function confirmInput()
{
if(confirm("Install a virus and delete all your files?"))
document.getElementById('level').value = "0";
}
there is a syntax error in your code here:
alert(ans ? document.getElementById('level').value = "0"; // this semicolon is invalid
: "If no, do nothing");
It executes till this semicolon and that terminates. Check your console, there should be an error message.
Another thing is that ?: operator can only return a value. It shouldn't contain operations, only values or function, which returns the value.

Javascript not working in firefox

I have a PHP form validation function that I developed in chrome and now will not work in firefox or Opera.
The function checks to see if a section of the form is blank and shows and error message. If there is no error then then the form submits through document.events.submit();
CODE:
function submit_events()
{
//Check to see if a number is entered if the corosponding textbox is checked
if (document.events.dj_card.checked == true && dj_amount.value==""){
//Error Control Method
//alert ('You didn\'t enetr an Amount for DJ\'s Card!');
var txt=document.getElementById("error")
txt.innerHTML="<p><font color=\"#FF0000\"> You didn\'t enetr an Amount for DJ\'s Card!</font></p>";
window.document.getElementById("dj_card_label").style.color = '#FF0000';
//Reset
window.document.getElementById("company_amount_label").style.color = '#000000';
window.document.getElementById("own_amount_label").style.color = '#000000';
}else{
document.events.submit();
}
The document.events.submit();does work across all my browsers however the check statements do not.
If the box is not ticked the form submits. If the box is ticked it does not matter whether there is data in the dj_amount.value or not. The form will not submit and no error messages are displayed.
Thanks guys.
Here are some things I noticed. Not sure if it will solve the problem, but you need to fix some of these; some of them are just observations.
dj_amount is not declared nor referenced; my guess is you mean documents.events.dj_amount
You should put a ; at the end of every statement in javascript, including the end of var txt = document.getElementById("error")
You don't need to escape the string in the txt.innerHTML line; you only need to escape like quotes, such as "\"" or '\'', not "'" or '"'
You don't need the window.document referenced; document will do in almost all cases
EDIT - As Guffa points out, FONT is an old and deprecated element in HTML. It's not the cause of your problems, but modern markup methods mean you don't need it. Consider omitting and applying the style to the paragraph tag instead.
See edits below.
function submit_events() {
//Check to see if a number is entered if the corosponding textbox is checked
if (document.events.dj_card.checked == true && document.events.dj_amount.value == "") {
//Error Control Method
//alert ('You didn't enetr an Amount for DJ\'s Card!');
var txt = document.getElementById("error");
txt.innerHTML = "<p style=\"color: #FF0000;\"> You didn't enter an Amount for DJ's Card!</p>";
document.getElementById("dj_card_label").style.color = '#FF0000';
//Reset
document.getElementById("company_amount_label").style.color = '#000000';
document.getElementById("own_amount_label").style.color = '#000000';
} else {
document.events.submit();
}
}
Consider Firebug so that you can see and log to console javascript errors and messages:
http://getfirebug.com
I believe one of the above answers would solve your problem. For future reference, although it might not be suitable for your project, please know that writing forms and javascript feedback is much easier and faster when you use a library like jQuery.
To have minimal changes in code, just add this line before the first if statement:
var dj_amount = document.forms["events"].elements["dj_amount"];
However your code need serious optimization let us know if you're interested.
Edit: here is the optimization. First the "small" things - instead of whatever you have now for "error" container, have only this instead:
<p id="error"></p>
Now add this CSS to your page:
<style type="text/css">
#error { color: #ff0000; }
</style>
This will take care of the red color, instead of hard coding this in the JS code you now control the color (and everything else) from within simple CSS. This is the correct approach.
Second, right now you are submitting the form as response to onclick event of ordinary button. Better approach (at least in my humble opinion) is having submit button then overriding the form onsubmit event, cancelling it if something is not valid. So, first you have to change the function name to be more proper then have proper code in the function. Cutting to the chase, here is the function:
function ValidateForm(oForm) {
//declare local variables:
var oCardCheckBox = oForm.elements["dj_card"];
var oAmoutTextBox = oForm.elements["dj_amount"];
//checkbox cheched?
if (oCardCheckBox.checked) {
//store value in local variable:
var strAmount = oAmoutTextBox.value;
//make sure not empty:
if (strAmount.length == 0) {
ErrorAndFocus("You didn't enter amount for DJ's Card!", oAmoutTextBox);
return false;
}
//make sure it's numeric and positive and not too big:
var nAmount = parseInt(strAmount, 10);
if (isNaN(nAmount) || nAmount < 1 || nAmount > 1000000) {
ErrorAndFocus("DJ's Card amount is invalid!", oAmoutTextBox);
return false;
}
}
//getting here means everything is fine and valid, continue submitting.
return true;
}
As you see, when something is wrong you return false otherwise you return true indicating the form can be submitted. To attach this to the form, have such form tag:
<form ... onsubmit="return ValidateForm(this);">
And instead of the current button have ordinary submit button:
<input type="submit" value="Send" />
The code will be called automatically.
Third, as you can see the function is now using "helper" function to show the error and focus the "misbehaving" element - this makes things much more simple when you want to validate other elements and show various messages. The function is:
function ErrorAndFocus(sMessage, element) {
var oErrorPanel = document.getElementById("error");
oErrorPanel.innerHTML = sMessage;
document.getElementById("dj_card_label").style.color = '#FF0000';
document.getElementById("company_amount_label").style.color = '#000000';
document.getElementById("own_amount_label").style.color = '#000000';
}
Last but not least, the "new" code also makes sure the amount is positive number in addition to check its existence - little addition that will prevent server side crash.
Everything else is pretty much self explanatory in the function: naming conventions, using local variables.... most important is have as little redundancy as possible and keep the code readable.
Hope at least some of this make sense, feel free to ask for clarifications. :)
You should bring up the error console so that you see what the error actually is.
Lacking that information, I can still make a guess. Try some less ancient HTML code; the parser can be picky about code you add to the page using innerHTML:
txt.innerHTML="<p style=\"color:#FF0000\"> You didn\'t enetr an Amount for DJ\'s Card!</p>";

Categories