Prevent Wrong Input in JS After Submitting A Form - javascript

I am creating a sample MabLibs type thing in HTML and JS. When the person inputs stuff in a field, it will use that to create their own MadLib.
I've done a little research and not finding exactly what I am looking for. Say a person puts 12 in the Name field. How would code that so if this instance does happen, it won't go through and alert "That is not a valid input. PLease type again!" or something along those lines.
The code I am using is below. I am very new to Javascript so I know the format and stuff might be wrong.
<html><head>
<title>
Mad Libs Story
</title>
<script>
function getVars() {
person1 = String(document.getElementById("personOne").value);
age = Number(document.getElementById("ageOne").value);
firstAdjective = String(document.getElementById("adjective").value);
document.getElementById("madLibCreation").innerHTML = "There once was a person named " + person1 + ". She was " + age + " and very " + firstAdjective = ".";
}
</script>
</head>
<body>
<h3>
Welcome to Mad Libs! Please type in the prompted Information. Then press the submit button. Have fun!
</h3>
<p>
Name of Person in Room: <input type="text" id="personOne">
</p>
<p>
Age: <input type="text" id="ageOne">
</p>
<p>
Adjective: <input type="text" id="adjective">
</p>
<input type="submit" value="Get My MadLib Creation!" onclick="getVars();">
<p id="madLibCreation"></p>
</body></html>

For that, you have to check Name field value is number or not. We can check the value is number or not using isNaN function. This function returns true or false.
isNaN(12) // falsee
isNaN(-4.5) // false
isNaN(15-3) // false
isNaN(0) // false
isNaN('123') // false
isNaN('Nuwan') // true
isNaN('2005/12/12') // true
isNaN() // true
So, in your code getVars() function change like this
function getVars() {
var name = document.getElementById("personOne").value;
if(!isNaN(name) && name.length != 0){
alert("That is not a valid input. PLease type again!");
}else{
person1 = String(document.getElementById("personOne").value);
age = Number(document.getElementById("ageOne").value);
firstAdjective = String(document.getElementById("adjective").value);
document.getElementById("madLibCreation").innerHTML = "There once was a person named " + person1 + ". She was " + age + " and very " + firstAdjective + ".";
}
}

https://www.w3.org/WAI/tutorials/forms/validation/
This link provides some useful information and example code around how you can do this with HTML5, providing the validations and required inputs to each input field.
By implementing these validations your form will not submit until the requirements are met.
Here are a few other ideas that may also help:
By using a
<form onsubmit="getVars()" name="MadLibs">
tag, your data will be wrapped inside the event, which can be accessed within your submit function. This will also reduce the effort to collect the data via element id’s.
const getVars = function(event) {
event.preventDefault(); // stop the page refresh on submit
const formData = event.target;
const personOne = formData.personOne;
...
}
Lastly by adding tags for each input, it will further increase the accessibility of the form:
https://www.w3.org/WAI/tutorials/forms/labels/
Hope this helps with your project.

So you want to prevent wrong information before submitting any thing. This can be achieved by some checks to the value entered into the fields. This can be done all at once on button click or while typing with an event handler on the field for keyup. You can further use setTimeout to check with a small delay.
If you check and set classes to elements which are faulty, you can check for them with a css selector.
const person1 = document.getElementById("personOne")
const age = document.getElementById("ageOne")
const firstAdjective = document.getElementById("adjective")
// use a function(){} block for the handler, it will bin this
person1.addEventListener(`keyup`, function(){
// use arrow function to not bind this so it will refer to the html node
// can be used to delay the evaluation
setTimeout(()=>{
// some regex... /regex/flags will create a new regex
// ^ is start, $ is end and [a-z]* is a to z 0 or more times
// flag i is case insensitive
const regEx = /^[a-z]+$/i
//
if(!regEx.test(person1.value)){
this.classList.add(`invalid`)
} else {
this.classList.remove(`invalid`)
}
},200)
})
function getVars() {
if(!document.querySelectorAll(`.invalid`)[0]){
document.getElementById("madLibCreation").innerText = `There once was a person named ${person1.value} she was ${age.value} and very ${firstAdjective.value}.`
} else {
alert(`fix your shit`)
}
}
.invalid{
color: red;
}
<html>
<head>
<title>
Mad Libs Story
</title>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
</head>
<body>
<h3>
Welcome to Mad Libs! Please type in the prompted Information. Then press the submit button. Have fun!
</h3>
<p>
Name of Person in Room: <input type="text" id="personOne">
</p>
<p>
Age: <input type="text" id="ageOne">
</p>
<p>
Adjective: <input type="text" id="adjective">
</p>
<input type="submit" value="Get My MadLib Creation!" onclick="getVars()">
<p id="madLibCreation"></p>
</body>
<script src="./main.js"></script>
</html>

