adamdehaven
adamdehaven

Reputation: 5920

Javascript Validate on input change, only submit when Submit button clicked

I have a form on my site. When the submit button is clicked, a function runs to get the contents of each field, validate the contents based on RegEx and other requirements, and then if everything looks fine, the form is submitted via Ajax to a .php mailer.

I would like the form to validate automatically when the input field values change, OR when the input field loses focus (I have no preference, either would be great) AND THEN I would like the form to submit ONLY when the user clicks the Submit button on the form. If the user clicks the Submit button BEFORE all fields are valid, I do NOT want the form to submit.

Here's my code:

    //contact form validation   
$(function(){
    $('.error').hide();
    // hide error messages onchange
    $("#contact-form").change(function(){
        $('.error').hide(); 
        $("label#name_error").hide(); 
        $("label#invalid_error").hide(); 
        $("label#email_error").hide(); 
        $("label#invalid_phone_error").hide(); 
        $("label#phone_error").hide(); 
        $("label#zip_error").hide();
    });

    // validate fields on click
    $(".cool-button").click(function(){
        $('.error').hide(); 
        $("label#name_error").hide(); 
        $("label#invalid_error").hide(); 
        $("label#email_error").hide(); 
        $("label#invalid_phone_error").hide(); 
        $("label#phone_error").hide(); 
        $("label#zip_error").hide(); 

        var name=$("input#contact_name").val();
        var email=$("input#contact_email").val();
        var emailRegEx =/^([a-zA-Z0-9])(([a-zA-Z0-9])*([\._-])?([a-zA-Z0-9]))*@(([a-zA-Z0-9\-])+(\.))+([a-zA-Z]{2,4})+$/
        var phone=$("input#contact_phone").val();
        var phone=phone.replace(/\s+-/g, "");
        var phoneRegEx = /^(1-?)?\s?(\([2-9]\d{2}\)|\s?-?[2-9]\d{2})-?\s?[2-9]\d{2}-?\d{4}$/
        var zip=$("input#contact_zip").val();
        var best_time=$("input#contact_best_time").val();
        var message=$("textarea#contact_message").val();
        var timestamp=$("input#timestamp").val();

        if(name==""){
            $("label#name_error").show();
            $("input#contact_name").focus();return false;
            }
        if(email==""){
            $("label#email_error").show();
            $("input#contact_email").focus();return false;
            }
        if (document.getElementById('contact_email').value.search(emailRegEx )==-1) {
            $("label#invalid_error").show();
            $("input#contact_email").focus();return false;
            }
        if(phone==""){
            $("label#phone_error").show();
            $("input#contact_phone").focus();return false;
            }
        if (document.getElementById('contact_phone').value.search(phoneRegEx )==-1) {
            $("label#invalid_phone_error").show();
            $("input#contact_phone").focus();return false;
            }
        if(zip==""){
            $("label#zip_error").show();
            $("input#contact_zip").focus();return false;
            }
        if(message==""){
            $("label#message_error").show();
            $("textarea#contact_message").focus();return false;
            }
        else {
var dataString='contact_name='+name+'&contact_email='+email+'&contact_phone='+phone+'&contact_zip='+zip+'&contact_best_time='+best_time+'&timestamp='+timestamp+'&contact_message='+encodeURIComponent(message);
    $.ajax({
        type:"POST",
        url:"php/contact.php",
        data:dataString,
        success:function(){$('#contact-form').html("<div id='message'></div>");$('#message').html("<h3>Message Sent</h3>").append("<p>Thank you for contacting us. We'll be in touch. <br /><br />If you have any further questions, you can always email us at [email protected] or call us at 800-924-9473</p>").hide().fadeIn(800,function(){$('#message').append("<img id='checkmark' src='images/submit2.png' />");});}});
        }
        return false;
    });

});

AND HERE IS THE HTML and PHP CODE FOR THE FORM

