Returning HTML Ends Loop Premature - javascript

I am using javascript to validate some form elements. The fields I want to be required are passed into my validateReqFields function when the form is submitted. Everything is working perfectly until I get to the for loop that is meant to add an error message the an empty beside the form field. It seems that as soon as one field fails and it adds the message to the div, the for loop does not continue.
The HTML Form Elements:
First Name <input type="text" name="firstName" onkeypress="return checkField(event, letters);"/><div id="firstNameMsg" style="display:inline-block;"></div>
<br>
Last Name <input type="text" name="lastName" onkeypress="return checkField(event, letters);"/><div id="lastNameMsg" style="display:inline-block;"></div>
The Javascript function:
function validateReqFields(formName, reqFields){
var fieldArray = reqFields.split(",");
var failedList = new Array();
var message = "Required Field";
for(var i=0; i<fieldArray.length; i++){
removeWhiteSpace(fieldArray[i]);
var s = eval('document.'+formName+'.'+fieldArray[i]+'.value');
if(s.length<1) { failedList.push(fieldArray[i]); }
}
if(failedList.length >= 1) {
for(var i=0; i<failedList.length; i++) {
//BUG - Only shows first failed field.
document.getElementById(failedList[i] + 'Msg').innerHTML = message;
}
} else {
document.mForm.submit();
}
}
function removeWhiteSpace(mString){
mString = mString.replace(/(^\s+|\s+$)/g,' ');
return mString;
}
I have done a few tests and concluded that when the for loops sets the innerHtml on the first div element, it breaks the for loop. Is there a way to avoid this?

My removeWhiteSpace function was not working correctly, thus everything after my first field was failing. Silly mistake. Please close this question.

Related

For Loop Only Running Through Once