Related

Unpredictable behavior in form validation with regular expressions

I'm completing some exercises from a javascript course (they are only meant for practice, I don't have to send my solutions) and when I'm trying to do a custom validation using regular expressions, capturing the submit event. The problem is that, if I enter an invalid input the first time, sometimes even if I correct it the custom validity message keeps showing up, and the console.log that show how many times the user tried to submit the form doesn't work, as if the submit event didn't even happen (for example: 1st input: "a", 2nd input: "aa", the custom validity message shows up and nothing can be loaded to the console, as if the submit event didn't even happen,but if I enter a valid input the first time, the error dissapears). I don't know if the way to solve this problem is to add an event listener for the blur event of the input and remove the custom validity there if necessary. A part of the code looks something like this (I added changes, the original one was simpler and had even more problems):
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example of form validation</title>
</head>
<body>
<form>
<fieldset>
<legend>Enter your user data</legend>
<div class="group">
<label for="name">Name</label>
<input id="name" type="text" placeholder="Example: John Doe">
</div>
</fieldset>
<button>Continue</button>
</form>
<script>
let form = document.querySelector("form")
let i = 0
form.addEventListener("submit", function(e){
i++
console.log(`You tried to submit this form ${i} times`)
e.preventDefault()
let input_name = document.querySelector("#name")
let value = input_name.value
let words = [value.split(" ")[0], value.split(" ")[1]]
let words_joined = words[1] ? words[0] + " " + words[1] : words[0] // this ugly conditional statement prevents the program from joining a string with an undefined value
let regex = /^\w{2,}(\s+\w{2,})*$/
let matches = words_joined.match(regex)?.length
try {
if(matches){
handleSuccess.call(input_name)
} else {
let err_msg = `You must enter 1 or 2 words with at least 2 characters each`
input_name.setCustomValidity(err_msg)
throw new Error(err_msg)
}
} catch (err){
handleError.call(form, err) /// I prefer to send to both handlers the apropiate "this"
}
})
function handleError(err){
console.log(err)
}
function handleSuccess(){
this.setCustomValidity(``)
this.classList.add(`success`)
console.log(`The input with the id "${this.id}" is valid`)
this.parentElement.parentElement.parentElement.submit() // submits the form
}
</script>
</body>
</html>```
If I remove the setCustomValidity() function everywhere, the problem dissapears, but that isn't very practical. At least it seems like that is the root of the problem.
Problem solved thanks to the help of Ivar. I made some changes to the original code (those are reflected on the original post, sorry for not posting them anywhere else), and added the following lines:
let value = input_name.value
let words = [value.split(" ")[0], value.split(" ")[1]]
let words_joined = words[1] ? words[0] + " " + words[1] : words[0] // this ugly conditional statement prevents the program from joining a string with an undefined value
// words_joined only contains the first 1 or 2 words
let regex = /^\w{2,}(\s+\w{2,})*$/
let matches = words_joined.match(regex)?.length
try {
if(matches){
value = words_joined // if there were more than 2 words, only the first 2 remain in the value of the input with the id "name"
handleSuccess.call(input_name, "don't submit")
} else {
let err_msg = `You must enter 1 or 2 words with at least 2 characters each`
input_name.setCustomValidity(err_msg)
throw new Error(err_msg)
}
} catch (err){
handleError.call(form, err) /// I prefer to send to both handlers the apropiate "this"
}
})
function handleError(err){
console.log(err)
}
function handleSuccess(shouldSubmit){
this.setCustomValidity(``)
this.classList.add(`success`)
console.log(`The input with the id "${this.id}" is valid`)
if(shouldSubmit != "don't submit") this.parentElement.parentElement.parentElement.submit() // submits the form
}```
the last two functions are almost equal to the ones written in the original question, but with the addition of the "shouldSubmit" parameter and a conditional statement for the last one. Basically, the unpredictability of the error seems to have been caused by how regular expressions with the "g" flag work in js, and it was solved by assigning the return value of the match() function to a variable and using that variable on the rest of the scope. And the main problem, that error showing up even after correcting an invalid input, was ocurring because the custom validity was showing up between submits. Now that an event listener for the "change" event of the input is added, this is corrected. Thanks for the help!

