I used a tutorial from css-tricks to help me with HTML5 Constraint Validation for my application's client-side validation. I would like to introduce an AJAX script that submits the form to prevent reloading the page (as the form is displayed in a modal pop-up that I don't want closing on submit.)
From what I have gathered online, it seems the best way to do this is to use jQuery. However, the validation script is written in regular ol' Javascript.
I'm kind of confused as to how to implement this within my validation script so that I don't need to make another http request to a separate js file (not even sure if that's an option, as I kind of need it to work seamlessly with the existing script). Do I just call jQuery inside the existing script to prevent conflicts (as shown below?) Do I need to wrap the entire script in the ready event?
Currently, I'm not sure why this isn't working. The form still submits and reloads the page, so it seems to be ignoring the Ajax submit function.
The following includes the form markup from its PHP class and the form.validate.js file used for validation and ajax:
function copyTxtVal(bf) {
if(bf.samecheck.checked == true) {
bf.contact_name_first.value = bf.cpap_sup_name_first.value;
bf.contact_name_last.value = bf.cpap_sup_name_last.value;
} else {
bf.contact_name_first.value = '';
bf.contact_name_last.value = '';
}
}
// Add the novalidate attribute when the JS loads
var forms = document.querySelectorAll('.validate');
for (var i = 0; i < forms.length; i++) {
forms[i].setAttribute('novalidate', true);
}
// Validate the field
var hasError = function (field) {
// Don't validate submits, buttons, file and reset inputs, and disabled fields
if(field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') return;
// Get Validity
var validity = field.validity;
// Get valid, return null
if(validity.valid) return;
// If field is required and empty
if (validity.valueMissing) return 'Please fill out this field.';
// If not the right type
if (validity.typeMismatch) {
if(field.type === 'email') return 'Please enter an email address.';
if(field.type === 'url') return 'Please enter a URL.';
}
// If too short
if (validity.tooShort) return 'Please lengthen this text to ' + field.getAttribute('minLength') + ' characters or more. You are currently using ' + field.value.length + ' characters.';
// If too long
if (validity.tooLong) return 'Please short this text to no more than ' + field.getAttribute('maxLength') + ' characters. You are currently using ' + field.value.length + ' characters.';
// If number input isn't a number
if (validity.badInput) return 'Please enter a number.';
// If a number value doesn't match the step interval
if (validity.stepMismatch) return 'Please select a valid value.';
// If a number field is over the max
if (validity.rangeOverflow) return 'Please select a smaller value.';
// If a number field is below the min
if (validity.rangeUnderflow) return 'Please select a larger value.';
// If pattern doesn't match
if (validity.patternMismatch) {
// If pattern info is included, return custom error
if (field.hasAttribute('title')) return field.getAttribute('title');
// Otherwise, generic error
return 'Please match the requested format.';
}
// If all else fails, return a generic catchall error
return 'The value you entered for this field is invalid.';
};
var showError = function(field, error){
// Add error class to field
field.classList.add('error');
// Get field id or name
var id = field.id || field.name;
if (!id) return;
// Check if error message field already exists
// If not, create one
var message = field.form.querySelector('.error-message#error-for-' + id );
if (!message) {
message = document.createElement('div');
message.className = 'error-message';
message.id = 'error-for-' + id;
field.parentNode.insertBefore( message, field.nextSibling );
}
// Add ARIA role to the field
field.setAttribute('aria-describedby', 'error-for-' + id);
// Update error message
message.innerHTML = error;
// Show error message
message.style.display = 'block';
message.style.visibility = 'visible';
}
var removeError = function(field) {
// Remove the error message
// Remove error class to field
field.classList.remove('error');
// Remove ARIA role from the field
field.removeAttribute('aria-describedby');
// Get field id or name
var id = field.id || field.name;
if (!id) return;
// Check if an error message is in the DOM
var message = field.form.querySelector('.error-message#error-for-' + id + '');
if (!message) return;
// If so, hide it
message.innerHTML = '';
message.style.display = 'none';
message.style.visibility = 'hidden';
};
//Listen to all blur events
document.addEventListener('blur', function (event) {
// Only run if field is in a form to be validated by our custom script
if (!event.target.form.classList.contains('validate')) return;
// Validate field
var error = hasError(event.target);
// If there's an error, show it
if(error){
showError(event.target, error);
return;
}
//Otherwise, remove any existing error msg
removeError(event.target);
}, true);
// Check all fields on submit
document.addEventListener('submit', function (event) {
// Only run on forms flagged for validation
if (!event.target.classList.contains('validate')) return;
// Get all of the form elements
var fields = event.target.elements;
// Validate each field
// Store the first field with an error to a variable so we can bring it into focus later
var error, hasErrors;
for (var i = 0; i < fields.length; i++) {
error = hasError(fields[i]);
if (error) {
showError(fields[i], error);
if (!hasErrors) {
hasErrors = fields[i];
}
}
}
// If there are errors, don't submit form and focus on first element with error
if (hasErrors) {
event.preventDefault();
hasErrors.focus();
}
// Call self invoking jQuery function to handle form submit by Ajax if validation passes
else {
(function($){
var form = $('#cpapsupform');
var formMessages = $('#cpap-form-messages');
// Is this line below necessary if I've done this in the normal js above?
$(form).submit(function(event){
event.preventDefault();
// Serialize Form Data
var formData = $(form).serialize();
//Submit the form via AJAX
$.ajax({
type: 'POST',
url: $(form).attr('action'),
data: formData
})
.done(function(response) {
// Make sure that the formMessages div has the 'success' class.
$(formMessages).removeClass('error');
$(formMessages).addClass('success');
// Set the message text.
$(formMessages).text(response);
// Clear the form.
$('#cpap_sup_name_first').val('');
$('#cpap_sup_name_last').val('');
$('#contact_name_first').val('');
$('#contact_name_last').val('');
$('#cpap_contact_email').val('');
$('#cpap_contact_phone').val('');
$('#cpap_patient_dob').val('');
$('#cpap_patient_zip').val('');
})
.fail(function(data) {
// Make sure that the formMessages div has the 'error' class.
$(formMessages).removeClass('success');
$(formMessages).addClass('error');
// Set the message text.
if (data.responseText !== '') {
$(formMessages).text(data.responseText);
} else {
$(formMessages).text('An error occured and your message could not be sent.');
}
});
});
})(jQuery);
}
}, false);
Here is the form markup (excerpted from the php form class I am using):
<?php
<div id="cpap-form-area">
<div id="cpap-form-messages"></div>
<div class="cpap-form-greet">
<p>Some text goes here.</p>
</div>
<form method="POST" action="" id="cpapsupform" class="validate" enctype="multipart/form-data" >
<fieldset>
<legend>Patient Name</legend>
<div class="p-firstname">
<label for="cpap_sup_name_first">First Name:</label>
<input type="text" size="50" name="cpap_sup_name_first" id="cpap_sup_name_first" value="<?php echo $display['cpap_sup_name_first']; ?>" required />
</div>
<div class="p-lastname">
<label for="cpap_sup_name_last">Last Name:</label>
<input type="text" size="50" name="cpap_sup_name_last" id="cpap_sup_name_last" value="<?php echo $display['cpap_sup_name_last']; ?>" required />
</div>
</fieldset>
<fieldset>
<legend>Point of Contact</legend>
<div class="samename">
<div class="cpap_input_alt">
<input id="samecheck" type="checkbox" name="samecheck" onchange="copyTxtVal(this.form);">
</div>
<label for="samecheck">Use same as above</label>
</div>
<div class="c-firstname">
<label for="contact_name_first">First Name:</label>
<input type="text" size="50" name="contact_name_first" id="contact_name_first" value="<?php echo $display['contact_name_first']; ?>" required />
</div>
<div class="c-lastname">
<label for="contact_name_last">Last Name:</label>
<input type="text" size="50" name="contact_name_last" id="contact_name_last" value="<?php echo $display['contact_name_last']; ?>" required />
</div>
</fieldset>
<fieldset>
<legend>Contact Details</legend>
<div class="cpap-email-contact">
<label for="cpap_contact_email">Email:</label>
<input type="email" name="cpap_contact_email" id="cpap_contact_email" value="<?php echo $display['cpap_contact_email']; ?>" title="The domain portion of the email after '#' is invalid." pattern="^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*(\.\w{2,})+$" required />
</div>
<div class="cpap-tel-contact">
<label for="cpap_contact_phone">Phone:<br /><span class="tiny-txt">(10 digits; no spaces)</span></label>
<input type="text" maxlength="10" name="cpap_contact_phone" id="cpap_contact_phone" value="<?php echo $display['cpap_contact_phone']; ?>" pattern="\d{10}" required />
</div>
</fieldset>
<fieldset>
<legend>Patient Date of Birth</legend>
<div class="cpap-dob">
<label for="cpap_patient_dob">Birthdate: <br /><span class="tiny-txt">(MM/DD/YYYY)</span></label>
<input type="text" name="cpap_patient_dob" id="cpap_patient_dob" value="<?php echo $display['cpap_patient_dob']; ?>" title="Your date looks incorrect, or it doesn't match the required format." max-length="10" pattern="((0[1-9])|(1[0-2]))/(([0-2]\d)|([3][01]))/((19|20)\d{2})" required ></input>
</div>
</fieldset>
<fieldset>
<legend>Address Info</legend>
<div class="cpap-zip">
<label for="cpap_patient_zip">Patient Zipcode:<br /><span class="tiny-txt">(first 5 digits only)</span></label>
<input type="text" maxlength="5" name="cpap_patient_zip" id="cpap_patient_zip" value="<?php echo $display['cpap_patient_zip']; ?>" required ></input>
</div>
</fieldset>
<button type="submit" id="cpapAjaxButton" name="cpapAjaxButton">Submit Request</button>
<p class="form-msg">All fields must be completed</p>
<div class="clearfix"></div>
<?php wp_nonce_field('submit_cpap_form','nonce_field_for_submit_cpap_form'); ?>
</form>
</div>
First, you do have a syntax error in that you are missing the opening curly brace of your else branch right here:
// Call self invoking jQuery function to handle form submit by Ajax if validation passes
else (function($){
It should be:
// Call self invoking jQuery function to handle form submit by Ajax if validation passes
else { (function($){
And, to avoid these kinds of errors, good indentation and formatting of code goes a long way, so really, this would be the best way to write it:
// Call self invoking jQuery function to handle form submit by Ajax if validation passes
else {
(function($) {
Now, to you main point. As long as you have referenced the JQuery library prior to your code needing to use it, you just go ahead and use JQuery when and where you need to. If you need some page initialization work done, then yes, a "document ready" function should be passed into the JQuery object. But, apart from that, you can leverage JQuery whenever you need to so the self-invoking function you have inside of your else branch is redundant - - if code execution enters that branch, you don't invoke JQuery again, you just use it.
Also, you start off with:
document.addEventListener('submit', function (event) {
But, the document object doesn't have a submit event. The event listener should be set up on the form element that is going to be submitted.
You also have some unnecessary variables and in a couple of cases, you set your variables equal to JQuery objects, but then passed those objects into the JQuery object again later as if they were regular DOM objects.
Here is your cleaned up code. Check the comments carefully for what changes were made and why. Also, this is the best we can do with answers since you didn't provide the hasError and showError functions and your HTML as well.
// The document object doesn't get submitted, the form does.
// Also this sytax finds every form that has the "validate" class,
// so there is no need to test for that in the callback function
$("form.validate").on('submit', function (event) {
// Get all of the form elements
var fields = event.target.elements;
// Always initialize your variables. Set them to null if you don't know the value to use yet
// Also, the "error" and "hasError" variables are not needed. You'll see why in a couple of lines down.
var hasErrors = null;
for (var i = 0; i < fields.length; i++) {
// I'm assuming you have a working "hasError" function that returns a boolean
// So, just take that return value and make that the basis for the if condition -- no
// need to store it just to test it on the next line.
if (hasError(fields[i])) {
// I'm assuming you have a working "showError" function. If we've entered into this
// branch of the code, we know that "hasError" returned true, so we can just pass that
// directly into the "showError" function instead of the "error" variable that we've
// now gotten rid of.
showError(fields[i], true);
// No need to test here. There is an error.
hasErrors = fields[i];
}
}
// If there are errors, don't submit form and focus on first element with error
if (hasErrors) {
event.preventDefault();
hasErrors.focus();
} else {
// You don't need a self-invoking function here. Just write the code that should execute
// It is a common convention to name variables that store references to JQuery objects
// with a leading $ to distinguish them as such and not regular DOM objects
var $form = $('#cpapsupform');
var $formMessages = $('#cpap-form-messages');
// Submit the form via AJAX
$.ajax({
type: 'POST',
url: $form.attr('action'), // $form is already a JQuery object, don't pass it to JQuery again
data: $form.serialize() // <-- You had semi-colon here, which you shouldn't have
}).done(function(response) {
// $formMessages is already a JQuery object, don't pass it to JQuery again
$formMessages.removeClass('error');
$formMessages.addClass('success');
// Set the message text.
$formMessages.text(response);
// Just use the DOM form.reset() method here instead of resetting each form field
$form[0].reset();
}).fail(function(data) {
// Make sure that the formMessages div has the 'error' class.
$formMessages.removeClass('success');
$formMessages.addClass('error');
// Set the message text.
if (data.responseText !== '') {
$formMessages.text(data.responseText);
} else {
$formMessages.text('An error occured and your message could not be sent.');
}
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="GET" class="validate">
<input type="text" id="name">
<input type="submit">
</form>
<form action="#" method="GET">
<input type="text" id="name">
<input type="submit">
</form>
jQuery IS Javascript, so of course you can use them together. I think your problem might lie in you not properly bracketing your else statement:
else { (function($){ // was missing brace after 'else'
var form = $('#cpapsupform');
var formMessages = $('#cpap-form-messages');
....
})(jQuery);
}//closing else brace
Related
I'm making sign in form with submit. What I want to do is to alert when there is blank in the form. But the function only works when all of the form are filled. Here's the HTML and JS code. The result is the same using onsubmit inside of the HTML or addEventListener("submit" function name)
HTML : It's basically a form for sign in / ordering.
<form id="registration" method="POST" onsubmit="return validate();" action="phplink">
<p> <label for="custName">Name : </label>
<input type="text" id="cname" name="cname" required="required" /> </p>
</form>
JS :
function validate(event) {
event.preventDefault();
var r = document.getElementById("registration");
var cname = r.cname.value;
var errMsg = "";
if (cname == "") {
errMsg += "Please enter your Name.\n";
}
if (errMsg.length != 0) {
alert(errMsg);
result = false;
}
return result;
}
The validation constrains, such as your required="required" are validated before your browser will trigger a submit event. If the validation fails (a value to a required field is not provided) it will not submit your form.
If you want to do the validation using JavaScript instead of the validation constraint attributes, you either need to remove the required="required" attribute (together with any other similar attributes) or you can add the novalidate attribute to your form to indicate that it should not perform this validation on submit.
If you use the latter, you can still use formElement.reportValidity() to see if all the elements satisfy their validation constraints.
If you add a required attribute to each field that shouldn’t be blank, it’ll prevent form submission with empty fields, like this...
<input type="text" name="username" required>
Hi you have several problem. on submit must pass event => onsubmit="return validate(event);" .
you must first defined result and thats your flag => var result = false .
if you want show alert then input dont need required attribute.
so this is your Fixed Code;
function validate(event) {
event.preventDefault();
var result = true;
var r = document.getElementById("registration");
var cname = r.cname.value;
var errMsg = "";
if (cname == "") {
errMsg += "Please enter your Name.\n";
}
if (errMsg.length != 0) {
alert(errMsg);
result = false;
}
return result;
}
I am trying to clear an error icon on keydown.
** EDIT - adding the HTML **
<input class="validate" type="text" data-type="string" id="address" />
<input class="validate" type="text" data-type="number" id="zip" />
** END EDIT - Unsure if this will help shed some light **
Currently, the error displays using this function:
function validateFields(){
$(".validate").blur(function(){
var status = "";
var label = this.id;
var value = this.value;
if(value != ""){
status = "good";
console.log("status " + status);
}
else{
status = "error";
console.log("status " + status);
}
if(status == "good"){
label.html(label.html()+' ✅');
}
if(status == "error"){
label.html(label.html()+' ❌');
}
});
}
If status equals Error, show the error icon.
So now, I want to clear the error when the user keydowns. Here is my attempt:
function clearError(){
$(".validate").keydown(function(){
var datatype = $(this).data("type");
var label = this.id;
label.html(label.html()+' ');
});
}
Obviously, I am not having much success clearing the error using the above keydown function.
How can I make this work?
The label business with trying to keep the text inside is not very intuitive, so I added span to your label so you remove and add error symbols from the span in your functions. Additionally, you had some unnecessary code that could be removed in both functions. For example, your if statements checking status were unnecessary since you already checked if the value was empty (where you set the status), therefore you could move that code into the if statement checking for empty values.
We set each corresponding span's id to the id of the input with "Span" id="testSpan", so it can be easily accessible by the JS functions. Remember inside jQuery functions this always refers to the non-jQuery object, so you can use the JS vanilla methods on it.
This is what I could come up with:
$(".validate").blur(function () {
var id = this.id; // get id
if (this.value != "") { // check if input is empty
document.getElementById(id + "Span").innerHTML = '✅'; //set ok symbol
console.log("good");
} else {
document.getElementById(id + "Span").innerHTML = '❌'; // set error symbol
console.log("error empty text");
}
});
$(".validate").keydown(function () {
// if value is empty set error symbol, otherwise nothing (keep ok symbol)
if (this.value === "") document.getElementById(this.id + "Span").textContent = "";
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="test">test<span id="testSpan"></span></label>
<input id="test" class="validate">
<label for="test2">test<span id="test2Span"></span></label>
<input id="test2" class="validate">
I am writing three functions in javascript to do different things. Search functions only needs firstname and lastname. Add and update functions needs everything to filled out completely. I have those working, however when submitting form, if anything is missing, it alerts me but still submits it. I don't want it to do that, how can i do it?
function search() {
checkme = false
//alert('all feilds must be filled out');
var nameExpression = /^[a-zA-Z]+$/;
firstName = document.getElementById('firstName').value;
lastName = document.getElementById('lastName').value;
//check firstname
if (firstName!=""&&nameExpression.test(firstName)) {
checkme = true;
}else{
document.getElementById("firstName").classList.add("is-invalid");
alert("Please enter valid first name");
}
//check lastName
if (lastName!=""&&nameExpression.test(lastName)) {
checkme = true;
}else{
document.getElementById("lastName").classList.add("is-invalid");
alert("Please enter valid last name");
}
return checkme;
}
, here is how i am calling the function as well
<input name="Action" type="submit" name="Search" value="Search" onclick="return search();"">
The reason your function fails to stop submission, is because of a system called event bubbling, where an event propagates up the DOM tree, and any handlers related to that event are triggered. There are also default events that occur on certain actions. Some of these are cancelable events, one of which is the Form Submit event. The e.preventDefault() command basically cancels the default action of the event, which is submitting the form, and prevents it from submitting regardless of the output of your function. We then call the submit() function manually when all requirements are satisfied.
Here's a version that I feel is shorter and easier to understand. No checkme variables needed either. It assumes your form has the id yourForm, and submits it if both first and last names pass the RegEx check.
function search(e) {
e.preventDefault();
const nameExpression = /^[a-zA-Z]+$/;
const firstName = document.getElementById('firstName').value;
const lastName = document.getElementById('lastName').value;
const yourForm = document.getElementById('yourForm');
if (nameExpression.test(firstName) && nameExpression.test(lastName)) {
yourForm.submit();
} else {
alert('All fields must be filled out, and contain only alphabets');
}
}
document.getElementById('yourForm').addEventListener('submit', search);
<form id="yourForm">
<input type="text" id="firstName" placeholder="First Name" />
<br>
<input type="text" id="lastName" placeholder="Last Name" />
<br>
<input name="Action" type="submit" name="Search" value="Search">
</form>
P.S. You can do what you are trying to do here in pure HTML by adding the pattern attribute to your first and last name inputs. This also helps in case the user has an extension like NoScript installed, but the downside is you cannot control how the validation error looks.
(I'm beginner/intermediate in JS) I once also worked on something like this. I would suggest to add a paramater of 'e' in your function, en then writing "e.preventDefault" In your code. It would prevent the default submit action of your form. And then, you can submit the form in JS if it matches a certain condition, and if not, it will give you an alert.
Im guessing checkme, firstName and lastName weren't defined yet.
function search(e) {
e.preventDefault();
var checkme = false;
//alert('all fields must be filled out');
var nameExpression = /^[a-zA-Z]+$/;
var firstName = document.getElementById('firstName').value;
var lastName = document.getElementById('lastName').value;
//check firstname
if (firstName!=""&&nameExpression.test(firstName)) {
checkme = true;
} else {
document.getElementById("firstName").classList.add("is-invalid");
alert("Please enter valid first name");
}
//check lastName
if (lastName!=""&&nameExpression.test(lastName)) {
checkme = true;
} else {
document.getElementById("lastName").classList.add("is-invalid");
alert("Please enter valid last name");
}
if (checkme == true) {
your_form.submit();
}
This may not be a perfect solution to your problem, but this is roughly how I do these things with JS and validating forms. I hope this helped.
Edit:
The code is the author's source code, I tried to not edit it too much.
I got most of this form validation to work properly but the only issue is that when the form detects an error on submit and the user corrects the mistake, the error text won't go away. This can be confusing for the user but I can't seem to figure out a way to make the error text disappear with the way that I am doing this. Also I know I have the option of PHP validation but there is a few reasons why I want to use this front end validation. Here is the whole validation script for the form. The submit portion is at the bottom:
JavaScript/jQuery
var valid = 0;
function checkName(elem) {
//gather the calling elements value
var val = document.getElementById(elem.id).value;
//Check length
if (val.length<1) {
document.getElementById("errorName").innerHTML = "<span>Don't forget your name.</span>";
} else if (val.length>40){
document.getElementById("errorName").innerHTML = "<span>This doesn't look like a name.</span>";
//If valid input increment var valid.
} else {
document.getElementById("errorName").innerHTML = "";
valid++;
}
}
function checkEmail(elem) {
var val = document.getElementById(elem.id).value;
//Check email format validity
var re = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (!re.test(val)) {
document.getElementById("errorEmail").innerHTML = "<span>Please enter a valid email.</span>";
} else {
document.getElementById("errorEmail").innerHTML = "";
valid++;
}
}
function checkMessage(elem) {
var val = document.getElementById(elem.id).value;
if (val.length<1) {
document.getElementById("errorMessage").innerHTML = "<span>It looks like you forgot the message.</span>";
} else if (val.length>2000) {
document.getElementById("errorMessage").innerHTML = "<span>It looks like your message is too long.</span>";
} else {
document.getElementById("errorMessage").innerHTML = "";
valid++;
}
}
//Contact: jQuery check for null/empty/errors
$(document).ready(function() {
function checkSubmit() {
if (valid == 3) {
document.getElementById("errorSubmit").innerHTML = "";
}
}
//If errors when submitting display message
$('#form13').submit(function(submit) {
if ($.trim($("#name").val()) === "" || $.trim($("#email").val()) === "" || $.trim($("#message").val()) === "") {
document.getElementById("errorSubmit").innerHTML = "<span>Please fill out all the form fields.</span>";
submit.preventDefault();
} else if (valid < 3) {
document.getElementById("errorSubmit").innerHTML = "<span>Please check the errors above.</span>";
submit.preventDefault();
}
})
});
HTML Form
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="cform" id="contact-form">
<form id="form13" name="form13" role="form" class="contactForm" accept-charset="UTF-8" autocomplete="off" enctype="multipart/form-data" method="post" novalidate
action="https://Some3rdPartyPOSTService">
<div class="form-group">
<label for="name">Your Name</label>
<input type="text" name="Field1" class="form-control" id="name" placeholder="Tony Stark" onblur="checkName(this)"/>
<span id="errorName" style="margin-left:10px;"></span>
</div>
<div class="form-group">
<label for="email">Your Email</label>
<input type="email" class="form-control" name="Field4" id="email" placeholder="" data-rule="email" data-msg="Please enter a valid email" onblur="checkEmail(this)"/>
<span id="errorEmail" style="margin-left:10px;"></span>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea class="form-control" name="Field3" id="message" rows="5" data-rule="required" data-msg="Please write something here" onblur="checkMessage(this)"></textarea>
<span id="errorMessage" style="margin-left:10px;"></span>
</div>
<span id="errorSubmit" style="margin-left:10px;"></span>
<button type="submit" class="btn btn-theme pull-left">SEND MESSAGE</button>
</form>
</div>
</div>
<!-- ./span12 -->
</div>
</div>
</section>
Simply put your check on onChange event callback, if:
var x = getElementById("formid"); // then add a listener
x.addEventListener('change', function () {
callback with your code that examines the form
});
Or listen for a specific text box change event, that would be the simplest way, and look for a way to disable submit if the conditions aren't met.
Add an onchange event to your text inputs that will remove the error message.
Rather than making a count of valid fields, I would also check for the existence of error messages. This will make it easier to add more fields to your form.
function checkName(e) {
//gather the calling elements value
var val = $(e.target).val();
//Check length
if (val.length<1) {
document.getElementById("errorName").innerHTML = "<span class="errmsg">Don't forget your name.</span>";
} else if (val.length>40){
document.getElementById("errorName").innerHTML = "<span class='errmsg'>This doesn't look like a name.</span>";
//If valid input increment var valid.
} else {
document.getElementById("errorName").innerHTML = "";
}
}
function checkEmail(e) {
var val = $(e.target).val();
//Check email format validity
var re = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (!re.test(val)) {
document.getElementById("errorEmail").innerHTML = "<span class='errmsg'>Please enter a valid email.</span>";
} else {
document.getElementById("errorEmail").innerHTML = "";
}
}
function checkMessage(e) {
var val = $(e.target).val();
if (val.length<1) {
document.getElementById("errorMessage").innerHTML = "<span class='errmsg'>It looks like you forgot the message.</span>";
} else if (val.length>2000) {
document.getElementById("errorMessage").innerHTML = "<span class='errmsg'>It looks like your message is too long.</span>";
} else {
document.getElementById("errorMessage").innerHTML = "";
}
}
//Contact: jQuery check for null/empty/errors
$(document).ready(function() {
$('#name').change(checkName);
$('#email').change(checkEmail);
$('#message').change(checkMessage);
function checkSubmit() {
if ($('form .errmsg').length > 0) {
document.getElementById("errorSubmit").innerHTML = "";
}
}
}
/If errors when submitting display message
$('#form13').submit(function(submit) {
if ($.trim($("#name").val()) === "" || $.trim($("#email").val()) === "" || $.trim($("#message").val()) === "") {
document.getElementById("errorSubmit").innerHTML = "<span class='errmsg'>Please fill out all the form fields.</span>";
submit.preventDefault();
} else if ($('form .errmsg').length > 0) {
document.getElementById("errorSubmit").innerHTML = "<span class='errmsg'>Please check the errors above.</span>";
submit.preventDefault();
}
})
});
Since you were already using jQuery, I modified the code to use more of the jQuery functionality to make things easier. Now when a form field is modified and the element loses focus, the validation will occur immediately. We also no longer need to know how many error messages could potentially appear (though you never had a decrement operation for corrected values so the valid could become greater than 3). Instead we just make sure that there isn't more than 0 of them.
I've removed your onblur html attributes and replaced them by JavaScript keyup events. This will allow your script to check everything as soon as the user type something :
document.getElementById("message").addEventListener('keyup', function () {
checkMessage(this);
});
document.getElementById("email").addEventListener('keyup', function () {
checkEmail(this);
});
document.getElementById("name").addEventListener('keyup', function () {
checkName(this);
});
JSFIDDLE
I have a strange behaviour in IE browser.
I have simple form:
<form name="test" id="test" action="some_url_here" method="post">
<input type="text" name="url" id="url" class="required" />
<input type="text" name="page" id="page" class="required" />
...
<input type="submit" name="submit" value="Submit" />
</form>
and in JS:
var result = true;
$("#test").on("submit", function(){
$(".required").removeClass("error");
$.each($("input.required"), function(k, v) {
if($(this).val() === '') {
$(this).addClass("error");
result = false;
return false;
}
});
if(result) {
if(!IsValidUrl($("input[name='url']").val()){
$("input[name='url']").addClass("error");
return false;
}
} else {
return false;
}
});
Let's assume that I filled all fields correctly.
In Chrome & Firefox, when I press on submit button then works fine, just once time.
In IE (all versions) I have to press two times on the submit form to execute/sumbit the form.
Why ?
I tried also to put after IsValidUrl condition:
$(this).submit();
But no success.
You have two options here. On both you need to stop the submit event and validate the form.
One is to go through all the fields in the form, add the class error to the invalid ones (if there's any), set the variable result and return (or submit if everything is alright).
The other is to stop the test at the first invalid field found, not using the variable result, and return (or submit if everything is alright).
JS
$(function () {
$("#test").on("submit", function (e) {
// Stop the submit, because you need to validate the form before proceeding.
e.preventDefault();
// Check the comments below to decide for the use of the variable.
var result = true;
$(".required").removeClass("error");
$.each($("input.required"), function (k, v) {
// Test for empty fields or, if it's the URL, check whether is valid.
if ($(this).val() === "" || ($(this).attr("name") == "url" && !IsValidUrl($(this).val())) {
// Add class error to the invalid fields.
$(this).addClass("error");
// At this point, you could just return false stopping the loop,
// or keep going to make sure all the invalid fields will get the
// class error. In this case, you can still use the variable result.
result = false;
// Keep going, so, no return.
// return false;
}
});
// If you decided to carry on through all the fields, and don't return
// false at the first error, test for the result value.
// As this is the case...
if (!result) return false;
else $(this).submit();
// If you didn't return previously...
// $(this).submit();
});
});