In the following program, for some reason, the for loop runs through once, and then does not repeat. I believe the error is with the bold code. Help is very much appreciated. This is a program used to change a text box to caps, title case, etc. Title case being the first letter of each word capitalized. Thank you.
<html>
<head>
<script type="text/javascript">
function titlize(){
tLength=tBox.box.value.length
character=new Array()
for(i=1; i<tLength+1; i++){
**character[i]=tBox.box.value.slice(i-1,i)**
document.write(character[i])
if(i==1){
character[i]=character[i].toUpperCase()
}else if(character[i-1]==" "){
character[i]=character[i].toUpperCase()
}else{
character[i]=character[i].toLowerCase()
}
document.write(i)
document.write(character[i])
}
}
function upperC (){
toUpperCase(tBox.box.value)
}
function verify (){
if(tBox.uppercase.checked){
tBox.box.value=tBox.box.value.toUpperCase()
}
if(tBox.lowercase.checked){
tBox.box.value=tBox.box.value.toLowerCase()
}
if(tBox.titlecase.checked){
titlize()
}
if(tBox.uppercase.checked){
tBox.box.value=tBox.box.value.toUpperCase()
}
}
</script>
</head>
<body>
<form name="tBox">
<input type="text" name="box" value=""><br>
<input type="checkbox" name="uppercase" onClick=verify(this.form)>Uppercase<br>
<input type="checkbox" name="lowercase" onClick=verify(this.form)>Lowercase<br>
<input type="checkbox" name="titlecase" onClick=verify(this.form)>Titlecase<br>
</form>
</body>
</html>
tBox is your form not your textbox, so trying to get it's value and then the length of that value is not valid. The code needs to access your textbox, so it should be:
// Scan for the first textbox. Give that textbox a unique id to be
// able to write a more specific query.
tLength= document.querySelector("input[type='text']").value.length;
character=new Array()
// Not sure why you were writing: i < tLength +1 as that will
// cause your loop to go one character too far. Remember,
// arrays start from 0 and length starts from 1.
for(i=1; i < tLength; i++){
Lastly, avoid document.write() because if you use it on a document that has finished being parsed, it will cause the entire existing document to be thrown out.
Based on the code above. You have document.write statements in your function, which is causing issues in overwriting your DOM. I've removed those, and that will allow it to function normally. Also, I added tBox.box.value = character.join("") to put the text back into the text box.
https://plnkr.co/edit/qOPIxwH16hJUlj0RFBhv?p=preview
function titlize() {
tLength=tBox.box.value.length;
character=new Array();
for(i=1; i < tLength + 1; i++){
console.log('print')
character[i]= tBox.box.value.slice(i - 1,i)
//document.write(character[i])
if(i==1) {
character[i]=character[i].toUpperCase()
} else if(character[i-1]==" ") {
character[i] = character[i].toUpperCase()
} else {
character[i]=character[i].toLowerCase()
}
console.log(i)
console.log(character[i])
}
tBox.box.value = character.join("")
}

Javascript: How use a loop function to show all the user input in one single alert box?

I'm trying to write a function that will show an Alert Box for all the data entered by the user in the form. I must do it only in simple javascript (sorry no jQuery). My HTML is as follows:
<form method="POST">
<label class="form">Name: </label><input type="text" name="name" id="name"><br>
<label class="form">Address: </label><input type="text" name="address" id="address"><br>
<label class="form">Email: </label><input type="text" name="email" id="email"><br>
<button id="submit" type="submit" value="submit" onclick="showAlert()">
Submit
</button>
</form>
My javascript:
function showAlert() {
var userInputs = document.getElementsByTagName("input");
for (var i=0; i < userInputs.length; i++) {
alert(userInputs.value + " ");
//Basically my idea would be to implement a loop for as many input fields,
//run through all of them, then display ONE SINGLE alert box containing all the
//data entered by the user. But I'm having trouble with how to implement the loop.
}
}
How do I implement the loop?
I have written another function that achieves the same effect but it involved writing a long, tedious list of variables for each input field and I don't want to do that since it's messy:
function alternateShowAlert() {
var name = document.getElementById('name').value;
var address = document.getElementById('address').value;
var email = document.getElementById('email'.value;
alert(name + " " + address + " " + email)
//This function, although it works fine, will be too long and tedious if I have
//more input fields such as age, city, state, country, gender, etc. I want to put
//it in a loop format but how do I do this?
}
function showAlert() {
var userInputs = document.getElementsByTagName("input");
var alertBody = "";
for (var i=0; i < userInputs.length; i++) {
alertBody += userInputs[i].value + " ";
}
alert(alertBody);
}
document.getElementsByTagName() returns an array, so you need to access the elements of the array using their index: userInputs[i].
Or you can use Array.prototype.forEach. See the example below.
function showAlert() {
var userInputs = document.getElementsByTagName("input");
var alertBody = "";
Array.prototype.forEach.call(userInputs, function(element) {
alertBody += element.value + " ";
});
alert(alertBody);
}
You have the logic: you need the loop to collect all info, but should show only one alert, so instead of alert'ing inside the loop, you need to do it after:
function showAlert() {
var userInputs = document.getElementsByTagName("input");
var infos = ""; // Create a string for the content
for (var i=0; i < userInputs.length; i++) {
infos += userInputs[i].value + " "; // Add the info from user input
}
alert(infos); // Show one alert at the end
}
Martin is getting you part of the way there, but I think you'll trip up at getting the values. Document.getElementsByTagName
returns an HTML collection best treated as an array.
So user inputs.value would probably need to be something like userinputs[i].value for Martin's code to work
You can do it in one single line, without any loop:
function Show() {
alert([].slice.call(document.querySelectorAll("input[type='text']")).map(function(x) { return x.id + ": " + x.value; }).join("\n"));
}
Name: <input type="text" id="name" /><br />
Address: <input type="text" id="address" /><br />
Email: <input type="text" id="email" /><br />
<button type="button" onclick="Show();">Show</button>
The method querySelectorAllis supported by all modern browsers (IE 9+) and is the plain JS equivalent to jQuery selectors. However, it returns a node list which should be converted to plain array in order for us to use the desired .map() method to get all the values easily.

Does node created within a sub-function stay valid even after the function exited?

I have project for my php class where I have to enter First name, last name, email, and phone number and output returns the exact values. (but I will only put the 'first name' code for editing).
I have a function in of html that gets called from 'onsubmit' inside
<script>
function validate3(){
alert ("1validate3 called");
var elemFnameSpan = document.createElement("span");
var elemFnameBr = document.getElementById("idFnameBr");
var elemFnameBrParent = elemFnameBr.parentNode;
elemFnameBrParent.insertBefore(elemFnameSpan,elemFnameBr);
elemFnameSpan.id = "idFnameErr";
elemFnameSpan.style.color="red";
elemFnameSpan.innerHTML="";
var elemFname=document.getElementById("idFname");
var elemFnameValue = elemFname.value;
var errorFlag=false;
if (elemFnameValue == null || elemFnameValue ==""){
elemFnameSpan.innerHTML ="required field";
return false;
}
else{
elemFnameSpan.innerHTML="";
}
if(errorFlag==true){
return false;
}
return true;
}
</script>
<form onsubmit="return validate3()" action = "ContactInfo.php">
First Name<span style="color:red">*</span>
<input type="text" name = "Fname" size = "10" id="idFname" onchange="eraseFnameErr()"/>
<br id="idFnameBr" >
<input type="submit" name="submit" value="Submit" /><br>
The function creates a node 'elemFnameSpan' before of id 'idFnameBr'. If the textinput for first name is empty, elemFnameSpan.innerHTML outputs "required field", and false on 'onsubmit' . My problem is that the output doesn't refresh everytime the submit button is called, so 'required field' outputs get extended next to each other.
I am having difficulty resolving this situation and tried to remove the previous child node everytime the new function is called, but that didn't work either for me yet.
Once you append any DOM node, it never removed unless you do it explicitly.
I can suggest two ways to achieve your goal.
First, you can save the node in a global variable.
var elemFnameSpan;
function validate3(){
alert ("1validate3 called");
if (!elemFnameSpan) {
elemFnameSpan = document.createElement("span");
}
var elemFnameBr = document.getElementById("idFnameBr");
var elemFnameBrParent = elemFnameBr.parentNode;
Or, set id to elemFnameSpan and find it every time the form is submitted.
function validate3(){
alert ("1validate3 called");
var elemFnameSpan = document.getElementById('whatever_you_want');
if (!elemFnameSpan) {
elemFnameSpan = document.createElement("span");
elemFnameSpan.setAttribute('id', 'whatever_you_want');
}
var elemFnameBr = document.getElementById("idFnameBr");
var elemFnameBrParent = elemFnameBr.parentNode;
You need to check if you have already created the span element, if you have grab it by using getElementById, if you havent then create it.
//This is an "if" shortcut, if getElementById returns null
//the code in right side will execute and the return value
//will be put in eleFnameSpan
var eleFnameSpan = document.getElementById("idFnameErr") || document.createElement("span");
var elemFnameBr = document.getElementById("idFnameBr");
//Check parentNode on elemFnameBr if it is null/undefined then it hasnt
//been added to the dom yet
if(!elemFnameBr.parentNode){
//No need to store the parentNode (unless needing it else were in code)
elemFnameBr.parentNode.insertBefore(elemFnameSpan,elemFnameBr);
elemFnameSpan.id = "idFnameErr";
elemFnameSpan.style.color="red";
elemFnameSpan.innerHTML="";
}
The rest of the code can stay the same
What is happening is you are just creating a new span on each click, and since on each click you add a new span and edit that one instead of the original one you keep getting new message stacked next to each other.

How to check if all textboxes (including dynamically added) are empty or not?

In my form, onsubmit asks for return values form three different functions. One function should check whether the textboxes with a certain class are empty or not. In my form I can add textboxes with the same class as the one that already exixsts. When I add such a textbox, the function only seems to check the last added textbox because when I submit the form, it submits even when the first textbox is empty.
When I do not add any textboxes, the first one is checked... so the problem is only there when I add textboxes.
I would appreciate it when someone can help me out! Thanks in advance!
Here's my code:
function legedienst()
{
var omschrijvingen = document.getElementsByClassName('omschrijving');
var valid = true;
for (var i=0; i < omschrijvingen.length; i++)
{
if (omschrijvingen[i].value == '')
{
document.getElementById('error').innerHTML = 'Vul alle diensten in a.u.b.';
valid = false;
}
}
return valid;
}
Here is the code that creates and deletes dynamic textboxes.
"bereken()" is just a function that is called to calculate some values.
// dienst toevoegen
var linenumber = 0;
addLine = function()
{
linenumber++;
$('#dienst').append('<tr><td><input name="dienstomschrijving[]" type="text" style="width: 200px;" class="omschrijving" /></td><td><input name="prijs" class="prijs" type="text" style="width: 100px;" /></td><td><input name="verwijder_dienst" type="button" value="Verwijder dienst" onclick="delLine(this)" /></td></tr>');
bereken();
}
// dienst verwijderen
delLine = function(line)
{
$(this).closest('tr').remove();
};
I see you are using jQuery. Try this way.
function legedienst() {
$('tr td. omschrijving').each(function(){
if($(this).val().length==0){
return false;
}
});
return true;
}
Your function legedienst, for validating the textboxes having the class='omchrijving' is correct. In the delLine function change the "this" into "line", and it will also work.
$(line).closest('tr').remove();
I don't see what is wrong on your side. You can play with a working demo: http://jsfiddle.net/FkGb7/

In Javascript, Value not comming instead the variable name is displayed

function ProvideValue(){
Values = document.getElementById('HiddenValue').value;
FirstCut = Values.split("###"); // This will return the array ID#-#VALUE#-#TYPE
var CtrlId;
for (i = 0; i < FirstCut.length - 1; i++) {
Strings = FirstCut[i];
SecondCut = Strings.split("#-#");
if(SecondCut[2].match("TEXT")) {
CtrlId = "" + SecondCut[0];
document.getElementById(CtrlId).value = SecondCut[1];
}
}
}
This is my code instead of the Id, which i can print it.But CtrlId is not replaced by the actual value. Am getting error document.getElementById(CtrlId).value is NULL. I tried to hard code the ID then its working fine but i cannot hard code the controlsID because there are 1000s of control and everytime the ID changes.
Your code seems fine (apart from implied globals1), you must have some other problem in your HTML document... I'm also not sure why you're leaving out the last value from the first cut since you're interating to length - 2, because i is less than length - 1 (not less than or equal) which means that it goes all the way to value length - 2 and then breaks the loop.
Here's a JSFiddle I created that uses your code and displays some additional console messages and actually applies values to inputs as provided by the hidden input.
1Important
I applied var to your variables so they're not implied globals which should be avoided at all times because they're nothing but evil friend of hidden bugs.
The code I used
HTML is super simple but I do have both elements with IDs that are being addressed in the compound value of the hidden field:
<input type="hidden" id="hidden" value="me#-#Rob#-#text###you#-#Mike#-#text" />
<input id="me" value="name" />
<input id="you" value="name" />​
Script is simple as well (runs on DOM ready for JSFiddle simplicity reasons):
var vals = document.getElementById('hidden').value;
var firstCut = vals.split("###");
for(var i = 0; i < firstCut.length; i++) {
var ctrl = firstCut[i].split("#-#");
if (ctrl[2].match("text")) {
var id = ctrl[0];
document.getElementById(id).value = ctrl[1];
}
}​

Categories