Js logic in html,js, and css basic username and password script

I am trying to make a basic username and password login using HTML, JS, and CSS. I've looked at a few examples for help and can't seem to find anything.
I'm very new at this stuff so it might not be perfect. here is the HTML
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="reee">
<h1 id = "dad"> Login </h1>
</div>
<div class = "yes">
<div id = "action">
<form action="after sub/after.html">
</div>
<label class = "u" for="fname">Username</label>
<input type="text" id="uname" name="user" placeholder="Your username...">
<label class = "p" for="lname">Password</label>
<input type="text" id="pass" name="pass" placeholder="Your password...">
<script src = "script.js"></script>
<input type="submit" value="Submit" id = "loginto" onclick='reee()'><p class = "wrong" id =
"wrong"> </p>
</form>
</div>
</body>
</html>
It seems a little chaotic and messy and I'm trying to work on that but that's not the point.
Here is the JS.
function reee() {
var user = document.getElementById("uname").value;
var pass = document.getElementById("pass").value;
var usernames = [
["johnsmith", "racH2sPu"],
["joe", "13579086"],
["donald", "KUzaDr#9"]
]
var utest = usernames.some(function(uval) {
return (usernames == user, pass);
})
if (utest != true) {
document.getElementById("wrong").innerHTML = "Username or password incorrect"
var wrong = true
document.getElementById("action").innerHTML = "<form>"
} else
document.getElementById("action").innerHTML = "<form action='after sub/after.html'>"
}
Once again sorry if it is a little messy and chaotic I'm working on it.
I basically want to run through the array of usernames and passwords and make sure that it matches what the user put in the username and password boxes.
I also want to make sure that the username matches its password before continuing. If anyone knows how to get this to work pls let me know.
I do believe you are creating this for learning because, in the real world, there are a lot of security reasons to consider.
But you can create a login form using only HTML and JavaScript
It's kinda difficult to explain, please read the comment in this code below:
NOTE: I've changed some of the class, and id name.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="reee">
<h1 id = "dad"> Login </h1>
</div>
<div id = "action">
<form>
<label class ="u" for="fname">Username</label>
<input type="text" id="uname" name="user" placeholder="Your username...">
<label class = "p" for="lname">Password</label>
<input type="text" id="pass" name="pass" placeholder="Your password...">
<input type="submit" value="Submit" id = "loginto" onclick="reee()">
<p class = "wrong" id = "status"></p>
</form>
</div>
<script src = "script.js"></script> // NOTE: ALways put the javascript file link in the bottom.
</body>
</html>
JavaScript:
var usernames = [ //This is the place to store usernames and passwords. In real world, you have to store it in database. In this case I store it in Javascript Object to improve readability
{username: 'john', password: '123'},
{username: 'albert', password: '234'},
{username: 'tesla', password: '345'},
];
function reee() {
var user = document.getElementById("uname").value; //Get user in put from form field
var pass = document.getElementById("pass").value;
for (var i = 0; i < usernames.length; i++){ // Looping. To check every single data in usernames array above
if(user != usernames[i].username || pass != usernames[i].password) { // Check if input is not equal to the usernames list
document.getElementById("status").innerHTML = "The password or username is incorrect"; //Display wrong message
} else {
document.getElementById("status").innerHTML = "Welcome " + user; //Display welcome message and username
break; //To stop checking. Because username has already been found
}
}
}
I hope it will be helpful
EDIT 1: You can see the live demo here
EDIT 2: I've made a silly mistake. If we look at the code below:
/// ORIGINAL
if(user != usernames[i].username && pass != usernames[i].password) {
If we use that code we will pass the login page if the username OR the password is correct (not both), because I use the &&.
So, I have to use ||, so the code should be:
// EDIT 2
if(user != usernames[i].username || pass != usernames[i].password) {
Now, the user should input the correct username and password in order to pass the login page.
I think everything should work fine now.
I'm seeing a huge fundamental issue here.
You really need a backend; look into NodeJS with Express if you like JavaScript.
There are so many things wrong with doing it like this.
User info is deleted upon reloading. Any user info created with this function is stored in the browser's RAM and is destroyed when the page is closed.
The existing user info (default info) can be accessed by anyone, even if they're not logged in.
Passwords are stored in plain text. This is so dangerous because if someone gets access to your database (which they can because it's front-end available) they will have your password. You NEED to hash it, and if you're not experienced with cybersecurity you should definitely use Firebase Google Authentication instead.
Input verification is done on the front-end. Of course, you don't have a back-end, but you want to do this on the back-end once you do some research into this. Otherwise, a user could directly fetch the backend from the console and bypass verification, thereby allowing SQL injection with zero effort.
Minor issue here. Your class names are not human-friendly to other developers or even future you. Please rename the input classes to something like "usernameBox," "passwordBox," and "loginErrorText."
There are a lot more I could list, but you really need to look into a tutorial on this because this is the most easily hackable code I've ever seen.

Not able to know whether values are being inserted or not

Im taking input from user and keeping those values in new array called movie2. If user enters input again it should check the value from movie2 array and if it matches should give a pop up like it already added and if it is a different input it should add those values to movie2 array. I have tried many times but whatever the user inputs it is getting added, it is not comparing.
<!DOCTYPE html>
<html>
<head>
<title>Movie Mania</title>
<link rel="stylesheet" type="text/css" href="Movie.css" >
<script src="Movie.js"></script>
</head>
<body>
<div class="content">
<div class="matter">
<p class="header">Movie Mania</p>
<div class="regis">
<form class="reg">
<input type="text" name="user" id="movie" placeholder="Please enter any
movie name" size="40"><hr>
<div><input type="submit" class="button" value="Search" id="sub"
onclick="validation()" /></div >
</form></div>
</div>
</div></body>
</html>
Javascript:
var movie1 = ["Bahubali", "The Final Destination", "The Cars ","P.K "," Bajarangi Baijaan ","Force "];
var movie2=[];
function validation() {
var movie = document.getElementById("movie").value;
if (!movie.trim()) { //its validate the input empty undefined null
var name2 = "Please enter your favoite movie name";
alert(name2);
}
else if (movie1.includes(movie)) { // includes used for find the value is in array or not
var name2 = "Movie exists in our database";
alert(name2);
}
else {
insert();
}}
function insert(){
var movie = document.getElementById("movie").value;
if(movie2.indexOf(movie)==true){
var name2="Movie already added to Array 2";
alert(name2);
}
else{
movie2.push(movie);
var name2 = "Movie added into Array2";
alert(name2);
}
}
.includes() is part of ES2016, which isn't fully implemented in all browsers yet. Use .indexOf() instead. Now, indexOf() returns -1 when the value doesn't exist or the index position of the item when it does. You have:
if(movie2.indexOf(movie)==true){
Which is not the correct way to test against indexOf(). If indexOf() were to return 0, it would mean that the item was found at the first position in the array (indices start with 0). But, because you are attempting to compare it against true, true will be converted to a number (to perform a number to number comparison) and it will convert to 1. Since 0 doesn't equal 1, the test will fail, and insert the movie even though it already exists.
Also, JavaScript does not have block level scope when using the var keyword for declaration. If you declare a variable with var anywhere in a function, its scope is the entire function. So, you can't declare the variable in one branch of the if and then again in the other. In reality, you don't even need to set up your name variable because all you are doing with it is immediately displaying it in an alert(). Instead, you can just put your string in the alert().
Additionally, don't use inline HTML event attributes (onclick, etc.). Here's why.
Lastly, it appears that you are not actually trying to submit data anywhere. In that case, don't use a submit button, just use a regular button.
// Get refrence to button and textbox
var btn = document.querySelector("form.reg input[type=button]");
// Don't create references to DOM properties because if you decide you want
// to get the value of a different property later, you'll have to scan the DOM
// for the element all over again. Just get a reference to the element once and
// then you can access whatever property you need when you need it.
var movie = document.getElementById("movie");
// Set up click event handler
btn.addEventListener("click", validate);
var movie2 = [];
// Your two functions are redundant. They can be combined into this one:
function validate(evt){
// Access the property of the DOM object you want (user input should always be trimmed)
var mv = movie.value.trim();
// Quick test for input:
if(mv === "") {
alert("You didn't enter anything!");
return;
}
// If we've gotten this far, there is input, so test to see if it is already in the array
var message = "";
if(movie2.indexOf(mv) > -1){
message = "Movie already added to Array 2!!!!";
} else {
movie2.push(mv);
message = "Movie added to Array 2";
}
alert(message);
// Just for testing:
console.clear();
console.log(movie2);
}
<div class="content">
<div class="matter">
<p class="header">Movie Mania</p>
<div class="regis">
<form class="reg" action="#">
<input type="text" name="user" id="movie" placeholder="Please enter any movie name" size="40">
<hr>
<div>
<input type="button" class="button" value="Search" id="sub">
</div>
</form>
</div>
</div>
</div>
The includes() method determines whether a string contains the
characters of a specified string. This method returns true if the
string contains the characters, and false if not.
Hence we shall not use includes() method to compare/search strings.
There are multiple ways you can search for a string in an array of string.
I check for string given to me in given array of string using
indexOf()
The indexOf() method returns the position of the first occurrence of a specified value in a string.
This method returns -1 if the value to search for never occurs.
And where you are adding the movie to the array, you do not need to read data from input box again. The better idea is to clean up the input, validate it and provide it as input to insert(movie).
Here is the sample code, which is working for me.
var movie1 = ["Bahubali", "The Final Destination", "The Cars ","P.K "," Bajarangi Baijaan ","Force "];
var movie2=[];
function validation()
{
var movie = document.getElementById("movie").value;
movie = movie.trim();
if (!movie) //its validate the input empty undefined null
{
var name2 = "Please enter your favoite movie name";
alert(name2);
}
else if (movie1.indexOf(movie) > -1) // check if movie already exists
{
var name2 = "Movie exists in our database";
alert(name2);
}
else
{
insert(movie);
}
}
function insert(movie)
{
if(movie2.indexOf(movie) > -1)
{
var name2="Movie already added to Array 2";
alert(name2);
}
else
{
movie2.push(movie);
var name2 = "Movie added into Array2";
//alert(name2);
for (var i=0; i < movie2.length ; i++)
{
console.log(movie2[i]);
}
}
}
<!DOCTYPE html>
<html>
<head>
<title>Movie Mania</title>
<script type="text/javascript" src="testjs.js"></script>
</head>
<body>
<p class="header">Movie Mania</p>
<form>
<input type="text" name="user" id="movie" placeholder="Please enter any movie name" size="40">
<hr>
<div>
<input type="submit" class="button" value="Search" id="sub"
onclick="validation()" />
</div >
</form>
</body>
</html>

javascript alerts refuse to work in form validation?

i keep trying everything to get these alerts to pop up correctly. i started out using nested functions, then threw them out and put it all in one function, and now when I press enter after filling out any one text box it does nothing at all, just puts the strings in the url, instead of alerting like it was before. I'm not sure if its my function call or anything else because I double checked everything and it all seems to check out to me. here is the entire code that doesnt do anything:
<html xmlns="http://www.w3.org/1999/xhtml">
<HEAD>
<TITLE>Smart Form </TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!-- VARIABLE DECLARATION -->
f1.city.focus();
function check_form()
{
at_sign = email.search(/#/);
if(document.f1.city.value.length < 1)
{
alert('Please enter a city');
f1.city.focus();
}
else if(document.f1.state.value.length != 2 || !(state.charCodeAt('0')>=65 && state.charCodeAt('0')<=91))
{
alert('Please enter a state in abreviated form');
f1.state.focus();
}
else if(document.f1.zip.value.length != 5 || document.f1.zip.value.isNaN()==true)
{
alert('Please enter a 5 digit zip code');
f1.zip.focus();
}
else if((at_sign<1) || (email.length<3))
{
alert('Please enter a valid email address');
f1.email.focus();
}
else
{
document.write("Form completed");
}
}
</SCRIPT>
</HEAD>
<BODY >
<form name = "f1" action="smartform.html">
<b>City</b>
<input type = "text" name = "city" size = "18" value="" onSubmit = "javascript:check_form()">
<b>State</b>
<input type = "text" name = "state" size = "4" value="" onSubmit = "javascript:check_form()">
<b>Zip Code</b>
<input type = "text" name = "zip" size = "5" value="" onSubmit = "javascript:check_form()">
<b>Email</b>
<input type = "text" name = "email" size = "18" value="" onSubmit = "javascript:check_form()">
<input type = "submit" name = "button" value = "Done" onclick = "javascript:check_form()">
</form>
</BODY>
</HTML>
edit: nothing seems to be working that everyone says.. here is my new code:
<html xmlns="http://www.w3.org/1999/xhtml">
<HEAD>
<TITLE>Smart Form </TITLE>
<SCRIPT LANGUAGE="JavaScript">
f1.city.focus();
function check_form(f1)
{
var at_sign = f1.email.search(/#/);
if(f1.city.value.length < 1)
{
alert('Please enter a city');
f1.city.focus();
return false;
}
else if(f1.state.value.length != 2 || !(f1.state.charCodeAt('0')>=65 && state.charCodeAt('0')<=91))
{
alert('Please enter a state in abreviated form');
f1.state.focus();
return false;
}
else if((f1.zip.value.length != 5) || (f1.zip.value.isNaN()==true))
{
alert('Please enter a 5 digit zip code');
f1.zip.focus();
return false;
}
else if((at_sign<1) || (f1.email.length<3))
{
alert('Please enter a valid email address');
f1.email.focus();
return false;
}
else
{
//document.write("Form completed");
}
return false;
}
</SCRIPT>
</HEAD>
<BODY >
<form name = "f1" onSubmit="return check_form(this)">
<b>City</b>
<input type = "text" name = "city" size = "18" value="">
<b>State</b>
<input type = "text" name = "state" size = "4" value="">
<b>Zip Code</b>
<input type = "text" name = "zip" size = "5" value="">
<b>Email</b>
<input type = "text" name = "email" size = "18" value="">
<input type = "submit" name = "button" value = "Done" onclick = "return check_form(this)">
</form>
<b>hi</b>
</BODY>
</HTML>
still get no alerts... i put that hi up and got that.. but no alerts......
alright, I know I should probably be using getElementByID, but my new focus is to find out precisely why my code isn't working. Since my lecture outline examples didnt use this method, I want to figure out why the following code doesnt activate alerts like it used to. I simplified it to this:
<!DOCTYPE html>
<html>
<HEAD>
<TITLE>Smart Form </TITLE>
<SCRIPT LANGUAGE="JavaScript">
function check_form()
{
document.write("Form started");
var at_sign = document.f1.email.search(/#/);
if(document.f1.city.value.length < 1)
{
alert('Please enter a city');
document.f1.city.focus();
//return false;
}
else if(document.f1.state.value.length != 2 || !(document.f1.state.charCodeAt('0')>=65 && document.f1.state.charCodeAt('0')<=91))
{
alert('Please enter a state in abreviated form');
document.f1.state.focus();
//return false;
}
else if(document.f1.zip.value.length != 5 || isNaN(document.f1.zip.value)==true)
{
alert('Please enter a 5 digit zip code');
document.f1.zip.focus();
//return false;
}
else if((at_sign<1) || (document.f1.email.value.length<3))
{
alert('Please enter a valid email address');
document.f1.email.focus();
//return false;
}
else
{
document.write("Form completed");
}
}
</SCRIPT>
</HEAD>
<BODY onLoad= "javascript:document.f1.city.focus();">
<form name = "f1" action="smartform1.html" onSubmit="javascript:check_form();">
<b>City</b>
<input type = "text" name = "city" size = "18">
<b>State</b>
<input type = "text" name = "state" size = "4">
<b>Zip Code</b>
<input type = "text" name = "zip" size = "5">
<b>Email</b>
<input type = "text" name = "email" size = "18">
<input type = "submit" name = "button" value = "Done" onclick = "javascript:check_form();">
</form>
</BODY>
</HTML>
I get no errors in console, and now when I type something in, I get the test line "form started" to appear for a split second, along with some mysterious error, and then it all disapears and shows the form. but my question is, why doesnt an alert happen along the way to this result? it seems like even if the page got overwritten, it should still pop up. also, is there a way to pause it with code/and or debugging before it gets to the point where its overwritten? so my basic question is: why don't the alerts pop up, and how do I get the alerts to popup and the focus to remain in the correct field where the function left off within the if/else statement?
update 2: i did a quick screen cap of the errors and it turns out f1.email etc were undefined and indeed causing the thing to not work. So I still want to know how to pause it with code or in the debugger, the posts and links didnt exactly seem to be clear 100% on it. once im in the consonle and in debug mode, where exactly do i go from there to let the program pause on error?
also: if I declare the getElementByID variables at the top of my script in the header, then use them in the function, should that work without all the other event handling methods? I'm attempting this as i type.
You should put the submit listener on the form and pass a reference to the form, and return whatever value the function returns, e.g.
<form onsubmit="return check_form(this);" ...>
You should reference the controls as properties of form using their name, don't use the name as a global variable. And declare all variables.
So the function looks like:
function check_form(form) {
var at_sign = email.search(/#/);
if (form.city.value.length < 1) {
alert('Please enter a city');
f1.city.focus();
// cancel submit by returning false
return false;
} else if (form.state.value.length != 2 || !(form.state.charCodeAt(0) >=65 && state.charCodeAt(0)<=91)) {
alert('Please enter a state in abreviated form');
f1.state.focus();
return false;
}
...
}
You should probably be using a regular expression or lookup for validating the state value rather than charCodeAt.
Using document.write after the page has finished loading (e.g. when submitting the form) will erase the entire content of the page before writing the new content.
Edit
Here's what's wrong with your new code:
<SCRIPT LANGUAGE="JavaScript">
Get rid of the language attribute. It's not harmful (well, in a very specific case it might be).
f1.city.focus();
f1 has no been defined or initialised (see comments above about element names and global variables)
function check_form(f1)
{
var at_sign = f1.email.search(/#/);
f1.email is an input element, it has no search property, you can't call it. It does have a value property that is a string, perhaps you meant:
var at_sign = f1.email.value.search(/#/);
Then there is:
else if(f1.state.value.length != 2 || !(f1.state.charCodeAt('0')>=65 && state.charCodeAt('0')<=91))
again you have forgotten the value property for two of the three expressions, and forgotten to use f1 in the third. You want:
else if(f1.state.value.length != 2 || !(f1.state.value.charCodeAt(0)>=65 && f1.state.value.charCodeAt(0)<=91))
Note that this requires users to enter the state in capital letters, it might help to tell them about that.
Then there is:
else if((f1.zip.value.length != 5) || (f1.zip.value.isNaN() == true))
isNaN is a global variable, not a method of strings. If no value has been entered, then the value is the empty string and isNaN('') returns false. If you want to test that 5 digits have been entered then use:
else if (!/^\d{5}$/test(f1.zip.value))
There is no need to test against true, just use it, nor is there a need to group simple expressions:
else if (f1.zip.value.length != 5 || isNaN(f1.zip.value))
Then finally, if all the test pass:
return false;
that stops the form from submitting. You can omit this return statement, returning undefined will let the form submit. Or return true if you really want.
Ok I want to answer your question but first things first lets walk through your
code and clean it up.
Use this as a template of properly formated code:
<!DOCTYPE html>
<html>
<head>
<title>Smart Form</title>
</head>
<body>
<!-- Code goes here -->
<script type="text/javascript">
</script>
</body>
</html>
Tags & attributes don't need to be capitalized. Javascript comments are like this:
/** Comment. */
Html comments are like this:
<!-- Comment. -->
Also nitpick: attributes should be followed by an equal sign not a space. i.e.
<form name="f1" id="smartForm" action="smartform.html"> ... </form>
Next up proper event binding.
var smartForm = document.getElementById('smartForm');
smartForm.addEventListener('submit', validateForm);
Next up I'm going to teach you how to fish real quick so you can figure out why this was broken for you and how to fix these bugs in the future. Open up the developer console. Evergreen browsers (Chrome, Firefox etc...) have good ones these day. The trick you should know is how to evaluate your code so that you can see if you did something wrong or not in how you're accessing your data. So look up how to open up the developer console in your browser for your platform and type this into your console:
1+1
Should evaluate to: 2.
Next type: document
If you click around you can see that you can walk through the dom a little bit.
Next load up your smartForm app with my changes above and type:
document.getElementById('smartForm')
You should see your element. This is how to properly query objects in the dom.
You'll notice that if you type document.smartForm doesn't work. You should get null, this should tell you that there should be a way to get the element from the document. Hint, it's getElementById. So if you put id's on all your inputs then you can make a list of all the document objects you can query:
var cityElement = document.getElementById('city');
var stateElement = document.getElementById('state');
var zipElement = document.getElementById('zip');
var emailElement = document.getElementById('email');
Next you can start querying the values and such like you were doing:
cityElement.value.length != 2
A cleaned up version would look like this:
<!DOCTYPE html>
<html>
<head>
<title>Smart form</title>
</head>
<body>
<form id='smartForm' action='smartform.html'>
<b>City</b>
<input type="text" id="city" size="18">
<b>State</b>
<input type="text" id="state" size="4">
<b>Zip Code</b>
<input type="text" id="zip" size="5">
<b>Email</b>
<input type="text" id="email" size="18">
<input type="submit" value="done">
</form>
<script type="text/javascript">
var validateForm = function(evt) {
var error = false;
var cityElement = document.getElementById('city');
var stateElement = document.getElementById('state');
var zipElement = document.getElementById('zip');
var emailElement = document.getElementById('email');
if (cityElement.value.length != 2 ||
!(state.charCodeAt(0) >= 65 && state.charCodeAt(0) <= 91)) {
error = true;
alert('oops');
cityElement.focus();
}
// etc..
if (error) {
evt.preventDefault();
}
};
var smartForm = document.getElementById('smartForm');
smartForm.addEventListener('submit', validateForm);
</script>
</body>
</html>
Ok a couple more things I noticed. charCodeAt is for strings only. "hi".chatCodeAt not element.charCodeAt. Also you have this random variable at_sign.
You can save yourself a TON of time and you can learn how to diagnose where the issues are by reading this: https://developer.chrome.com/devtools/docs/console
Learning how to diagnose where the issues are is the single best skill you can learn while trying to get a grapple on javascript. I cannot emphasize this enough, learn how to debug, and you will learn how to program orders of magnitude faster. Trust me, let debugging tutorials be your bread at butter!
Full working example of your code:
http://codepen.io/JAStanton/pen/tjFHn?editors=101
A little less verbose version:
http://codepen.io/JAStanton/pen/iBJAk?editors=101
onSubmit goes in the form, not the inputs, w/o the javascript: Solved =p
<form onsubmit="return check_form();" ...
There are several mishaps in your code that might also cause errors and prevent that from working
Also, check if there are mistakes (like the HTML comment inside script), if an error happens in javascript and is untreated, all javascript in that context stops working. You can check that with any browser debugger (usually F12 will show you a window and display errors if they happen)

How to pass input variable from HTML Form

I'm trying to create a code which will take ask the user how many items of X, Y, etc and use Javascript to calculate the total owed and also to print a summary (receipt) of all items purchased. Sorry for noob question, trying to learn code without any formal training. Thanks for all of the help!
<html>
<head>
<title>Cost Calculator</title>
<script language="javascript" type="text/javascript">
function packageTotal(){
//Enter in prices here
var applePrice = 1;
var bookPrice = 2;
x = Number(document.calculator.books.value);
y = Number(document.calculator.apples.value);
var b = applePrice*x + bookPrice*y;
var p = applePrice*x + bookPrice*y + .5;
if (document.getElementById('noBag').checked) {
//Basic package is checked
document.calculator.total.value = b;
} else if (document.getElementById('yesBag').checked) {
//Pro package is checked
document.calculator.total.value = p;
}
//Want to add summary of purchase
//document.write("You want " + x " books and " y " apples.");
}
</head>
<body>
<!-- Opening a HTML Form. -->
<form name="calculator">
<!-- Here user will enter the number of Books and Apples -->
Enter Number of Books: <input type="text" name="books">
<br />
Enter the Number of Apples: <input type="text" name="apples">
<br />
<br />
<input type="radio" name="item" id="noBag" value="No" /> noBag
<input type="radio" name="item" id="yesBag" value="Yes" checked /> yesBag
<!-- Here result will be displayed. -->
<input type="button" value="Submit" onclick="packageTotal();">
Your Total Price is: <input type="text" name="total">
</form>
</body>
</html>
It's not clear from the question, but if this is the problem:
//Want to add summary of purchase
//document.write("You want " + x " books and " y " apples.");
then that would certainly break. document.write only adds to the current document when the document is still loading. If you call it afterwards it will implicitly open a new document to write to, destroying the current page. Generally document.write is a bad thing.
(also there are trivial syntax errors due to missing + concatenation operators)
If you want to write arbitrary text to the page, create a placeholder element:
<div id="message"></div>
and then set its text content:
function setTextContent(element, text) {
element.innerHTML = ''; // remove current content
element.appendChild(document.createTextNode(text));
}
var message = document.getElementById('message');
setTextContent(message, 'You want '+x+' books and '+y+' apples.');
(There is a textContent property on elements which you can also use instead of the function, but it's not supported on IE<9 which use innerText instead. Simply writing the message directly to innerHTML would also work in this case, but it is a bad habit because it leads to HTML-injection security holes when used with user input.)

Categories