Introduction

Alright, I'll admit: I'm just  31, and before JavaScript, the only thing I knew that remotely resembles any programming language was HTML. Like many people in the same situation as I was, I thought that learning JavaScript was going to be a very difficult and arduous task. Well, I was in fact dead wrong. It was so easy, and believe me, if I could do it, anyone can. It took me around a week before I started creating actual working scripts for my webpages. Now, I hope to pass on some of that knowledge on to others. Instead of confusing you with lots of geek talk and confusing concepts, I'll be showing you- through examples- how JavaScript works and how it could better your site. As if that's not enough, I've also compiled a wealth of great JavaScript resources on the net you can use to further your study of this great programming language. Enjoy! JavaScript is an interpreted language with a C like syntax. While many people brush the language off as nothing more than a browser scripting language, it actually supports many advanced concepts such as object-oriented-programming, recursion, lambda, and closures. It's a very approachable language for the beginner that quickly scales to be as powerful a tool as your skills allow. This reference will cover the basic language constructs. This is not a beginner's guide to programming. This article focuses on bringing people who already know another programming language up to speed on Javascript methodology. Additionally, this is not an exhaustive language definition, it is a broad overview that will occasionally focus in on some more advanced concepts. It's here to get you started, other articles will focus on making you an expert,let we start..

Javascript is an interpreted language with a C like syntax. While many people brush the language off as nothing more than a browser scripting language, it actually supports many advanced concepts such as object-oriented-programing, recursion, lambda, and closures. It's a very approachable language for the beginner that quickly scales to be as powerful a tool as your skills allow.

This reference will cover the basic language constructs. This is not a beginner's guide to programming. This article focuses on bringing people who already know another programming language up to speed on Javascript methodology. Additionally, this is not an exhaustive language definition, it is a broad overview that will occasionally focus in on some more advanced concepts. It's here to get you started, other articles will focus on making you an expert.

Getting Started

To dive into Javascript all you need is a simple text-editor and a browser. In windows, you can use notepad under your accessories and Linux and mac users have a similar editor. Simply create a blank HTML page as such…

<html>
  <head>
     <title>Learning Javascript easily</title>
  </head>
  <body>
     <p>Hello World!
  </body>
</html>

Save the file then in your browser type in the file name you just created to see the results. Javascript is interpreted so any changes you make to this file will show up instantly in the browser the moment you hit the reload button.

In-Line Javascript

To define a Javascript block in your web page, simply use the following block of HTML.

<script type='text/javascript'>
// Your script goes here.
</script>

You can place these script blocks anywhere on the page that you wish, there are some rules and conventions however. If you are generating dynamic content as the page loads you will want the script blocks to appear where you want their output to be. For instance, if I wanted to say "Hello World!" I would want my script block to appear in the <body> area of my web page and not in the <head> section.

Unless your scripts are generating output as the page loads, good practice says that you should place your scripts at the very bottom of your HTML. The reason for this is that each time the browser encounters a <script> tag it has to pause, compile the script, execute the script, then continue on generating the page. This takes time so if you can get away with it, make sure the browser hits your scripts at the end of the page instead of the start.

External Javascript

External Javascript is where things get interesting. Any time you have a block of code which you will want to use on several different web pages you should place that block in an external Javascript file. The clock on the upper right-hand corner of this page is a good example. The clock appears on almost every page on this site and so it is included in my "common.js" file. Every web-page on the site will load this file and so the clock is available to all of my web-pages.

There's nothing fancy about an external Javascript file. All it is, is a text file where you've put all your Javascript. Basically everything that would ordinarily go between the <script> tags can go in your external file. Note that between was stressed, you can not have the <script> </script> tags themselves in your external file or you will get errors.

The biggest advantage to having an external Javascript file is that once the file has been loaded, the script will hang around the browser's cache which means if the Javascript is loaded on one page then it's almost a sure thing that the next page on the site the user visits will be able to load the file from the browser's cache instead of having to reload it over the Internet (This is an incredibly fast and speedy process).

Including an external file is basically the same as doing an in-line script, the only difference is that you specify a filename, and there's no actual code between <script> and </script>...

<script type='text/javascript' src='common.js'></script>

When the browser encounters this block it will load common.js, evaluate it, and execute it. Like in-line scripts above you can place this block anywhere you need the script to be and like in-line scripts you should place these as close to the bottom of the web-page as you can get away with.

The only difference between in-line Javascript blocks and external Javascript blocks is that an external Javascript block will pause to load the external file. If you discount that one thing, there's no procedural difference between the two!

Javascript is case sensitive.

It should also be noted, before we begin, that Javascript is extremely case sensitive so if you're trying to code along with any examples make sure lowercase is lowercase and uppercase is uppercase. For the most part Javascript is also a camel-cased language. That is, if you're trying to express more than one word you will eliminate the spaces, leave the first letter uncapitalized and capitalize the first letter of each word. Thus "get element by id" becomes "getElementByID".

By contrast, HTML itself is NOT case sensitive.

Output (writeln)

One of the most important things to do when learning a new language is to master basic input and output which is why hello world has become almost a cliche in programming textbooks. For Javascript you need three hello worlds because there are three ways to communicate with the user, each increasingly more useful than the last.

The first method is to use the document.writeln(string) command. This can be used while the page is being constructed. After the page has finished loading a new document.writeln(string) command will delete the page in most browsers, so use this only while the page is loading. Here's how a simple web-page will look...

<html>
  <head>
  </head>
  <body>
     <script type='text/javascript'>

        document.writeln('Hello World!');     

     </script>
  </body>
</html>

As the page is loading, Javascript will encounter this script and it will output "Hello World!" exactly where the script block appears on the page.

The problem with writeln is that if you use this method after the page has loaded the browser will destroy the page and start constructing a new one. As you can see by clicking on this example which will execute a document.writeln after the page has finished loading.

For the most part, document.writeln is useful only when teaching yourself the language. Dynamic content during page load is better served by the server-side scripting languages. That said, document.writeln is very useful in pre-processing forms before they're sent to the server -- you can basically create a new web-page on the fly without the need to contact the server.

Output (alert)

The second method is to use a browser alert box. While these are incredibly useful for debugging (and learning the language), they are a horrible way to communicate with the user. Alert boxes will stop your scripts from running until the user clicks the OK button, and it has all the charm and grace of all those pop-up windows everyone spent so many years trying to get rid of!

<html>
  <head>
  </head>
  <body>
     <script type='text/javascript'>

        alert('Hello World!');

     </script>
  </body>
</html>

You can see this alert in action by clicking here!

Output (getElementById)

The last method is the most powerful and the most complex (but don't worry, it's really easy!).

Everything on a web page resides in a box. A paragraph (<P>) is a box. When you mark something as bold you create a little box around that text that will contain bold text. You can give each and every box in HTML a unique identifier (an ID), and Javascript can find boxes you have labeled and let you manipulate them. Well enough verbiage, check out the code!

<html>
  <head>
  </head>
  <body>

     <div id='feedback'></div>

     <script type='text/javascript'>

        document.getElementById('feedback').innerHTML='Hello World!';

     </script>
  </body>
</html>

The page is a little bigger now but it's a lot more powerful and scalable than the other two. Here we defined a division <div> and named it "feedback". That HTML has a name now, it is unique and that means we can use Javascript to find that block, and modify it. We do exactly this in the script below the division! The left part of the statement says on this web page (document) find a block we've named "feedback" ( getElementById('feedback') ), and change its HTML (innerHTML) to be 'Hello World!'.

We can change the contents of 'feedback' at any time, even after the page has finished loading (which document.writeln can't do), and without annoying the user with a bunch of pop-up alert boxes (which alert can't do!).

It should be mentioned that innerHTML is not a published standard. The standards provide ways to do exactly what we did in our example above. That mentioned, innerHTML is supported by every major Browser and in addition innerHTML works faster, and is easier to use and maintain. It's, therefore, not surprising that the vast majority of web pages use innerHTML over the official standards.

While we used "Hello World!" as our first example, its important to note that, with the exception of <script> and <style>, you can use full-blown HTML. Which means instead of just Hello World we could do something like this…

<html>
  <head>
  </head>
  <body>

     <div id='feedback'></div>

     <script type='text/javascript'>

        document.getElementById('feedback').innerHTML='<P><font color=red>Hello World!</font>';

     </script>
  </body>
</html>

innerHTML will process your string and basically redraw the web page with the new content. This is a VERY powerful and easy to use concept. It means you can basically take an empty HTML element (which our feedback division is) and suddenly expand it out with as much HTML content as you'd like.

Input (One Click To Rule Them All)

Input, of course, is a little more complicated. For now we'll just reduce it to a bare click of the mouse.

If everything in HTML is a box and every box can be given a name, then every box can be given an event as well and one of those events we can look for is "onClick". Lets revisit our last example...

<html>
  <head>
  </head>
  <body>

     <div id='feedback' onClick='goodbye()'>Users without Javascript see this.</div>

     <script type='text/javascript'>

        document.getElementById('feedback').innerHTML='Hello World!';

        function goodbye() {
           document.getElementById('feedback').innerHTML='Goodbye World!';
        }

     </script>
  </body>
</html>

Here we did two things to the example, first we added an "onClick" event to our feedback division which tells it to execute a function called goodbye() when the user clicks on the division. A function is nothing more than a named block of code. In this example goodbye does the exact same thing as our first hello world example, it's just named and inserts 'Goodbye World!' instead of 'Hello World!'. See for yourself! Click the text below…

Another new concept in this example is that we provided some text for people without Javascript to see. As the page loads it will place "Users without Javascript will see this." in the division. If the browser has Javascript, and it's enabled then that text will be immediately overwritten by the first line in the script which looks up the division and inserts "Hello World!", overwriting our initial message. This happens so fast that the process is invisible to the user, they see only the result, not the process. The goodbye() function is not executed until it's explicitly called and that only happens when the user clicks on the division.

