views:

1186

answers:

6

I'm working on a form validation script at work and am having some difficulty. The form is meant to make sure that the user fills out a name, a real-looking email, a category (fromt he drop down) and a question:

This names the form and gathers all the data up from the form:

<script>

  function checkForm(form1) {
name = document.getElementById("FieldData0").value;
category = document.getElementById("FieldData3").value;
question = document.getElementById("FieldData1").value;
email = document.getElementById("FieldData2").value;

This checks to see that something is in the "name" field. It works fine and validates exactly like it should, displaying the error text:

  if (name == "") {
  hideAllErrors();
document.getElementById("nameError").style.display = "inline";
document.getElementById("FieldData0").select();
document.getElementById("FieldData0").focus();
  return false;

This also works just like it should. It checks to see if the email field is empty and if it is empty,displays error text and selects that field:

  } else if (email == "") {
hideAllErrors();
document.getElementById("emailError").style.display = "inline";
document.getElementById("FieldData2").select();
document.getElementById("FieldData2").focus();
  return false;
  }

This also works just like it should, makes sure that the questions field isn't empty:

else if (question == "") {
hideAllErrors();
document.getElementById("questionError").style.display = "inline";
document.getElementById("FieldData1").select();
document.getElementById("FieldData1").focus();
  return false;
  }

This one works partially - If no drop down is selected, it will display the error message, but that doesn't stop the form from submitting, it just displays the error text while the form submits:

else if (category == "") {
hideAllErrors();
document.getElementById("categoryError").style.display = "inline";
document.getElementById("FieldData3").select();
document.getElementById("FieldData3").focus();
  return false;
  }

This one doesn't work at all no matter where I put it. I used a variation on the same script last week and it worked fine. This is supposed to check to see that the email entered looks like a real email address:

else if (!check_email(document.getElementById("FieldData1").value)) {
hideAllErrors();
document.getElementById("emailError2").style.display = "inline";
document.getElementById("FieldData2").select();
document.getElementById("FieldData2").focus();
  return false;
  } 

Otherwise it lets the form submit:


  return true;
  }

This checks the email out:

function check_email(e) {
ok = "1234567890qwertyuiop[]asdfghjklzxcvbnm.@-_QWERTYUIOPASDFGHJKLZXCVBNM";

for(i=0; i < e.length ;i++){
if(ok.indexOf(e.charAt(i))<0){ 
return (false);
}   
} 

if (document.images) {
re = /(@.*@)|(\.\.)|(^\.)|(^@)|(@$)|(\.$)|(@\.)/;
re_two = /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
if (!e.match(re) && e.match(re_two)) {
return (-1);     
} 

}

}

This function hides all errors so the user isn't bombarded with red text. I tried putting in "document.getElementById("emailError").style.display = "none"" but that breaks the whole thing:

  function hideAllErrors() {
document.getElementById("nameError").style.display = "none"
document.getElementById("emailError").style.display = "none"
document.getElementById("categoryError").style.display = "none"
document.getElementById("questionError").style.display = "none"

  }


</script>

And the form looks like this:

<form onSubmit="return checkForm();" method="post" action="http://www.emailmeform.com/fid.php?formid=303341io4u" name="form1">

<p><div class=error id=nameError>Required: Please enter your name<br/></div><p><strong>Name:</strong> <span></span><br><input type="text" name="FieldData0" id="FieldData0" value="" size="22" tabindex="1" />
<label for="name"></label></p>

<p><div class=error id=emailError>Required: Please enter your email address<br/></div>
<div class=error id=nameError2>This doesn't look like a real email address, please check and reenter<br/></div>
<strong><p>Email:</strong> <span>(will not be published)</span><br><input type="text" name="FieldData2" id="FieldData2" value="" size="22" tabindex="2" />
<label for="email"></label>
</p>

<div class=error id=categoryError>Please select a category from the drop-down menu<br></div>
<p><strong>Category:</strong> <span></span><br>
<p><select id="FieldData3" name="FieldData3">
<option value="">Please select a category</option>
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
<option value="d">d</option>
<option value="e">e</option>
<option value="f">f</option>
<option value="other">Other</option>
</select><label for="category"></label>

<p><div class=error id=questionError>Please type your question in the box below:<br></div><label for="question"><strong><p>Your Question:</strong> <span></span></label><br>

<textarea name="FieldData1" id="FieldData1" cols="50" rows="10"></textarea></p>

<p><input type="submit" class="btn" value="Submit Question" name="Submit"></p>
</div>
</form>

Is the problem the order that I run the checks? I can't seem to figure this out. Any help would be appreciated.

A: 

First problem: move the content of that if statement into a function...then go from there. You have about 5 pieces of code doing essentially the same thing.

Next: since you're only allowing one error message at a time, create a generic div to hold it and just move the thing. That way, you don't need to keep track of hiding certain errors, displaying others, etc.

Next: only return true or false from your check_email function...returning -1 and false, etc. is bad form even though javascript is lenient on such things.

After you have cleaned up your code, it will be much easier to debug.

Zack
A: 

I would recommend getting rid of the whole if else chain and check each on individually this this.

var error = 0;
if (value == '') {
    error = 1;
    // other stuff;
}

if (value2 == '') {
    error = 1;
    // do stuff;
} 

...

if (error) {
    // show error
} else {
    // submit form
}
atodd
why error = 1|0? ever heard of true|false?
roryf
This not much better than the current code, there would still be a lot of duplication.
brianpeiris
That's what i was thinking, it seems like 6 of one half dozen of another. Thank you for the help though.
pg
Roy did you know 1|0 is the same boolean representation as true|false. jackass.
atodd
A: 