<form id="contact-form" method="post" action="#">
                          <p class="form-subscr-field">
                            <label for="contact_name" id="contact_name_label">Your name: *</label>
                            <input id="contact_name" type="text" name="contact_name" class="inputbox" size="10" required/>
                            <label class="error error-tip" for="contact_name" id="name_error" style="display: none; ">Please enter your name.</label>
                          </p>
                          <p class="form-subscr-field">
                            <label for="contact_email" id="contact_email_label">E-mail Address: *</label>
                            <input id="contact_email" type="email" name="contact_email" class="inputbox" size="10" required/>
                            <label class="error error-tip" for="contact_email" id="email_error" style="display: none; ">Please enter your email address.</label>
                            <label class="error error-tip" for="contact_email" id="invalid_error" style="display: none; ">Invalid email address.</label>
                          </p>
                          <fieldset class="w50">
                          <p class="form-subscr-field rowElem left">
                            <label for="contact_phone" id="contact_phone_label">Phone: *</label>
                            <input id="contact_phone" type="tel" name="contact_phone" class="inputbox"  size="10" required minlength="9"/>
                            <label class="error error-tip" for="contact_phone" id="phone_error" style="display: none; ">Please enter your phone number.</label>
                            <label class="error error-tip" for="contact_phone" id="invalid_phone_error" style="display: none; ">Please enter a valid phone number.</label>
                          </p>
                           </fieldset>
                           <fieldset class="w50">
                          <p class="form-subscr-field rowElem right">
                            <label for="contact_zip" id="contact_zip_label">Zip Code: *</label>
                            <input id="contact_zip" type="text" name="contact_zip" class="inputbox"  size="10" required minlength="5"/>
                            <label class="error error-tip" for="contact_zip" id="zip_error" style="display: none; ">Please enter your shipping zip code.</label>
                          </p>
                           </fieldset>
                          <p class="form-subscr-field">
                            <label for="contact_best_time" id="contact_best_time_label">Best time to Contact:</label>
                            <input id="contact_best_time" type="text" name="contact_best_time" class="inputbox"  size="10" />
                          </p>
                          <p class="form-subscr-field">
                            <label for="contact_message" id="comment_label">Your message: *</label>
                            <textarea id="contact_message" name="contact_message" rows="8" cols="30" required minlength="2"></textarea>
                            <label class="error error-tip" for="contact_message" id="message_error" style="display: none; ">This field is required.</label>
                          </p>
                          <input type="hidden" id="timestamp" name="timestamp" value="<?php
$hourdiff = "2"; // hours diff btwn server and local time
$insertdate = date("l, d F Y h:i a",time() + ($hourdiff * 3600));
print ("$insertdate");
?>" />
                          <div class="submit-contact">
                            <p>
                              <input type="submit" name="submit" class="cool-button csbutton-color spot-action" id="contact_button" value="Submit" />
                            </p>
                          </div>
                        </form>

Upvotes: 1

Views: 9721

Answers (3)

pete
pete

Reputation: 25091

I tend to break validation down for each input, which makes this stuff a lot easier. You could also use a jQuery plugin, which would probably be more modular in the long run.

That said, I would do it like this (working jsFiddle):

//contact form validation 
$(function() {
    $('.error').hide(); //hide all errors
    function fieldHasValue(field, label) {
        var value = field.val().trim(); //Grab value without leading or trailing whitespace
        if (value.length > 0) {
            label.hide();
        } else {
            label.show();
            field.focus();
        }
        return (value.length > 0);
    }
    function nameIsValid() {
        return fieldHasValue($("input#contact_name"), $("label#name_error"));
    }
    function emailIsValid() {
        var email = $("input#contact_email").val().trim(); //Grab value without leading or trailing whitespace
        var emailRegEx = /^([a-zA-Z0-9])(([a-zA-Z0-9])*([\._\-])?([a-zA-Z0-9]))*@(([a-zA-Z0-9\-])+(\.))+([a-zA-Z]{2,4})+$/;
        var isValid = (email.length > 0) && email.match(emailRegEx);
        if (isValid) {
            $("label#email_error").hide();
            $("label#invalid_error").hide();
        } else if (email.length > 0) {
            $("label#invalid_error").show();
            $("input#contact_email").focus();
        } else {
            $("label#email_error").show();
            $("input#contact_email").focus();
        }
        return isValid;
    }
    function phoneIsValid() {
        var phone = $("input#contact_phone").val().replace(/\s+-/g, "").trim(); //Grab value without leading or trailing whitespace and replace [whitespace -] with an empty string.
        var phoneRegEx = /^(1-?)?\s?(\([2-9]\d{2}\)|\s?-?[2-9]\d{2})-?\s?[2-9]\d{2}-?\d{4}$/;
        var isValid = (phone.length > 0) && phone.match(phoneRegEx);
        if (isValid) {
            $("label#invalid_phone_error").hide();
            $("label#phone_error").hide();
        } else if (phone.length > 0) {
            $("label#invalid_phone_error").show();
            $("input#contact_phone").focus();
        } else {
            $("label#phone_error").show();
            $("input#contact_phone").focus();
        }
        return isValid;
    }
    function zipIsValid() {
        return fieldHasValue($("input#contact_zip"), $("label#zip_error"));
    }
    function messageIsValid() {
        return fieldHasValue($("textarea#contact_message"), $("label#message_error"));
    }
    function bestTimeIsValid() {
        return fieldHasValue($("input#contact_best_time"), $("label#best_time_error"));
    }
    function allInputsAreValid() {
        var validName = nameIsValid();
        var validEmail = emailIsValid();
        var validPhone = phoneIsValid();
        var validZIP = zipIsValid();
        var validMessage = messageIsValid();
        var validBestTime = bestTimeIsValid();
        var isValid = validName && validEmail && validPhone && validZIP && validMessage && validBestTime;
        return isValid;
    }
    $("input#contact_name").on('change blur', nameIsValid);
    $("input#contact_email").on('change blur', emailIsValid);
    $("input#contact_phone").on('change blur', phoneIsValid);
    $("input#contact_zip").on('change blur', zipIsValid);
    $("textarea#contact_message").on('change blur', messageIsValid);
    $("input#contact_best_time").on('change blur', bestTimeIsValid);
    $("input#contact_button").on('click', function (e) {
        var timestamp = $("input#timestamp").val();

        if (allInputsAreValid()) {
            var dataString = 'contact_name=' + name + '&contact_email=' + email + '&contact_phone=' + phone + '&contact_zip=' + zip + '&contact_best_time=' + best_time + '&timestamp=' + timestamp + '&contact_message=' + encodeURIComponent(message);
            $.ajax({
                type: "POST",
                url: "php/contact.php",
                data: dataString,
                success: function() {
                    $('#contact-form').html("<div id='message'></div>");
                    $('#message').html("<h3>Message Sent</h3>").append("<p>Thank you for contacting us. We'll be in touch. <br /><br />If you have any further questions, you can always email us at [email protected] or call us at 800-924-9473</p>").hide().fadeIn(800, function() {
                        $('#message').append("<img id='checkmark' src='images/submit2.png' />");
                    });
                }
            });
        }
        e.preventDefault();
        return false;
    });
});

