Home » Tutorials Advanced Tutorial

JavaScript and Accessibility. Pt. 2.

3.5/5.0 (2 votes total)
Rate:

Jonathan Fenocchi
February 17, 2006


Jonathan Fenocchi
Jonathan Fenocchi is a talented young developer coming at you from southern TX, USA. Accessibility advocate, proficient programmer, and determined designer, Jonathan spends his free time researching new technologies, developing new ideas, playing video games and listening to rock music. Jonathan runs a Slightly Remarkable blog where he focuses on web-related content, and continues to pursue his goals as an aspiring web developer."

Jonathan Fenocchi has written 20 tutorials for JavaScriptSearch.
View all tutorials by Jonathan Fenocchi...

Last week we began this series with a discussion about new practical and standards-compliant use of JavaScript. In part one of this series, we covered how functionality and usability will be the primary concerns of JavaScript in 2005. We introduced Web Standards, what they mean to the developer, introduced the reader to responsible scripting, and began a discussion concerning classical techniques and how to fix them. We continue that this week beginning with Form Validation. [Ed. note.]

Form Validation

Another classical idea is form validation. Here’s an example:

The Script.
<script type=”text/javascript”><!—
  function validateForm(){
    if(myForm.fName == "" || myForm.lName == "" || myForm.fColor == ""){
      alert("Please fill in all fields.");
    return false;
  }
 return true;
}
//--></script>

The HTML.
<form name="myForm" action="some-script.pl" method="post" onsubmit="return validateForm()"><fieldset>
<legend>Enter your information</legend>
<label>First name: <input type="text" name="fName"></label><br>
<label>Last name: <input type="text" name="lName"></label><br>
<label>Favorite color: <input type="text" name="fColor"></label><br>
<label><input type="submit" value="Submit form"></label>
</fieldset></form>

This script may work in some cases, but it has a few flaws. The form, named “myForm,” is referenced in the global scope. This is wrong because “myForm” could also be a variable. It is also incorrect to use document.all[“myForm”] since, according to the W3C specifications, there is no such thing as “document.all.” The script is unlikely to work in most browsers, and sure to fail in archaic ones. Another problem is that you could enter a space in any of the fields and the script would assume it is valid. You may already know, but for clarification, the “return” part of our code in the onSubmit event is to prevent the form from submitting if the validation fails. This is also why “return true” and “return false” statements are included in the function. When a function reaches a “return” statement, it ends the function, even if code follows thereafter. Also, you should take note that Regular Expressions should be used for any sort of string validation – in JavaScript or in any other programming language that makes it available. Since the HTML is perfectly fine in this instance (validation should also be done on the server-side for users who have JavaScript disabled) we only need to update the JavaScript itself.

<script type="text/javascript"><!--
  function validateForm(){
    var theForm = document.forms["myForm"];
    var regex = /^\s*$/i;
      if(regex.test(theForm.fName.value) || regex.test(theForm.lName.value) || regex.test(theForm.fColor.value)){
alert("Please fill in all fields.");
       return false;
    }
  return true;
}
//--></script>

Notice that we set the variable “theForm” to document.forms[“myForm”]. This is the proper way to point to the form named “myForm.” Since this is the first form of the document, you can also refer to it as “document.forms[0].” We set a separate variable, “regex,” to hold our regular expression. This isn’t entirely important, but it saves a little memory – you can just refer to a variable instead of typing out the RegEx each time you run a match against an element’s value to validate it. In a human-readable format, you could say that this RegEx says that it will match “anything that begins and ends with zero or more spaces.” If the text field is empty or has only whitespace in it, the RegEx will match it and the function will return false.

Instead of setting the variable “theForm” to a form element that we know exists, we can write a sort of global form validation function, which we can use on any form. Then we can include it in an external *.js file to be cached by the browser and quickly available whenever we need it. We’ll need to make just a tiny modification to our FORM element, so that no matter what the name of the FORM is, we can still validate it.

<form name="myForm" action="some-script.pl" method="post" onsubmit="return
validateForm(this)">

By adding “this” we can send the FORM object to the validateForm function.

<script type="text/javascript"><!--
  function validateForm(f){
    var regex = /^\s*$/i;
      for(var i=0; i<f.elements.length; i++){
        if(regex.test(f.elements[i].value)){
          alert("Please fill in all fields.");
          f.elements[i].focus();
          return false;
       }
    }
  return true;
}
//--></script>

Since we passed “this” to the function, the local variable “f” now refers to the FORM element and all its properties. Therefore, we can run a for loop through the array of elements and test them for validity. All of the elements are being checked to make sure they are not empty, so we have no problem.

If we wanted to test for numbers or letters exclusively, we modify the form and add a CLASS attribute that will tell us what kind of validation should be done on each particular element. This gives us control of the appearance of elements that require different validation methods.

Note: You can color the borders of all the form elements that are numbers only red by changing the CSS accordingly. This is optional for the CSS, but required for the JavaScript. Replacing the field for your favorite color with a field for your age, we get the following form:

