Javascript Tutorial -- Working with Forms



So far, all of the Javascript code we have written has processed static data -- data that was hard-coded into the script before the program was run. This is fine for examples, but in the real world, we usually want to process input from sources outside of our own programs. In Javascript, one of the ways we obtain input from the user is from HTML forms.

This is the point at which most Javascript tutorials will diverge for a while into the "Document Object Model" or "DOM". This is fine in a book on Javascript -- the format of a book lends itself to detailed discussions of the deeper concepts behind how and why a programming language was designed the way it was. Despite the fact that some of the previous lessons may have seemed a little long-winded, I really am making an effort to keep things as simple and concise as possible.

In keeping with this philosophy, I am going to avoid the topic of the DOM in this tutorial, and instead just explain a few of the concepts encompassed by the DOM as needed to explain how Javascript works with the HTML in your web page. So...here goes.

Suppose you have an HTML document that contains some <img> tags. Javascript can reference these tags using a method called "getElementByID()". This method references the document object, and accepts the ID of the <input>, <select> or <textarea> tag. The ID is assigned by the web developer by adding an "id" attribute like this:
        <input type="text" id="EmailAddress">
      
There is one twist to this, however. While most of our previous scripts have run as soon as the HTML is loaded, when using a form, we will have to wait until the user has entered the required data before we can process it. There are a number of ways to do this -- we can submit a request to execute a function in a URL using "javascript:function_name" in the form's "action" attribute, we can call the function from an "onChange" attribute in the <input> tag, or we can use an "onClick" attribute in the "submit" button. Here is a modification of the original "Hello, World!" script that requests a name from the user via a form, then writes "Hello <username>" to an alert window, and using the "onChange" attribute:
        <!--
          <script type="text/javascript">
            function Hello()
              {
                var Name = document.getElementById('name')

                if (Name.value.match(/^[a-zA-Z0-9_\-]+$/))
                  {
                    alert("Hello, " + Name.value)
                  }
                else
                  {
                    alert("Sorry -- please use only numbers, letters, hyphens or underscores")
                  }
              }
          //-->
        </script>
        <form>
          <input type="text" id="name" onChange="Hello()">
          <input type="submit" value="click">
        </form>
      
One last caveat before I wrap up this lesson: security should be of the utmost importance to the web developer, whether you are developing in Javascript, Perl, PHP, Python, VBScript or any other language. As we mentioned in Lesson 16, one of the first things you should do to secure your scripts is sanitize your user input by passing it through a regular expression. While I don't have the time or space in this tutorial to give a thorough lesson in web developer security, I will show a few examples of things to watch and test for.

One common use for forms is to add a new user to a members directory in an on-line forum. You commonly will see a text field for a user name, password and e-mail address in such a form. The Javascript code will retrieve this data, and hand it off to a CGI program, which after a little additional processing will add the new user name, password and e-mail address to a database, often by including the user data in a dynamically generated SQL query, like this:
        $Query="insert into Database values (\"$username", \"$e-mail\", \"$password\")";
      
However, suppose the username were...:
        bogususer\");delete from Database where (username=*)
      
When expanded by the CGI script on the web server, this qenerates the SQL statement...:
        insert into Database values ("bogususer"); delete from Database where (username=*)
      
In this case, the attacker has closed the original query (with the parenthesis and the semi-colon) and then generated a new query that was crafted to delete all the data from the database. This is called an "SQL injection" and is one of many ways an attacker can wreak havoc through poorly written scripts.

Another type of attack, cross-site scripting, is where the attacker inserts Javascript or HTML in, for example, a web forum or bulletin board in an attempt to redirect future readers to a phony site so that they can trick unwary users into giving away their credentials. Consider the web form we used in the SQL injection example: suppose instead of entering SQL into the username field, we entered an "<a href=...>" tag that redirects to a phishing site.

To prevent attacks like this, the Javascript developer must test user input for malicious data. OK, enough theory -- how do you test for bad input data? First, don't try to pattern match all of the possible bad attacks. You have to catch every possible attack; the attacker only has to guess one possible attack (the one that works). Instead, filter out everything other than what you expect to see in the input. If you have a data field that should only contain text characters, block everything but text characters. If you have a data field that should only contain numerical digits, then block everything but numerical digits. Even if you have a field that expects non-text characters like the less-than sign ("<"), quotes ("), etc., then use regular expressions to replace them with the HTML code for them -- or at least escape them using the escape sequence in whatever CGI language you use. For example, in the e-mail field, you might want a regex like the following:
        <script type="text/javascript">
          <!--
            function EmailIsValid(e-mail)
              {
                //Not necessarily a valid e-mail address -- ldsle.zfl is not
                //a real domain name, for example, but will prevent SQL injection
                var Regex = "/[a-zA-Z_]*[a-zA-Z0-9_\.]+@[a-zA-Z0-9_\-\.]+/

                if (e-mail.match(Regex))
                  {
                    return(1)
                  }
                else
                  {
                    return(0)
                  }
              }
          //-->
        </script>
      
Here is a sample script to poll data from an HTML form.