Upvotes: 0

Matt Wolfe
Matt Wolfe

Reputation: 9294

You should use some kind of validator plugin. Personally I've used jquery tools form validator and it works great.. There are others as well. Check this: http://flowplayer.org/tools/validator/

I also use a plugin that I built which will take a form and submit it via ajax, and there are some out there which work real similar to mine:

http://jquery.malsup.com/form/

Is one example. This allows you to make the form in normal html and it will submit the form to the form's action url, and it will build the forms values the same way the browser would if you submitted without ajax. Thus, to whatever your backend script is the form fields submit just as if you hadn't used ajax.

Since this seems like too much work for you, let me show you what your code looks like with and without it.

Without (look above at your js).

No assuming your form looks like this (simplified)

<form method="POST" action="php/contact.php">
  <label for="contact_name">Name</label>
  <input name="contact_name" id="contact_name" />
  <br />
  <label for="contact_email">Email</label>
  <input name="contact_email" id="contact_email" />
  <br />
  <label for="contact_phone">Phone</label>
  <input name="contact_phone" id="contact_phone" />
  <br />
  <label for="contact_zip">Zip</label>
  <input name="contact_zip" id="contact_zip" />
  <br />
  <label for="contact_best_time">Best time for Contact</label>
  <input name="contact_best_time" id="contact_best_time" />
  <br />
  <label for="contact_message">Message:</label>
  <input name="contact_message" id="contact_message" />
</form>

Now thats probably similar to what it looks like now without all the extra html for formatting.

If you used both the validator and the ajax form validator you have to make hardly any changes. Let me show them.

With the validator and ajax form you would then have this:

<form method="POST" action="php/contact.php" class="use-validator ajax-form">
  <label for="contact_name">Name</label>
  <input name="contact_name" id="contact_name" />
  <br />
  <label for="contact_email">Email</label>
  <input name="contact_email" id="contact_email" type="email" required="required" />
  <br />
  <label for="contact_phone">Phone</label>
  <input name="contact_phone" id="contact_phone" type="phone" />
  <br />
  <label for="contact_zip">Zip</label>
  <input name="contact_zip" id="contact_zip" required="required" />
  <br />
  <label for="contact_best_time">Best time for Contact</label>
  <input name="contact_best_time" id="contact_best_time" required="required" />
  <br />
  <label for="contact_message">Message:</label>
  <textarea name="contact_message" id="contact_message" required="required"></textarea>
</form>

Then your js would be:

