Table of contents
- Important guidelines
- Introduction to JavaScript
- Examples
- Adding JavaScript to a page
- Object oriented programming
- Operators
- Variables
- Control structures
- Writing with script
- Writing functions
- Referencing
- Browser inspecific referencing
- Browser specific referencing
- DHTML
- Element contents
- Window size and scrolling
- Event information
- Creating objects
- Creating time delays
- Using cookies
- Security
- Semicolons
- The JavaScript object
- W3C DOM introduction
- DOM nodes and tree
- DOM tables
- DOM CSS
- DOM Style Sheets
- DOM events
- DOM objects and methods
Important guidelines
First let's learn some important stuff. There are lots of browsers out there that cannot support JavaScript. Although browsers generally support more and more with each release, the language itself keeps evolving, and there is already a vast amount of the JavaScript language available for browsers to support. No browser will ever support all of it, and you cannot expect them to.
There are many reasons why people cannot or will not 'upgrade' to your chosen browser. A few are:
- They are at work and they can only use the system default browser.
- They want to view pages more quickly so they use a text only browser.
- They are blind or have poor eyesight so they need a text only browser/reader/Braille reader.
- They realise that the more extra features like JavaScript or VBScript you use, the more you leave yourself open to becoming a target for viruses or vulnerability exploits.
- They don't like the way some sites insist on taking over their control of the browser, opening popup windows, breaking the operation of the back button, preventing the context menu from working, or insisting on making things appear and disappear in a way that causes usability problems.
Whatever their reasons, you should not stop them from using your site. If your site
uses JavaScript for navigation or content, then that navigation and content should be there without JavaScript enabled.
Your JavaScript can extract content from the page, and do whatever it wants with that, but you
should make sure that content is available without the script. If you want to use a script in
way that you cannot simply extract the information from the static page, then you should use
<noscript> to provide an alternative for people that cannot run your script.
There are also many browsers out there that you do not realise exist. I know of well over a hundred different browsers that support JavaScript to varying degrees. If your script uses something that browsers may not support, you should detect if the browser is capable of using it, and then fall back to an accessible alternative if it doesn't.
There is no magic formula for this, but the basic rules are that you should not detect a browser make or version. You will get it wrong, and you will mistakenly detect one browser and think it is another, ending up with you using the wrong code. You will make incorrect assumptions about current and future browsers, and you will cause problems for your users.
This tutorial should help you learn how to correctly detect capabilities, and wherever needed, it will show you how to work out when a browser cannot do what you need, so you can halt your script, or provide an alternative. When there are different ways to do the same thing, and some browsers only support one, while others support another, it will show you how to correctly work out which one to use.
Introduction to JavaScript
JavaScript is a programming language that can be included on web pages to make them more interactive. You can use it to check or modify the contents of forms, change images, open new windows and write dynamic page content. You can even use it with CSS to make DHTML (Dynamic HyperText Markup Language). This allows you to make parts of your web pages appear or disappear or move around on the page. JavaScripts only execute on the page(s) that are on your browser window at any set time. When the user stops viewing that page, any scripts that were running on it are immediately stopped. The only exception is a cookie, which can be used by many pages to pass information between them, even after the pages have been closed.
Before we go any further, let me say; JavaScript has nothing to do with Java. If we are honest, JavaScript, originally nicknamed LiveWire and then LiveScript when it was created by Netscape, should in fact be called ECMAscript as it was renamed when Netscape passed it to the ECMA for standardisation.
JavaScript is a client side, interpreted, object oriented, high level scripting language, while Java is a client side, compiled, object oriented high level language. Now after that mouthful, here's what it means.
- Client side
- Programs are passed to the computer that the browser is on, and that computer runs them. The alternative is server side, where the program is run on the server and only the results are passed to the computer that the browser is on. Examples of this would be PHP, Perl, ASP, JSP etc.
- Interpreted
- The program is passed as source code with all the programming language visible. It is then converted into machine code as it is being used. Compiled languages are converted into machine code first then passed around, so you never get to see the original programming language. Java is actually dual half compiled, meaning it is half compiled (to 'byte code') before it is passed, then executed in a virtual machine which converts it to fully compiled code just before use, in order to execute it on the computer's processor. Interpreted languages are generally less fussy about syntax and if you have made mistakes in a part they never use, the mistake usually will not cause you any problems.
- Scripting
- This is a little harder to define. Scripting languages are often used for performing repetitive tasks. Although they may be complete programming languages, they do not usually go into the depths of complex programs, such as thread and memory management. They may use another program to do the work and simply tell it what to do. They often do not create their own user interfaces, and instead will rely on the other programs to create an interface for them. This is quite accurate for JavaScript. We do not have to tell the browser exactly what to put on the screen for every pixel, we just tell it that we want it to change the document, and it does it. The browser will also take care of the memory management and thread management, leaving JavaScript free to get on with the things it wants to do.
- High level
- Written in words that are as close to english as possible. The contrast would be with assembly code, where each command can be directly translated into machine code.
- Object oriented
- See the section on 'object oriented programming' for details.
How is JavaScript constructed
The basic part of a script is a variable, literal or object. A variable is a word that represents a piece of text, a number, a boolean true or false value or an object. A literal is the actual number or piece of text or boolean value that the variable represents. An object is a collection of variables held together by a parent variable, or a document component.
The next most important part of a script is an operator. Operators assign literal values to variables or say what type of tests to perform.
The next most important part of a script is a control structure. Control structures say what scripts should be run if a test is satisfied.
Functions collect control structures, actions and assignments together and can be told to run those pieces of script as and when necessary.
The most obvious parts of a script are the actions it performs. Some of these are done with operators but most are done using methods. Methods are a special kind of function and may do things like submitting forms, writing pages or displaying messages.
Events can be used to detect actions, usually created by the user, such as moving or clicking the mouse, pressing a key or resetting a form. When triggered, events can be used to run functions.
Lastly and not quite so obvious is referencing. This is about working out what to write to access the contents of objects or even the objects themselves.
As an example, think of the following situation. A person clicks a submit button on a form. When they click the button, we want to check if they have filled out their name in a text box and if they have, we want to submit the form. So, we tell the form to detect the submit event. When the event is triggered, we tell it to run the function that holds together the tests and actions. The function contains a control structure that uses a comparison operator to test the text box to see that it is not empty. Of course we have to work out how to reference the text box first. The text box is an object. One of the variables it holds is the text that is written in the text box. The text written in it is a literal. If the text box is not empty, a method is used that submits the form.
Examples
All examples on this page and elsewhere in my JavaScript tutorial are provided free of charge. Please see the terms and conditions page for terms of use.
These examples are all useful in their own right but when used together can produce spectacular results. I will leave that to your own creativity.
Note that the syntax highlighted source of all the header files I use in these examples, as well as several others, is available on my JavaScript libraries page. The header files can also be downloaded from there.
The header file scripts are meant to be real scripts for real use, not tutorials. I have included them on this page as they can be viewed as examples of real programming, not lessons on how to program. I agree that they are not always easy to read, but that is mainly because they are optimised for real use. You may choose to see this as a bad programming method, but I do not, as I can always see what I was intending for the script to do, and it helps to cut down on the transmitted file size, something which modem users are always happy for.
To give you an example of a more 'friendly' format, which is easier to use as a learning aid, one of my readers has kindly produced a reformatted version of my generic re-writable elements script, which is included in the email they sent me.
Non DHTML
The most popular use of JavaScript; changing images when the mouse hangs over a link
The next most popular use of JavaScript; opening new browser windows
The next most popular use of JavaScript; writing dynamic content
The next most popular use of JavaScript; checking forms
Slightly less used but just as useful, retaining variables from one page for use on another page
- Complicated string manipulation, taking variables from the location bar.
- Creating, reading and modifying cookies.
Some specialist scripts
- Form manipulation, offering the correct countries for a continent.
- More form manipulation, expandable tree structure.
The most irresponsible script
- Browser sniffing - to be used only to help avoid browser specific bugs, not to determine capability.
DHTML
Appearing / disappearing content
- Popup Menus.
- Popup Menus with delay - see Gecko engine bug.
- Auto-generation Popup Menus with delay - Gecko engine bugs removed.
- Tooltips.
Movable content
- Tooltips.
- Static logo.
- Falling objects (snow).
- Flying stars (changes apparent size of div elements).
- Fireworks (demonstrates changing colour).
- Analogue clock.
Mouse trails
Rewritable document content
W3C DOM
- Importing XML data files - a very advanced scripting topic.
- Solitaire game - a very advanced script.
These scripts any many more are included on my JavaScript libraries page. The page also contains several utility scripts, which you may find useful for your Web development. Please see the terms and conditions page for terms of use.
Games
Ok, so they are far too complicated to be examples, but all of the principles are the same as I have described in these tutorials. These games require various different technologies like HTML, CSS, DHTML, etc. Not all browsers will be able to use all of the games, in particular the 3D games, because they are VERY demanding on resources. The simpler games may even work in browsers like Netscape 3.
These games are all on my games site.
Adding JavaScript to a page
You can add a script anywhere inside the head or body sections of your document. However, to keep your document well structured there are some basic guidelines:
- Most scripts can go inside the document head. This keeps them out of the way of the main document content.
- If your script needs to run at a certain stage during page layout (for example, if it uses document.write to create content), it should be put at the correct stage of the document, almost always somewhere inside the document body. If the script is very small, then put it all where it will be used. If it is larger, then put it inside the head inside a function, and you can then call that function when you need it.
- If your script is used on more than one page, or if it is of any significant size, then put it in its own file, and load it in the document head. Not only will this help to keep the clutter of the document, but it will also help avoid potential syntax problems (I will cover these later). As an extra benefit, these can be used by multiple pages, allowing browsers to use their cache, and saving bandwidth for you and your visitors.
Adding a script to the page
To insert JavaScript into a web page, use the <script> tag. You should use the type attribute to specify the type of script being used, which in the case of JavaScript is text/javascript. It is also possible to the language attribute to say what JavaScript version you are using. In practice, this number means very little to browsers. They may claim to support a specific version, but will have vastly different capabilities. All JavaScript supporting browsers currently in use will support a level of JavaScript equivalent to JavaScript 1.2 (represented as "javascript1.2") or higher, so this is what I will teach you in this tutorial.
Browsers will generally choose an arbitrary version number that they will claim to support, and will run any script that has either no language version number, or a version equal to or lower than the one they claim to support. Since the language is so unreliable, you should generally omit this attribute, although it is common to see scripts using it. Your script can then detect if the browser is capable of running your script, and it can do this a lot more accurately than the version number can.
This is an example of a script tag, used to include a script in your page:
<script type="text/javascript">
//JavaScript goes here
</script>
If your script is incapable of providing its own fallback, but it is needed to access the page, you should include support for non-JavaScript browsers by using:
<noscript>
<p>This will not be displayed if JavaScript is enabled</p>
</noscript>
Using comments
Comments allow you to leave notes to yourself and other people in your script, and are useful as a reminder of what the script is doing and why. The double slash indicates a single line comment. Everything after it on the same line will be ignored by the script engine. The slash-asterisk indicates a block comment. Everything after it will be ignored by the script engine until an asterisk-slash is encountered.
<script type="text/javascript">
//This is a single line comment
/* This is a
block comment */
</script>
Using external script files
You can also use a separate header file to contain the JavaScript (usually *.js) making it easy to share across pages:
<script src="whatever.js" type="text/javascript"></script>
When using header files, if you put any script code in between the <script ...> and </script> tags, it will only be executed if the browser does not support header files (assuming it does support the version of JavaScript shown in the language attribute, if you used one). In reality, this is only for very old browsers that are not used at all any more, so there is no need for anything to be put there.
Scripts in header files are executed as if they were in the main page. If the script referances any external files, such as images, the addresses it uses are relative to the main page, not the script URI.
Commenting out your scripts
This is not needed any more. All current browsers are aware of script tags, and how to treat their contents, since they have been part of HTML since HTML 3. Browsers that do not understand HTML 3 or scripts (these are virtually never used now) will display the script as if it was the content of the page. You can hide the script from them by commenting out your script with standard HTML comments. Browsers that understand script will simply ignore these comments, and will just interpret the script within them. The opening comment is ignored as if it were a normal single line JavaScript comment. The closing comment will not, so it needs to have a JavaScript comment put before it:
<script type="text/javascript">
<!--
//JavaScript goes here
//-->
</script>
These HTML comments should not be used if you are using an external script file, and are not to be used anywhere else in your scripts.
Dealing with XHTML
Note that when I talk about XHTML, I am talking about pages that are served using a content type of application/xhtml+xml - the majority of pages that use XHTML markup are actually served as text/html and as a result are correctly treated as HTML, not XHTML.
The rules in XHTML are different. Script tags are not treated as being special. Their contents are treated as any other part of XHTML, so various operators can be misinterpreted as part of the markup. To avoid this, it is best to put all scripts in external script files so that they do not interfere with the page itself. If you feel the need to put something directly on the page, you can declare it as CDATA (the default for script contents in normal HTML):
<script type="text/javascript">
<![CDATA[
//JavaScript goes here
]]>
</script>
If you feel the compulsion to comment out your script in XHTML, you must use a more ugly structure to contain your scripts. Again, this really is not needed, since browsers that do not understand script also do not understand XHTML, but in case you want to use it (maybe you are serving it as XHTML to some browsers, and HTML to others), this is what to use:
<script type="text/javascript">
<!--//--><![CDATA[//><!--
//JavaScript goes here
//--><!]]>
</script>
Controlling when the script is activated
By default, any script you write will be processed as the document loads. For example:
<script type="text/javascript">
var myVariable = 'Hello';
window.alert(myVariable);
//as the document loads, a message box saying 'Hello' will be displayed
</script>
Sometimes, this may be undesirable and it may be better to write functions (see the section on Writing functions) and activate them later.
To activate JavaScript, you can use HTML events. Modern browsers can detect a vast number of events on most elements. Older browsers are more limited and can only detect the standard set of events on specific elements. The ones that will work in all browsers I have tested are:
- input, textarea, select
- onclick, onkeydown, onkeyup, onkeypress, onchange, onfocus, onblur, etc.
- form
- onsubmit, onreset
- a
- onclick, onmouseover, onmouseout, onfocus, onblur
- body
- onload, onunload
Check with the HTML specifications on the W3C site for more details. 'a' elements can also detect onmousemove in all current browsers (but not some of the older browsers that are not used any more. For some of these older browsers, such as Netscape 4, it is possible to compensate using a combination of onmouseover, onmouseout and then document.captureEvents and onmousemove on the body (see the section on Event information). The Event information and more advanced DOM events chapters of this tutorial show how to listen for more event types, and obtain information from them.
These are some examples of using events (shown here using traditional inline event handlers - later on in this tutorial, I will show you alternative ways to attach events to elements that will not require you to alter your HTML):
<a onmouseover="name_of_function(params)" href="somepage.html">
<input onkeypress="myVariable = 2;startTest();">
<select onchange="self.location.href = this.options[this.selectedIndex].value;">
<body onunload="window.alert('bye')">
Another way of making HTML activate JavaScript is to use
<a href="javascript:name_of_function(params)"> but in general it is best to use events,
so the link can provide an accessible alternative if JavaScript is not available (the event handler can prevent the
browser from using the link normally if scripting is available).
In all these cases, the script is contained within HTML attributes, and is subject to the normal rules of HTML entities. If you need to put quotes in the script in between the quotes in the html, use the HTML entity " or " for " style quotes or if your quotes in the HTML are done using the ' quotes (which is unusual ...), you can use ' to represent these in the script. If you need to include < or > operators, you should use the < and > entities.
Object oriented programming
Objects
An object is a 'thing'. For example a number is an object. An array is an object. Your browser window is an object. A form in your document is an object. There are hundreds more, and in some cases you can create your own.
Objects can have objects in them. For example, your document can have a form in it. This form is a
'child object' of the document. Therefore the document is the 'parent object' of the form. To reference
the child object, we have to go through the parent object, eg. document.myForm
An array can have numbers in its cells. As we have already discussed, the array is an object, and so
would be a cell within it, and so is the content of the cell. We cannot refer to the cell itself, but
we can refer to its contents: myArray['cell name or number'] for example.
Classes (or types)
A class is a goup of objects that are similar in some way. For example, a number and a piece of text can both be stored as a variable (in a way, like the variables you would use in mathematical algebra). In essence, we can say that pieces of text and numbers are examples of class 'variable'.
Numbers can be sub divided into two groups, integers and floats (or doubles). Integers are whole numbers: 1, 2, 3, 4, 0, -1, -2, etc. Floats have decimal points: 1.1, -5.7, 0.5, etc. In this case, we can say that 3 is an instance of class variable, (sub)class number, (sub)class integer.
In fact, a variable is a type of object. All instances of class 'object' have a certain two methods: toString() and valueOf(). Therefore, as 3 is an instance of class object, (sub)class variable, (sub)class number, (sub)class integer, it will inherit the toString() and valueOf() methods provided by the class 'object'.
Classes are not so important in JavaScript as they are in many other object oriented programming languages. Classes can be created when you define your own classes of objects, but it is not usual to create your own 'sub'-classes.
Collections
If you need to know what arrays are, see the section on Variables.
There are many arrays that are inbuilt into each document. The document itself is an array in certain uses.
The most obvious of these collections is the images collection. To refer to images in the document, we use
document.images['name of image']
This is a special kind of array, known as a collection.
Properties
Take, for example, an image. When we define images in HTML, we write:
<img src="frog.gif" name="myImage" height="10" width="10" alt="A frog">
The properties of the image would be src, name, height, width, alt and if we also used Style Sheets we might
have included several more (like background-color for example). All properties are a type of object so to
refer to the src of my image, I would write document.images['myImage'].src
Methods
There are always actions that are associated with objects. For example, a form may be submitted or reset. The
actions are methods. To submit a form in non-object-oriented programs, we might write
submit('name of form')
That would simply be a function. In object oriented programming like JavaScript, we would use
document.nameOfForm.submit()
The reason this is a method and not just a function is that each form will have its own submit() function built in, which is referred to using the object oriented syntax shown above. You will never have to write methods in yourself unless you create your own objects, the browser does that for you.
You can think of it like this:
- With the non-object-oriented way, we would tell a function to submit the form.
- With the object oriented way, we would tell the form to submit itself.
If wanted, you can run several methods in turn on the same object by using:
referenceToTheObject.method1().method2().method3().method1again()
In this case, method1 must return a class of object that has the method 'method2' etc.
Operators
The most common operators are mathematical operators; +, -, /, * (add, subtract, divide, multiply) for example. Operators can be split into two groups, comparison operators and assignment or 'action' operators. Comparison operators test to see if two variables relate to each other in the specified way, for example, one variable is a higher number than the other. Other operators perform an action on a variable, such as increasing it by one.
The following table gives those that are most commonly used. There are many JavaScript 1.3 operators such as the identity
operator === and others like it. These are supported by all current browsers, but are rarely used.
Browsers that do not understand them will just produce errors.
| Operator | Uses |
|---|---|
+ | adds two numbers or appends two strings - if more than one type of variable is appended, including a string appended to a number or vice-versa, the result will be a string |
- | subtracts the second number from the first |
/ | divides the first number by the second |
* | multiplies two numbers |
% | divide the first number by the second and return the remainder |
= | assigns the value on the right to the object on the left |
+= | the object on the left = the object on the left + the value on the right - this also works when appending strings |
-= | the object on the left = the object on the left - the value on the right |
> | number on the left must be greater than the number on the right - this also works with strings and values |
< | number on the left must be less than the number on the right - this also works with strings and values |
>= | number on the left must be greater than or equal to the number on the right - this also works with strings and values |
<= | number on the left must be less than or equal to the number on the right - this also works with strings and values |
++ | increment the number |
-- | decrement the number |
== | the numbers or objects or values must be equal |
!= | the numbers or objects or values must not be equal |
<< | bitwise leftshift |
>> | bitwise rightshift |
& | bitwise AND |
| | bitwise OR |
^ | bitwise XOR |
~ | bitwise NOT |
! | logical NOT (the statement must not be true) |
&& | logical AND (both statements must be true) |
|| | logical OR (either statement must be true) |
in | object or array on the right must have the property or cell on the left |
Note, if you do not set the language="javascript1.2" attribute in the <script>
tag, 0 == false == '' and undefined == null. If you do set the language attribute
to 'javascript1.2', Mozilla/Firefox and other Gecko browsers (but none of the other major browsers)
will change this so that none of these will equate to each other. Since the attribute is deprecated anyway, and
the JavaScript versions were never standardised, you should not rely on this behaviour.
There are also a few operators that can also be used like functions:
- void
void statementorvoid(statement)(see the section on writing functions)- typof
typeof variableortypeof(variable)returns the type (or class) of a variable.- eval
eval(string)interprets a string as JavaScript code.
There are also the 'var', 'new' and 'delete' operators. See the section on
variables for examples of their uses. Also see the section on the Math object operators below.
Note that JavaScript has no logical XOR operator. If you need that functionality, see my separate XOR article.
Operator precedence
If you ask JavaScript to perform a calculation using multiple operators, those operators will be
evaluated in a specific order. For example 3 + 6 * 7 is calculated as ( 6 * 7 ) + 3
because the * is calculated before the +. The order in which these are evaluated is: * / % + - +
(where the second + is appending strings).
To change the order in which they are calculated, use parenthesis ( ) as the contents of
parenthesis are calculated before the contents outside the parenthesis. For example, 3 + 6 * 7 = 45
but ( 3 + 6 ) * 7 = 63
The Math object methods
In reality, these are methods of the Math object but they are used in place of operators.
| Operator | What it does |
|---|---|
Math.abs(n) | Returns the absolute value of n |
Math.acos(n) | Returns (in radians) cos-1 of n |
Math.asin(n) | Returns (in radians) sin-1 of n |
Math.atan(n) | Returns (in radians) tan-1 of n |
Math.atan2(n,k) | Returns the angle (rads) from cartesian coordinates 0,0 to n,k |
Math.ceil(n) | Returns n rounded up to the nearest whole number |
Math.cos(n) | Returns cos n (where n is in radians) |
Math.exp(n) | Returns en |
Math.floor(n) | Returns n rounded down to the nearest whole number |
Math.log(n) | Returns ln(n) Note, to find log10(n), use Math.log(n) / Math.log(10) |
Math.max(a,b,c,...) | Returns the largest number |
Math.min(a,b,c,...) | Returns the smallest number |
Math.pow(n,k) | Returns nk |
Math.random() | Returns a random number between 0 and 1 |
Math.round(n) | Returns n rounded up or down to the nearest whole number |
Math.sin(n) | Returns sin n (where n is in radians) |
Math.sqrt(n) | Returns the square root of n |
Math.tan(n) | Returns tan n (where n is in radians) |
Variables
Variable types are not important in JavaScript. They may be interchanged as necessary. This means that if a variable is a string one minute, it can be an integer the next. The basic variable types are:
- character
- 'a' or '@' or 'k' etc.
- string
- 'hdttgs 8 -46hs () Get the idea'
- integer
- 0 or 1 or 2 or 3 or 4 etc. or -1 or -2 or -3 or -4 etc.
- float (or double)
- 23.546 or -10.46
- boolean
- true or false
- function
- A function; see the section on Functions
- object
- An object; see the section on Object oriented programming
- array
- A type of object that can store variables in cells (see below)
- undefined
- A variable that has not been given a value yet
- null
- A variable that has been defined but has been assigned the value of null
Integer and float are grouped together as 'number'. Character and string are grouped together as 'string'.
Use the typeof operator to find out which variable type your variable is. Note, typeof will return 'object' for arrays and null.
Defining variables
See the section on 'Referencing' subsection 'Avoiding referencing conflicts' to see how to choose names for your variables.
Normal variables
It is good practice to pre-define all variables using the var keyword. It is possible to define the variable, leaving its value undefined, or assigning a value immediately, or even to define multiple variables in a single command:
var variablename;
var variablename = value;
var vari1 = value, vari2 = anotherValue, vari3;
JavaScript is fairly lenient, and will create a global variable if you forget to use the 'var' keyword, but you
assign a value to an undeclared variable (if you attempt to read the value of an undeclared variable, it will throw an
error, as discussed below). However,
this can lead to problems if you end up accidentally overwriting variables from another scope (this will be covered in
the chapter on Functions). Once a variable is defined do not use
'var variablename' again unless you wish to completely overwrite the variable. It makes no sense to redeclare
a variable with the var keyword within the same scope, but browsers will not complain if you do it.
These are some examples of how to define variables, in this case, a string, a number, and a regular expression:
var myFish = 'A fish swam in the river';
var myNumberOfGoats = 23;
var myPattern = /<[^>]*@[^<]*>/gi;
Note that variables can be defined at any point in your script, including inside a control structure that causes that statement never to be executed. However, no matter where you choose to define your variable, the JavaScript engine will create the variable at the start of the current scope. It will hold the value undefined until a statement is executed that gives it a value.
Objects
- WebTV 2.6- does not support the {} syntax for creating objects.
If you want to create variables that you want to be able to give child properties to, you must
define the variable as an object. To define a variable as an object, use either the new Object()
or {} syntax:
var variableName = new Object();
var variableName = {myFirstProperty:1,myNextProperty:'hi',etc};
You can then assign child objects or properties to that object as you want:
variableName.aPropertyNameIMadeUp = 'hello';
variableName.aChildObjectNameIMadeUp = new Object();
Note that if you want to run a method on an object that you just created, for true JavaScript 1.2 compliance, you must surround the object declaration with brackets (early Netscape 4 will have problems otherwise). This example will not work in early Netscape 4, and other browsers made at the same time:
new Date().getTime()
This example will work in all JavaScript supporting browsers:
( new Date() ).getTime()
This applies to all object types like Array, Image, Option, Object, Date and ones you create yourself.
Arrays
- WebTV 2.6- does not support the [] syntax for creating arrays.
Arrays are similar to the Object we have just defined, but with some small differences.
I like to think of arrays as boxes. Inside the box, there are several compartments or cells.
We can vary the number of compartments. To refer to the contents of a compartment, we write the name of the box,
then we write square brackets, inside which we put the name or number of the compartment.
To create an array, use either the new Array() or [] syntax:
var nameOfArray = new Array();
var nameOfArray = new Array('content_of_first_cell','and_the_second',8,'blah','etc');
var nameOfArray = ['content_of_first_cell','and_the_second',8,'blah','etc'];
You can also use a number as a parameter when creating the array object. If the number is a positive integer,
an array will be created with that many cells, all of which will be empty: new Array(5). Note that
if you set the language version to javascript1.2, some browsers (but not all) will create an array with a single cell containing
the number 5.
To refer to the contents of its cells, use the syntax nameOfArray[name_or_number_of_entry]
(if using names instead of numbers, the name should be in quotes). Numeric arrays start at 0, not 1, so the first
cell is number 0.
In JavaScript, arrays and objects are almost equivalent, and accessing a named cell of an array is the same as accessing a property of an object. If a cell of an array is called 'mycell', you could use either of these to access its contents:
nameOfArray['mycell']
nameOfArray.mycell
There are some important differences between arrays and objects. By default, arrays have far more methods
attached to them, for stepping through the array, or splitting it into pieces. In addition, if numbers are used for
entries, you can find out how many entries (or variables) the array is holding, using nameOfArray.length
It is possible to create multi-dimensional arrays, by creating aditional arrays as the contents of the cell of another array:
var nameOfArray = new Array(new Array(1,2,3,4),'hello',['a','b','c']);
You can refer to the cells of that array using the square bracket notation twice (or multiple times, depending on how many dimensions your array has):
nameOfArray[name_or_number_of_entry][name_or_number_of_inner_entry]
Other types of objects
Browsers will have many built in types of objects. All JavaScript capable browsers will provide the following aditional object types:
- Date
- Creates a date object, which can perform calculations based on the date, for example:
var mydate = new Date(); window.alert( 'The year is' + mydate.getFullYear() ); - Image
- Creates an image that is not visible but is stored in cache. Setting the src attribute of the image causes
the image to be loaded and stored in the browser's cache:
Now each time I want to change an image on the page, I can sayvar myimage = new Image(); myimage.src = 'thing.gif';document['imagename'].src = myimage.src;and the image will change, without having to wait for the new image to load. - Option
- Creates an option that can be added into a select input, for example:
var myoption = new Option('text','value'); selectInput.options[selectInput.options.length] = myoption;
See the section on 'Creating objects' for how to create your own objects that are not one of the pre-defined object types. DOM compliant browsers will provide far more object types - these will be covered in later chapters of this tutorial.
Deleting properties
On several occasions here I have created properties for objects. Even if these are set to undefined or null, they still exist, holding that new value, and will be found using the for-in control structure. You can delete them completely by using the 'delete' keyword:
delete myObject.itsProperty;
Of course, unless you have serious computer memory considerations, or security risks, it is usually not necessary to do this at all, since JavaScript engines clean up after themselves once the variable is no longer referenced.
Avoiding errors with variables
If at any time you refer to a variable that does not exist, you will cause an error. However, JavaScript allows you to refer to one level of undefined child properties of an object. This is a very important rule to learn, as it forms the basis of object and capability detection, and is fundamental to making cross browser scripts. The following series of examples will demonstrate what will throw errors:
var myObject = new Object(), nonObject = '', nonObject2;
This sets everything up for the following examples. So far, everything is fine, but in the code below, b is undefined. This will cause an error:
var a = b + 5;
In the next example, the parent object has been defined, but its property has not. Since this is only one level of undefined properties, this is allowed, and will not cause an error:
var b = myObject.myChild;
In the next example, the parent object has been defined, but its property has not. Trying to refer to a child of the non existent property means there are now two levels of undefined properties. This will cause an error:
b = myObject.myChild.itsChild;
In the next example, the parent object has been defined, but it is a type of variable that cannot accept child properties. Trying to create a child property will not throw an error, since it is only one level of undefined properties. However, it will not do anything, since the new property will be rejected:
nonObject.itsChild = 7;
window.alert(nonObject.itsChild);
//This will alert 'undefined'
In the next example, the parent object has been declared, but it was not given a value. As a result, it holds the value undefined. Trying to refer to a child property means there are now two levels of undefined properties, and will throw an error:
nonObject2.itsChild = 7;
Referencing a variable or just its value
If you assign one variable to another, there are cases where this merely copies the value in one variable and 'pastes' it into the other, but there are also cases where instead of copying the variable, it just provides you with a new way to reference that variable. The following is an example of where this might occur:
var myNewVariable = myOldVariable;
If myOldVariable was already defined as a string, number, boolean, null or undefined, it would
simply have copied myOldVariable and 'pasted' it into myNewVariable. If the new variable were
changed (for example, using myNewVariable = 'some new value';) myOldVariable retains
its old value.
If, on the other hand, myOldVariable was already defined as a function, array, object or
option, myNewVariable would have been created as a pointer to myOldVariable. The children of
myOldVariable would now also be the children of myNewVariable. If the new variable were
changed (for example, using myNewVariable = 'some new value';), it would only alter
the value of myNewVariable so that it no longer references the same contents as myOldVariable.
However, changing the child properties of myNewVariable will change the properties of the
object it references, and as a result, myOldVariable would also see the change:
var myOldVariable = new Object();
var myNewVariable = myOldVariable;
myNewVariable.newChild = 'Hello';
alert(myOldVariable.newChild);
//This will alert 'Hello'
More about numbers
JavaScript understands numbers in several formats, allowing you to specify numbers in hex, decimal, and octal. If a 0 precedes a number and there is no number higher than 7, the number is considered to be in octal (base 8) and if the number is preceded by 0x, then it is considered to be in hex (base 16) and can also contain characters A, B, C, D, E, F. Neither may contain decimal points.
With decimal numbers, 12e+4 may be used to replace 12x104 and 12e-4 may be used
to replace 12x10-4 etc.
There are a few numbers that are held by the Math object and can be used as variables with the exception that you cannot assign values to them. These are known as constants. There are some constants available that give the document area of the window that is available for writing to. These require specific referencing to obtain and so have been included in the section on referencing items, objects and elements, subsection 'Window size'.
The available Math object constants are:
| Math object property | Value (approx) | Mathematical equivalent |
|---|---|---|
| Math.E | 2.718 | e |
| Math.LN2 | 0.693 | ln(2) |
| Math.LN10 | 2.303 | ln(10) |
| Math.LOG2E | 1.442 | log2(e) |
| Math.LOG10E | 0.434 | log10(e) |
| Math.PI | 3.142 | Pi |
| Math.SQRT1_2 | 0.707 | (sqrt(2))-1 or sqrt(1/2) |
| Math.SQRT2 | 1.414 | sqrt(2) |
Special string characters
There are a few string characters that can be escaped with a backslash and can be used to replace untypeable characters. These are:
- \n
- A newline character. Use this if you want to insert a line break into text.
- \f
- A form feed. Try not to use this ever. Use \n instead.
- \r
- A carriage return. Try not to use this ever. Use \n instead.
- \t
- A tab character.
- \\
- A \ character
- \/
- A / character (most web developers [myself included on occasion] forget this one - generally, browsers will have no trouble with you forgetting the backslash but it is important for representing closing tags and in theory you should always use the backslash escape when writing a forward slash - see the section on Writing with script for details of where it is needed)
If you need to recognise a Windows linebreak, you need to look for \r\n. If you are trying to add a linebreak (for example, when modifying the value of a textarea input), you should insert a \n character. This will work cross browser. Note that browsers on Windows may convert this \n character into a \r\n automatically, depending on where you use it.
Old Mac Operating Systems (OS 9 and below) used \r for linebreaks, but as far as my tests showed, they are converted to \n by JavaScript. However, just be aware that you may encounter some of these, especially in text inputs (Mac OS 9 is still popular among Mac users - probably a little less than 50% of the Mac market). Unix based Operating Systems (including Mac OS X) use \n for linebreaks.
If you are writing a string that contains double quotes, the easiest way to deal with it is to surround it with single quotes. You should also use double quotes if your string contains single quotes:
var mystring = 'And he said "help" twice';
var mystring = "Help Andy's cat";
You may notice a problem. What if you have both single and double quotes in your string? The solution is to use the escape character '\' to excape the quotes (in fact, you can always escape quotes, even if the string is delimited by the other type of quotes). For example, both of the following are valid:
var mystring = 'And he said "help Andy\'s cat" twice';
var mystring = "And he said \"help Andy's cat\" twice";
If your string becomes too long to fit on one line (this really doesn't matter - you can make the text as long as you want), and you want to split it onto several lines, simply end the string, follow it with the concatenation operator + and start a new string on the next line:
var mystring = 'first line of the string ' +
'still on the first line of the string - it\'s like we never broke the line';
Note, in theory, you can use \ to break the string:
var mystring = 'like \
this';
But this has significant problems; the \ will not always cope with trailing whitespace, may or may not correctly treat the leading whitespace before the new line, and does not work correctly in all JavaScript implementations:
- Netscape 4 (inventors of JavaScript), Escape, Opera 7.6- and ICEbrowser include the linebreaks in the string.
- Internet Explorer, Mozilla/FireFox, Opera 8+, Safari/Konqueror, iCab and OmniWeb ignore the linebreak characters.
- ICEbrowser sometimes ignores the whole string
I mention this only for completeness. Do not use it. It is easier and better to use the concatenation operator as shown above.
Regular expressions
- Opera 4-6 has a major bug in its regular expression handling and will fail on even the simplest regular expressions.
- Pocket Internet Explorer, Internet Explorer for Windows CE and iCab 2- do not support regular expressions properly.
Certain methods, like the stringObject.replace() and stringObject.match() methods, can
recognise patterns in text. To do this, they use regular expressions. These are well documented
elsewhere
so I will not describe the syntax here. Basically, what you can do is use special characters to
recognise text patterns (like \w for characters a-z, A-Z, 0-9 and _). To define a collection of
characters as a regular expression, you use the / character (sometimes with a g or i after it).
For example, the regular expression /\/\*[\w\W]*\*\// matches block comments.
Some rare browsers do not support regular expressions. In theory, you should be able to detect regular expression support using this:
if( window.RegExp ) { var myRegularExpression = new RegExp("pattern"); }
This should not produce errors in Pocket Internet Explorer and Internet Explorer for Windows CE (as they do not understand the /pattern/options syntax or support the RegExp object). However, as Opera 6- and iCab 2- support the RegExp object, but fail to use it correctly, your scripts will still fail, though hopefully without errors. Thankfully, current releases of Opera and iCab do support regular expressions correctly.
Control structures
The 'if' statement
if( myVariable == 2 ) {
myVariable = 1;
} else {
myVariable = 0;
}
If myVariable had been 2 it would now be 1. If it had been anything other than 2 it would now be 0.
'If' statements can also test for the occurence of a child object of an object that may not exist. For example,
some browsers provide document.body.style while some older browsers do not even provide
document.body. In these browsers, writing 'if( document.body.style )'
would just produce an error (see the section on 'Variables' subsection
'Avoiding errors with variables').
In order to solve this problem, we could write this:
if( document.body ) {
if( document.body.style ) { etc. }
}
However, the && operator has a useful feature that we can use here to combine the two
'if' statements into one:
if( document.body && document.body.style ) { etc. }
The first test would be false, so the browser would not proceed to the second. This is known as a short-circuit.
The || operator has a similar feature, but it will only evaluate the second test if the first one fails.
JavaScript understands that if the '{' and '}' (curly brace) characters are left out, then only the next command belongs to that statement:
if( x < 5 )
x++;
window.alert(x);
Here, the alert will always happen reguardless of x, but x will only be incremented if x is less than 5. This may seem convenient, as it allows you to make your code a tiny bit shorter, but I recommend avoiding this syntax. It makes your code harder to read, especially if you start nesting your control structures. It also makes it easy to forget to put them in when you needed them, and also makes debugging code much harder, since you will need to go back through your code to add them so that you can add extra debugging tests. It is best to always use the curly braces, even if they are optional.
As always, there is an exception. Nested 'if' statements like this can start to get difficult to manage:
if( myVariable == 2 ) {
myVariable = 1;
} else {
if( myVariable == 5 ) {
myVariable = 3;
} else {
myVariable = 4;
}
}
By strategically removing curly braces, that can usefully be reduced to this construct (which you may recognise from other programming languages) - note that 'else if' is not written as 'elseif':
if( myVariable == 2 ) {
myVariable = 1;
} else if( myVariable == 5 ) {
myVariable = 3;
} else {
myVariable = 4;
}
The 'for' loop
This is one of the most common constructs in use. Typically, it is used to cycle through the contents of an array, or to create a specific number of new objects, but it can do many more useful things if needed. The syntax of the 'for' loop is as follows:
for( starting_initialise; continue_as_long_as_condition; do_this_each_time )
- starting_initialise
- This is where you define new variables that you will use in the loop, typically for use with incremental counting.
As with all variables, you must declare them (if you have not done so already). You can define multiple variables if
needed, using:
These variables are not restricted to being inside the 'for' loop, and will be available to all code after the loop (in the same scope as the loop).var myVariable1 = value, myVariable2 = another_value; - continue_as_long_as_condition
- This is where you define the conditons under which the loop should continue to execute. The syntac is exactly
the same as for the 'if' statement, so you can apply more than one continue condition by using the && or ||
operators:
If the condition is not satisfied when the for loop begins, then it will never loop through it.myVariable1 <= 5 && myVariable2 >= 70; - do_this_each_time
- Once the end of the loop is reached, it will do whatever you tell it to here. Typically, this is used to increment
or decrement a stepping variable, and it is possible to perform actions on more than one variable by separating them with
a comma:
myVariable1++, myVariable2 -= 4
The following is a full example.
for( var myVariable = 1; myVariable <= 5; myVariable++ ) {
myArray[myVariable] = 1;
}
myArray[1] to myArray[5] are now 1.
The 'for - in' loop
The 'for - in' loop is used to cycle through all exposed properties of an object (or array). Every time you create properties or methods on an object, these will be added to the list of properties that will be exposed. Most internal properties (the ones that JavaScript creates) will also be exposed, but JavaScript engines are allowed to hide internal properties and methods if they want to. You should not rely on any specific behaviour here, but note that some browsers will give the internal properties and methods of intrinsic objects, and some will not.
Again, you should declare the variable names that you use, if you have not done so already. The syntax of the 'for - in' loop is as follows:
for( var myVariable in anObjectOrArray ) {
This will run through the loop, once for each exposed property in anObjectOrArray. Each time it loops, it assigns the next property name as a string value to myVariable. You can then use array notation to access the value of that property. The following example writes all the exposed properties of the document object:
for( var myVariable in document ) {
document.write( myVariable + ' = ' + document[myVariable] + '<br>' );
}
Note that if you use this loop on an array, it will list the numbered and named keys, including the internal 'length' property. It is very easy to make mistakes here, so be careful not to mistake these property types for each other.
The 'while' loop
The 'while' loop is identical in behaviour to the 'for' loop, only without the initial setup, and loop-end actions. It will continue to run as long as the condition is satisfied:
var myVariable = 1;
while( myVariable <= 5 ) {
myArray[myVariable] = 1;
myVariable++;
}
myArray[1] to myArray[5] are now 1.
Using a feature of the increment (and decrement) operator here, it is possible to shorten the code inside the loop to
be just 'myArray[myVariable++] = 1;', and it would have exactly the same effect. Firstly, it would use the
value of myVariable to index the array cell, then it would increment myVariable.
This also works in reverse; 'myArray[++myVariable] = 1;'. Firstly, it would increment the value of
myVariable, then it would use the new value to index the array cell. If I had done
this, myArray[2] to myArray[6] would now be 1.
These features also work outside loops, but this is where you will most commonly see them, so I have included them here.
The 'do - while' loop
This is similar to the while loop, but with an important difference. The condition is evaluated at the end of the loop, meaning that even if the condition is never satisfied, it will still run through the loop at least once.
var myVariable = 1;
do {
myArray[myVariable] = 1;
myVariable++;
} while( myVariable <= 5 );
myArray[1] to myArray[5] are now 1.
The 'switch' statement
The 'switch' statement is like repeated 'if' statements, testing a single value to see if it matches one of a set of values:
switch(myVar) {
case 1:
//if myVar is 1 this is executed
case 'sample':
//if myVar is 'sample' (or 1, see the next paragraph)
//this is executed
case false:
//if myVar is false (or 1 or 'sample', see the next paragraph)
//this is executed
default:
//if myVar does not satisfy any case, (or if it is
//1 or 'sample' or false, see the next paragraph)
//this is executed
}
If a case is satisfied, the code beyond that case will also be executed unless the break statement is used. In the above example, if myVar is 1, the code for case 'sample', case false and default will all be executed as well. The solution is to use break; as follows (The use of the break statement is described below).
switch(myVar) {
case 1:
//if myVar is 1 this is executed
break;
case 'sample':
//if myVar is 'sample' this is executed
break;
case false:
//if myVar is false this is executed
break;
default:
//if myVar does not satisfy any case, this is executed
//break; is unnecessary here as there are no cases following this
}
The 'with' statement
Take for example the following example:
x = Math.round( Math.LN2 + Math.E + Math.pow( y, 4 ) );
Using the 'with' statement, this can be replaced with:
with( Math ) {
x = round( LN2 + E + pow( y, 4 ) );
}
Note that the 'with' statement brings extra variable names into the current scope. In the example above, if I already had a variable called pow before the 'with' statement, this variable would be unavailable inside the with statement, as it would have been replaced by the method of the Math object (as would any other variables that matched property or method names). Once the 'with' statement is complete, the old variables would become available again.
The quick 'if' statement
This is known as the conditional or ternary operator, and is an easy way to assign different values to a variable, depending on a condition.
var myVariable = document.getElementById ? 1 : 0;
This is identical to:
if( document.getElementById ) {
var myVariable = 1;
} else {
var myVariable = 0;
}
The try - catch - finally statement
- Netscape 4, Internet Explorer 4 and WebTV do not support this structure and will produce errors if you use it.
The 'try - catch - finally' control stucture allows you to detect errors and quietly deal with them without producing error messages or aborting the script, and in fact, without even interrupting the flow of the script that is running. This makes it superior to the original way of handling script errors (without error messages) where scripts are completely aborted:
window.onerror = referenceToFunction;
The syntax of the 'try - catch - finally' control stucture is as follows:
try {
//do something that might cause an error
} catch( myError ) {
//if an error occurs, this code will be run
//two properties will (by default) be available on the
//object passed to the statement
alert( myError.name + ': ' + myError.message );
} finally {
//optional - this code will always be run before the
//control structure ends, even if you rethrow the error
//in the catch
}
If an error occurs in the 'try' section, it immediately jumps to the 'catch' part, passing some information about the error. Different browsers provide different information for the same error so don't trust it (in theory, DOM browsers will use a specific set of error types, but this depends on their level of DOM support - Internet Explorer is the least compliant here). Once the 'try' or 'catch' parts have been run, the 'finally' part is run if you have provided one, then the script following the control structure is run, unless you throw another error.
If you nest these statements (one 'try - catch' inside another), you can rethrow the error from the 'catch' part of the inner statement to the 'catch' part of the outer statement (the 'finally' part - if there is one - would still be run before the outer 'catch' is run, but the script following the inner structure will not be run). This is done using the 'throw' method:
try{
//...some other code goes in here
try {
var a = nonexist.b; //this will produce an error
} catch(myError) {
//this catches the error and alerts the message
alert( myError.message );
//re-throw the error up to the outer try - catch
throw( myError );
}
//...some other code goes in here
} catch( myErrorObject ) {
//I re-threw the first error, so this is the same error object
//the message should be the same
alert( myErrorObject.message );
}
You can also throw your own errors at any point by creating an object with the required properties, and passing it as the parameter when using throw:
try{
var myEr = new Object();
myEr.name = 'My error';
myEr.message = 'You did something I didn\'t like';
throw( myEr );
} catch( detectedError ) {
alert( detectedError.name + '\n' + detectedError.message );
}
What is wrong with it?
It's lack of support in older browsers is its major failing. Thankfully these browsers are hardly used any more. It would be very useful to use this structure detect errors in Netscape 4 (like the 'this' keyword + inline method bug - for example - there are lots more errors), but that browser does not support the statement. It would also be useful for checking for stupid bugs, like where checking for something like navigator.taintEnabled causes errors in Internet Explorer. However, the error is not correctly thrown for these errors.
Unfortunately, if you use this structure in any script run by a browser that does not support it, the browser will abort the entire script with errors, even if it does not use the part containing the structure.
It should never be used to detect if a browser supports a method or property like document.getElementById as a proper object detect would suffice.
So when should it be used?
It can be used for W3C DOM scripting, where you may want to avoid DOM mutation errors (for example), which are valid errors, but serve to warn you not to do something, and do not always need to abort the whole script. Older browsers do not support the DOM anyway, so it doesn't matter if they don't understand this part of it. However, they will still run the script (it is not possible to protect them by using the language attribute on the script tag, as you need to use JavaScript 1.2 - not anything higher - to enable Internet Explorer 5 support). This means that the older browsers will still produce errors, unless you define the old error handling method in an earlier script.
It can be used for throwing your own errors if you create the 'error' deliberately under certain circumstances.
It can be used to check if accessing a frameset frame will cause a browser security error (for example, if the page in the frame belongs to another site).
It could also enable you to avoid problems where different browsers support the same methods but expect a different syntax, for example, the selectBox.add method (I did not include this method in my DOM section of the tutorial due to this problem):
try {
selectBox.add(optionObject,otherOptionObject);
} catch ( e ) {
selectBox.add(optionObject,index);
}
Conditionals without a condition?
You may notice in the example for "The quick 'if' statement" that I tested for a property without testing
for any specific value: 'if( document.getElementById )'
That is valid, and is one of the most useful parts of JavaScript. This is a very important rule to learn, as it forms the basis of object and capability detection, and is fundamental to making cross browser scripts. This will be true if:
document.getElementById != "" &&
document.getElementById != 0 &&
document.getElementById != false &&
document.getElementById != undefined &&
document.getElementById != null
The opposite is also possible: 'if( !document.getElementById )'
This will be true if:
document.getElementById == "" ||
document.getElementById == 0 ||
document.getElementById == false ||
document.getElementById == undefined ||
document.getElementById == null
Using this, you can detect one type of capability, and if it fails, detect another type, and continue until you find one that works.
You can also do this anywhere where a condition is expected, such as with the 'while' loop condition, the 'do - while' loop condition and the 'continue_as_long_as_condition' in the for loop.
Checking for properties with 'in'
- WebTV crashes if you use the 'in' operator to check for a property that does not exist.
- Netscape 4, Internet Explorer 5.0- on Windows and Internet Explorer on Mac cannot use the 'in' operator as shown here.
The 'in' operator used in the 'for - in' loop has another purpose. It can also be used to check for the existence of named properties of an object. In most cases, it is best to use a conditional without a condition, as shown above. However, there are some cases where you want to test for the existence of a property even thought the property's value may be one that does not evaluate to true. An example would be where you want to check for the existence of a property whose value may be 0, or an empty string, or null.
If you know what the type of the property will be, it is possible to achieve this using identity operators, or the typeof operator, as shown here:
if( typeof( document.body.innerHTML ) == 'string' ) {
However, it is also possible to use the 'in' operator to test for a property. This allows you to test for its existence, no matter what value it currently holds, and no matter what type of value it currently has (even if it has been assigned a value of undefined). In the 'for - in' loop, the 'in' operator returned the name of properties as a string, and so here, it expects the name to be a string. This limits the usefulness a little, as it can only search for the name, and cannot be used to see if one of the properties holds a specific value or value type.
if( 'innerHTML' in document.body ) {
Note that this is around 20 times slower in Internet Explorer than the conditional without a condition, as shown above. In most other browsers, the two alternatives perform about the same. In general, I consider it best to use the more common alternatives, unless you have a specific use that needs the behaviour of the 'in' operator.
Assignments inside a conditional
JavaScript allows you to perform an assignment at the same time as testing if the assignment worked. This can be used inside any conditional, including inside an 'if', 'for', 'while' and 'do - while'.
if( x = document.getElementById('mydiv') ) {...}
do {
alert( node.tagName );
} while( node = node.parentNode );
Note that Internet Explorer on Mac will produce an error if you try to do this with an array, when it steps off the end of the array.
Continue and break statements and labels
Labels
Labels are used to name the 'while', 'do - while', 'for', 'for - in' and 'switch' control structures. The syntax used is:
LabelName:
Control Structure
Labels are very rarely used in JavaScript.
The break statement
Writing break inside a switch, for, for-in, while or do - while control structure will cause the program to jump to the end of the statement. If you just use, for example:
for( var x = 1; x < 5; x++ ) {
var y = 1;
while( y < 7 ) {
y++;
if( y == 5 ) { break; }
document.write(y);
}
}
The script will jump past the end of the while loop when y is 5. But if you use this:
myForLoop:
for( var x = 1; x < 5; x++ ) {
var y = 1;
while( y < 7 ) {
y++;
if( y == 5 ) { break myForLoop; }
document.write(y);
}
}
The script will jump past the end of the for loop when y is 5.
The continue statement
Writing continue inside a 'for', 'for - in', 'while' or 'do - while' control structure will cause the program to jump to the test condition of the structure and re-evaluate it having performed any 'do_this_each_time' instructions. If you just use this, for example:
for( var x = 1; x < 5; x++ ) {
var y = 1;
while( y < 7 ) {
y++;
if( y == 5 ) { continue; }
document.write(y);
}
}
This script will jump to the test condition of the while loop when y is 5 so 5 will never be written but 6 and 7 will be. If you use this instead:
myForLoop:
for( var x = 1; x < 5; x++ ) {
var y = 1;
while( y < 7 ) {
y++;
if( y == 5 ) { continue myForLoop; }
document.write(y);
}
}
Here, the script will increment x as part of the for loop and then re-evaluate the for condition.
Writing with script
Be careful when writing with script. If script is not available, that content will not be created.
You should limit your use of this to parts of the page that are not needed to access page content.
If you do write important parts of the page that are unavailable without scripting, you should use
<noscript> tags to provide an alternative.
Writing while the page is still loading
If your code is being executed while the page is still loading (in other words, if it is run as part of the initial page layout) put the following:
<script type="text/javascript">
document.write('<p>What ever you want to write<\/p>');
document.writeln('<p>What ever you want to write<\/p>');
//writeln puts a line break after the line.
//This is treated as a line break in the source of HTML
</script>
It will write whatever you put, in whatever part of the page the script is currently running. Of course, you can include HTML tags in there too or some pre-programming.
Note that if you write content using an event handler (such as the onload handler for an image), it will be treated as if the page has completed loading, even if it has not.
Writing after the page has loaded
After the page has completed loading, the rules change. Instead of adding content to the page, it will replace the page. To do this, you should firstly open the document stream (most browsers will automatically do this for you if you just start writing). Then you should write what you want, and finally, you should close the document stream. Again, most browsers will automatically close the stream for you. The notable exception here is the Mozilla/Firefox family of browsers, that will continue to show a loading graphic until you close the stream. Some other browsers may fail to render part or all of the content. Just to be safe, make sure you always close the stream.
<script type="text/javascript">
document.open();
document.write('<p>What ever you want to write<\/p>');
document.write('<p>More stuff you want to write<\/p>');
document.close();
</script>
That will remove everything that is currently being shown and replace it with what you write in there. This is the equivalent of moving the user to a completely new page. You should put <html> tags and things like that in there too if you want to use that method.
You may notice that I close my HTML tags inside the script with a backslash before the forward slash in the closing tag. This is a requirement of the specification (and can cause the HTML validator not to validate your page if you forget it), although all browsers will understand if you omit the backslash.
However, since you can write HTML with script, you can write style or even script tags with it, making one script import another. If you omit the backslash on any </script> tags that you are writing with the script, the browser will read that as the closing tag for the current script, and your script will fail.
The same applies to opening or closing comments (although I fail to see why you would want to write comments using a script).
These can be written as '<'+'!--' and '-'+'->'. When the script runs, the plus
sign tells it to append the strings, creating a valid HTML comment.
Problems with old browsers
Although not really in use any more, you may want to be nice to older browsers like Netscape 4. If using document.write to dynamically write a div element, do not give the div an inline style with left: or top: positioning. This will cause Netscape 4 to fail completely and be unrecoverable without careful use of dialogs and task kills.
Also, Netscape 4 will completely fail to load if you attempt to use this method to create a
<div style="position:absolute"> and instead, you should use the unnofficial
<layer> tag. You can use if( document.layers ) to
detect if the layer tag should be used.
Writing functions
General syntax
- Pre-alpha versions of Tkhtml Hv3 do not correctly interpret the Function class constructor.
Functions group together script code; control structures, operations, method calls, etc. in the same way as a normal script. These functions can then be called when needed, and the code contained within them will be run. This makes it very easy to reuse code without having to repeat it within your script.
Functions are defined using one of these constructs:
- Normal function construct
function nameOfFunction(listOfVariableNames) { function code should be written here }- Anonymous function, assigned to a variable
- Using this syntax for object methods in early Netscape 4 versions will cause problems with the 'this' keyword due to bugs.
nameOfFunction = function (listOfVariableNames) { function code should be written here }; - Normal function construct, assigned to a variable
nameOfFunction = function anotherNameForTheFunction(listOfVariableNames) { function code should be written here };Note that in this particular case, because the function is being assigned, and not defined normally, the name anotherNameForTheFunction can be used by the code inside the function to refer to the function itself, but the code outside the function cannot see it at all (note that some browsers, mainly Internet Explorer, do not implement this correctly, so you should not rely on it - it is better to use arguments.callee as shown below).
- The Function class constructor
functionName = new Function("function code should be written here");This construct evaluates the code as a string, and is much slower than assigning anonymous functions. It should only be used in places where it is actually needed.
- The Function class constructor with parameters
functionName = new Function("varName","varName2","etc.","function code");
See the section on 'Referencing' subsection 'Avoiding referencing conflicts' to see how to choose names for your functions.
Functions are called using one of these:
nameOfFunction(listOfVariables);window.nameOfFunction(listOfVariables);object.onEventName = nameOfFunction;
When created using the normal function construct, the definition does not have to appear at the start of the script (though it is usually best to do so for the sake of clarity). It can even be defined after the the code that calls it. In most cases, no matter where you choose to define your function, the JavaScript engine will create the function at the start of the current scope.
Note that you should never create a function using the normal function construct inside an 'if' statement (or any equivalent control structure):
if( someCondition ) {
function functionName() {
...this will not work in most browsers...
}
}
This is permitted by Mozilla's JavaScript 1.5, but this conflicts with ECMAScript 3, the core language used by JavaScript 1.5. As a result, Mozilla based browsers allow it, and most others do not (they will always evaluate the function, even if the condition evaluates to false). It is best not to rely on either behaviour, and do not try to declare functions in this way. Declaring functions inside these statements is possible in all current browsers using assigned anonymous functions, and this is the correct way to achieve the desired effect:
var functionName;
if( someCondition ) {
functionName = function () {
...
};
}
Passing variables to functions
Variables passed to a function are known as arguments.
When a function is called, the variables or values passed to it in the brackets are assigned to the variable names in the brackets of the function definition.
function checkval(passvar) {
//if I ran the function using the command "checkval('hello')"
//then passvar would take on the value 'hello'
if( passvar != "" ) {
document.myform.mytextinput.value = passvar;
}
}
This function, when called, will set the value of a text input to whatever value of passvar was, as long as passvar was not blank.
As an example, part of my html will contain this:
<input type="button" onClick="checkval('pygmy')">
When the user clicks on the button, the text input's value will change to 'pygmy'.
You can pass more than one variable to a function using commas to separate the values:
function functionName(variable1,variable2,variable3,etc.) { function code }
functionName(5,6,7,etc.);
If not enough variables are passed to fill up all of the variables in the function declaration, then any remaining variables will contain the value undefined. You can pass no variables to a function like this
function functionName() { function code }
functionName();
If I called that last function using something like this:
functionName(1,2,3,myVar,window,'stringy bit')
The variables would still be passed to the function but I would only be able to access the variables using the arguments collection (which can also be referenced as referenceToFunction.arguments).
You can use the arguments collection to refer to the arguments, even if you did not write the variable name in the function definition, or you can mix it so that some variable names are defined but others are only available using the arguments collection:
function functionName(variable1,variable2) {
window.alert(variable1); //alerts 5
window.alert(arguments[0]); //alerts 5
window.alert(variable2); //alerts 6
window.alert(arguments[1]); //alerts 6
window.alert(arguments[2]); //alerts 7
window.alert(functionName.arguments[3]); //alerts 8
}
functionName(5,6,7,8);
The arguments collection also has a very useful property; arguments.callee. This is a reference to the function itself, meaning that code running inside an anonymous function can still obtain a reference to the function that is being run. This property is not available in some older browsers.
Using the return statement
The return statement causes a function to stop executing at that point. The code that called the function will still continue to execute.
function doWhatever() {
var apod = Math.pow(3,7);
return;
//the following code will not be executed,
//no matter what
apod *= 34;
if( 700 * 3 <= apod ) {
return;
//return on its own is more usually
//used as part of a conditional
} else {
window.alert('The script has made a mistake');
}
}
The following is an example of using the return statement to return a variable from a function:
function appendComment(passvar) {
//in this case, I have passed a string variable and I return
//a string variable. I could return any variable type I want.
passvar += ' without your help';
return passvar;
}
var myString = appendComment('I did it');
//myString is now 'I did it without your help'
Note that if you need your code to work in older browsers, it is important to make sure that if the return statement is used to return a value, you must ensure that in all cases, the function returns a value, or some Netscape 4 versions will produce errors.
Take, for example, the action of fading. I want to write the same thing repeatedly, slowly fading from one colour to another. Rather than having to calculate this manually, I want to run some script that calculates the fade for me. The script will run nicely as part of a function, where the function returns the next colour at each step, which I can then use. This is useful, because I can then use the same function to produce a variation of the same effect later on, based on different parameters.
function fadeColour( fromcol, tocol, fadePortion ) {
//in the format fadeColour( 'ff0098', 'fe0934', 0.23 )
var oF = [], oT = [], oP = [];
var oH = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
//get the red, green and blue substrings ...
for( var x = 0; x < 3; x++ ) {
//... and convert them from hex into decimal ...
oF[x] = eval( '0x' + fromcol.substring( 2 * x, ( 2 * x ) + 2 ) );
oT[x] = eval( '0x' + tocol.substring( 2 * x, ( 2 * x ) + 2 ) );
//... add on the required portion of difference between the two ...
oP[x] = Math.round( oF[x] + ( ( oT[x] - oF[x] ) * fadePortion ) );
//... and convert it back into hex ...
oP[x] = oH[ ( oP[x] - ( oP[x] % 16 ) ) / 16 ] + oH[ oP[x] % 16 ];
}
//... and put them back together again as a colour string
return '#' + oP.join('');
}
for( var y = 0; y < 10; y++ ) {
//in 10 steps, fade the colour - also see the section on writing with script
document.write( '<span style="color:' + fadeColour( 'd2cbff', '000099', y / 9 ) +
';">Fade!<\/span> ' );
}
for( var y = 0; y < 12; y++ ) {
//in 12 steps, fade the colour
document.write( '<span style="color:' + fadeColour( 'ff0000', '000000', y / 11 ) +
';">Fade!<\/span> ' );
}
Warning, if you are returning a value from a function, do not call the function directly from
the <a href= method to activate it, or many browsers will (correctly) create a new page containing
the returned value as the page content. You can still use return; on its own. You can only return
values if you call the function script from another piece of script (like another function).
If you need to call the function using the <a href= method, use the void operator.
Note, returning false for many events will cancel the action. As an example, if a user submits a form, returning false will cause the form not to be submitted. The exception is onmouseover, where returning true will stop the mouseover from having any effect (such as with a link, where returning true will stop the link url from being displayed in the status bar).
Variable scope
Variable scope is one of the very useful features of languages like JavaScript, so even though it may seem a little complicated, it is worth taking the time to learn how it works.
In a basic script, there may be any number of variables and functions. Take the following example:
var a = 1, b = 2, c = 3;
function sample() {
var d;
a = 7;
}
sample();
alert(a);
The variables a, b and c are not inside any function when they are declared, so they are in a scope called the global scope. They are available anywhere. Code anywhere else in the script, including inside the sample function, has access to them. The sample function is also global, since it is not inside any other functions. If any other piece of code changes the contents of those variables, then every other part of the code now sees the new contents. As a result, the alert here will show '7', since the value held by the global variable is changed when the function is run.
Variable d is defined inside the sample function, so it is not global. It is in the local scope of the function. What that means is that only the code inside the function can see it. Code outside the function does not even know it exists. This happens with any function. They have the ability to create their own scopes, and their own local variables, without them interfering with variables located in the global scope. Variable names written in the brackets of the function definition are also created as variables in the local scope (and the same applies to the arguments collection):
function sample(myvar) {
//myvar is now a variable in the local scope
alert(myvar);
}
sample('hello');
Now try this modification to the earlier code:
var a = 1, b = 2, c = 3;
function sample() {
var a, d;
a = 7;
}
sample();
alert(a);
Here, the variable a is redefined inside the function. Because it is declared using the var keyword, it becomes a local instance of a variable. Even though it shares the same name as a global variable, the two are completely independent. The changes made to that variable inside the function only affect the local variable, not the global one. As a result, the alert will show '1', and not '7'.
Now imagine that the code inside the function wants to reference the global variable 'a' instead of the local one.
The global scope is special. In JavaScript, the global scope can be referenced using the name 'window'. The code
inside the function can use window.a to reference the global 'a' variable. Incidentally, this is why
methods like alert can be called using either alert or window.alert, since these methods are
globally available (unless they are overwritten in the current scope, of course).
Nested functions
It is possible to create functions inside other functions. Simply declare another function inside the code of an existing function:
var a = 1, b = 2, c = 3;
function sample() {
var a, d, e;
function anothersample() {
var e, f;
}
anothersample();
}
sample();
In that example, the anothersample function only exists inside the sample function, and it can only be called by the code inside the sample function. Code outside that function does not even know it exists. The scopes are also nested, so the code inside the anothersample function has access to b and c from the global scope, a and d from the sample scope, and then e and f from its own local scope. It can also use window.a to reference the variable a from the global scope.
Of course, if you assign a reference to the nested function to a global variable, then the function can be accessed globally through that variable. There is not much point in doing that here, but it becomes very useful when creating object methods (these will be covered in detail in a later chapter).
Scopes have memory
Scopes are actually very clever, since they persist over time. Imagine that the code inside a function creates a local variable. It also creates an event handler function that will be triggered when the user clicks a link:
function sample() {
var a = 20;
document.links[0].onclick = function () {
alert(a);
};
}
sample();
The action that calls the event handler (inner) function happens much later, a long time after the script that created it has finished running. However, the variable 'a' has survived, so the alert will display the number 20.
Using scope to prevent conflicts
Imagine that you are running a script that uses many global variable and function names. You want to put another script on the same page, but there is a chance that the two scripts will use the same variable names as each other, and may conflict. It is easy to workaround this problem by putting the code from each script inside a function, and running the function. That way, the local scope provided by the function will protect the variables overwriting each other in the global scope. Note that when doing this, it is very important that you remember to declare your variables properly.
The easy way to do this without creating a global function is to create an anonymous function, and enclosing it in parenthesis (internally, the engine will then replace that entire construct with the function reference). You can then use the open-close parenthesis to run it immediately. This construct may look a little odd, but it works:
(function () {
//Put your script code in here
})();
Using nested function scope to preserve instantaneous values
This is an advanced topic that is covered in its own article.
Referencing
How browsers affect it
Referencing is, in my experience, the hardest thing to learn to get right. It is not helped by the fact that the methods required may be different in different browsers and so you have to include several different versions of the code to ensure it will work in all of them. I have put together a list of the most popular browsers available that support JavaScript.
Opera and Mozilla currently have the highest level of JavaScript support, but many scripts are poorly written, and are based on the implementation of just a few browsers, typically just Internet Explorer and one other browser. Unfortunately, Internet Explorer does not have a very good JavaScript implementation. It often does not comply with the standards, relying instead on authors to use its non-standard extensions. Many authors do not realise these are non-standard, and end up writing code that relies on these extensions. Other browsers may implement some of these extensions in an attempt to get these scripts to work.
What I have done in this tutorial is to carefully test the responses of as many different browser engines as I could, and put together something that works in as many of them as possible. Where possible, I will rely on the standards compliant version, and only fall back to the alternatives if a standards compliant technique cannot be used.
Object hierarchy
To reference items (objects) on the page, refer to an object structure or hierarchy. The topmost object is usually 'document' and the next will be different depending on the document structure. Most elements (HTML tags) cannot be referenced in all 4th generation browsers. Those that can are:
- body, referred to as document
- div, referred to using browser specific references, targetting its id
- span, referred to using browser specific references, targetting its id (it is best not to reference this for 4th generation DHTML as layers browsers have bugs that will show up if you do)
- img, referred to through the document object targetting its name
- a, referred to through the document object targetting its index
- form, referred to through the document object targetting its name
- input, select or textarea, referred to through the form targetting its name
In most browsers, these components will be available to scripts immediately after they have been written. If being
written by script, they should be available immediately, but in some older browsers they may not be available until
that script has completed executing (after the </script> tag).
In some more poorly written old browsers, these document components will only be available after the document has loaded.
You can detect when the document has loaded using the window.onload event (which can also be written in HTML as
<body onload= ...). Strangely, Gecko browsers (Mozilla/Firefox/Netscape 6+) will need at least one non-entity character to be written
between the element's opening tag and the script, even if the element is an image, or the element will not be available
to script until after the page loads.
There are a few others elements that can be referenced. For a full list of objects, properties, collections and methods, refer to the section on The JavaScript object.
I have written a generic referencing function that can be used to reference all document components that can be referenced (except links), but I suggest you work through the next few sections of the tutorial first instead of taking a shortcut. You might actually understand what I am doing, instead of blindly using my code without knowing how it works.
Avoiding referencing conflicts
Remember that all names in JavaScript are case sensitive. Names must begin with a-z or A-Z or _ and may only contain the characters a-z, A-Z, 0-9 and _. The convention is to use names that describe the object. If the name is made up of more than one word, there should never be a space between the words and it is not usual to have an underscore ( _ ) between the words. The usual practice is to capitalise the first letter of all words except the first.
For example, I have a variable that I will be using to store some text about me. I decide the best name is 'text about me' and I must remove the spaces and capitalise the first letters of all words except the first. Therefore, the variable name becomes 'textAboutMe'.
In order to avoid referencing conflicts, you must make sure that no two JavaScript objects or document elements are given the same name (except inputs - see the next section).
When choosing names for variables, functions and both names and IDs of HTML elements, there is a set of reserved words which you must not use, regardless of the case. These are: abstract, arguments, boolean, break, byte, case, catch, char, class, const, continue, debugger, default, delete, do, double, else, enum, export, extends, false, final, finally, float, for, function, goto, if, implements, import, in, instanceof, int, interface, long, native, new, null, package, private, protected, public, return, short, static, super, switch, synchronized, this, throw, throws, transient, true, try, typeof, var, void, volatile, while, with.
In addition, it is generally a good idea not to use names that conflict with the names of existing properties or methods of the global/window object (unless you really want to overwrite them). See the section on The JavaScript object for more details.
Browser inspecific referencing
Note that to avoid referencing problems, no two elements should EVER be given the same name or id. The only exception is form inputs which can share names.
Global references
Variables are referenced simply by typing their name, or by using window.variableName.
Functions are referenced simply by typing their name, or by using window.functionName.
'window' (or 'self') may be used to reference the global object for the current document,
regardless of what scope your script is running in. If your script is running in another script and you are
having trouble referencing global variables because a local variable uses the same name, this problem
can be quickly solved by adding 'window.' to the start of the variable name. For example window.myvariable
By a similar nature, you can use 'this' to represent the current object. By default, 'this' will be the window object. If you are writing the script as part of a HTML event handler, 'this' will be the element that detected the event. For example, this can be used to alert the value of the text input:
function myFunction(x) { window.alert(x.value); }
...
<input type="text" onkeypress="myFunction(this)">
Using this same function from a script running in the global scope, the word 'this' refers to the window object. The window object does not have a value property, so the function would alert 'undefined'.
However, if the onkeypress method is activated manually, the word 'this' once again refers to the input, so the function will alert the value of the input:
document.forms[0].elements[0].onkeypress();
Frameset references
There are four very useful references that refer to parts of a frameset. These are 'window' or 'self', 'window.parent', 'window.top' (window is usually omitted) and the window.frames collection.
- self and window
- These refer to the global object of current web page.
- parent
- Refers to the window object of the page that is holding the current page in a frameset.
- top
- Refers to the window object of the page at the top of the frames hierarchy.
- window.frames[nameOrNumberOfFrame]
- Refers to a frame or iframe held by the current page.
With iframes (if the browser supports them) you have to use the extra word 'window' on the end to reference the window object of the document contained by the iframe (there are alternatives, but this one works in all browsers that support iframes, making it superior to all other techniques, since they only work in a selection of browsers):
window.frames[nameOrNumberOfFrame].window
If the page is the only page being displayed, top, parent, self and window will be equal. If the page is being held within a frameset, self and top will not be equal. If the page is the page containing the frameset, and it itself is not being held within a frameset, self and top will be equal. If someone is loading your page into their frameset and you don't want them to, you can use the self-top relationship to remove your page from their frameset and replace their frameset page with your page using:
if( self != top ) { top.location.replace(self.location.href); }
Note, I could have used this:
if( self != top ) { top.location.href = self.location.href; }
However, that makes the browser add the new entry into its history, so if they clicked their back button, they would be forwarded back to your page again. Unfortunately, Gecko browsers (Mozilla/Firefox/Netscape 6+) will only allow the second option as they have very high security levels relating to cross-site scripts.
Note that using scripts to force pages in and out of framesets is a very bad idea. It causes usability problems for many users, breaks search engines, and annoys your visitors. I know you know how to do it, but that does not mean that you should.
With all frames, the name is set using the name="nameOfFrame" attribute in the
<frame ...> tag. The number is automatically generated by the browser in the order that the frames
are defined in the HTML, beginning at 0.
To fully reference the window object of another frame when inside a frameset, use one of these:
- parent.frames.otherframename
- parent.frames['otherframename']
- parent.frames[2] (assuming 2 is the index of the frame)
- parent.otherframename
From there, you can reference items inside that document using document.whatever
parent.frames['otherframename'].document.images['imagename'].src = "sample.gif";
Take, for example, the following frame page structure. The main page - main.html - (which by default has no name, although it can be set with JavaScript, or by opening the page with target="newName") contains two frames; 'left' and 'right'. 'left' contains the page 'links.html'. 'right' contains a page - inner.html - containing a further two frames; 'banner' and 'mainpart'. The locations of 'banner' and 'mainpart' are upper.html and lower.html respectively. The names of the files are irrelevant, but it helps me to explain the structure to you. This produces the following frame tree structure:
unnamed frame (main.html)
____________|____________
| |
left (links.html) right (inner.html)
__________|______________
| |
banner (upper.html) mainpart (lower.html)
The following examples use the frames collection, although any of the above syntaxes would be fine.
If a script were running in main.html, it would be able to reference the window and document objects of lower.html using this:
window.frames['right'].frames['mainpart']
window.frames['right'].frames['mainpart'].document
If a script were running in lower.html, it would be able to reference the window object of links.html using either of these:
window.parent.parent.frames['left']
window.top.frames['left']
Attempting to access the contents of a frame before they have loaded will cause an error. In all browsers, the window object will not exist for that frame unless the page has loaded.
if( !window.frames['nameOfFrame'] ) { window.alert( 'Frame has not loaded' ); }
This algorithm also works with iframes, without requiring any changes.
Forms
Note that this changes in Netscape 4 and other layers browsers if the form is put inside a positioned element. See the section on Element contents for more details.
To fully reference a form, use document.formname for a form that was defined with the
name="nameOfForm" attribute in the <form ...> tag, or
document.forms[number_of_form] either should work. The number is generated automatically by the browser in
the order that the forms are defined in the HTML, beginning at 0.
To fully reference an input, use any of these:
reference_to_form.inputname
reference_to_form.elements['inputname']
reference_to_form.elements[number_of_input_(not_image_input)]
Name is defined using the name="nameOfInput" attribute in the <input ...>,
<textarea ...>, <button ...> or <select ...> tags.
Number is generated automatically by the browser in the order that the inputs are defined in the HTML, beginning at 0.
You can read or write the value of text inputs and textareas with their 'value' property. See the section on The JavaScript object for a full list of what parts of a form can be read or changed.
If more than one input of any kind in the same form share the same name (as is common with radio button inputs), they must be referenced using the numerical array associated with that name. The array will contain an entry for each input with that name, in ascending order of how they appear in the source of the document, beginning at 0. For example, if a radio button has the name 'mybutton', it can be referenced using this:
document.nameOfForm.mybutton
But if two radio buttons share the name 'mybutton', the second button (for example) can be referenced using this:
document.nameOfForm.mybutton[1]
This will be the case for any input type, even if inputs of different types share the same name. In practice, radio buttons will almost always share a name, and checkboxes may occasionally share a name. Even if inputs share a name, they will still have individual entries in the elements collection.
For select boxes, each individual option can be referenced using
input_name.options[number_of_option]. For example:
if( document.myForm.mySelect.selectedIndex == 1 ) {
document.myForm.mySelect.options[3].selected = true;
if( !document.myForm.myRadio[1].checked ) {
document.myForm.myRadio[2].checked = false;
document.myForm.myRadio[1].checked = true;
document.myForm.myRadio[0].checked = false;
}
}
You can reference the value of an option tag with '.value' and the text it displays with '.text'. You can also find out how many options there are by using the '.length' property of the options collection.
Note, setting a select option to null will remove it from the select box:
document.forms[number_of_form].mySelect.options[0] = null;
All other options will have their index numbers adjusted to reflect this change. To add or replace one, use this:
document.forms[number_of_form].mySelect.options[number] = new Option('text','value');
Most commonly, number used is the length of the collection, as that will add the new option onto the end:
document.forms[number_of_form].mySelect.options.length
Warning: although the selectInputObject.selectedIndex property should be read-write, it is read-only in Internet Explorer 4. If this causes problems, you car use this:
selectInputObject.options[index].selected = true;
Images
Note that this changes in Netscape 4 and other layers browsers if the form is put inside a positioned element. See the section on