Web Programming Step by Step, 2nd Edition

Lecture 15: Unobtrusive JavaScript

Reading: 8.2.10, 8.4–8.5; 9.1–9.1.2, 9.2.3

Except where otherwise noted, the contents of this document are Copyright 2012 Marty Stepp, Jessica Miller, and Victoria Kirst. All rights reserved. Any redistribution, reproduction, transmission, or storage of part or all of the contents in any form is prohibited without the author's expressed written permission.

Valid HTML5 Valid CSS

8.4: Advanced JavaScript Syntax

Arrays

var name = [];                          // empty array
var name = [value, value, ..., value];   // pre-filled
name[index] = value;                     // store element
var ducks = ["Huey", "Dewey", "Louie"];

var stooges = [];        // stooges.length is 0
stooges[0] = "Larry";    // stooges.length is 1
stooges[1] = "Moe";      // stooges.length is 2
stooges[4] = "Curly";    // stooges.length is 5
stooges[4] = "Shemp";    // stooges.length is 5

Array methods

var a = ["Stef", "Jason"];   // Stef, Jason
a.push("Brian");             // Stef, Jason, Brian
a.unshift("Kelly");          // Kelly, Stef, Jason, Brian
a.pop();                     // Kelly, Stef, Jason
a.shift();                   // Stef, Jason
a.sort();                    // Jason, Stef

Splitting strings: split and join

var s = "the quick brown fox";
var a = s.split(" ");          // ["the", "quick", "brown", "fox"]
a.reverse();                   // ["fox", "brown", "quick", "the"]
s = a.join("!");               // "fox!brown!quick!the"

Special values: null and undefined

var ned = null;
var benson = 9;
var caroline;

// at this point in the code,
//   ned is null
//   benson's 9
//   caroline is undefined

9.1: Global DOM Objects

The six global DOM objects

Every Javascript program can refer to the following global objects:

namedescription
document current HTML page and its content
history list of pages the user has visited
location URL of the current HTML page
navigator info about the web browser you are using
screen info about the screen area occupied by the browser
window the browser window

The window object

the entire browser window; the top-level object in DOM hierarchy

Popup windows with window.open

window.open("http://foo.com/bar.html", "My Foo Window",
            "width=900,height=600,scrollbars=1");

The document object

the current web page and the elements inside it

The location object

the URL of the current web page

The navigator object

information about the web browser application

The screen object

information about the client's display screen

The history object

the list of sites the browser has visited in this window

9.1.1: Unobtrusive JavaScript

Unobtrusive JavaScript

Obtrusive event handlers (bad)

<button onclick="okayClick();">OK</button>
// called when OK button is clicked
function okayClick() {
	alert("booyah");
}

Attaching an event handler in JavaScript code

objectName.onevent = function;
<button id="ok">OK</button>
var okButton = document.getElementById("ok");
okButton.onclick = okayClick;

When does my code run?

<html>
	<head>
		<script src="myfile.js" type="text/javascript"></script>
	</head>
	<body> ... </body> </html>
var x = 3;
function f(n) { return n + 1; }
function g(n) { return n - 1; }
x = f(x);

A failed attempt at being unobtrusive

<html>
	<head>
		<script src="myfile.js" type="text/javascript"></script>
	</head>
	<body>
		<div><button id="ok">OK</button></div>
var ok = document.getElementById("ok");
ok.onclick = okayClick;   // error: null

The window.onload event

function functionName() {
	// code to initialize the page
	...
}

// run this function once the page has finished loading
window.onload = functionName;

An unobtrusive event handler

<button id="ok">OK</button>               <!-- (1) -->
// called when page loads; sets up event handlers
function pageLoad() {
	var ok = document.getElementById("ok");   // (3)
	ok.onclick = okayClick;
}

function okayClick() {
	alert("booyah");                          // (4)
}

window.onload = pageLoad;                   // (2)

Common unobtrusive JS errors

Unobtrusive styling

function okayClick() {
	this.style.color = "red";
	this.className = "highlighted";
}
.highlighted { color: red; }

Anonymous functions

function(parameters) {
	statements;
}

Anonymous function example

window.onload = function() {
	var ok = document.getElementById("ok");
	ok.onclick = okayClick;
};

function okayClick() {
	alert("booyah");
}
window.onload = function() {
	document.getElementById("ok").onclick = function() {
		alert("booyah");
	};
};

Anonymous vs. named functions

These two function declarations are exactly equivalent:

function foo() {
   // ...
}
var foo = function() {
   // ...
};

In both cases JavaScript stores the function as an object, which can be passed around like any other variable:

var bar = foo;
// the following runs the same function twice
foo();
bar();

Declaring vs. calling functions

function foo() { ... }

var bar = foo;        // foo IS NOT executed
                      // (assigned to another variable)
executeFunction(bar); // bar IS NOT executed yet
                      // (passed as a parameter)
foo();                // foo IS executed (parentheses added)

function executeFunction(fn) { // bar accepted as a parameter
                               // (NOT executed yet)
	fn(); // bar (i.e., foo) IS executed (parentheses added)
}

Passing functions as parameters

function gandalf(verb) {
   alert("You shall not: " + verb.toUpperCase());
}

function runFunction(func, value) {
   func(value); // calls whichever function is passed, passing value as a parameter
}

runFunction(gandalf, "pass!!!!!"); // 'You shall not: PASS!!!!!'
runFunction(function(meaning) {
   alert("The meaning of life is: " + meaning); // 'The meaning of life is: 42'
}, 42);

The danger of global variables

var count = 0;
function incr(n) {
  count += n;
}
function reset() {
  count = 0;
}

incr(4);
incr(2);
console.log(count);

Enclosing code in a function

function everything() {
	var count = 0;
	function incr(n) {
		count += n;
	}
	function reset() {
		count = 0;
	}

	incr(4);
	incr(2);
	console.log(count);
}

everything();   // call the function to run the code

The "module pattern"

(function() {
    statements;
})();

Module pattern example

(function() {
	var count = 0;
	function incr(n) {
		count += n;
	}
	function reset() {
		count = 0;
	}

	incr(4);
	incr(2);
	console.log(count);
})();