$.tools.validator.fn("[type=phone]", "Invalid phone number", function(input, value) {   
   var phoneRegEx = /^(1-?)?\s?(\([2-9]\d{2}\)|\s?-?[2-9]\d{2})-?\s?[2-9]\d{2}-?\d{4}$/ 
   return value.test(phoneRegEx);
});

$("form.use-validator").validator();

$("form.ajax-form").ajaxForm({
 success:function(){$('#contact-form').html("<div id='message'></div>");$('#message').html("<h3>Message Sent</h3>").append("<p>Thank you for contacting us. We'll be in touch. <br /><br />If you have any further questions, you can always email us at [email protected] or call us at 800-924-9473</p>").hide().fadeIn(800,function(){$('#message').append("<img id='checkmark' src='images/submit2.png' />");});}});
});

And any custom validators you make you can reuse on other forms..

And then you may need some custom error messages but that's it.. You can delete all that other js code you have.

Upvotes: 0

Jeffrey Sweeney
Jeffrey Sweeney

Reputation: 6124

This is commonly achieved with the keyup function. Whenever a key is released, a function can be called to make sure that all the fields are accurate, and if so, left the user know in an unobtrusive way. In your case, you could have the submit button disabled unless all the fields are correct.

Note: You should never modify currently edited text fields with the function, or do anything else that will prove to be an annoyance to the user ;)


Edit: I modified the code to validate every time a key is lifted for all input fields. I'm not fluent in JQuery, so I did it with vanilla Javascript. If need be, it should be pretty easy to convert.

$(function(){


  var inputs = document.getElementsByTagName("input");

  for(var i = 0; i < inputs.length; i++) {

    inputs[i].addEventListener("keyup", function(){validate()}, true);

  }


  $('.error').hide();
  $(".cool-button").click(function(){validate()});

  function validate() {
                          $('.error').hide(); 
                          $("label#name_error").hide(); 
                          $("label#invalid_error").hide(); 
                          $("label#email_error").hide(); 
                          $("label#invalid_phone_error").hide(); 
                          $("label#phone_error").hide(); 
                          $("label#zip_error").hide(); 

                          var name=$("input#contact_name").val();
                          var email=$("input#contact_email").val();
                          var emailRegEx =/^([a-zA-Z0-9])(([a-zA-Z0-9])*([\._-])?([a-zA-Z0-9]))*@(([a-zA-Z0-9\-])+(\.))+([a-zA-Z]{2,4})+$/
                          var phone=$("input#contact_phone").val();
                          var phone=phone.replace(/\s+-/g, "");
                          var phoneRegEx = /^(1-?)?\s?(\([2-9]\d{2}\)|\s?-?[2-9]\d{2})-?\s?[2-9]\d{2}-?\d{4}$/
                          var zip=$("input#contact_zip").val();
                          var best_time=$("input#contact_best_time").val();
                          var message=$("textarea#contact_message").val();
                          var timestamp=$("input#timestamp").val();

                          if(name==""){
                          $("label#name_error").show();$("input#contact_name").focus();return false;
                          }
                          if(email==""){
                          $("label#email_error").show();$("input#contact_email").focus();return false;
                          }
                          if (document.getElementById('contact_email').value.search(emailRegEx )==-1) {
                          $("label#invalid_error").show();$("input#contact_email").focus();return false;
                          }
                          if(phone==""){
                          $("label#phone_error").show();$("input#contact_phone").focus();return false;
                          }
                          if (document.getElementById('contact_phone').value.search(phoneRegEx )==-1) {
                          $("label#invalid_phone_error").show();$("input#contact_phone").focus();return false;
                          }
                          if(zip==""){
                          $("label#zip_error").show();$("input#contact_zip").focus();return false;
                          }
                          if(message==""){
                          $("label#message_error").show();$("textarea#contact_message").focus();return false;
                          }
                          else {
                          var dataString='contact_name='+name+'&contact_email='+email+'&contact_phone='+phone+'&contact_best_time='+best_time+'&contact_zip='+zip+'&timestamp='+timestamp+'&contact_message='+encodeURIComponent(message);
                          $.ajax({
                                 type:"POST",
                                 url:"php/contact.php",
                                 data:dataString,
                                 success:function(){$('#contact-form').html("<div id='message'></div>");$('#message').html("<h3>Message Sent</h3>").append("<p>Thank you for contacting us. We'll be in touch. <br /><br />If you have any further questions, you can always email us at [email protected] or call us at 800-924-9473</p>").hide().fadeIn(800,function(){$('#message').append("<img id='checkmark' src='images/submit2.png' />");});}});
                          }
                          return false;
                          };
  });

Upvotes: 0

Related Questions