JavaScript Form Processing

Individual Field Validations

When we use modern unobtrusive JavaScript to attach our validation functions to our form fields using event listeners we don't pass the element that triggered the event as a parameter the way we used to with the obtrusive event handlers that we used to code in the HTML. While we could make each validation function specific to a particular form field and simply retrieve the form field element again using a copy of the same getElementById call that we used to attach the event listener to the field, there is a better way.

Instead of simply retrieving the specific element again we can do a call to retrieve whichever element triggered the event listener in the first place. This will give us the flexibility to attach the same function to two separate event listeners where the same validation is required and have the validation apply to whichever field triggered the function without needing to either pass that element into the function or to hard code the element into the function (and so not be able to share the function).

We can do this because the event that triggered the function is accessible from within the function and the event knows what element is is currently processing.

Since we again have versions of Internet Explorer that operate differently from the standards we first need one extra function that will retrieve the element from the event which tests which uses feature sensing to retrieve the element from whichever place the browser stores it.


whichElement = function(e) {
  var targ;
  targ = (window.event) ? window.event.srcElement : e.target;
  if (3===targ.nodeType) {
    targ = targ.parentNode;
  }
  return targ;
};

With that function in place we can easily get the element that called the validateMyField function by calling the whichElement function as the first thing inside of the function.

Note that as most browsers pass the event that triggered the function as a parameter into the function we need to define it as an argument for our function to be able to pass it to the whichElement function which is not being triggered directly by an event and so would not otherwise have the event passed to it.

Calling the argument that receives the event "e" is a convention that many people follow, you don't have to name it that just as long as you name it consistently.


validateMyField = function(e) {
var elem = whichElement(e);
... // code to do validation on elem.value goes here
};

With this code in place our validation function is independent of a specific form field and can be attached to any form field where we want the particular validation to be applied and elem.value will automatically reference the value contained within the form field where an event triggered this function.

This allows us to attach our validation function directly to an event listener on the specific form field but what about when we want to rerun all of the validations for the entire form before we submit the form? The code we currently have does not allow for that so we need to make a slight modification so that the function can be called from a more general validation function as well as being attached directly to the form field.


validateMyField = function(e, elem) {
if (elem === undefined) elem = whichElement(e);
... // code to do validation on elem.value goes here
};

We have now added a second optional argument into our function which if present will pass in the specific element to be processed by the function. If that argument is not supplied then we will assume that the function has been called directly in response to an event and will use the whichElement() function to retrieve the element that the event was triggered on.

When we want to call this validation from within the function that performs the validation of the entire form we'll simply include the element to be validated in the call. So from within our validateForm function we'd call validateMyField like this:


validateForm = function(e) {
validateMyField(e,document.getElementById('myfield'));
...
};