<form name="myForm" action="some-script.pl" method="post" onsubmit="return validateForm(this)"><fieldset>
<legend>Enter your information</legend>
<label>First name: <input type="text" name="fName" class="letOnly"></label><br>
<label>Last name: <input type="text" name="lName" class="letOnly"></label><br>
<label>Age: <input type="text" name="age" class="numOnly"></label><br>
<label><input type="submit" value="Submit form"></label>
</fieldset></form>

Our JavaScript now can be updated to check for letters only if “letOnly” is one of the classes of the current input field in the loop, or check for numbers only if “numOnly” is one of the classes of the current input field in the loop.

<script type="text/javascript"><!--
  function validateForm(f){
    var regex = /^\s*$/;
    var let = /^[a-zA-Z]+$/i;
    var num = /^[0-9]+$/;
    var e = f.elements;
      for(var i=0; i<e.length; i++){
        if(regex.test(e[i].value)){
          alert("Please fill in all fields.");
          e[i].focus();
          return false;
       }
       if(e[i].className.indexOf("letOnly")!=-1 && !let.test(e[i].value)){
          alert("Please enter letters only.");
          e[i].focus();
          return false;
      }
      if(e[i].className.indexOf("numOnly")!=-1 && !num.test(e[i].value)){
         alert("Please enter numbers only.");
         e[i].focus();
         return false;
     }
   }
  return true;
}
//--></script>

This script tests for the class names “letOnly” and “numOnly”; if either is present, it will validate and only allow letters or numbers. Most often, this type of validation is sufficient and effective.

Rollover, Rover!

JavaScript image rollovers are a classical issue – there have been many methods available to accomplish rollovers, but I think I’ve found what is likely to be the best. To begin with, you will preload your images with the “on” and “off” equivalents.

<script type="text/javascript"><!--
  var img1 = [], img2 = [];
  img1[0] = new Image(); img1[0].src = "http://localhost/html.gif";
  img1[1] = new Image(); img1[1].src= "http://localhost/html.jpg";
  img2[0] = new Image(); img2[0].src = "http://localhost/gif.gif";
  img2[1] = new Image(); img2[1].src= "http://localhost/jpg.gif";
  function roll(n,s){
    document.images[n].src = window[n][s].src;
  }
//--></script>

<img src="/html.gif" onmouseover="roll(this.name,1)" onmouseout="roll(this.name,0)" name="img1"><br>
<img src="/gif.gif" onmouseover="roll(this.name,1)" onmouseout="roll(this.name,0)" name="img2">

You will need to change the addresses on your own (be aware that these are from a local testing server). Start by deciding how rollovers you want to use for your images. In my case, there are two, so I create two new arrays, named “img1” and “img2” respectively. You can name your array variables anything you want and you don’t have to add numbers after them. Make sure, though, that your variable names and the names of your images are the same.

An explanation of the “roll” function: two values are passed to the “n” and “s” variables of this function. They are the name of the image and the state in which the image should be at this point. That is, when you put your mouse over the image, you give the name of the image (you can also just put “this.name” if the roll function is directly on the image) and whether you want the image to be in its original state (0) or its “over” state (1). The roll function will search for “document.images[n]” – that is, the image with the name “n” on the current web page – and change its SRC to “window[n][s].src,” or the sth index of the array that has the same name as the image you rolled over. This could also be written as eval(“n[s].src”); but it’s preferable to avoid using eval.

Let’s quickly run through our list from earlier:

    1. Is this practical, or am I just trying to add something else to my web page? It is practical.
    2. Do I need JavaScript to do this, or can I do it a different way? Hmm, can we?
    3. Will this work if someone doesn’t have JavaScript available? If not, how can I provide an alternative? It won’t work for users without JavaScript, but the page can still be used without JavaScript. It is possible, however, to preload images and do rollovers without using JavaScript.
    4. Am I designing this with the user in mind? In other words, will this make my web site difficult for people to see and/or read? Yes, the rollovers can be an enhancement to a web page and can be important for usability – it’s easier to see what you’re about to click when the appearance is different from other similarly designed images on the page.
    5. Is it guaranteed to work cross-browser and cross-platform? If not, what can I do to provide an alternative? It has only been tested on Windows, but is likely to work fine on other operating systems. If it doesn’t work, the page can still be used without any major difficulties.

Following the above list, we met our criteria for the responsible use of JavaScript, but when an alternate technology is available, why not take advantage of it? Using Cascading Style Sheets, you can preload your rollovers. This will work for users who have JavaScript disabled, but have a browser with decent CSS support.

Next week, we conclude this series, beginning with Drop-down Navigation Selections. Other topics covered will be DHTML Menus, Proprietary Alternatives, Document.all, and innerHTML. See you then.


Add commentAdd comment (Comments: 0)  

Advertisement

Partners

Related Resources

Other Resources

arrow