While Javascript is nearly universal there are people who surf with it deliberately turned off and the search bots (googlebot, yahoo's slurp, etc) also don't process your Javascript, so you may want to make allowances for what people and machines are-not seeing.

Input (User Input)

Clicks are powerful and easy and you can add an onClick event to pretty much any HTML element, but sometimes you need to be able to ask for input from the user and process it. For that you'll need a basic form element and a button…

<input id='userInput' size=60> <button onClick='userSubmit()'>Submit</button><BR>
<P><div id='result'></div>

Here we create an input field and give it a name of userInput. Then we create a HTML button with an onClick event that will call the function userSubmit(). These are all standard HTML form elements but they're not bound by a <form> tag since we're not going to be submitting this information to a server. Instead, when the user clicks the submit button, the onClick event will call the userSubmit() function…

<script type='text/javascript'>
function userSubmit() {
   var UI=document.getElementById('userInput').value;
   document.getElementById('result').innerHTML='You typed: '+UI;
} 
</script>

Here we create a variable called UI which looks up the input field userInput. This lookup is exactly the same as when we looked up our feedback division in the previous example. Since the input field has data, we ask for its value and place that value in our UI variable. The next line looks up the result division and puts our output there. In this case the output will be "You Typed: " followed by whatever the user had typed into the input field.

Give it a try and see how it works…


We don't actually need to have a submit button. If you'd like to process the user input as the user types then simply attach an onKeyup event to the input field as such…

<input id='userInput' onKeyUp="userSubmit()" size=60><BR>
<P><div id='result'></div>

There's no need to modify the userSubmit() function. Now whenever a user presses a key while the userInput box has the focus, for each keypress, userSubmit() will be called, the value of the input box retrieved, and the result division updated. And here's the example…

It's interesting to note that as you're typing you're actually creating HTML and inserting it into this document which means that html tags you typed will be appropriately processed. Try typing "The quick<p>brown fox." and you'll see the line break correctly inserted in the output.

Javascript is an Event Driven Language

As you can tell from the input examples, Javascript is an event driven language which means your scripts react to events you set up. Your code isn't running all the time, it simply waits until an event starts something up! Going into all the Javascript events is beyond the scope of this document but here's a short-list of common events to get you started.

Operator Description
+ Addition (also string concatention)
- Subtration (also unary minus)
* Multiplication
/ Division
% Remainder of division (or modulus)
++ pre or post increment
-- pre or post decrement

++ and -- are C style operators their position around the variable they are operating on is important. If the operator appears BEFORE the variable they will be evaluated immediately, if they appear AFTER the variable they will be evaluated only after the entire line has been resolved. For instance…

   var x = 5;
   var y = x++;     // y=5, x=6

   var x = 5;
   var y = ++x;     // y=6, x=6

In the first example y is assigned the value of x (5) and then x is incremented by one because the ++ operator appears AFTER x. In the second example, x is incremented by one first because ++ appears BEFORE the x, so y is given the value 6.

Additional shorthand operators exist when working on the same variable. For instance…

   x = x + 5;  // is the same as...
   x += 5;

Logical and Comparison Operators

Javascript supports equality checking (==) and identity checking (===). Equality checks for equality regardless of type. Therefore 25 and '25' will evaluate as true. Identity checking checks not only for equality but type equality as well so 25 and '25' will evaluate as false because, while both are 25, one is a string and the other a number. Note that a single equal sign is an assignment statement! x=5 will assign 5 to x, while x==5 will see if x is equal to 5, and x===5 will check to see if x is identical to 5.

In addition to == and ===, you can check for not equal (!=) and not identical (!==).

Operator Description
= Assignment x=5; // assigns 5 to x
== Equality, is x==5?
=== Identity, is x 5 and a number as well?
!= Not equal, is x unequal to 5?
!== Not identical, is x unequal to the Number 5?
! Not, if not(false) is true.
|| OR, is (x==5) OR (y==5)
&& And, is (x==5) AND (y==5)
< Less than. is x less than 5?
<= Less than or equal. is x less than or equal to 5?
> Greater than. is x greater than 5?
>= Greater than or qual. is x greater than or equal to 5?

 

Conditionals: IF

The if statement lets you execute a block of code if some test is passed.

var x=5;
if (x==5) {
   alert('x is equal to 5!');
}

You can also use an else clause to execute code if the test fails.

var x=5;
if (x==5) {
   alert('x is equal to 5!');
} else {
   alert('x is not equal to 5!');
}

An elseif statement also exists which allows for better formating of long conditional tests.

var x=5;
if (x==1) {
   alert('x is equal to 1!');
} else if (x==2) {
   alert('x is equal to 2!');
} else if (x==5) {
   alert('x is equal to 5!');
} else {
   alert('x isn't 1, 2 or 5!');
}

Conditionals: SWITCH

If you're going to be doing a large number of tests, it makes sense to use a switch statement instead of nested ifs. Switches in javascript are quite

powerful, allowing evaluations on both the switch and the case.

var x=5;
switch (x) {
   case 1: alert('x is equal to 1!'; break;
   case 2: alert('x is equal to 2!'; break;
   case 5: alert('x is equal to 5!'; break;
   default: alert("x isn't 1, 2 or 5!");
}

Note that if you omit the break statement that ALL of the code to the end of the switch statement will be executed. So if x is actually equal to 5 and

there is no break statement, an alert for "x is equal to 5" will appear as well as an alert for "x isn't 1,2, or 5!".

Sometimes it makes more sense to do the evaluation in the case statement itself. In this case you'd use true, false, or an expression which evaluates

 to true or false in the switch statement.

var x=5;
switch (true) {
   case (x==1): alert('x is equal to 1!'; break;
   case (x==2): alert('x is equal to 2!'; break;
   case (x==5): alert('x is equal to 5!'; break;
   default: alert("x isn't 1, 2 or 5!");
}

Conditionals: Shorthand Assignment

Javascript supports more advanced constructs. Often you will see code like the following…

function doAddition(firstVar, secondVar) {
   var first = firstVar  ||  5;
   var second= secondVar || 10;
   return first+second; 
}

doAddition(12);

Here Javascript uses a logical OR (||) to determine if the passed variables actually have a value. In the example we call doAddition with a value of

 12 but we neglect to pass a second argument. When we create the first variable firstVar is a non-falsey value (IE it's actually defined) so Javascript

assigns firstVar to first. secondVar was never passed a value so it is undefined which evaluates to false so here the variable second will be assigned a

 default value of 10.

You should note that zero evaluates as false so if you pass zero as either firstVar or secondVar the default values will be assigned and NOT zero. In our

example above it is impossible for first or second to be assigned a zero.

In psuedo code...

var someVariable = (assign if this is truthy) || (assign this if first test evaluates false)

Conditionals: Ternary Operators

Ternary operators are a shorthand if/else block who's syntax can be a bit confusing when you're dealing with OPC (Other People's Code). The syntax boils

down to this.

var userName = 'Bob';
var hello = (userName=='Bob') ? 'Hello Bob!' : 'Hello Not Bob!'; 

In this example the statement to be evaluated is (userName=='Bob'). The question marks ends the statement and begins the conditionals. If UserName is,

indeed, Bob then the first block 'Hello Bob!' will be returned and assigned to our hello variable. If userName isn't Bob then the second block ('Hello Not Bob!') is returned and assigned to our hello variable.

In psudeo code…

var someVariable = (condition to test) ? (condition true) : (condition false);

The question mark (?) and colon (:) tend to get lost in complex expressions as you can see in this example taken from wikipedia (but which will also

work in Javascript if the various variables are assigned...)

for (i = 0; i < MAX_PATTERNS; i++)
   c_patterns[i].ShowWindow(m_data.fOn[i] ? SW_SHOW : SW_HIDE);

So while quick and efficient, they do tend to reduce the maintainability/readability of the code. Loops: FOR The for loop follows basic C syntax, consisting of an initialization, an evaluation, and an increment. for (var i=0; (i<5); i++) { document.writeln('I is equal to '+i+'
'); } // outputs: // I is equal to 0 // I is equal to 1 // I is equal to 2 // I is equal to 3 // I is equal to 4 This is actually an extreme simplification of what a for statement can do. On the other end of the spectrum, consider this shuffle prototype which will randomly shuffle the contents of an array. Here, everything is defined, and executed within the context of the for statement itself, needing no additional block to handle the code. Array.prototype.shuffle = function (){ for(var rnd, tmp, i=this.length; i; rnd=parseInt(Math.random()*i), tmp=this[--i], this[i]=this[rnd], this[rnd]=tmp); }

Loops: FOR/IN

Javascript has a variant of the for loop when dealing with Javascript objects.

Consider the following object…

var myObject = { 'animal'  : 'dog',
                 'growls'  : true,
                 'hasFleas': true,
                 'loyal'   : true }                 

We can loop through these values with the following construct.

var myObject = { 'animal'  : 'dog',
                 'growls'  : true,
                 'hasFleas': true,
                 'loyal'   : true }
                 
for (var property in myObject) {
   document.writeln(property + ' contains ' + myObject[property]+'<br>');
}                                  
// Outputs:
// animal contains dog
// growls contains true
// hasFleas contains true
// loyal contains true

What this essentially does is assign the property name to the variable property. We can then access myObject through an associative array style syntax.

For instance the first itteration of the loop assigns animal to property and myObject["animal"] will return dog.

There is a big caveat here in that properties and methods added by prototyping will also show up in these types of loops. Therefore it's best to always

check to make sure you are dealing with data and not a function as such…

for (var property in myObject) {
   if (typeof(myObject[property]) != 'function') {
      document.writeln(property + ' contains ' + myObject[property]+'<br>');
   }
}                                  

The typeof check to screen out functions will ensure that your for/in loops will extract only data and not methods that may be added by popular javascript libraries like Prototype.

Loops: WHILE

while loops in Javascript also follow basic C syntax and are easy to understand and use.

The while loop will continue to execute until its test condition evaluates to false or the loop encounters a break statement.

var x = 1;
while (x<5) {
   x = x +1;
}

var x = 1;
while (true) {
   x = x + 1;
   if (x>=5) {
      break;
   }
}

Sometimes it makes more sense to evaluate the test condition at the end of the loop instead of the beginning. So for this Javascript supports a do/while structure.

var x=1;
do {
   x = x + 1;
} while (x < 5);

Bringing It All Together

So now you know how to do basic input and output, how to do conditional branching and how to do loops. That's pretty much everything you need to know about any programming language to get started! So lets wrap everything we've done so far into one simple web application.

First we'll define our web page.

<html>
   <head>
      <title>My First Javascript</title>
   </head>
   <body>
      Hello World!
   </body>
</html>

Now to this we will add an input line, a drop down box, and a submit button. Notice we give an ID to the form elements, and have the submit button call a function when it's clicked. A function which we will write later. We've also added some descriptive text.

<html>
   <head>
      <title>My First Javascript</title>
   </head>
   <body>
      Hello World!
      <p>Say what? <input id="sayThis" size=40>
      <P>How many times? <select id='howMany'>
                            <option value=1>1</option>
                            <option value=5 selected>5</option>
                            <option value=10>10</option>
                            <option value=20>20</option>
                         </select>
      <p><button onClick='doLoop()'>Do It!</button>
   </body>
</html>

Now we need to add a division where the output will occurr. We'll add this right below the form elements, specifically the "Do It!" button.

<html>
   <head>
      <title>My First Javascript</title>
   </head>
   <body>
      Hello World!
      <p>Say what? <input id="sayThis" size=40>
      <P>How many times? <select id='howMany'>
                            <option value=1>1</option>
                            <option value=5 selected>5</option>
                            <option value=10>10</option>
                            <option value=20>20</option>
                         </select>
      <p><button onClick='doLoop()'>Do It!</button>
      <p><div id="results"></div>                         
   </body>
</html>

The script for this will be simple enough. When the button is clicked the doLoop() function will be called. doLoop() will lookup the value of the sayThis input field, then repeat that howMany times.

Here's the script itself, separate from the HTML…

   function doLoop() {
      var sayWhat = document.getElementById('sayThis').value;
      var maxLoop = document.getElementById('howMany').value;
      var str = ''; // where we'll store our output temporarily.
      for (var i=1; (i<=maxLoop); i++) {
         str=str+i+':'+sayWhat+'<br>';
      }
      document.getElementById("results").innerHTML=str;
   }

And the entire application, all together.

<html>
   <head>
      <title>My First Javascript</title>
   </head>
   <body>
      Hello World!
      <p>Say what? <input id="sayThis" size=40>
      <P>How many times? <select id='howMany'>
                            <option value=1>1</option>
                            <option value=5 selected>5</option>
                            <option value=10>10</option>
                            <option value=20>20</option>
                         </select>
      <p><button onClick='doLoop()'>Do It!</button>
      <p><div id="results"></div>
      <script type='text/html'>
         function doLoop() {
            var sayWhat = document.getElementById('sayThis').value;
            var maxLoop = document.getElementById('howMany').value;
            var str = ''; // where we'll store our output temporarily.
            for (var i=1; (i<=maxLoop); i++) {
               str=str+i+':'+sayWhat+'<br>';
            }
            document.getElementById("results").innerHTML=str;
         }
      </script>                         
   </body>
</html>

And finally a working example.

Hello World!

Say what?

How many times?

DHTML: Dynamic HTML

The above example is what's technically considered Dynamic HTML (or DHTML) because the contents of the page dynamically change based on user interaction after the page has finished loading. Going into great detail on DHTML is beyond the scope of this article but there is one small, trivial jump that can really change how you see HTML and Javascript.

This page has pulled an HTML element with the use of document.getElementById. Once we've had this assigned to a variable we've been able to manipulate the contents of that element with innerHTML, and in the case of forms find the value of the element with the value property.

There is also a style property which lets you access, and change, the CSS styles for that element. There is a nice CSS reference at ILoveJackDaniels. Most all of the properties you can access are listed on the left and right margin of the cheat sheet (the interior/brown areas aren't applicable). The only real trick is that where you see a dash in the CSS name, for Javascript you need to remove the dash and capitalize the next letter. So the CSS style background-color becomes backgroundColor in Javascript.

Here's an example which will change the background color of a division when you click on it's contents.

<div id="example" onClick="colorize()">Click on this text to change the background color</div>
<script type='text/javascript'>
   function colorize() {
      var element = document.getElementById("example");
      element.style.backgroundColor='#800';
   }
</script>

And the example.

Click on this text to change the background color

Here we create a division with a name of example which will call a function called colorize() when that division is clicked. colorize() will lookup the example division and assign it to the Javascript variable element. Next, we assign a color of #800 (burgundy) to the element's style.backgroundColor property.

This actually made the text hard to read so in the next example we'll add another line to change the color of the text to white.

<div id="example" onClick="colorize()">Click on this text to change the background color</div>
<script type='text/javascript'>
   function colorize() {
      var element = document.getElementById("example");
      element.style.backgroundColor='#800';
      element.style.color='white';
   }
</script>

And the new example…

Click on this text to change the background color

And lets go ahead and center the text as well.

<div id="example" onClick="colorize()">Click on this text to change the background color</div>
<script type='text/javascript'>
   function colorize() {
      var element = document.getElementById("example");
      element.style.backgroundColor='#800';
      element.style.color='white';
      element.style.textAlign='center';
   }
</script>
Click on this text to change the background color

The manipulation of an HTML element's CSS styles is incredibly powerful! You can hide, or display elements with the style.display property (style.display=none=invisible, style.display=block=visible) You can let the elements float over the page with style.position (absolute/relative/fixed), you can change their position on the page by setting style.left and style.top. The possibilities are literally endless.

Conclusion

As stated at the beginning of this article, this document is intended to bring a programmer up to speed in Javascript, and is not an exhaustive review of the language. This article is a part of a larger series of reference articles (listed at the top of the page). As you master the fundamentals introduced on this page, it's recommended that you visit the other reference articles to master the details of the language.

Read more… ////////////////////////////////////////////////////

This is the first of a series of tutorials which will help you to add interactivity to your HTML documents by using JavaScript. These tutorials assume a working knowledge of HTML 4 and of CSS style as well as a commitment to validate all code including stylesheets.

Javascript documents should always be written to the language standard set by ECMA. The following tutorials use ECMA - Edition3 (JavaScript 1.6). One of the best ways of checking your work is to use jsLint. Just cut and paste your script into the input box and press the jsLint button. Either you will get an 'ok' message or an easy to interpret message including line number on any problem. Code that checks with jsLint will be less likely to be quirky in any of the modern browsers.

In each of the following JavaScript tutorials any text that is displayed in a yellow box can be cut and pasted (aka ripped) into a new HTML document template (ie. complete with doctype, head, title and body elements) and viewed with your favorite browser. You may prefer to type in the example yourself just so that you can review your understanding of each line as it is entered. Choose a strategy which works for you and have some fun learning about the power that JavaScript gives to web page designers.

Topics

A Standard JavaScript Template

Start by making a template file [eg. jstemp.htm] or setting up a macro in your text editor that contains the following code:

<script type="text/javascript">
//<![CDATA[

//]]>
</script>

The first line creates an HTML element which tells your browser that what follows is in a scripted language and this time it is JavaScript (not VBScript or JScript). The next line marks it as unparsed character data. Otherwise characters like & and &lt; will be treated as start of character entities (like &nbsp;) and tags (like <b>) respectively. A comment mark is used so that JavaScript doesn't try to interpret CDATA. The next line (ie. the blank one) is where your JavaScript will be inserted. Finally both the CDATA and script elements are closed in the normal HTML manner.

Note1: It is recommended that you write code that assumes that some users may not have JavaScript enabled browsers or have temporarily turned it off. This is part of the 'Be kind to ALL users' philosophy. HTML provides an element specifically for this purpose. Make a template (or macro) of the following so that it can be included easily in the body section of every document that has a script element.

<noscript>NOTE: Your browser does not support JavaScript
    or support has been turned off. Sorry!</noscript>

The message between <noscript> and </noscript> will appear on a non-script enabled browser or one with scripting turned off. The noscript element must be placed in the body section of your document to be valid HTML 4!.

Note2: Unfortunately many browsers such as FireFox, Opera and SlimBrowser do not display the contents of a noscript element when JavaScript has been deselected. Use CSS style visibility to solve this issue.

Where Is JavaScript Placed

JavaScript is similar to style property rules in that it can be placed in one of several locations depending on how often the code is needed.

Short examples or trivial 'snippets' (such as many in this first tutorial) can be placed inline (sometimes called on-the-fly). These are inserted (with the above template) into the body section of a document.

Most JavaScript utilities are placed in the head section of a document. This assures that they are loaded immediately and that if appropriate can be used in several places in the document.

Just as stylesheets can be in separate files for access from many documents, JavaScript routines can also be isolated to separate files for reuse by several documents. Isolation also prevents html validators from signaling false errors inside javascript. My tutorials use this method.

And finally JavaScript can be invoked or started from within element attributes by using the javascript: keyword.

The best choice is to first develop and 'debug' scripts within the head element. This saves time switching between files. When the script is working well, then cut and paste it to a separate file for reuse. To link to these files, the script element changes to include a 'src' attribute but no content between the tags. For example:

<script type="text/javascript" src="mtmtrack.js"></script>

NOTE: It is a long standing tradition for these external files to use the extension .js but it is not a requirement.

'Hello World' Example

A common first programming assignment in many languages is to write the greeting 'hello world' to the screen. This will give you the chance to become familiar with your text editor and the development process as well as some basic JavaScript syntax.

<script type="text/javascript">
document.writeln('hello world!');
</script>

document.writeln('hello world!'); may seem trivial but it has many points of interest that should be thoroughly understood. The word document indicates one of the major objects in JavaScript. The complete list of available JavaScript objects are given in the Appendices In this example document is used to direct data into an HTML document for display. The following dot indicates that a method or operation is to be applied to that particular object. In this example the method is writeln(). Brackets indicate a parameter or value to be used by the method. Inside the bracket is a quoted string value to be used as is. Matching double quotes may also be used but there are many situations where double quotes conflict with HTML attribute assignment so single quotes are preferred. Finally, the sentence known in programming as a statement) ends with a semicolon. There is another method called write() which is almost the same as writeln() but does not display a new line after the parameter value. New lines can be forced in JavaScript with the \n newline escape sequence.

Alert, Prompt and Confirm Windows

JavaScript has three very simple ways of providing the user with information and possibly feedback through the use of popup windows. window.alert() is a window object method which displays a message but no feedback can be gathered from the user. There is only one string parameter.

<script type="text/javascript">
window.alert('hello world!');
</script>

The method window.prompt() displays a standard dialog which allows the user to enter data. Note that there are two strings, separated by commas as parameters. The first parameter is a prompt message. The second parameter sets the default value of the entry. It is normally blank but is required to give a blank input line in the MSIE browser.

<script type="text/javascript">
window.prompt('Please enter your name: ','');
</script>

The method window.confirm() displays a standard dialog which allows the user to respond with either ok or no. The parameter is a prompt message.

<script type="text/javascript">
window.confirm('Shall we continue ?');
</script>

Interactive 'Hello World' Example

To improve a bit on the basic 'hello world' example and to show how JavaScript can introduce interactivity with the user, let's prompt for the user's name and then use it in our display.

<script type="text/javascript">
name="";
name = window.prompt('Please enter your name: ','');
document.write('hello '+name+ ' !');
</script>

name=""; introduces the concept of a variable which is a temporary data holder. Variable names must begin with a letter, contain only alphanumeric characters and underscore, and are case sensitive. Appendix - Reserved Words list words with special meanings that cannot be used as variable names. The Core Language tutorial has more details on variables, operators and statements.

After the data is entered using the prompt method, it is stored in the variable called name. It is then appended to the message 'hello ' and displayed on the screen. Note that an alert window could also have been used for the display.

Last Update and Current Date Examples

The first snippet demonstrates a useful script to tag your web pages with the lastmodified property of the document object. Many authors hard code the file date into the text but forget to update it when the page changes. Why not let the browser do the work for you?

<script type="text/javascript">
document.writeln("This page updated on " + document.lastModified);
</script>

This page updated on 09/08/2007 03:27:53

The next example introduces the built-in system object called Date. A copy of the object called todays_date is created with the new operator and then printed. For more on objects and how they are created, refer to Objects, Events and Functions. For a complete listing of system objects refer to ECMA Core Objects.

<script type="text/javascript">
todays_date=new Date();
document.write("Current Date/Time is ");
document.writeln(todays_date);
</script>
Current Date/Time is Tue Sep 11 03:43:32 UTC+0530 2007

Using the Status Line

Writing a message on the status line using the status property of the window object is just as easy as calling an alert window and is less intrusive. This sample script must be placed in the head section as it uses two user defined functions (one to display a message and the other to reset the status line). Functions are explained in the Objects, Events and Functions tutorial. To start the display function the onLoad event is referred to by the body element (eg <body onLoad="showStatus();">). Events are discussed in the Objects, Events and Functions tutorial.

<script type="text/javascript">
function showStatus(){
  window.status='hello world!';timerId=setTimeout("xit()",1000);}
function xit(){window.status="";}
</script>

After a fixed amount of time delay, the status line is cleared using the setTimeout() method. It transfers control to the xit() function (first parameter) after 10 seconds (the second parameter [value in brackets] which is given in milliseconds). Because the setTimeout() method is only defined for the window object, you do not need to use its full name (ie. window.setTimeout()).

Caution: Current programming practice avoids the use of the status line unless absolutely necessary. Many readers rely on access to the status line for observing link addresses. Also be aware that a reader can choose to turn off the status line display.

2 Objects, Events and Functions

JavaScript uses modern object oriented programming techniques to make it easier to program and reuse code. JavaScript is also highly interactive because it is event driven (ie. it reacts to user or system activities).

This tutorial describes JavaScript objects, function calls and event handling as well as many useful event functions.

TOPICS

Objects, Properties and Methods

Objects are collections of related properties and methods. Properties are things, similar to variables but their contents are contained within the object itself. Methods are actions that can be performed on an object. Often methods alter one or more of an object's properties.

Note: an analogy may be of help here. One can consider cars as objects. They have a collection of properties, one of which is the status of the parking brakes (park_brake) (either set or released). One method or action would be to apply the parking brakes (apply_park_brake()) which would change the status of park_brake to set.

Objects can be created when necessary by using the new operator keyword and equating them to a name. The created object can then have its properties accessed and appropriate methods applied to it. An example of object creation using our analogy is would be:

myCar=new Car;// creates one car from the Car template

Object properties and methods are accessed using dot notation such as object_name.object_property or object_name.object_method(). Note that methods are identified by brackets. When a method is unambiguous (ie only available through one object), the object_name can be omitted such as alert() instead of window.alert(). But this is not good programming practice. Also the dot notation is considered as a hierarchy (or tree) notation. For example to refer to the current value property of a specific control object within a specific form object you would use a format like form_name.control_name.value.

A simple example using the math object's property PI reveals JavaScript's value of π.

window.alert('The value of PI is '+Math.PI);

Another simple math example demonstrates a method that rounds a number to the closest integer.

window.alert('The value is '+Math.round(4.56789));

The JavaScript Appendix shows how object rich the JavaScript language is. There are many core and client side browser specific objects with methods or routines to handle data gathering and display, string and math manipulation, and system calls. The object properties are used to retain settings for recall.

Note: Some global object [core] methods are also referred to as built-in functions.

User Defined Functions

Functions gather a group of statements together for performing a complex operation or reaction to an event action. The general format of a function looks like:

function doIt(param1, param2, etc.){
    some statement ;
    another statement;
    etc;
    return xyz;
    }

A function is begun with the keyword function followed by a unique identifier name and a set of round brackets. Inside the round brackets is a parameter list of identifiers or names for each value passed to the function, separated by commas. These values can be simple data (such as numbers or strings) or objects. The parameter list can also be empty (ie. null)! Statements within the function are grouped into a block using brace (curly) brackets. A function is called or started by referring to it in another portion of the script or from an event handler.

Parameters are passed by value, ie. changing the variables value inside the function will not change its value outside the function. It is good programming practice to use different parameter names when writing a function!

Functions can optionally return a single value back to the event handler or other function that called them.

Note #1: There is no semicolon after a curly bracket!
Note #2: The round brackets must be used in both the function and the calling statement even when no parameter values are passed.

Functions are useful in separating code from the XHTML (functions are normally found in head section) and can also be referenced or reused from several other points in the script. Functions are NOT a part of object oriented programming but provide an much easier approach to fast program development. JavaScript makes this tradeoff to keep the language from being 'elitist' only!

function biggest(a,b,c){
   biggun=a; // start by assuming first is biggest
   if(b>biggun){biggun=b;}
   if(c>biggun){biggun=c;}
   return biggun;
}
...
alert('biggest is '+biggest(x,y,z));

This function has three formal parameters. Based on the values fed in, the largest numerical is selected and returned to the caller. The caller simply displays the result. Note that the parameter names in the caller do not need to be (and in fact it is good programming practice that they are not) the same as the formal parameters used in the function.

Event Handlers

Events are actions that occur because of user interaction. Using the car analogy given above one possible event is pressing the parking brake pedal which would use the apply_parking_brake() method and perhaps others such as turn_brake_indicator_on() and turn_running_lights_off(). In computing, user events (like moving the mouse) or system effects (like a file completing loading) are common occurrences. JavaScript can use event handlers to initiate some process such as checking for valid information in a form by calling a function. To see the list of possible actions that you can program for by using event handlers, check Appendix - Events and Handlers.

The most common method of calling a function with an event handler is to treat the event as an XHTML attribute for the appropriate element. Note that any element, not just form controls can have associated events. To enable event handling from an XHTML attribute use a call such as:

event_name="function_name(parameter_list);return true;"
    This format forces a true result to be passed to the event_name.
event_name="return function_name(parameter_list);"
    This format allows a function to return a true/false indicator.
    This can be used with validation handlers to react to bad input.
event_name="function_name(parameter_list);"
    The result passed is unpredictable.

For example:

<body onLoad="startUpStuff()>"

The preceding line would call the function startUpStuff() as soon as the page was loaded. Another example is:

<form name="formx" action="?" method="post">
<input id="b1" name="b1" type="button" value="Transfer Now!"
   onclick="transfer(a,b);return true"/>
...
</form>

Note that the string between the quotes is a list of Javascript statements. If there are more than a couple of statements it is better programming practice to call a single function whose task is to sequence those statements. And the code is much more readable too!

Time On Page Example

The next example illustrates how one can time how long a viewer remains on a page. The person_in function records the start time. The person_out function records the stop time, takes the difference and shows the result to the reader. The result could also be accumulated in a cookie!

<script type="text/javascript">
function person_in(){enter=new Date();}
function person_out(){
exit=new Date();
time_dif=(exit.getTime()-enter.getTime())/1000;
time_dif=Math.round(time_dif);
alert("You've only been on this page for: "+time_dif+" seconds!!");
}
</script>
. . .
<body onLoad="person_in()" onUnLoad="person_out()">
<h1>Timing This Page Now!</h1>

Page Timeout Example

This example watches how long the page has been displayed and transfers to another page when timed out. The application is perfect for a static splash screen or front 'intro' page. Be sure to use the onLoad event to initialize the timer function.

<script type="text/javascript">
limit=5;// time limit in seconds
limit=limit * 1000;
function timer(){
  setTimeout('window.location=""',limit);
  }
</script>

Mouse Rollover Effect

In the most common form, a rollover consists of an image serving as a hypertext link. While the mouse pointer is over the image, it changes appearance to attract attention to the link. For example, you could add a glow effect, a drop shadow or simply change the background color. The onMouseOver and onMouseOut events are used for rollovers. Images are preloaded to avoid delays in transmission.Here is an example of the JavaScript functions which can be placed in the document head section or saved as a separate .js file:

// preload images to avoid delays
img1out=new Image();img1out.src="images/enter1.gif";
img1over=new Image();img1over.src="images/enter2.gif";
img2out=new Image();img2out.src="images/keio.gif";
img2over=new Image();img2over.src="images/inria.gif";
// add statement pair for each rollover wanted
function chgImg(el, image){document.image[el].src=eval(image+".src");}

And the XHTML document code to be used for each rollover area is:

<a href="#" onMouseOver='chgImg("item1","img1over");'
  onMouseOut='chgImg("item1","img1out");' onfocus='chgImg("item1","img1over");'
  onblur='chgImg("item1","img1out");'>
<img id="item1" src="images/enter1.gif" alt="*"/></a>

and here is what it looks like ...

*

NOTE: These images were created using a freeware painting tool by adding a hot wax effect and then a drop shadow to the text. You can find advice and royalty free clip art on the Web by using a search engine.

And here is a second rollover to show how the Javascript portion is reusable. In fact every rollover on your site can be pointed to the same external .js file if you wish!

Note: Make sure that all of the images are the same width and height. An alternative is to add width and height attributes to the img element to ensure the images are all shown at the same size.

Timed Ad Cycler

If your website has several sponsors, then you can use an image link that cycles through each of the sponsor's ads in turn. The first step is to create an image for each of your sponsors banner ad. All the images should have the same size. The corresponding URLs for the images and for the websites are then loaded into the arrays named adImages and adURLs defined at the start of the script. The img element for the link should be initialized to the first image in the array. The cycle is started by using the onLoad event on the body element. The delay between ads is set by the setTimeout() method.

<script type="text/javascript">
adImages=["images/mit.gif","images/inria.gif", "images/keio.gif"];
adURLs=["www.lcs.mit.edu","www.inria.fr","www.keio.ac.jp"];thisAd=0;
function gotoAd(){document.location.href="http://"+adURLs[thisAd];}
function cycleAds(){
  if(++thisAd==adImages.length){thisAd=0;} //move to next ad
  document.images.adBanner.src=adImages[thisAd]; //display current ad
  setTimeout("cycleAds()", 3000);  //change ad every 3 seconds
}
</script>

The above is placed in the head section and the following in the body:

<body onLoad="cycleAds()">
...
<a href="javascript:gotoAd()"><img name="adBanner"
src="images/mit.gif" border="0" alt="Our sponsors"></a>

Our Sponsors:

body {
  background: #eeeeee;
  font-family: "Trebuchet MS", Verdana, Arial, serif;
}

As you can see in the above code I have seperated the color from the font-family with a semi-colon, seperated the various fonts with commas and contained the "Trebuchet MS" within quotations marks. The final result sets the body color to light grey, and sets the font to ones that most users will have installed on there computer.

I have changed the way I layout my code, but you can arrange it in one line if you choose. I find that it is more readable if I spread each property to a seperate line, with a 2 space indention.

Inheritance

When you nest one element inside another, the nested element will inherit the properties assigned to the containing element. Unless you modify the inner elements values independently.

For example, a font declared in the body will be inherited by all text in the file no matter the containing element, unless you declare another font for a specific nested element.

body {font-family: Verdana, serif;}

Now all text within the (X)HTML file will be set to Verdana.

If you wanted to style certain text with another font, like an h1 or a paragraph then you could do the following.

h1 {font-family: Georgia, sans-serif;}
p {font-family: Tahoma, serif;}

Now all <h1> tags within the file will be set to Georgia and all <p> tags are set to Tahoma, leaving text within other elements unchanged from the body declaration of Verdana.

There are instances where nested elements do not inherit the containing elements properties.

For example, if the body margin is set to 20 pixels, the other elements within the file will not inherit the body margin by default.

body {margin: 20px;}

Combining Selectors

You can combine elements within one selector in the following fashion.

h1, h2, h3, h4, h5, h6 {
  color: #009900;
  font-family: Georgia, sans-serif;
}

As you can see in the above code, I have grouped all the header elements into one selector. Each one is seperated by a comma. The final result of the above code sets all headers to green and to the specified font. If the user does not have the first font I declared it will go to another sans-serif font the user has installed on there computer.

Comment tags

Comments can be used to explain why you added certain selectors within your css file. So as to help others who may see your file, or to help you remember what you we're thinking at a later date. You can add comments that will be ignored by browsers in the following manner.

/* This is a comment */

You will note that it begins with a / (forward slash) and than an * (asterisks) then the comment, then the closing tag which is just backward from the opening tag * (asterisks) then the / (forward slash).

3 - Core Language

JavaScript like many languages (eg C, Java, awk, perl) is based on a common syntax and grammar developed by the Bell Labs in the 60's. This makes it easy to cross over from one language to another based on program requirements, resources and politics. This tutorial on JavaScript syntax and grammar (ie. programming in the small) assumes introductory programming experience in another language and includes the following topics:

TOPICS

Lexical Structure

The lexical structure of a programming language is the set of elementary rules that specify how you write a program. It is the lowest level syntax of a language and specifies such things as what identifier names look like. Some of the basic rules for JavaScript are:

  • JavaScript is case sensitive.
  • Whitespace, tabs, and newline characters are ignored except when part of string constants. Whitespace can be added as needed for readability.
  • Block comments begin with /* and end with */ [preferred over single liners]
  • Single line comments begin with //
  • Identifiers are names for constants, variables, functions, loop labels, objects and classes. The first character must be an ASCII letter, underscore or dollar sign. Following characters can also include digits.
    Note1: JavaScript style has constants in all uppercase and classes beginning with an initial capital letter.
    Note2: An identifier must NOT be any word contained in the JavaScript Reserved Word List
  • Reserved words (or keywords) have special meanings within the language syntax. Check the JavaScript Reserved Word List for a complete listing.
  • Statements terminate in semicolons! Make sure to always terminate statements with a semicolon.

Literals or Constants

Literals (or constants) are values that do not change within a program. Some types of literals and examples are:

  • Boolean: true, false
  • Numeric 5, 0xFF (hexadecimal), 2.543, 8e12, -4.1E-6
  • String: 'fred', "Fred and Ethel"
  • Primitive: Infinity, NaN, null, undefined

One question that is often asked is 'WHY can one use either kind of quote marks (they must match however) when defining a STRING value?' The answer lies in the fact that you may need to have a string that uses a possessive form or contraction (apostrophe) or an internal quote. To handle either situation bracket the string with the opposite form of quote

Note: Floating point numbers less than one should begin with a leading zero. For example write 0.1 rather than .1

Warning: If a number begins with two zeros and contains a decimal point (eg. 005.3) it will generate an error. Validation techniques to guard against this type of error will be discussed in Getting the Bugs Out.

Escape Characters

Escape characters are used inside literal strings to allow print formatting as well as preventing certain characters from causing interpretation errors. Each escape character starts with a backslash. The available character sequences are:

Seq Name Seq Name
\b backspace \f formfeed
\t horizontal tab \" double quote
\n newline \' single quote
\r carriage return \\ backslash
\### Latin encoded character \uHHHH Unicode encoded character

Variables

Variables are temporary data holders. Variable names (or identifiers) must begin with a letter, underscore or dollarsign, use ASCII characters and underscore only, and are case sensitive. They can not be one of the JavaScript reserved words. Variables are declared with the reserved word var (optional). At the same time variables are declared they may or may not be assigned or take on a value of boolean, numeric or string type. JavaScript is said to be a loosely typed language as the variable can take on a different type later in the script depending on its 'assigned' value. Variables have scope, ie. they are either global (defined outside any function) or local to the function they are defined within).

var name;            /* variable created but undefined */
signal_flag = true;  /* boolean */
counter = 1;         /* numeric */
first_name = 'fred'; /* string using single quotes */
last_name = "fred";  /* string using double quotes */

Arrays

Arrays allow you to store several related values in the same variable (eg. a set of marks). They are created with either a literal constructor or the new operator and Array constructor.

myArray = []; // null literal array [Best Practice]
myDataArray = [25,30,22,10]; // array with values [Best Practice]
myImages = new Array(); // uses new to assign variable name but no content
myPics = new Array(10); // assigns space for 10 items
myData = new Array(25,30,22,10,5); // assigns data on array creation

An example that shows how days and months can be displayed as text rather than as numbers is:

// Set up array of day Names
dayNames=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday',
   'Saturday'];
// Set up array of month Names
monthNames=['January','February','March','April','May','June',
   'July','August','September','October','November','December'];

To access an individual value in an array use the array name followed by an indexing number in square brackets. The array name by itself will return the full array (ie. all values). If you ever need to know how many items are contained in an array, use the length property (eg. monthNames.length would return the value 12).

ADVANCED TOPIC: Multiple dimension arrays can be set up as an array of arrays.

array1 = ['fred', 'ethel', 'ricky', 'lucy']; // people
array2 = ['65', '60' , '33', '31'];   // ages
arrayArray = [array1, array2]; // two dimensioned array of above
alert(arrayArray[0][3]); // shows array access

ADVANCED TOPIC: Associative arrays can be faked by using the Object object.

aa=Object();
aa["red"] = "red";  // if you like bracket style
aa.size = 15;       // if you like object style

You can access the values in the usual manner. And to get a full display of the entire array you can use the for/in construct.

text = "";
for (prop in aa) {
    text += prop + ': ' + aa[prop] + ' \n';
    }
alert (text);

Operators

Operators are actions that manipulate, combine or compare variables. They fall into several categories as follows:

  • Arithmetic: + - * / % (modulus) ++ (increment) -- (decrement)
  • String Concatenation: +
  • Assignment: =
  • Advanced Assignment: += -= *= /= %=
  • Comparison: == != > >= < <=
  • Identity: === !==
    Note: Use this form when type conversion is unwanted before comparison! (eg true, false, null or "")
  • Logical: && || !
  • Bitwise: & | ^ ~ - << >> >>>
  • Conditional: ? (eg. ans = (w<x) ? trueval : falseval )
  • Typeof: typeof
  • Object specific: new, delete
  • Void: void [returns undefined regardless of expression]

Expressions and Conditions

Expressions are used to combine two or more values using operators to create a new value. One example is x + y which will add the two values together if they are numeric or catenate or join them together if they are strings.

Conditions compare two values (often as variables) and return either a true or a false value. An example is "does x equal 9". In JavaScript the condition is surrounded by round brackets and expressed in logical terms (x == 9) note the double equal!.

Statements

Statements are complete program instructions made from constants, variables, expressions and conditions. Statements always end with a semicolon. A program contains one or more statements. Although most interpreters assume a semicolon at the end of a line, a good coding practice is to make sure you put it in explicitly!

Blocks are sets or lists of assignment statements enclosed in curly brackets. Blocks are normally treated as units.

Variable statements assign a named placeholder for referencing a value. The variable statement can optionally assign an initial value as well. For example:

this_car;
this_truck = "Mazda B2000";

Assignment statements use an assignment operator to store a value or the result of an expression in a variable.

first_name = "Fred";

Conditional statements execute a set of other statements only if certain conditions are met. The condition is always enclosed in round brackets. The statements to be performed if the condition is true are enclosed in blocks (ie curly brackets). For example:

if (value > 5) { x = 7;}

Occasionally you may want to perform some actions for the false outcome of the condition as well. The else keyword is used to separate branches.

if (name == "fred") { x = 4;} else { x = 20;}

NOTE: When the conditional if statement is used only to make an assignment to one variable, you can use the terse C syntax such as:

x = (name == "fred") ? 4 : 20;

Loops and Switches

While statements allow a set of statements to be repeated or looped through until a certain condition is met. For example to output #1 #2 #3 etc. on separate rows you could write:

while (i<=5) {
    document.writeln("#"+i);
    i = i + 1;
    }

For statements allow a set of statements to be repeated or looped through a fixed number of times. For example to output #1 #2 #3 etc. on separate rows you could write:

for (i=1; i<=15; i++) {
    document.writeln("#"+i);
    }

For ... in statements allow looping through all the elements of an array or properties of an object. For example:

for (propname in navigator) {
    browser += propname + ": " + navigator[propname] + "\n";
    }
alert(browser);

would loop through all the navigator object's properties. This can be made into a great exploring tool.

Switch (or case) statements are used to select which statements are to be executed depending on a variable's value matching a label.

yourchoice=window.prompt('pick a number between 1 and 3');
switch (yourchoice) {
   case '1': alert('you typed a 1'); break;
   case '2': alert('you typed a 2'); break;
   case '3': alert('you typed a 3'); break;
   default: alert('Only 1, 2 or 3 allowed!);
   }

A problem with this example is that there is only one type of error checking done. What if the user had entered a punctuation sign or typed TWO instead. Also this is a forced example as one could have used the variable yourchoice within the alert method and not used a switch statement at all. Think of the example as just a demonstration of how the switch statement is structured.

Continue, Break and Return

Continue statements are used in 'while' or 'for' statements to force another iteration of the loop. The following is a trivial example. Most often the continue is used as part of a conditional statement that only happens in certain cases.

x = 0;
while (x < 10) {
   x++;
   alert(x);
   continue;
   alert('you will never see this alert dialog');
   }

Break statements are used in 'while', 'for' and 'switch' statements to force an abrupt termination or exit from the loop. In the following example the loop is never completed. Once again the normal use of break is as part of a conditional statement.

x = 0;
while (x < 10) {
   x++;
   alert(x);
   break;
   alert('you will never see this alert dialog');
   }

Return statements are used to exit quickly from a function or to to pass values back from the function.

4 - DOM and DHTML

Dynamic HTML (DHTML) is a collection of strategies (scripting, CSS and DOM) that lets you create web pages that are more interactive, responsive and animated than ever before. The W3 Consortium document object model (DOM) extends access to virtually every HTML element using programming objects as the basic modeling paradigm. This allows a variety of scripting languages to dynamically modify the look of a page as they react to events. Although all modern browsers incorporate DOM, they are not at the same stage and the model itself is being extended. QuirksMode.com gives details of variants. It is always a wise procedure to test any browser that your clients/viewers may use against the w3.org DOM support test.

TOPICS

Accessing Elements Using DOM

The procedure for setting up access to an element is:

  1. Establish appropriate property values for the element's class [CSS]
  2. Identify the element with a unique id attribute [HTML]
  3. Set a class group attribute for the element [HTML]
  4. Create an activating event that passes the identifier [HTML]
  5. Capture the element's object [script]
  6. Work with the element's style, position, visibility or content [script]

Capture an element's object by using the DOM document.getElementById('idname') method and the appropriate object such as style. You can then modify any of the object's properties (such as styling, position, visibility or content).

Dynamic Style - Color & Font Changes

Objects and Events has already demonstrated how different images could be activated with the onMouseOver and onMouseOut events. As an simple example of implementing DHTML using the DOM model here is one approach for changing a heading's color as the cursor rolls over it. Note that the element identifier is passed to JavaScript so that the function can be written in a generic way.

Changing Color Test - Touch Me!

...
<style type="text/css">
h2.rollover {color:black}  /* initialize properties on class */
</style>
<script type="text/javascript">
function change(thistag){
   styleObj=document.getElementById(thistag).style;styleObj.color="red";
}
function back(thistag){
   styleObj=document.getElementById(thistag).style;styleObj.color="black";
}
</script>
...
<h2 id="roll" class="rollover"
   onMouseOver="change('roll');" onMouseOut="back('roll');">
This is the changing color heading...</h2>
...

You can achieve a fade effect by choosing colors of successive shades and cycling through them. Our first example of fade is programmed with a increment function using a switch statement to select the next color. The onMouseOver event is used to trigger the event. You could also use an onclick event or better still an onLoad event and setTimeout() method.

Fading Color Test - Touch Me!

The JavaScript code for the fade function is:

fadept=0; // global to remember fade state
function fade(thisone){
col="#000";
switch (fadept){
    case 0:col='#000';break;
    case 1:col='#333';break;
    case 2:col='#666';break;
    case 3:col='#999';break;
    case 4:col='#aaa';break;
    case 5:col='#ccc';break;
    case 6:col='#ddd';break;
    case 7:col='#eee';break;
    case 8:col='#fff';break;
    }
fadept+=1;  // increment for next time around
if(fadept>8){fadept=0;} // hit end so reset
    styleObj=document.getElementById(thisone).style;
    styleObj.color=col;
 }

The second version of fade uses a mathematical progression for the fadeout. It also automatically fades on a timer. You may want to reset the count or have a method for starting the fade another time.

fadept2=0;       // global to remember fade state
fadeid="fadezone"; // global for object to be faded
function fade2(){
    if(fadept2 < 255){
    fadept2+=4;
    styleObj=document.getElementById(thisone).style;
    newColor='rgb('+fadept2+','+fadept2+','+fadept2+')';
    styleObj.color=newColor;
    setTimeout('fade2()',2);
    }
}

For a more flexible fader check the source code for JR's Ultimate Fader. The user can pick both start and finish color as well as the number of steps in the fade effect. Routines to allow cycling or reverse cycling are included but not hardwired. The effect can also be redirected to any element that a programmer wishes to write for.

Instead of using color changes, you could do fontsize changes to achieve a zooming effect. Instead of using the switch to set the colors, you set siz="12pt"; etc. and then use the fontSize property. Note that CSS style properties with hyphens are changed when used as a JavaScript property. Drop the hyphen and capitalize the next word (eg. CSS margin-left becomes JavaScript marginLeft).

Font Change Test - Touch Me!

Dynamic Visibility - Collapsing Text

Using the display property of CSS, one can hide segments of content such as detailed descriptions or sub topics until needed. This adds clarity to the presentation. Collapsing menus is a simple application of the visibility property. The function expand uses a pointer from the topic element clicked on to access and unhide its related subtopic element. The next click on the topic element rehides the subtopic. This could be expanded several levels if needed.

Topic One
Topic Two
Topic Three

The XHTML component uses styled topic elements (in this case h6) that are always visible but clickable. The onclick event calls the expand function for its related subtopic element.

<h6 onclick="expand('text1');">Topic One</h6>
<p id="text1" style="display:none;color:red">
A whole bunch of stuff that needs display</p>
....  etc.

The expand function toggles the display property for any referenced element. Note that a global state saver is not needed as this function can easily access the current state using a style property.

function expand(thistag){
  styleObj=document.getElementById(thistag).style;
  if(styleObj.display=='none'){styleObj.display='';}
  else {styleObj.display='none';}
}

Dynamic Visibility - The <noscript> Issue

You should always write code that assumes that some users may not have JavaScript enabled browsers or have temporarily turned it off. This is part of the 'Be kind to ALL users' philosophy. HTML provided a noscript element specifically for this purpose but many browsers (such as Opera, SlimBrowser etc.) do not respect it when scripting is turned off. The workaround is to use a div with display styling. Write a simple function that turns the display property to none and call this function with the onload attribute of the body element.

function hidemsg(){
  document.getElementById('jsmsg').style.display='none';}
....
<div id="jsmsg">NOTE: Your browser does not support JavaScript
    or support has been turned off. Sorry!</div>

The message between <div> and </div> will appear on a non-script enabled browser or one with scripting turned off.

Dynamic Content - Toggle Button Caption

An important use of dynamic content is to isolate repetitive or changing text to an external JavaScript file. Documents needing this material only require a pointer to the file and a specific element to contain it. Changes in content need not be copied to all referring documents. embedding audio has a working example of dynamic text.

  • Use the value property for most form controls.
  • Use the innerHTML property for the textarea control and all non-form elements.
  • Caution: Nothing works for textarea in Opera! Fall back to older DOM0 methods.
  • Beware: MSIE has non-DOM model restrictions on some elements. Read this!

An older method for dynamic writing of content commonly seen in texts and internet articles was document.write() but it is invalid for xml (and hence xhtml) documents. Quirksmode Blog indicates a possible continuing use for the document.write function.

Some utilities need a toggle or push to start/push to stop button. One example is a run/pause button within a slide show. Since a button's value is displayed as a caption, it becomes easy to alter the caption value with an if condition. There is also a multiple toggle button demo available.

flip=false;off="Start";on="Stop" // global to save state
flip=false;on="Stop";off="Start"; // global to save state
function toggle(pn){
p=parseInt(pn,10); // make sure its a number
if(flip){
   //insert stopping code action here
   document.getElementById('b'+p).style.background="lightgreen";
   document.getElementById('b'+p).value=off;
   } else {
    //insert starting code action here
   document.getElementById('b'+p).style.background="red";
   document.getElementById('b'+p).value=on;
   }
flip=!flip; // toggle th state of button
}

The above control uses styling classes for effect and the html is:

<div class="togglezone">
<input id="b0" class="togglezone" type="button" onclick="toggle('0')"
       value="Start"/></div>

Dynamic Positioning - 'Sticky' Elements

Long pages may cause problems for some viewers. A GoToTop link sitting in the lower right of the screen can help. This is done by moving the element according to its scrolled position so that it appears to stick. Sticky elemnts can also be used to hold menus or title sections on screen. Sticky elements are added to the document's body as in:

<div id="stickyEl"
style="position:absolute;top:380px;left:655px;z-index:3">***</div>

The sticky element (stickyEl) can be styled as desired. Non-dynamic content can also be included inside the sticky element (note the ***). Non-dynamic content will be displayed if not overridden by dynamic content or whenever JavaScript is disabled or unavailable. An onload="stickyInit();" attribute is required in the body element to start the position checking loop.

scrollSpeed2=20; //Screen refresh rate in msec.
scrolled2='document.body.scrollTop';var ltop2;
function checkScrolled2(){ //backTo Top link stays in lower right
  document.getElementById('stickyEl').style.top=eval(scrolled2)+ltop2+'px';
  setTimeout('checkScrolled2()',scrollSpeed2) ;}
function stickyInit(){
  copy='<a href="jstutor4.htm">GoTo Top<\/a>'; // dynamic text only
  document.getElementById('stickyEl').innerHTML=copy; // dynamic text only
  x1=eval(scrolled2);window.scrollBy(0,1);  //test scrolled2 ptr
  x2=eval(scrolled2);window.scrollBy(0,-1); //reset position
  if((x2-x1)<1){scrolled2='document.documentElement.scrollTop';}
  ltop2=parseInt(document.getElementById('stickyEl').style.top,10);
  checkScrolled2();}

The start of the script points at the object that normally contains the document scrolled info (scrolled2). The initializing function (stickyInit) alters the pointer for browsers that do not use that method. On scrolling the top property is adjusted to hold the position. A further improvement would be to adjust both the top and left offset to accommodate scrolling, resolution changes and window sizing. A loop (checkscroll2) monitors the visual top of the document and adds an offset to place the 'sticky' element where wanted (in this case at the bottom of the screen). This example also uses optional dynamic text.

5 - DOM GrabBag

The grabBag page is a spot for DOM events and objects that don't fit in other areas. Many are fundamental to larger applications and projects.

TOPICS

Object Explorer Tool

This example displays all the properties that a specific browser agent contains in its navigator object. Note that many of the properties are not available on older browsers but it is worth while checking for yourself. You must run this example using each of the browsers that you want to check out.

The technique uses a for/in loop which works a bit differently than the usual for loop that we have been using for string scanning. Instead of incrementing a counter, For/in loops increment their way through the named object's properties. In this case the named object was navigator which indicates the browser. But you could have used other objects such as window or Math. Those who enjoy finding every property implemented can have fun by grabbing the next chunk of code and changing the name navigator to another object name. What client object properties are not available in Opera 7? That is easy to find out. A bit harder is to find out if MSIE is missing one of the core object properties. But a bit of testing and saving screen shots will solve these problems.

function explore_it(){
browser="browser info:\n";
if(!navigator){alert('navigator object missing from browser');}
for (propname in navigator){browser+=propname+": "+navigator[propname]+"\n";}
alert(browser);
}

Event Listeners

Event listeners are event handlers that are defined within JavaScript itself. This lets the application react to a user initiated event immediately. For example resizing a window may require repositioning some elements.

window.onResize = someFunctionName;

In this example someFunctionName will be called on each window resizing event. Note that there is no parameter brackets for the event listener function call. The initiating event object is passed to the function differently based on the browser!. mozilla receives the object through a passed parameter while MSIE uses the window.event object. The following object sensor will make your function browser-transparent.

function someFunctionName(e) {
e=e||window.event; //fudge browser
... }

Unfortunately the onResize event in some browsers only applies to a window and not to an object. It sometimes helps to implement an onFocus event listener as one natural user reaction is to click on any out-of-sorts display before clicking on the refresh icon.

Cursor Location

Some dynamic positioning applications are dependent on cursor location. This is determined in different ways depending on browser. A reliable getMouse() function is given for those who need to use cursor positioning

xMouse=0;yMouse=0;      // globals to hold coordinates
document.onmousemove=getMouse; // start event listener
function getMouse(e){
e=e||window.event;
if (e.pageX||e.pageY){xMouse=e.pageX;yMouse=e.pageY;}
  else {
    de=document.documentElement;b=document.body;
    xMouse=e.clientX+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||0);
    yMouse=e.clientY+(de.scrollTop||b.scrollTop) - (de.clientTop||0);}
}

Popup boxes allow the display of annotations, attributions, citations, definitions or other small notes while retaining the context (unlike tabbed windows). The position of a hotbox can be determined by the cursor location. Hover a hotzone and a popup box can allow a set of notes or links to be displayed. Hover a link and a tooltip like information box can be provided. The onclick event or a form button can also trigger a popup. The popup menu demo uses a styled table and dynamic positioning.

Window Dimensions

Many animations require knowing the window boundaries of your page which could possibly be resized. Unfortunately MSIE doesn't provide an innerHeight or innerHeight property so one must make use of its document.documentElement.clientHeight and document.documentElement.clientHeight properties.

h=self.innerHeight;
if(!h){h=document.body.clientHeight+document.documentElement.clientHeight;}
w=self.innerWidth;if(!w){w=document.documentElement.clientWidth;}

Object Position|Dimension

At times you need to find the dimensions or absolute position of an object on a page regardless of resizing or font. One application is positioning a floating menu in a sidebar where it does not float upwards into any static information in the sidebar.

function getX(oNode){var x=0;
while (oNode){x+=oNode.offsetLeft;oNode=oNode.offsetParent;}
return x;}
function getY(oNode){var y=0;
while (oNode){y+=oNode.offsetTop;oNode=oNode.offsetParent;}
return y;}
function getWidth(oNode){return oNode.offsetWidth;}
function getHeight(oNode){return oNode.offsetHeight;}

Equalized Column Heights

The common practice for parallel columns is to use either float or absolute positioning within a div structure. However the columns can be of unequal height which is unattractive when they are colored differently as often done in sidebars.

By default the height property is content dependent. Setting it to a specific size would not respect resizing and font changes. And unfortunately w3.org chose to interpret height:100% to be relative to the window and not to the document! Using the dimensioning routines from above you can guarantee columns are equal in length.

function equalize(){
  cObj=document.getElementById('content');
  sObj=document.getElementById('sidebar');
  if(!cObj||!sObj){return;} //column ids??
  ch=getHeight(cObj);sh=getHeight(sObj);
  if(sh<ch){sObj.style.height=ch+'px';}
  if(ch<sh){cObj.style.height=sh+'px';} }

Jumping To A New Location

The top.location object has an href property which can be set to an URL which will be jumped to. The URL reference can be local or to a new document. The URL is often dynamically set in script and jumped to on an onclick or onmouseover event.

The property top.location.href can also be used in other ways to jump to a new HTML document. For example by using the system's date, one could move on to other screens depending on the day of the week or hour of the day. It can also be used with browser sniffing (described in Dynamic Form Examples) to skip a page for specific browsers which do not support specific code on that page.

Click To Print Effect

Suppose you have a page with an image such as a directions map on it. You want the reader to be able to click on the image to print a copy. You can start with the onclick event tied to the image element. It would call the window.print() method to do the actual printing of the page.

<img src="location.jpg" onclick="window.print();">

But what if you only want to print the image and not the rest of the page. This takes a bit more work but mostly a bit of thought. Since window.print() does a whole page, why not put a copy of the image on its own page. You can even scale the image, center it, and add information if needed. A fragment of the second page is:

<script type="text/javascript">
function doit() {
window.print();\\ does the print of this page
top.location.href='first.htm';} \\ returns to original page
</script></head><body onload="doit();">

The only additional component you need besides the two pages is a method of transferring from one to the other.

<img src="location.jpg" onclick="top.location.href='second.htm';">

 6 - Animation and Multimedia

Animation is the process of making text and/or graphics move or appear to move. Multimedia includes audio, video and print presentations. Animation does not add content to a webpage but multimedia does. When properly used, both can be important attractors of viewers or highlighters of material needing emphasis.

TOPICS

Scrolling Marquees

Marquees or scrolling banners are used to draw the reader's attention to important information such as a new product release. The HTML marquee tag has been superceded by dynamic marquees using JavaScript data manipulation. One algorithm that is easy to implement is to rebuild the message to be displayed by dropping the first letter and adding one to the end, then redisplaying the message after a short delay. The first rather simple example uses the status bar for display. It could be autostarted with the onLoad event but then it should also be timed out instead of continuously running. Remember that the status line has some very important uses and should not be captured forever by a JavaScript function.

mmsg=" -- JR's marquee demonstration";
counter=(mmsg.length+1)*1;rate=8;
function scrollMsg() {
if (counter>0) {
  window.status=mmsg;
  mmsg=mmsg.substring(1,mmsg.length)+mmsg.substring(0,1);
  setTimeout('scrollMsg()',1000/rate);counter -=1;}
}

The example is terminated by counting the letters and stopping after one pass through. You can change the number of passes by changing the multiplier on the counter variable. Another refinement would be to start with no message at the start. I chose to present the whole message first to remove the drama ;-]

An improved version starts with a blank marquee and runs continuously. Output is to a textarea form element to show some display variations that are allowed with JavaScript. You can use style to hide or change the look of the textarea if you wish.

text=" This is the demonstration text -- ";
len=text.length;// total characters in status line - Opera is short!
msg="";      // build blank message for clean start
for (i=0;i <= len;i++) {msg+=" ";}
pos=0;       // pointer into text array
speed=10;    // adjust scrolling speed here

function scroll(id) {
msg=msg.substring(1,len)+text.charAt(pos);
// slides window over and adds one char from text message
document.getElementById(id).value=msg;
if (pos++==text.length) {pos=0;}
// returns to front of message for next go around
id=setTimeout("scroll(id)",1000/speed);
}

An assignment that will check your understanding of the algorithm is to change the scrolling so that letters appear to move from left to right instead of the usual right to left motion.

Flying Text

Text can be given the appearance of flying by using CSS positioning. The first example will fly the text to the right only. Step one is to define the text, uniquely identify it and give it some initial position. The text is contained in a div element with some inline css style. Inline style is used as the position can only be set on an element by element basis. It is placed in the body of the document. For example:

<div id="flyer" style="position:absolute;left:0px;top:10px">
Pizza to Go...</div>

An alternative to inline style is to use a css style element with an id selector:

#flyer {position:absolute;left:0px;top:10px}

The move() function sets the position of the div element using its style.left property. Note the addition of "px". This is very important for correct functioning in some browsers. If the text hasn't reached the right edge, it increments the position. Finally a delay to allow reading the message is built in by using the setTimeout() method. Without the delay the text would blur across the screen. The JavaScript code is placed in the head section of the document.

spot=0;// global state memory for position
function move() {
styleObj=document.getElementById('flyer').style;
if (spot < 500) {    // check if at right stop point
    spot+=2;               // no - so move over a bit
    styleObj.left=spot+"px"; // redisplay at new site
    setTimeout('move()',50); // but first wait 50 milliseconds
    }
}

To start the flying on page load, add an onLoad event attribute to the body element. For example;

<body onLoad="move();">

A simple modification to this routine would be to add parameters for the stop, increment, and delay settings. This would make the function much more flexible for reuse.

Another modification would be to add vertical motion with the .top style property. How about moving the other way with negative values for the steps (don't forget to set initial and final positions and invert the check method). And instead of simply stopping when you reach the limit you may want to repeat the movement. Repetition can be done by adding an else component to the decision to increment such as:

} else {  // this addition makes continuous flying possible
//  if (times < 2) {times+=1; else {return;}
    spot=0;    // this does the reset for next cycle
    styleObj.left=spot+"px"; // redisplay
    setTimeout('move()',50); // but first wait 50 milliseconds
    }

Note: The commented out line will also add a limit to the number of repetitions. For this to work correctly, times has to be declared as a global variable. And of course REMOVE the comment ;-]

For an 'Over The Top' application you could add a routine to randomly pick both the horizontal and vertical increments. And then once an edge is hit, reverse that direction. How about correct angle of bounce off the wall. Lots of ideas here for those who want to explore animation. See what you can do with dynamic text movement.

Caution: MSIE has pixelLeft and pixelTop properties which guarantee that the measure is in pixels and is a numeric quantity. Unfortunately these properties are not part of the DOM recommendation and not implemented in other browsers. Whenever you see any pixelxx references in another author's work, be sure to change them as follows:

where=styleObj.pixelLeft;  // MSIE specific position read
where=parseInt(styleObj.left,10); // generic browser read
. . .
styleObj.pixelLeft=where; // MSIE specific position write
styleObj.left=where+'px'  // generic browser write

Transitions and Viewports

Image transitions are changes from one image to another. The basic transition is an abrupt switch from one to another. Several methods can be used to make the transition more attractive. These methods include:

  • fade transition using the CSS opacity property. Technique
  • Javascript applet using a java fader class. Technique
  • sequenced images created from morphing software. Downside:Complexity and filesize bloat.
  • MSIE proprietary filters to fade or do more complex transitions such as wipes and curtains. Technique Downside: Limits viewers to MSIE browsers (the images will change - only the effect is lost).

A viewport is an image viewer that allows transition selection by hovering on a related menu item. It is set up similar to a rollover effect with event initiators onmouseover and onmouseout. The onclick event can be added to link to an appropriate page (perhaps full screen view). Viewport.zip is a working example that can be tailored with css and script. Be sure to consult the readme.txt file for setup information.

Presentations and Slide Shows

Presentations are linear structured events that focus on transfering facts to the audience in an effective and memorable way. Presentation slide shows enhance this experience with lists and graphics. In some cases interactivity and animation are included. The most commonly used presentation slideshow is PowerPoint® but this program uses proprietary techniques and bulky files. In addition, style is intermixed with content in the design process. Many Open Source Code utilities use a combination of CSS and JavaScript to duplicate the functionality of PowerPoint®. Two popular solutions are Meyer's S5 and Raggett's slidy.

A different approach to slideshows is available for those who are showing non-interactive slides but need a slick interface with transitions, an auto-sequencing timer and perhaps audio for stand-alone kiosk type operation. Herdejurgen's JSViewer and Maricopa College's JClicker emphasize the attractive user look. My own S3 (Simple Slide Show) can be a start point for those who want to roll their own slideshow.

News Scrollers

News!!!

Any important message goes here

Note: Hover on newsbox to stop scrolling!

Many sites now include a news scroller with important or fresh information. The usual way of adding a scroller is with animated gifs. But a JavaScript newsScroller will allow you to stop the scrolling by hovering on the newsbox. This gives you time to read the text. To use the newScroller as seen here, copy the script from the tutor #5 section in JavaScript Code and make it your own with a bit of hand tuning. Be sure to include the style rules for .scroll and .newsbox that are in this document's head section. Then add the following div element where the newsbox is to appear.

<div id="newsbox"><script type="text/javascript">
c=new scrollerObj('c','135','100','200','100',p6,'ffdd00','cccccc',
'3','center')
</script></div>

The parameters represent the boxName, boxHeight, boxWidth, contentHeight, contentWidth, content, boxColor, textColor, speed and initial FloatPosition.

Embedding Audio

To have multimedia, you must have more than a visual component! And that usually means audio. The usual way of getting music to play in all major browsers is with the embed element like:

<embed src="canyon.mid" hidden="true" loop="true" autostart="true">
</embed>

The problem with the embed element (as well as the object element) is that they are not acceptable within the XHTML recommendation and validators will complain about them being invalid. There is a sneaky solution using JavaScript which actually allows a great deal of flexibility to be added to the use of music or other embed and object applications.

The toggle button example from a previous tutorial has already shown how the content of a div element can be rewritten dynamically. Well the content could include the embed element! By providing an empty div element in the body and an onLoad function to place the embedded sound object, you now have a document that verifies but still plays background.

function turnon(entry) {
musicFile="canyon.mid";text='<embed src="'+musicFile;
text+='" hidden="true" loop="true" autostart="true">';
document.getElementById(entry).innerHTML=text;
}
...
<body onLoad="turnon('musicdiv');">
...
<div id="musicdiv"></div>

Couple this with the toggle button and a second function that turns the audio off (ie autostart="false") and you give the user control of his speakers. Hint: Start with the music off! Use a set of radio buttons to control which tune is played. This is done by making the src="x" attribute a variable which is set by the radio controls. Don't forget to make one of them an OFF button. Add a file selection control so that the user can select any file on the site (or drive if the program is put on a cd).

7 - Cookies

Cookies are used for information storage that can be read either by the same page on a later viewing, other HTML/JavaScript pages on the same site or by servers. Cookies are stored in a file named cookies.txt in Netscape or in the folder \System\Cookies in MSIE. Some of the many uses of cookies are: tracking visits by a specific client, remembering the last page viewed,shopping basket storage, notifying a user of any recent change to site, user profiling: login, view method, preferences, passing information from one document to another and maintaining state information longer than a session

TOPICS

Required Cookie Ingredients

Certain ingredients are required for the correct baking of a cookie from scratch. The following sections of this page provide functions that set reasonable defaults for most applications. But these ingredients can be added as baking parameters if needed by a specialized application.

Name
Used as the identifier as many cookies could be used for different purposes by the same site. Names can't contain semicolon, comma or space. Well behaved calls will verify that the name does not have any of these characters.
Value
The data that is to be saved.
Expires
Last date that the 'value' is valid for. Format is DD-Mon-YY HH:MM:SS UTC
NOTE: MSIE expires after the date, gecko expires on the date. The data is not necessarily removed from the file but it is inaccessable using JavaScript.
Path
Restricts cookie to specific level of a site. Defaults to the level that made the cookie.
Domain
Site specification to restrict access to cookies. Defaults to open.
Secure
If set to 'true', the cookie responds only to a 'secure' server. Defaults to 'false'

Baking a Cookie

bakeCookie is a generic function for creating cookies. It also illustrates how you can have a variable number of parameters for a JavaScript function. The mandatory parameters are the variable name and the value to be stored. Multiple values can be stored in the same cookie by calling the bakeCookie function several times but using a different variable name as the first parameter. This function is written so that optional parameters default to useful values, and the order is predefined as given above in cookie ingredients (ie. expiry [defaults to never], path, domain, security). MSIE stores cookies in \windows\cookies and gecko browsers store cookies in a cookies.txt file (useful debugging note!). Netscape and mozilla share the cookie.txt file in the mozilla profile.

function bakeCookie(name,value) {
   argv=arguments;
   argc=arguments.length;
   expires=(argc>2) ? argv[2] : null;
   path=(argc>3) ? argv[3] : null;
   domain=(argc>4) ? argv[4] : null;
   secure=(argc>5) ? argv[5] : false;
   document.cookie=name+"="+escape(value) +
     ((expires === null) ? "" : ("; expires="+expires.toUTCString())) +
     ((path === null) ? "" : ("; path="+path)) +
     ((domain === null) ? "" : ("; domain="+domain)) +
     ((secure === true) ? "; secure" : "");
}

Eating a Cookie

eatCookie is a generic function that recovers stored cookie information. The only required parameter is the variable name. The returned value is a string value or null if nothing was stored in that variable.

function eatCookie(name) {
   arg=name+"=";
   alen=arg.length;
   clen=document.cookie.length;
   i=0;
   while (i<clen) {
      j=i+alen;
      if (document.cookie.substring(i,j) == arg) {
          return eatCookieVal(j);
          }
      i=document.cookie.indexOf(" ",i) + 1;
      if (i === 0) {break;}
   }
}
function eatCookieVal(offset) {
   endstr=document.cookie.indexOf(";",offset);
   if (endstr == -1) {endstr=document.cookie.length;}
   return unescape(document.cookie.substring(offset,endstr));
}

Tossing a Cookie

tossCookie is a generic function that removes an old cookie value from further use. It relies on the fact that each cookie has an expiry date. By setting that date to one prior to today, the cookie will be eliminated automatically.

function tossCookie(name) {
   threeDays=3*24*60*60*1000; //in millisecounds
   expDate=new Date();
   expDate.setTime(expDate.getTime()-threeDays);
   document.cookie=name+'=foobar; expires='+expDate.toGMTString();
}

Example #1 - Saving a User Preference

A common use of cookies is saving user preferences for reuse. Our example will use the newColor selector method modified with a line that bakes a new cookie when the background color is changed. Cookies are used to save the color choice. Returning to the page will reset the color to the last setting selected.

              <fieldset>
              <legend>Background</legend>
              





 </fieldset>
STEP 1: Create an interface such as a form for the color entry. Dynamic Form Examples has several methods that may be used. Make sure that the element that displays the color has an id attribute.

STEP 2: Add a script element to the document body and initialize a global value for the cookie's expiry date.

   expDate=new Date();
   ThreeDays=3*24*60*60*1000; //in millisec
   expDate.setTime(exp.getTime()-ThreeDays);

STEP 3: Copy the bakeCookie(), eatCookie(), tossCookie() and newColor2() functions into the script.

   bakeCookie("colorSet",entry,expDate);
   styleObj=document.getElementById(areaID).style;
   styleObj.background=entry;}

STEP 4: Set up init function that eats the old cookie if it is there and calls the color setting function. Call this function with the onload attribute in the body element.

function initCookie(areaID) { // points at color element
   colorSet=null;
   if (!(colorSet=eatCookie("colorSet"))) {colorSet=null;}
   if (colorSet !== null) {newColor2(colorSet,areaID);}
}

STEP 5: Add a call from the color setting function to bake a new cookie with any updates.

Example #2 - Saving a User 'Agreement'

User agreement to site policy statements are common on corporate sites offering copyright material or corporate property on-line. To perform this kind of customer recording you would first display 'the terms of use' message with a checkbox or radio button for acknowledgement of reading. Some do not display checkbox/button until scrolling has been done, indicating a chance of 'terms' being read. At the acknowledgement, a cookie is created so that the next visit does not show the agreement. Some sites also create a mailto message at this point to record the visitors agreement (ie. documentation for later legal use). Any page that requires the agreement would check for the cookie's existence and if not there redirect the user to the agreement page.

Step 1: Create a form with the 'terms' and buttons for acknowledgement.

Step 2: When 'Agree' button is checked bake a cookie for it.

Step 3: If needed, submit the form as a mailto or to a mail server.

Step 4: Add an eat cookie and if not found then redirect routine to each page on site that requires agreement acknowledgement.

8 - Working With Forms

User interaction is commonly accomplished through the use of HTML forms and their input controls. Interaction involves acquiring data and then performing some task based on that information. The results can be presented either with dialogs or more commonly by using other input control elements.

As this tutorial relies heavily on their use, you should already be able to create HTML forms and include any input control in a functional layout. You may wish to refer to my Quick Forms for a fast review of your skills or to my Creating Forms page for more complete details.

 Topics

Accessing Form and Control Objects

Forms can be designed to permit controlled (ie. prevalidated) data (eg. radio buttons, check boxes and select lists) or free format data such as text entry boxes and file uploads using input controls. These forms can be checked before submission using the techniques that are discussed in form validation. The controls can also be used for input and output in client-side utilities that are never submitted to an external server. Note that there are two techniques for referencing an input control object for reading or modifying it.

The DOM level 1 element access method (new way) requires NO form element and uses the format:

document.getElementById('control_id')

Use the element method [PREFERRED WAY] when:

  • XHTML specification is used!
  • the input controls are strictly for client-side use with no form submission and no support for Netscape 4 is offered. Removal of the form element helps suppress false submissions in some browsers. See the validation by entry topic for another technique that is used when a form is used.

The DOM level 0 form access method (old way) requires a surrounding form element and uses these formats:

document.form_name.control_name
document.forms['fname'].elements['ename']
document.forms[fidx].elements[eidx]

Use the form method (old way) when any of the following conditions apply:

  • many elements have to be passed to a single function.
  • multiple field validations are to be done with arrays.
  • a form is required for CGI submission purposes.
  • Netscape 4 has to be supported.

Note: Gecko engine based browsers (eg FireFox) do not treat form objects in the same manner as MSIE and Opera. To them, forms are not globally accessible so either they are passed to the called function as an object or the specific value is passed. MSIE can access a form by using its specific name in the function. If you always pass the form through as a function parameter your routines will work in both sets of browsers! And it is better programming practice too!

Accessing Control Contents

Most controls can have their contents accessed or updated through the value property of the control's object. When used on the right side of an (equal's) assignment, the current value of the object is read. When used on the left side of an assignment, the object is updated. Exceptions to this general rule are:

Check Box
Use the checked property. The value is either true or false.
Radio Buttons
Use the checked property. The value is either true or false. Since all radio buttons in a group have the same name, the individual object is accessed via an index. Indexes are numbers in square brackets such as radioButton[0] etc. (NOTE: index numbering starts at zero with the first reference in the HTML document.)
Select List
The selectedIndex property holds the position in the list of the first currently selected item. A value of -1 indicates no selection has been made or it has been deselected.
form_name.control_name[form_name.control_name.selectedIndex].value reads the value (ie. what is assigned by the value attribute of the current selection.
form_name.control_name[form_name.control_name.selectedIndex].text reads the text (ie. what is contained in the option element) of the current selection.
Note: If multiple selections are allowed, you must cycle through the entire select control, testing the selected property of each item in the options array.
Note2: If you are trying to support the MSIE browser, use the multiple selection method, even if only one selection is allowed.
File
The file control uses FileUpload.value (note that the Object name is not the same as the type value - this is done to deliberately confuse programmers!)

Note: Although radio buttons are the most commonly indexed input control, any control can be set up for indexing by reusing (overloading) its name attribute in HTML. One appropriate use would be for gathering a column of numbers (perhaps scores or unit prices) in an array within a loop and doing totals or averages. The arrays always start at '0' and are accessed similar to the radio control example above.

Simple Text Control Example

Input text controls (single line) and textarea controls (multiple line) are commonly used to output the results of processing the input data. The simplest cases are explained in my QuickForms tutorial. The following example places the results of the system object Date method toString() into an input area. The input box is made readonly to prevent typing to it.

Since this is a simple action it can be done within the event call itself such as:

<input class="go130" type="button" value="Display date &amp; time"
   onclick="now=new Date();document.getElementById('t').value=now.toString();"/>
<input name="t" type="text" readonly="readonly"/>

However a more structured and easier to read approach is to separate the programming action into its own function that can be removed to the head section of the document (or even to a separate file). The activating event passes one control object to the called function so that it can be updated.

function showDate(thisObj){
/* create a Date object using the system clock */
now=new Date();
/* convert contents to string and place in control */
document.getElementById(thisObj).value=now.toString();
}
................
<input type="button" value="Display date &amp; time"
   onclick="showDate('t');"/>
<input id="t" type="text" readonly="readonly"/>

Radio Button Confirmation Example

There are times when you may need to confirm that something has been read or an agreement made before access is given to a page. This can be done easily with a radio button control. Even more design elements (legend and fieldset) are included in this example. Note their effect.

Licence Agreement

Here is the button setup and event call. For the complete form read the source file.

<label for="y">I have read and accept this agreement</label>
<input id="y" name="rbc" type="radio"/>
<label for="y">Yes</label>
<input id="n" name="rbc" type="radio" checked="checked"/>
<label for="n">No</label>
<input name="act" type="button" value="View Utilities"
 onclick="doYes(document.getElementById('y').checked);"/>

And here is the JavaScript function. The === is important!

function doYes(entry){
if(entry===true){
    top.location.href="utility.htm";
    }else{
    alert("Sorry - You must sign agreement to access utilities");
    }
}

Note: In this example I chose to pass only a simple data value rather than a control or complete form. It was sufficient for performing a test. However if feedback to a form control is needed, then the form or at least the control must be passed. Some programmers choose to always pass the form for consistency.

If you want this agreement to be remembered so that it doesn't have to be repeated, you will need to bake a cookie as described in the Cookies tutorial. If you need to log that an agreement was made, you will need to do a mailto submission as outlined in the Quick Forms tutorial. If you need security (ie. a concealed jump address) FlashPeak offers CryptHTML for encoding html and JavaScript docu

 9 Dynamic Form Examples

Dynamic HTML (DHTML) is a collection of strategies (scripting, CSS and DOM) that lets you create web pages that are more interactive, responsive and animated than ever before. DOM and DHTML explained the DOM level 1 model as well as ways to really liven up your site. This tutorial emphasizes working with forms for interaction and dynamically modifying web pages. You should already be familiar with HTML forms (refer to Quick Forms) and JavaScripting before starting this tutorial.

TOPICS

Dynamic Select Lists


DOM allows creating new option elements from within scripts using the Option(caption[,value]) constructor which creates a new option instance which is inserted in the appropriate select control's options[] array. history.go[0]; can be used to update the window after element insertion.

Note: Other control objects do not have instance constructors. They must be created with the more rudimentary document tree traversal / node creation technique offered by the DOM model.

This example illustrates passing multiple selected items from a select list to another select control. The onclick event passes only the control element ids. The add2list() function finds the controls and loops through the input list's options array looking for selected items. The function also prevents duplicate entries by maintaining a global picked array. The selected items are added to the output list using the Option objectconstructor. The form construction is:

<div class="c"><table class="n"><tr>
<th class="n"><select id="list1" size="6" style="width:190px" multiple="multiple">
<option>1 - Basic Display</option>
<option>2 - Objects and Events</option>
... etc ...
</select></th><th class="n">
<input class="go" type="button" value=" --> "
       onclick="add2list('list1','list2');"><br/>
<input class="go" type="button" value=" --> "
       onclick="add2list('list1','list2');"/></th>
<th class="n"><select id="list2" size="6" style="width:190px">
<option></option></select></th></tr></div>

Thanks to tim@bpinternetservices.com for the takefromlist() function which removes a previously selected element from the second list.

Background Color Function

The form examples shown on this page all use a common function called newColor to set the desired element's background color. The newColor method accepts X11|SVG named colours, hexadecimal 3 and 6 character formats preceded by a # and rgb format [eg. rgb(50,100,200)] entries. The examples all default to body element (ie no second parameter given).

function newColor(entry,areaID) { // use DOM only, no geezer browsers
if (areaID===null) {areaID="body";} // default to whole body
document.getElementById(areaID).style.background=entry;}

Select List Color Picker

This example shows the use of a selection list to pick a color from the X11|SVG named colors. The onChange event uses the form name explicitly to get a value to feed the newColor function. newColor sniffs for the browser type and changes a style property dynamically.

Background Color from X11|SVG List

The color selection form in HTML

<form action="">
<fieldset><legend>Background Color Selection from X11|SVG List</legend>
<select id="c_sel" size="6"
onChange="selColor('c_sel');">
<option>aliceblue</option>
<option>antiquewhite</option>
...
</select></fieldset></div>

Radio Button Color Selector

This example shows the use of a 'controlled' input to choose from a 'restricted' set of color backgrounds. The onclick event feeds the selected color value to the newColor function.

Background Color Selector
<form id="radio_form" action="" method="get">
<fieldset><legend>Background Color Selector</legend>
<label>Aquamarine:<input name="radCol" type="radio"
onclick="newColor('Aquamarine');"/></label>
<label>Burlywood:<input name="radCol" type="radio"
onclick="newColor('Burlywood');"/></label>
<label>Floralwhite:<input name="radCol" type="radio"
onclick="newColor('Floralwhite');"/></label><br>
<label>Goldenrod:<input name="radCol" type="radio"
onclick="newColor('Goldenrod');"/></label>
<label>Peachpuff:<input name="radCol" type="radio"
onclick="newColor('Peachpuff');"/></label>
<label>White:<input name="radCol" type="radio"
checked="checked" onclick=newColor"('White');"/></label>
</fieldset></form>

Hexadecimal Entry Color Picker

This example lets the user enter a 6 digit hex code and test the color choice before using it on a web page. This example also includes verification that the input was a valid hexcode before using it to prepare the new background color. Validation should always be performed on any free format input. Numeric validation discusses some methods of input validation.

Free Format Color Selector
<form id="formhex" action="" method="get" onsubmit="return false;">
<fieldset><legend>Free Format Color Selector</legend>
<label for="query">Background color (6 hexadigits): </label>
<input id="query" type="text" size="8" maxlength="6">
<input type="button" value="Test!" onclick="ChangeColor('query');"></form>

And the validation script is:

function ChangeColor(id){
entry=document.getElementById(id).value.toUpperCase();
strlen=entry.length; validChar='0123456789ABCDEF';
if(strlen!=6){
  alert("Entry must be EXACTLY 6 characters long");
  return false;
  }
// Check for legal characters in string
for (i=0;i<6;i++ ){
  if(validChar.indexOf(entry.charAt(i))<0){
     alert("Entry must be in RRGGBB hexcode format!");return false;}
  }
if(entry.charAt(0) || "#" ){entry="#"+entry;}
newColor(entry);return true;
}

10 - Form Validation

Data validation routines test for required or invalid strings of numerics or characters. Specific values, a range of accepted values or a pattern of an acceptable format can each be tested. Validation is required in forms and within routines that manipulate data.

The best method of form validation is to choose form controls that restrict value selection to known pretested quantities. Examples of these controls are radio buttons, check boxes and select lists. However there are times when they are not always appropriate. In these cases you can let the user complete the form and then validate it or validate on each individual entry.

TOPICS

Common Validations Needed

There are many types of common validations that you should be ready to do. Most involve freeform controls. These checks include:

  • guaranteeing a minimum (eg. password of 5 or more chars) or maximum length
  • making sure an entry matches a specific word
  • making sure two entries agree (eg. double entry of password)
  • validating a number format or range
  • checking the format for a pattern (eg. does this look like a mail address)
  • checking two or more fields for inconsistent results such as married--no and the name of spouse field filled in.

However do not make any false assumptions in what the entry will be. Assuming that age:14 children:3 is in error may require checking the state address ;-] ;-] Some common validation mistakes seen on entry forms are:

  • Assuming a specific format for telephone numbers. Some numbers require an area code. And some international numbers are NOT 3x3x4 digits long. And of course letters are still valid!
  • Not all addresses are ZIP codes! In fact only one country uses them. There is a large variation in postal codes.
  • Dates have many variations depending on locale. Separate entry boxes for each component (year/month/day) is a safer method of entry.
  • Some select controls omit needed selections (eg. Canadian locations require 10 provinces plus three territories).

Validating Before Form Submission

The onSubmit event can be used to call a function to check all fields that require validation before sending a form. The values to be checked (or perhaps the entire form) are passed as parameters. The validation function must return a true if ready to submit or a false if not ready. It also makes sense to use dialog boxes to indicate the nature of the error. An example of a simple call to a validating function is:

<form id="SurveyForm" action="http://www.flintstone.ca/survey/"
      method="post" onSubmit="return validate(fld1,fld2);"></form>

An alternative method uses a simple button with an onclick event. Either the submit action is suppressed by placing onSubmit="return false;" in the form element or removing the form element altogether!

<form id="foo" action="?" method="post" onSubmit="return false;">
. . .
<input value="Check Form!" onclick="validate(fld1,fld2);"/>
</form>

Validating On A By Entry Basis

Many forms are best validated on a by entry basis. A function to validate the contents of an entry box can be called by the onBlur event. onBlur occurs whenever an element such as an entrybox loses focus. That means the entry is checked when you click on a new entry field or another spot in your window or use the tab key to move off the entry.
NOTE: Read my Bugs Tutorial to see how some browsers can create endless loops when blur and focus events are encountered. Another event that can be used is onChange which only does the validation when you move off the entry box and that entry has changed. The next example brings up an alert dialog if the correct word is not entered.

Input the word STOP in the following entry box:
Then click somewhere outside of the box to test!
<table><tr>
<td>Input the word STOP in the following entry box:<br>
   Then click somewhere outside of the box to test!</td><td>
   <input id="i1" type="text" value="" onclick="return false;"
          onBlur="isit('i1','STOP');return true;">
</td></tr></table>

And here is the JavaScript checking routine. Note that the validation is case sensitive. The onSubmit event in the form element is used to suppress the return key and the onclick event suppresses other key clicks.

function isit(id,expectedval){
   inputval=document.getElementById(id).value;
   if(inputval!=expectedval){alert('You must enter the word '+ expectedval);
      }else{alert('ok');}
   }

Validating On A Keystroke Basis

Sometimes you may want to restrict specific characters from being entered into a control or do some form of on-the-fly reformatting. This requires catching individual keystrokes with one of the keystroke events.as well as character validation. Have you ever been stung by a textbox that let you enter data and then when submitted you were told that only ### characters are allowed, Did you ever wish that the w3.org recommendation had defined a maxlength attribute on a textarea control. This example places a limit on the number of characters allowed in a textarea as well as eliminating unwanted one.

The initCount('txtAreaId','dspAreaId') method must be called in the body onload="" element for each textarea to be controlled. The global variable maxLength sets the character limit. The routine also returns a display of the number of characters remaining! If this display is NOT to be used, use the keyword 'NODISPLAY' instead of an actual element id. Check the tutorial on regular expressions for correct syntax for unwanted characters.

You have 9 characters remaining!

 

maxLength=9; regExInvalidChars = /\W/; //global settings
function initCount(ident,displayId){ // initial display setting
  taObj=document.getElementById(ident);
  if (displayId.toLowerCase()=="nodisplay") {return;} // suppress display
  dispObj=document.getElementById(displayId);
  dispObj.innerHTML=maxLength-taObj.value.length;
}
function taCount(ident,displayId){
  taObj=document.getElementById(ident);
  taLength=taObj.value.length; // look at current length
  if (taLength>maxLength) { // clip characters
    taObj.value = taObj.value.substring(0,maxLength);}
  taLength=taObj.value.length; oldLength=0;
  while (oldLength<taLength) { //validate characters
    tChar=taObj.value.charAt(oldLength);
    if (regExInvalidChars.test(tChar)) {
       alert('Invalid char['+tChar+'] Letters, numbers or hyphens only.');
       tStr = taObj.value; tail = tStr.substring(oldLength+1);
       taObj.value = tStr.substring(0,oldLength) + tail; taLength--;
       } else {oldLength++;}
  }
  if (displayId.toLowerCase()=="nodisplay") {return;} // suppress display
  dispObj=document.getElementById(displayId);
  dispObj.innerHTML=(maxLength-taObj.value.length);
}

Another example of validating on each keystroke is:

document.onkeydown=keyHit:// register key pressed event
upArrow=38:dnArrow=40: // names for important keys
function keyHit(evt){
	thiskey=window.event.keyCode;
	if(thiskey==upArrow){alterSelection(-1);}
	if(thiskey==dnArrow){alterSelection(+1);}
	}

Notice that instead of using an element attribute, the event is registered in JavaScript. The evt object can be tested if you need to restrict keystrokes to specific zones or elements. You can use an alert(thiskey) method to show the specific keyCode. It helps to make a name synonym for any keyCode that is being used such as pound or percent.

Multiple Field Validation

In many situations the same type of validity check has to be repeated over many fields. One simple method is to use the fact that if the name attribute is reused for several similar controls, an array is automatically set up to give unique pointers to each control value.

Note: To convert this form to one that is submitted to a server for script processing change the HTML form element's method to get, the enctype to multipart/form-data and redirect the action to the appropriate URL.

Testing Multiple Fields
Each entry box must be filled in with a single digit, no alpha or punctuation or blanks allowed prior to submission. Note how the focus moves to first blank box but user can refocus if desired.
 
function verify(id) {  // check entries for single digit values only
for (idx=0;idx<99;idx++) { // if any field is blank, set focus to it
   if (!document.getElementById(id+idx)) {return;}
   obj=document.getElementById(id+idx);temp=obj.value;
   if (isNaN(parseInt(temp,10))) {
       alert('Entry must contain exactly one digit!');
       obj.value="";obj.focus();return false;}
   }
return true;}

Validating Numeric Data

Numeric input must also be verified before continuing. JavaScript's built-in function Number() and internal methods (such as isNaN(), parseInt(), parseFloat(), etc.) work well for validating decimal based numbers. However they are incomplete for other radix systems and you will have to gather together your own set of functions to paste into projects.

A simple brute force validator solution is to test each character of the entry string for permitted values. Binary integers are limited to 0's and 1's. Octal numbers can have only the characters from 0 to 7. Hexadecimal codes can contain the digits 0 to 9 and the letters A to F (either upper or lower case) only.

The following is an example of a hexadecimal entry checker. With suitable changes to the characters allowed and perhaps a length control (fixed or maximum) this code can be reused in many validation situations. The steps are:

  1. Make sure there is something to check!
  2. Since uppercase letters are more common, be sure to uppercase the string.
    Or you could include both cases in the character scan.
  3. Finally do a simple character by character check for valid characters.

In this test invalid or null hexadecimal string will display an error message and return a false value. If the whole string passes the check an ok! message is displayed and a true value is returned. Often these validating functions are written without display messages, leaving it up to the calling function. One last variation is to accept a second parameter which represents whether a message is to be displayed.

function isHex(entry){
validChar='0123456789ABCDEF':// characters allowed in hex
strlen=entry.length:         // how long is test string
if(strlen < 1){alert('Enter Something!');return false;}
entry=entry.toUpperCase():   // lowercase characters?
// Now scan string for illegal characters
for (i=0:i<strlen:i++){
    if(validChar.indexOf(entry.charAt(i))<0){
       alert("Entry must be in hexadecimal format!");return false;}
    } // end scanning loop
alert('ok!'):return true;
}
Hexcode String Test

Once you know for sure that a variable is a number, then you can use the Math object methods parseInt() and parseFloat() to make them into the appropriate type if required. Using parseInt() and parseFloat() by themselves may cause unexpected problems as they can truncate some nonnumeric strings and yield a number as an answer (eg. 1st.). isNaN() is a function to test for numbers but it is limited to decimal values only.

11 - String Validation

String validation and manipulation are the basis of many forms and utilities. This page illustrates useful objects, techniques and several working examples.

Brute Force String Validation

Brute force evaluation is programming that takes the simplest approach or uses very crude assumptions. It is easy to get the code in place and most often does the job. Stepwise refinement can then be applied. But the resulting code is not elegant and often quirky. As an example suppose that a field is intended to hold a person's surname and is a mandatory field. The first approach is to check for an empty string. That is a start but surely a person's last name is at least 2 characters long. And only a few punctuation symbols (such as hyphen and apostrophe) are allowed and no digits please!

There are several String object functions and properties that can make your brute force checks easy! You may want to refer to Appendices - Objects for the complete list.

  • entry=entry.toUpperCase() will change any lowercase characters to uppercase. This way you do not have to check for each of ANN, ann, Ann, etc.
  • x=entry.length; will return the length of the string entry.
  • x=entry.indexOf(char) will return the first position of char within the string entry. Returns 0 if not found!
  • x=entry.lastIndexOf(char) will return the last position of char within the string entry. Returns 0 if not found!
  • x=entry.indexOf(char,start) will return the first position of char within the string entry starting at position start. Returns 0 if not found!
  • x=entry.charAt(p) will return the character at the specific position p. Combined with a loop such as for (p=1;p<entry.length;p++){BLOCK} which scans the entire string, you can watch for problem characters.
  • x=parseInt(entry,10) will return an INTEGER number from the string. BEWARE: truncation can occur!
  • x=parseFloat(entry) will return an DECIMAL number from the string. BEWARE: truncation can occur!

Two specific examples of brute force validation are e-mail addresses and postal codes. Check the forms projects page for some techniques.

Validation with regular expressions is more elegant and much easier than the brute force technique, once you master the syntax. If your scripts rely heavily on input validation, it is well worth the effort to learn how to use them.

Multiple Valid Answers

In some situations there are alternatives that are equally correct. The validation function would then scan an array of answers looking for a match. Any match returns a positive flag. For example look in the source code for validmany().

Name one color in the American flag:

Text Analysis

Word count analysis require breaking up (ie. parsing) the source text into words (ie. tokens) that are terminated (ie. delimited) with spaces or punctuation. Fortunately JavaScript has the built-in string method split() which breaks a string into array items based on a delimiter symbol. The CountWords function in the head section of this document shows how the text is first prepared by adding leading/lagging spaces and changing other white space into plain space by using the string method replace(). Then the split() method with space as its delimiter is used to place all the 'words' into an array called splitString. The length of this array is the number of words in the text.

Word Count Utility

NOTE: You must view the source code for the CountWords() function!

Concordance is the counting of each occurrence of each word and providing the results in a table fashion either sorted by alpha or sorted by most frequently used. This type of utility quickly leads to a spellchecker.

Text Formatting

Text formatting can be as simple as changing case or initializing all words or first words in sentence. More complex forms of formatting could be adding/removing database tagging or removing obsolete HTML elements. Text justification and decimal roundoff are examples of formatting routines often needed for output display.

Right justification is a simple matter of padding a string from the left hand side. Here is a short funcion to do it.

function rjust(st,siz) {
t = siz - st.length;
if (t>0) {st = spaces(t) + st;}
return st;}
function spaces(len) {
s = " ";
for (i=0;i<len;i++) {s = s + " ";}
return s;}

Decimal roundoff is another common need. This is done by moving the decimal to where needed, clipping with the round method, and restoring the number.

function roundoff(x,y) {
scale=Math.pow(10,y);return Math.round(x * scale)/scale;}

Order Forms

Order forms normally include extended prices, totals, taxes and handling charges. Note: Refer to form design for some basics. A start on a simple order form is given and you are encouraged to 'flesh it out' with:

  • some simple math for first line. UGH!
  • automatically update the line after changes.
  • assume that any null entry implies null display.
  • add totaling operation.
  • add tax line including round off to pennies.
  • complete with grand total line.

Refer back to multiple field validations for the technique for handling many line items.

Sample Order Form
Item Description Quantity Unit Cost Extension

Major project extensions: This order form could be turned into a major project by adding shipping and handling charges and checkboxes for non-taxable items. Or perhaps select boxes for product that when chosen, fill in the unit cost field (preventing the need for some error checks. A long term project could contain item descriptions (perhaps even images) with checkboxes. A checked box places the item on the order form. This may include the quantity level which is echoed to the form.

Health Checkup Form Example

Body Mass Index Calculator

A Body Mass Index of more than 25 indicates that you are overweight. A BMI factor of 30 or more indicates obesity. Being overweight can cause many health problems such as heart disease, strokes and diabetes. And if you should live long enough there is an increased chance of Alzheimer's. Just a word to the wise..

12 - Debugging

Bugs or programming errors occur often when learning a new programming language or when developing a new routine or utility. Ripped or cut/pasted scripts are often filled with latent bugs as well. This tutorial will hopefully give you some successful strategies for squashing any bugs that occur in your JavaScript writings or trying to get ripped scripts to work correctly.

TOPICS

Types of Errors

There are several types of error, each with its own method of detection and repair. The basic types of error are:

Browser Implementation Errors
These are quirks that occur in one browser but not others. See Browser Issues for more details. Test your code on all anticipated client browsers!
Syntax Errors
These are errors in grammar and punctuation such as mismatched quotes or missed commas. These errors are caught quickly if you have the browser's built-in error detector in display mode or run the script through JS Lint.
Runtime Errors
These errors only show up as the script is executed. Common examples are calling a function that hasn't been declared (typing error or case-sensitivity issue) or division by zero. Although JavaScript is typeless, many built in objects expect and/or return specific types (eg. style.left needs string type).
Logic Errors
These are basic errors in the programmer's algorithms or procedural errors. Diagnosis only comes when incorrect results occur and solution requires mapping out the flow for test cases. The wrong scoping of a variable is an example of this kind of error.
Incorrect Operator Precedence Errors
These are basic mathematical grouping errors. The best way to avoid them is with brackets to force the order that you want operations to occur explicitly.

Common Errors

Errors can take some of the fun out of programming but experience will gradually eliminate (or at least make you more watchful for) certain commonly made ones. Some of the most common errors are:

  • Spelling and typo errors. Remember case sensitivity and avoid hard to find lookalikes (1 and l, 0 and O, etc.).
  • Not matching brackets or quotes correctly.
  • Wrong type of bracket. Each has its own use.
  • Not using the escaper backslash when required.
  • The type of the variable may be critical in spite of being a typeless language.
  • The scope of a variable can affect its current value.

Testing and Debugging

Microsoft Internet Explorer has a script error display but it must be enabled by selecting Tools -- Internet Options -- Advanced. Uncheck the box labeled 'disable script debugging' and check the box that says 'display a notice about every script error'. Note that the line number given in any error message is only approximately correct ;-[

FireFox and Netscape 7 browsers has a script error display that is accessible from Tools Menu -- Errors Console. Firefox add-on FireBug is an extremely useful debugging tool for script and CSS problems.

Previous tutorials have shown how to use the alert window to provide feedback to the user. This same technique can be used by a JavaScript programmer to set breakpoints (ie pauses) and watch the value of variables within the code. Don't forget to use the typeof() operator to check the type of the variable. And sometimes it is more convenient to use window.status to display variable contents without pausing the program.

At times you may want to analyze a list of values. You can open a new window and use the write() or writeln() methods. This is equivalent to the use of print or printf statements in other languages.

The Venkman tutorial is a comprehensive document for learning how to use this important debugging tool.

Using the JSlint Validator

JSlint is an on-line validator that is very easy to use. Simply cut and paste your script into the text entry zone and press the JSlint button. Any error will generate a simple text message and a line number reference. This is an excellent way of getting the lint out of the wash ;-]

JSlint enforces a style that is tighter than what most browsers need but which detects many common mistakes that programmers make. Some of the guidelines are as follows:

  • jslint expects that every statement be followed by ; except for for, function, if, switch, try, and while.
  • jslint does not expect to see unnecessary semicolons or the empty statement.
  • jslint does not expect to see an identifier, a string, a number, or a suffix operator such as ) ] ++ -- at the end of a line.
  • jslint expects that if and for statements will be made with blocks {that is, with statements enclosed in braces}.
  • jslint expects blocks with function, if, switch, while, for, do, and try statements and nowhere else.
  • jslint expects that a var will be declared only once, and that it will be declared before it is used.

Browser Issues

In the nineties, browsers developed at a fast pace and without standards. This led to proprietary ways of doing things and the need for sniffing to see what browser was being used. But in today's world there is a known recommendation for both script [ECMA] and DOM [w3.org]. Unfortunately some recommendations are vague and consequently are implemented differently. Also texts and on-line material continue to use legacy methods which no longer work in the modern browsers. The next few subtopics are a guide as to what to beware of in texts, tutorials and ripped scripts. The best way to avoid problems is to stick with the ECMA/w3.org recommendations!

DOM Level 0 Objects

The original document object had properties that could be read using script and some could also be set. The window.screen object also provided useful readable properties. Refer to client objects for specific properties. DOM level 0 has been superceded by DOM level 1. Some examples of DOM level 1 access that dhould be replaced (often by CSS) are:

textColor = document.fgcolor;
document.bgColor = 'thistle';
colors = screen.colorDepth; // note windows. omitted as redundant!
document.myform.outbox.value = xyz; // accessing form controls 

Window dimensions and cursor locations continue to be implemented differently in mozilla and msie browsers.

component mozilla microsoft
window dimension innerHeight document.documentElement.clientHeight
cursor location event.pageX window.event.clientX

Microsoft Internet Explorer

MSIE has properties in addition to those in the DOM model. But it is better to find these and replace with w3.org recommendation coding. For example both pixelTop and pixelLeft should be replaced by top and left as in the following:

where=styleObj.pixelLeft;  //MSIE specific
where=parseInt(styleObj.left,10); // makes integer count in pixels
. . .
styleObj.pixelLeft=where;  // MSIE specific
styleObj.left=where+'px' // guarantees measured in pixels

The MSIE also has extra objects such as document.all. Replace it with the recommended DOM construct as in the following block:

x=document.all.ident.value;  // MSIE specific
x=document.getElementById('ident').value; // DOM way

An example of a vague recommendation in DOM that causes a problem in MSIE is the sequence of actions when both focus and blur (anti-focus) occur at the same time. Here is a fragment that tries to insure that a field is not empty as soon as you move to the next field. Unfortunately, in MSIE it leads to an endless loop.

<script type="text/javascript">
function requiredString (control,label) {
if (control.value.length == 0)
   {alert("you need to enter a string for "+label);control.focus();}
}</script>
. . .
<input name="Control1" onBlur="requiredString(this,'Label1');">
<input name="Control2" onBlur="requiredString(this,'Label2');">

For some reason MSIE does not like smart forms to be nested in definition lists even though it is a valid html construct. This can result in SELECT box text becoming inaccessible.

JavaScript variable names that are the same as html ids can cause error messages within MSIE. This is an undocumented enhancement in MicroSpeak. ;-] ;-]

MSIE has filters and transitions which look slick but only in MSIE. Avoid the use of any proprietary feature! It is just not worth the maintenance hassle.

Browser Sniffing

The document object model (DOM) is a convenient way of understanding how to access html elements. Unfortunately the major browser makers have chosen to implement some DOM objects differently. And older browsers used a concept called layers to achieve many of the effects now done with the DOM model. Thus there are compatibility problems that must be overcome either by programming branches within a script, offering different pages depending on browsers, defensive programming, warning users of possible conflicts, or benign neglect (playing the percentages that one browser has over 90 percent of the users). It is important to realize that there is an issue! Decide how you will deal with these differences. And know your clients, their browsers, and their ability to upgrade to newer, better ones! Browser sniffing is commonly used:

  • to invoke either DOM or layers depending on the browser's age
  • to program around various vendor interpretations of what the style object should be
  • to avoid problems with tags that certain browsers do not handle well
  • to provide an alternate stylesheet for a specific browser

Sniffers can be designed to either return a single value denoting the appropriate browser and version or to set global variables which flag capabilities such as DOMable, layered, etc.

The best strategy allows for maintainability and documentation by identifying the object properties that are different and building a JavaScript module of functions to deal with those variations. This isolates the selection of processing techniques to one area of your script. Further scripts allow reuse of these functions and if a newer browser requires sniffer tweaking, it is only needed in one file.

The first example identifies a browser as a non-dom model and then transfers to another page. This method can be used to skip a page (eg a fancy splash screen) entirely or transfer to one that is layered.

var dom=document.getElementById; //browser uses DOM ??
if (dom==0){top.location.href="http://www.xyz.com/nextpage.htm";}

My favorite technique is to redirect users of older versions to available upgrade sites (not subtle but many need this type of HINT).

/* shield page from geezer browsers -- try to get them to upgrade */
if (document.layers){top.location.href="http://www.mozilla.com";}
if (document.all && !document.getElementById){ //oops - MSIE v5
   top.location.href="http://www.microsoft.com/windows/ie/";}

A variation on this theme is to check for layer users (eg. Netscape 4) or MSIE specific browsers and then set variables to avoid troubles.

if (document.layers) {ns=1} else {ns=0}
if (document.all) {ie=1} else {ie=0}

An older strategy is to rely on the navigator object that is available even in the original browsers. In many cases identifying the browser by name and version is sufficient. But BEWARE! Many browsers have the capabilities of identifying as another browser (aka spoofing).

/* Sniffer uses navigator object - archaic */
ie=0;ns=0;gecko=0;opera=0;
agent=navigator.userAgent;agent=agent.toLowerCase();
browser=navigator.appName;browser=browser.charAt(0);
version=parseInt(navigator.appVersion,10);
if (agent.indexOf('gecko') != -1) {gecko=1;}
if (agent.indexOf('opera') != -1) {opera=1;}
if (browser=="N" && version < 5) {ns=1;} else {ie=1;}

Important Note: The last example is provided only for historical purposes and to indicate what you should avoid! Modern techniques use object availability identification for sniffing.

13 - Regular Expressions

Regular expressions are a shorthand notation for matching, extracting, sorting or formatting strings. Their most common use is to reduce the amount of work while validating data input. This tutorial covers the special syntax used, how one can use a regular expression in form validation, and several useful examples.

TOPICS

Escaper Characters

Escaper characters are used to literally represent characters that normally have a special meaning in regular expressions (ie. meta-characters). They are also used to represent non-typable characters.

Escaper Literal Character
\f Formfeed
\n Newline
\r Carriage return
\t Tab
\v Vertical Tab
 
Escaper Literal Character
\xnn ASCII char defined by hex code nn
\onn ASCII char defined by octal code nn
\unnnn Unicode char defined by sequence nnnn
\cX Control char defined by X
 

Character Classes

Special characters are used as a shorthand, to abbreviate the amount of typing and specifying required when creating a regular expression. For example \w includes all letters, numbers and the underscore character.

Character Matches
. Any character except newline
\d Any digit 0-9
\D Any non-digit
\s Any whitespace character
\S Any single non-whitespace
\w Any letter, number or underscore
\W Any char except letter, number
or underscore
Character Matches
[abcde] Any character in the enclosed set
[^abcde] Any character not in the enclosed set
[a-e] Any character in the enclosed range
() Grouping that is stored (back referenced) for later use ($1, $2 etc.)
x|y Either x or y (ie. logical OR)

 

Boundary Matches and Greedy Quantifiers

Character Matches
^ Beginning of string
$ End of string
\b Word boundary
\B Non-word boundary
Character Matches Previous Char
* Zero or more times
+ One or more times
? Zero or one time
{n} Exactly n occurrences
{n,} At least n occurrences
{n,m} Between n and m occurrences

Regular Expression Modifiers

Regular expression modifiers have been added to the syntax to handle global modification of the entire expression. They are placed at the end of the expression outside the quoting brackets as in /[abc]+/i

Character Modification
g global search for all matches
i insensitive case searches
m multiple line searches

Testing Regular Expressions

Several on-line sites let you test a regular expression before using it in your own scripts. A good one to use is provided by Locher.

Using Regular Expressions in Scripts

To use a regular expression for validating an entry in JavaScript, first set up a variable that contains the expression.
Note: Forward slashes are used to quote a regular expression while ' and " are used to quote a string expression.

re = /whatever/

Then apply the regular expression test method on the string to be tested.

if (re.test(entryValue)) {return true;}

To use a regular expression to extract a matching string, first set up a regular expression variable as above. Next use the regular expression exec method on the string. Any match is returned and null indicates no match.

var ar = re.exec(var_string);

To use a regular expression for modifying a string in JavaScript first set up a regular expression variable as above. Next use the string replace method. Note that you can use back references if required.

var x = y.replace(re,"$1");

Example - Canadian Postal Codes

Canadian postal codes alternate between letter and number such as L0S 1E0. Some choose not to put in the space. And not every letter is used as the first letter which designates region. The regions are (from east to west, then north): A,B,C,E,G,H,J,K,L,M,N,P,R,S,T,V,X,Y. A 'first version' regular expression for Canadian postal codes is:

/^([a-z]\d){3}$/i

This expression makes sure that there is exactly 3 {3} groups of a letter [a-z] followed by a digit \d. The i suffix indicates insensitivity (ie capitals allowed). The ^ and $ guarantee that no other data is provided. However this easy to understand expression does not allow for an optional space after the third character or a restricted subset on the first letter. It also doesn't allow for leading/trailing whitespace. The solution is to explicitly do the repeating but place a (/s)? to check for zero or one space after the third character and to reduce the matches on the first letter to the specific regional characters.

/^\s*[a-ceghj-npr-tvxy]\d[a-z](\s)?\d[a-z]\d\s*$/i

Example - URLs and Files

Often validation of an URL or filename requires a specific extension. One regular expression that will catch all filenames (and more!) is:

/^\S+\.(gif|jpg|jpeg|png)$/

The above expression will match only image files that are Web standard. The expression is not foolproof as it permits subfolders with null names such as a//b.gif and specs like a:/b:/c.gif

Example - E-mail Addresses

E-mail addresses are of the form xxx@yyy where xxx is the specific mailbox (and can contain underscores and periods) and yyy is the domain which can contain a series of suffixes such as .com.uk. One regular expression that matches 99.99% of valid entries is:

/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/

This is a very complex expression and deserves explanation. All regular expressions start and end with forward slashes to differentiate them from ordinary string expressions. Most regular expressions start matches at the first character ^ and end at the last $.

Now we try to match the mailbox name which can include periods and dashes \w+ states one or more alphanumeric must be at the start of the name. ([\.-]?\w+)* allows periods or dashes to be included in the mailbox name with the trailing \w+ ensuring that those characters can not finish the name. The @ is the mandatory separator.

The domain name can have several .xx or .xyz suffixes such as .com.uk. Once again \w+ ensures that domain starts with an alphanumeric and ([\.-]?\w+)* allows for the dashes and periods. Finally (\.\w{2,3})+ ensures that there is at least one suffix of between 2 and 3 characters preceded by a period.

Note: This is not a completely foolproof validation as it does not account for new domain names of 4 or more characters. Also not all two and three letter combinations are legitimate domains!

14 - User-Defined Objects

Larger projects require the use of many specialized objects of a similar type. In modern languages this is normally done with user-defined objects. This tutorial shows you how to create your own specialized user-defined objects and explains the issues of constructors, prototypes and inheritance. This tutorial also describes JSON, a cross language data interchange format. Note: This page assumes familiarity with basic Object Oriented Language principles!

TOPICS

Object Constructors

Object constructors can be thought of as templates for making objects. As a simple example, rectangles contain several basic properties (aka variables). A simple template is:

// define a constructor with properties
function Rectangle(w,h) {
   this.width = w;
   this.height = h;
   }

Note that Rectangle has its initial letter capitalized. This indicates that it is a constructor function (similar to a class in Java). The keyword this refers to the current object that called the constructor function. It identifies constructor objects and is not normally used otherwise.

Defining Methods in Constructors

Methods may also be added to constructors. However they must be defined first. The names used in this definition are not important but one convention is to prepend the method name with constructor name and an underscore. It is also good pratice to keep the defining methods and the constructor that uses them near each other (maybe using comments to help).

// define some methods to be included in Rectangle object
function Rectangle_area() {return this.width * this.height;}
function Rectangle_perimeter() {return 2 * (this.width+this.height);}
function Rectangle_enlarge() {this.width *= 2; this.height *= 2;}

// define Rectangle's property display method
function Rectangle_showObj() {
   document.writeln('Width is '+this.width+'<br>');
   document.writeln('Height is '+this.height+'<br>');
   document.writeln('Area is '+this.area()+'<br>');
   document.writeln('Perimeter is '+this.perimeter()+'<br>');
   }

// define constructor with properties
function Rectangle(w,h) {
   this.width = w;
   this.height = h;
   this.area = Rectangle_area; // Note: parameter brackets are not used
   this.perimeter = Rectangle_perimeter;
   this.enlarge = Rectangle_enlarge;
   this.showObj = Rectangle_showObj;
   }

// test by creating and displaying an instance of the Rectangle object
myRect = new Rectangle(5,6);
myRect.showObj();
myRect.enlarge();
myRect.showObj();

This works but is very inefficient. Each instance of a new Rectangle object would contain all of the code for each method such as computing area and perimeter. The prototype based inheritance section illustrates a much better way of constructing objects.

Strictly Typed Properties

You can provide strict type checking inside an object by using typeof and the watch() method as in:

function Example_setWith(idName) {
   this.a = document.getElementById(idName).value;
}
function Example() {
   this.a = 1;
   this.watch("a", function(property, oldval, newval) {
      if(typeof(oldval) != typeof(newval)) {
         alert("Invalid Type Assignment. Aborting...");
         return(oldval);
      } else {
         return(newval);
      }
   });
   this.setWith = Example_setWith;
}
var ex = new Example();

Caution: The watch() method is not available in MSIE browsers.

Function Constructor Methods

Function constructor methods allow dynamic compilation of a function. An example for the area and perimeter functions used above is:

Rectangle_area = new Function("return this.width * this.height;")
Rectangle_perimeter = new Function("return 2 * (this.width+this.height);")

Note that Function is capitalized (ie. an object) and uses round (ie. method) brackets.

Function literals can also be used to define a function such as:

Rectangle_area = function{return this.width * this.height;};
Rectangle_perimeter = function{return 2 * (this.width + this.height);};

Note that the function is unnamed on the right hand side.

Prototype Based Inheritance

Javascript is different from the more commonly used object oriented languages such as C++ and Java in that it uses prototypes instead of classes for inheritance.

Prototypes are special template objects whose properties and methods are inherited (ie pointed at, not copied to by objects created by them. This allows method code to be reused rather than copied. It also can be used to set a property to a constant value. If many objects have the same default value for a specific property but with a few exceptions, the prototype can set the default and an individual instance override the setting. A sample of a prototype approach to the Rectangle object is:

// define a couple of methods to be included in Rectangle object
function Rectangle_area() {return this.width * this.height;}
function Rectangle_perimeter() {return 2 * (this.width + this.height);}
function Rectangle_enlarge() {this.width *= 2; this.height *= 2;}

// define Rectangle's property display method
function Rectangle_showObj() {
   document.writeln('Shape is '+this.shape+'<br>');
   document.writeln('Width is '+this.width+'<br>');
   document.writeln('Height is '+this.height+'<br>');
   document.writeln('Area is '+this.area()+'<br>');
   document.writeln('Perimeter is '+this.perimeter()+'<br>');
   }

// define constructor with properties
function Rectangle(w,h) {
   this.width = w;
   this.height = h;
   this.shape = "rectangle" // majority are !!
   }

// create and throw away a prototype object
new Rectangle (0,0);

// define object methods for rectangles
Rectangle.prototype.area = Rectangle_area;
Rectangle.prototype.perimeter = Rectangle_perimeter;
Rectangle.prototype.enlarge = Rectangle_enlarge;
Rectangle.prototype.showObj = Rectangle_showObj;

// test by creating and displaying an instance of the Rectangle object
myRect = new Rectangle(5,6);
myRect.showObj();
myRect.enlarge();
myRect.showObj();

// and a special instance of the Rectangle object that is square
mySquare = new Rectangle(3,3);
mySquare.shape = "Square"
mySquare.showObj();
mySquare.enlarge();
mySquare.showObj();

The prototype object may also be applied to any built-in class to add a new method to it.

Subclasses

Although not often needed subclasses (children) of user defined classes are able to be created by making their prototype objects instances of their superclass (parent). As an example we will extend a Complex object:

//constructor for subclass
function MoreComplex (real, imaginary) {
  this.x = real;
  this.y = imaginary;
}
/*force the prototype to be a Complex (superclass) object
  which has been defined previously in the script */
MoreComplex.prototype = new Complex (0,0);
//now add new method or features to MoreComplex
MoreComplex.prototype.swap = function () {
  var tmp = this.x;
  this.x = this.y;
  this.y = tem;
}

NOTE: This makes the MoreComplex constructor property the same as its superclass. To overcome this the constructor property must be reset explicitly such as:

MoreComplex.prototype.constructor = MoreComplex;

Objects as Associative Arrays

In addition to the dot address method of identification such as object.property, object data can also be represented in array format such as object[property].

One advantage of the array representation is that the array index is a string and can thus itself be manipulated dynamically. For example to catenate all customer address data into a single string:

var addr = "";
for (i=0; i < 4; i++) { addr += customer["address" + i] }

The above example could have been hard coded with the dot address method but it would hve been longer and less elegant. And there are times when the dynamic capability is required. For example if a client query is made for entry of a database stock item and the quantity on hand is to be obtained from the database:

var item_name = get_item_name(item); // dialog with user, dynamic answer
var quantity = database[item];
show_info(item, quantity); // display the results

And because objects can be expressed as associative arrays the powerful for/in construct can be used as illustrated in the browser explorer tool. For the above database we could quickly calculate the total inventory count without knowing the names or number of unique items in the database:

var item=""; var names=""; total = 0; // variables initialized
// define a constructor with properties
function Database() {}
// construct the database
database = new Database();
// now populate the database
database.widgets = 6; database.gadgets = 7;
for (item in database) {
    names += item + ": " + database[item] + "\n";
    total += database[item];}
alert(names + "\n--------------\n" + "Total: " + total)

Javascript Object Notation

Javascript Object Notation (JSON) is a cross language data interchange format that has a much simpler syntax than XML. It is based on the constructs objects and arrays which are found in virtually all modern languages. JSON has been implemented on Java, C++, C#, Python and other languages.

© 2007 Faith Solutions. All rights reserved.