<html>
<head>
<title>Control Statements</title>
</head>
<body>
<!-- this uses old style page creation
and should be avoided -->
<script type="text/javascript">
document.writeln("<pre>")
var i
for( i = 0 ; i < 10; i++ ) {
document.writeln(i, " ", 2*i, ' ', Math.pow(2,i) )
}
document.writeln("</pre>")
</script>
</body>
</html>
While this page and the next set demonstrate features of Javascript,
they are not good examples of production quality Javascript code.
In general, most Javascript code should only appear in the
head element. Also, these examples are not proper XHTML.
all control statements
Javascript supports the following control structures:
S
if ( C ) S
if ( C ) S else S
while ( C ) S
for ( init; C; incr ) S
do S while ( C )
switch ( E ) { case E1: S... case E2: S... default: ...}
break, break label
continue, continue label
return
E(args...)
{ S1; S2... }
throw
try S catch ( V ) S
data types
Javascript supports the following data types:
numbers
represented by floating point, but integer operations are defined,
strings
an immutable sequence of Unicode characters, the
length of the string is given by the length attribute,
boolean
the result of relation operator can be true or false,
boolean can be convert to numbers, true = 1, false = 0,
functions
functions can be created, assigned and passed as arguments,
objects
an object is a collection of named values,
arrays
an array is a collection of values accessed by
indexes starting at 0, an array entry can
store any value (e.g., number, function, object, arrays).
null
stands for an empty value,
undefined
any variable that has not been assigned a value has
the undefined value,
regular expressions
regular expressions are used to match patterns in text
Expression evaluation
Evaluating the following javascript expressions
yields the following results.
Expression
Value
a list of colours
Produces a list of colours and demonstrates arrays.
Functions are created with function name
( args..) { body } .
Single or double quotes can be used to define strings.
Scripts are evaluated while the HTML pages is being rendered.
array methods
The array in Javascript is similar to the array in Perl.
Some of the operations and attributes supported by an array are:
length
the number of elements in the array; writable.
concat(value, ...)
Append the arguments to the end of the array.
The elements of an array are appended, and a different new array is returned.
join(str)
produce a string where all the elements are converted
to strings and joined with copies of str; default delimiter is ","
pop()
remove and return the last element
push(e)
append e to the end
reverse()
reverse the array in place
shift()
remove and return the first element of the array
slice(start, end)
return a subarray from start up to end (the last element is
just before end)
sort(), sort( compare )
sort the array in ascending order
splice(start, deleteCount, value, ... )
Delete the deleteCount elements from the array,
and insert the arguments starting with value in
the array starting at index. The deleted elements
are returned.
unshift(e)
insert e at the front of the array
Experimenting with arrays
An example session that experiments with arrays is:
Expression
Value
generate a month calendar
The following Javascript computes a monthly calendar.
The function monthCalendar does
the calculations, and the function genCalendar
produce a HTML table containing the calendar for a month.
/* * calcuate the number of days in the month. */function daysInMonth( year, month ) { var d = daysInMonth.days[ month ] if ( month != 1 ) return d if ( (year % 4) != 0 ) return d if ( (year % 400) == 0 ) return d+1 if ( (year % 100) == 0 ) return d return d+1}daysInMonth.days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]/* * Return an array of weeks, each week is an array of dates */function monthCalendar( year, month ) { var d = new Date( year, month, 1 ) var first = d.getDay() // 0:Sun .. 6:Sat var w = [] // add empty days for first week var date = 1 for(i = 0; i < 7; i++ ) w.push( i < first ? null : date++ ) var cal = []; var noDays = daysInMonth( year, month ) var offset = first-1 while ( date <= noDays ) { if ( ((date+offset) % 7) == 0 ) { cal.push( w ) w = [] } w.push( date++ ) } // finish week if ( w.length > 0 ) { for( i = w.length; i < 7; i++ ) w.push( null ) cal.push( w ) } return cal}function genCalendar( doc, year, month ) { var cal = monthCalendar( year, month ) var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ] cal.unshift( dayName ) // add headers doc.writeln("<table class='calendar'>") var i for( weeks = 0 ; weeks < cal.length ; weeks++ ) { var week = cal[weeks] doc.write("<tr>") for( d = 0 ; d < 7 ; d++ ) { doc.write("<td>") var s = week[d] if ( s == null ) s = ' ' doc.write( s ) doc.write("</td>") } doc.writeln("</tr>") } doc.writeln("</table>")}
calendar demo
The monthCalendar function can be used
to create calendars.
The concat, splice, and slice are also useful methods.
Expression
Value
string method
The string, String object, in Javascript has similar methods
as Java. Some of the methods and attributes are:
length
number of characters
charAt(index)
return the char at index (e.g., str.charAt(1) ),
there are no character is Javascript, thus
a string of length one is returned
concat(args, ...)
return the concatenated strings (e.g., str.concat('foo')
returns the concatenation of str with 'foo')
replace(regexp,replace)
replace the regexp in str with replace
split(delimiter, limit)
split the string in up to limit substrings by the delimiter, returning array.
substr(start, length)
returns the substring at the start index of the given length
search(regexp)
return the index of the substring that matches the regexp,
return -1 if there is no match
escape(str)
return an string using the URL encoding
unescape(str)
return a string where the URL encoding is reversed
String experiments
A session with string experiments is:
Expression
Value
objects in Javascript
An object is created with new Object().
Objects store properties and values.
Objects can be implemented with hash tables.
Some operations on objects are demonstrated by:
Expression
Value
The method, hasOwnProperty( name ), checks
if an object has the named property.
A new property and value is added to the object with:
obj.property = value
or
obj[property-as-string] = value
Values are retrieved with:
obj.property or
obj[property-as-string]
The listable properties of an object are listed with
str='';
for(a in o) str += 'o.' + a + '=' + o[a] + ' ';
str
Function experiments
Functions can be created, called, passed as arguments,
and return after being created.
Functions are objects in JavaScript.
Expression
Value
closure
A closure is created when a function is defined inside of
an outer function, and that inner function is returned
from the outer function. All of the variables defined
in the outer function are accessible from the inner function.
When the inner function is called, the values of the variables
defined in that outer function assume that same values
as when the inner function was returned.
For example:
function mkSubstitue( x, y ) { return function( s ) { return s.replace(new RegExp(x,"g"), y ); };}sub1 = mkSubstitue( "cat", "dog" )sub1("the cat is an old cat" )sub2 = mkSubstitue( "red", "blue" )sub2("the red car is reduced" )
The mkSubstitue(x,y) function returns
a function that substitutes all occurrences of x with y.
sub1 replaces all occurrences of
cat with dog.
sub2 replaces all occurrences of
red with blue.
In sub1, x is 'cat'
and y is 'dog'.
In sub2, x is 'red'
and y is 'blue'.
<html>
<head>
<title>Replace</title>
<style>
button { color: white; border: thin solid red; background: gray; }
textarea { background:#AFF; border: thick dotted blue; }
input[type="text"] { background:#FFA; border: thin red dashed; }
</style>
<script type="text/javascript">
function doReplace( evt ) {
var form = evt.target.form
var s = form.search.value
var r = form.replace.value
var re = new RegExp( s, "g")
form.text.value = form.text.value.replace(re, r )
}
function doAdd( evt ) {
var form = evt.target.form
var div = document.getElementById('add-dest')
var p = "<p>" + form.text.value + "</p>"
div.innerHTML = p + div.innerHTML
}
function initForms() {
var form = document.getElementById('theform')
form.doReplace.onclick = doReplace;
form.doAdd.onclick = doAdd;
}
</script>
</head>
<body onload="initForms()">
<form action="javascript:void 1" name="theform" id="theform">
<button name="doReplace">replace</button>
<input type="text" size="10" name="search">
<input type="text" size="10" name="replace">
<button name="doAdd">add</button>
<br>
<textarea wrap="nowrap" rows="10" cols="40" name="text">
Some random text
that will be modified by the
search and replace function.
0 1 2 3 4 5 6 7 8 9
</textarea>
</form>
<div id="add-dest">
</div>
</body>
</html>
The name of the form becomes a global variable.
The name of every input element in the form becomes
a property (attribute) of form object. The form object
is accessed by the global variable.
The g option to RegExp object
replaces every occurrence of the search pattern with the
replace text.
A new paragraph is added to the page with the
contents of the text area when the add button
is clicked. The innerHTML property
can be used to retrieve or replace the HTML
contents of an element.
It is good practise to separate the form description
from the registering of the event handlers.
The initForms attached the event handlers
to the form.
getting elements, setting event handlers
Once an element is retrieved, it can be treated as a Javascript
object and manipulated by adjusting its properties.
The document property is provided
to any Javascript code to access the web page's document.
An element is retrieved by:
var elem = document.getElementById( id )
The initForms function is invoked
when the web pages is loaded, it then gets the
element with the attribute id="theForm".
function initForms() { var form = document.getElementById('theform') form.doReplace.onclick = doReplace; form.doAdd.onclick = doAdd;}
All of the input elements inside of the form are accessible
as properties of the form object. The name
attribute of the input element becomes the property
name in the form object.
The button elements:
are accessed with form.doReplace and
form.doAdd. To attach the onclick
event handler, a handler function is assigned to the
onclick property of a button object.
Modifying content
The innerHTML property of a document element
can be used to retrieve or modify the HTML contained in the element.
Content from the form is added to the web page with:
function doAdd( evt ) { var form = evt.target.form var div = document.getElementById('add-dest') var p = "<p>" + form.text.value + "</p>" div.innerHTML = p + div.innerHTML}
In Mozilla, all event handlers are given an event
object. The target property references the
object that caused the event. In this case, it is
clicking on the doAdd button. The form
attribute of the button object is the form containing the button.
The text in the textarea object in the form is accessed with
form.text.value. The last line updates
the HTML content of the div element with the add-dest id.
CSS and Javascript formatting
Every element in a HTML document is also a Javascript object.
Most elements have a style property that contains
the CSS properties. The background colour can be set with
element.style.background. The foreground colour
is controlled by the value of element.style.color.
Multiple word CSS properties (words separated by hyphens) are converted
to Javascript identifiers where the individual words are capitalized.
The CCS property font-family is
fontFamily.
The border-left-width property is accessed with
borderLeftWidth in Javascript.
CSS for formatting examples
The style sheet specifies the appearance of the formatting
controls on the page.
var formatElement // initially undefinedfunction getFE() { if ( formatElement ) return formatElement formatElement = document.getElementById('format-area' ) return formatElement}function setColour( colour ) { var e = getFE() e.style.color = colour}function setBackgroundColour( colour ) { var e = getFE() e.style.background = colour}function setFont( font ) { var e = getFE() e.style.fontFamily = font}function setFontSize( size ) { var e = getFE() e.style.fontSize = size}
Each handler function is called with the new value
of the CSS property.
There is a standard mapping between the Javascript
property names and the associated CSS property name.
Any hyphens are deleted, and the letter after the
hyphen is capitalized.
<html>
<head>
<title>Text Formating</title>
<link rel="stylesheet" type="text/css" href="text-formatting.css">
<script type="text/javascript" src="text-formatting.js">
</script>
</head>
<body>
<div class="controls">
<label>Colour:
<select id="sel-colour" onchange="setColour(this.value)">
<option>inherit</option>
<option>aqua</option> <option>black</option>
<option>blue</option> <option>fuchsia</option>
<option>gray</option> <option>green</option>
<option>lime</option> <option>maroon</option>
<option>navy</option> <option>olive</option>
<option>orange</option> <option>purple</option>
<option>red</option> <option>silver</option>
<option>teal</option> <option>white</option>
<option>yellow</option>
</select>
</label>
<label>Background:
<select id="sel-bg-colour" onchange="setBackgroundColour(this.value)">
<option>inherit</option>
<option>aqua</option> <option>black</option>
<option>blue</option> <option>fuchsia</option>
<option>gray</option> <option>green</option>
<option>lime</option> <option>maroon</option>
<option>navy</option> <option>olive</option>
<option>orange</option> <option>purple</option>
<option>red</option> <option>silver</option>
<option>teal</option> <option>white</option>
<option>yellow</option>
</select>
</label>
<label>Font:
<select id="sel-font" onchange="setFont(this.value)">
<option>inherit</option>
<option>monospace</option>
<option>serif</option>
<option>sans-serif</option>
</select>
</label>
<label>Size:
<select id="sel-font-size" onchange="setFontSize(this.value)">
<option>inherit</option>
<option>0.7em</option>
<option>0.8em</option>
<option>1.2em</option>
<option>1.5em</option>
<option>7pt</option>
<option>8pt</option>
<option>9pt</option>
<option>10pt</option>
<option>11pt</option>
<option>12pt</option>
<option>13pt</option>
<option>14pt</option>
<option>16pt</option>
<option>18pt</option>
<option>20pt</option>
</select>
</label>
</div>
<div id="format-area">
<p>
Every element in a HTML document is also a Javascript object.
Most elements have a <em>style</em> property that contains
the CSS properties. The background colour can be set with
<code class="jss">element.style.background</code>. The foreground colour
is controlled by the value of <code class="jss">element.style.color</code>.
</p>
<p>
Multiple word CSS properties (words separated by hyphens) are converted
to Javascript identifiers where the individual words are capitalized.
The CCS property <code class="css">font-family</code> is
<code class="jss">fontFamily</code>.
The <code class="css">border-left-width</code> property is accessed with
<code class="jss">borderLeftWidth</code> in Javascript.
</p>
</div>
</body>
</html>
The event handler is set with the:
onchange="setFont(this.value)"
in the select element. The this
variable reference the select element. The value
property give the text of the currently selected option.
Note, the setting of event handler should not be done
in the select element.
The value property of a select
element is the value of the currently selected option.
The value property of a text input
is the contents of the text field.
The value property of a textarea
is the contents of the text area.
The arena containing the bouncing text is defined by
an div element with a class of arena.
A padding of 0em allows the text to touch
the borders. The border style makes the border visible.
Finally the size of the arena is given by the width and height.
The span element inside the div become the bouncing text.
A position style of absolute places the text relative
to the containing div. The actually placement is controlled
by the top and left styles.
The white-space style of nowrap ensures that the text
will not be wrapped.
/* * constructs a BounceText object, which manages the * movement (bouncing). */function BounceText( e, a ) { this.arena = a this.element = e this.x = e.offsetLeft // offset from left edge of e this.y = e.offsetTop // offset from top edge of e /* * Reduce the width and height of the arena * ensures that the text box will not go outside * of the arena. */ this.w = a.offsetWidth - e.offsetWidth this.h = a.offsetHeight - e.offsetHeight /* defines the movement vector. */ this.dx = Math.random()*20 - 10 this.dy = Math.random()*20 - 10}/* * performs the movement. */BounceText.prototype.update = function() { this.x += this.dx if ( this.x < 0 ) { this.x -= this.dx this.dx = Math.random()*10 + 5 } else if ( this.x > this.w ) { this.x -= this.dx this.dx = -(Math.random()*10 + 5) } this.y += this.dy if ( this.y < 0 ) { this.y -= this.dy this.dy = Math.random()*10 + 5 } else if ( this.y > this.h ) { this.y -= this.dy this.dy = -(Math.random()*10 + 5 ) } this.element.style.left = this.x.toString() this.element.style.top = this.y.toString()}/* * bouncing contains all the BounceText objects. * doAnaimation() is invoked 10 times a second * to update the postions of the text elements. */var bouncing = []function doAnaimation() { var i for( i = 0 ; i < bouncing.length; i++ ) { bouncing[i].update() }}/* * Creates the BounceText objects from * the web pages's document. * Invoked when the web page is loaded by the onload event. */function startAnimation() { var i,j var arenas = document.getElementsByTagName( "div" ); for( i = 0 ; i < arenas.length; i++ ) { var cl = arenas[i].getAttribute("class") if ( cl == null || cl.search("arena") == -1 ) continue; var spans = arenas[i].getElementsByTagName( "span" ); for( j = 0 ; j < spans.length; j++ ) { spans[j].style.top = 10*j + 'mm' spans[j].style.left = 20*j + 'mm' bouncing.push( new BounceText(spans[j], arenas[i] ) ) } } // doAnaimation() will be invoked every 100ms setInterval("doAnaimation()", 100 )}
bouncing text
A BounceText object is created to manage
the movement (bouncing) of the span element containing the text.
This object contains the following properties:
x - the left position of the span
y - the top position of the span
w - the width in pixel of the arena - span
h - the height in pixel of the arena - span
dx - the amount to move the text horizontally when updated
dy - the amount to move the text vertically when updated
In Javascript, a normal function is turned into
a constructor function with the new keyword.
A BounceText object is created with:
var bt = new BounceText( span, arena )
where span is the span element, and arena is the
div element.
constructor experiments
Objects whose properties are initially identical
are created with constructor functions. Some experiments are:
Expression
Value
Inheritance in Javascript
The prototype property is used to implement
a form of inheritance. If a property is not found
in an object, then the prototype of its constructor is searched for
the property. All of the properties in prototype
are inherited by the object.
Methods of the object are usually placed in the
prototype object.
The BounceText.prototype object contains
the update function. This function
repositions the text element when invoked
by modifying the style values.
build BounceText objects
All of the elements in the document with the given
tag name can be retrieved with:
var list = document.getElementsByTagName( tagname )
list is an array.
The div elements can be gotten with:
var arenas = document.getElementsByTagName( "div" )
An attribute of an element is returned with the
getAttribute( name ) function.
In the bouncing example, only div element with
a class attribute of "arena" need to be examined.
Any other div elements can be skipped with:
var cl = arenas[i].getAttribute("class")
if ( cl == null || cl.search("arena") == -1 ) continue;
All the span elements are accessed with:
var spans = arenas[i].getElementsByTagName( "span" );
Note that the getElementsByTagName
can be applied to any element, not just the document.
list with hidden items
Collapsing lists are common interface elements on web
pages. The list can be created using a combination
of Javascript and CSS.
/* * Set the display to none for all the UL children. */function display( li ) { var children = li.childNodes var i for( i = 0 ; i < children.length; i++ ) { if ( children[i].tagName == 'UL') { children[i].style.display = 'none' } }}/* * Set the display to block for all the UL children. */function undisplay( li ) { var children = li.childNodes var i for( i = 0 ; i < children.length; i++ ) { if ( children[i].tagName == 'UL') { children[i].style.display = 'block' } }}/* * Handle click on a list item, by displaying or hiding * any children. Change the marker to indicate if any * children are possible hiden. */function toggle( evt ) { // not interested in other phases if ( evt.eventPhase != Event.AT_TARGET ) return var elem = evt.target var liStyle = elem.style if( ! liStyle.listStyleImage || liStyle.listStyleImage.search('plus') != -1 ) { undisplay( elem ) elem.style.listStyleImage = 'url(minus.png)' } else { display( elem ) elem.style.listStyleImage = 'url(plus.png)' }}/* * Set the event handler on all the list items * with a ul parent with a class="tree". */function initTree() { var lis = document.getElementsByTagName('li'); var i for( i = 0; i < lis.length; i++ ) { var parent = lis[i].parentNode var pClass = parent.getAttribute('class') if ( pClass != null && pClass.search('tree') != -1 ) { lis[i].onclick = toggle } }}
The childNodes returns an
array of the elements children.
This includes text and other elements.
The parentNode returns
the parent of the element.
The style.listStyleImage property
controls the list item's marker.
make a calendar
A calendar can be generated from a form on
the web page. This allows the user to create
their our calendar.
/* * calcuate the number of days in the month. */function daysInMonth( year, month ) { var d = daysInMonth.days[ month ] if ( month != 1 ) return d if ( (year % 4) != 0 ) return d if ( (year % 400) == 0 ) return d+1 if ( (year % 100) == 0 ) return d return d+1}daysInMonth.days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]/* * Return an array of weeks, each week is an array of dates */function monthCalendar( year, month ) { var d = new Date( year, month, 1 ) var first = d.getDay() // 0:Sun .. 6:Sat var w = [] // add empty days for first week var date = 1 for(i = 0; i < 7; i++ ) w.push( i < first ? null : date++ ) var cal = []; var noDays = daysInMonth( year, month ) var offset = first-1 while ( date <= noDays ) { if ( ((date+offset) % 7) == 0 ) { cal.push( w ) w = [] } w.push( date++ ) } // finish week if ( w.length > 0 ) { for( i = w.length; i < 7; i++ ) w.push( null ) cal.push( w ) } return cal}function genCalendar( doc, year, month, id ) { var html = '' var cal = monthCalendar( year, month ) var dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ] cal.unshift( dayName ) // add headers html += "<table class='calendar'>" var i for( weeks = 0 ; weeks < cal.length ; weeks++ ) { var week = cal[weeks] html += "<tr>" for( d = 0 ; d < 7 ; d++ ) { html += "<td>" var s = week[d] if ( s == null ) s = ' ' html += s html += "</td>" } html += "</tr>" } html += "</table>" var elem = document.getElementById( id ) elem.innerHTML = html}
Once a document is loaded, the document.write
function can no longer be used to modify the page.
Instead, the DOM (Document Object Model) must be used to
make changes.
Window object
Every window and frame has a Window object
that can be used to control behaviour of that window.
The Window object contains all the top
level properties (i.e., where the global variables are accessed).
This object has different properties for different browsers.
Some of the main common properties are:
document
read-only reference to HTMLDocument object of the currently loaded document
history
reference to History object which contains previously viewed documents.
It supports forward(), back(), and go( )
location
the URL of the current document.
It can be used to load a new document by assigning a value to it.
Note that its replace() method does not create a history record.
Math
reference to Math object
status
change the contents of status bar, "turned off in firefox"
screen
reference to Screen object, information of screen size
navigator
general information about the browser
Window demo
ping.html demonstrates use of
the window.location and window.status.
<html>
<head>
<title>Pong</title>
<script type="text/javascript">
function dumpScreen() {
var d = ""
for( a in screen ) {
d += 'screen.' + a + ' = ' + screen[a] + '\n'
}
alert( d )
}
</script>
</head>
<body>
<button onclick='document.location.replace("ping.html")'>
Go to Ping Document
</button> <br>
<button onclick='dumpScreen()'>
dump screen
</button> <br>
<button onclick='history.back()'>
back in history
</button>
</body>
</html>
common Window object methods
Some of the common methods defined for the Window object are:
alert(str)
displays a dialog box with str
clearInterval( intervalID )
clears an interval returned by setInterval
clearTimeout( timeoutID )
cancels a timeout function returned by setTimeout
close()
closes the window
open( url, name, features, replace )
opens new window or replaces the contents of named window
setInterval(str, time)
javascript in str is evaluated at the given interval in milliseconds
setTimeout(str, time)
javascript in str is evaluated at end of timeout period
Document Object
Most of the dynamic content on a web page is controlled
by the document object. Some of the main DOM 0 properties are:
applets
array of all applets on the page
forms
array of all forms on the page
images
array of all images on the page
links
array of all links on the page
URL
url of document
cookie
string of cookies for this page
Some of the main DOM0 methods are:
close()
close a document opened with open, no more writes
open()
clears a document to be rewritten
write( str ), writeln(str)
write the str to the document, interpreted as HTML