An important aspect of form handling is validation of input fields. Any time you're receiving data from a user, you should make sure that it won't harm anything. For a couple of reasons
We want to make sure that an action, if it fails, will fail gracefully. In other words...no BSOD (or the web equivalent). Anticipate how it can fail and catch it if it does. If we don't do this, it will have a negative impact on the user experience (UX)
We also want to make sure that malicious actors can't use our forms to hack our site. A common means of attack is intentionally entering bogus information in a form's field(s) to try to make the server fail. And thus obtain information that can further enable their attack
So, let's take a look at this:
Let's Go!I updated the process.php file, so it isn't quite as boring: process.php. Save this in your project's root folder, over-writing the original
Now, originally, I had the code written to just open up that boring old alert box. But we made a much better looking modal in our jquery-2 lab. So let's reuse that code a little, shall we?
Hint: you can copy/past the code directly from the code block below.
$(document).ready(function() {
// when user submits form
$('#submit').on('click', function() {
// get form information
let name = $('#name').val().trim(),
email = $('#email').val().trim();
//check for empty name value
if (name == '') {
displayError('Please enter a name');
return false;
}
// check for empty email value
if (email == '') {
displayError('Please enter an email address');
return false;
}
// check for valid email address
if (isEmail(email) == false) {
displayError('You entered an invalid email address');
return false;
}
/* Delete this, we won't need it for this assignment. The modal is
only going to launch if there's an error, which is handled by
the displayError() function
// if everything is correct,
// fade the form out
$('#contactForm').fadeOut();
// build the modal
$('#modal').html('You entered valid information');
$('#modal').append('<button id="ok">OK</button>');
// display the modal
$('#modal').fadeIn('slow');
// reset the form values
$('#email').val('');
$('#name').val('');
****************************************************/
}); // end of Submit event listener
// called by the submit event listener to
// display an error modal. 'm' is the error
// message
function displayError(m) {
$('#contactForm').fadeOut('slow');
$('#modal').html(m);
$('#modal').append('<button id="ok">OK</button>');
$('#modal').fadeIn('slow');
}
// fade the modal out and the form back in
$(document).on('click', '#ok', function() {
$('#modal').fadeOut('slow');
$('#contactForm').fadeIn('slow');
});
// use regex to validate the entered email format
// called by the submit event listener
function isEmail(email) {
let id = '^([a-zA-Z0-9_\\.\\-\\+])+',
domain = '(([a-zA-Z0-9\\-])+\\.)+',
tld = '([a-zA-Z0-9]{2,10})+$',
regex = new RegExp(id + '\\@' + domain + tld);
// combined: /^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,10})+$/
// id @ domain . tld
// if the entered email address doesn't match the pattern
if (!regex.test(email)) {
return false;
} else { // if it does match
return true;
}
}
}); // end of $(document).ready()
Notice here that we have to change the selector for the name variable to $('#first_name')
With this form, we'd like to capture all of the errors the user may make, rather than displaying them one at a time with a bunch of successive modals. We also want to add some visual feedback to show the user just where he or she screwed up
highlight() and resetBorder() will be created in a little bit. You can see with errorMessage that we're beginning to build the output for the modal. Each check, if triggered, will add its own bit to the message. Also, if the check is triggered, the flag, isValid will be set. We'll use that later to determine whether the form should be submitted
The else statement handles situations where a user might fix one error, but fail to fix others. The corrected field's display will revert to normal
So we can see with the last four screen shots, the script will check each field to see that everything's kosher. When an error is encountered, the error message is built. That way, when it's displayed, the user will be advised of all of the detected errors at once
It took me the longest time, when I was learning JavaScript and jQuery, to get used to the }); notation. If you stop and think about it, it makes perfect sense, given how the anonymous function is nested within the code. Anyway, if you set up the parantheses/brackets first, then add the code, things will usually work out ok
These two functions toggle the border of the offending text fields - red if they're not filled in; black if they're ok. This provides visual feedback, showing the user which field(s) is/are in error when the field is submitted
Notice here that we've removed the form fadeout() method and changed modal to modal-inner. This way, the modal will take up the whole display, while the error message will be displayed in the modal-inner element
Also, we've removed the form fadeIn() method. Ultimately, this time, the modal display will overlay the display, instead of fading the form out and in
Note to self: We have to modify the project's CSS before we're done...
This may seem a little counterintuitive. Why are we resetting the form before it's submitted? The answer is that the form will be initialized every time the document loads. The first time, it's already initialized, so it isn't noticeable. Subsequent times, (i.e., when the user returns to it after successful submission), it will initialize again, resetting the form values
#modal {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
height: 150px;
padding: 20px;
background: #444;
color: #ddd;
text-align: center;
font-size: 2rem;
z-index: 1;
}
#modal #ok {
position: absolute;
bottom: 15px;
left: 50%;
transform: translateX(-50%);
width: 100px;
height: 40px;
border-radius: 25px;
border-width: 0;
background: #ddd;
color: #444;
font-size: 1.4rem;
cursor: pointer;
}
#modal #ok:hover {
transition: .5s;
opacity: 0.6;
cursor: pointer;
}
While we're reusing the code to a large degree, pay close attention here. We also have to modify a few values and add a few properties/values to make it work.
Since #modal and #modal-inner share some properties and values, I'd duplicate the original #modal id, rename the second to #modal-inner, and make the above-listed changes to each
Some of the values for #modal-inner, by the way, were determined by again using the Developer Tools to tweak the appearance, then copying/pasting the code back in to the source document. I thought about having y'all do this, but the assignment's getting a little long already. Feel free, though, to experiment with the values to make the element display more to your liking
I still think this is super cool: the element starts the day empty (we probably don't even need the display: none; property in the CSS). It only is populated and displayed in response to a user error
Now we have the jQuery and CSS done (sort of), what have we (I) forgotten? Oh yeah! Add a link to index.html that includes validate.js
One potential scenario is that the user messes up two or more times. As the user corrects each omission and tries to submit the form, the error message will display differently and the border for the corrected field will be reset
Of course, that's good as far as it goes, but let's style the form a little better. Along the way, we'll learn a new way to select HTML elements in CSS (I think, thinking about it more, we may already have discussed this. But either way...)
It's looking pretty good. But we can make some subtle changes that will make it look more contemporary and professional
Now, there's a way we can select HTML for our CSS using an elements or elements' values. This is super cool, particularly when styling forms, which have a bunch of <input> elements of different types. We can single out a specific type for styling
We could use any attribute here. For example, we could style an anchor element that has a certain href attribute value:
would apply those rules only to links to ETSU's website
I used the developer tools trick again to get the position the way I wanted it. You might have different ideas - feel free to play around with this. I tested the final product for responsiveness and it worked pretty well
Have a nice day 😊