1. |
function initForms() {
for (var i=0; i< document.forms. length; i++) {
document.forms[i].onsubmit = function() {return validForm();}
When the page first loads, the initForms() function is called. This function loops through every form on the page. For each one, it adds an event handler to that form's onsubmit: a call to function() {return validForm();}. This is another anonymous function, but this time it does something: it returns true or false to tell the browser whether or not to continue with the action attribute. When an onsubmit handler returns a value of false, the form doesn't get passed back to the server. The server only gets the form (running whatever CGI is stored in the action attribute) when we return a value of true.
|
2. |
var allTags = document.getElementsByTagName("*");
document.getElementsByTagName("*")
is very usefulthat asterisk tells JavaScript to return an array containing every tag on the page. Then, we can just loop through the allTags variable looking for things of interest.
|
3. |
for (var i=0; i<allTags.length; i++) {
if (!validTag(allTags[i])) {
allGood = false;
This loop searches through allTags, and the if conditional calls the validTag() function, which checks each tag to see if there's anything there that should keep the form from submitting this page. It's passed allTags[i], which is the object that we're currently processing. If any tag causes validTag() to return false, we set allGood to false. However, even if one is false, we still keep going through all the tags.
|
| |
4. |
We return allGood, to signify whether or not we're good to go.
|
5. |
function validTag(thisTag) {
Create the validTag() function, and set it to receive the value thisTag.
|
6. |
var allClasses = thisTag.className. split(" ");
For each tag, we want to look at every class attribute (remember, class can be set to have multiple attributes "like so and so and so"). The allClasses array is created and set based on thisTag.className.split(" "); which splits a string up into an array, broken up by the string that's passed in. Here, the string is a space, which would, for example, cause the string "this that and the other" to turn into an array of five elements: this, that, and, the, other.
We want to look at each class attribute, because class is where we're storing what we want each form field to have to provide. In this task, the one we care about is reqdrequired. If any form field has a class of reqd, it's got to contain something.
|
7. |
for (var j=0; j<allClasses.length; j++) {
outClass += validBasedOnClass(allClasses[j]) + " ";
}
This loop uses j as its loop variable because we're inside a loop that's using i. We loop around once for each class attribute in allClasses.
For each class, we perform: outClass += validBasedOnClass(allClasses[j]) + " "; This calls the validBasedOnClass() function (explained below), passing in the current class we're looking at. That function returns something, and that something, plus a space, is appended onto the outClass variable.
|
| |
8. |
thisTag.className = outClass;
When we've finished with the allClasses loop, we take the contents of outClass and put it into thisTag.className, overwriting the current class attribute for this form field. That's because it can change during this process, as we'll see very shortly.
|
9. |
if (outClass.indexOf("invalid") > -1) {
Something that can be returned in the new class attribute is the word "invalid", so we check for it. If that's found anywhere in the new class, do the following, as there's a problem.
|
10. |
If this form field can take focus (remember, we discussed focus in Chapter 6), we want to put the focus into the field, and that's what this line does. This is a way of forcing the user to know which field is the problem.
|
11. |
if (thisTag.nodeName == "INPUT") {
thisTag.select();
}
Basically, these lines say, "This tag I'm looking at: is it an <input> tag? If so, select its value so that the user has an easier time modifying it."
|
12. |
We're still inside the "invalid was returned" block, so we return false back to where we were called.
|
13. |
If all is good and valid, we return true.
|
14. |
function validBasedOnClass (thisClass) {
Begin the new validBasedOnClass() function, and set it to receive the value thisClass.
|
| |
15. |
Create the classBack variable, and fill it with nothing for now. This is going to contain the class to be returned, that is, the value we want to send back.
|
16. |
The switch statement looks at the single class attribute that was passed in (in thisClass) and does something based on it.
|
17. |
case "":
case "invalid":
break;
If thisClass is empty or invalid, then break out of the conditional; otherwise, continue.
|
18. |
case "reqd":
if (allGood && thisTag.value == "") classBack = "invalid ";
classBack += thisClass;
break;
If the attribute being processed is reqd and allGood is true and the current value of the current tag is "" (i.e., nothing), then we set classBack to be invalid, because there's a problem, and we want to notify the user. After that, whether there was a problem or not, we append the current class to classBack so that it doesn't get lost.
|
19. |
default:
classBack += thisClass;
The default block is executed whenever something happens that isn't caught by one of the above cases. When that happens, it's a class we don't care about, so we just stick it onto classBack and don't fret.
|
20. |
Finally, we return classBack.
|