Try replacing the == for === which doesn't type cast. It might help you with the dropdown problem.

Your function is returning false and it might also return -1.

As I don't know what type cast JavaScript does with !-1 you should also do this:

check_email(...)!==false;

Instead of this:

!check_email(...)
fmsf
+1  A: 

Regarding the error on the drop-down, don't call this line:

document.getElementById("FieldData1").select();

I seem to recall having the exact same problem a few weeks ago.

Marc Bernier
You're right, except the dropdown's id is "FieldData3".
brianpeiris
Yeah, I was trying to treat it like it was a regular text field. My mistake.
pg
+3  A: 

I've taken the liberty to re-write your javascript to make it more readable and easier to debug.

As Marc Bernier mentioned, the dropdown element does not support the select function so I put an if statement around it to prevent an exception. I've also simplified your checkEmail function, it seemed rather convoluted. I renamed it to isAnInvalidEmail in order to make the checkForm code simpler.

You have also incorrectly named the 'emailError2' div in your HTML, which would cause another exception in the javascript. Your HTML is rather messy and, in some cases, invalid. There are missing quotes on some attribute values and missing end-tags. You should consider using the W3C validator to ensure your HTML is clean and is standards compliant.

I've hosted your code on jsbin: http://jsbin.com/iyeco (editable via http://jsbin.com/iyeco/edit)

Here's the cleaned up Javascript:

function checkForm() {
  hideAllErrors();
  var formIsValid =
    showErrorAndFocusIf('FieldData0', isEmpty, 'nameError')
    && showErrorAndFocusIf('FieldData2', isEmpty, 'emailError')
    && showErrorAndFocusIf('FieldData2', isAnInvalidEmail, 'emailError2')
    && showErrorAndFocusIf('FieldData3', isEmpty, 'categoryError')
    && showErrorAndFocusIf('FieldData1', isEmpty, 'questionError');

  /* For debugging, lets prevent the form from submitting. */
  if (formIsValid) {
    alert("Valid form!");
    return false;
  }

  return formIsValid;
}

function showErrorAndFocusIf(fieldId, predicate, errorId) {
  var field = document.getElementById(fieldId);
  if (predicate(field)) {
    document.getElementById(errorId).style.display = 'inline';
    if (field.select) {
      field.select();
    }
    field.focus();
    return false;
  }

  return true;
}

function isEmpty(field) {
  return field.value == '';
}

function isAnInvalidEmail(field) {
  var email = field.value;

  var ok = "1234567890qwertyuiop[]asdfghjklzxcvbnm.@-_QWERTYUIOPASDFGHJKLZXCVBNM";

  for(i = 0; i < email.length; i++){
    if(ok.indexOf(email.charAt(i)) < 0) {
      return true;
    }
  }

  re = /(@.*@)|(\.\.)|(^\.)|(^@)|(@$)|(\.$)|(@\.)/;
  re_two = /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
  return re.test(email) || !re_two.test(email);
}



function hideAllErrors() {
  document.getElementById("nameError").style.display = "none"
  document.getElementById("emailError").style.display = "none"
  document.getElementById("emailError2").style.display = "none"
  document.getElementById("categoryError").style.display = "none"
  document.getElementById("questionError").style.display = "none"
}

And the cleaned up HTML:

<form onSubmit="return checkForm();" method="post" action="http://www.emailmeform.com/fid.php?formid=303341io4u" name="form1"> 
  <div> 
    <div class="error" id="nameError"> 
      Required: Please enter your name 
    </div> 
    <label for="FieldData0"><strong>Name:</strong></label> 
    <input type="text" name="FieldData0" id="FieldData0" value="" size="22" tabindex="1" /> 
  </div> 

  <div> 
    <div class="error" id="emailError"> 
      Required: Please enter your email address 
    </div> 
    <div class="error" id="emailError2"> 
      This doesn't look like a real email address, please check and reenter 
    </div> 
    <label for="FieldData2"><strong>Email:</strong>(will not be published)</label> 
    <input type="text" name="FieldData2" id="FieldData2" value="" size="22" tabindex="2" /> 
  </div> 

  <div> 
    <div class="error" id="categoryError"> 
      Please select a category from the drop-down menu 
    </div> 
    <label for="FieldData3"><strong>Category:</strong></label> 
    <select id="FieldData3" name="FieldData3"> 
      <option value="">Please select a category</option> 
      <option value="a">a</option> 
      <option value="b">b</option> 
      <option value="c">c</option> 
      <option value="d">d</option> 
      <option value="e">e</option> 
      <option value="f">f</option> 
      <option value="other">Other</option> 
    </select> 
  </div> 

  <div> 
    <div class="error" id="questionError"> 
      Please type your question in the box below: 
    </div> 
    <label for="FieldData1"><strong>Your Question:</strong></label> 
    <textarea name="FieldData1" id="FieldData1" cols="50" rows="10"></textarea> 
  </div> 

  <input type="submit" class="btn" value="Submit Question" name="Submit"> 
</form>
brianpeiris
Thank you for such a thorough answer. I will take your advice to heart.
pg
You're very welcome. Happy coding!
brianpeiris
A: 

IS there any way to show the error messages all at the same time (for instance, when the user leaves all the field blank)?

yeah you just have to turn off "hideallerrors"
pg